
/* /web/static/src/legacy/js/core/class.js */
odoo.define('@web/legacy/js/core/class',[],function(require){'use strict';let __exports={};function OdooClass(){}
var initializing=false;var fnTest=/xyz/.test(function(){xyz();})?/\b_super\b/:/.*/;OdooClass.extend=function(){var _super=this.prototype;var args=[...arguments];args.unshift({});const prop={};args.forEach((arg)=>{Object.assign(prop,arg);});initializing=true;var This=this;var prototype=new This();initializing=false;Object.keys(prop).forEach((name)=>{prototype[name]=typeof prop[name]=="function"&&fnTest.test(prop[name])?(function(name,fn){return function(){var tmp=this._super;this._super=_super[name];var ret=fn.apply(this,arguments);this._super=tmp;return ret;};})(name,prop[name]):prop[name];});function Class(){if(this.constructor!==OdooClass){throw new Error("You can only instanciate objects with the 'new' operator");}
this._super=null;if(!initializing&&this.init){var ret=this.init.apply(this,arguments);if(ret){return ret;}}
return this;}
Class.include=function(properties){Object.keys(properties).forEach((name)=>{if(typeof properties[name]!=='function'||!fnTest.test(properties[name])){prototype[name]=properties[name];}else if(typeof prototype[name]==='function'&&prototype.hasOwnProperty(name)){prototype[name]=(function(name,fn,previous){return function(){var tmp=this._super;this._super=previous;var ret=fn.apply(this,arguments);this._super=tmp;return ret;};})(name,properties[name],prototype[name]);}else if(typeof _super[name]==='function'){prototype[name]=(function(name,fn){return function(){var tmp=this._super;this._super=_super[name];var ret=fn.apply(this,arguments);this._super=tmp;return ret;};})(name,properties[name]);}});};Class.prototype=prototype;Class.constructor=Class;Class.extend=this.extend;return Class;};__exports[Symbol.for("default")]=OdooClass;return __exports;});;

/* /web/static/src/legacy/js/public/minimal_dom.js */
odoo.define('@web/legacy/js/public/minimal_dom',['@web/core/utils/ui'],function(require){'use strict';let __exports={};const{addLoadingEffect}=require('@web/core/utils/ui');const DEBOUNCE=__exports.DEBOUNCE=400;const BUTTON_HANDLER_SELECTOR=__exports.BUTTON_HANDLER_SELECTOR='a, button, input[type="submit"], input[type="button"], .btn';__exports.makeAsyncHandler=makeAsyncHandler;function makeAsyncHandler(fct,preventDefault,stopPropagation,stopImmediatePropagation){let pending=false;function _isLocked(){return pending;}
function _lock(){pending=true;}
function _unlock(){pending=false;}
return function(ev){if(preventDefault===true||preventDefault&&preventDefault()){ev.preventDefault();}
if(stopPropagation===true||stopPropagation&&stopPropagation()){ev.stopPropagation();}
if(stopImmediatePropagation===true||stopImmediatePropagation&&stopImmediatePropagation()){ev.stopImmediatePropagation();}
if(_isLocked()){return;}
_lock();const result=fct.apply(this,arguments);Promise.resolve(result).finally(_unlock);return result;};}
__exports.makeButtonHandler=makeButtonHandler;function makeButtonHandler(fct,preventDefault,stopPropagation,stopImmediatePropagation){fct=makeAsyncHandler(fct,preventDefault,stopPropagation,stopImmediatePropagation);return function(ev){const result=fct.apply(this,arguments);const buttonEl=ev.target.closest(BUTTON_HANDLER_SELECTOR);if(!(buttonEl instanceof HTMLElement)){return result;}
buttonEl.classList.add("pe-none");new Promise(resolve=>setTimeout(resolve,DEBOUNCE)).then(()=>{buttonEl.classList.remove("pe-none");const restore=addLoadingEffect(buttonEl);return Promise.resolve(result).then(restore,restore);});return result;};}
return __exports;});;

/* /web/static/src/legacy/js/public/public_widget.js */
odoo.define('@web/legacy/js/public/public_widget',['@odoo/owl','@web/legacy/js/core/class','@web/core/assets','@web/core/utils/hooks','@web/core/utils/render','@web/legacy/js/public/minimal_dom'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const Class=require("@web/legacy/js/core/class")[Symbol.for("default")];const{loadBundle,loadCSS,loadJS}=require('@web/core/assets');const{SERVICES_METADATA}=require("@web/core/utils/hooks");const{renderToElement}=require("@web/core/utils/render");const{makeAsyncHandler,makeButtonHandler}=require("@web/legacy/js/public/minimal_dom");const ParentedMixin={__parentedMixin:true,init:function(){this.__parentedDestroyed=false;this.__parentedChildren=[];this.__parentedParent=null;},setParent(parent){if(this.getParent()){if(this.getParent().__parentedMixin){const children=this.getParent().getChildren();this.getParent().__parentedChildren=children.filter((child)=>child.$el!==this.$el);}}
this.__parentedParent=parent;if(parent&&parent.__parentedMixin){parent.__parentedChildren.push(this);}},getParent(){return this.__parentedParent;},getChildren(){return[...this.__parentedChildren];},isDestroyed(){return this.__parentedDestroyed;},destroy(){this.getChildren().forEach(function(child){child.destroy();});this.setParent(undefined);this.__parentedDestroyed=true;},};function OdooEvent(target,name,data){this.target=target;this.name=name;this.data=Object.create(null);Object.assign(this.data,data);this.stopped=false;}
OdooEvent.prototype.stopPropagation=function(){this.stopped=true;};OdooEvent.prototype.is_stopped=function(){return this.stopped;};class Events{on(events,callback,context){var ev;events=events.split(/\s+/);var calls=this._callbacks||(this._callbacks={});while((ev=events.shift())){var list=calls[ev]||(calls[ev]={});var tail=list.tail||(list.tail=list.next={});tail.callback=callback;tail.context=context;list.tail=tail.next={};}
return this;}
off(events,callback,context){var ev,calls,node;if(!events){delete this._callbacks;}else if((calls=this._callbacks)){events=events.split(/\s+/);while((ev=events.shift())){node=calls[ev];delete calls[ev];if(!callback||!node){continue;}
while((node=node.next)&&node.next){if(node.callback===callback&&(!context||node.context===context)){continue;}
this.on(ev,node.callback,node.context);}}}
return this;}
callbackList(){var lst=[];for(const[eventName,el]of Object.entries(this._callbacks||{})){var node=el;while((node=node.next)&&node.next){lst.push([eventName,node.callback,node.context]);}}
return lst;}
trigger(events){var event,node,calls,tail,args,all,rest;if(!(calls=this._callbacks)){return this;}
all=calls.all;(events=events.split(/\s+/)).push(null);while((event=events.shift())){if(all){events.push({next:all.next,tail:all.tail,event:event});}
if(!(node=calls[event])){continue;}
events.push({next:node.next,tail:node.tail});}
rest=Array.prototype.slice.call(arguments,1);while((node=events.pop())){tail=node.tail;args=node.event?[node.event].concat(rest):rest;while((node=node.next)!==tail){node.callback.apply(node.context||this,args);}}
return this;}}
const EventDispatcherMixin=Object.assign({},ParentedMixin,{__eventDispatcherMixin:true,"custom_events":{},init(){ParentedMixin.init.call(this);this.__edispatcherEvents=new Events();this.__edispatcherRegisteredEvents=[];this._delegateCustomEvents();},proxy(method){var self=this;return function(){var fn=(typeof method==='string')?self[method]:method;if(fn===void 0){throw new Error("Couldn't find method '"+method+"' in widget "+self);}
return fn.apply(self,arguments);};},_delegateCustomEvents(){if(Object.keys(this.custom_events||{}).length===0){return;}
for(var key in this.custom_events){if(!Object.prototype.hasOwnProperty.call(this.custom_events,key)){continue;}
var method=this.proxy(this.custom_events[key]);this.on(key,this,method);}},on(events,dest,func){var self=this;if(typeof func!=="function"){throw new Error("Event handler must be a function.");}
events=events.split(/\s+/);events.forEach((eventName)=>{self.__edispatcherEvents.on(eventName,func,dest);if(dest&&dest.__eventDispatcherMixin){dest.__edispatcherRegisteredEvents.push({name:eventName,func:func,source:self});}});return this;},off(events,dest,func){var self=this;events=events.split(/\s+/);events.forEach((eventName)=>{self.__edispatcherEvents.off(eventName,func,dest);if(dest&&dest.__eventDispatcherMixin){dest.__edispatcherRegisteredEvents=dest.__edispatcherRegisteredEvents.filter(el=>{return!(el.name===eventName&&el.func===func&&el.source===self);});}});return this;},trigger(){this.__edispatcherEvents.trigger.apply(this.__edispatcherEvents,arguments);return this;},"trigger_up":function(name,info){var event=new OdooEvent(this,name,info);this._trigger_up(event);return event;},"_trigger_up":function(event){var parent;this.__edispatcherEvents.trigger(event.name,event);if(!event.is_stopped()&&(parent=this.getParent())){parent._trigger_up(event);}},destroy(){var self=this;this.__edispatcherRegisteredEvents.forEach((event)=>{event.source.__edispatcherEvents.off(event.name,event.func,self);});this.__edispatcherRegisteredEvents=[];this.__edispatcherEvents.callbackList().forEach(((cal)=>{this.off(cal[0],cal[2],cal[1]);}).bind(this));this.__edispatcherEvents.off();ParentedMixin.destroy.call(this);},});function protectMethod(widget,fn){return function(...args){return new Promise((resolve,reject)=>{Promise.resolve(fn.call(this,...args)).then((result)=>{if(!widget.isDestroyed()){resolve(result);}}).catch((reason)=>{if(!widget.isDestroyed()){reject(reason);}});});};}
const ServicesMixin={bindService:function(serviceName){const{services}=Component.env;const service=services[serviceName];if(!service){throw new Error(`Service ${serviceName} is not available`);}
if(serviceName in SERVICES_METADATA){if(service instanceof Function){return protectMethod(this,service);}else{const methods=SERVICES_METADATA[serviceName];const result=Object.create(service);for(const method of methods){result[method]=protectMethod(this,service[method]);}
return result;}}
return service;},call:function(service,method){var args=Array.prototype.slice.call(arguments,2);var result;this.trigger_up('call_service',{service:service,method:method,args:args,callback:function(r){result=r;},});return result;},};const PublicWidget=__exports.PublicWidget=Class.extend(EventDispatcherMixin,ServicesMixin,{tagName:'div',id:null,className:null,attributes:{},template:null,cssLibs:null,jsLibs:null,assetLibs:null,selector:false,selectorHas:false,events:{},init:function(parent,options){EventDispatcherMixin.init.call(this);this.setParent(parent);this.options=options||{};},willStart:function(){var proms=[];if(this.jsLibs||this.cssLibs||this.assetLibs){var assetsPromise=Promise.all([...(this.cssLibs||[]).map(loadCSS),...(this.jsLibs||[]).map(loadJS),]);for(const bundleName of this.assetLibs||[]){if(typeof bundleName==="string"){assetsPromise=assetsPromise.then(()=>{return loadBundle(bundleName);});}else{assetsPromise=assetsPromise.then(()=>{return Promise.all([...bundleName.map(loadBundle)]);});}}
proms.push(assetsPromise);}
return Promise.all(proms);},start:function(){return Promise.resolve();},destroy:function(){EventDispatcherMixin.destroy.call(this);if(this.$el){this._undelegateEvents();if(!this.selector){this.$el.remove();}}},appendTo:function(target){var self=this;return this._widgetRenderAndInsert(function(t){self.$el.appendTo(t);},target);},attachTo:function(target){var self=this;this.setElement(target.$el||target);return this.willStart().then(function(){if(self.__parentedDestroyed){return;}
return self.start();});},insertAfter:function(target){var self=this;return this._widgetRenderAndInsert(function(t){self.$el.insertAfter(t);},target);},insertBefore:function(target){var self=this;return this._widgetRenderAndInsert(function(t){self.$el.insertBefore(t);},target);},prependTo:function(target){var self=this;return this._widgetRenderAndInsert(function(t){self.$el.prependTo(t);},target);},renderElement:function(){var $el;if(this.template){$el=$(renderToElement(this.template,{widget:this}));}else{$el=this._makeDescriptive();}
this._replaceElement($el);},replace:function(target){return this._widgetRenderAndInsert((t)=>{this.$el.replaceAll(t);},target);},setElement:function(element){if(this.$el){this._undelegateEvents();}
this.$el=(element instanceof $)?element:$(element);this.el=this.$el[0];this._delegateEvents();if(this.selector){this.$target=this.$el;this.target=this.el;}
return this;},$:function(selector){if(selector===undefined){return this.$el;}
return this.$el.find(selector);},_delegateEvents:function(){var self=this;const _delegateEvent=(method,key)=>{var match=/^(\S+)(\s+(.*))?$/.exec(key);var event=match[1];var selector=match[3];event+='.widget_events';if(!selector){self.$el.on(event,method);}else{self.$el.on(event,selector,method);}};Object.entries(this.events||{}).forEach(([event,method])=>{if(typeof method!=='string'){_delegateEvent(self.proxy(method),event);return;}
var methodOptions=method.split(' ');if(methodOptions.length<=1){_delegateEvent(self.proxy(method),event);return;}
var isAsync=methodOptions.includes('async');if(!isAsync){_delegateEvent(self.proxy(method),event);return;}
method=self.proxy(methodOptions[methodOptions.length-1]);if(String(event).startsWith("click")){method=makeButtonHandler(method);}else{method=makeAsyncHandler(method);}
_delegateEvent(method,event);});},_getContext:function(extra,extraContext){var context;this.trigger_up('context_get',{extra:extra||false,context:extraContext,callback:function(ctx){context=ctx;},});return context;},_makeDescriptive:function(){var attrs=Object.assign({},this.attributes||{});if(this.id){attrs.id=this.id;}
if(this.className){attrs['class']=this.className;}
var $el=$(document.createElement(this.tagName));if(Object.keys(attrs||{}).length>0){$el.attr(attrs);}
return $el;},_replaceElement:function($el){var $oldel=this.$el;this.setElement($el);if($oldel&&!$oldel.is(this.$el)){if($oldel.length>1){$oldel.wrapAll('<div/>');$oldel.parent().replaceWith(this.$el);}else{$oldel.replaceWith(this.$el);}}
return this;},_undelegateEvents:function(){this.$el.off('.widget_events');},_widgetRenderAndInsert:function(insertion,target){var self=this;return this.willStart().then(function(){if(self.__parentedDestroyed){return;}
self.renderElement();insertion(target);return self.start();});},});var registry={};__exports[Symbol.for("default")]={Widget:PublicWidget,registry:registry,ParentedMixin:ParentedMixin,EventDispatcherMixin:EventDispatcherMixin,ServicesMixin:ServicesMixin,};return __exports;});;

/* /web_editor/static/lib/cropperjs/cropper.js */
(function(global,factory){typeof exports==='object'&&typeof module!=='undefined'?module.exports=factory():typeof define==='function'&&define.amd?define(factory):(global=global||self,global.Cropper=factory());}(this,function(){'use strict';function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function(obj){return typeof obj;};}else{_typeof=function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}
return _typeof(obj);}
function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}
function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}
function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}
function _toConsumableArray(arr){return _arrayWithoutHoles(arr)||_iterableToArray(arr)||_nonIterableSpread();}
function _arrayWithoutHoles(arr){if(Array.isArray(arr)){for(var i=0,arr2=new Array(arr.length);i<arr.length;i++)arr2[i]=arr[i];return arr2;}}
function _iterableToArray(iter){if(Symbol.iterator in Object(iter)||Object.prototype.toString.call(iter)==="[object Arguments]")return Array.from(iter);}
function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance");}
var IS_BROWSER=typeof window!=='undefined'&&typeof window.document!=='undefined';var WINDOW=IS_BROWSER?window:{};var IS_TOUCH_DEVICE=IS_BROWSER?'ontouchstart'in WINDOW.document.documentElement:false;var HAS_POINTER_EVENT=IS_BROWSER?'PointerEvent'in WINDOW:false;var NAMESPACE='cropper';var ACTION_ALL='all';var ACTION_CROP='crop';var ACTION_MOVE='move';var ACTION_ZOOM='zoom';var ACTION_EAST='e';var ACTION_WEST='w';var ACTION_SOUTH='s';var ACTION_NORTH='n';var ACTION_NORTH_EAST='ne';var ACTION_NORTH_WEST='nw';var ACTION_SOUTH_EAST='se';var ACTION_SOUTH_WEST='sw';var CLASS_CROP="".concat(NAMESPACE,"-crop");var CLASS_DISABLED="".concat(NAMESPACE,"-disabled");var CLASS_HIDDEN="".concat(NAMESPACE,"-hidden");var CLASS_HIDE="".concat(NAMESPACE,"-hide");var CLASS_INVISIBLE="".concat(NAMESPACE,"-invisible");var CLASS_MODAL="".concat(NAMESPACE,"-modal");var CLASS_MOVE="".concat(NAMESPACE,"-move");var DATA_ACTION="".concat(NAMESPACE,"Action");var DATA_PREVIEW="".concat(NAMESPACE,"Preview");var DRAG_MODE_CROP='crop';var DRAG_MODE_MOVE='move';var DRAG_MODE_NONE='none';var EVENT_CROP='crop';var EVENT_CROP_END='cropend';var EVENT_CROP_MOVE='cropmove';var EVENT_CROP_START='cropstart';var EVENT_DBLCLICK='dblclick';var EVENT_TOUCH_START=IS_TOUCH_DEVICE?'touchstart':'mousedown';var EVENT_TOUCH_MOVE=IS_TOUCH_DEVICE?'touchmove':'mousemove';var EVENT_TOUCH_END=IS_TOUCH_DEVICE?'touchend touchcancel':'mouseup';var EVENT_POINTER_DOWN=HAS_POINTER_EVENT?'pointerdown':EVENT_TOUCH_START;var EVENT_POINTER_MOVE=HAS_POINTER_EVENT?'pointermove':EVENT_TOUCH_MOVE;var EVENT_POINTER_UP=HAS_POINTER_EVENT?'pointerup pointercancel':EVENT_TOUCH_END;var EVENT_READY='ready';var EVENT_RESIZE='resize';var EVENT_WHEEL='wheel';var EVENT_ZOOM='zoom';var MIME_TYPE_JPEG='image/jpeg';var REGEXP_ACTIONS=/^e|w|s|n|se|sw|ne|nw|all|crop|move|zoom$/;var REGEXP_DATA_URL=/^data:/;var REGEXP_DATA_URL_JPEG=/^data:image\/jpeg;base64,/;var REGEXP_TAG_NAME=/^img|canvas$/i;var MIN_CONTAINER_WIDTH=200;var MIN_CONTAINER_HEIGHT=100;var DEFAULTS={viewMode:0,dragMode:DRAG_MODE_CROP,initialAspectRatio:NaN,aspectRatio:NaN,data:null,preview:'',responsive:true,restore:true,checkCrossOrigin:true,checkOrientation:true,modal:true,guides:true,center:true,highlight:true,background:true,autoCrop:true,autoCropArea:0.8,movable:true,rotatable:true,scalable:true,zoomable:true,zoomOnTouch:true,zoomOnWheel:true,wheelZoomRatio:0.1,cropBoxMovable:true,cropBoxResizable:true,toggleDragModeOnDblclick:true,minCanvasWidth:0,minCanvasHeight:0,minCropBoxWidth:0,minCropBoxHeight:0,minContainerWidth:200,minContainerHeight:100,ready:null,cropstart:null,cropmove:null,cropend:null,crop:null,zoom:null};var TEMPLATE='<div class="cropper-container" touch-action="none">'+'<div class="cropper-wrap-box">'+'<div class="cropper-canvas"></div>'+'</div>'+'<div class="cropper-drag-box"></div>'+'<div class="cropper-crop-box">'+'<span class="cropper-view-box"></span>'+'<span class="cropper-dashed dashed-h"></span>'+'<span class="cropper-dashed dashed-v"></span>'+'<span class="cropper-center"></span>'+'<span class="cropper-face"></span>'+'<span class="cropper-line line-e" data-cropper-action="e"></span>'+'<span class="cropper-line line-n" data-cropper-action="n"></span>'+'<span class="cropper-line line-w" data-cropper-action="w"></span>'+'<span class="cropper-line line-s" data-cropper-action="s"></span>'+'<span class="cropper-point point-e" data-cropper-action="e"></span>'+'<span class="cropper-point point-n" data-cropper-action="n"></span>'+'<span class="cropper-point point-w" data-cropper-action="w"></span>'+'<span class="cropper-point point-s" data-cropper-action="s"></span>'+'<span class="cropper-point point-ne" data-cropper-action="ne"></span>'+'<span class="cropper-point point-nw" data-cropper-action="nw"></span>'+'<span class="cropper-point point-sw" data-cropper-action="sw"></span>'+'<span class="cropper-point point-se" data-cropper-action="se"></span>'+'</div>'+'</div>';var isNaN=Number.isNaN||WINDOW.isNaN;function isNumber(value){return typeof value==='number'&&!isNaN(value);}
var isPositiveNumber=function isPositiveNumber(value){return value>0&&value<Infinity;};function isUndefined(value){return typeof value==='undefined';}
function isObject(value){return _typeof(value)==='object'&&value!==null;}
var hasOwnProperty=Object.prototype.hasOwnProperty;function isPlainObject(value){if(!isObject(value)){return false;}
try{var _constructor=value.constructor;var prototype=_constructor.prototype;return _constructor&&prototype&&hasOwnProperty.call(prototype,'isPrototypeOf');}catch(error){return false;}}
function isFunction(value){return typeof value==='function';}
var slice=Array.prototype.slice;function toArray(value){return Array.from?Array.from(value):slice.call(value);}
function forEach(data,callback){if(data&&isFunction(callback)){if(Array.isArray(data)||isNumber(data.length)){toArray(data).forEach(function(value,key){callback.call(data,value,key,data);});}else if(isObject(data)){Object.keys(data).forEach(function(key){callback.call(data,data[key],key,data);});}}
return data;}
var assign=Object.assign||function assign(target){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}
if(isObject(target)&&args.length>0){args.forEach(function(arg){if(isObject(arg)){Object.keys(arg).forEach(function(key){target[key]=arg[key];});}});}
return target;};var REGEXP_DECIMALS=/\.\d*(?:0|9){12}\d*$/;function normalizeDecimalNumber(value){var times=arguments.length>1&&arguments[1]!==undefined?arguments[1]:100000000000;return REGEXP_DECIMALS.test(value)?Math.round(value*times)/times:value;}
var REGEXP_SUFFIX=/^width|height|left|top|marginLeft|marginTop$/;function setStyle(element,styles){var style=element.style;forEach(styles,function(value,property){if(REGEXP_SUFFIX.test(property)&&isNumber(value)){value="".concat(value,"px");}
style[property]=value;});}
function hasClass(element,value){return element.classList?element.classList.contains(value):element.className.indexOf(value)>-1;}
function addClass(element,value){if(!value){return;}
if(isNumber(element.length)){forEach(element,function(elem){addClass(elem,value);});return;}
if(element.classList){element.classList.add(value);return;}
var className=element.className.trim();if(!className){element.className=value;}else if(className.indexOf(value)<0){element.className="".concat(className," ").concat(value);}}
function removeClass(element,value){if(!value){return;}
if(isNumber(element.length)){forEach(element,function(elem){removeClass(elem,value);});return;}
if(element.classList){element.classList.remove(value);return;}
if(element.className.indexOf(value)>=0){element.className=element.className.replace(value,'');}}
function toggleClass(element,value,added){if(!value){return;}
if(isNumber(element.length)){forEach(element,function(elem){toggleClass(elem,value,added);});return;}
if(added){addClass(element,value);}else{removeClass(element,value);}}
var REGEXP_CAMEL_CASE=/([a-z\d])([A-Z])/g;function toParamCase(value){return value.replace(REGEXP_CAMEL_CASE,'$1-$2').toLowerCase();}
function getData(element,name){if(isObject(element[name])){return element[name];}
if(element.dataset){return element.dataset[name];}
return element.getAttribute("data-".concat(toParamCase(name)));}
function setData(element,name,data){if(isObject(data)){element[name]=data;}else if(element.dataset){element.dataset[name]=data;}else{element.setAttribute("data-".concat(toParamCase(name)),data);}}
function removeData(element,name){if(isObject(element[name])){try{delete element[name];}catch(error){element[name]=undefined;}}else if(element.dataset){try{delete element.dataset[name];}catch(error){element.dataset[name]=undefined;}}else{element.removeAttribute("data-".concat(toParamCase(name)));}}
var REGEXP_SPACES=/\s\s*/;var onceSupported=function(){var supported=false;if(IS_BROWSER){var once=false;var listener=function listener(){};var options=Object.defineProperty({},'once',{get:function get(){supported=true;return once;},set:function set(value){once=value;}});WINDOW.addEventListener('test',listener,options);WINDOW.removeEventListener('test',listener,options);}
return supported;}();function removeListener(element,type,listener){var options=arguments.length>3&&arguments[3]!==undefined?arguments[3]:{};var handler=listener;type.trim().split(REGEXP_SPACES).forEach(function(event){if(!onceSupported){var listeners=element.listeners;if(listeners&&listeners[event]&&listeners[event][listener]){handler=listeners[event][listener];delete listeners[event][listener];if(Object.keys(listeners[event]).length===0){delete listeners[event];}
if(Object.keys(listeners).length===0){delete element.listeners;}}}
element.removeEventListener(event,handler,options);});}
function addListener(element,type,listener){var options=arguments.length>3&&arguments[3]!==undefined?arguments[3]:{};var _handler=listener;type.trim().split(REGEXP_SPACES).forEach(function(event){if(options.once&&!onceSupported){var _element$listeners=element.listeners,listeners=_element$listeners===void 0?{}:_element$listeners;_handler=function handler(){delete listeners[event][listener];element.removeEventListener(event,_handler,options);for(var _len2=arguments.length,args=new Array(_len2),_key2=0;_key2<_len2;_key2++){args[_key2]=arguments[_key2];}
listener.apply(element,args);};if(!listeners[event]){listeners[event]={};}
if(listeners[event][listener]){element.removeEventListener(event,listeners[event][listener],options);}
listeners[event][listener]=_handler;element.listeners=listeners;}
element.addEventListener(event,_handler,options);});}
function dispatchEvent(element,type,data){var event;if(isFunction(Event)&&isFunction(CustomEvent)){event=new CustomEvent(type,{detail:data,bubbles:true,cancelable:true});}else{event=document.createEvent('CustomEvent');event.initCustomEvent(type,true,true,data);}
return element.dispatchEvent(event);}
function getOffset(element){var box=element.getBoundingClientRect();return{left:box.left+(window.pageXOffset-document.documentElement.clientLeft),top:box.top+(window.pageYOffset-document.documentElement.clientTop)};}
var location=WINDOW.location;var REGEXP_ORIGINS=/^(\w+:)\/\/([^:/?#]*):?(\d*)/i;function isCrossOriginURL(url){var parts=url.match(REGEXP_ORIGINS);return parts!==null&&(parts[1]!==location.protocol||parts[2]!==location.hostname||parts[3]!==location.port);}
function addTimestamp(url){var timestamp="timestamp=".concat(new Date().getTime());return url+(url.indexOf('?')===-1?'?':'&')+timestamp;}
function getTransforms(_ref){var rotate=_ref.rotate,scaleX=_ref.scaleX,scaleY=_ref.scaleY,translateX=_ref.translateX,translateY=_ref.translateY;var values=[];if(isNumber(translateX)&&translateX!==0){values.push("translateX(".concat(translateX,"px)"));}
if(isNumber(translateY)&&translateY!==0){values.push("translateY(".concat(translateY,"px)"));}
if(isNumber(rotate)&&rotate!==0){values.push("rotate(".concat(rotate,"deg)"));}
if(isNumber(scaleX)&&scaleX!==1){values.push("scaleX(".concat(scaleX,")"));}
if(isNumber(scaleY)&&scaleY!==1){values.push("scaleY(".concat(scaleY,")"));}
var transform=values.length?values.join(' '):'none';return{WebkitTransform:transform,msTransform:transform,transform:transform};}
function getMaxZoomRatio(pointers){var pointers2=assign({},pointers);var ratios=[];forEach(pointers,function(pointer,pointerId){delete pointers2[pointerId];forEach(pointers2,function(pointer2){var x1=Math.abs(pointer.startX-pointer2.startX);var y1=Math.abs(pointer.startY-pointer2.startY);var x2=Math.abs(pointer.endX-pointer2.endX);var y2=Math.abs(pointer.endY-pointer2.endY);var z1=Math.sqrt(x1*x1+y1*y1);var z2=Math.sqrt(x2*x2+y2*y2);var ratio=(z2-z1)/z1;ratios.push(ratio);});});ratios.sort(function(a,b){return Math.abs(a)<Math.abs(b);});return ratios[0];}
function getPointer(_ref2,endOnly){var pageX=_ref2.pageX,pageY=_ref2.pageY;var end={endX:pageX,endY:pageY};return endOnly?end:assign({startX:pageX,startY:pageY},end);}
function getPointersCenter(pointers){var pageX=0;var pageY=0;var count=0;forEach(pointers,function(_ref3){var startX=_ref3.startX,startY=_ref3.startY;pageX+=startX;pageY+=startY;count+=1;});pageX/=count;pageY/=count;return{pageX:pageX,pageY:pageY};}
function getAdjustedSizes(_ref4)
{var aspectRatio=_ref4.aspectRatio,height=_ref4.height,width=_ref4.width;var type=arguments.length>1&&arguments[1]!==undefined?arguments[1]:'contain';var isValidWidth=isPositiveNumber(width);var isValidHeight=isPositiveNumber(height);if(isValidWidth&&isValidHeight){var adjustedWidth=height*aspectRatio;if(type==='contain'&&adjustedWidth>width||type==='cover'&&adjustedWidth<width){height=width/aspectRatio;}else{width=height*aspectRatio;}}else if(isValidWidth){height=width/aspectRatio;}else if(isValidHeight){width=height*aspectRatio;}
return{width:width,height:height};}
function getRotatedSizes(_ref5){var width=_ref5.width,height=_ref5.height,degree=_ref5.degree;degree=Math.abs(degree)%180;if(degree===90){return{width:height,height:width};}
var arc=degree%90*Math.PI/180;var sinArc=Math.sin(arc);var cosArc=Math.cos(arc);var newWidth=width*cosArc+height*sinArc;var newHeight=width*sinArc+height*cosArc;return degree>90?{width:newHeight,height:newWidth}:{width:newWidth,height:newHeight};}
function getSourceCanvas(image,_ref6,_ref7,_ref8){var imageAspectRatio=_ref6.aspectRatio,imageNaturalWidth=_ref6.naturalWidth,imageNaturalHeight=_ref6.naturalHeight,_ref6$rotate=_ref6.rotate,rotate=_ref6$rotate===void 0?0:_ref6$rotate,_ref6$scaleX=_ref6.scaleX,scaleX=_ref6$scaleX===void 0?1:_ref6$scaleX,_ref6$scaleY=_ref6.scaleY,scaleY=_ref6$scaleY===void 0?1:_ref6$scaleY;var aspectRatio=_ref7.aspectRatio,naturalWidth=_ref7.naturalWidth,naturalHeight=_ref7.naturalHeight;var _ref8$fillColor=_ref8.fillColor,fillColor=_ref8$fillColor===void 0?'transparent':_ref8$fillColor,_ref8$imageSmoothingE=_ref8.imageSmoothingEnabled,imageSmoothingEnabled=_ref8$imageSmoothingE===void 0?true:_ref8$imageSmoothingE,_ref8$imageSmoothingQ=_ref8.imageSmoothingQuality,imageSmoothingQuality=_ref8$imageSmoothingQ===void 0?'low':_ref8$imageSmoothingQ,_ref8$maxWidth=_ref8.maxWidth,maxWidth=_ref8$maxWidth===void 0?Infinity:_ref8$maxWidth,_ref8$maxHeight=_ref8.maxHeight,maxHeight=_ref8$maxHeight===void 0?Infinity:_ref8$maxHeight,_ref8$minWidth=_ref8.minWidth,minWidth=_ref8$minWidth===void 0?0:_ref8$minWidth,_ref8$minHeight=_ref8.minHeight,minHeight=_ref8$minHeight===void 0?0:_ref8$minHeight;var canvas=document.createElement('canvas');var context=canvas.getContext('2d');var maxSizes=getAdjustedSizes({aspectRatio:aspectRatio,width:maxWidth,height:maxHeight});var minSizes=getAdjustedSizes({aspectRatio:aspectRatio,width:minWidth,height:minHeight},'cover');var width=Math.min(maxSizes.width,Math.max(minSizes.width,naturalWidth));var height=Math.min(maxSizes.height,Math.max(minSizes.height,naturalHeight));var destMaxSizes=getAdjustedSizes({aspectRatio:imageAspectRatio,width:maxWidth,height:maxHeight});var destMinSizes=getAdjustedSizes({aspectRatio:imageAspectRatio,width:minWidth,height:minHeight},'cover');var destWidth=Math.min(destMaxSizes.width,Math.max(destMinSizes.width,imageNaturalWidth));var destHeight=Math.min(destMaxSizes.height,Math.max(destMinSizes.height,imageNaturalHeight));var params=[-destWidth/2,-destHeight/2,destWidth,destHeight];canvas.width=normalizeDecimalNumber(width);canvas.height=normalizeDecimalNumber(height);context.fillStyle=fillColor;context.fillRect(0,0,width,height);context.save();context.translate(width/2,height/2);context.rotate(rotate*Math.PI/180);context.scale(scaleX,scaleY);context.imageSmoothingEnabled=imageSmoothingEnabled;context.imageSmoothingQuality=imageSmoothingQuality;params=params.map(normalizeDecimalNumber);context.drawImage(image,params[0],params[1],Math.floor(params[2]),Math.floor(params[3]));context.restore();return canvas;}
var fromCharCode=String.fromCharCode;function getStringFromCharCode(dataView,start,length){var str='';length+=start;for(var i=start;i<length;i+=1){str+=fromCharCode(dataView.getUint8(i));}
return str;}
var REGEXP_DATA_URL_HEAD=/^data:.*,/;function dataURLToArrayBuffer(dataURL){var base64=dataURL.replace(REGEXP_DATA_URL_HEAD,'');var binary=atob(base64);var arrayBuffer=new ArrayBuffer(binary.length);var uint8=new Uint8Array(arrayBuffer);forEach(uint8,function(value,i){uint8[i]=binary.charCodeAt(i);});return arrayBuffer;}
function arrayBufferToDataURL(arrayBuffer,mimeType){var chunks=[];var chunkSize=8192;var uint8=new Uint8Array(arrayBuffer);while(uint8.length>0){chunks.push(fromCharCode.apply(null,toArray(uint8.subarray(0,chunkSize))));uint8=uint8.subarray(chunkSize);}
return"data:".concat(mimeType,";base64,").concat(btoa(chunks.join('')));}
function resetAndGetOrientation(arrayBuffer){var dataView=new DataView(arrayBuffer);var orientation;try{var littleEndian;var app1Start;var ifdStart;if(dataView.getUint8(0)===0xFF&&dataView.getUint8(1)===0xD8){var length=dataView.byteLength;var offset=2;while(offset+1<length){if(dataView.getUint8(offset)===0xFF&&dataView.getUint8(offset+1)===0xE1){app1Start=offset;break;}
offset+=1;}}
if(app1Start){var exifIDCode=app1Start+4;var tiffOffset=app1Start+10;if(getStringFromCharCode(dataView,exifIDCode,4)==='Exif'){var endianness=dataView.getUint16(tiffOffset);littleEndian=endianness===0x4949;if(littleEndian||endianness===0x4D4D){if(dataView.getUint16(tiffOffset+2,littleEndian)===0x002A){var firstIFDOffset=dataView.getUint32(tiffOffset+4,littleEndian);if(firstIFDOffset>=0x00000008){ifdStart=tiffOffset+firstIFDOffset;}}}}}
if(ifdStart){var _length=dataView.getUint16(ifdStart,littleEndian);var _offset;var i;for(i=0;i<_length;i+=1){_offset=ifdStart+i*12+2;if(dataView.getUint16(_offset,littleEndian)===0x0112){_offset+=8;orientation=dataView.getUint16(_offset,littleEndian);dataView.setUint16(_offset,1,littleEndian);break;}}}}catch(error){orientation=1;}
return orientation;}
function parseOrientation(orientation){var rotate=0;var scaleX=1;var scaleY=1;switch(orientation){case 2:scaleX=-1;break;case 3:rotate=-180;break;case 4:scaleY=-1;break;case 5:rotate=90;scaleY=-1;break;case 6:rotate=90;break;case 7:rotate=90;scaleX=-1;break;case 8:rotate=-90;break;default:}
return{rotate:rotate,scaleX:scaleX,scaleY:scaleY};}
var render={render:function render(){this.initContainer();this.initCanvas();this.initCropBox();this.renderCanvas();if(this.cropped){this.renderCropBox();}},initContainer:function initContainer(){var element=this.element,options=this.options,container=this.container,cropper=this.cropper;addClass(cropper,CLASS_HIDDEN);removeClass(element,CLASS_HIDDEN);var containerData={width:Math.max(container.offsetWidth,Number(options.minContainerWidth)||200),height:Math.max(container.offsetHeight,Number(options.minContainerHeight)||100)};this.containerData=containerData;setStyle(cropper,{width:containerData.width,height:containerData.height});addClass(element,CLASS_HIDDEN);removeClass(cropper,CLASS_HIDDEN);},initCanvas:function initCanvas(){var containerData=this.containerData,imageData=this.imageData;var viewMode=this.options.viewMode;var rotated=Math.abs(imageData.rotate)%180===90;var naturalWidth=rotated?imageData.naturalHeight:imageData.naturalWidth;var naturalHeight=rotated?imageData.naturalWidth:imageData.naturalHeight;var aspectRatio=naturalWidth/naturalHeight;var canvasWidth=containerData.width;var canvasHeight=containerData.height;if(containerData.height*aspectRatio>containerData.width){if(viewMode===3){canvasWidth=containerData.height*aspectRatio;}else{canvasHeight=containerData.width/aspectRatio;}}else if(viewMode===3){canvasHeight=containerData.width/aspectRatio;}else{canvasWidth=containerData.height*aspectRatio;}
var canvasData={aspectRatio:aspectRatio,naturalWidth:naturalWidth,naturalHeight:naturalHeight,width:canvasWidth,height:canvasHeight};canvasData.left=(containerData.width-canvasWidth)/2;canvasData.top=(containerData.height-canvasHeight)/2;canvasData.oldLeft=canvasData.left;canvasData.oldTop=canvasData.top;this.canvasData=canvasData;this.limited=viewMode===1||viewMode===2;this.limitCanvas(true,true);this.initialImageData=assign({},imageData);this.initialCanvasData=assign({},canvasData);},limitCanvas:function limitCanvas(sizeLimited,positionLimited){var options=this.options,containerData=this.containerData,canvasData=this.canvasData,cropBoxData=this.cropBoxData;var viewMode=options.viewMode;var aspectRatio=canvasData.aspectRatio;var cropped=this.cropped&&cropBoxData;if(sizeLimited){var minCanvasWidth=Number(options.minCanvasWidth)||0;var minCanvasHeight=Number(options.minCanvasHeight)||0;if(viewMode>1){minCanvasWidth=Math.max(minCanvasWidth,containerData.width);minCanvasHeight=Math.max(minCanvasHeight,containerData.height);if(viewMode===3){if(minCanvasHeight*aspectRatio>minCanvasWidth){minCanvasWidth=minCanvasHeight*aspectRatio;}else{minCanvasHeight=minCanvasWidth/aspectRatio;}}}else if(viewMode>0){if(minCanvasWidth){minCanvasWidth=Math.max(minCanvasWidth,cropped?cropBoxData.width:0);}else if(minCanvasHeight){minCanvasHeight=Math.max(minCanvasHeight,cropped?cropBoxData.height:0);}else if(cropped){minCanvasWidth=cropBoxData.width;minCanvasHeight=cropBoxData.height;if(minCanvasHeight*aspectRatio>minCanvasWidth){minCanvasWidth=minCanvasHeight*aspectRatio;}else{minCanvasHeight=minCanvasWidth/aspectRatio;}}}
var _getAdjustedSizes=getAdjustedSizes({aspectRatio:aspectRatio,width:minCanvasWidth,height:minCanvasHeight});minCanvasWidth=_getAdjustedSizes.width;minCanvasHeight=_getAdjustedSizes.height;canvasData.minWidth=minCanvasWidth;canvasData.minHeight=minCanvasHeight;canvasData.maxWidth=Infinity;canvasData.maxHeight=Infinity;}
if(positionLimited){if(viewMode>(cropped?0:1)){var newCanvasLeft=containerData.width-canvasData.width;var newCanvasTop=containerData.height-canvasData.height;canvasData.minLeft=Math.min(0,newCanvasLeft);canvasData.minTop=Math.min(0,newCanvasTop);canvasData.maxLeft=Math.max(0,newCanvasLeft);canvasData.maxTop=Math.max(0,newCanvasTop);if(cropped&&this.limited){canvasData.minLeft=Math.min(cropBoxData.left,cropBoxData.left+(cropBoxData.width-canvasData.width));canvasData.minTop=Math.min(cropBoxData.top,cropBoxData.top+(cropBoxData.height-canvasData.height));canvasData.maxLeft=cropBoxData.left;canvasData.maxTop=cropBoxData.top;if(viewMode===2){if(canvasData.width>=containerData.width){canvasData.minLeft=Math.min(0,newCanvasLeft);canvasData.maxLeft=Math.max(0,newCanvasLeft);}
if(canvasData.height>=containerData.height){canvasData.minTop=Math.min(0,newCanvasTop);canvasData.maxTop=Math.max(0,newCanvasTop);}}}}else{canvasData.minLeft=-canvasData.width;canvasData.minTop=-canvasData.height;canvasData.maxLeft=containerData.width;canvasData.maxTop=containerData.height;}}},renderCanvas:function renderCanvas(changed,transformed){var canvasData=this.canvasData,imageData=this.imageData;if(transformed){var _getRotatedSizes=getRotatedSizes({width:imageData.naturalWidth*Math.abs(imageData.scaleX||1),height:imageData.naturalHeight*Math.abs(imageData.scaleY||1),degree:imageData.rotate||0}),naturalWidth=_getRotatedSizes.width,naturalHeight=_getRotatedSizes.height;var width=canvasData.width*(naturalWidth/canvasData.naturalWidth);var height=canvasData.height*(naturalHeight/canvasData.naturalHeight);canvasData.left-=(width-canvasData.width)/2;canvasData.top-=(height-canvasData.height)/2;canvasData.width=width;canvasData.height=height;canvasData.aspectRatio=naturalWidth/naturalHeight;canvasData.naturalWidth=naturalWidth;canvasData.naturalHeight=naturalHeight;this.limitCanvas(true,false);}
if(canvasData.width>canvasData.maxWidth||canvasData.width<canvasData.minWidth){canvasData.left=canvasData.oldLeft;}
if(canvasData.height>canvasData.maxHeight||canvasData.height<canvasData.minHeight){canvasData.top=canvasData.oldTop;}
canvasData.width=Math.min(Math.max(canvasData.width,canvasData.minWidth),canvasData.maxWidth);canvasData.height=Math.min(Math.max(canvasData.height,canvasData.minHeight),canvasData.maxHeight);this.limitCanvas(false,true);canvasData.left=Math.min(Math.max(canvasData.left,canvasData.minLeft),canvasData.maxLeft);canvasData.top=Math.min(Math.max(canvasData.top,canvasData.minTop),canvasData.maxTop);canvasData.oldLeft=canvasData.left;canvasData.oldTop=canvasData.top;setStyle(this.canvas,assign({width:canvasData.width,height:canvasData.height},getTransforms({translateX:canvasData.left,translateY:canvasData.top})));this.renderImage(changed);if(this.cropped&&this.limited){this.limitCropBox(true,true);}},renderImage:function renderImage(changed){var canvasData=this.canvasData,imageData=this.imageData;var width=imageData.naturalWidth*(canvasData.width/canvasData.naturalWidth);var height=imageData.naturalHeight*(canvasData.height/canvasData.naturalHeight);assign(imageData,{width:width,height:height,left:(canvasData.width-width)/2,top:(canvasData.height-height)/2});setStyle(this.image,assign({width:imageData.width,height:imageData.height},getTransforms(assign({translateX:imageData.left,translateY:imageData.top},imageData))));if(changed){this.output();}},initCropBox:function initCropBox(){var options=this.options,canvasData=this.canvasData;var aspectRatio=options.aspectRatio||options.initialAspectRatio;var autoCropArea=Number(options.autoCropArea)||0.8;var cropBoxData={width:canvasData.width,height:canvasData.height};if(aspectRatio){if(canvasData.height*aspectRatio>canvasData.width){cropBoxData.height=cropBoxData.width/aspectRatio;}else{cropBoxData.width=cropBoxData.height*aspectRatio;}}
this.cropBoxData=cropBoxData;this.limitCropBox(true,true);cropBoxData.width=Math.min(Math.max(cropBoxData.width,cropBoxData.minWidth),cropBoxData.maxWidth);cropBoxData.height=Math.min(Math.max(cropBoxData.height,cropBoxData.minHeight),cropBoxData.maxHeight);cropBoxData.width=Math.max(cropBoxData.minWidth,cropBoxData.width*autoCropArea);cropBoxData.height=Math.max(cropBoxData.minHeight,cropBoxData.height*autoCropArea);cropBoxData.left=canvasData.left+(canvasData.width-cropBoxData.width)/2;cropBoxData.top=canvasData.top+(canvasData.height-cropBoxData.height)/2;cropBoxData.oldLeft=cropBoxData.left;cropBoxData.oldTop=cropBoxData.top;this.initialCropBoxData=assign({},cropBoxData);},limitCropBox:function limitCropBox(sizeLimited,positionLimited){var options=this.options,containerData=this.containerData,canvasData=this.canvasData,cropBoxData=this.cropBoxData,limited=this.limited;var aspectRatio=options.aspectRatio;if(sizeLimited){var minCropBoxWidth=Number(options.minCropBoxWidth)||0;var minCropBoxHeight=Number(options.minCropBoxHeight)||0;var maxCropBoxWidth=limited?Math.min(containerData.width,canvasData.width,canvasData.width+canvasData.left,containerData.width-canvasData.left):containerData.width;var maxCropBoxHeight=limited?Math.min(containerData.height,canvasData.height,canvasData.height+canvasData.top,containerData.height-canvasData.top):containerData.height;minCropBoxWidth=Math.min(minCropBoxWidth,containerData.width);minCropBoxHeight=Math.min(minCropBoxHeight,containerData.height);if(aspectRatio){if(minCropBoxWidth&&minCropBoxHeight){if(minCropBoxHeight*aspectRatio>minCropBoxWidth){minCropBoxHeight=minCropBoxWidth/aspectRatio;}else{minCropBoxWidth=minCropBoxHeight*aspectRatio;}}else if(minCropBoxWidth){minCropBoxHeight=minCropBoxWidth/aspectRatio;}else if(minCropBoxHeight){minCropBoxWidth=minCropBoxHeight*aspectRatio;}
if(maxCropBoxHeight*aspectRatio>maxCropBoxWidth){maxCropBoxHeight=maxCropBoxWidth/aspectRatio;}else{maxCropBoxWidth=maxCropBoxHeight*aspectRatio;}}
cropBoxData.minWidth=Math.min(minCropBoxWidth,maxCropBoxWidth);cropBoxData.minHeight=Math.min(minCropBoxHeight,maxCropBoxHeight);cropBoxData.maxWidth=maxCropBoxWidth;cropBoxData.maxHeight=maxCropBoxHeight;}
if(positionLimited){if(limited){cropBoxData.minLeft=Math.max(0,canvasData.left);cropBoxData.minTop=Math.max(0,canvasData.top);cropBoxData.maxLeft=Math.min(containerData.width,canvasData.left+canvasData.width)-cropBoxData.width;cropBoxData.maxTop=Math.min(containerData.height,canvasData.top+canvasData.height)-cropBoxData.height;}else{cropBoxData.minLeft=0;cropBoxData.minTop=0;cropBoxData.maxLeft=containerData.width-cropBoxData.width;cropBoxData.maxTop=containerData.height-cropBoxData.height;}}},renderCropBox:function renderCropBox(){var options=this.options,containerData=this.containerData,cropBoxData=this.cropBoxData;if(cropBoxData.width>cropBoxData.maxWidth||cropBoxData.width<cropBoxData.minWidth){cropBoxData.left=cropBoxData.oldLeft;}
if(cropBoxData.height>cropBoxData.maxHeight||cropBoxData.height<cropBoxData.minHeight){cropBoxData.top=cropBoxData.oldTop;}
cropBoxData.width=Math.min(Math.max(cropBoxData.width,cropBoxData.minWidth),cropBoxData.maxWidth);cropBoxData.height=Math.min(Math.max(cropBoxData.height,cropBoxData.minHeight),cropBoxData.maxHeight);this.limitCropBox(false,true);cropBoxData.left=Math.min(Math.max(cropBoxData.left,cropBoxData.minLeft),cropBoxData.maxLeft);cropBoxData.top=Math.min(Math.max(cropBoxData.top,cropBoxData.minTop),cropBoxData.maxTop);cropBoxData.oldLeft=cropBoxData.left;cropBoxData.oldTop=cropBoxData.top;if(options.movable&&options.cropBoxMovable){setData(this.face,DATA_ACTION,cropBoxData.width>=containerData.width&&cropBoxData.height>=containerData.height?ACTION_MOVE:ACTION_ALL);}
setStyle(this.cropBox,assign({width:cropBoxData.width,height:cropBoxData.height},getTransforms({translateX:cropBoxData.left,translateY:cropBoxData.top})));if(this.cropped&&this.limited){this.limitCanvas(true,true);}
if(!this.disabled){this.output();}},output:function output(){this.preview();dispatchEvent(this.element,EVENT_CROP,this.getData());}};var preview={initPreview:function initPreview(){var element=this.element,crossOrigin=this.crossOrigin;var preview=this.options.preview;var url=crossOrigin?this.crossOriginUrl:this.url;var alt=element.alt||'The image to preview';var image=document.createElement('img');if(crossOrigin){image.crossOrigin=crossOrigin;}
image.src=url;image.alt=alt;this.viewBox.appendChild(image);this.viewBoxImage=image;if(!preview){return;}
var previews=preview;if(typeof preview==='string'){previews=element.ownerDocument.querySelectorAll(preview);}else if(preview.querySelector){previews=[preview];}
this.previews=previews;forEach(previews,function(el){var img=document.createElement('img');setData(el,DATA_PREVIEW,{width:el.offsetWidth,height:el.offsetHeight,html:el.innerHTML});if(crossOrigin){img.crossOrigin=crossOrigin;}
img.src=url;img.alt=alt;img.style.cssText='display:block;'+'width:100%;'+'height:auto;'+'min-width:0!important;'+'min-height:0!important;'+'max-width:none!important;'+'max-height:none!important;'+'image-orientation:0deg!important;"';el.innerHTML='';el.appendChild(img);});},resetPreview:function resetPreview(){forEach(this.previews,function(element){var data=getData(element,DATA_PREVIEW);setStyle(element,{width:data.width,height:data.height});element.innerHTML=data.html;removeData(element,DATA_PREVIEW);});},preview:function preview(){var imageData=this.imageData,canvasData=this.canvasData,cropBoxData=this.cropBoxData;var cropBoxWidth=cropBoxData.width,cropBoxHeight=cropBoxData.height;var width=imageData.width,height=imageData.height;var left=cropBoxData.left-canvasData.left-imageData.left;var top=cropBoxData.top-canvasData.top-imageData.top;if(!this.cropped||this.disabled){return;}
setStyle(this.viewBoxImage,assign({width:width,height:height},getTransforms(assign({translateX:-left,translateY:-top},imageData))));forEach(this.previews,function(element){var data=getData(element,DATA_PREVIEW);var originalWidth=data.width;var originalHeight=data.height;var newWidth=originalWidth;var newHeight=originalHeight;var ratio=1;if(cropBoxWidth){ratio=originalWidth/cropBoxWidth;newHeight=cropBoxHeight*ratio;}
if(cropBoxHeight&&newHeight>originalHeight){ratio=originalHeight/cropBoxHeight;newWidth=cropBoxWidth*ratio;newHeight=originalHeight;}
setStyle(element,{width:newWidth,height:newHeight});setStyle(element.getElementsByTagName('img')[0],assign({width:width*ratio,height:height*ratio},getTransforms(assign({translateX:-left*ratio,translateY:-top*ratio},imageData))));});}};var events={bind:function bind(){var element=this.element,options=this.options,cropper=this.cropper;if(isFunction(options.cropstart)){addListener(element,EVENT_CROP_START,options.cropstart);}
if(isFunction(options.cropmove)){addListener(element,EVENT_CROP_MOVE,options.cropmove);}
if(isFunction(options.cropend)){addListener(element,EVENT_CROP_END,options.cropend);}
if(isFunction(options.crop)){addListener(element,EVENT_CROP,options.crop);}
if(isFunction(options.zoom)){addListener(element,EVENT_ZOOM,options.zoom);}
addListener(cropper,EVENT_POINTER_DOWN,this.onCropStart=this.cropStart.bind(this));if(options.zoomable&&options.zoomOnWheel){addListener(cropper,EVENT_WHEEL,this.onWheel=this.wheel.bind(this),{passive:false,capture:true});}
if(options.toggleDragModeOnDblclick){addListener(cropper,EVENT_DBLCLICK,this.onDblclick=this.dblclick.bind(this));}
addListener(element.ownerDocument,EVENT_POINTER_MOVE,this.onCropMove=this.cropMove.bind(this));addListener(element.ownerDocument,EVENT_POINTER_UP,this.onCropEnd=this.cropEnd.bind(this));if(options.responsive){addListener(window,EVENT_RESIZE,this.onResize=this.resize.bind(this));}},unbind:function unbind(){var element=this.element,options=this.options,cropper=this.cropper;if(isFunction(options.cropstart)){removeListener(element,EVENT_CROP_START,options.cropstart);}
if(isFunction(options.cropmove)){removeListener(element,EVENT_CROP_MOVE,options.cropmove);}
if(isFunction(options.cropend)){removeListener(element,EVENT_CROP_END,options.cropend);}
if(isFunction(options.crop)){removeListener(element,EVENT_CROP,options.crop);}
if(isFunction(options.zoom)){removeListener(element,EVENT_ZOOM,options.zoom);}
removeListener(cropper,EVENT_POINTER_DOWN,this.onCropStart);if(options.zoomable&&options.zoomOnWheel){removeListener(cropper,EVENT_WHEEL,this.onWheel,{passive:false,capture:true});}
if(options.toggleDragModeOnDblclick){removeListener(cropper,EVENT_DBLCLICK,this.onDblclick);}
removeListener(element.ownerDocument,EVENT_POINTER_MOVE,this.onCropMove);removeListener(element.ownerDocument,EVENT_POINTER_UP,this.onCropEnd);if(options.responsive){removeListener(window,EVENT_RESIZE,this.onResize);}}};var handlers={resize:function resize(){var options=this.options,container=this.container,containerData=this.containerData;var minContainerWidth=Number(options.minContainerWidth)||MIN_CONTAINER_WIDTH;var minContainerHeight=Number(options.minContainerHeight)||MIN_CONTAINER_HEIGHT;if(this.disabled||containerData.width<=minContainerWidth||containerData.height<=minContainerHeight){return;}
var ratio=container.offsetWidth/containerData.width;if(ratio!==1||container.offsetHeight!==containerData.height){var canvasData;var cropBoxData;if(options.restore){canvasData=this.getCanvasData();cropBoxData=this.getCropBoxData();}
this.render();if(options.restore){this.setCanvasData(forEach(canvasData,function(n,i){canvasData[i]=n*ratio;}));this.setCropBoxData(forEach(cropBoxData,function(n,i){cropBoxData[i]=n*ratio;}));}}},dblclick:function dblclick(){if(this.disabled||this.options.dragMode===DRAG_MODE_NONE){return;}
this.setDragMode(hasClass(this.dragBox,CLASS_CROP)?DRAG_MODE_MOVE:DRAG_MODE_CROP);},wheel:function wheel(event){var _this=this;var ratio=Number(this.options.wheelZoomRatio)||0.1;var delta=1;if(this.disabled){return;}
event.preventDefault();if(this.wheeling){return;}
this.wheeling=true;setTimeout(function(){_this.wheeling=false;},50);if(event.deltaY){delta=event.deltaY>0?1:-1;}else if(event.wheelDelta){delta=-event.wheelDelta/120;}else if(event.detail){delta=event.detail>0?1:-1;}
this.zoom(-delta*ratio,event);},cropStart:function cropStart(event){var buttons=event.buttons,button=event.button;if(this.disabled||isNumber(buttons)&&buttons!==1||isNumber(button)&&button!==0||event.ctrlKey){return;}
var options=this.options,pointers=this.pointers;var action;if(event.changedTouches){forEach(event.changedTouches,function(touch){pointers[touch.identifier]=getPointer(touch);});}else{pointers[event.pointerId||0]=getPointer(event);}
if(Object.keys(pointers).length>1&&options.zoomable&&options.zoomOnTouch){action=ACTION_ZOOM;}else{action=getData(event.target,DATA_ACTION);}
if(!REGEXP_ACTIONS.test(action)){return;}
if(dispatchEvent(this.element,EVENT_CROP_START,{originalEvent:event,action:action})===false){return;}
event.preventDefault();this.action=action;this.cropping=false;if(action===ACTION_CROP){this.cropping=true;addClass(this.dragBox,CLASS_MODAL);}},cropMove:function cropMove(event){var action=this.action;if(this.disabled||!action){return;}
var pointers=this.pointers;event.preventDefault();if(dispatchEvent(this.element,EVENT_CROP_MOVE,{originalEvent:event,action:action})===false){return;}
if(event.changedTouches){forEach(event.changedTouches,function(touch){assign(pointers[touch.identifier]||{},getPointer(touch,true));});}else{assign(pointers[event.pointerId||0]||{},getPointer(event,true));}
this.change(event);},cropEnd:function cropEnd(event){if(this.disabled){return;}
var action=this.action,pointers=this.pointers;if(event.changedTouches){forEach(event.changedTouches,function(touch){delete pointers[touch.identifier];});}else{delete pointers[event.pointerId||0];}
if(!action){return;}
event.preventDefault();if(!Object.keys(pointers).length){this.action='';}
if(this.cropping){this.cropping=false;toggleClass(this.dragBox,CLASS_MODAL,this.cropped&&this.options.modal);}
dispatchEvent(this.element,EVENT_CROP_END,{originalEvent:event,action:action});}};var change={change:function change(event){var options=this.options,canvasData=this.canvasData,containerData=this.containerData,cropBoxData=this.cropBoxData,pointers=this.pointers;var action=this.action;var aspectRatio=options.aspectRatio;var left=cropBoxData.left,top=cropBoxData.top,width=cropBoxData.width,height=cropBoxData.height;var right=left+width;var bottom=top+height;var minLeft=0;var minTop=0;var maxWidth=containerData.width;var maxHeight=containerData.height;var renderable=true;var offset;if(!aspectRatio&&event.shiftKey){aspectRatio=width&&height?width/height:1;}
if(this.limited){minLeft=cropBoxData.minLeft;minTop=cropBoxData.minTop;maxWidth=minLeft+Math.min(containerData.width,canvasData.width,canvasData.left+canvasData.width);maxHeight=minTop+Math.min(containerData.height,canvasData.height,canvasData.top+canvasData.height);}
var pointer=pointers[Object.keys(pointers)[0]];var range={x:pointer.endX-pointer.startX,y:pointer.endY-pointer.startY};var check=function check(side){switch(side){case ACTION_EAST:if(right+range.x>maxWidth){range.x=maxWidth-right;}
break;case ACTION_WEST:if(left+range.x<minLeft){range.x=minLeft-left;}
break;case ACTION_NORTH:if(top+range.y<minTop){range.y=minTop-top;}
break;case ACTION_SOUTH:if(bottom+range.y>maxHeight){range.y=maxHeight-bottom;}
break;default:}};switch(action){case ACTION_ALL:left+=range.x;top+=range.y;break;case ACTION_EAST:if(range.x>=0&&(right>=maxWidth||aspectRatio&&(top<=minTop||bottom>=maxHeight))){renderable=false;break;}
check(ACTION_EAST);width+=range.x;if(width<0){action=ACTION_WEST;width=-width;left-=width;}
if(aspectRatio){height=width/aspectRatio;top+=(cropBoxData.height-height)/2;}
break;case ACTION_NORTH:if(range.y<=0&&(top<=minTop||aspectRatio&&(left<=minLeft||right>=maxWidth))){renderable=false;break;}
check(ACTION_NORTH);height-=range.y;top+=range.y;if(height<0){action=ACTION_SOUTH;height=-height;top-=height;}
if(aspectRatio){width=height*aspectRatio;left+=(cropBoxData.width-width)/2;}
break;case ACTION_WEST:if(range.x<=0&&(left<=minLeft||aspectRatio&&(top<=minTop||bottom>=maxHeight))){renderable=false;break;}
check(ACTION_WEST);width-=range.x;left+=range.x;if(width<0){action=ACTION_EAST;width=-width;left-=width;}
if(aspectRatio){height=width/aspectRatio;top+=(cropBoxData.height-height)/2;}
break;case ACTION_SOUTH:if(range.y>=0&&(bottom>=maxHeight||aspectRatio&&(left<=minLeft||right>=maxWidth))){renderable=false;break;}
check(ACTION_SOUTH);height+=range.y;if(height<0){action=ACTION_NORTH;height=-height;top-=height;}
if(aspectRatio){width=height*aspectRatio;left+=(cropBoxData.width-width)/2;}
break;case ACTION_NORTH_EAST:if(aspectRatio){if(range.y<=0&&(top<=minTop||right>=maxWidth)){renderable=false;break;}
check(ACTION_NORTH);height-=range.y;top+=range.y;width=height*aspectRatio;}else{check(ACTION_NORTH);check(ACTION_EAST);if(range.x>=0){if(right<maxWidth){width+=range.x;}else if(range.y<=0&&top<=minTop){renderable=false;}}else{width+=range.x;}
if(range.y<=0){if(top>minTop){height-=range.y;top+=range.y;}}else{height-=range.y;top+=range.y;}}
if(width<0&&height<0){action=ACTION_SOUTH_WEST;height=-height;width=-width;top-=height;left-=width;}else if(width<0){action=ACTION_NORTH_WEST;width=-width;left-=width;}else if(height<0){action=ACTION_SOUTH_EAST;height=-height;top-=height;}
break;case ACTION_NORTH_WEST:if(aspectRatio){if(range.y<=0&&(top<=minTop||left<=minLeft)){renderable=false;break;}
check(ACTION_NORTH);height-=range.y;top+=range.y;width=height*aspectRatio;left+=cropBoxData.width-width;}else{check(ACTION_NORTH);check(ACTION_WEST);if(range.x<=0){if(left>minLeft){width-=range.x;left+=range.x;}else if(range.y<=0&&top<=minTop){renderable=false;}}else{width-=range.x;left+=range.x;}
if(range.y<=0){if(top>minTop){height-=range.y;top+=range.y;}}else{height-=range.y;top+=range.y;}}
if(width<0&&height<0){action=ACTION_SOUTH_EAST;height=-height;width=-width;top-=height;left-=width;}else if(width<0){action=ACTION_NORTH_EAST;width=-width;left-=width;}else if(height<0){action=ACTION_SOUTH_WEST;height=-height;top-=height;}
break;case ACTION_SOUTH_WEST:if(aspectRatio){if(range.x<=0&&(left<=minLeft||bottom>=maxHeight)){renderable=false;break;}
check(ACTION_WEST);width-=range.x;left+=range.x;height=width/aspectRatio;}else{check(ACTION_SOUTH);check(ACTION_WEST);if(range.x<=0){if(left>minLeft){width-=range.x;left+=range.x;}else if(range.y>=0&&bottom>=maxHeight){renderable=false;}}else{width-=range.x;left+=range.x;}
if(range.y>=0){if(bottom<maxHeight){height+=range.y;}}else{height+=range.y;}}
if(width<0&&height<0){action=ACTION_NORTH_EAST;height=-height;width=-width;top-=height;left-=width;}else if(width<0){action=ACTION_SOUTH_EAST;width=-width;left-=width;}else if(height<0){action=ACTION_NORTH_WEST;height=-height;top-=height;}
break;case ACTION_SOUTH_EAST:if(aspectRatio){if(range.x>=0&&(right>=maxWidth||bottom>=maxHeight)){renderable=false;break;}
check(ACTION_EAST);width+=range.x;height=width/aspectRatio;}else{check(ACTION_SOUTH);check(ACTION_EAST);if(range.x>=0){if(right<maxWidth){width+=range.x;}else if(range.y>=0&&bottom>=maxHeight){renderable=false;}}else{width+=range.x;}
if(range.y>=0){if(bottom<maxHeight){height+=range.y;}}else{height+=range.y;}}
if(width<0&&height<0){action=ACTION_NORTH_WEST;height=-height;width=-width;top-=height;left-=width;}else if(width<0){action=ACTION_SOUTH_WEST;width=-width;left-=width;}else if(height<0){action=ACTION_NORTH_EAST;height=-height;top-=height;}
break;case ACTION_MOVE:this.move(range.x,range.y);renderable=false;break;case ACTION_ZOOM:this.zoom(getMaxZoomRatio(pointers),event);renderable=false;break;case ACTION_CROP:if(!range.x||!range.y){renderable=false;break;}
offset=getOffset(this.cropper);left=pointer.startX-offset.left;top=pointer.startY-offset.top;width=cropBoxData.minWidth;height=cropBoxData.minHeight;if(range.x>0){action=range.y>0?ACTION_SOUTH_EAST:ACTION_NORTH_EAST;}else if(range.x<0){left-=width;action=range.y>0?ACTION_SOUTH_WEST:ACTION_NORTH_WEST;}
if(range.y<0){top-=height;}
if(!this.cropped){removeClass(this.cropBox,CLASS_HIDDEN);this.cropped=true;if(this.limited){this.limitCropBox(true,true);}}
break;default:}
if(renderable){cropBoxData.width=width;cropBoxData.height=height;cropBoxData.left=left;cropBoxData.top=top;this.action=action;this.renderCropBox();}
forEach(pointers,function(p){p.startX=p.endX;p.startY=p.endY;});}};var methods={crop:function crop(){if(this.ready&&!this.cropped&&!this.disabled){this.cropped=true;this.limitCropBox(true,true);if(this.options.modal){addClass(this.dragBox,CLASS_MODAL);}
removeClass(this.cropBox,CLASS_HIDDEN);this.setCropBoxData(this.initialCropBoxData);}
return this;},reset:function reset(){if(this.ready&&!this.disabled){this.imageData=assign({},this.initialImageData);this.canvasData=assign({},this.initialCanvasData);this.cropBoxData=assign({},this.initialCropBoxData);this.renderCanvas();if(this.cropped){this.renderCropBox();}}
return this;},clear:function clear(){if(this.cropped&&!this.disabled){assign(this.cropBoxData,{left:0,top:0,width:0,height:0});this.cropped=false;this.renderCropBox();this.limitCanvas(true,true);this.renderCanvas();removeClass(this.dragBox,CLASS_MODAL);addClass(this.cropBox,CLASS_HIDDEN);}
return this;},replace:function replace(url){var hasSameSize=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;if(!this.disabled&&url){if(this.isImg){this.element.src=url;}
if(hasSameSize){this.url=url;this.image.src=url;if(this.ready){this.viewBoxImage.src=url;forEach(this.previews,function(element){element.getElementsByTagName('img')[0].src=url;});}}else{if(this.isImg){this.replaced=true;}
this.options.data=null;this.uncreate();this.load(url);}}
return this;},enable:function enable(){if(this.ready&&this.disabled){this.disabled=false;removeClass(this.cropper,CLASS_DISABLED);}
return this;},disable:function disable(){if(this.ready&&!this.disabled){this.disabled=true;addClass(this.cropper,CLASS_DISABLED);}
return this;},destroy:function destroy(){var element=this.element;if(!element[NAMESPACE]){return this;}
element[NAMESPACE]=undefined;if(this.isImg&&this.replaced){element.src=this.originalUrl;}
this.uncreate();return this;},move:function move(offsetX){var offsetY=arguments.length>1&&arguments[1]!==undefined?arguments[1]:offsetX;var _this$canvasData=this.canvasData,left=_this$canvasData.left,top=_this$canvasData.top;return this.moveTo(isUndefined(offsetX)?offsetX:left+Number(offsetX),isUndefined(offsetY)?offsetY:top+Number(offsetY));},moveTo:function moveTo(x){var y=arguments.length>1&&arguments[1]!==undefined?arguments[1]:x;var canvasData=this.canvasData;var changed=false;x=Number(x);y=Number(y);if(this.ready&&!this.disabled&&this.options.movable){if(isNumber(x)){canvasData.left=x;changed=true;}
if(isNumber(y)){canvasData.top=y;changed=true;}
if(changed){this.renderCanvas(true);}}
return this;},zoom:function zoom(ratio,_originalEvent){var canvasData=this.canvasData;ratio=Number(ratio);if(ratio<0){ratio=1/(1-ratio);}else{ratio=1+ratio;}
return this.zoomTo(canvasData.width*ratio/canvasData.naturalWidth,null,_originalEvent);},zoomTo:function zoomTo(ratio,pivot,_originalEvent){var options=this.options,canvasData=this.canvasData;var width=canvasData.width,height=canvasData.height,naturalWidth=canvasData.naturalWidth,naturalHeight=canvasData.naturalHeight;ratio=Number(ratio);if(ratio>=0&&this.ready&&!this.disabled&&options.zoomable){var newWidth=naturalWidth*ratio;var newHeight=naturalHeight*ratio;if(dispatchEvent(this.element,EVENT_ZOOM,{ratio:ratio,oldRatio:width/naturalWidth,originalEvent:_originalEvent})===false){return this;}
if(_originalEvent){var pointers=this.pointers;var offset=getOffset(this.cropper);var center=pointers&&Object.keys(pointers).length?getPointersCenter(pointers):{pageX:_originalEvent.pageX,pageY:_originalEvent.pageY};canvasData.left-=(newWidth-width)*((center.pageX-offset.left-canvasData.left)/width);canvasData.top-=(newHeight-height)*((center.pageY-offset.top-canvasData.top)/height);}else if(isPlainObject(pivot)&&isNumber(pivot.x)&&isNumber(pivot.y)){canvasData.left-=(newWidth-width)*((pivot.x-canvasData.left)/width);canvasData.top-=(newHeight-height)*((pivot.y-canvasData.top)/height);}else{canvasData.left-=(newWidth-width)/2;canvasData.top-=(newHeight-height)/2;}
canvasData.width=newWidth;canvasData.height=newHeight;this.renderCanvas(true);}
return this;},rotate:function rotate(degree){return this.rotateTo((this.imageData.rotate||0)+Number(degree));},rotateTo:function rotateTo(degree){degree=Number(degree);if(isNumber(degree)&&this.ready&&!this.disabled&&this.options.rotatable){this.imageData.rotate=degree%360;this.renderCanvas(true,true);}
return this;},scaleX:function scaleX(_scaleX){var scaleY=this.imageData.scaleY;return this.scale(_scaleX,isNumber(scaleY)?scaleY:1);},scaleY:function scaleY(_scaleY){var scaleX=this.imageData.scaleX;return this.scale(isNumber(scaleX)?scaleX:1,_scaleY);},scale:function scale(scaleX){var scaleY=arguments.length>1&&arguments[1]!==undefined?arguments[1]:scaleX;var imageData=this.imageData;var transformed=false;scaleX=Number(scaleX);scaleY=Number(scaleY);if(this.ready&&!this.disabled&&this.options.scalable){if(isNumber(scaleX)){imageData.scaleX=scaleX;transformed=true;}
if(isNumber(scaleY)){imageData.scaleY=scaleY;transformed=true;}
if(transformed){this.renderCanvas(true,true);}}
return this;},getData:function getData(){var rounded=arguments.length>0&&arguments[0]!==undefined?arguments[0]:false;var options=this.options,imageData=this.imageData,canvasData=this.canvasData,cropBoxData=this.cropBoxData;var data;if(this.ready&&this.cropped){data={x:cropBoxData.left-canvasData.left,y:cropBoxData.top-canvasData.top,width:cropBoxData.width,height:cropBoxData.height};var ratio=imageData.width/imageData.naturalWidth;forEach(data,function(n,i){data[i]=n/ratio;});if(rounded){var bottom=Math.round(data.y+data.height);var right=Math.round(data.x+data.width);data.x=Math.round(data.x);data.y=Math.round(data.y);data.width=right-data.x;data.height=bottom-data.y;}}else{data={x:0,y:0,width:0,height:0};}
if(options.rotatable){data.rotate=imageData.rotate||0;}
if(options.scalable){data.scaleX=imageData.scaleX||1;data.scaleY=imageData.scaleY||1;}
return data;},setData:function setData(data){var options=this.options,imageData=this.imageData,canvasData=this.canvasData;var cropBoxData={};if(this.ready&&!this.disabled&&isPlainObject(data)){var transformed=false;if(options.rotatable){if(isNumber(data.rotate)&&data.rotate!==imageData.rotate){imageData.rotate=data.rotate;transformed=true;}}
if(options.scalable){if(isNumber(data.scaleX)&&data.scaleX!==imageData.scaleX){imageData.scaleX=data.scaleX;transformed=true;}
if(isNumber(data.scaleY)&&data.scaleY!==imageData.scaleY){imageData.scaleY=data.scaleY;transformed=true;}}
if(transformed){this.renderCanvas(true,true);}
var ratio=imageData.width/imageData.naturalWidth;if(isNumber(data.x)){cropBoxData.left=data.x*ratio+canvasData.left;}
if(isNumber(data.y)){cropBoxData.top=data.y*ratio+canvasData.top;}
if(isNumber(data.width)){cropBoxData.width=data.width*ratio;}
if(isNumber(data.height)){cropBoxData.height=data.height*ratio;}
this.setCropBoxData(cropBoxData);}
return this;},getContainerData:function getContainerData(){return this.ready?assign({},this.containerData):{};},getImageData:function getImageData(){return this.sized?assign({},this.imageData):{};},getCanvasData:function getCanvasData(){var canvasData=this.canvasData;var data={};if(this.ready){forEach(['left','top','width','height','naturalWidth','naturalHeight'],function(n){data[n]=canvasData[n];});}
return data;},setCanvasData:function setCanvasData(data){var canvasData=this.canvasData;var aspectRatio=canvasData.aspectRatio;if(this.ready&&!this.disabled&&isPlainObject(data)){if(isNumber(data.left)){canvasData.left=data.left;}
if(isNumber(data.top)){canvasData.top=data.top;}
if(isNumber(data.width)){canvasData.width=data.width;canvasData.height=data.width/aspectRatio;}else if(isNumber(data.height)){canvasData.height=data.height;canvasData.width=data.height*aspectRatio;}
this.renderCanvas(true);}
return this;},getCropBoxData:function getCropBoxData(){var cropBoxData=this.cropBoxData;var data;if(this.ready&&this.cropped){data={left:cropBoxData.left,top:cropBoxData.top,width:cropBoxData.width,height:cropBoxData.height};}
return data||{};},setCropBoxData:function setCropBoxData(data){var cropBoxData=this.cropBoxData;var aspectRatio=this.options.aspectRatio;var widthChanged;var heightChanged;if(this.ready&&this.cropped&&!this.disabled&&isPlainObject(data)){if(isNumber(data.left)){cropBoxData.left=data.left;}
if(isNumber(data.top)){cropBoxData.top=data.top;}
if(isNumber(data.width)&&data.width!==cropBoxData.width){widthChanged=true;cropBoxData.width=data.width;}
if(isNumber(data.height)&&data.height!==cropBoxData.height){heightChanged=true;cropBoxData.height=data.height;}
if(aspectRatio){if(widthChanged){cropBoxData.height=cropBoxData.width/aspectRatio;}else if(heightChanged){cropBoxData.width=cropBoxData.height*aspectRatio;}}
this.renderCropBox();}
return this;},getCroppedCanvas:function getCroppedCanvas(){var options=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};if(!this.ready||!window.HTMLCanvasElement){return null;}
var canvasData=this.canvasData;var source=getSourceCanvas(this.image,this.imageData,canvasData,options);if(!this.cropped){return source;}
var _this$getData=this.getData(),initialX=_this$getData.x,initialY=_this$getData.y,initialWidth=_this$getData.width,initialHeight=_this$getData.height;var ratio=source.width/Math.floor(canvasData.naturalWidth);if(ratio!==1){initialX*=ratio;initialY*=ratio;initialWidth*=ratio;initialHeight*=ratio;}
var aspectRatio=initialWidth/initialHeight;var maxSizes=getAdjustedSizes({aspectRatio:aspectRatio,width:options.maxWidth||Infinity,height:options.maxHeight||Infinity});var minSizes=getAdjustedSizes({aspectRatio:aspectRatio,width:options.minWidth||0,height:options.minHeight||0},'cover');var _getAdjustedSizes=getAdjustedSizes({aspectRatio:aspectRatio,width:options.width||(ratio!==1?source.width:initialWidth),height:options.height||(ratio!==1?source.height:initialHeight)}),width=_getAdjustedSizes.width,height=_getAdjustedSizes.height;width=Math.min(maxSizes.width,Math.max(minSizes.width,width));height=Math.min(maxSizes.height,Math.max(minSizes.height,height));var canvas=document.createElement('canvas');var context=canvas.getContext('2d');canvas.width=normalizeDecimalNumber(width);canvas.height=normalizeDecimalNumber(height);context.fillStyle=options.fillColor||'transparent';context.fillRect(0,0,width,height);var _options$imageSmoothi=options.imageSmoothingEnabled,imageSmoothingEnabled=_options$imageSmoothi===void 0?true:_options$imageSmoothi,imageSmoothingQuality=options.imageSmoothingQuality;context.imageSmoothingEnabled=imageSmoothingEnabled;if(imageSmoothingQuality){context.imageSmoothingQuality=imageSmoothingQuality;}
var sourceWidth=source.width;var sourceHeight=source.height;var srcX=initialX;var srcY=initialY;var srcWidth;var srcHeight;var dstX;var dstY;var dstWidth;var dstHeight;if(srcX<=-initialWidth||srcX>sourceWidth){srcX=0;srcWidth=0;dstX=0;dstWidth=0;}else if(srcX<=0){dstX=-srcX;srcX=0;srcWidth=Math.min(sourceWidth,initialWidth+srcX);dstWidth=srcWidth;}else if(srcX<=sourceWidth){dstX=0;srcWidth=Math.min(initialWidth,sourceWidth-srcX);dstWidth=srcWidth;}
if(srcWidth<=0||srcY<=-initialHeight||srcY>sourceHeight){srcY=0;srcHeight=0;dstY=0;dstHeight=0;}else if(srcY<=0){dstY=-srcY;srcY=0;srcHeight=Math.min(sourceHeight,initialHeight+srcY);dstHeight=srcHeight;}else if(srcY<=sourceHeight){dstY=0;srcHeight=Math.min(initialHeight,sourceHeight-srcY);dstHeight=srcHeight;}
var params=[srcX,srcY,srcWidth,srcHeight];if(dstWidth>0&&dstHeight>0){var scale=width/initialWidth;params.push(dstX*scale,dstY*scale,dstWidth*scale,dstHeight*scale);}
context.drawImage.apply(context,[source].concat(_toConsumableArray(params.map(function(param){return Math.floor(normalizeDecimalNumber(param));}))));return canvas;},setAspectRatio:function setAspectRatio(aspectRatio){var options=this.options;if(!this.disabled&&!isUndefined(aspectRatio)){options.aspectRatio=Math.max(0,aspectRatio)||NaN;if(this.ready){this.initCropBox();if(this.cropped){this.renderCropBox();}}}
return this;},setDragMode:function setDragMode(mode){var options=this.options,dragBox=this.dragBox,face=this.face;if(this.ready&&!this.disabled){var croppable=mode===DRAG_MODE_CROP;var movable=options.movable&&mode===DRAG_MODE_MOVE;mode=croppable||movable?mode:DRAG_MODE_NONE;options.dragMode=mode;setData(dragBox,DATA_ACTION,mode);toggleClass(dragBox,CLASS_CROP,croppable);toggleClass(dragBox,CLASS_MOVE,movable);if(!options.cropBoxMovable){setData(face,DATA_ACTION,mode);toggleClass(face,CLASS_CROP,croppable);toggleClass(face,CLASS_MOVE,movable);}}
return this;}};var AnotherCropper=WINDOW.Cropper;var Cropper=function(){function Cropper(element){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};_classCallCheck(this,Cropper);if(!element||!REGEXP_TAG_NAME.test(element.tagName)){throw new Error('The first argument is required and must be an <img> or <canvas> element.');}
this.element=element;this.options=assign({},DEFAULTS,isPlainObject(options)&&options);this.cropped=false;this.disabled=false;this.pointers={};this.ready=false;this.reloading=false;this.replaced=false;this.sized=false;this.sizing=false;this.init();}
_createClass(Cropper,[{key:"init",value:function init(){var element=this.element;var tagName=element.tagName.toLowerCase();var url;if(element[NAMESPACE]){return;}
element[NAMESPACE]=this;if(tagName==='img'){this.isImg=true;url=element.getAttribute('src')||'';this.originalUrl=url;if(!url){return;}
url=element.src;}else if(tagName==='canvas'&&window.HTMLCanvasElement){url=element.toDataURL();}
this.load(url);}},{key:"load",value:function load(url){var _this=this;if(!url){return;}
this.url=url;this.imageData={};var element=this.element,options=this.options;if(!options.rotatable&&!options.scalable){options.checkOrientation=false;}
if(!options.checkOrientation||!window.ArrayBuffer){this.clone();return;}
if(REGEXP_DATA_URL.test(url)){if(REGEXP_DATA_URL_JPEG.test(url)){this.read(dataURLToArrayBuffer(url));}else{this.clone();}
return;}
var xhr=new XMLHttpRequest();var clone=this.clone.bind(this);this.reloading=true;this.xhr=xhr;xhr.onabort=clone;xhr.onerror=clone;xhr.ontimeout=clone;xhr.onprogress=function(){if(xhr.getResponseHeader('content-type')!==MIME_TYPE_JPEG){xhr.abort();}};xhr.onload=function(){_this.read(xhr.response);};xhr.onloadend=function(){_this.reloading=false;_this.xhr=null;};if(options.checkCrossOrigin&&isCrossOriginURL(url)&&element.crossOrigin){url=addTimestamp(url);}
xhr.open('GET',url);xhr.responseType='arraybuffer';xhr.withCredentials=element.crossOrigin==='use-credentials';xhr.send();}},{key:"read",value:function read(arrayBuffer){var options=this.options,imageData=this.imageData;var orientation=resetAndGetOrientation(arrayBuffer);var rotate=0;var scaleX=1;var scaleY=1;if(orientation>1){this.url=arrayBufferToDataURL(arrayBuffer,MIME_TYPE_JPEG);var _parseOrientation=parseOrientation(orientation);rotate=_parseOrientation.rotate;scaleX=_parseOrientation.scaleX;scaleY=_parseOrientation.scaleY;}
if(options.rotatable){imageData.rotate=rotate;}
if(options.scalable){imageData.scaleX=scaleX;imageData.scaleY=scaleY;}
this.clone();}},{key:"clone",value:function clone(){var element=this.element,url=this.url;var crossOrigin=element.crossOrigin;var crossOriginUrl=url;if(this.options.checkCrossOrigin&&isCrossOriginURL(url)){if(!crossOrigin){crossOrigin='anonymous';}
crossOriginUrl=addTimestamp(url);}
this.crossOrigin=crossOrigin;this.crossOriginUrl=crossOriginUrl;var image=document.createElement('img');if(crossOrigin){image.crossOrigin=crossOrigin;}
image.src=crossOriginUrl||url;image.alt=element.alt||'The image to crop';this.image=image;image.onload=this.start.bind(this);image.onerror=this.stop.bind(this);addClass(image,CLASS_HIDE);element.parentNode.insertBefore(image,element.nextSibling);}},{key:"start",value:function start(){var _this2=this;var image=this.image;image.onload=null;image.onerror=null;this.sizing=true;var isIOSWebKit=WINDOW.navigator&&/(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent);var done=function done(naturalWidth,naturalHeight){assign(_this2.imageData,{naturalWidth:naturalWidth,naturalHeight:naturalHeight,aspectRatio:naturalWidth/naturalHeight});_this2.sizing=false;_this2.sized=true;_this2.build();};if(image.naturalWidth&&!isIOSWebKit){done(image.naturalWidth,image.naturalHeight);return;}
var sizingImage=document.createElement('img');var body=document.body||document.documentElement;this.sizingImage=sizingImage;sizingImage.onload=function(){done(sizingImage.width,sizingImage.height);if(!isIOSWebKit){body.removeChild(sizingImage);}};sizingImage.src=image.src;if(!isIOSWebKit){sizingImage.style.cssText='left:0;'+'max-height:none!important;'+'max-width:none!important;'+'min-height:0!important;'+'min-width:0!important;'+'opacity:0;'+'position:absolute;'+'top:0;'+'z-index:-1;';body.appendChild(sizingImage);}}},{key:"stop",value:function stop(){var image=this.image;image.onload=null;image.onerror=null;image.parentNode.removeChild(image);this.image=null;}},{key:"build",value:function build(){if(!this.sized||this.ready){return;}
var element=this.element,options=this.options,image=this.image;var container=element.parentNode;var template=document.createElement('div');template.innerHTML=TEMPLATE;var cropper=template.querySelector(".".concat(NAMESPACE,"-container"));var canvas=cropper.querySelector(".".concat(NAMESPACE,"-canvas"));var dragBox=cropper.querySelector(".".concat(NAMESPACE,"-drag-box"));var cropBox=cropper.querySelector(".".concat(NAMESPACE,"-crop-box"));var face=cropBox.querySelector(".".concat(NAMESPACE,"-face"));this.container=container;this.cropper=cropper;this.canvas=canvas;this.dragBox=dragBox;this.cropBox=cropBox;this.viewBox=cropper.querySelector(".".concat(NAMESPACE,"-view-box"));this.face=face;canvas.appendChild(image);addClass(element,CLASS_HIDDEN);container.insertBefore(cropper,element.nextSibling);if(!this.isImg){removeClass(image,CLASS_HIDE);}
this.initPreview();this.bind();options.initialAspectRatio=Math.max(0,options.initialAspectRatio)||NaN;options.aspectRatio=Math.max(0,options.aspectRatio)||NaN;options.viewMode=Math.max(0,Math.min(3,Math.round(options.viewMode)))||0;addClass(cropBox,CLASS_HIDDEN);if(!options.guides){addClass(cropBox.getElementsByClassName("".concat(NAMESPACE,"-dashed")),CLASS_HIDDEN);}
if(!options.center){addClass(cropBox.getElementsByClassName("".concat(NAMESPACE,"-center")),CLASS_HIDDEN);}
if(options.background){addClass(cropper,"".concat(NAMESPACE,"-bg"));}
if(!options.highlight){addClass(face,CLASS_INVISIBLE);}
if(options.cropBoxMovable){addClass(face,CLASS_MOVE);setData(face,DATA_ACTION,ACTION_ALL);}
if(!options.cropBoxResizable){addClass(cropBox.getElementsByClassName("".concat(NAMESPACE,"-line")),CLASS_HIDDEN);addClass(cropBox.getElementsByClassName("".concat(NAMESPACE,"-point")),CLASS_HIDDEN);}
this.render();this.ready=true;this.setDragMode(options.dragMode);if(options.autoCrop){this.crop();}
this.setData(options.data);if(isFunction(options.ready)){addListener(element,EVENT_READY,options.ready,{once:true});}
dispatchEvent(element,EVENT_READY);}},{key:"unbuild",value:function unbuild(){if(!this.ready){return;}
this.ready=false;this.unbind();this.resetPreview();this.cropper.parentNode.removeChild(this.cropper);removeClass(this.element,CLASS_HIDDEN);}},{key:"uncreate",value:function uncreate(){if(this.ready){this.unbuild();this.ready=false;this.cropped=false;}else if(this.sizing){this.sizingImage.onload=null;this.sizing=false;this.sized=false;}else if(this.reloading){this.xhr.onabort=null;this.xhr.abort();}else if(this.image){this.stop();}}}],[{key:"noConflict",value:function noConflict(){window.Cropper=AnotherCropper;return Cropper;}},{key:"setDefaults",value:function setDefaults(options){assign(DEFAULTS,isPlainObject(options)&&options);}}]);return Cropper;}();assign(Cropper.prototype,render,preview,events,handlers,change,methods);return Cropper;}));;

/* /web_editor/static/lib/jquery-cropper/jquery-cropper.js */
(function(global,factory){typeof exports==='object'&&typeof module!=='undefined'?factory(require('jquery'),require('cropperjs')):typeof define==='function'&&define.amd?define(['jquery','cropperjs'],factory):(factory(global.jQuery,global.Cropper));}(this,(function($,Cropper){'use strict';$=$&&$.hasOwnProperty('default')?$['default']:$;Cropper=Cropper&&Cropper.hasOwnProperty('default')?Cropper['default']:Cropper;if($.fn){var AnotherCropper=$.fn.cropper;var NAMESPACE='cropper';$.fn.cropper=function jQueryCropper(option){for(var _len=arguments.length,args=Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}
var result=void 0;this.each(function(i,element){var $element=$(element);var isDestroy=option==='destroy';var cropper=$element.data(NAMESPACE);if(!cropper){if(isDestroy){return;}
var options=$.extend({},$element.data(),$.isPlainObject(option)&&option);cropper=new Cropper(element,options);$element.data(NAMESPACE,cropper);}
if(typeof option==='string'){var fn=cropper[option];if($.isFunction(fn)){result=fn.apply(cropper,args);if(result===cropper){result=undefined;}
if(isDestroy){$element.removeData(NAMESPACE);}}}});return result!==undefined?result:this;};$.fn.cropper.Constructor=Cropper;$.fn.cropper.setDefaults=Cropper.setDefaults;$.fn.cropper.noConflict=function noConflict(){$.fn.cropper=AnotherCropper;return this;};}})));;

/* /web_editor/static/lib/jQuery.transfo.js */
(function($){'use strict';var rad=Math.PI/180;var methods={init:function(settings){return this.each(function(){var $this=$(this),transfo=$this.data('transfo');if(!transfo){_init($this,settings);}else{_overwriteOptions($this,transfo,settings);_targetCss($this,transfo);}});},destroy:function(){return this.each(function(){var $this=$(this);if($this.data('transfo')){_destroy($this);}});},reset:function(){return this.each(function(){var $this=$(this);if($this.data('transfo')){_reset($this);}});},toggle:function(){return this.each(function(){var $this=$(this);var transfo=$this.data('transfo');if(transfo){transfo.settings.hide=!transfo.settings.hide;_showHide($this,transfo);}});},hide:function(){return this.each(function(){var $this=$(this);var transfo=$this.data('transfo');if(transfo){transfo.settings.hide=true;_showHide($this,transfo);}});},show:function(){return this.each(function(){var $this=$(this);var transfo=$this.data('transfo');if(transfo){transfo.settings.hide=false;_showHide($this,transfo);}});},settings:function(){if(this.length>1){this.map(function(){var $this=$(this);return $this.data('transfo')&&$this.data('transfo').settings;});}
return this.data('transfo')&&$this.data('transfo').settings;},center:function(){if(this.length>1){this.map(function(){var $this=$(this);return $this.data('transfo')&&$this.data('transfo').$center.offset();});}
return this.data('transfo')&&this.data('transfo').$center.offset();}};$.fn.transfo=function(method){if(methods[method]){return methods[method].apply(this,Array.prototype.slice.call(arguments,1));}else if(typeof method==='object'||!method){return methods.init.apply(this,arguments);}else{$.error('Method '+method+' does not exist on jQuery.transfo');}
return false;};function _init($this,settings){var transfo={};$this.data('transfo',transfo);transfo.settings=settings;transfo.settings.document=transfo.settings.document||document;var css="box-sizing: border-box; position: absolute; background-color: #fff; border: 1px solid #ccc; width: 8px; height: 8px; margin-left: -4px; margin-top: -4px;";transfo.$markup=$(''
+'<div class="transfo-container">'
+'<div class="transfo-controls">'
+'<div style="cursor: crosshair; position: absolute; margin: -30px; top: 0; right: 0; padding: 1px 0 0 1px;" class="transfo-rotator">'
+'<span class="fa-stack fa-lg">'
+'<i class="fa fa-circle fa-stack-2x"></i>'
+'<i class="fa fa-repeat fa-stack-1x fa-inverse"></i>'
+'</span>'
+'</div>'
+'<div style="'+css+'top: 0%; left: 0%; cursor: nw-resize;" class="transfo-scaler-tl"></div>'
+'<div style="'+css+'top: 0%; left: 100%; cursor: ne-resize;" class="transfo-scaler-tr"></div>'
+'<div style="'+css+'top: 100%; left: 100%; cursor: se-resize;" class="transfo-scaler-br"></div>'
+'<div style="'+css+'top: 100%; left: 0%; cursor: sw-resize;" class="transfo-scaler-bl"></div>'
+'<div style="'+css+'top: 0%; left: 50%; cursor: n-resize;" class="transfo-scaler-tc"></div>'
+'<div style="'+css+'top: 100%; left: 50%; cursor: s-resize;" class="transfo-scaler-bc"></div>'
+'<div style="'+css+'top: 50%; left: 0%; cursor: w-resize;" class="transfo-scaler-ml"></div>'
+'<div style="'+css+'top: 50%; left: 100%; cursor: e-resize;" class="transfo-scaler-mr"></div>'
+'<div style="'+css+'border: 0; width: 0px; height: 0px; top: 50%; left: 50%;" class="transfo-scaler-mc"></div>'
+'</div>'
+'</div>');transfo.$center=transfo.$markup.find(".transfo-scaler-mc");_setOptions($this,transfo);_overwriteOptions($this,transfo,settings);$(transfo.settings.document.body).append(transfo.$markup);setTimeout(function(){_targetCss($this,transfo);},0);_bind($this,transfo);_targetCss($this,transfo);_stop_animation($this[0]);}
function _overwriteOptions($this,transfo,settings){transfo.settings=$.extend(transfo.settings,settings||{});}
function _stop_animation(target){target.style.webkitAnimationPlayState="paused";target.style.animationPlayState="paused";target.style.webkitTransition="none";target.style.transition="none";}
function _setOptions($this,transfo){var style=$this.attr("style")||"";var transform=style.match(/transform\s*:([^;]+)/)?style.match(/transform\s*:([^;]+)/)[1]:"";transfo.settings={};transfo.settings.angle=transform.indexOf('rotate')!=-1?parseFloat(transform.match(/rotate\(([^)]+)deg\)/)[1]):0;transfo.settings.scalex=transform.indexOf('scaleX')!=-1?parseFloat(transform.match(/scaleX\(([^)]+)\)/)[1]):1;transfo.settings.scaley=transform.indexOf('scaleY')!=-1?parseFloat(transform.match(/scaleY\(([^)]+)\)/)[1]):1;transfo.settings.style=style.replace(/[^;]*transform[^;]+/g,'').replace(/;+/g,';');$this.attr("style",transfo.settings.style);_stop_animation($this[0]);transfo.settings.pos=$this.offset();transfo.settings.height=$this.innerHeight();transfo.settings.width=$this.innerWidth();var translatex=transform.match(/translateX\(([0-9.-]+)(%|px)\)/);var translatey=transform.match(/translateY\(([0-9.-]+)(%|px)\)/);transfo.settings.translate="%";if(translatex&&translatex[2]==="%"){transfo.settings.translatexp=parseFloat(translatex[1]);transfo.settings.translatex=transfo.settings.translatexp/100*transfo.settings.width;}else{transfo.settings.translatex=translatex?parseFloat(translatex[1]):0;}
if(translatey&&translatey[2]==="%"){transfo.settings.translateyp=parseFloat(translatey[1]);transfo.settings.translatey=transfo.settings.translateyp/100*transfo.settings.height;}else{transfo.settings.translatey=translatey?parseFloat(translatey[1]):0;}
transfo.settings.css=window.getComputedStyle($this[0],null);transfo.settings.rotationStep=5;transfo.settings.hide=false;transfo.settings.callback=function(){};}
function _bind($this,transfo){function mousedown(event){_mouseDown($this,this,transfo,event);$(transfo.settings.document).on("mousemove",mousemove).on("mouseup",mouseup);}
function mousemove(event){_mouseMove($this,this,transfo,event);}
function mouseup(event){_mouseUp($this,this,transfo,event);$(transfo.settings.document).off("mousemove",mousemove).off("mouseup",mouseup);}
transfo.$markup.off().on("mousedown",mousedown);transfo.$markup.find(".transfo-controls >:not(.transfo-scaler-mc)").off().on("mousedown",mousedown);}
function _mouseDown($this,div,transfo,event){event.preventDefault();if(transfo.active||event.which!==1)return;var type="position",$e=$(div);if($e.hasClass("transfo-rotator"))type="rotator";else if($e.hasClass("transfo-scaler-tl"))type="tl";else if($e.hasClass("transfo-scaler-tr"))type="tr";else if($e.hasClass("transfo-scaler-br"))type="br";else if($e.hasClass("transfo-scaler-bl"))type="bl";else if($e.hasClass("transfo-scaler-tc"))type="tc";else if($e.hasClass("transfo-scaler-bc"))type="bc";else if($e.hasClass("transfo-scaler-ml"))type="ml";else if($e.hasClass("transfo-scaler-mr"))type="mr";transfo.active={"type":type,"scalex":transfo.settings.scalex,"scaley":transfo.settings.scaley,"pageX":event.pageX,"pageY":event.pageY,"center":transfo.$center.offset(),};}
function _mouseUp($this,div,transfo,event){transfo.active=null;}
function _mouseMove($this,div,transfo,event){event.preventDefault();if(!transfo.active)return;var settings=transfo.settings;var center=transfo.active.center;var cdx=center.left-event.pageX;var cdy=center.top-event.pageY;if(transfo.active.type=="rotator"){var ang,dang=Math.atan((settings.width*settings.scalex)/(settings.height*settings.scaley))/rad;if(cdy)ang=Math.atan(-cdx/cdy)/rad;else ang=0;if(event.pageY>=center.top&&event.pageX>=center.left)ang+=180;else if(event.pageY>=center.top&&event.pageX<center.left)ang+=180;else if(event.pageY<center.top&&event.pageX<center.left)ang+=360;ang-=dang;if(settings.scaley<0&&settings.scalex<0)ang+=180;if(!event.ctrlKey){settings.angle=Math.round(ang/transfo.settings.rotationStep)*transfo.settings.rotationStep;}else{settings.angle=ang;}
_targetCss($this,transfo);var new_center=transfo.$center.offset();var x=center.left-new_center.left;var y=center.top-new_center.top;var angle=ang*rad;settings.translatex+=x*Math.cos(angle)-y*Math.sin(-angle);settings.translatey+=-x*Math.sin(angle)+y*Math.cos(-angle);}
else if(transfo.active.type=="position"){var angle=settings.angle*rad;var x=event.pageX-transfo.active.pageX;var y=event.pageY-transfo.active.pageY;transfo.active.pageX=event.pageX;transfo.active.pageY=event.pageY;var dx=x*Math.cos(angle)-y*Math.sin(-angle);var dy=-x*Math.sin(angle)+y*Math.cos(-angle);settings.translatex+=dx;settings.translatey+=dy;}
else if(transfo.active.type.length===2){var angle=settings.angle*rad;var dx=cdx*Math.cos(angle)-cdy*Math.sin(-angle);var dy=-cdx*Math.sin(angle)+cdy*Math.cos(-angle);if(transfo.active.type.indexOf("t")!=-1){settings.scaley=dy/(settings.height/2);}
if(transfo.active.type.indexOf("b")!=-1){settings.scaley=-dy/(settings.height/2);}
if(transfo.active.type.indexOf("l")!=-1){settings.scalex=dx/(settings.width/2);}
if(transfo.active.type.indexOf("r")!=-1){settings.scalex=-dx/(settings.width/2);}
if(settings.scaley>0&&settings.scaley<0.05)settings.scaley=0.05;if(settings.scalex>0&&settings.scalex<0.05)settings.scalex=0.05;if(settings.scaley<0&&settings.scaley>-0.05)settings.scaley=-0.05;if(settings.scalex<0&&settings.scalex>-0.05)settings.scalex=-0.05;if(event.shiftKey&&(transfo.active.type==="tl"||transfo.active.type==="bl"||transfo.active.type==="tr"||transfo.active.type==="br")){settings.scaley=settings.scalex;}}
settings.angle=Math.round(settings.angle);settings.translatex=Math.round(settings.translatex);settings.translatey=Math.round(settings.translatey);settings.scalex=Math.round(settings.scalex*100)/100;settings.scaley=Math.round(settings.scaley*100)/100;_targetCss($this,transfo);_stop_animation($this[0]);return false;}
function _setCss($this,css,settings){var transform="";var trans=false;if(settings.angle!==0){trans=true;transform+=" rotate("+settings.angle+"deg) ";}
if(settings.translatex){trans=true;transform+=" translateX("+(settings.translate==="%"?settings.translatexp+"%":settings.translatex+"px")+") ";}
if(settings.translatey){trans=true;transform+=" translateY("+(settings.translate==="%"?settings.translateyp+"%":settings.translatey+"px")+") ";}
if(settings.scalex!=1){trans=true;transform+=" scaleX("+settings.scalex+") ";}
if(settings.scaley!=1){trans=true;transform+=" scaleY("+settings.scaley+") ";}
if(trans){css+=";"
css+="-webkit-transform:"+transform+";"
+"-moz-transform:"+transform+";"
+"-ms-transform:"+transform+";"
+"-o-transform:"+transform+";"
+"transform:"+transform+";";}
css=css.replace(/(\s*;)+/g,';').replace(/^\s*;|;\s*$/g,'');$this.attr("style",css);}
function _targetCss($this,transfo){var settings=transfo.settings;var width=parseFloat(settings.css.width);var height=parseFloat(settings.css.height);settings.translatexp=Math.round(settings.translatex/width*1000)/10;settings.translateyp=Math.round(settings.translatey/height*1000)/10;_setCss($this,settings.style,settings);transfo.$markup.css({"position":"absolute","width":width+"px","height":height+"px","top":settings.pos.top+"px","left":settings.pos.left+"px"});var $controls=transfo.$markup.find('.transfo-controls');_setCss($controls,"width:"+width+"px;"+"height:"+height+"px;"+"cursor: move;",settings);$controls.children().css("transform","scaleX("+(1/settings.scalex)+") scaleY("+(1/settings.scaley)+")");_showHide($this,transfo);transfo.settings.callback.call($this[0],$this);}
function _showHide($this,transfo){transfo.$markup.css("z-index",transfo.settings.hide?-1:1000);if(transfo.settings.hide){transfo.$markup.find(".transfo-controls > *").hide();transfo.$markup.find(".transfo-scaler-mc").show();}else{transfo.$markup.find(".transfo-controls > *").show();}}
function _destroy($this){$this.data('transfo').$markup.remove();$this.removeData('transfo');}
function _reset($this){var transfo=$this.data('transfo');_destroy($this);$this.transfo(transfo.settings);}})(jQuery);;

/* /web_editor/static/lib/webgl-image-filter/webgl-image-filter.js */
(function(window){var WebGLProgram=function(gl,vertexSource,fragmentSource){var _collect=function(source,prefix,collection){var r=new RegExp('\\b'+prefix+' \\w+ (\\w+)','ig');source.replace(r,function(match,name){collection[name]=0;return match;});};var _compile=function(gl,source,type){var shader=gl.createShader(type);gl.shaderSource(shader,source);gl.compileShader(shader);if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){console.log(gl.getShaderInfoLog(shader));return null;}
return shader;};this.uniform={};this.attribute={};var _vsh=_compile(gl,vertexSource,gl.VERTEX_SHADER);var _fsh=_compile(gl,fragmentSource,gl.FRAGMENT_SHADER);this.id=gl.createProgram();gl.attachShader(this.id,_vsh);gl.attachShader(this.id,_fsh);gl.linkProgram(this.id);if(!gl.getProgramParameter(this.id,gl.LINK_STATUS)){console.log(gl.getProgramInfoLog(this.id));}
gl.useProgram(this.id);_collect(vertexSource,'attribute',this.attribute);for(var a in this.attribute){this.attribute[a]=gl.getAttribLocation(this.id,a);}
_collect(vertexSource,'uniform',this.uniform);_collect(fragmentSource,'uniform',this.uniform);for(var u in this.uniform){this.uniform[u]=gl.getUniformLocation(this.id,u);}};const identityMatrix=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,];const weightedAvg=(a,b,w)=>a*w+b*(1-w);var WebGLImageFilter=window.WebGLImageFilter=function(params){if(!params)
params={};var
gl=null,_drawCount=0,_sourceTexture=null,_lastInChain=false,_currentFramebufferIndex=-1,_tempFramebuffers=[null,null],_filterChain=[],_width=-1,_height=-1,_vertexBuffer=null,_currentProgram=null,_canvas=params.canvas||document.createElement('canvas');var _shaderProgramCache={};var gl=_canvas.getContext("webgl")||_canvas.getContext("experimental-webgl");if(!gl){throw"Couldn't get WebGL context";}
this.addFilter=function(name){var args=Array.prototype.slice.call(arguments,1);var filter=_filter[name];_filterChain.push({func:filter,args:args});};this.reset=function(){_filterChain=[];};this.apply=function(image){_resize(image.width,image.height);_drawCount=0;if(!_sourceTexture)
_sourceTexture=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,_sourceTexture);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,image);if(_filterChain.length==0){var program=_compileShader(SHADER.FRAGMENT_IDENTITY);_draw();return _canvas;}
for(var i=0;i<_filterChain.length;i++){_lastInChain=(i==_filterChain.length-1);var f=_filterChain[i];f.func.apply(this,f.args||[]);}
return _canvas;};var _resize=function(width,height){if(width==_width&&height==_height){return;}
_canvas.width=_width=width;_canvas.height=_height=height;if(!_vertexBuffer){var vertices=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,-1,1,0,0,1,-1,1,1,1,1,1,0]);_vertexBuffer=gl.createBuffer(),gl.bindBuffer(gl.ARRAY_BUFFER,_vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,true);}
gl.viewport(0,0,_width,_height);_tempFramebuffers=[null,null];};var _getTempFramebuffer=function(index){_tempFramebuffers[index]=_tempFramebuffers[index]||_createFramebufferTexture(_width,_height);return _tempFramebuffers[index];};var _createFramebufferTexture=function(width,height){var fbo=gl.createFramebuffer();gl.bindFramebuffer(gl.FRAMEBUFFER,fbo);var renderbuffer=gl.createRenderbuffer();gl.bindRenderbuffer(gl.RENDERBUFFER,renderbuffer);var texture=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,texture);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,width,height,0,gl.RGBA,gl.UNSIGNED_BYTE,null);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.framebufferTexture2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,texture,0);gl.bindTexture(gl.TEXTURE_2D,null);gl.bindFramebuffer(gl.FRAMEBUFFER,null);return{fbo:fbo,texture:texture};};var _draw=function(flags){var source=null,target=null,flipY=false;if(_drawCount==0){source=_sourceTexture;}
else{source=_getTempFramebuffer(_currentFramebufferIndex).texture;}
_drawCount++;if(_lastInChain&&!(flags&DRAW.INTERMEDIATE)){target=null;flipY=_drawCount%2==0;}
else{_currentFramebufferIndex=(_currentFramebufferIndex+1)%2;target=_getTempFramebuffer(_currentFramebufferIndex).fbo;}
gl.bindTexture(gl.TEXTURE_2D,source);gl.bindFramebuffer(gl.FRAMEBUFFER,target);gl.uniform1f(_currentProgram.uniform.flipY,(flipY?-1:1));gl.drawArrays(gl.TRIANGLES,0,6);};var _compileShader=function(fragmentSource){if(_shaderProgramCache[fragmentSource]){_currentProgram=_shaderProgramCache[fragmentSource];gl.useProgram(_currentProgram.id);return _currentProgram;}
_currentProgram=new WebGLProgram(gl,SHADER.VERTEX_IDENTITY,fragmentSource);var floatSize=Float32Array.BYTES_PER_ELEMENT;var vertSize=4*floatSize;gl.enableVertexAttribArray(_currentProgram.attribute.pos);gl.vertexAttribPointer(_currentProgram.attribute.pos,2,gl.FLOAT,false,vertSize,0*floatSize);gl.enableVertexAttribArray(_currentProgram.attribute.uv);gl.vertexAttribPointer(_currentProgram.attribute.uv,2,gl.FLOAT,false,vertSize,2*floatSize);_shaderProgramCache[fragmentSource]=_currentProgram;return _currentProgram;};var DRAW={INTERMEDIATE:1};var SHADER={};SHADER.VERTEX_IDENTITY=['precision highp float;','attribute vec2 pos;','attribute vec2 uv;','varying vec2 vUv;','uniform float flipY;','void main(void) {','vUv = uv;','gl_Position = vec4(pos.x, pos.y*flipY, 0.0, 1.);','}'].join('\n');SHADER.FRAGMENT_IDENTITY=['precision highp float;','varying vec2 vUv;','uniform sampler2D texture;','void main(void) {','gl_FragColor = texture2D(texture, vUv);','}',].join('\n');var _filter={};_filter.colorMatrix=function(matrix,amount=1){matrix=matrix.map((coef,index)=>weightedAvg(coef,identityMatrix[index],amount));var m=new Float32Array(matrix);m[4]/=255;m[9]/=255;m[14]/=255;m[19]/=255;var shader=(1==m[18]&&0==m[3]&&0==m[8]&&0==m[13]&&0==m[15]&&0==m[16]&&0==m[17]&&0==m[19])?_filter.colorMatrix.SHADER.WITHOUT_ALPHA:_filter.colorMatrix.SHADER.WITH_ALPHA;var program=_compileShader(shader);gl.uniform1fv(program.uniform.m,m);_draw();};_filter.colorMatrix.SHADER={};_filter.colorMatrix.SHADER.WITH_ALPHA=['precision highp float;','varying vec2 vUv;','uniform sampler2D texture;','uniform float m[20];','void main(void) {','vec4 c = texture2D(texture, vUv);','gl_FragColor.r = m[0] * c.r + m[1] * c.g + m[2] * c.b + m[3] * c.a + m[4];','gl_FragColor.g = m[5] * c.r + m[6] * c.g + m[7] * c.b + m[8] * c.a + m[9];','gl_FragColor.b = m[10] * c.r + m[11] * c.g + m[12] * c.b + m[13] * c.a + m[14];','gl_FragColor.a = m[15] * c.r + m[16] * c.g + m[17] * c.b + m[18] * c.a + m[19];','}',].join('\n');_filter.colorMatrix.SHADER.WITHOUT_ALPHA=['precision highp float;','varying vec2 vUv;','uniform sampler2D texture;','uniform float m[20];','void main(void) {','vec4 c = texture2D(texture, vUv);','gl_FragColor.r = m[0] * c.r + m[1] * c.g + m[2] * c.b + m[4];','gl_FragColor.g = m[5] * c.r + m[6] * c.g + m[7] * c.b + m[9];','gl_FragColor.b = m[10] * c.r + m[11] * c.g + m[12] * c.b + m[14];','gl_FragColor.a = c.a;','}',].join('\n');_filter.brightness=function(brightness){var b=(brightness||0)+1;_filter.colorMatrix([b,0,0,0,0,0,b,0,0,0,0,0,b,0,0,0,0,0,1,0]);};_filter.saturation=function(amount){var x=(amount||0)*2/3+1;var y=((x-1)*-0.5);_filter.colorMatrix([x,y,y,0,0,y,x,y,0,0,y,y,x,0,0,0,0,0,1,0]);};_filter.desaturate=function(){_filter.saturation(-1);};_filter.contrast=function(amount){var v=(amount||0)+1;var o=-128*(v-1);_filter.colorMatrix([v,0,0,0,o,0,v,0,0,o,0,0,v,0,o,0,0,0,1,0]);};_filter.negative=function(){_filter.contrast(-2);};_filter.hue=function(rotation){rotation=(rotation||0)/180*Math.PI;var cos=Math.cos(rotation),sin=Math.sin(rotation),lumR=0.213,lumG=0.715,lumB=0.072;_filter.colorMatrix([lumR+cos*(1-lumR)+sin*(-lumR),lumG+cos*(-lumG)+sin*(-lumG),lumB+cos*(-lumB)+sin*(1-lumB),0,0,lumR+cos*(-lumR)+sin*(0.143),lumG+cos*(1-lumG)+sin*(0.140),lumB+cos*(-lumB)+sin*(-0.283),0,0,lumR+cos*(-lumR)+sin*(-(1-lumR)),lumG+cos*(-lumG)+sin*(lumG),lumB+cos*(1-lumB)+sin*(lumB),0,0,0,0,0,1,0]);};_filter.desaturateLuminance=function(amount){_filter.colorMatrix([0.2764723,0.9297080,0.0938197,0,-37.1,0.2764723,0.9297080,0.0938197,0,-37.1,0.2764723,0.9297080,0.0938197,0,-37.1,0,0,0,1,0],amount);};_filter.sepia=function(amount){_filter.colorMatrix([0.393,0.7689999,0.18899999,0,0,0.349,0.6859999,0.16799999,0,0,0.272,0.5339999,0.13099999,0,0,0,0,0,1,0],amount);};_filter.brownie=function(amount){_filter.colorMatrix([0.5997023498159715,0.34553243048391263,-0.2708298674538042,0,47.43192855600873,-0.037703249837783157,0.8609577587992641,0.15059552388459913,0,-36.96841498319127,0.24113635128153335,-0.07441037908422492,0.44972182064877153,0,-7.562075277591283,0,0,0,1,0],amount);};_filter.vintagePinhole=function(amount){_filter.colorMatrix([0.6279345635605994,0.3202183420819367,-0.03965408211312453,0,9.651285835294123,0.02578397704808868,0.6441188644374771,0.03259127616149294,0,7.462829176470591,0.0466055556782719,-0.0851232987247891,0.5241648018700465,0,5.159190588235296,0,0,0,1,0],amount);};_filter.kodachrome=function(amount){_filter.colorMatrix([1.1285582396593525,-0.3967382283601348,-0.03992559172921793,0,63.72958762196502,-0.16404339962244616,1.0835251566291304,-0.05498805115633132,0,24.732407896706203,-0.16786010706155763,-0.5603416277695248,1.6014850761964943,0,35.62982807460946,0,0,0,1,0],amount);};_filter.technicolor=function(amount){_filter.colorMatrix([1.9125277891456083,-0.8545344976951645,-0.09155508482755585,0,11.793603434377337,-0.3087833385928097,1.7658908555458428,-0.10601743074722245,0,-70.35205161461398,-0.231103377548616,-0.7501899197440212,1.847597816108189,0,30.950940869491138,0,0,0,1,0],amount);};_filter.polaroid=function(amount){_filter.colorMatrix([1.438,-0.062,-0.062,0,0,-0.122,1.378,-0.122,0,0,-0.016,-0.016,1.483,0,0,0,0,0,1,0],amount);};_filter.shiftToBGR=function(amount){_filter.colorMatrix([0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0],amount);};_filter.convolution=function(matrix){var m=new Float32Array(matrix);var pixelSizeX=1/_width;var pixelSizeY=1/_height;var program=_compileShader(_filter.convolution.SHADER);gl.uniform1fv(program.uniform.m,m);gl.uniform2f(program.uniform.px,pixelSizeX,pixelSizeY);_draw();};_filter.convolution.SHADER=['precision highp float;','varying vec2 vUv;','uniform sampler2D texture;','uniform vec2 px;','uniform float m[9];','void main(void) {','vec4 c11 = texture2D(texture, vUv - px);','vec4 c12 = texture2D(texture, vec2(vUv.x, vUv.y - px.y));','vec4 c13 = texture2D(texture, vec2(vUv.x + px.x, vUv.y - px.y));','vec4 c21 = texture2D(texture, vec2(vUv.x - px.x, vUv.y) );','vec4 c22 = texture2D(texture, vUv);','vec4 c23 = texture2D(texture, vec2(vUv.x + px.x, vUv.y) );','vec4 c31 = texture2D(texture, vec2(vUv.x - px.x, vUv.y + px.y) );','vec4 c32 = texture2D(texture, vec2(vUv.x, vUv.y + px.y) );','vec4 c33 = texture2D(texture, vUv + px );','gl_FragColor = ','c11 * m[0] + c12 * m[1] + c22 * m[2] +','c21 * m[3] + c22 * m[4] + c23 * m[5] +','c31 * m[6] + c32 * m[7] + c33 * m[8];','gl_FragColor.a = c22.a;','}',].join('\n');_filter.detectEdges=function(){_filter.convolution.call(this,[0,1,0,1,-4,1,0,1,0]);};_filter.sobelX=function(){_filter.convolution.call(this,[-1,0,1,-2,0,2,-1,0,1]);};_filter.sobelY=function(){_filter.convolution.call(this,[-1,-2,-1,0,0,0,1,2,1]);};_filter.sharpen=function(amount){var a=amount||1;_filter.convolution.call(this,[0,-1*a,0,-1*a,1+4*a,-1*a,0,-1*a,0]);};_filter.emboss=function(size){var s=size||1;_filter.convolution.call(this,[-2*s,-1*s,0,-1*s,1,1*s,0,1*s,2*s]);};_filter.blur=function(size){var blurSizeX=(size/7)/_width;var blurSizeY=(size/7)/_height;var program=_compileShader(_filter.blur.SHADER);gl.uniform2f(program.uniform.px,0,blurSizeY);_draw(DRAW.INTERMEDIATE);gl.uniform2f(program.uniform.px,blurSizeX,0);_draw();};_filter.blur.SHADER=['precision highp float;','varying vec2 vUv;','uniform sampler2D texture;','uniform vec2 px;','void main(void) {','gl_FragColor = vec4(0.0);','gl_FragColor += texture2D(texture, vUv + vec2(-7.0*px.x, -7.0*px.y))*0.0044299121055113265;','gl_FragColor += texture2D(texture, vUv + vec2(-6.0*px.x, -6.0*px.y))*0.00895781211794;','gl_FragColor += texture2D(texture, vUv + vec2(-5.0*px.x, -5.0*px.y))*0.0215963866053;','gl_FragColor += texture2D(texture, vUv + vec2(-4.0*px.x, -4.0*px.y))*0.0443683338718;','gl_FragColor += texture2D(texture, vUv + vec2(-3.0*px.x, -3.0*px.y))*0.0776744219933;','gl_FragColor += texture2D(texture, vUv + vec2(-2.0*px.x, -2.0*px.y))*0.115876621105;','gl_FragColor += texture2D(texture, vUv + vec2(-1.0*px.x, -1.0*px.y))*0.147308056121;','gl_FragColor += texture2D(texture, vUv                             )*0.159576912161;','gl_FragColor += texture2D(texture, vUv + vec2( 1.0*px.x,  1.0*px.y))*0.147308056121;','gl_FragColor += texture2D(texture, vUv + vec2( 2.0*px.x,  2.0*px.y))*0.115876621105;','gl_FragColor += texture2D(texture, vUv + vec2( 3.0*px.x,  3.0*px.y))*0.0776744219933;','gl_FragColor += texture2D(texture, vUv + vec2( 4.0*px.x,  4.0*px.y))*0.0443683338718;','gl_FragColor += texture2D(texture, vUv + vec2( 5.0*px.x,  5.0*px.y))*0.0215963866053;','gl_FragColor += texture2D(texture, vUv + vec2( 6.0*px.x,  6.0*px.y))*0.00895781211794;','gl_FragColor += texture2D(texture, vUv + vec2( 7.0*px.x,  7.0*px.y))*0.0044299121055113265;','}',].join('\n');_filter.pixelate=function(size){var blurSizeX=(size)/_width;var blurSizeY=(size)/_height;var program=_compileShader(_filter.pixelate.SHADER);gl.uniform2f(program.uniform.size,blurSizeX,blurSizeY);_draw();};_filter.pixelate.SHADER=['precision highp float;','varying vec2 vUv;','uniform vec2 size;','uniform sampler2D texture;','vec2 pixelate(vec2 coord, vec2 size) {','return floor( coord / size ) * size;','}','void main(void) {','gl_FragColor = vec4(0.0);','vec2 coord = pixelate(vUv, size);','gl_FragColor += texture2D(texture, coord);','}',].join('\n');};})(window);;

/* /web/static/lib/dompurify/DOMpurify.js */
(function(global,factory){typeof exports==='object'&&typeof module!=='undefined'?module.exports=factory():typeof define==='function'&&define.amd?define(factory):(global=typeof globalThis!=='undefined'?globalThis:global||self,global.DOMPurify=factory());})(this,(function(){'use strict';const{entries,setPrototypeOf,isFrozen,getPrototypeOf,getOwnPropertyDescriptor}=Object;let{freeze,seal,create}=Object;let{apply,construct}=typeof Reflect!=='undefined'&&Reflect;if(!freeze){freeze=function freeze(x){return x;};}
if(!seal){seal=function seal(x){return x;};}
if(!apply){apply=function apply(fun,thisValue,args){return fun.apply(thisValue,args);};}
if(!construct){construct=function construct(Func,args){return new Func(...args);};}
const arrayForEach=unapply(Array.prototype.forEach);const arrayPop=unapply(Array.prototype.pop);const arrayPush=unapply(Array.prototype.push);const stringToLowerCase=unapply(String.prototype.toLowerCase);const stringToString=unapply(String.prototype.toString);const stringMatch=unapply(String.prototype.match);const stringReplace=unapply(String.prototype.replace);const stringIndexOf=unapply(String.prototype.indexOf);const stringTrim=unapply(String.prototype.trim);const objectHasOwnProperty=unapply(Object.prototype.hasOwnProperty);const regExpTest=unapply(RegExp.prototype.test);const typeErrorCreate=unconstruct(TypeError);function unapply(func){return function(thisArg){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}
return apply(func,thisArg,args);};}
function unconstruct(func){return function(){for(var _len2=arguments.length,args=new Array(_len2),_key2=0;_key2<_len2;_key2++){args[_key2]=arguments[_key2];}
return construct(func,args);};}
function addToSet(set,array){let transformCaseFunc=arguments.length>2&&arguments[2]!==undefined?arguments[2]:stringToLowerCase;if(setPrototypeOf){setPrototypeOf(set,null);}
let l=array.length;while(l--){let element=array[l];if(typeof element==='string'){const lcElement=transformCaseFunc(element);if(lcElement!==element){if(!isFrozen(array)){array[l]=lcElement;}
element=lcElement;}}
set[element]=true;}
return set;}
function cleanArray(array){for(let index=0;index<array.length;index++){const isPropertyExist=objectHasOwnProperty(array,index);if(!isPropertyExist){array[index]=null;}}
return array;}
function clone(object){const newObject=create(null);for(const[property,value]of entries(object)){const isPropertyExist=objectHasOwnProperty(object,property);if(isPropertyExist){if(Array.isArray(value)){newObject[property]=cleanArray(value);}else if(value&&typeof value==='object'&&value.constructor===Object){newObject[property]=clone(value);}else{newObject[property]=value;}}}
return newObject;}
function lookupGetter(object,prop){while(object!==null){const desc=getOwnPropertyDescriptor(object,prop);if(desc){if(desc.get){return unapply(desc.get);}
if(typeof desc.value==='function'){return unapply(desc.value);}}
object=getPrototypeOf(object);}
function fallbackValue(){return null;}
return fallbackValue;}
const html$1=freeze(['a','abbr','acronym','address','area','article','aside','audio','b','bdi','bdo','big','blink','blockquote','body','br','button','canvas','caption','center','cite','code','col','colgroup','content','data','datalist','dd','decorator','del','details','dfn','dialog','dir','div','dl','dt','element','em','fieldset','figcaption','figure','font','footer','form','h1','h2','h3','h4','h5','h6','head','header','hgroup','hr','html','i','img','input','ins','kbd','label','legend','li','main','map','mark','marquee','menu','menuitem','meter','nav','nobr','ol','optgroup','option','output','p','picture','pre','progress','q','rp','rt','ruby','s','samp','section','select','shadow','small','source','spacer','span','strike','strong','style','sub','summary','sup','table','tbody','td','template','textarea','tfoot','th','thead','time','tr','track','tt','u','ul','var','video','wbr']);const svg$1=freeze(['svg','a','altglyph','altglyphdef','altglyphitem','animatecolor','animatemotion','animatetransform','circle','clippath','defs','desc','ellipse','filter','font','g','glyph','glyphref','hkern','image','line','lineargradient','marker','mask','metadata','mpath','path','pattern','polygon','polyline','radialgradient','rect','stop','style','switch','symbol','text','textpath','title','tref','tspan','view','vkern']);const svgFilters=freeze(['feBlend','feColorMatrix','feComponentTransfer','feComposite','feConvolveMatrix','feDiffuseLighting','feDisplacementMap','feDistantLight','feDropShadow','feFlood','feFuncA','feFuncB','feFuncG','feFuncR','feGaussianBlur','feImage','feMerge','feMergeNode','feMorphology','feOffset','fePointLight','feSpecularLighting','feSpotLight','feTile','feTurbulence']);const svgDisallowed=freeze(['animate','color-profile','cursor','discard','font-face','font-face-format','font-face-name','font-face-src','font-face-uri','foreignobject','hatch','hatchpath','mesh','meshgradient','meshpatch','meshrow','missing-glyph','script','set','solidcolor','unknown','use']);const mathMl$1=freeze(['math','menclose','merror','mfenced','mfrac','mglyph','mi','mlabeledtr','mmultiscripts','mn','mo','mover','mpadded','mphantom','mroot','mrow','ms','mspace','msqrt','mstyle','msub','msup','msubsup','mtable','mtd','mtext','mtr','munder','munderover','mprescripts']);const mathMlDisallowed=freeze(['maction','maligngroup','malignmark','mlongdiv','mscarries','mscarry','msgroup','mstack','msline','msrow','semantics','annotation','annotation-xml','mprescripts','none']);const text=freeze(['#text']);const html=freeze(['accept','action','align','alt','autocapitalize','autocomplete','autopictureinpicture','autoplay','background','bgcolor','border','capture','cellpadding','cellspacing','checked','cite','class','clear','color','cols','colspan','controls','controlslist','coords','crossorigin','datetime','decoding','default','dir','disabled','disablepictureinpicture','disableremoteplayback','download','draggable','enctype','enterkeyhint','face','for','headers','height','hidden','high','href','hreflang','id','inputmode','integrity','ismap','kind','label','lang','list','loading','loop','low','max','maxlength','media','method','min','minlength','multiple','muted','name','nonce','noshade','novalidate','nowrap','open','optimum','pattern','placeholder','playsinline','popover','popovertarget','popovertargetaction','poster','preload','pubdate','radiogroup','readonly','rel','required','rev','reversed','role','rows','rowspan','spellcheck','scope','selected','shape','size','sizes','span','srclang','start','src','srcset','step','style','summary','tabindex','title','translate','type','usemap','valign','value','width','wrap','xmlns','slot']);const svg=freeze(['accent-height','accumulate','additive','alignment-baseline','ascent','attributename','attributetype','azimuth','basefrequency','baseline-shift','begin','bias','by','class','clip','clippathunits','clip-path','clip-rule','color','color-interpolation','color-interpolation-filters','color-profile','color-rendering','cx','cy','d','dx','dy','diffuseconstant','direction','display','divisor','dur','edgemode','elevation','end','fill','fill-opacity','fill-rule','filter','filterunits','flood-color','flood-opacity','font-family','font-size','font-size-adjust','font-stretch','font-style','font-variant','font-weight','fx','fy','g1','g2','glyph-name','glyphref','gradientunits','gradienttransform','height','href','id','image-rendering','in','in2','k','k1','k2','k3','k4','kerning','keypoints','keysplines','keytimes','lang','lengthadjust','letter-spacing','kernelmatrix','kernelunitlength','lighting-color','local','marker-end','marker-mid','marker-start','markerheight','markerunits','markerwidth','maskcontentunits','maskunits','max','mask','media','method','mode','min','name','numoctaves','offset','operator','opacity','order','orient','orientation','origin','overflow','paint-order','path','pathlength','patterncontentunits','patterntransform','patternunits','points','preservealpha','preserveaspectratio','primitiveunits','r','rx','ry','radius','refx','refy','repeatcount','repeatdur','restart','result','rotate','scale','seed','shape-rendering','specularconstant','specularexponent','spreadmethod','startoffset','stddeviation','stitchtiles','stop-color','stop-opacity','stroke-dasharray','stroke-dashoffset','stroke-linecap','stroke-linejoin','stroke-miterlimit','stroke-opacity','stroke','stroke-width','style','surfacescale','systemlanguage','tabindex','targetx','targety','transform','transform-origin','text-anchor','text-decoration','text-rendering','textlength','type','u1','u2','unicode','values','viewbox','visibility','version','vert-adv-y','vert-origin-x','vert-origin-y','width','word-spacing','wrap','writing-mode','xchannelselector','ychannelselector','x','x1','x2','xmlns','y','y1','y2','z','zoomandpan']);const mathMl=freeze(['accent','accentunder','align','bevelled','close','columnsalign','columnlines','columnspan','denomalign','depth','dir','display','displaystyle','encoding','fence','frame','height','href','id','largeop','length','linethickness','lspace','lquote','mathbackground','mathcolor','mathsize','mathvariant','maxsize','minsize','movablelimits','notation','numalign','open','rowalign','rowlines','rowspacing','rowspan','rspace','rquote','scriptlevel','scriptminsize','scriptsizemultiplier','selection','separator','separators','stretchy','subscriptshift','supscriptshift','symmetric','voffset','width','xmlns']);const xml=freeze(['xlink:href','xml:id','xlink:title','xml:space','xmlns:xlink']);const MUSTACHE_EXPR=seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);const ERB_EXPR=seal(/<%[\w\W]*|[\w\W]*%>/gm);const TMPLIT_EXPR=seal(/\${[\w\W]*}/gm);const DATA_ATTR=seal(/^data-[\-\w.\u00B7-\uFFFF]/);const ARIA_ATTR=seal(/^aria-[\-\w]+$/);const IS_ALLOWED_URI=seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i);const IS_SCRIPT_OR_DATA=seal(/^(?:\w+script|data):/i);const ATTR_WHITESPACE=seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g);const DOCTYPE_NAME=seal(/^html$/i);const CUSTOM_ELEMENT=seal(/^[a-z][.\w]*(-[.\w]+)+$/i);var EXPRESSIONS=Object.freeze({__proto__:null,MUSTACHE_EXPR:MUSTACHE_EXPR,ERB_EXPR:ERB_EXPR,TMPLIT_EXPR:TMPLIT_EXPR,DATA_ATTR:DATA_ATTR,ARIA_ATTR:ARIA_ATTR,IS_ALLOWED_URI:IS_ALLOWED_URI,IS_SCRIPT_OR_DATA:IS_SCRIPT_OR_DATA,ATTR_WHITESPACE:ATTR_WHITESPACE,DOCTYPE_NAME:DOCTYPE_NAME,CUSTOM_ELEMENT:CUSTOM_ELEMENT});const NODE_TYPE={element:1,attribute:2,text:3,cdataSection:4,entityReference:5,entityNode:6,progressingInstruction:7,comment:8,document:9,documentType:10,documentFragment:11,notation:12};const getGlobal=function getGlobal(){return typeof window==='undefined'?null:window;};const _createTrustedTypesPolicy=function _createTrustedTypesPolicy(trustedTypes,purifyHostElement){if(typeof trustedTypes!=='object'||typeof trustedTypes.createPolicy!=='function'){return null;}
let suffix=null;const ATTR_NAME='data-tt-policy-suffix';if(purifyHostElement&&purifyHostElement.hasAttribute(ATTR_NAME)){suffix=purifyHostElement.getAttribute(ATTR_NAME);}
const policyName='dompurify'+(suffix?'#'+suffix:'');try{return trustedTypes.createPolicy(policyName,{createHTML(html){return html;},createScriptURL(scriptUrl){return scriptUrl;}});}catch(_){console.warn('TrustedTypes policy '+policyName+' could not be created.');return null;}};function createDOMPurify(){let window=arguments.length>0&&arguments[0]!==undefined?arguments[0]:getGlobal();const DOMPurify=root=>createDOMPurify(root);DOMPurify.version='3.1.5';DOMPurify.removed=[];if(!window||!window.document||window.document.nodeType!==NODE_TYPE.document){DOMPurify.isSupported=false;return DOMPurify;}
let{document}=window;const originalDocument=document;const currentScript=originalDocument.currentScript;const{DocumentFragment,HTMLTemplateElement,Node,Element,NodeFilter,NamedNodeMap=window.NamedNodeMap||window.MozNamedAttrMap,HTMLFormElement,DOMParser,trustedTypes}=window;const ElementPrototype=Element.prototype;const cloneNode=lookupGetter(ElementPrototype,'cloneNode');const getNextSibling=lookupGetter(ElementPrototype,'nextSibling');const getChildNodes=lookupGetter(ElementPrototype,'childNodes');const getParentNode=lookupGetter(ElementPrototype,'parentNode');if(typeof HTMLTemplateElement==='function'){const template=document.createElement('template');if(template.content&&template.content.ownerDocument){document=template.content.ownerDocument;}}
let trustedTypesPolicy;let emptyHTML='';const{implementation,createNodeIterator,createDocumentFragment,getElementsByTagName}=document;const{importNode}=originalDocument;let hooks={};DOMPurify.isSupported=typeof entries==='function'&&typeof getParentNode==='function'&&implementation&&implementation.createHTMLDocument!==undefined;const{MUSTACHE_EXPR,ERB_EXPR,TMPLIT_EXPR,DATA_ATTR,ARIA_ATTR,IS_SCRIPT_OR_DATA,ATTR_WHITESPACE,CUSTOM_ELEMENT}=EXPRESSIONS;let{IS_ALLOWED_URI:IS_ALLOWED_URI$1}=EXPRESSIONS;let ALLOWED_TAGS=null;const DEFAULT_ALLOWED_TAGS=addToSet({},[...html$1,...svg$1,...svgFilters,...mathMl$1,...text]);let ALLOWED_ATTR=null;const DEFAULT_ALLOWED_ATTR=addToSet({},[...html,...svg,...mathMl,...xml]);let CUSTOM_ELEMENT_HANDLING=Object.seal(create(null,{tagNameCheck:{writable:true,configurable:false,enumerable:true,value:null},attributeNameCheck:{writable:true,configurable:false,enumerable:true,value:null},allowCustomizedBuiltInElements:{writable:true,configurable:false,enumerable:true,value:false}}));let FORBID_TAGS=null;let FORBID_ATTR=null;let ALLOW_ARIA_ATTR=true;let ALLOW_DATA_ATTR=true;let ALLOW_UNKNOWN_PROTOCOLS=false;let ALLOW_SELF_CLOSE_IN_ATTR=true;let SAFE_FOR_TEMPLATES=false;let SAFE_FOR_XML=true;let WHOLE_DOCUMENT=false;let SET_CONFIG=false;let FORCE_BODY=false;let RETURN_DOM=false;let RETURN_DOM_FRAGMENT=false;let RETURN_TRUSTED_TYPE=false;let SANITIZE_DOM=true;let SANITIZE_NAMED_PROPS=false;const SANITIZE_NAMED_PROPS_PREFIX='user-content-';let KEEP_CONTENT=true;let IN_PLACE=false;let USE_PROFILES={};let FORBID_CONTENTS=null;const DEFAULT_FORBID_CONTENTS=addToSet({},['annotation-xml','audio','colgroup','desc','foreignobject','head','iframe','math','mi','mn','mo','ms','mtext','noembed','noframes','noscript','plaintext','script','style','svg','template','thead','title','video','xmp']);let DATA_URI_TAGS=null;const DEFAULT_DATA_URI_TAGS=addToSet({},['audio','video','img','source','image','track']);let URI_SAFE_ATTRIBUTES=null;const DEFAULT_URI_SAFE_ATTRIBUTES=addToSet({},['alt','class','for','id','label','name','pattern','placeholder','role','summary','title','value','style','xmlns']);const MATHML_NAMESPACE='http://www.w3.org/1998/Math/MathML';const SVG_NAMESPACE='http://www.w3.org/2000/svg';const HTML_NAMESPACE='http://www.w3.org/1999/xhtml';let NAMESPACE=HTML_NAMESPACE;let IS_EMPTY_INPUT=false;let ALLOWED_NAMESPACES=null;const DEFAULT_ALLOWED_NAMESPACES=addToSet({},[MATHML_NAMESPACE,SVG_NAMESPACE,HTML_NAMESPACE],stringToString);let PARSER_MEDIA_TYPE=null;const SUPPORTED_PARSER_MEDIA_TYPES=['application/xhtml+xml','text/html'];const DEFAULT_PARSER_MEDIA_TYPE='text/html';let transformCaseFunc=null;let CONFIG=null;const formElement=document.createElement('form');const isRegexOrFunction=function isRegexOrFunction(testValue){return testValue instanceof RegExp||testValue instanceof Function;};const _parseConfig=function _parseConfig(){let cfg=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};if(CONFIG&&CONFIG===cfg){return;}
if(!cfg||typeof cfg!=='object'){cfg={};}
cfg=clone(cfg);PARSER_MEDIA_TYPE=SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE)===-1?DEFAULT_PARSER_MEDIA_TYPE:cfg.PARSER_MEDIA_TYPE;transformCaseFunc=PARSER_MEDIA_TYPE==='application/xhtml+xml'?stringToString:stringToLowerCase;ALLOWED_TAGS=objectHasOwnProperty(cfg,'ALLOWED_TAGS')?addToSet({},cfg.ALLOWED_TAGS,transformCaseFunc):DEFAULT_ALLOWED_TAGS;ALLOWED_ATTR=objectHasOwnProperty(cfg,'ALLOWED_ATTR')?addToSet({},cfg.ALLOWED_ATTR,transformCaseFunc):DEFAULT_ALLOWED_ATTR;ALLOWED_NAMESPACES=objectHasOwnProperty(cfg,'ALLOWED_NAMESPACES')?addToSet({},cfg.ALLOWED_NAMESPACES,stringToString):DEFAULT_ALLOWED_NAMESPACES;URI_SAFE_ATTRIBUTES=objectHasOwnProperty(cfg,'ADD_URI_SAFE_ATTR')?addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES),cfg.ADD_URI_SAFE_ATTR,transformCaseFunc):DEFAULT_URI_SAFE_ATTRIBUTES;DATA_URI_TAGS=objectHasOwnProperty(cfg,'ADD_DATA_URI_TAGS')?addToSet(clone(DEFAULT_DATA_URI_TAGS),cfg.ADD_DATA_URI_TAGS,transformCaseFunc):DEFAULT_DATA_URI_TAGS;FORBID_CONTENTS=objectHasOwnProperty(cfg,'FORBID_CONTENTS')?addToSet({},cfg.FORBID_CONTENTS,transformCaseFunc):DEFAULT_FORBID_CONTENTS;FORBID_TAGS=objectHasOwnProperty(cfg,'FORBID_TAGS')?addToSet({},cfg.FORBID_TAGS,transformCaseFunc):{};FORBID_ATTR=objectHasOwnProperty(cfg,'FORBID_ATTR')?addToSet({},cfg.FORBID_ATTR,transformCaseFunc):{};USE_PROFILES=objectHasOwnProperty(cfg,'USE_PROFILES')?cfg.USE_PROFILES:false;ALLOW_ARIA_ATTR=cfg.ALLOW_ARIA_ATTR!==false;ALLOW_DATA_ATTR=cfg.ALLOW_DATA_ATTR!==false;ALLOW_UNKNOWN_PROTOCOLS=cfg.ALLOW_UNKNOWN_PROTOCOLS||false;ALLOW_SELF_CLOSE_IN_ATTR=cfg.ALLOW_SELF_CLOSE_IN_ATTR!==false;SAFE_FOR_TEMPLATES=cfg.SAFE_FOR_TEMPLATES||false;SAFE_FOR_XML=cfg.SAFE_FOR_XML!==false;WHOLE_DOCUMENT=cfg.WHOLE_DOCUMENT||false;RETURN_DOM=cfg.RETURN_DOM||false;RETURN_DOM_FRAGMENT=cfg.RETURN_DOM_FRAGMENT||false;RETURN_TRUSTED_TYPE=cfg.RETURN_TRUSTED_TYPE||false;FORCE_BODY=cfg.FORCE_BODY||false;SANITIZE_DOM=cfg.SANITIZE_DOM!==false;SANITIZE_NAMED_PROPS=cfg.SANITIZE_NAMED_PROPS||false;KEEP_CONTENT=cfg.KEEP_CONTENT!==false;IN_PLACE=cfg.IN_PLACE||false;IS_ALLOWED_URI$1=cfg.ALLOWED_URI_REGEXP||IS_ALLOWED_URI;NAMESPACE=cfg.NAMESPACE||HTML_NAMESPACE;CUSTOM_ELEMENT_HANDLING=cfg.CUSTOM_ELEMENT_HANDLING||{};if(cfg.CUSTOM_ELEMENT_HANDLING&&isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)){CUSTOM_ELEMENT_HANDLING.tagNameCheck=cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;}
if(cfg.CUSTOM_ELEMENT_HANDLING&&isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)){CUSTOM_ELEMENT_HANDLING.attributeNameCheck=cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;}
if(cfg.CUSTOM_ELEMENT_HANDLING&&typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements==='boolean'){CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements=cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;}
if(SAFE_FOR_TEMPLATES){ALLOW_DATA_ATTR=false;}
if(RETURN_DOM_FRAGMENT){RETURN_DOM=true;}
if(USE_PROFILES){ALLOWED_TAGS=addToSet({},text);ALLOWED_ATTR=[];if(USE_PROFILES.html===true){addToSet(ALLOWED_TAGS,html$1);addToSet(ALLOWED_ATTR,html);}
if(USE_PROFILES.svg===true){addToSet(ALLOWED_TAGS,svg$1);addToSet(ALLOWED_ATTR,svg);addToSet(ALLOWED_ATTR,xml);}
if(USE_PROFILES.svgFilters===true){addToSet(ALLOWED_TAGS,svgFilters);addToSet(ALLOWED_ATTR,svg);addToSet(ALLOWED_ATTR,xml);}
if(USE_PROFILES.mathMl===true){addToSet(ALLOWED_TAGS,mathMl$1);addToSet(ALLOWED_ATTR,mathMl);addToSet(ALLOWED_ATTR,xml);}}
if(cfg.ADD_TAGS){if(ALLOWED_TAGS===DEFAULT_ALLOWED_TAGS){ALLOWED_TAGS=clone(ALLOWED_TAGS);}
addToSet(ALLOWED_TAGS,cfg.ADD_TAGS,transformCaseFunc);}
if(cfg.ADD_ATTR){if(ALLOWED_ATTR===DEFAULT_ALLOWED_ATTR){ALLOWED_ATTR=clone(ALLOWED_ATTR);}
addToSet(ALLOWED_ATTR,cfg.ADD_ATTR,transformCaseFunc);}
if(cfg.ADD_URI_SAFE_ATTR){addToSet(URI_SAFE_ATTRIBUTES,cfg.ADD_URI_SAFE_ATTR,transformCaseFunc);}
if(cfg.FORBID_CONTENTS){if(FORBID_CONTENTS===DEFAULT_FORBID_CONTENTS){FORBID_CONTENTS=clone(FORBID_CONTENTS);}
addToSet(FORBID_CONTENTS,cfg.FORBID_CONTENTS,transformCaseFunc);}
if(KEEP_CONTENT){ALLOWED_TAGS['#text']=true;}
if(WHOLE_DOCUMENT){addToSet(ALLOWED_TAGS,['html','head','body']);}
if(ALLOWED_TAGS.table){addToSet(ALLOWED_TAGS,['tbody']);delete FORBID_TAGS.tbody;}
if(cfg.TRUSTED_TYPES_POLICY){if(typeof cfg.TRUSTED_TYPES_POLICY.createHTML!=='function'){throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');}
if(typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL!=='function'){throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');}
trustedTypesPolicy=cfg.TRUSTED_TYPES_POLICY;emptyHTML=trustedTypesPolicy.createHTML('');}else{if(trustedTypesPolicy===undefined){trustedTypesPolicy=_createTrustedTypesPolicy(trustedTypes,currentScript);}
if(trustedTypesPolicy!==null&&typeof emptyHTML==='string'){emptyHTML=trustedTypesPolicy.createHTML('');}}
if(freeze){freeze(cfg);}
CONFIG=cfg;};const MATHML_TEXT_INTEGRATION_POINTS=addToSet({},['mi','mo','mn','ms','mtext']);const HTML_INTEGRATION_POINTS=addToSet({},['foreignobject','annotation-xml']);const COMMON_SVG_AND_HTML_ELEMENTS=addToSet({},['title','style','font','a','script']);const ALL_SVG_TAGS=addToSet({},[...svg$1,...svgFilters,...svgDisallowed]);const ALL_MATHML_TAGS=addToSet({},[...mathMl$1,...mathMlDisallowed]);const _checkValidNamespace=function _checkValidNamespace(element){let parent=getParentNode(element);if(!parent||!parent.tagName){parent={namespaceURI:NAMESPACE,tagName:'template'};}
const tagName=stringToLowerCase(element.tagName);const parentTagName=stringToLowerCase(parent.tagName);if(!ALLOWED_NAMESPACES[element.namespaceURI]){return false;}
if(element.namespaceURI===SVG_NAMESPACE){if(parent.namespaceURI===HTML_NAMESPACE){return tagName==='svg';}
if(parent.namespaceURI===MATHML_NAMESPACE){return tagName==='svg'&&(parentTagName==='annotation-xml'||MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);}
return Boolean(ALL_SVG_TAGS[tagName]);}
if(element.namespaceURI===MATHML_NAMESPACE){if(parent.namespaceURI===HTML_NAMESPACE){return tagName==='math';}
if(parent.namespaceURI===SVG_NAMESPACE){return tagName==='math'&&HTML_INTEGRATION_POINTS[parentTagName];}
return Boolean(ALL_MATHML_TAGS[tagName]);}
if(element.namespaceURI===HTML_NAMESPACE){if(parent.namespaceURI===SVG_NAMESPACE&&!HTML_INTEGRATION_POINTS[parentTagName]){return false;}
if(parent.namespaceURI===MATHML_NAMESPACE&&!MATHML_TEXT_INTEGRATION_POINTS[parentTagName]){return false;}
return!ALL_MATHML_TAGS[tagName]&&(COMMON_SVG_AND_HTML_ELEMENTS[tagName]||!ALL_SVG_TAGS[tagName]);}
if(PARSER_MEDIA_TYPE==='application/xhtml+xml'&&ALLOWED_NAMESPACES[element.namespaceURI]){return true;}
return false;};const _forceRemove=function _forceRemove(node){arrayPush(DOMPurify.removed,{element:node});try{node.parentNode.removeChild(node);}catch(_){node.remove();}};const _removeAttribute=function _removeAttribute(name,node){try{arrayPush(DOMPurify.removed,{attribute:node.getAttributeNode(name),from:node});}catch(_){arrayPush(DOMPurify.removed,{attribute:null,from:node});}
node.removeAttribute(name);if(name==='is'&&!ALLOWED_ATTR[name]){if(RETURN_DOM||RETURN_DOM_FRAGMENT){try{_forceRemove(node);}catch(_){}}else{try{node.setAttribute(name,'');}catch(_){}}}};const _initDocument=function _initDocument(dirty){let doc=null;let leadingWhitespace=null;if(FORCE_BODY){dirty='<remove></remove>'+dirty;}else{const matches=stringMatch(dirty,/^[\r\n\t ]+/);leadingWhitespace=matches&&matches[0];}
if(PARSER_MEDIA_TYPE==='application/xhtml+xml'&&NAMESPACE===HTML_NAMESPACE){dirty='<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>'+dirty+'</body></html>';}
const dirtyPayload=trustedTypesPolicy?trustedTypesPolicy.createHTML(dirty):dirty;if(NAMESPACE===HTML_NAMESPACE){try{doc=new DOMParser().parseFromString(dirtyPayload,PARSER_MEDIA_TYPE);}catch(_){}}
if(!doc||!doc.documentElement){doc=implementation.createDocument(NAMESPACE,'template',null);try{doc.documentElement.innerHTML=IS_EMPTY_INPUT?emptyHTML:dirtyPayload;}catch(_){}}
const body=doc.body||doc.documentElement;if(dirty&&leadingWhitespace){body.insertBefore(document.createTextNode(leadingWhitespace),body.childNodes[0]||null);}
if(NAMESPACE===HTML_NAMESPACE){return getElementsByTagName.call(doc,WHOLE_DOCUMENT?'html':'body')[0];}
return WHOLE_DOCUMENT?doc.documentElement:body;};const _createNodeIterator=function _createNodeIterator(root){return createNodeIterator.call(root.ownerDocument||root,root,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_TEXT|NodeFilter.SHOW_PROCESSING_INSTRUCTION|NodeFilter.SHOW_CDATA_SECTION,null);};const _isClobbered=function _isClobbered(elm){return elm instanceof HTMLFormElement&&(typeof elm.nodeName!=='string'||typeof elm.textContent!=='string'||typeof elm.removeChild!=='function'||!(elm.attributes instanceof NamedNodeMap)||typeof elm.removeAttribute!=='function'||typeof elm.setAttribute!=='function'||typeof elm.namespaceURI!=='string'||typeof elm.insertBefore!=='function'||typeof elm.hasChildNodes!=='function');};const _isNode=function _isNode(object){return typeof Node==='function'&&object instanceof Node;};const _executeHook=function _executeHook(entryPoint,currentNode,data){if(!hooks[entryPoint]){return;}
arrayForEach(hooks[entryPoint],hook=>{hook.call(DOMPurify,currentNode,data,CONFIG);});};const _sanitizeElements=function _sanitizeElements(currentNode){let content=null;_executeHook('beforeSanitizeElements',currentNode,null);if(_isClobbered(currentNode)){_forceRemove(currentNode);return true;}
const tagName=transformCaseFunc(currentNode.nodeName);_executeHook('uponSanitizeElement',currentNode,{tagName,allowedTags:ALLOWED_TAGS});if(currentNode.hasChildNodes()&&!_isNode(currentNode.firstElementChild)&&regExpTest(/<[/\w]/g,currentNode.innerHTML)&&regExpTest(/<[/\w]/g,currentNode.textContent)){_forceRemove(currentNode);return true;}
if(currentNode.nodeType===NODE_TYPE.progressingInstruction){_forceRemove(currentNode);return true;}
if(SAFE_FOR_XML&&currentNode.nodeType===NODE_TYPE.comment&&regExpTest(/<[/\w]/g,currentNode.data)){_forceRemove(currentNode);return true;}
if(!ALLOWED_TAGS[tagName]||FORBID_TAGS[tagName]){if(!FORBID_TAGS[tagName]&&_isBasicCustomElement(tagName)){if(CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp&&regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck,tagName)){return false;}
if(CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function&&CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)){return false;}}
if(KEEP_CONTENT&&!FORBID_CONTENTS[tagName]){const parentNode=getParentNode(currentNode)||currentNode.parentNode;const childNodes=getChildNodes(currentNode)||currentNode.childNodes;if(childNodes&&parentNode){const childCount=childNodes.length;for(let i=childCount-1;i>=0;--i){const childClone=cloneNode(childNodes[i],true);childClone.__removalCount=(currentNode.__removalCount||0)+1;parentNode.insertBefore(childClone,getNextSibling(currentNode));}}}
_forceRemove(currentNode);return true;}
if(currentNode instanceof Element&&!_checkValidNamespace(currentNode)){_forceRemove(currentNode);return true;}
if((tagName==='noscript'||tagName==='noembed'||tagName==='noframes')&&regExpTest(/<\/no(script|embed|frames)/i,currentNode.innerHTML)){_forceRemove(currentNode);return true;}
if(SAFE_FOR_TEMPLATES&&currentNode.nodeType===NODE_TYPE.text){content=currentNode.textContent;arrayForEach([MUSTACHE_EXPR,ERB_EXPR,TMPLIT_EXPR],expr=>{content=stringReplace(content,expr,' ');});if(currentNode.textContent!==content){arrayPush(DOMPurify.removed,{element:currentNode.cloneNode()});currentNode.textContent=content;}}
_executeHook('afterSanitizeElements',currentNode,null);return false;};const _isValidAttribute=function _isValidAttribute(lcTag,lcName,value){if(SANITIZE_DOM&&(lcName==='id'||lcName==='name')&&(value in document||value in formElement)){return false;}
if(ALLOW_DATA_ATTR&&!FORBID_ATTR[lcName]&&regExpTest(DATA_ATTR,lcName));else if(ALLOW_ARIA_ATTR&&regExpTest(ARIA_ATTR,lcName));else if(!ALLOWED_ATTR[lcName]||FORBID_ATTR[lcName]){if(_isBasicCustomElement(lcTag)&&(CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp&&regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck,lcTag)||CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function&&CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag))&&(CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp&&regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck,lcName)||CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function&&CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName))||lcName==='is'&&CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp&&regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck,value)||CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function&&CUSTOM_ELEMENT_HANDLING.tagNameCheck(value)));else{return false;}}else if(URI_SAFE_ATTRIBUTES[lcName]);else if(regExpTest(IS_ALLOWED_URI$1,stringReplace(value,ATTR_WHITESPACE,'')));else if((lcName==='src'||lcName==='xlink:href'||lcName==='href')&&lcTag!=='script'&&stringIndexOf(value,'data:')===0&&DATA_URI_TAGS[lcTag]);else if(ALLOW_UNKNOWN_PROTOCOLS&&!regExpTest(IS_SCRIPT_OR_DATA,stringReplace(value,ATTR_WHITESPACE,'')));else if(value){return false;}else;return true;};const _isBasicCustomElement=function _isBasicCustomElement(tagName){return tagName!=='annotation-xml'&&stringMatch(tagName,CUSTOM_ELEMENT);};const _sanitizeAttributes=function _sanitizeAttributes(currentNode){_executeHook('beforeSanitizeAttributes',currentNode,null);const{attributes}=currentNode;if(!attributes){return;}
const hookEvent={attrName:'',attrValue:'',keepAttr:true,allowedAttributes:ALLOWED_ATTR};let l=attributes.length;while(l--){const attr=attributes[l];const{name,namespaceURI,value:attrValue}=attr;const lcName=transformCaseFunc(name);let value=name==='value'?attrValue:stringTrim(attrValue);hookEvent.attrName=lcName;hookEvent.attrValue=value;hookEvent.keepAttr=true;hookEvent.forceKeepAttr=undefined;_executeHook('uponSanitizeAttribute',currentNode,hookEvent);value=hookEvent.attrValue;if(hookEvent.forceKeepAttr){continue;}
_removeAttribute(name,currentNode);if(!hookEvent.keepAttr){continue;}
if(!ALLOW_SELF_CLOSE_IN_ATTR&&regExpTest(/\/>/i,value)){_removeAttribute(name,currentNode);continue;}
if(SAFE_FOR_XML&&regExpTest(/((--!?|])>)|<\/(style|title)/i,value)){_removeAttribute(name,currentNode);continue;}
if(SAFE_FOR_TEMPLATES){arrayForEach([MUSTACHE_EXPR,ERB_EXPR,TMPLIT_EXPR],expr=>{value=stringReplace(value,expr,' ');});}
const lcTag=transformCaseFunc(currentNode.nodeName);if(!_isValidAttribute(lcTag,lcName,value)){continue;}
if(SANITIZE_NAMED_PROPS&&(lcName==='id'||lcName==='name')){_removeAttribute(name,currentNode);value=SANITIZE_NAMED_PROPS_PREFIX+value;}
if(trustedTypesPolicy&&typeof trustedTypes==='object'&&typeof trustedTypes.getAttributeType==='function'){if(namespaceURI);else{switch(trustedTypes.getAttributeType(lcTag,lcName)){case'TrustedHTML':{value=trustedTypesPolicy.createHTML(value);break;}
case'TrustedScriptURL':{value=trustedTypesPolicy.createScriptURL(value);break;}}}}
try{if(namespaceURI){currentNode.setAttributeNS(namespaceURI,name,value);}else{currentNode.setAttribute(name,value);}
if(_isClobbered(currentNode)){_forceRemove(currentNode);}else{arrayPop(DOMPurify.removed);}}catch(_){}}
_executeHook('afterSanitizeAttributes',currentNode,null);};const _sanitizeShadowDOM=function _sanitizeShadowDOM(fragment){let shadowNode=null;const shadowIterator=_createNodeIterator(fragment);_executeHook('beforeSanitizeShadowDOM',fragment,null);while(shadowNode=shadowIterator.nextNode()){_executeHook('uponSanitizeShadowNode',shadowNode,null);if(_sanitizeElements(shadowNode)){continue;}
if(shadowNode.content instanceof DocumentFragment){_sanitizeShadowDOM(shadowNode.content);}
_sanitizeAttributes(shadowNode);}
_executeHook('afterSanitizeShadowDOM',fragment,null);};DOMPurify.sanitize=function(dirty){let cfg=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};let body=null;let importedNode=null;let currentNode=null;let returnNode=null;IS_EMPTY_INPUT=!dirty;if(IS_EMPTY_INPUT){dirty='<!-->';}
if(typeof dirty!=='string'&&!_isNode(dirty)){if(typeof dirty.toString==='function'){dirty=dirty.toString();if(typeof dirty!=='string'){throw typeErrorCreate('dirty is not a string, aborting');}}else{throw typeErrorCreate('toString is not a function');}}
if(!DOMPurify.isSupported){return dirty;}
if(!SET_CONFIG){_parseConfig(cfg);}
DOMPurify.removed=[];if(typeof dirty==='string'){IN_PLACE=false;}
if(IN_PLACE){if(dirty.nodeName){const tagName=transformCaseFunc(dirty.nodeName);if(!ALLOWED_TAGS[tagName]||FORBID_TAGS[tagName]){throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');}}}else if(dirty instanceof Node){body=_initDocument('<!---->');importedNode=body.ownerDocument.importNode(dirty,true);if(importedNode.nodeType===NODE_TYPE.element&&importedNode.nodeName==='BODY'){body=importedNode;}else if(importedNode.nodeName==='HTML'){body=importedNode;}else{body.appendChild(importedNode);}}else{if(!RETURN_DOM&&!SAFE_FOR_TEMPLATES&&!WHOLE_DOCUMENT&&dirty.indexOf('<')===-1){return trustedTypesPolicy&&RETURN_TRUSTED_TYPE?trustedTypesPolicy.createHTML(dirty):dirty;}
body=_initDocument(dirty);if(!body){return RETURN_DOM?null:RETURN_TRUSTED_TYPE?emptyHTML:'';}}
if(body&&FORCE_BODY){_forceRemove(body.firstChild);}
const nodeIterator=_createNodeIterator(IN_PLACE?dirty:body);while(currentNode=nodeIterator.nextNode()){if(_sanitizeElements(currentNode)){continue;}
if(currentNode.content instanceof DocumentFragment){_sanitizeShadowDOM(currentNode.content);}
_sanitizeAttributes(currentNode);}
if(IN_PLACE){return dirty;}
if(RETURN_DOM){if(RETURN_DOM_FRAGMENT){returnNode=createDocumentFragment.call(body.ownerDocument);while(body.firstChild){returnNode.appendChild(body.firstChild);}}else{returnNode=body;}
if(ALLOWED_ATTR.shadowroot||ALLOWED_ATTR.shadowrootmode){returnNode=importNode.call(originalDocument,returnNode,true);}
return returnNode;}
let serializedHTML=WHOLE_DOCUMENT?body.outerHTML:body.innerHTML;if(WHOLE_DOCUMENT&&ALLOWED_TAGS['!doctype']&&body.ownerDocument&&body.ownerDocument.doctype&&body.ownerDocument.doctype.name&&regExpTest(DOCTYPE_NAME,body.ownerDocument.doctype.name)){serializedHTML='<!DOCTYPE '+body.ownerDocument.doctype.name+'>\n'+serializedHTML;}
if(SAFE_FOR_TEMPLATES){arrayForEach([MUSTACHE_EXPR,ERB_EXPR,TMPLIT_EXPR],expr=>{serializedHTML=stringReplace(serializedHTML,expr,' ');});}
return trustedTypesPolicy&&RETURN_TRUSTED_TYPE?trustedTypesPolicy.createHTML(serializedHTML):serializedHTML;};DOMPurify.setConfig=function(){let cfg=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};_parseConfig(cfg);SET_CONFIG=true;};DOMPurify.clearConfig=function(){CONFIG=null;SET_CONFIG=false;};DOMPurify.isValidAttribute=function(tag,attr,value){if(!CONFIG){_parseConfig({});}
const lcTag=transformCaseFunc(tag);const lcName=transformCaseFunc(attr);return _isValidAttribute(lcTag,lcName,value);};DOMPurify.addHook=function(entryPoint,hookFunction){if(typeof hookFunction!=='function'){return;}
hooks[entryPoint]=hooks[entryPoint]||[];arrayPush(hooks[entryPoint],hookFunction);};DOMPurify.removeHook=function(entryPoint){if(hooks[entryPoint]){return arrayPop(hooks[entryPoint]);}};DOMPurify.removeHooks=function(entryPoint){if(hooks[entryPoint]){hooks[entryPoint]=[];}};DOMPurify.removeAllHooks=function(){hooks={};};return DOMPurify;}
var purify=createDOMPurify();return purify;}));;

/* /web_editor/static/src/js/editor/odoo-editor/src/OdooEditor.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/OdooEditor',['@web_editor/js/editor/odoo-editor/src/commands/deleteBackward','@web_editor/js/editor/odoo-editor/src/commands/deleteForward','@web_editor/js/editor/odoo-editor/src/commands/enter','@web_editor/js/editor/odoo-editor/src/commands/shiftEnter','@web_editor/js/editor/odoo-editor/src/commands/shiftTab','@web_editor/js/editor/odoo-editor/src/commands/tab','@web_editor/js/editor/odoo-editor/src/commands/toggleList','@web_editor/js/editor/odoo-editor/src/commands/align','@web_editor/js/editor/odoo-editor/src/utils/sanitize','@web_editor/js/editor/odoo-editor/src/utils/serialize','@web_editor/js/editor/odoo-editor/src/utils/utils','@web_editor/js/editor/odoo-editor/src/commands/commands','@web_editor/js/editor/odoo-editor/src/powerbox/Powerbox','@web_editor/js/editor/odoo-editor/src/tablepicker/TablePicker','@web_editor/js/editor/odoo-editor/src/utils/constants'],function(require){'use strict';let __exports={};require("@web_editor/js/editor/odoo-editor/src/commands/deleteBackward");require("@web_editor/js/editor/odoo-editor/src/commands/deleteForward");require("@web_editor/js/editor/odoo-editor/src/commands/enter");require("@web_editor/js/editor/odoo-editor/src/commands/shiftEnter");require("@web_editor/js/editor/odoo-editor/src/commands/shiftTab");require("@web_editor/js/editor/odoo-editor/src/commands/tab");require("@web_editor/js/editor/odoo-editor/src/commands/toggleList");require("@web_editor/js/editor/odoo-editor/src/commands/align");const{sanitize}=require("@web_editor/js/editor/odoo-editor/src/utils/sanitize");const{serializeNode,unserializeNode,serializeSelection}=require("@web_editor/js/editor/odoo-editor/src/utils/serialize");const{closestBlock,commonParentGet,containsUnremovable,DIRECTIONS,ensureFocus,getCursorDirection,getFurthestUneditableParent,getListMode,getOuid,insertText,isColorGradient,nodeSize,preserveCursor,setCursorStart,setSelection,toggleClass,closestElement,isVisible,isHtmlContentSupported,rgbToHex,isIconElement,ICON_SELECTOR,getInSelection,getDeepRange,getRowIndex,getColumnIndex,ancestors,firstLeaf,previousLeaf,nextLeaf,isUnremovable,fillEmpty,isEmptyBlock,URL_REGEX,isSelectionFormat,YOUTUBE_URL_GET_VIDEO_ID,unwrapContents,peek,getAdjacentPreviousSiblings,getAdjacentNextSiblings,isBlock,getTraversedNodes,getSelectedNodes,descendants,hasValidSelection,hasTableSelection,pxToFloat,parseHTML,splitTextNode,isEditorTab,isMacOS,isProtected,isArtificialVoidElement,cleanZWS,isZWS,setCursorEnd,paragraphRelatedElements,getDeepestPosition,leftPos,isNotAllowedContent,EMAIL_REGEX,prepareUpdate,boundariesOut,getFontSizeDisplayValue,rightLeafOnlyNotBlockPath,lastLeaf,isUnbreakable,splitAroundUntil,ZERO_WIDTH_CHARS,ZERO_WIDTH_CHARS_REGEX,getAdjacentCharacter,isLinkEligibleForZwnbsp,isZwnbsp,childNodeIndex,setTagName,}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");const{editorCommands}=require("@web_editor/js/editor/odoo-editor/src/commands/commands");const{Powerbox}=require("@web_editor/js/editor/odoo-editor/src/powerbox/Powerbox");const{TablePicker}=require("@web_editor/js/editor/odoo-editor/src/tablepicker/TablePicker");Object.assign(__exports,require("@web_editor/js/editor/odoo-editor/src/utils/utils"));const{UNBREAKABLE_ROLLBACK_CODE,UNREMOVABLE_ROLLBACK_CODE}=require("@web_editor/js/editor/odoo-editor/src/utils/constants");const BACKSPACE_ONLY_COMMANDS=['oDeleteBackward','oDeleteForward'];const BACKSPACE_FIRST_COMMANDS=BACKSPACE_ONLY_COMMANDS.concat(['oEnter','oShiftEnter']);const HISTORY_SNAPSHOT_INTERVAL=1000*60;const HISTORY_SNAPSHOT_BUFFER_TIME=1000*10;const KEYBOARD_TYPES={VIRTUAL:'VIRTUAL',PHYSICAL:'PHYSICAL',UNKNOWN:'UKNOWN'};const AVATAR_SIZE=__exports.AVATAR_SIZE=25;const IS_KEYBOARD_EVENT_UNDO=ev=>ev.key==='z'&&(ev.ctrlKey||ev.metaKey);const IS_KEYBOARD_EVENT_REDO=ev=>ev.key==='y'&&(ev.ctrlKey||ev.metaKey);const IS_KEYBOARD_EVENT_BOLD=ev=>ev.key==='b'&&(ev.ctrlKey||ev.metaKey);const IS_KEYBOARD_EVENT_ITALIC=ev=>ev.key==='i'&&(ev.ctrlKey||ev.metaKey);const IS_KEYBOARD_EVENT_UNDERLINE=ev=>ev.key==='u'&&(ev.ctrlKey||ev.metaKey);const IS_KEYBOARD_EVENT_STRIKETHROUGH=ev=>ev.key==='5'&&(ev.ctrlKey||ev.metaKey);const IS_KEYBOARD_EVENT_LEFT_ARROW=ev=>ev.key==='ArrowLeft'&&!(ev.ctrlKey||ev.metaKey);const IS_KEYBOARD_EVENT_RIGHT_ARROW=ev=>ev.key==='ArrowRight'&&!(ev.ctrlKey||ev.metaKey);const IS_KEYBOARD_EVENT_UP_ARROW=ev=>ev.key==='ArrowUp'&&!(ev.ctrlKey||ev.metaKey);const IS_KEYBOARD_EVENT_DOWN_ARROW=ev=>ev.key==='ArrowDown'&&!(ev.ctrlKey||ev.metaKey);const CLIPBOARD_BLACKLISTS={unwrap:['.Apple-interchange-newline','DIV'],remove:['META','STYLE','SCRIPT'],};const CLIPBOARD_WHITELISTS=__exports.CLIPBOARD_WHITELISTS={nodes:['P','H1','H2','H3','H4','H5','H6','BLOCKQUOTE','PRE','UL','OL','LI','I','B','U','S','EM','FONT','STRONG','TABLE','THEAD','TH','TBODY','TR','TD','IMG','BR','A','.fa',],classes:[/^float-/,'d-block','mx-auto','img-fluid','img-thumbnail','rounded','rounded-circle','table','table-bordered',/^padding-/,/^shadow/,/^text-o-/,/^bg-o-/,'o_checked','o_checklist','oe-nested',/^btn/,/^fa/,],attributes:['class','href','src','target'],styledTags:['SPAN','B','STRONG','I','S','U','FONT','TD'],};const SELECTIONLESS_COMMANDS=['addRow','addColumn','removeRow','removeColumn','resetSize'];const FORMATTING_COMMANDS=['applyColor','bold','italic','underline','strikeThrough','setFontSize']
function defaultOptions(defaultObject,object){const newObject=Object.assign({},defaultObject,object);for(const[key,value]of Object.entries(object)){if(typeof value==='undefined'){newObject[key]=defaultObject[key];}}
return newObject;}
function getImageFiles(dataTransfer){return[...dataTransfer.items].filter(item=>item.kind==='file'&&item.type.includes('image/')).map((item)=>item.getAsFile());}
function getImageUrl(file){return new Promise((resolve,reject)=>{const reader=new FileReader();reader.readAsDataURL(file);reader.onloadend=(e)=>{if(reader.error){return reject(reader.error);}
resolve(e.target.result);};});}
const OdooEditor=__exports.OdooEditor=class OdooEditor extends EventTarget{constructor(editable,options={}){super();this.options=defaultOptions({controlHistoryFromDocument:false,getContextFromParentRect:()=>{return{top:0,left:0};},getScrollContainerRect:()=>document.body.getBoundingClientRect(),toSanitize:true,isRootEditable:true,placeholder:false,showEmptyElementHint:true,defaultLinkAttributes:{},plugins:[],getUnremovableElements:()=>[],getReadOnlyAreas:()=>[],getContentEditableAreas:()=>[],getPowerboxElement:()=>{const selection=document.getSelection();if(selection.isCollapsed&&selection.rangeCount){const elementSelectors=['DIV','LI',...paragraphRelatedElements];return closestElement(selection.anchorNode,elementSelectors.join(', '));}},preHistoryUndo:()=>{},beforeAnyCommand:()=>{},isHintBlacklisted:()=>false,filterMutationRecords:(records)=>records,postProcessExternalSteps:()=>null,onPostSanitize:()=>{},direction:'ltr',_t:string=>string,allowCommandVideo:true,renderingClasses:[],allowInlineAtRoot:false,useResponsiveFontSizes:true,showResponsiveFontSizesBadges:false,showExtendedTextStylesOptions:false,autoActivateContentEditable:true,getCSSVariableValue:()=>null,convertNumericToUnit:x=>x,},options,);this.document=options.document||document;this.isDestroyed=false;this.isMobile=matchMedia('(max-width: 767px)').matches;this.isFirefox=navigator.userAgent.toLowerCase().indexOf('firefox')>-1;this.isPrepareUpdateLocked=false;this.keyboardType=KEYBOARD_TYPES.UNKNOWN;this._checkStepUnbreakable=true;this._domListeners=[];this._observerTimeoutUnactive=new Set();this._observerUnactiveLabels=new Set();this._currentMouseState='mouseup';this._onKeyupResetContenteditableNodes=[];this._toRollback=false;this._idToNodeMap=new Map();this._plugins=[];for(const plugin of this.options.plugins){this._pluginAdd(plugin);}
if(editable.innerHTML.trim()===''){editable.innerHTML='<p><br></p>';}
this.initElementForEdition(editable);editable.oid='root';this._idToNodeMap.set(1,editable);this.editable=editable;this.editable.classList.add("odoo-editor-editable");if(this.options.toSanitize){sanitize(editable);this.options.onPostSanitize(editable);}
this.editable.setAttribute('dir',this.options.direction);this.canActivateContentEditable=this.options.autoActivateContentEditable;if(this.canActivateContentEditable){this._activateContenteditable();}
this._collabClientId=this.options.collaborationClientId;this._collabClientAvatarUrl=this.options.collaborationClientAvatarUrl;this._collabSelectionInfos=new Map();this._collabSelectionColor=`hsl(${(Math.random() * 360).toFixed(0)}, 75%, 50%)`;this._avatarsOverlaps={}
this.mainAbsoluteContainer=this.document.createElement('div');this.mainAbsoluteContainer.classList.add('oe-absolute-container');this.editable.before(this.mainAbsoluteContainer);this._selectionsContainer=this.makeAbsoluteContainer('oe-selections-container');this._avatarsContainer=this.makeAbsoluteContainer('oe-avatars-container');this._avatarsCountersContainer=this.makeAbsoluteContainer('oe-avatars-counters-container');this._postProcessExternalStepsPromise=null;this._externalStepsBuffer=[];this.idSet(editable);this._historyStepsActive=true;this.historyReset();if(this.options.initialHistoryId){this.historySetInitialId(this.options.initialHistoryId);}
this._pluginCall('start',[editable]);this._pluginCall('sanitizeElement',[editable]);this.powerboxTablePicker=new TablePicker({document:this.document,floating:true,getContextFromParentRect:this.options.getContextFromParentRect,direction:this.options.direction,});document.body.appendChild(this.powerboxTablePicker.el);this.powerboxTablePicker.addEventListener('cell-selected',ev=>{this.execCommand('insertTable',{rowNumber:ev.detail.rowNumber,colNumber:ev.detail.colNumber,});});this._tableUiContainer=this.document.createElement('div');this._tableUiContainer.classList.add('o_table_ui_container');const parser=new DOMParser();const isRTL=this.options.direction==="rtl";for(const direction of['row','column']){const iconClass=(direction==='row')?'fa-ellipsis-v':'fa-ellipsis-h';const ui=parser.parseFromString(`<div class="o_table_ui o_${direction}_ui" style="visibility: hidden;">
                <div>
                    <span class="o_table_ui_menu_toggler fa ${iconClass}"></span>
                    <div class="o_table_ui_menu"></div>
                </div>
            </div>`,'text/html').body.firstElementChild;const uiMenu=ui.querySelector('.o_table_ui_menu');if(direction==='column'){if(isRTL){uiMenu.append(...parser.parseFromString(`
                        <div class="o_move_right"><span class="fa fa-chevron-right"></span>`+this.options._t('Move left')+`</div>
                        <div class="o_move_left"><span class="fa fa-chevron-left"></span>`+this.options._t('Move right')+`</div>
                    `,'text/html').body.children);}else{uiMenu.append(...parser.parseFromString(`
                        <div class="o_move_left"><span class="fa fa-chevron-left"></span>`+this.options._t('Move left')+`</div>
                        <div class="o_move_right"><span class="fa fa-chevron-right"></span>`+this.options._t('Move right')+`</div>
                    `,'text/html').body.children);}
this.addDomListener(uiMenu.querySelector('.o_move_left'),'click',this._onTableMoveLeftClick);this.addDomListener(uiMenu.querySelector('.o_move_right'),'click',this._onTableMoveRightClick);}else{uiMenu.append(...parser.parseFromString(`
                    <div class="o_move_up"><span class="fa fa-chevron-left" style="transform: rotate(90deg);"></span>`+this.options._t('Move up')+`</div>
                    <div class="o_move_down"><span class="fa fa-chevron-right" style="transform: rotate(90deg);"></span>`+this.options._t('Move down')+`</div>
                `,'text/html').body.children);this.addDomListener(uiMenu.querySelector('.o_move_up'),'click',this._onTableMoveUpClick);this.addDomListener(uiMenu.querySelector('.o_move_down'),'click',this._onTableMoveDownClick);}
if(direction==='column'){if(isRTL){uiMenu.append(...parser.parseFromString(`
                        <div class="o_insert_right"><span class="fa fa-plus"></span>`+this.options._t('Insert left')+`</div>
                        <div class="o_insert_left"><span class="fa fa-plus"></span>`+this.options._t('Insert right')+`</div>
                    `,'text/html').body.children);}else{uiMenu.append(...parser.parseFromString(`
                        <div class="o_insert_left"><span class="fa fa-plus"></span>`+this.options._t('Insert left')+`</div>
                        <div class="o_insert_right"><span class="fa fa-plus"></span>`+this.options._t('Insert right')+`</div>
                    `,'text/html').body.children);}
this.addDomListener(uiMenu.querySelector('.o_insert_left'),'click',()=>this.execCommand('addColumn','before',this._columnUiTarget));this.addDomListener(uiMenu.querySelector('.o_insert_right'),'click',()=>this.execCommand('addColumn','after',this._columnUiTarget));}else{uiMenu.append(...parser.parseFromString(`
                    <div class="o_insert_above"><span class="fa fa-plus"></span>`+this.options._t('Insert above')+`</div>
                    <div class="o_insert_below"><span class="fa fa-plus"></span>`+this.options._t('Insert below')+`</div>
                `,'text/html').body.children);this.addDomListener(uiMenu.querySelector('.o_insert_above'),'click',()=>this.execCommand('addRow','before',this._rowUiTarget));this.addDomListener(uiMenu.querySelector('.o_insert_below'),'click',()=>this.execCommand('addRow','after',this._rowUiTarget));}
if(direction==='column'){uiMenu.append(parser.parseFromString(`<div class="o_delete_column"><span class="fa fa-trash"></span>`+this.options._t('Delete')+`</div>
                `,'text/html').body.firstChild)
this.addDomListener(uiMenu.querySelector('.o_delete_column'),'click',this._onTableDeleteColumnClick);}else{uiMenu.append(parser.parseFromString(`<div class="o_delete_row"><span class="fa fa-trash"></span>`+this.options._t('Delete')+`</div>
                `,'text/html').body.firstChild)
this.addDomListener(uiMenu.querySelector('.o_delete_row'),'click',this._onTableDeleteRowClick);}
uiMenu.append(parser.parseFromString(`<div class="o_reset_table_size"><span class="fa fa-table"></span>`+this.options._t('Reset Size')+`</div>
                `,'text/html').body.firstChild)
this.addDomListener(uiMenu.querySelector('.o_reset_table_size'),'click',()=>this.execCommand('resetSize',this._tableUiTarget));this[`_${direction}Ui`]=ui;this._tableUiContainer.append(ui);this.addDomListener(ui.querySelector('.o_table_ui_menu_toggler'),'click',this._onTableMenuTogglerClick);this.editable.before(this._tableUiContainer);}
this.powerbox=new Powerbox({editable:this.editable,getContextFromParentRect:this.options.getContextFromParentRect,commandFilters:this.options.powerboxFilters,onShow:()=>{this.powerboxTablePicker.hide();},beforeCommand:()=>{if(this._isPowerboxOpenOnInput){this.historyRevertUntil(this._powerboxBeforeStepIndex);this.historyStep(true);this._historyStepsStates.set(peek(this._historySteps).id,'consumed');ensureFocus(this.editable);getDeepRange(this.editable,{select:true});}},afterCommand:()=>{this.historyStep(true);this._isPowerboxOpenOnInput=false;},categories:[{name:this.options._t('Structure'),priority:70},{name:this.options._t('Format'),priority:60},{name:this.options._t('Widgets'),priority:30},...(this.options.categories||[]),],commands:[{category:this.options._t('Structure'),name:this.options._t('Bulleted list'),priority:110,description:this.options._t('Create a simple bulleted list'),fontawesome:'fa-list-ul',isDisabled:()=>!this.isSelectionInBlockRoot(),callback:()=>{this.execCommand('toggleList','UL');},},{category:this.options._t('Structure'),name:this.options._t('Numbered list'),priority:100,description:this.options._t('Create a list with numbering'),fontawesome:'fa-list-ol',isDisabled:()=>!this.isSelectionInBlockRoot(),callback:()=>{this.execCommand('toggleList','OL');},},{category:this.options._t('Structure'),name:this.options._t('Checklist'),priority:90,description:this.options._t('Track tasks with a checklist'),fontawesome:'fa-check-square-o',isDisabled:()=>!this.isSelectionInBlockRoot(),callback:()=>{this.execCommand('toggleList','CL');},},{category:this.options._t('Structure'),name:this.options._t('Table'),priority:80,description:this.options._t('Insert a table'),fontawesome:'fa-table',isDisabled:()=>!this.isSelectionInBlockRoot(),callback:()=>{if(this.isMobile){this.execCommand('insertTable',{rowNumber:this.powerboxTablePicker.rowNumber,colNumber:this.powerboxTablePicker.colNumber,});}else{this.powerboxTablePicker.show();}},},{category:this.options._t('Format'),name:this.options._t('Heading 1'),priority:50,description:this.options._t('Big section heading'),fontawesome:'fa-header',isDisabled:()=>!this.isSelectionInBlockRoot(),callback:()=>{this.execCommand('setTag','H1');},},{category:this.options._t('Format'),name:this.options._t('Heading 2'),priority:40,description:this.options._t('Medium section heading'),fontawesome:'fa-header',isDisabled:()=>!this.isSelectionInBlockRoot(),callback:()=>{this.execCommand('setTag','H2');},},{category:this.options._t('Format'),name:this.options._t('Heading 3'),priority:30,description:this.options._t('Small section heading'),fontawesome:'fa-header',isDisabled:()=>!this.isSelectionInBlockRoot(),callback:()=>{this.execCommand('setTag','H3');},},{category:this.options._t('Format'),name:this.options._t('Switch direction'),priority:20,description:this.options._t('Switch the text\'s direction'),fontawesome:'fa-exchange',callback:()=>{this.execCommand('switchDirection');},},{category:this.options._t('Format'),name:this.options._t('Text'),priority:10,description:this.options._t('Paragraph block'),fontawesome:'fa-paragraph',isDisabled:()=>!this.isSelectionInBlockRoot(),callback:()=>{this.execCommand('setTag','P');},},{category:this.options._t('Widgets'),name:this.options._t('3 Stars'),priority:20,description:this.options._t('Insert a rating over 3 stars'),fontawesome:'fa-star-o',callback:()=>{let html='\u200B<span contenteditable="false" class="o_stars o_three_stars">';html+=Array(3).fill().map(()=>'<i class="fa fa-star-o"></i>').join('');html+='</span>\u200B';this.execCommand('insert',parseHTML(this.document,html));},},{category:this.options._t('Widgets'),name:this.options._t('5 Stars'),priority:10,description:this.options._t('Insert a rating over 5 stars'),fontawesome:'fa-star',callback:()=>{let html='\u200B<span contenteditable="false" class="o_stars o_five_stars">';html+=Array(5).fill().map(()=>'<i class="fa fa-star-o"></i>').join('');html+='</span>\u200B';this.execCommand('insert',parseHTML(this.document,html));},},...(this.options.commands||[]),...(!this.options.commands||!this.options.commands.find(c=>c.name===this.options._t('Separator'))?[{category:this.options._t('Structure'),name:this.options._t('Separator'),priority:40,description:this.options._t('Insert a horizontal rule separator'),fontawesome:'fa-minus',isDisabled:()=>!this.isSelectionInBlockRoot(),callback:()=>{this.execCommand('insertHorizontalRule');},}]:[]),],});this.observerActive();this.addDomListener(this.editable,'keydown',this._onKeyDown);this.addDomListener(this.editable,'input',this._onInput);this.addDomListener(this.editable,'beforeinput',this._onBeforeInput);this.addDomListener(this.editable,'mousedown',this._onMouseDown);this.addDomListener(this.editable,'mouseup',this._onMouseup);this.addDomListener(this.editable,'mousemove',this._onMousemove);this.addDomListener(this.editable,'mouseleave',this._onMouseLeave);this.addDomListener(this.editable,'paste',this._onPaste);this.addDomListener(this.editable,'dragstart',this._onDragStart);this.addDomListener(this.editable,'drop',this._onDrop);this.addDomListener(this.editable,'copy',this._onClipboardCopy);this.addDomListener(this.editable,'cut',this._onClipboardCut);this.addDomListener(this.document,'selectionchange',this._onSelectionChange);this.addDomListener(this.document,'selectionchange',this._handleCommandHint);this.addDomListener(this.document,'keydown',this._onDocumentKeydown);this.addDomListener(this.document,'keyup',this._onDocumentKeyup);this.addDomListener(this.document,'mouseup',this._onDocumentMouseup);this.addDomListener(this.document,'click',this._onDocumentClick);this.addDomListener(this.document,'scroll',this._onScroll,true);this.multiselectionRefresh=this.multiselectionRefresh.bind(this);this._resizeObserver=new ResizeObserver(this.multiselectionRefresh);this._resizeObserver.observe(this.document.body);this._resizeObserver.observe(this.editable);this.addDomListener(this.editable,'scroll',this.multiselectionRefresh);if(this._collabClientId){this._snapshotInterval=setInterval(()=>{this._historyMakeSnapshot();},HISTORY_SNAPSHOT_INTERVAL);}
if(this.options.toolbar){this.setupToolbar(this.options.toolbar);}
if(editable.textContent===''&&this.options.placeholder){this._makeHint(editable.firstChild,this.options.placeholder,true);}}
destroy(){this.observerUnactive();this._removeDomListener();this.powerbox.destroy();this.powerboxTablePicker.el.remove();this.mainAbsoluteContainer.remove();this._resizeObserver.disconnect();clearInterval(this._snapshotInterval);this._pluginCall('destroy',[]);this.isDestroyed=true;this._rowUi.remove();this._columnUi.remove();}
setupToolbar(toolbar){this.toolbar=toolbar;this.autohideToolbar=this.options.autohideToolbar;if(!this.options.showExtendedTextStylesOptions){this.toolbar.querySelectorAll("[data-extended-text-style]").forEach(el=>el.classList.add("d-none"));}
this.bindExecCommand(this.toolbar);const toolbarAnchors=this.toolbar.querySelectorAll('a');toolbarAnchors.forEach(a=>a.addEventListener('click',e=>e.preventDefault()));for(const colorLabel of this.toolbar.querySelectorAll('label')){colorLabel.addEventListener('mousedown',ev=>{if(ev.detail<2){ev.preventDefault();ev.currentTarget.dispatchEvent(new MouseEvent('click',{detail:2}));}});colorLabel.addEventListener('input',ev=>{this.document.execCommand(ev.target.name,false,ev.target.value);this.updateColorpickerLabels();});}
const fontSizeInput=this.toolbar.querySelector('input#fontSizeCurrentValue');this.addDomListener(this.toolbar,'click',ev=>{if(fontSizeInput&&!fontSizeInput.readOnly&&ev.target.closest('#font-size .dropdown-toggle')){fontSizeInput.select();}else if(!this.isSelectionInEditable()&&ev.target.nodeName!=='INPUT'&&ev.target.id!=='image-transform'){this.historyResetLatestComputedSelection(true);}});const applyFontSizeREM=pxStrValue=>{const pxValue=parseFloat(pxStrValue);const remValue=this.options.convertNumericToUnit(pxValue,"px","rem");this.execCommand("setFontSize",`${remValue}rem`);};if(fontSizeInput){const debouncedOnInputChange=(()=>{let handle;return()=>new Promise(resolve=>{clearTimeout(handle);handle=setTimeout(()=>{handle=null;const fontSize=parseInt(fontSizeInput.value);if(fontSize>0){getDeepRange(this.editable,{correctTripleClick:true,select:true});if(!this.isSelectionInEditable()){this.historyResetLatestComputedSelection(true);}
applyFontSizeREM(fontSize);fontSizeInput.blur();}
resolve();},50);});})();this.addDomListener(fontSizeInput,'change',debouncedOnInputChange);}
const fontSizeDropdown=this.toolbar.querySelector('#font-size');if(fontSizeDropdown){this.computeFontSizeSelectorValues(fontSizeDropdown);const applyFontSizeChoice=optionEl=>{if(!this.isSelectionInEditable()){this.historyResetLatestComputedSelection(true);}
if(this.options.useResponsiveFontSizes){const fontSizeClassName=optionEl.dataset.applyClass;this.execCommand("setFontSize",undefined);this.historyResetLatestComputedSelection(true);this.execCommand("setFontSizeClassName",fontSizeClassName);}else{applyFontSizeREM(optionEl.dataset.value);}};fontSizeDropdown.querySelectorAll('.dropdown-item').forEach(item=>{this.addDomListener(item,'mousedown',ev=>{applyFontSizeChoice(ev.currentTarget);});this.addDomListener(item,'keydown',ev=>{if(ev.key!=='Enter'){return;}
applyFontSizeChoice(ev.currentTarget);});});}
this._updateToolbar();}
computeFontSizeSelectorValues(fontSizeDropdownEl){fontSizeDropdownEl=fontSizeDropdownEl||this.toolbar.querySelector("#font-size");if(!fontSizeDropdownEl){return;}
let previousItem=null;let previousValue=-1;const style=this.document.defaultView.getComputedStyle(this.document.body);for(const itemEl of fontSizeDropdownEl.querySelectorAll("[data-dynamic-value]")){const variableName=itemEl.dataset.dynamicValue;const strValue=this.options.getCSSVariableValue(variableName,style);const remValue=parseFloat(strValue);const pxValue=this.options.convertNumericToUnit(remValue,"rem","px");const roundedValue=Math.round(pxValue);itemEl.dataset.value=roundedValue;itemEl.firstChild.textContent=roundedValue;if(previousItem){previousItem.parentElement.classList.toggle('d-none',Math.abs(pxValue-previousValue)<0.001);}
previousItem=itemEl;previousValue=pxValue;}
for(const badgeEl of fontSizeDropdownEl.querySelectorAll(".o_we_font_size_badge")){badgeEl.classList.toggle("d-none",!this.options.showResponsiveFontSizesBadges);}}
resetContent(value){value=value||'<p><br></p>';this.editable.innerHTML=value;this.sanitize(this.editable);this.historyStep(true);this._toRollback=false;if(this.editable.textContent===''&&this.options.placeholder){this._makeHint(this.editable.firstChild,this.options.placeholder,true);}
this.multiselectionRefresh();}
sanitize(target){this.observerFlush();let record;if(!target){for(record of this._currentStep.mutations){const node=this.idFind(record.parentId||record.id)||this.editable;if(!this.editable.contains(node)){continue;}
target=target?commonParentGet(target,node,this.editable):node;}}
if(!target){return false;}
const nestedListAncestor=closestElement(target,'.oe-nested');if(nestedListAncestor&&nestedListAncestor.parentElement){target=nestedListAncestor.parentElement;}
sanitize(target,this.editable);this._resetLinkInSelection();this._pluginCall('sanitizeElement',[target.parentElement||target]);this.options.onPostSanitize(target);}
addDomListener(element,eventName,callback,useCapture){const boundCallback=callback.bind(this);this._domListeners.push([element,eventName,boundCallback]);element.addEventListener(eventName,boundCallback,useCapture);}
makeAbsoluteContainer(containerId){const container=this.document.createElement('div');container.className=`oe-absolute-container`;container.setAttribute('data-oe-absolute-container-id',containerId);this.mainAbsoluteContainer.append(container);return container;}
_generateId(){return Math.floor(Math.random()*Math.pow(2,52)).toString();}
idSet(node,testunbreak=false){if(!node.oid){node.oid=this._generateId();}
this._idToNodeMap.set(node.oid,node);node.ouid=node.ouid||getOuid(node,true);if(testunbreak&&!(node.nodeType===Node.TEXT_NODE&&!node.length)){const ouid=getOuid(node);if(!this._toRollback&&ouid&&ouid!==node.ouid){this._toRollback=UNBREAKABLE_ROLLBACK_CODE;}}
let childNode=node.firstChild;while(childNode){this.idSet(childNode,testunbreak);childNode=childNode.nextSibling;}}
idFind(id){return this._idToNodeMap.get(id);}
serializeNode(node,mutatedNodes){return this._collabClientId?serializeNode(node,mutatedNodes):node;}
unserializeNode(node){return this._collabClientId?unserializeNode(node):node;}
automaticStepActive(label){this._observerTimeoutUnactive.delete(label);}
automaticStepUnactive(label){this._observerTimeoutUnactive.add(label);}
automaticStepSkipStack(){this.automaticStepUnactive('skipStack');setTimeout(()=>this.automaticStepActive('skipStack'));}
observerUnactive(label){this._observerUnactiveLabels.add(label);if(this.observer){clearTimeout(this.observerTimeout);this.observerFlush();this.dispatchEvent(new Event('observerUnactive'));this.observer.disconnect();}}
observerFlush(){const records=this.observer.takeRecords();this.observerIdSet(records);this.observerApply(this.filterMutationRecords(records));}
observerActive(label){this._observerUnactiveLabels.delete(label);if(this._observerUnactiveLabels.size!==0)return;if(!this.observer){this.observer=new MutationObserver(records=>{this.observerIdSet(records);records=this.filterMutationRecords(records);if(!records.length)return;this.dispatchEvent(new Event('contentChanged'));clearTimeout(this.observerTimeout);if(this._observerTimeoutUnactive.size===0){this.observerTimeout=setTimeout(()=>{this.historyStep();},100);}
this.observerApply(records);});}
this.dispatchEvent(new Event('preObserverActive'));this.observer.observe(this.editable,{childList:true,subtree:true,attributes:true,attributeOldValue:true,characterData:true,characterDataOldValue:true,});this.dispatchEvent(new Event('observerActive'));}
observerIdSet(records){for(const record of records){if(record.type==='childList'){this.idSet(record.target);}}}
observerApply(records){const mutatedNodes=new Set();for(const record of records){if(record.type==='childList'){for(const node of record.addedNodes){this.idSet(node,this._checkStepUnbreakable);mutatedNodes.add(node.oid);}
for(const node of record.removedNodes){this.idSet(node,this._checkStepUnbreakable);mutatedNodes.delete(node.oid);}}}
for(const record of records){switch(record.type){case'characterData':{this._currentStep.mutations.push({'type':'characterData','id':record.target.oid,'text':record.target.textContent,'oldValue':record.oldValue,});break;}
case'attributes':{this._currentStep.mutations.push({'type':'attributes','id':record.target.oid,'attributeName':record.attributeName,'value':record.target.getAttribute(record.attributeName),'oldValue':record.oldValue,});break;}
case'childList':{record.addedNodes.forEach(added=>{if(!this._toRollback&&containsUnremovable(added)){this._toRollback=UNREMOVABLE_ROLLBACK_CODE;}
const mutation={'type':'add',};if(!record.nextSibling&&record.target.oid){mutation.append=record.target.oid;}else if(record.nextSibling&&record.nextSibling.oid){mutation.before=record.nextSibling.oid;}else if(!record.previousSibling&&record.target.oid){mutation.prepend=record.target.oid;}else if(record.previousSibling&&record.previousSibling.oid){mutation.after=record.previousSibling.oid;}else{return false;}
mutation.id=added.oid;mutation.node=this.serializeNode(added,mutatedNodes);this._currentStep.mutations.push(mutation);});record.removedNodes.forEach(removed=>{if(!this._toRollback&&containsUnremovable(removed)){this._toRollback=UNREMOVABLE_ROLLBACK_CODE;}
this._currentStep.mutations.push({'type':'remove','id':removed.oid,'parentId':record.target.oid,'node':this.serializeNode(removed),'nextId':record.nextSibling?record.nextSibling.oid:undefined,'previousId':record.previousSibling?record.previousSibling.oid:undefined,});});break;}}}
if(records.length){this.dispatchEvent(new Event('observerApply'));}}
filterMutationRecords(records){const attributeCache=new Map();const filteredRecords=[];for(const record of records){if(record.type==='attributes'){if(record.target===this.editable)continue;if(record.attributeName==='contenteditable'){continue;}
attributeCache.set(record.target,attributeCache.get(record.target)||{});if(record.attributeName==='class'){const classBefore=(record.oldValue&&record.oldValue.split(' '))||[];const classAfter=(record.target.className&&record.target.className.split&&record.target.className.split(' '))||[];const excludedClasses=[];for(const klass of classBefore){if(!classAfter.includes(klass)){excludedClasses.push(klass);}}
for(const klass of classAfter){if(!classBefore.includes(klass)){excludedClasses.push(klass);}}
if(excludedClasses.length&&excludedClasses.every(c=>this.options.renderingClasses.includes(c))){continue;}}
if(typeof attributeCache.get(record.target)[record.attributeName]==='undefined'){const oldValue=record.oldValue===undefined?null:record.oldValue;attributeCache.get(record.target)[record.attributeName]=oldValue!==record.target.getAttribute(record.attributeName);}
if(!attributeCache.get(record.target)[record.attributeName]){continue;}}
const closestProtectedCandidate=closestElement(record.target,'[data-oe-protected]');if(closestProtectedCandidate){const protectedValue=closestProtectedCandidate.dataset.oeProtected;switch(protectedValue){case"true":case"":if(record.type!=="attributes"||record.target!==closestProtectedCandidate||isProtected(closestProtectedCandidate.parentElement)){continue;}
break;case"false":if(record.type==="attributes"&&record.target===closestProtectedCandidate&&isProtected(closestProtectedCandidate.parentElement)){continue;}
break;}}
filteredRecords.push(record);}
return this.options.filterMutationRecords(filteredRecords);}
historyReset(){this._historyClean();const firstStep=this._historyGetSnapshotStep();this._firstStepId=firstStep.id;this._historySnapshots=[{step:firstStep}];this._historySteps.push(firstStep);this._historyIds=[];}
historySetInitialId(id){this._historyIds.unshift(id);}
historyGetBranchIds(){return this._historyIds.concat(this._historySteps.map(s=>s.id));}
historyGetSnapshotSteps(){if(!this._historySnapshots[0].time){return{steps:this._historySteps,historyIds:this.historyGetBranchIds()};}
const steps=[];let snapshot;if(this._historySnapshots[0].time+HISTORY_SNAPSHOT_BUFFER_TIME<Date.now()){snapshot=this._historySnapshots[0];}else{snapshot=this._historySnapshots[1];}
let index=this._historySteps.length-1;while(this._historySteps[index].id!==snapshot.step.id){steps.push(this._historySteps[index]);index--;}
steps.push(snapshot.step);steps.reverse();return{steps,historyIds:this.historyGetBranchIds()};}
historyResetFromSteps(steps,historyIds){this._historyIds=historyIds;this.observerUnactive();let latestComputedSelectionPath;if(this._latestComputedSelection?.anchorNode){latestComputedSelectionPath={...this._latestComputedSelection,anchorNode:this._getNodeIndexPath(this._latestComputedSelection.anchorNode),focusNode:this._getNodeIndexPath(this._latestComputedSelection.focusNode),};}
for(const node of[...this.editable.childNodes]){node.remove();}
this._historyClean();for(const step of steps){this.historyApply(step.mutations);}
if(latestComputedSelectionPath){this._latestComputedSelection={...latestComputedSelectionPath,anchorNode:this._getNodeFromIndexPath(latestComputedSelectionPath.anchorNode),focusNode:this._getNodeFromIndexPath(latestComputedSelectionPath.focusNode),};if(this.isSelectionInEditable(this._latestComputedSelection)){this._latestComputedSelectionInEditable=this._latestComputedSelection;}}
this._historySnapshots=[{step:steps[0]}];this._historySteps=steps;this._postProcessExternalStepsPromise=this.options.postProcessExternalSteps(this.editable);this._handleCommandHint();this.multiselectionRefresh();this.observerActive();this.dispatchEvent(new Event('historyResetFromSteps'));}
historyGetSteps(){return this._historySteps;}
historyGetMissingSteps({fromStepId,toStepId}){const fromIndex=this._historySteps.findIndex(x=>x.id===fromStepId);const toIndex=toStepId?this._historySteps.findIndex(x=>x.id===toStepId):this._historySteps.length;if(fromIndex===-1||toIndex===-1){return-1;}
return this._historySteps.slice(fromIndex+1,toIndex);}
historyStep(skipRollback=false,{stepId}={}){if(!this._historyStepsActive){return;}
this.sanitize();if(this._toRollback){if(!skipRollback)this.historyRollback();this._toRollback=false;}
const currentStep=this._currentStep;if(!currentStep.mutations.length){return false;}
currentStep.id=stepId||this._generateId();const previousStep=peek(this._historySteps);currentStep.clientId=this._collabClientId;currentStep.previousStepId=previousStep.id;this._historySteps.push(currentStep);if(this.options.onHistoryStep){this.options.onHistoryStep(currentStep);}
this._currentStep={selection:{},mutations:[],};this._checkStepUnbreakable=true;this._recordHistorySelection();this.dispatchEvent(new Event('historyStep'));this.multiselectionRefresh();}
historyApply(records){for(const record of records){if(record.type==='characterData'){const node=this.idFind(record.id);if(node){node.textContent=record.text;}}else if(record.type==='attributes'){const node=this.idFind(record.id);if(node){let value=record.value;if(typeof value==='string'&&record.attributeName==='class'){value=value.split(' ').filter(c=>!this.options.renderingClasses.includes(c)).join(' ');}
if(this._collabClientId){this._safeSetAttribute(node,record.attributeName,value);}else{node.setAttribute(record.attributeName,value);}}}else if(record.type==='remove'){const toremove=this.idFind(record.id);if(toremove){toremove.remove();}}else if(record.type==='add'){let node=this.idFind(record.oid)||(record.node&&this.unserializeNode(record.node));if(!node){continue;}
if(this._collabClientId){const fakeNode=document.createElement('fake-el');fakeNode.appendChild(node);DOMPurify.sanitize(fakeNode,{IN_PLACE:true,ADD_TAGS:["#document-fragment","fake-el"],ADD_ATTR:["contenteditable"],});node=fakeNode.childNodes[0];if(!node){continue;}}
this.idSet(node,true);if(record.append&&this.idFind(record.append)){this.idFind(record.append).append(node);}else if(record.before&&this.idFind(record.before)){this.idFind(record.before).before(node);}else if(record.after&&this.idFind(record.after)){this.idFind(record.after).after(node);}else{continue;}}}}
historyRollback(until=0){const step=this._currentStep;this.observerFlush();this.historyRevert(step,{until});this.observerFlush();step.mutations=step.mutations.slice(0,until);this._toRollback=false;}
historyRevertCurrentStep(){this.observerFlush();this.historyRevert(this._currentStep,{sideEffect:false});this.observerFlush();this._currentStep.mutations=[];this.activateContenteditable();this.historySetSelection(this._currentStep);}
historyUndo(){this.options.preHistoryUndo();const lastStep=this._currentStep;this.historyRevert(lastStep);lastStep.mutations=[];const pos=this._getNextUndoIndex();if(pos>0){this._historyStepsStates.set(this._historySteps[pos].id,'consumed');this.historyRevert(this._historySteps[pos]);const stepId=this._generateId();this._historyStepsStates.set(stepId,'undo');this.historyStep(true,{stepId});this.dispatchEvent(new Event('historyUndo'));}}
historyRedo(){this.historyRevert(this._currentStep);this._currentStep.mutations=[];const pos=this._getNextRedoIndex();if(pos>0){this._historyStepsStates.set(this._historySteps[pos].id,'consumed');this.historyRevert(this._historySteps[pos]);this.historySetSelection(this._historySteps[pos]);const stepId=this._generateId();this._historyStepsStates.set(stepId,'redo');this.historyStep(true,{stepId});this.dispatchEvent(new Event('historyRedo'));}}
historyCanUndo(){return this._getNextUndoIndex()>0;}
historyCanRedo(){return this._getNextRedoIndex()>0;}
historySize(){return this._historySteps.length;}
historyRevert(step,{until=0,sideEffect=true}={}){for(let i=step.mutations.length-1;i>=until;i--){const mutation=step.mutations[i];if(!mutation){break;}
switch(mutation.type){case'characterData':{const node=this.idFind(mutation.id);if(node)node.textContent=mutation.oldValue;break;}
case'attributes':{const node=this.idFind(mutation.id);if(node){if(mutation.oldValue){let value=mutation.oldValue;if(typeof value==='string'&&mutation.attributeName==='class'){value=value.split(' ').filter(c=>!this.options.renderingClasses.includes(c)).join(' ');}
if(this._collabClientId){this._safeSetAttribute(node,mutation.attributeName,value);}else{node.setAttribute(mutation.attributeName,value);}}else{node.removeAttribute(mutation.attributeName);}}
break;}
case'remove':{let nodeToRemove=this.idFind(mutation.id);if(!nodeToRemove){if(!mutation.node){continue;}
nodeToRemove=this.unserializeNode(mutation.node);const fakeNode=document.createElement('fake-el');fakeNode.appendChild(nodeToRemove);DOMPurify.sanitize(fakeNode,{IN_PLACE:true,ADD_TAGS:["#document-fragment","fake-el"],ADD_ATTR:["contenteditable"],});nodeToRemove=fakeNode.childNodes[0];if(!nodeToRemove){continue;}
this.idSet(nodeToRemove);}
if(mutation.nextId&&this.idFind(mutation.nextId)?.parentElement){const node=this.idFind(mutation.nextId);node&&node.before(nodeToRemove);}else if(mutation.previousId&&this.idFind(mutation.previousId)?.parentElement){const node=this.idFind(mutation.previousId);node&&node.after(nodeToRemove);}else{const node=this.idFind(mutation.parentId);node&&node.append(nodeToRemove);}
break;}
case'add':{const node=this.idFind(mutation.id);if(node){node.remove();node.ouid=undefined;}}}}
if(sideEffect){this.historySetSelection(step);}}
withoutRollback(callback){const priorRollback=this._toRollback;callback();this.observerFlush();if(!priorRollback){this._toRollback=false;}}
historyResetLatestComputedSelection(limitToEditable){const computedSelection=limitToEditable?this._latestComputedSelectionInEditable:this._latestComputedSelection;if(computedSelection&&computedSelection.anchorNode){const anchorNode=this.idFind(computedSelection.anchorNode.oid);const focusNode=this.idFind(computedSelection.focusNode.oid)||anchorNode;if(anchorNode){setSelection(anchorNode,computedSelection.anchorOffset,focusNode,computedSelection.focusOffset,);return true;}}
return false;}
historySetSelection(step){if(step.selection&&step.selection.anchorNodeOid){const anchorNode=this.idFind(step.selection.anchorNodeOid);const focusNode=this.idFind(step.selection.focusNodeOid)||anchorNode;if(anchorNode){setSelection(anchorNode,step.selection.anchorOffset,focusNode,step.selection.focusOffset!==undefined?step.selection.focusOffset:step.selection.anchorOffset,false,);this._handleSelectionInTable();}}}
unbreakableStepUnactive(){if(this._toRollback===UNBREAKABLE_ROLLBACK_CODE){this._toRollback=false;}
this._checkStepUnbreakable=false;}
historyPauseSteps(){this._historyStepsActive=false;}
historyUnpauseSteps(){this._historyStepsActive=true;}
historyStash(){if(!this._historyStashedMutations){this._historyStashedMutations=[];}
this._historyStashedMutations.push(...this._currentStep.mutations);this._currentStep.mutations=[];}
historyUnstash(){if(!this._currentStep.mutations){this._currentStep.mutations=[];}
this._currentStep.mutations.unshift(...this._historyStashedMutations);this._historyStashedMutations=[];}
_getNodeIndexPath(node){return[node,...ancestors(node,this.editable)].map((ancestor)=>childNodeIndex(ancestor));}
_getNodeFromIndexPath(indexPath){return(indexPath.reduceRight((node,index)=>node?.childNodes?.[index],this.editable.parentElement));}
_historyClean(){this._historySteps=[];this._currentStep={selection:{anchorNodeOid:undefined,anchorOffset:undefined,focusNodeOid:undefined,focusOffset:undefined,},mutations:[],id:undefined,clientId:undefined,};this._historyStepsStates=new Map();}
_historyGetSnapshotStep(){return{selection:{anchorNode:undefined,anchorOffset:undefined,focusNode:undefined,focusOffset:undefined,},mutations:Array.from(this.editable.childNodes).map(node=>({type:'add',append:1,id:node.oid,node:this.serializeNode(node),})),id:this._generateId(),clientId:this.clientId,previousStepId:undefined,};}
_historyMakeSnapshot(){if(!this._lastSnapshotHistoryLength||this._lastSnapshotHistoryLength<this._historySteps.length){this._lastSnapshotHistoryLength=this._historySteps.length;const step=this._historyGetSnapshotStep();step.id=this._historySteps[this._historySteps.length-1].id;const snapshot={time:Date.now(),step:step,};this._historySnapshots=[snapshot,this._historySnapshots[0]];}}
_historyAddExternalStep(newStep){let index=this._historySteps.length-1;while(index>=0&&this._historySteps[index].id!==newStep.previousStepId){if(this._historySteps[index].id===newStep.id){return;}
index--;}
if(index<0){if(this.options.onHistoryMissingParentSteps){const historySteps=this._historySteps;let index=historySteps.length-1;while(index!==0){if(historySteps[index].clientId===newStep.clientId){break;}
index--;}
const fromStepId=historySteps[index].id;this.options.onHistoryMissingParentSteps({step:newStep,fromStepId:fromStepId,});}
return;}
let concurentSteps=[];index++;while(index<this._historySteps.length){if(this._historySteps[index].previousStepId===newStep.previousStepId){if(this._historySteps[index].id.localeCompare(newStep.id)===1){break;}else{concurentSteps=[this._historySteps[index].id];}}else{if(concurentSteps.includes(this._historySteps[index].previousStepId)){concurentSteps.push(this._historySteps[index].id);}else{break;}}
index++;}
const stepsAfterNewStep=this._historySteps.slice(index);for(const stepToRevert of stepsAfterNewStep.slice().reverse()){this.historyRevert(stepToRevert,{sideEffect:false});}
this.historyApply(newStep.mutations);this._historySteps.splice(index,0,newStep);for(const stepToApply of stepsAfterNewStep){this.historyApply(stepToApply.mutations);}}
collaborationSetClientId(id){this._collabClientId=id;}
onExternalHistorySteps(newSteps){if(this._postProcessExternalStepsPromise){this._externalStepsBuffer.push(...newSteps);}
this.observerUnactive();this._computeHistorySelection();let stepIndex=0;for(const newStep of newSteps){this._historyAddExternalStep(newStep);stepIndex++;this._postProcessExternalStepsPromise=this.options.postProcessExternalSteps(this.editable);if(this._postProcessExternalStepsPromise){this._postProcessExternalStepsPromise.then(()=>{this._postProcessExternalStepsPromise=undefined;this.onExternalHistorySteps(this._externalStepsBuffer);});this._externalStepsBuffer=newSteps.slice(stepIndex);break;}}
this.observerActive();this.historyResetLatestComputedSelection();this._handleCommandHint();this.multiselectionRefresh();this.dispatchEvent(new Event('onExternalHistorySteps'));}
onExternalMultiselectionUpdate(selection){const{clientId}=selection;const currentInfo=this._collabSelectionInfos.get(clientId);if(currentInfo){currentInfo.selection=selection;}else{this._collabSelectionInfos.set(clientId,{selection});}
this._drawClientSelection(selection);this._drawClientAvatar(selection);this._updateAvatarCounters();}
multiselectionRefresh(){for(const{selection}of this._collabSelectionInfos.values()){this._drawClientSelection(selection);this._drawClientAvatar(selection);}
this._updateAvatarCounters();}
_drawClientSelection({selection,color,clientId,clientName=this.options._t('Anonymous')}){this._multiselectionRemoveClient(clientId);let clientRects;let anchorNode=this.idFind(selection.anchorNodeOid);let focusNode=this.idFind(selection.focusNodeOid);let anchorOffset=selection.anchorOffset;let focusOffset=selection.focusOffset;if(!anchorNode||!focusNode){anchorNode=this.editable.children[0];focusNode=this.editable.children[0];anchorOffset=0;focusOffset=0;}
if(anchorNode.isConnected&&focusNode.isConnected){[anchorNode,anchorOffset]=getDeepestPosition(anchorNode,anchorOffset);[focusNode,focusOffset]=getDeepestPosition(focusNode,focusOffset);}else{anchorNode=this.editable.children[0];focusNode=this.editable.children[0];anchorOffset=0;focusOffset=0;}
const direction=getCursorDirection(anchorNode,anchorOffset,focusNode,focusOffset,);const range=new Range();try{if(direction===DIRECTIONS.RIGHT){range.setStart(anchorNode,anchorOffset);range.setEnd(focusNode,focusOffset);}else{range.setStart(focusNode,focusOffset);range.setEnd(anchorNode,anchorOffset);}
clientRects=Array.from(range.getClientRects());}catch{clientRects=[];}
if(!clientRects.length){return;}
const containerRect=this._selectionsContainer.getBoundingClientRect();const indicators=clientRects.map(({x,y,width,height})=>{const rectElement=this.document.createElement('div');rectElement.style=`
                position: absolute;
                top: ${y - containerRect.y}px;
                left: ${x - containerRect.x}px;
                width: ${width}px;
                height: ${height}px;
                background-color: ${color};
                opacity: 0.25;
                pointer-events: none;
            `;rectElement.setAttribute('data-selection-client-id',clientId);return rectElement;});const caretElement=this.document.createElement('div');caretElement.style=`border-left: 2px solid ${color}; position: absolute;`;caretElement.setAttribute('data-selection-client-id',clientId);caretElement.className='oe-collaboration-caret';const caretTopSquare=this.document.createElement('div');caretTopSquare.className='oe-collaboration-caret-top-square';caretTopSquare.style['background-color']=color;caretTopSquare.setAttribute('data-client-name',clientName);caretElement.append(caretTopSquare);if(direction===DIRECTIONS.LEFT){const rect=clientRects[0];caretElement.style.height=`${rect.height * 1.2}px`;caretElement.style.top=`${rect.y - containerRect.y}px`;caretElement.style.left=`${rect.x - containerRect.x}px`;}else{const rect=peek(clientRects);caretElement.style.height=`${rect.height * 1.2}px`;caretElement.style.top=`${rect.y - containerRect.y}px`;caretElement.style.left=`${rect.right - containerRect.x}px`;}
this._selectionsContainer.append(caretElement,...indicators);}
_drawClientAvatar({selection,clientId,clientAvatarUrl='',clientName=this.options._t('Anonymous')}){const anchorNode=this.idFind(selection.anchorNodeOid);const focusNode=this.idFind(selection.focusNodeOid);if(!anchorNode||!focusNode){return;}
const anchorBlock=closestBlock(anchorNode);if(!anchorBlock)return;const containerRect=this._avatarsContainer.getBoundingClientRect();const selectionInfo=this._collabSelectionInfos.get(clientId)||{};let avatarElement=selectionInfo.avatarElement;if(!avatarElement){avatarElement=this.document.createElement('div');avatarElement.className='oe-collaboration-caret-avatar';avatarElement.style.display='none';const image=this.document.createElement('img');avatarElement.append(image);image.onload=()=>avatarElement.style.removeProperty('display');image.setAttribute('src',clientAvatarUrl);image.classList.add('o_object_fit_cover');}
if(!avatarElement.parentElement){this._avatarsContainer.append(avatarElement);}
selectionInfo.avatarElement=avatarElement;selectionInfo.clientName=clientName;selectionInfo.avatarTargetElement=anchorBlock;this._collabSelectionInfos.set(clientId,selectionInfo);const anchorBlockRect=anchorBlock.getBoundingClientRect();const top=anchorBlockRect.y-containerRect.y;avatarElement.style.top=top+'px';const closestList=closestElement(anchorNode,'ul, ol');const anchorX=closestList?closestList.getBoundingClientRect().x:anchorBlockRect.x;const left=anchorX-containerRect.x-AVATAR_SIZE;avatarElement.style.left=left+'px';selectionInfo.avatarPositionKey=`${left}|${top}`;}
_updateAvatarCounters(){this._avatarsOverlaps={};for(const info of this._collabSelectionInfos.values()){const key=info.avatarPositionKey;this._avatarsOverlaps[key]=this._avatarsOverlaps[key]||new Set();this._avatarsOverlaps[key].add(info);}
this._avatarsCountersContainer.replaceChildren();for(const[overlapKey,infos]of Object.entries(this._avatarsOverlaps)){const size=infos.size;if(size>1){const[left,top]=overlapKey.split('|').map((n)=>parseInt(n,10));const div=document.createElement('div');div.className='oe-overlapping-counter';div.style.left=left+10+'px';div.style.top=top+10+'px';div.innerText=size;this._avatarsCountersContainer.append(div);}}}
multiselectionRemove(clientId){const selectionInfo=this._collabSelectionInfos.get(clientId);if(selectionInfo&&selectionInfo.avatarElement){selectionInfo.avatarElement.remove();}
this._multiselectionRemoveClient(clientId)
this._collabSelectionInfos.delete(clientId);this._updateAvatarCounters();}
_multiselectionRemoveClient(clientId){const elements=this._selectionsContainer.querySelectorAll(`[data-selection-client-id="${clientId}"]`,);for(const element of elements){element.remove();}}
execCommand(...args){this._computeHistorySelection();return this._applyCommand(...args);}
bindExecCommand(element){for(const buttonEl of element.querySelectorAll('[data-call]')){buttonEl.addEventListener('click',ev=>{const arg1=buttonEl.dataset.arg1;const args=arg1&&arg1.split(",")||[];this.execCommand(buttonEl.dataset.call,...args);this.historyResetLatestComputedSelection(true);ev.preventDefault();this._updateToolbar();});}}
deselectTable(){const tds=this.editable.querySelectorAll('.o_selected_table, .o_selected_td');if(!tds.length){return false;}
this.observerUnactive('deselectTable');for(const td of tds){td.classList.remove('o_selected_td','o_selected_table');if(!td.classList.length){td.removeAttribute('class');}}
this.observerActive('deselectTable');return true;}
activateContenteditable(){this.canActivateContentEditable=true;this._activateContenteditable();}
_removeDomListener(){for(const[element,eventName,boundCallback]of this._domListeners){element.removeEventListener(eventName,boundCallback);}
this._domListeners=[];}
deleteRange(sel){if(this.deleteTableRange()){return;}
let range=getDeepRange(this.editable,{sel,correctTripleClick:true});if(!range)return;for(const node of descendants(closestBlock(range.commonAncestorContainer))){if(node.nodeType===Node.TEXT_NODE&&[...node.textContent].every(char=>char==='\uFEFF')){const restore=prepareUpdate(...leftPos(node));node.remove();restore();}}
const columnsContainers=[];const fullRange=this.document.getSelection().getRangeAt(0);const selectionCommonAncestor=fullRange.commonAncestorContainer;if(selectionCommonAncestor.nodeType===Node.ELEMENT_NODE){const rows=selectionCommonAncestor.classList.contains("row")?[selectionCommonAncestor]:selectionCommonAncestor.getElementsByClassName("row");for(const row of rows){if(row&&row.parentElement&&row.parentElement.classList.contains("o_text_columns")){const firstColumnNode=firstLeaf(row);const lastColumnNode=lastLeaf(row);if(fullRange.isPointInRange(firstColumnNode,0)&&fullRange.isPointInRange(lastColumnNode,0)){columnsContainers.push(row.parentElement);}}}}
if(!this.editable.childElementCount){const p=document.createElement('p');p.append(document.createElement('br'));this.editable.append(p);setSelection(p,0);return;}
range=getDeepRange(this.editable,{sel,splitText:true,select:true,correctTripleClick:true,});if(!range)return;const commonAncestorContainer=this.editable.contains(range.commonAncestorContainer)?range.commonAncestorContainer:this.editable;const startUneditable=getFurthestUneditableParent(range.startContainer,commonAncestorContainer);if(startUneditable){let leaf=previousLeaf(startUneditable);if(leaf){range.setStart(leaf,nodeSize(leaf));}else{range.setStart(commonAncestorContainer,0);}}
const endUneditable=getFurthestUneditableParent(range.endContainer,commonAncestorContainer);if(endUneditable){let leaf=nextLeaf(endUneditable);if(leaf){range.setEnd(leaf,0);}else{range.setEnd(commonAncestorContainer,nodeSize(commonAncestorContainer));}}
let insertedZws;let{startContainer:start,startOffset,endContainer:end,endOffset}=range;const startBlock=closestBlock(start);const endBlock=closestBlock(end);const[firstLeafOfStartBlock,lastLeafOfEndBlock]=[firstLeaf(startBlock),lastLeaf(endBlock)];const startLink=closestElement(range.startContainer,'a');const rangeStartSameAsColumnsStart=columnsContainers.length&&firstLeaf(range.startContainer)===firstLeaf(columnsContainers[0]);if(sel&&!sel.isCollapsed&&!range.startOffset&&!range.startContainer.previousSibling&&!startLink&&!rangeStartSameAsColumnsStart){const zws=document.createTextNode('\u200B');range.startContainer.before(zws);insertedZws=zws;}
const doJoin=!(startBlock===closestBlock(range.commonAncestorContainer)&&endBlock===closestBlock(range.commonAncestorContainer))&&(startBlock.tagName!=='TD'&&endBlock.tagName!=='TD')&&!(firstLeafOfStartBlock===start&&lastLeafOfEndBlock===end);let next=nextLeaf(end,this.editable);if(isBlock(end)){next=nextLeaf(end.childNodes[endOffset],this.editable);}
if(end.nodeType===Node.TEXT_NODE){splitTextNode(end,endOffset);endOffset=nodeSize(end);}
if(start.nodeType===Node.TEXT_NODE){splitTextNode(start,startOffset);startOffset=0;}
const restoreUpdate=prepareUpdate(...boundariesOut(start).slice(0,2),...boundariesOut(end).slice(2,4),{allowReenter:false,label:'deleteRange'});if(columnsContainers.length){const firstColumnContainer=columnsContainers[0];const lastColumnContainer=columnsContainers[columnsContainers.length-1];const startsWithColumn=firstLeaf(range.startContainer)===firstLeaf(firstColumnContainer);const endsWithColumn=lastLeaf(range.endContainer)===lastLeaf(lastColumnContainer);if(startsWithColumn){range.setStart(firstColumnContainer,0);}
if(endsWithColumn){range.setEnd(lastColumnContainer,lastColumnContainer.childNodes.length);}}
const contents=range.extractContents();for(const columnsContainer of columnsContainers){if(!columnsContainer.hasChildNodes()){columnsContainer.remove();}}
const startLi=closestElement(start,'li');const endLi=closestElement(end,'li');let isBlockRemovable=false;if(startLi&&endLi&&(!startLi.textContent||isZWS(startLi))&&getListMode(startLi.parentElement)!==getListMode(endLi.parentElement)){const isNested=closestElement(startLi,'.oe-nested')
const nodeToRemove=isNested?isNested:startLi.parentNode;endLi.parentElement.prepend(startLi);isEmptyBlock(nodeToRemove)&&nodeToRemove.remove();if(endLi.textContent&&start.parentElement){start=start.parentElement;start.removeChild(start.firstChild);isBlockRemovable=true;setSelection(endLi,0);}else{setSelection(startLi,nodeSize(startLi));}}else{setSelection(start,nodeSize(start));}
if(startLi&&startLi.classList.contains('o_checked')&&['\u200B',''].includes(startLi.textContent)&&closestElement(end,'li')!==startLi){startLi.classList.remove('o_checked');}
range=getDeepRange(this.editable,{sel});[...contents.querySelectorAll('*')].filter(isUnremovable).forEach(n=>{closestBlock(range.endContainer).after(n);n.textContent='';});const isRemovableInvisible=node=>!isVisible(node)&&!isZWS(node)&&!isUnremovable(node);const endIsStart=end===start;while(end&&isRemovableInvisible(end)&&(!end.contains(range.endContainer)||end===range.endContainer)){const parent=end.parentNode;end.remove();end=parent;}
while(start&&(!isBlock(start)||isBlockRemovable)&&isRemovableInvisible(start)&&!(endIsStart&&start.contains(range.startContainer))){const parent=start.parentNode;start.remove();start=parent;}
if(start){if(start===this.editable&&startBlock.textContent==='\u200B'){const p=document.createElement('p');start.appendChild(p);start=p;}
fillEmpty(closestBlock(start));}
fillEmpty(closestBlock(range.endContainer));range=getDeepRange(this.editable,{sel});let joinWith=!isBlockRemovable&&range.endContainer;if(joinWith){const rightLeaf=rightLeafOnlyNotBlockPath(joinWith).next().value;if(rightLeaf&&rightLeaf.nodeValue===' '){joinWith=rightLeaf;}}
while(doJoin&&next&&!(next.previousSibling&&next.previousSibling===joinWith)&&!(joinWith.nodeType===Node.ELEMENT_NODE&&joinWith.contains(next)&&childNodeIndex(next)===range.endOffset)&&this.editable.contains(next)&&(closestElement(joinWith,'TD')===closestElement(next,'TD'))){const restore=preserveCursor(this.document);this.observerFlush();const res=this._protect(()=>{next.oDeleteBackward();if(!this.editable.contains(joinWith)){this._toRollback=UNREMOVABLE_ROLLBACK_CODE;}else{next=firstLeaf(next);}},this._currentStep.mutations.length);if([UNBREAKABLE_ROLLBACK_CODE,UNREMOVABLE_ROLLBACK_CODE].includes(res)){restore();break;}}
if(startBlock&&startBlock.textContent==='\u200B'&&endBlock&&startBlock!==endBlock&&!isEmptyBlock(endBlock)&&paragraphRelatedElements.includes(endBlock.nodeName)){startBlock.remove();setSelection(endBlock,0);fillEmpty(endBlock);}
if(insertedZws){const el=closestElement(insertedZws);const next=insertedZws.nextSibling;const isLineBreak=el&&el.previousElementSibling&&el.previousElementSibling.tagName==='BR';insertedZws.remove();el&&fillEmpty(el);if(isLineBreak){el.before(this.document.createElement('BR'));}
setSelection(next,0);}
if(joinWith){const el=closestElement(joinWith);el&&fillEmpty(el);}
const restoreCursor=preserveCursor(this.document);restoreUpdate();restoreCursor();}
deleteTableRange(){const selectedTds=this.editable.querySelectorAll('.o_selected_td');const fullySelectedTables=[...this.editable.querySelectorAll('.o_selected_table')].filter(table=>([...table.querySelectorAll('td')].every(td=>td.classList.contains('o_selected_td'))));if(selectedTds.length&&!fullySelectedTables.length){this.historyPauseSteps();const rows=[...closestElement(selectedTds[0],'tr').parentElement.children].filter(child=>child.nodeName==='TR');const firstRowCells=[...rows[0].children].filter(child=>child.nodeName==='TD'||child.nodeName==='TH');const areFullColumnsSelected=getRowIndex(selectedTds[0])===0&&getRowIndex(selectedTds[selectedTds.length-1])===rows.length-1;const areFullRowsSelected=getColumnIndex(selectedTds[0])===0&&getColumnIndex(selectedTds[selectedTds.length-1])===firstRowCells.length-1;if(areFullColumnsSelected||areFullRowsSelected){if(areFullColumnsSelected){const startIndex=getColumnIndex(selectedTds[0]);let endIndex=getColumnIndex(selectedTds[selectedTds.length-1]);let currentIndex=startIndex;while(currentIndex<=endIndex){this.execCommand('removeColumn',firstRowCells[currentIndex]);currentIndex++;}}
if(areFullRowsSelected){const startIndex=getRowIndex(selectedTds[0]);let endIndex=getRowIndex(selectedTds[selectedTds.length-1]);let currentIndex=startIndex;while(currentIndex<=endIndex){this.execCommand('removeRow',rows[currentIndex]);currentIndex++;}}}else{for(const td of selectedTds){[...td.childNodes].forEach(child=>child.remove());td.append(document.createElement('br'));}}
this.historyUnpauseSteps();this.historyStep();return true;}else if(fullySelectedTables.length){fullySelectedTables.forEach(table=>table.remove());}
this._toggleTableUi();return false;}
updateColorpickerLabels(params={}){function hexFromColor(color){if(isColorGradient(color)){color=color.match(/gradient(.*)/)[0];let r=0,g=0,b=0,count=0;for(const entry of color.matchAll(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)/g)){count++;r+=parseInt(entry[1],10);g+=parseInt(entry[2],10);b+=parseInt(entry[3],10);}
color=`rgb(${Math.round(r / count)}, ${Math.round(g / count)}, ${Math.round(b / count)})`;}
return rgbToHex(color);}
let foreColor=params.foreColor;let hiliteColor=params.hiliteColor;const sel=this.document.getSelection();if(sel.rangeCount&&(!foreColor||!hiliteColor)){const endContainer=closestElement(sel.getRangeAt(0).endContainer);const computedStyle=getComputedStyle(endContainer);const backgroundImage=computedStyle.backgroundImage;const hasGradient=isColorGradient(backgroundImage);const hasTextGradientClass=endContainer.classList.contains('text-gradient');if(!foreColor){if(hasGradient&&hasTextGradientClass){foreColor=backgroundImage;}else{foreColor=this.document.queryCommandValue('foreColor');}}
if(!hiliteColor){if(hasGradient&&!hasTextGradientClass){hiliteColor=backgroundImage;}else{let ancestor=endContainer;while(ancestor&&!hiliteColor){hiliteColor=ancestor.style.backgroundColor;ancestor=ancestor.parentElement;}
if(!hiliteColor){hiliteColor=this.document.queryCommandValue('backColor');}}}}
foreColor=hexFromColor(foreColor);this.toolbar.style.setProperty('--fore-color',foreColor);const foreColorInput=this.toolbar.querySelector('#foreColor input');if(foreColorInput){foreColorInput.value=foreColor;}
hiliteColor=hexFromColor(hiliteColor);this.toolbar.style.setProperty('--hilite-color',hiliteColor);const hiliteColorInput=this.toolbar.querySelector('#hiliteColor input');if(hiliteColorInput){hiliteColorInput.value=hiliteColor.length<=7?hiliteColor:hexFromColor(hiliteColor);}}
_applyRawCommand(method,...args){const sel=this.document.getSelection();if(sel.anchorNode&&isProtected(sel.anchorNode)){return;}
if(!(SELECTIONLESS_COMMANDS.includes(method)&&args.length)&&!this.isSelectionInEditable(sel)&&!(closestElement(sel.anchorNode,"*[t-field],*[t-out],*[t-esc]")&&FORMATTING_COMMANDS.includes(method))){return false;}
if(!sel.isCollapsed&&BACKSPACE_FIRST_COMMANDS.includes(method)){let range=getDeepRange(this.editable,{sel,splitText:true,select:true,correctTripleClick:true});if(range&&range.startContainer===range.endContainer&&range.endContainer.nodeType===Node.TEXT_NODE&&ZERO_WIDTH_CHARS.includes(range.cloneContents().textContent)){sel.collapseToStart();if(BACKSPACE_ONLY_COMMANDS.includes(method)){this._applyRawCommand(method);}
return;}
this.deleteRange(sel);if(BACKSPACE_ONLY_COMMANDS.includes(method)){return true;}}
this.options.beforeAnyCommand();if(editorCommands[method]){return editorCommands[method](this,...args);}
if(method.startsWith('justify')){const mode=method.split('justify').join('').toLocaleLowerCase();return this._align(mode==='full'?'justify':mode);}
return sel.anchorNode[method](sel.anchorOffset,...args);}
_applyCommand(...args){this._recordHistorySelection(true);const result=this._protect(()=>this._applyRawCommand(...args));this.historyStep();this._handleCommandHint();return result;}
_protect(callback,rollbackCounter){try{const result=callback.call(this);this.observerFlush();if(this._toRollback){const torollbackCode=this._toRollback;this.historyRollback(rollbackCounter);return torollbackCode;}else{return result;}}catch(error){if(error===UNBREAKABLE_ROLLBACK_CODE||error===UNREMOVABLE_ROLLBACK_CODE){this.historyRollback(rollbackCounter);return error;}else{throw error;}}}
_activateContenteditable(){this.observerUnactive('activateContenteditable');this.editable.setAttribute('contenteditable',this.options.isRootEditable);const editableAreas=this.options.getContentEditableAreas(this);for(const node of editableAreas){if(!node.isContentEditable){if(isArtificialVoidElement(node)||node.nodeName==='IMG'){node.classList.add('o_editable_media');}else{node.setAttribute('contenteditable',true);if(!isBlock(node)&&node.textContent==="\u200b"){node.setAttribute('data-oe-zws-empty-inline','');}}}}
for(const node of this.options.getReadOnlyAreas()){node.setAttribute('contenteditable',false);}
for(const element of this.options.getUnremovableElements()){element.classList.add("oe_unremovable");}
this.observerActive('activateContenteditable');}
_stopContenteditable(){this.observerUnactive('_stopContenteditable');if(this.options.isRootEditable){this.editable.setAttribute('contenteditable',!this.options.isRootEditable);}
for(const node of this.options.getContentEditableAreas(this)){if(node.getAttribute('contenteditable')==='true'){node.setAttribute('contenteditable',false);}}
this.observerActive('_stopContenteditable');}
_handleSelectionInTable(ev=undefined){const selection=this.document.getSelection();const anchorNode=selection&&selection.rangeCount&&selection.getRangeAt(0)&&selection.anchorNode;if(anchorNode&&!ancestors(anchorNode).includes(this.editable)){return false;}
const traversedNodes=getTraversedNodes(this.editable);if(this._isResizingTable||!traversedNodes.some(node=>!!closestElement(node,'td')&&!isProtected(node))){return false;}
let range;if(this.isFirefox){if(selection.rangeCount>1){this.historyResetLatestComputedSelection(true);}else if(ev&&closestElement(ev.target,'table')===closestElement(selection.anchorNode,'table')&&closestElement(ev.target,'td')!==closestElement(selection.focusNode,'td')){setSelection(selection.anchorNode,selection.anchorOffset,ev.target,0);}
range=getDeepRange(this.editable,{correctTripleClick:anchorNode&&anchorNode.nodeName==='TR'});}else{range=getDeepRange(this.editable);}
const startTd=closestElement(range.startContainer,'td');const endTd=closestElement(range.endContainer,'td');let appliedCustomSelection=false;const startTable=ancestors(range.startContainer,this.editable).filter(node=>node.nodeName==='TABLE').pop();const endTable=ancestors(range.endContainer,this.editable).filter(node=>node.nodeName==='TABLE').pop();if(startTd!==endTd&&startTable===endTable){if(!isProtected(startTable)){this._selectTableCells(range);appliedCustomSelection=true;}}else if(!traversedNodes.every(node=>node.parentElement&&closestElement(node.parentElement,'table'))&&!selection.isCollapsed){this.observerUnactive('handleSelectionInTable');const traversedTables=new Set(traversedNodes.map((node)=>closestElement(node,"table")).filter((node)=>!isProtected(node)));for(const table of traversedTables){if(table&&!ancestors(table,this.editable).some(node=>[...traversedTables].includes(node))){table.classList.toggle('o_selected_table',true);for(const td of[...table.querySelectorAll('td')].filter(td=>closestElement(td,'table')===table)){td.classList.toggle('o_selected_td',true);}
appliedCustomSelection=true;}}
this.observerActive('handleSelectionInTable');}else if(ev&&startTd&&!isProtected(startTd)){const selectedNodes=getSelectedNodes(this.editable);const cellContents=descendants(startTd);const areCellContentsFullySelected=cellContents.filter(d=>!isBlock(d)).every(child=>selectedNodes.includes(child));if(areCellContentsFullySelected){const SENSITIVITY=5;const rangeRect=range.getBoundingClientRect();const isMovingAwayFromSelection=ev.clientX>rangeRect.x+rangeRect.width+SENSITIVITY||ev.clientX<rangeRect.x-SENSITIVITY;if(isMovingAwayFromSelection){this._selectTableCells(range);appliedCustomSelection=true;}}else if(cellContents.filter(isBlock).every(isEmptyBlock)&&Math.abs(ev.clientX-(this._lastMouseClickPosition?this._lastMouseClickPosition[0]:ev.clientX))>=15){this._selectTableCells(range);appliedCustomSelection=true;}}
return appliedCustomSelection;}
_selectTableCells(range){const table=closestElement(range.commonAncestorContainer,'table');if(!table){return;}
this.observerUnactive('_selectTableCells');const alreadyHadSelection=table.classList.contains('o_selected_table');this.deselectTable();table.classList.toggle('o_selected_table',true);const columns=[...table.querySelectorAll('td')].filter(td=>closestElement(td,'table')===table);const startCol=[range.startContainer,...ancestors(range.startContainer,this.editable)].find(node=>node.nodeName==='TD'&&closestElement(node,'table')===table)||columns[0];const endCol=[range.endContainer,...ancestors(range.endContainer,this.editable)].find(node=>node.nodeName==='TD'&&closestElement(node,'table')===table)||columns[columns.length-1];const[startRow,endRow]=[closestElement(startCol,'tr'),closestElement(endCol,'tr')];const[startColIndex,endColIndex]=[getColumnIndex(startCol),getColumnIndex(endCol)];const[startRowIndex,endRowIndex]=[getRowIndex(startRow),getRowIndex(endRow)];const[minRowIndex,maxRowIndex]=[Math.min(startRowIndex,endRowIndex),Math.max(startRowIndex,endRowIndex)];const[minColIndex,maxColIndex]=[Math.min(startColIndex,endColIndex),Math.max(startColIndex,endColIndex)];const grid=[...table.querySelectorAll('tr')].filter(tr=>closestElement(tr,'table')===table).map(tr=>[...tr.children].filter(child=>child.nodeName==='TD'));for(const tds of grid.filter((_,index)=>index>=minRowIndex&&index<=maxRowIndex)){for(const td of tds.filter((_,index)=>index>=minColIndex&&index<=maxColIndex)){td.classList.toggle('o_selected_td',true);}}
if(!alreadyHadSelection){this.toolbarShow();}
this.observerActive('_selectTableCells');}
_isHoveringTdBorder(ev){if(ev.target&&ev.target.nodeName==='TD'&&ev.target.isContentEditable){const SENSITIVITY=5;const targetRect=ev.target.getBoundingClientRect();if(ev.clientX<=targetRect.x+SENSITIVITY){return'left';}else if(ev.clientY<=targetRect.y+SENSITIVITY){return'top';}else if(ev.clientX>=targetRect.x+ev.target.clientWidth-SENSITIVITY){return'right';}else if(ev.clientY>=targetRect.y+ev.target.clientHeight-SENSITIVITY){return'bottom';}}
return false;}
_toggleTableResizeCursor(direction){this.editable.classList.remove('o_col_resize','o_row_resize');if(direction==='col'){this.editable.classList.add('o_col_resize');}else if(direction==='row'){this.editable.classList.add('o_row_resize');}}
_resizeTable(ev,direction,target1,target2){ev.preventDefault();let position=target1?(target2?'middle':'last'):'first';let[item,neighbor]=[target1||target2,target2];const table=closestElement(item,'table');const[sizeProp,positionProp,clientPositionProp]=direction==='col'?['width','x','clientX']:['height','y','clientY'];const isRTL=this.options.direction==="rtl";if(sizeProp==='width'){const tableRect=table.getBoundingClientRect();table.style[sizeProp]=tableRect[sizeProp]+'px';}
const unsizedItemsSelector=`${direction === 'col' ? 'td' : 'tr'}:not([style*=${sizeProp}])`;for(const unsizedItem of table.querySelectorAll(unsizedItemsSelector)){unsizedItem.style[sizeProp]=unsizedItem.getBoundingClientRect()[sizeProp]+'px';}
if(direction==='col'){let hostCell=closestElement(table,'td');const hostCells=[];while(hostCell){hostCells.push(hostCell);hostCell=closestElement(hostCell.parentElement,'td');}
const nthColumn=getColumnIndex(item);const firstRow=[...table.querySelector('tr').children];[item,neighbor]=[firstRow[nthColumn],firstRow[nthColumn+1]];for(const td of hostCells){if(td!==item&&td!==neighbor&&closestElement(td,'table')===table&&getColumnIndex(td)!==0){td.style.removeProperty(sizeProp);}}
if(isRTL&&position=="middle"){[item,neighbor]=[neighbor,item];}}
const MIN_SIZE=33;switch(position){case'first':{const marginProp=direction==='col'?(isRTL?'marginRight':'marginLeft'):'marginTop';const itemRect=item.getBoundingClientRect();const tableStyle=getComputedStyle(table);const currentMargin=pxToFloat(tableStyle[marginProp]);let sizeDelta=itemRect[positionProp]-ev[clientPositionProp];if(direction==='col'&&isRTL){sizeDelta=ev[clientPositionProp]-itemRect[positionProp]-itemRect[sizeProp];}
const newMargin=currentMargin-sizeDelta;const currentSize=itemRect[sizeProp];const newSize=currentSize+sizeDelta;if(newMargin>=0&&newSize>MIN_SIZE){const tableRect=table.getBoundingClientRect();const hostCell=closestElement(table.parentElement,'td');const childTable=item.querySelector('table');const endProp=isRTL?'left':'right'
if(direction==='col'&&(hostCell&&tableRect[endProp]+sizeDelta>hostCell.getBoundingClientRect()[endProp]-5||childTable&&childTable.getBoundingClientRect()[endProp]>itemRect[endProp]+sizeDelta-5)){break;}
table.style[marginProp]=newMargin+'px';item.style[sizeProp]=newSize+'px';if(sizeProp==='width'){table.style[sizeProp]=tableRect[sizeProp]+sizeDelta+'px';}}
break;}
case'middle':{const[itemRect,neighborRect]=[item.getBoundingClientRect(),neighbor.getBoundingClientRect()];const[currentSize,newSize]=[itemRect[sizeProp],ev[clientPositionProp]-itemRect[positionProp]];const editableStyle=getComputedStyle(this.editable);const sizeDelta=newSize-currentSize;const currentNeighborSize=neighborRect[sizeProp];const newNeighborSize=currentNeighborSize-sizeDelta;const enclosingCell=closestElement(table,"td, th");const containerWidth=enclosingCell?.getBoundingClientRect().width||this.editable.clientWidth;const maxWidth=containerWidth-pxToFloat(editableStyle.paddingLeft)-pxToFloat(editableStyle.paddingRight);const tableRect=table.getBoundingClientRect();if(newSize>MIN_SIZE&&(direction==='row'||newNeighborSize>MIN_SIZE||tableRect[sizeProp]+sizeDelta<maxWidth)){const childTable=item.querySelector('table');if(direction==='col'&&childTable&&childTable.getBoundingClientRect().right>itemRect.right+sizeDelta-5){break}
item.style[sizeProp]=newSize+'px';if(direction==='col'){neighbor.style[sizeProp]=(newNeighborSize>MIN_SIZE?newNeighborSize:currentNeighborSize)+'px';}else if(sizeProp==='width'){table.style[sizeProp]=tableRect[sizeProp]+sizeDelta+'px';}}
break;}
case'last':{const itemRect=item.getBoundingClientRect();let sizeDelta=ev[clientPositionProp]-(itemRect[positionProp]+itemRect[sizeProp]);if(direction==='col'&&isRTL){sizeDelta=itemRect[positionProp]-ev[clientPositionProp];}
const currentSize=itemRect[sizeProp];const newSize=currentSize+sizeDelta;if((newSize>=0||direction==='row')&&newSize>MIN_SIZE){const tableRect=table.getBoundingClientRect();const hostCell=closestElement(table.parentElement,'td');const childTable=item.querySelector('table');const endProp=isRTL?'left':'right'
if(direction==='col'&&(hostCell&&tableRect[endProp]+sizeDelta>hostCell.getBoundingClientRect()[endProp]-5||childTable&&childTable.getBoundingClientRect()[endProp]>itemRect[endProp]+sizeDelta-5)){break}
if(sizeProp==='width'){table.style[sizeProp]=tableRect[sizeProp]+sizeDelta+'px';}
item.style[sizeProp]=newSize+'px';}
break;}}}
_toggleTableUi(row=false,column=false){if(row){this._rowUi.style.visibility='visible';this._rowUiTarget=row;this._positionTableUi(row);}else{this._rowUi.style.visibility='hidden';}
if(column){this._columnUi.style.visibility='visible';this._columnUiTarget=column;this._positionTableUi(column);}else{this._columnUi.style.visibility='hidden';}
if(row||column){this._tableUiTarget=closestElement(row||column,'table');this._tableUiTarget&&this._tableUiTarget.addEventListener('mouseleave',()=>this._toggleTableUi(),{once:true});}}
_positionTableUi(element){if(!element.isConnected){return;}
const tableUiContainerRect=this._tableUiContainer.getBoundingClientRect();const isRtl=this.options.direction==='rtl';const isRow=element.nodeName==='TR';const ui=isRow?this._rowUi:this._columnUi;const elementRect=element.getBoundingClientRect();const wrappedUi=ui.firstElementChild;const table=closestElement(element,'table');const tableRect=table&&table.getBoundingClientRect();const resetTableSize=ui.querySelector('.o_reset_table_size');if(table&&!table.hasAttribute('style')){resetTableSize.classList.add('d-none');}else{resetTableSize.classList.remove('d-none');}
let left;let top;if(isRow){if(isRtl){left=tableRect.right-tableUiContainerRect.x;}else{left=elementRect.left-tableUiContainerRect.left-wrappedUi.clientWidth;}}else if(isRtl){left=elementRect.left-tableUiContainerRect.left+wrappedUi.clientWidth;}else{left=elementRect.left-tableUiContainerRect.left-(isRow?wrappedUi.clientWidth:0);}
top=elementRect.top-tableUiContainerRect.top-(isRow?0:wrappedUi.clientHeight);ui.style.left=left+'px';ui.style.top=top+'px';wrappedUi.style[isRow?'height':'width']=elementRect[isRow?'height':'width']+'px';}
_computeHistorySelection(){const sel=this.document.getSelection();if(!(sel&&sel.anchorNode)){return this._latestComputedSelection;}
this._latestComputedSelection={anchorNode:sel.anchorNode,anchorOffset:sel.anchorOffset,focusNode:sel.focusNode,focusOffset:sel.focusOffset,};if(this.isSelectionInEditable(sel)){this._latestComputedSelectionInEditable=this._latestComputedSelection;}
return this._latestComputedSelection;}
_recordHistorySelection(useCache=false){this._currentStep.selection=serializeSelection(useCache?this._latestComputedSelection:this._computeHistorySelection(),)||{};}
_isLatestComputedSelectionInsideEmptyInlineTag(){if(!this._latestComputedSelection){return false;}
const anchorNode=this._latestComputedSelection.anchorNode;const focusNode=this._latestComputedSelection.focusNode;const parentTextContent=anchorNode.parentElement?anchorNode.parentElement.textContent:null;return anchorNode===focusNode&&(['',...ZERO_WIDTH_CHARS].includes(parentTextContent))}
_getNextUndoIndex(){for(let index=this._historySteps.length-1;index>=0;index--){if(this._historySteps[index]&&this._historySteps[index].clientId===this._collabClientId){const state=this._historyStepsStates.get(this._historySteps[index].id);if(state==='redo'||!state){return index;}}}
return-1;}
_getNextRedoIndex(){let totalConsumed=0;for(let index=this._historySteps.length-1;index>=0;index--){if(this._historySteps[index]&&this._historySteps[index].clientId===this._collabClientId){const state=this._historyStepsStates.get(this._historySteps[index].id);switch(state){case'undo':return totalConsumed<=0?index:-1;case'redo':totalConsumed-=1;break;case'consumed':totalConsumed+=1;break;default:return-1;}}}
return-1;}
historyRevertUntil(toStepIndex){const lastStep=this._currentStep;this.historyRevert(lastStep);let stepIndex=this._historySteps.length-1;while(stepIndex>toStepIndex){const step=this._historySteps[stepIndex];const stepState=this._historyStepsStates.get(step.id);if(step.clientId===this._collabClientId&&stepState!=='consumed'){this.historyRevert(this._historySteps[stepIndex]);this._historyStepsStates.set(''+step.id,'consumed');}
stepIndex--;}}
toolbarHide(){this._updateToolbar(false);}
toolbarShow(){this._updateToolbar(true);}
_updateToolbar(show){if(!this.toolbar){return;}
if(!this.autohideToolbar&&this.toolbar.style.visibility!=='visible'){this.toolbar.style.visibility='visible';}
const sel=this.document.getSelection();if(sel===null){return;}
if(!hasTableSelection(this.editable)){if(this.editable.classList.contains('o_col_resize')||this.editable.classList.contains('o_row_resize')){show=false;}
if(!sel.anchorNode){show=false;}else{const selAncestors=[sel.anchorNode,...ancestors(sel.anchorNode,this.editable)];const isInStars=selAncestors.some(node=>node.classList&&node.classList.contains('o_stars'));if(isInStars){show=false;}}}
if(this.autohideToolbar&&!this.toolbar.contains(sel.anchorNode)){if(!this.isMobile){if(this.powerboxTablePicker.el.style.display==='block'){this.toolbar.style.visibility='hidden';return;}
if(show!==undefined){this.toolbar.style.visibility=show?'visible':'hidden';}
if(show===false){for(const menu of this.toolbar.querySelectorAll('.dropdown-menu.show')){menu.parentElement?.querySelector('[data-bs-toggle="dropdown"]')?.click();};return;}}}
const unlinkButton=this.toolbar.querySelector('#unlink');if(!this.isSelectionInEditable(sel)){unlinkButton?.classList.add('d-none');return;}
const paragraphDropdownButton=this.toolbar.querySelector('#paragraphDropdownButton');if(paragraphDropdownButton){for(const commandState of['justifyLeft','justifyRight','justifyCenter','justifyFull',]){const button=this.toolbar.querySelector('#'+commandState);const direction=commandState==='justifyFull'?'justify':commandState.replace('justify','').toLowerCase();let isStateTrue=false;const link=sel.anchorNode&&closestElement(sel.anchorNode,'a');const linkBlock=link&&closestBlock(link);if(linkBlock){const alignment=getComputedStyle(linkBlock).textAlign;isStateTrue=alignment===direction;}else{isStateTrue=this.document.queryCommandState(commandState)}
button.classList.toggle('active',isStateTrue);const newClass=`fa-align-${direction}`;paragraphDropdownButton.classList.toggle(newClass,isStateTrue);}}
if(sel.rangeCount){for(const format of['bold','italic','underline','strikeThrough','switchDirection']){const formatButton=this.toolbar.querySelector(`#${format.toLowerCase()}`);if(formatButton){formatButton.classList.toggle('active',isSelectionFormat(this.editable,format));}}
const fontSizeEl=this.toolbar.querySelector("#fontSizeCurrentValue");if(fontSizeEl){fontSizeEl.value=Math.round(getFontSizeDisplayValue(sel,this.options.getCSSVariableValue,this.options.convertNumericToUnit));}
const table=getInSelection(this.document,'table');const toolbarButton=this.toolbar.querySelector('.toolbar-edit-table');if(toolbarButton){this.toolbar.querySelector('.toolbar-edit-table').style.display=table?'block':'none';}
const selectionText=sel.toString().replace(/\s+/g,"");const translateDropdown=this.toolbar.querySelector('#translate');if(translateDropdown){const translateDropdownBtn=translateDropdown.querySelector('.btn');if(sel.isCollapsed){translateDropdown.style.display='none';}else{translateDropdown.style.display='';translateDropdownBtn.classList[!selectionText?'add':'remove']('disabled');}}
const chatGptBtn=this.toolbar.querySelector('#open-chatgpt.btn');if(chatGptBtn&&!sel.isCollapsed){chatGptBtn.classList[!selectionText?'add':'remove']('disabled');}}
this.updateColorpickerLabels();const listUIClasses={UL:'fa-list-ul',OL:'fa-list-ol',CL:'fa-tasks'};const block=closestBlock(sel.anchorNode);let activeLabel=undefined;for(const[style,cssSelector,isList]of[['paragraph','p:not(.small, .lead, .o_small)',false],['pre','pre',false],['heading1','h1:not(.display-1, .display-2, .display-3, .display-4)',false],['heading2','h2',false],['heading3','h3',false],['heading4','h4',false],['heading5','h5',false],['heading6','h6',false],['display-1','h1.display-1',false],['display-2','h1.display-2',false],['display-3','h1.display-3',false],['display-4','h1.display-4',false],['blockquote','blockquote',false],['small','.small, .o_small',false],['light','.lead',false],['unordered','UL',true],['ordered','OL',true],['checklist','CL',true],]){const button=this.toolbar.querySelector('#'+style);if(button&&!block){button.classList.toggle('active',false);}else if(button){const isActive=isList?block.tagName==='LI'&&getListMode(block.parentElement)===cssSelector:block.matches(cssSelector);button.classList.toggle('active',isActive);if(!isList&&isActive){activeLabel=button.textContent;}}}
if(block){const listMode=getListMode(block.parentElement);const listDropdownButton=this.toolbar.querySelector('#listDropdownButton');if(listDropdownButton){if(listMode){listDropdownButton.classList.remove('fa-list-ul','fa-list-ol','fa-tasks');listDropdownButton.classList.add(listUIClasses[listMode]);}
listDropdownButton.closest('button').classList.toggle('active',block.tagName==='LI');}}
const styleSection=this.toolbar.querySelector('#style');if(styleSection){if(!activeLabel){const firstButtonEl=styleSection.querySelector('#paragraph');firstButtonEl.classList.add('active');activeLabel=firstButtonEl.textContent;}
styleSection.querySelector('button span').textContent=activeLabel;}
const isInMedia=this.toolbar.classList.contains('oe-media');const linkNode=getInSelection(this.document,'a');const linkButton=this.toolbar.querySelector('#create-link');const transformButton=this.toolbar.querySelector("#image-transform");linkButton&&linkButton.classList.toggle('active',!!linkNode);unlinkButton?.classList.toggle('d-none',isInMedia||!linkNode);const undoButton=this.toolbar.querySelector('#undo');undoButton&&undoButton.classList.toggle('disabled',!this.historyCanUndo());const redoButton=this.toolbar.querySelector('#redo');redoButton&&redoButton.classList.toggle('disabled',!this.historyCanRedo());const range=getDeepRange(this.editable,{sel,correctTripleClick:true});const spansBlocks=[...range.commonAncestorContainer.childNodes].some(isBlock);linkButton?.classList.toggle('d-none',spansBlocks||isInMedia);if(this.options.disableTransform){transformButton.classList.add("d-none");}
const linkBtnGroup=this.toolbar.querySelector('#link.btn-group');linkBtnGroup?.classList.toggle('d-none',!linkBtnGroup.querySelector('.btn:not(.d-none)'));if(this.autohideToolbar&&!this.isMobile&&!this.toolbar.contains(sel.anchorNode)){this._positionToolbar();}}
updateToolbarPosition(){if(this.autohideToolbar&&!this.isMobile&&getComputedStyle(this.toolbar).visibility==='visible'){this._positionToolbar();}}
_positionToolbar(){const OFFSET=10;const BASELINE_MARGIN=5;let isBottom=false;this.toolbar.classList.toggle('d-none',false);this.toolbar.style.maxWidth=window.innerWidth-OFFSET*2+'px';const sel=this.document.getSelection();if(!sel.rangeCount){return;}
const range=sel.getRangeAt(0);const isSelForward=sel.anchorNode===range.startContainer&&sel.anchorOffset===range.startOffset;const startRect=range.startContainer.getBoundingClientRect&&range.startContainer.getBoundingClientRect();const selRect=range.getBoundingClientRect();const isSelectionPotentiallyBugged=[selRect.x,selRect.y,selRect.width,selRect.height].every(x=>x===0);let correctedSelectionRect=isSelectionPotentiallyBugged&&startRect?startRect:selRect;const selAncestors=[sel.anchorNode,...ancestors(sel.anchorNode,this.editable)];const selectedTable=selAncestors.find(node=>node.classList&&node.classList.contains('o_selected_table'));if(selectedTable){correctedSelectionRect=selectedTable.getBoundingClientRect();}
const toolbarWidth=this.toolbar.offsetWidth;const toolbarHeight=this.toolbar.offsetHeight;const editorRect=this.editable.getBoundingClientRect();const parentContextRect=this.options.getContextFromParentRect();const scrollContainerRect=this.options.getScrollContainerRect();const editorTopPos=Math.max(0,editorRect.top);const scrollX=document.defaultView.scrollX;const scrollY=document.defaultView.scrollY;const rangeRects=[...range.getClientRects()];const rangeSpansMultipleLines=rangeRects.length>1&&rangeRects.at(-1).bottom-rangeRects[0].bottom>BASELINE_MARGIN;let left=isSelForward||rangeSpansMultipleLines?correctedSelectionRect.left-OFFSET:correctedSelectionRect.right+OFFSET-toolbarWidth;left=Math.max(OFFSET,left);left=Math.min(window.innerWidth-OFFSET-toolbarWidth,left);const adjustedLeft=left+parentContextRect.left;this.toolbar.style.left=scrollX+adjustedLeft+'px';let top=correctedSelectionRect.top-toolbarHeight-OFFSET;if(top<editorTopPos||top+parentContextRect.top-scrollContainerRect.top<OFFSET/2){top=correctedSelectionRect.bottom+OFFSET;isBottom=true;}
top+=parentContextRect.top;this.toolbar.style.top=scrollY+top+'px';const hasArrow=!(rangeSpansMultipleLines||this.toolbar.classList.contains('oe-media'));this.toolbar.classList.toggle('noarrow',!hasArrow);let toolbarTop=top;let toolbarBottom=top+toolbarHeight;if(hasArrow){let arrowLeftPos=(isSelForward&&!isSelectionPotentiallyBugged?correctedSelectionRect.right:correctedSelectionRect.left)-left-OFFSET;arrowLeftPos=Math.max(OFFSET,arrowLeftPos);arrowLeftPos=Math.min(toolbarWidth-OFFSET-20,arrowLeftPos);this.toolbar.style.setProperty('--arrow-left-pos',arrowLeftPos+'px');const arrowTopPos=isBottom?-17:toolbarHeight-3;this.toolbar.classList.toggle('toolbar-bottom',isBottom);this.toolbar.style.setProperty('--arrow-top-pos',arrowTopPos+'px');toolbarTop=Math.min(top,top+arrowTopPos);toolbarBottom=Math.max(toolbarBottom,top+arrowTopPos+20);}
const distToScrollContainer=Math.min(toolbarTop-scrollContainerRect.top,scrollContainerRect.bottom-toolbarBottom);const isToolbarOverflow=distToScrollContainer<OFFSET/2;if(isToolbarOverflow){this.toolbar.style.top=`${(Math.max(selRect.top, scrollContainerRect.top) + OFFSET)}px`}}
_prepareClipboardData(clipboardData){const container=document.createElement('fake-container');container.append(parseHTML(this.document,clipboardData));for(const tableElement of container.querySelectorAll('table')){tableElement.classList.add('table','table-bordered','o_table');}
const progId=container.querySelector('meta[name="ProgId"]')
if(progId&&progId.content==='Excel.Sheet'){const xlStylesheet=container.querySelector('style');const xlNodes=container.querySelectorAll("[class*=xl],[class*=font]");for(const xlNode of xlNodes){for(const xlClass of xlNode.classList){const xlStyle=xlStylesheet.textContent.match(`.${xlClass}[^\{]*\{(?<xlStyle>[^\}]*)\}`).groups.xlStyle.replace('background:','background-color:');xlNode.setAttribute('style',xlNode.style.cssText+';'+xlStyle)}}}
for(const child of[...container.childNodes]){this._cleanForPaste(child);}
const fragment=document.createDocumentFragment();let p=document.createElement('p');for(const child of[...container.childNodes]){if(isBlock(child)){if(p.childNodes.length>0){fragment.appendChild(p);p=document.createElement('p');}
fragment.appendChild(child);}else{p.appendChild(child);}
if(p.childNodes.length>0){fragment.appendChild(p);}}
const brs=fragment.querySelectorAll('br');for(const br of brs){const block=closestBlock(br);if(['P','H1','H2','H3','H4','H5','H6'].includes(block.nodeName)&&!block.closest('li')){const isEmptyLine=block.firstChild.nodeName==='BR';const remainingBrContainer=splitAroundUntil(br,block);if(!isEmptyLine){remainingBrContainer.remove();}}}
return fragment;}
_cleanForPaste(node){if(!this._isWhitelisted(node)||this._isBlacklisted(node)||node.id&&node.id.startsWith('docs-internal-guid')){if(!node.matches||node.matches(CLIPBOARD_BLACKLISTS.remove.join(','))){node.remove();}else{let childNodes;if(node.nodeName==='DIV'&&[...node.childNodes].every(n=>!isBlock(n))){const dir=node.getAttribute('dir');const p=this.document.createElement('p');if(dir){p.setAttribute('dir',dir);}
p.append(...node.childNodes);node.replaceWith(p);childNodes=p.childNodes;}else{childNodes=unwrapContents(node);}
for(const child of childNodes){this._cleanForPaste(child);}}}else if(node.nodeType!==Node.TEXT_NODE){if(node.nodeName==="THEAD"){const tbody=node.nextElementSibling;if(tbody){tbody.prepend(...node.children);node.remove();node=tbody;}else{node=setTagName(node,"TBODY");}}else if(node.nodeName==="TH"){node=setTagName(node,"TD");}
if(node.nodeName==='TD'){if(node.hasAttribute('bgcolor')&&!node.style['background-color']){node.style['background-color']=node.getAttribute('bgcolor');}}else if(node.nodeName==='FONT'){if(node.hasAttribute('color')&&!node.style['color']){node.style['color']=node.getAttribute('color');}
if(node.hasAttribute('size')&&!node.style['font-size']){node.style['font-size']=+node.getAttribute('size')+10+'pt';}}else if(['S','U'].includes(node.nodeName)&&node.childNodes.length===1&&node.firstChild.nodeName==='FONT'){const fontNode=node.firstChild;node.before(fontNode);node.replaceChildren(...fontNode.childNodes);fontNode.appendChild(node);}else if(node.nodeName==='IMG'&&node.getAttribute('aria-roledescription')==='checkbox'){const checklist=node.closest('ul');const closestLi=node.closest('li');if(checklist){checklist.classList.add('o_checklist');if(node.getAttribute('alt')==='checked'){closestLi.classList.add('o_checked');}
node.remove();node=checklist;}}
for(const attribute of[...node.attributes]){if(CLIPBOARD_WHITELISTS.styledTags.includes(node.nodeName)&&attribute.name==='style'){node.removeAttribute(attribute.name);if(['SPAN','FONT'].includes(node.tagName)){for(const unwrappedNode of unwrapContents(node)){this._cleanForPaste(unwrappedNode);}}}else if(!this._isWhitelisted(attribute)){node.removeAttribute(attribute.name);}}
for(const klass of[...node.classList]){if(!this._isWhitelisted(klass)){node.classList.remove(klass);}}
for(const child of[...node.childNodes]){this._cleanForPaste(child);}}}
_isWhitelisted(item){if(item&&item.nodeType===Node.ATTRIBUTE_NODE){return CLIPBOARD_WHITELISTS.attributes.includes(item.name);}else if(typeof item==='string'){return CLIPBOARD_WHITELISTS.classes.some(okClass=>okClass instanceof RegExp?okClass.test(item):okClass===item,);}else{return(item.nodeType===Node.TEXT_NODE||(item.matches&&item.matches(CLIPBOARD_WHITELISTS.nodes)));}}
_isBlacklisted(node){return(node.nodeType!==Node.TEXT_NODE&&node.matches([].concat(...Object.values(CLIPBOARD_BLACKLISTS)).join(',')));}
_safeSetAttribute(node,attributeName,attributeValue){const clone=document.createElement(node.tagName);clone.setAttribute(attributeName,attributeValue);DOMPurify.sanitize(clone,{IN_PLACE:true,ADD_TAGS:["#document-fragment","fake-el"],ADD_ATTR:["contenteditable"],});if(clone.hasAttribute(attributeName)){node.setAttribute(attributeName,clone.getAttribute(attributeName));}else{node.removeAttribute(attributeName);}}
disableAvatarForElement(element){this.enableAvatars();for(const info of this._collabSelectionInfos.values()){if(info.avatarTargetElement===element){if(!info.avatarElement.classList.contains('opacity-0')){info.avatarElement.classList.add('opacity-0');}}}}
enableAvatars(){for(const element of this._avatarsContainer.querySelectorAll('.oe-collaboration-caret-avatar.opacity-0')){element.classList.remove('opacity-0');}}
_onBeforeInput(ev){this._lastBeforeInputType=ev.inputType;if(ev.inputType==="insertParagraph"){const banner=closestElement(ev.target,".o_editor_banner");if(banner&&closestElement(banner,"ul, ol")){ev.preventDefault();this._onInput(ev);return;}}}
_onInput(ev){const newSelection=this.document.getSelection();if(newSelection.anchorNode&&isProtected(newSelection.anchorNode)){return;}
const shouldOpenPowerbox=newSelection.isCollapsed&&newSelection.rangeCount&&ev.data==='/'&&this.powerbox&&!this.powerbox.isOpen&&(!this.options.getPowerboxElement||!!this.options.getPowerboxElement());if(shouldOpenPowerbox){this._powerboxBeforeStepIndex=this._historySteps.length-1;}
this._recordHistorySelection(true);const selection=this._currentStep.selection;const{anchorNodeOid,anchorOffset,focusNodeOid,focusOffset}=selection||{};const wasCollapsed=!selection||(focusNodeOid===anchorNodeOid&&focusOffset===anchorOffset);const isChromeDeleteforward=ev.inputType==='insertText'&&ev.data===null&&this._lastBeforeInputType==='deleteContentForward';const isChromeInsertParagraph=ev.inputType==='insertText'&&ev.data===null&&this._lastBeforeInputType==='insertParagraph';const isCompositionEvent=ev.inputType==="insertCompositionText"||(ev.inputType==="insertText"&&(this.keyboardType===KEYBOARD_TYPES.VIRTUAL||this.isMobile));if(isCompositionEvent){this._fromCompositionText=true;}
if(this.keyboardType===KEYBOARD_TYPES.PHYSICAL||!wasCollapsed){const anchorNode=this.idFind(anchorNodeOid);const focusNode=this.idFind(focusNodeOid);const wasSelectingAcrossDifferentBlocks=anchorNode&&focusNode&&closestBlock(anchorNode)!==closestBlock(focusNode);const shouldInterveneForDeletion=!this._fromCompositionText||wasSelectingAcrossDifferentBlocks;if(ev.inputType==='deleteContentBackward'&&shouldInterveneForDeletion){this._compositionStep();this.historyRollback();ev.preventDefault();this._applyCommand('oDeleteBackward');}else if((ev.inputType==='deleteContentForward'||isChromeDeleteforward)&&shouldInterveneForDeletion){this._compositionStep();this.historyRollback();ev.preventDefault();this._applyCommand('oDeleteForward');}else if((['insertParagraph','insertLineBreak'].includes(ev.inputType)||isChromeInsertParagraph)){this._compositionStep();this.historyRollback();ev.preventDefault();this._handleAutomaticLinkInsertion();const deepRange=getDeepRange(this.editable,{correctTripleClick:true});const startEl=deepRange&&closestElement(deepRange.startContainer);const endEl=deepRange&&closestElement(deepRange.endContainer);if(startEl&&endEl&&startEl.isContentEditable&&endEl.isContentEditable){const{startContainer,startOffset,endContainer,endOffset}=deepRange;const direction=getCursorDirection(newSelection.anchorNode,newSelection.anchorOffset,newSelection.focusNode,newSelection.focusOffset);if(direction===DIRECTIONS.RIGHT){setSelection(startContainer,startOffset,endContainer,endOffset);}else{setSelection(endContainer,endOffset,startContainer,startOffset);}}
const anchorTD=closestElement(newSelection.anchorNode,'.o_selected_td');const focusTD=closestElement(newSelection.focusNode,'.o_selected_td');if(anchorTD&&focusTD&&closestElement(anchorTD,'table')===closestElement(focusTD,'table')){this.deselectTable();setSelection(anchorTD.firstChild,0,anchorTD.lastChild,nodeSize(anchorTD.lastChild));}
if(ev.inputType==='insertLineBreak'||this._applyCommand('oEnter')===UNBREAKABLE_ROLLBACK_CODE){this._applyCommand('oShiftEnter');}}else if(['insertText','insertCompositionText'].includes(ev.inputType)){const selection=this.document.getSelection();const isUnitTests=!ev.isTrusted&&this.testMode;const latestSelectionInsideEmptyTag=this._isLatestComputedSelectionInsideEmptyInlineTag();const shouldInterveneForInsertion=!wasCollapsed&&shouldInterveneForDeletion;if(shouldInterveneForInsertion||latestSelectionInsideEmptyTag||isUnitTests){ev.preventDefault();if(!isUnitTests){this._protect(()=>this._applyRawCommand('oDeleteBackward'));}
if(latestSelectionInsideEmptyTag){const selectionBackup=this._latestComputedSelection;setSelection(selectionBackup.anchorNode,selectionBackup.anchorOffset);}
insertText(selection,ev.data===null?ev.dataTransfer.getData('text/plain'):ev.data);selection.collapseToEnd();}
const blockEl=closestBlock(selection.anchorNode);const stringToConvert=blockEl.textContent.substring(0,selection.anchorOffset);const shouldCreateNumberList=(/^(?:[1aA])[.)]\s$/).test(stringToConvert);const shouldCreateBulletList=(/^[-*]\s$/).test(stringToConvert);if(ev.data==='`'&&!closestElement(selection.anchorNode,'code')){const range=getDeepRange(this.editable);let textNode=range.startContainer;let offset=range.startOffset;let sibling=textNode.previousSibling;while(sibling&&sibling.nodeType===Node.TEXT_NODE){offset+=sibling.textContent.length;sibling.textContent+=textNode.textContent;textNode.remove();textNode=sibling;sibling=textNode.previousSibling;}
sibling=textNode.nextSibling;while(sibling&&sibling.nodeType===Node.TEXT_NODE){textNode.textContent+=sibling.textContent;sibling.remove();sibling=textNode.nextSibling;}
setSelection(textNode,offset);const textHasTwoTicks=/`.*`/.test(textNode.textContent);if(textHasTwoTicks&&textNode.textContent.replace(/`/g,'').length){this.historyStep();const insertedBacktickIndex=offset-1;const textBeforeInsertedBacktick=textNode.textContent.substring(0,insertedBacktickIndex-1);let startOffset,endOffset;const isClosingForward=textBeforeInsertedBacktick.includes('`');if(isClosingForward){startOffset=textBeforeInsertedBacktick.lastIndexOf('`');endOffset=insertedBacktickIndex;}else{const textAfterInsertedBacktick=textNode.textContent.substring(offset);startOffset=insertedBacktickIndex;endOffset=offset+textAfterInsertedBacktick.indexOf('`');}
if(endOffset&&endOffset<textNode.textContent.length){splitTextNode(textNode,endOffset+1,DIRECTIONS.LEFT);}
if(startOffset){splitTextNode(textNode,startOffset);}
textNode.textContent=textNode.textContent.substring(1,textNode.textContent.length-1);const codeElement=this.document.createElement('code');codeElement.classList.add('o_inline_code');textNode.before(codeElement);codeElement.append(textNode);if(!codeElement.previousSibling||codeElement.previousSibling.nodeType!==Node.TEXT_NODE){codeElement.before(document.createTextNode('\u200B'));}
if(isClosingForward){codeElement.after(document.createTextNode('\u200B'));setSelection(codeElement.nextSibling,1);}else{setSelection(codeElement.firstChild,0);}}}else if((shouldCreateNumberList||shouldCreateBulletList)&&!closestElement(selection.anchorNode,'li')){this.historyStep();const range=selection.getRangeAt(0);range.setStartBefore(blockEl.firstChild);range.extractContents();fillEmpty(blockEl);this.historyPauseSteps();if(shouldCreateNumberList){this._applyCommand('toggleList','OL');const[deepsetNode]=getDeepestPosition(selection.anchorNode,selection.anchorOffset);const closestOl=closestElement(deepsetNode,'OL');if(stringToConvert.startsWith('A')){closestOl.style.listStyle='upper-alpha';}else if(stringToConvert.startsWith('a')){closestOl.style.listStyle='lower-alpha';}}else if(shouldCreateBulletList){this._applyCommand('toggleList','UL');}
this.historyUnpauseSteps();}
this.historyStep();}else{this.historyStep();}}
if(!isCompositionEvent){this._fromCompositionText=false;}
if(shouldOpenPowerbox){this._isPowerboxOpenOnInput=true;this.powerbox.open();}}
_onClipboardCut(clipboardEvent){this._onClipboardCopy(clipboardEvent);this._recordHistorySelection();this.deleteRange();this.historyStep();}
_onClipboardCopy(clipboardEvent){if(!this.isSelectionInEditable()){return;}
clipboardEvent.preventDefault();const selection=this.document.getSelection();const range=selection.getRangeAt(0);let rangeContent=range.cloneContents();if(!rangeContent.hasChildNodes()){return;}
if(rangeContent.firstChild.nodeName==='LI'){const list=range.commonAncestorContainer.cloneNode();list.replaceChildren(...rangeContent.childNodes);rangeContent=list;}
if(rangeContent.firstChild.nodeName==='TR'||rangeContent.firstChild.nodeName==='TD'){const table=closestElement(range.commonAncestorContainer,'table');const tableClone=table.cloneNode(true);const isTableFullySelected=table.parentElement&&!!closestElement(table.parentElement,'td.o_selected_td')||[...table.querySelectorAll('td')].filter(td=>closestElement(td,'table')===table).every(td=>td.classList.contains('o_selected_td'));if(!isTableFullySelected){for(const td of tableClone.querySelectorAll('td:not(.o_selected_td)')){if(closestElement(td,'table')===tableClone){td.remove();}}
const trsWithoutTd=Array.from(tableClone.querySelectorAll('tr')).filter(row=>!row.querySelector('td'));for(const tr of trsWithoutTd){if(closestElement(tr,'table')===tableClone){tr.remove();}}}
rangeContent=tableClone;}
const startTable=closestElement(range.startContainer,'table');if(rangeContent.firstChild.nodeName==='TABLE'&&startTable){rangeContent.firstChild.after(startTable.cloneNode(true));rangeContent.firstChild.remove();}
const endTable=closestElement(range.endContainer,'table');if(rangeContent.lastChild.nodeName==='TABLE'&&endTable){rangeContent.lastChild.before(endTable.cloneNode(true));rangeContent.lastChild.remove();}
const commonAncestorElement=closestElement(range.commonAncestorContainer);if(commonAncestorElement&&!isBlock(rangeContent.firstChild)){const blockEl=closestBlock(commonAncestorElement);const ancestorsList=[commonAncestorElement,...ancestors(commonAncestorElement,blockEl)];for(const ancestor of ancestorsList){if(!isBlock(ancestor)||paragraphRelatedElements.includes(ancestor.nodeName)){const clone=ancestor.cloneNode();clone.append(...rangeContent.childNodes);rangeContent.appendChild(clone);}}}
const dataHtmlElement=document.createElement('data');dataHtmlElement.append(rangeContent);const odooHtml=dataHtmlElement.innerHTML.replace(/\uFEFF/g,"");const odooText=selection.toString().replace(/\uFEFF/g,"").replace(/\u00A0/g," ");clipboardEvent.clipboardData.setData('text/plain',odooText);clipboardEvent.clipboardData.setData('text/html',odooHtml);clipboardEvent.clipboardData.setData('text/odoo-editor',odooHtml);}
_onKeyDown(ev){delete this._isNavigatingByMouse;const selection=this.document.getSelection();if((!selection?.anchorNode)||(isProtected(selection.anchorNode))){return;}
if(this.document.querySelector(".transfo-container")){ev.preventDefault();return;}
this.keyboardType=ev.key==='Unidentified'?KEYBOARD_TYPES.VIRTUAL:KEYBOARD_TYPES.PHYSICAL;this._currentKeyPress=ev.key;if(/^.$/u.test(ev.key)&&!ev.ctrlKey&&!ev.metaKey&&(isMacOS()||!ev.altKey)){const selection=this.document.getSelection();if(selection&&!selection.isCollapsed&&this.isSelectionInEditable(selection)){this.deleteRange(selection);}}
if(ev.key==='Backspace'){const selection=this.document.getSelection();if(!ev.ctrlKey&&!ev.metaKey){if(selection.isCollapsed&&!this._fromCompositionText){ev.preventDefault();this._applyCommand('oDeleteBackward');}}else if(selection.isCollapsed&&selection.anchorNode){const anchor=(selection.anchorNode.nodeType!==Node.TEXT_NODE&&selection.anchorOffset)?selection.anchorNode[selection.anchorOffset]:selection.anchorNode;const element=closestBlock(anchor);if(isEmptyBlock(element)&&element.parentElement.children.length===1){ev.preventDefault();if(element.tagName!=='P'){const paragraph=this.document.createElement('P');const br=this.document.createElement('BR');paragraph.append(br);element.before(paragraph);const result=this._protect(()=>element.remove());if(result!==UNBREAKABLE_ROLLBACK_CODE&&result!==UNREMOVABLE_ROLLBACK_CODE){setCursorStart(paragraph);this.historyStep();}}}}}else if(ev.key==='Tab'){const tabHtml='<span class="oe-tabs" contenteditable="false">\u0009</span>\u200B';const sel=this.document.getSelection();const closestUnbreakable=closestElement(sel.anchorNode,isUnbreakable);const closestTableOrLi=closestElement(sel.anchorNode,'table, li');const closestUnbreakableOrLi=closestElement(sel.anchorNode,["li",closestUnbreakable?.nodeName].join(","));if(closestTableOrLi&&closestTableOrLi.nodeName==='TABLE'){this._onTabulationInTable(ev);}else if(!ev.shiftKey&&sel.isCollapsed&&closestUnbreakableOrLi?.nodeName!=='LI'){this.execCommand('insert',parseHTML(this.document,tabHtml));}else{const listItems=new Set();const nonListItems=new Set();for(const node of getTraversedNodes(this.editable)){const closestLi=closestElement(node,'li');const target=closestLi||node;if(!(target.querySelector&&target.querySelector('li'))){if(closestLi){listItems.add(closestLi);}else{nonListItems.add(node);}}}
const restore=preserveCursor(this.document);for(const listItem of listItems){if(ev.shiftKey){listItem.oShiftTab(0);}else{listItem.oTab(0);}}
if(ev.shiftKey){const editorTabs=new Set([...nonListItems].map(node=>{const block=closestBlock(node);return descendants(block).find(child=>isEditorTab(child));}).filter(node=>(node&&!getAdjacentPreviousSiblings(node).some(sibling=>(sibling.nodeType===Node.TEXT_NODE&&!/^[\u200B\s]*$/.test(sibling.textContent))))));for(const tab of editorTabs){let{anchorNode,anchorOffset,focusNode,focusOffset}=sel;const updateAnchor=anchorNode===tab.nextSibling;const updateFocus=focusNode===tab.nextSibling;let zwsRemoved=0;while(tab.nextSibling&&tab.nextSibling.nodeType===Node.TEXT_NODE&&tab.nextSibling.textContent.startsWith('\u200B')){splitTextNode(tab.nextSibling,1,DIRECTIONS.LEFT);tab.nextSibling.remove();zwsRemoved++;}
if(updateAnchor||updateFocus){setSelection(updateAnchor?tab.nextSibling:anchorNode,updateAnchor?Math.max(0,anchorOffset-zwsRemoved):anchorOffset,updateFocus?tab.nextSibling:focusNode,updateFocus?Math.max(0,focusOffset-zwsRemoved):focusOffset);}
tab.remove();};}else{const tab=parseHTML(this.document,tabHtml);for(const block of new Set([...nonListItems].map(node=>closestBlock(node)).filter(node=>node))){block.prepend(tab.cloneNode(true));}
restore();}
this.historyStep();}
ev.preventDefault();ev.stopPropagation();}else if(ev.key===' '){this._handleAutomaticLinkInsertion();}else if(IS_KEYBOARD_EVENT_UNDO(ev)){ev.preventDefault();ev.stopPropagation();this.historyUndo();}else if(IS_KEYBOARD_EVENT_REDO(ev)){ev.preventDefault();ev.stopPropagation();this.historyRedo();}else if(IS_KEYBOARD_EVENT_BOLD(ev)){ev.preventDefault();ev.stopPropagation();this.execCommand('bold');this.historyResetLatestComputedSelection(true);}else if(IS_KEYBOARD_EVENT_ITALIC(ev)){ev.preventDefault();ev.stopPropagation();this.execCommand('italic');this.historyResetLatestComputedSelection(true);}else if(IS_KEYBOARD_EVENT_UNDERLINE(ev)){ev.preventDefault();ev.stopPropagation();this.execCommand('underline');this.historyResetLatestComputedSelection(true);}else if(IS_KEYBOARD_EVENT_STRIKETHROUGH(ev)){ev.preventDefault();ev.stopPropagation();this.execCommand('strikeThrough');this.historyResetLatestComputedSelection(true);}else if(IS_KEYBOARD_EVENT_LEFT_ARROW(ev)||IS_KEYBOARD_EVENT_RIGHT_ARROW(ev)){const isRTL=this.options.direction==='rtl';const previousName=isRTL?'next':'previous';const nextName=isRTL?'previous':'next';const side=ev.key==='ArrowLeft'?previousName:nextName;const selection=this.document.getSelection();let{anchorNode,anchorOffset,focusNode,focusOffset}=selection||{};if(ev.shiftKey){const isFocusContentEditable=focusNode.isContentEditable;if(focusNode.nodeType===Node.ELEMENT_NODE){getDeepRange(this.editable,{selection,select:!isFocusContentEditable,correctTripleClick:!isFocusContentEditable});}
({anchorNode,anchorOffset,focusNode,focusOffset}=selection)
const currentBlock=closestBlock(focusNode);const isAtBoundary=side==='previous'?firstLeaf(currentBlock)===focusNode&&focusOffset===0:lastLeaf(currentBlock)===focusNode&&focusOffset===nodeSize(focusNode);const adjacentBlock=side==='previous'?currentBlock.previousElementSibling:currentBlock.nextElementSibling;const targetBlock=side==='previous'?adjacentBlock?.previousElementSibling:adjacentBlock?.nextElementSibling;if(!adjacentBlock?.isContentEditable&&targetBlock&&isAtBoundary){const leafNode=lastLeaf(targetBlock);const offset=side==='previous'?nodeSize(leafNode):0;selection.extend(leafNode,offset);ev.preventDefault();}}
const codeElement=anchorNode&&closestElement(anchorNode,'code');const siblingProperty=`${side}Sibling`;if(codeElement?.classList.contains('o_inline_code')&&((side==='previous'&&!anchorOffset)||(side==='next'&&anchorOffset===nodeSize(anchorNode)))&&codeElement[siblingProperty]?.nodeType!==Node.TEXT_NODE&&!isZWS(codeElement[siblingProperty])){codeElement[side==='previous'?'before':'after'](document.createTextNode('\u200B'));setSelection(codeElement[siblingProperty],side==='previous'?0:1);}else{let didSkipFeff=false;let adjacentCharacter=getAdjacentCharacter(this.editable,side);let previousSelection;const hasSelectionChanged=(oldSelection={})=>{const newSelection=this.document.getSelection();return(oldSelection.anchorNode!==newSelection.anchorNode||oldSelection.anchorOffset!==newSelection.anchorOffset||oldSelection.focusNode!==newSelection.focusNode||oldSelection.focusOffset!==newSelection.focusOffset);};while(ZERO_WIDTH_CHARS.includes(adjacentCharacter)&&hasSelectionChanged(previousSelection)){const selection=this.document.getSelection();previousSelection={anchorNode:selection.anchorNode,anchorOffset:selection.anchorOffset,focusNode:selection.focusNode,focusOffset:selection.focusOffset,};selection.modify(ev.shiftKey?'extend':'move',side==='previous'?'backward':'forward','character',);didSkipFeff=didSkipFeff||adjacentCharacter==='\ufeff';adjacentCharacter=getAdjacentCharacter(this.editable,side);}
if(didSkipFeff&&!ev.shiftKey){ev.preventDefault();ev.stopPropagation();}}}else if((IS_KEYBOARD_EVENT_UP_ARROW(ev)||IS_KEYBOARD_EVENT_DOWN_ARROW(ev))&&ev.shiftKey){const selection=this.document.getSelection();const isFocusContentEditable=selection.focusNode.isContentEditable;if(selection.focusNode.nodeType===Node.ELEMENT_NODE){getDeepRange(this.editable,{selection,select:!isFocusContentEditable,correctTripleClick:!isFocusContentEditable});}
const currentBlock=closestBlock(selection.focusNode);const isAtBoundary=ev.key==='ArrowUp'?firstLeaf(currentBlock)===selection.focusNode&&selection.focusOffset===0:lastLeaf(currentBlock)===selection.focusNode&&selection.focusOffset===nodeSize(selection.focusNode);const adjacentBlock=ev.key==='ArrowUp'?currentBlock.previousElementSibling:currentBlock.nextElementSibling;const targetBlock=ev.key==='ArrowUp'?adjacentBlock?.previousElementSibling:adjacentBlock?.nextElementSibling;if(!adjacentBlock?.isContentEditable&&targetBlock&&isAtBoundary){const leafNode=lastLeaf(targetBlock);const offset=ev.key==='ArrowUp'?nodeSize(leafNode):0;selection.extend(leafNode,offset);ev.preventDefault();}}}
_onSelectionChange(){const currentKeyPress=this._currentKeyPress;delete this._currentKeyPress;const selection=this.document.getSelection();if(!selection){return;}
const startTd=closestElement(selection.anchorNode,'.o_selected_td');const endTd=closestElement(selection.focusNode,'.o_selected_td');if(!(startTd&&startTd===endTd)||currentKeyPress){this.deselectTable();}
const anchorNode=selection.anchorNode;const isSelectionInEditable=this.isSelectionInEditable(selection);if(this._isNavigatingByMouse&&selection.isCollapsed&&isSelectionInEditable){delete this._isNavigatingByMouse;const{startContainer,startOffset,endContainer,endOffset}=getDeepRange(this.editable);const linkElement=closestElement(startContainer,"a");if(linkElement&&linkElement.textContent.startsWith("\uFEFF")&&linkElement.textContent.endsWith("\uFEFF")){const linkDescendants=descendants(linkElement);const isCursorAtStartOfLink=isZwnbsp(startContainer)?linkDescendants.indexOf(startContainer)===0:startContainer.nodeType===Node.TEXT_NODE&&linkDescendants.indexOf(startContainer)===1&&startOffset===0;const isCursorAtEndOfLink=isZwnbsp(endContainer)?linkDescendants.indexOf(endContainer)===linkDescendants.length-1:endContainer.nodeType===Node.TEXT_NODE&&linkDescendants.indexOf(endContainer)===linkDescendants.length-2&&endOffset===nodeSize(endContainer);if(isCursorAtStartOfLink||isCursorAtEndOfLink){const block=closestBlock(linkElement);const linkIndex=[...block.childNodes].indexOf(linkElement);setSelection(block,isCursorAtStartOfLink?linkIndex-1:linkIndex+2);}}}
if(selection.isCollapsed&&anchorNode===this.editable&&!this.options.allowInlineAtRoot){this._fixSelectionOnEditableRoot(selection,currentKeyPress);return;}
if(selection.rangeCount&&selection.getRangeAt(0)){this._handleSelectionInTable();}
if(!hasTableSelection(this.editable)){this._updateToolbar(!selection.isCollapsed&&isSelectionInEditable);}
if(!isSelectionInEditable){return;}
if(selection.anchorNode===this.editable&&selection.focusNode===this.editable&&selection.anchorOffset===0&&selection.focusOffset===[...this.editable.childNodes].length){getDeepRange(this.editable,{select:true});return;}
this._resetLinkInSelection();this._computeHistorySelection();if(this._currentMouseState==='mouseup'){this._fixFontAwesomeSelection();}
if(selection.rangeCount&&selection.getRangeAt(0)&&this.options.onCollaborativeSelectionChange){this.options.onCollaborativeSelectionChange(this.getCurrentCollaborativeSelection());}}
_resetLinkInSelection(){const selection=this.document.getSelection();const[anchorLink,focusLink]=[selection?.anchorNode,selection?.focusNode].map(node=>closestElement(node,'a:not(.btn)'));const isSingleLinkInSelection=anchorLink&&anchorLink===focusLink&&isLinkEligibleForZwnbsp(this.editable,anchorLink);if(isSingleLinkInSelection){this.observerUnactive('add.o_link_in_selection');anchorLink.classList.add('o_link_in_selection');this.observerActive('add.o_link_in_selection');}
for(const link of this.editable.querySelectorAll('.o_link_in_selection')){if(link!==anchorLink){this.observerUnactive('remove.o_link_in_selection');link.classList.remove('o_link_in_selection');this.observerActive('remove.o_link_in_selection');}};}
isSelectionInEditable(selection){selection=selection||this.document.getSelection();if(selection&&selection.anchorNode&&selection.focusNode){const anchorElement=closestElement(selection.anchorNode);const focusElement=closestElement(selection.focusNode);return anchorElement&&anchorElement.isContentEditable&&focusElement&&focusElement.isContentEditable&&this.editable.contains(selection.anchorNode)&&this.editable.contains(selection.focusNode);}else{return false;}}
isSelectionInBlockRoot(){const selection=this.document.getSelection();let selectionInBlockRoot;let currentNode=closestElement(selection.anchorNode);while(!currentNode.classList.contains('o_editable')&&!currentNode.classList.contains('odoo-editor-editable')&&!selectionInBlockRoot){selectionInBlockRoot=isBlock(currentNode);currentNode=currentNode.parentElement;}
return!!selectionInBlockRoot;}
_compositionStep(){if(this._fromCompositionText){this._fromCompositionText=false;this.sanitize();this.historyStep();}}
getCurrentCollaborativeSelection(){const selection=this._latestComputedSelection||this._computeHistorySelection();return{selection:selection?serializeSelection(selection):{anchorNodeOid:undefined,anchorOffset:undefined,focusNodeOid:undefined,focusOffset:undefined,},color:this._collabSelectionColor,clientId:this._collabClientId,clientAvatarUrl:this._collabClientAvatarUrl,};}
clean(){this.observerUnactive();this.cleanForSave();this.observerActive();}
initElementForEdition(element=this.editable){const orphanInlineChildNodes=[...element.childNodes].find((n)=>!isBlock(n)&&(n.nodeType===Node.ELEMENT_NODE||n.textContent.trim()!==""));if(orphanInlineChildNodes&&!this.options.allowInlineAtRoot){const childNodes=[...element.childNodes];const tempEl=document.createElement('temp-container');let currentP=document.createElement('p');currentP.style.marginBottom='0';do{const node=childNodes.shift();const nodeIsBlock=isBlock(node);const nodeIsBR=node.nodeName==='BR';if(!(nodeIsBlock||(nodeIsBR&&currentP.childNodes.length))){currentP.append(node);}
if(nodeIsBlock||nodeIsBR||childNodes.length===0){if(currentP.childNodes.length&&currentP.innerHTML.trim()!==''){tempEl.append(currentP);}
currentP=currentP.cloneNode();if(nodeIsBlock){tempEl.append(node);}}}while(childNodes.length)
element.replaceChildren(...tempEl.childNodes);}
for(const el of element.querySelectorAll('[contenteditable="false"]')){el.setAttribute('data-oe-keep-contenteditable','');}
for(const el of element.querySelectorAll('.oe-tabs')){el.setAttribute('contenteditable','false');}}
cleanForSave(element=this.editable){for(const hint of element.querySelectorAll('.oe-hint')){hint.classList.remove('oe-hint','oe-command-temporary-hint');if(hint.classList.length===0){hint.removeAttribute('class');}
hint.removeAttribute('placeholder');}
this._pluginCall('cleanForSave',[element]);const allWhitespaceRegex=/^[\s\u200b]*$/;for(const emptyElement of[...element.querySelectorAll('[data-oe-zws-empty-inline]')].reverse()){emptyElement.removeAttribute('data-oe-zws-empty-inline');const isEmptyArch=emptyElement.getAttribute("data-oe-field")==="arch"&&emptyElement.textContent==="\u200b";if((!allWhitespaceRegex.test(emptyElement.textContent)||emptyElement.hasAttribute("data-oe-field"))&&!isEmptyArch){cleanZWS(emptyElement);}else if(!emptyElement.classList.length){emptyElement.remove();}}
const protectedNodes=element.querySelectorAll('[data-oe-transient-content="true"], [data-oe-transient-content=""]');for(const node of protectedNodes){node.replaceChildren();}
sanitize(element);for(const link of element.querySelectorAll('.o_link_in_selection')){link.classList.remove('o_link_in_selection');}
for(const node of descendants(element)){if(node.nodeType===Node.TEXT_NODE&&node.textContent.includes('\uFEFF')){const restore=prepareUpdate(...leftPos(node));node.textContent=node.textContent.replaceAll('\uFEFF','');restore();}}
for(const link of element.querySelectorAll('a')){if(![...link.childNodes].some(isVisible)&&!link.classList.length){link.remove();}}
for(const el of element.querySelectorAll('[contenteditable="false"]')){if(!el.hasAttribute('data-oe-keep-contenteditable')){el.removeAttribute('contenteditable');}}
for(const el of element.querySelectorAll('[data-oe-keep-contenteditable]')){el.removeAttribute('data-oe-keep-contenteditable');}
for(const el of element.querySelectorAll(ICON_SELECTOR)){cleanZWS(el);}
if(this.deselectTable()&&hasValidSelection(this.editable)){this.document.getSelection().collapseToStart();}
for(const el of element.querySelectorAll('*[class=""]')){el.removeAttribute('class');}
for(const el of element.querySelectorAll('b[data-oe-field][data-oe-type="html"]')){const blockEl=this.document.createElement('div');for(const attr of el.attributes){blockEl.setAttribute(attr.name,attr.value);}
blockEl.replaceChildren(...el.childNodes);el.replaceWith(blockEl);}}
_handleCommandHint(){const selection=this.document.getSelection();const anchorNode=selection.anchorNode;if(isProtected(anchorNode)){return;}
const selectors={BLOCKQUOTE:this.options._t('Empty quote'),H1:this.options._t('Heading 1'),H2:this.options._t('Heading 2'),H3:this.options._t('Heading 3'),H4:this.options._t('Heading 4'),H5:this.options._t('Heading 5'),H6:this.options._t('Heading 6'),LI:this.options._t('List'),};for(const hint of this.editable.querySelectorAll('.oe-hint')){if(hint.classList.contains('oe-command-temporary-hint')||!isEmptyBlock(hint)||hint.querySelector('T[t-out]')){this.observerUnactive();hint.classList.remove('oe-hint','oe-command-temporary-hint');if(hint.dataset.oeEditPlaceholder){hint.setAttribute("placeholder",hint.dataset.oeEditPlaceholder);if(hint.innerText.trim().length===0){hint.classList.add("oe-hint");}}else{hint.removeAttribute("placeholder");}
if(hint.classList.length===0){hint.removeAttribute('class');}
this.observerActive();}}
const block=this.options.getPowerboxElement();if(block&&!this.options.isHintBlacklisted(block)){if(block.nodeName in selectors&&this.options.showEmptyElementHint){this._makeHint(block,selectors[block.nodeName],true);}else if(block.nodeName==='P'||block.nodeName==='DIV'){this._makeHint(block,this.options._t('Type "/" for commands'),true);}}
const sel=this.document.getSelection();if(this.editable.textContent.trim()===''&&this.options.placeholder&&this.editable.firstChild&&this.editable.firstChild.innerHTML&&!this.editable.contains(sel.focusNode)){this._makeHint(this.editable.firstChild,this.options.placeholder,true);}}
_makeHint(block,text,temporary=false){const content=block&&block.innerHTML.trim();if(block&&(content===''||content==='<br>')&&!block.querySelector('T[t-out],[t-field]')&&ancestors(block,this.editable).includes(this.editable)){this.observerUnactive();block.setAttribute('placeholder',text);block.classList.add('oe-hint');if(temporary){block.classList.add('oe-command-temporary-hint');}
this.observerActive();}}
_fixSelectionOnEditableRoot(selection,currentKeyPress){if(!this.editable.isContentEditable){return;}
let nodeAfterCursor=this.editable.childNodes[selection.anchorOffset];let nodeBeforeCursor=nodeAfterCursor&&nodeAfterCursor.previousElementSibling;if(currentKeyPress==='ArrowRight'||currentKeyPress==='ArrowDown'){while(nodeAfterCursor&&isNotAllowedContent(nodeAfterCursor)){nodeAfterCursor=nodeAfterCursor.nextElementSibling;}
if(nodeAfterCursor){setSelection(...getDeepestPosition(nodeAfterCursor,0));}else{this.historyResetLatestComputedSelection(true);}}else if(currentKeyPress==='ArrowLeft'||currentKeyPress==='ArrowUp'){while(nodeBeforeCursor&&isNotAllowedContent(nodeBeforeCursor)){nodeBeforeCursor=nodeBeforeCursor.previousElementSibling;}
if(nodeBeforeCursor){setSelection(...getDeepestPosition(nodeBeforeCursor,nodeSize(nodeBeforeCursor)));}else{this.historyResetLatestComputedSelection(true);}}else if(nodeAfterCursor&&paragraphRelatedElements.includes(nodeAfterCursor.nodeName)){setCursorStart(nodeAfterCursor);}else if(nodeBeforeCursor&&paragraphRelatedElements.includes(nodeBeforeCursor.nodeName)){setCursorEnd(nodeBeforeCursor);}else if(this._currentMouseState==='mousedown'){this._recordHistorySelection(true);const p=this.document.createElement('p');p.append(this.document.createElement('br'));if(!nodeAfterCursor){this.editable.append(p);}else if(!nodeBeforeCursor){this.editable.prepend(p);}else{nodeAfterCursor.before(p);}
setCursorStart(p);this.historyStep();}else{selection.removeAllRanges();}}
_onMouseup(ev){this._currentMouseState=ev.type;this._fixFontAwesomeSelection();}
_onMouseDown(ev){this._currentMouseState=ev.type;this._isNavigatingByMouse=true;this._lastMouseClickPosition=[ev.x,ev.y];if(this.canActivateContentEditable){this._activateContenteditable();}
this.observer.takeRecords();const selection=this.document.getSelection();if(!selection.isCollapsed){const range=selection.getRangeAt(0);const rangeContentChildNodes=range.cloneContents().childNodes;if(rangeContentChildNodes.length===1&&rangeContentChildNodes[0].nodeName==='BR'){setSelection(selection.anchorNode,0,selection.anchorNode,0);}}
const node=ev.target;if(node.tagName=='LI'&&getListMode(node.parentElement)=='CL'){const beforStyle=window.getComputedStyle(node,':before');const style1={left:parseInt(beforStyle.getPropertyValue('left'),10),top:parseInt(beforStyle.getPropertyValue('top'),10),}
style1.right=style1.left+parseInt(beforStyle.getPropertyValue('width'),10);style1.bottom=style1.top+parseInt(beforStyle.getPropertyValue('height'),10);const isMouseInsideCheckboxBox=ev.offsetX>=style1.left&&ev.offsetX<=style1.right&&ev.offsetY>=style1.top&&ev.offsetY<=style1.bottom;if(isMouseInsideCheckboxBox){toggleClass(node,'o_checked');this.historyStep();if(!document.getSelection().isCollapsed){this._updateToolbar(true);}}}
const isStar=el=>el.nodeType===Node.ELEMENT_NODE&&(el.classList.contains('fa-star')||el.classList.contains('fa-star-o'));if(isStar(node)&&node.parentElement&&node.parentElement.className.includes('o_stars')){const previousStars=getAdjacentPreviousSiblings(node,isStar);const nextStars=getAdjacentNextSiblings(node,isStar);if(nextStars.length||previousStars.length){const shouldToggleOff=node.classList.contains('fa-star')&&(!nextStars[0]||!nextStars[0].classList.contains('fa-star'));for(const star of[...previousStars,node]){star.classList.toggle('fa-star-o',shouldToggleOff);star.classList.toggle('fa-star',!shouldToggleOff);};for(const star of nextStars){star.classList.toggle('fa-star-o',true);star.classList.toggle('fa-star',false);};this.historyStep();}}
if(this.toolbar&&!ancestors(ev.target,this.editable).includes(this.toolbar)){this.toolbar.style.pointerEvents='none';if(this.deselectTable()&&hasValidSelection(this.editable)){this.document.getSelection().collapseToStart();this._updateToolbar(false);}}
const isHoveringTdBorder=this._isHoveringTdBorder(ev);const isRTL=this.options.direction==='rtl';if(isHoveringTdBorder){ev.preventDefault();const direction={top:'row',right:'col',bottom:'row',left:'col'}[isHoveringTdBorder]||false;let target1,target2;const column=closestElement(ev.target,'tr');if(isHoveringTdBorder==='top'&&column){target1=getAdjacentPreviousSiblings(column).find(node=>node.nodeName==='TR');target2=closestElement(ev.target,'tr');}else if(isHoveringTdBorder==='right'){if(isRTL){target1=getAdjacentPreviousSiblings(ev.target).find(node=>node.nodeName==='TD');target2=ev.target;}else{target1=ev.target;target2=getAdjacentNextSiblings(ev.target).find(node=>node.nodeName==='TD');}}else if(isHoveringTdBorder==='bottom'&&column){target1=closestElement(ev.target,'tr');target2=getAdjacentNextSiblings(column).find(node=>node.nodeName==='TR');}else if(isHoveringTdBorder==='left'){if(isRTL){target1=ev.target;target2=getAdjacentNextSiblings(ev.target).find(node=>node.nodeName==='TD');}else{target1=getAdjacentPreviousSiblings(ev.target).find(node=>node.nodeName==='TD');target2=ev.target;}}
this._isResizingTable=true;this._toggleTableResizeCursor(direction);const resizeTable=ev=>this._resizeTable(ev,direction,target1,target2);const stopResizing=ev=>{ev.preventDefault();this._isResizingTable=false;this._toggleTableResizeCursor(false);this.historyStep();this.document.removeEventListener('mousemove',resizeTable);this.document.removeEventListener('mouseup',stopResizing);this.document.removeEventListener('mouseleave',stopResizing);};this.document.addEventListener('mousemove',resizeTable);this.document.addEventListener('mouseup',stopResizing);this.document.addEventListener('mouseleave',stopResizing);}
const isEmojiPopover=document.querySelector('.o-EmojiPicker');if(isEmojiPopover&&ev.target!==isEmojiPopover){isEmojiPopover.remove();}}
_onScroll(ev){if(this._rowUiTarget&&!this._rowUi.classList.contains('o_open')){this._positionTableUi(this._rowUiTarget);}
if(this._columnUiTarget&&!this._columnUi.classList.contains('o_open')){this._positionTableUi(this._columnUiTarget);}}
_onDocumentKeydown(ev){const canUndoRedo=!['INPUT','TEXTAREA'].includes(this.document.activeElement.tagName);if(this.options.controlHistoryFromDocument&&canUndoRedo){if(IS_KEYBOARD_EVENT_UNDO(ev)&&canUndoRedo){ev.preventDefault();this.historyUndo();}else if(IS_KEYBOARD_EVENT_REDO(ev)&&canUndoRedo){ev.preventDefault();this.historyRedo();}}else{if(IS_KEYBOARD_EVENT_REDO(ev)||IS_KEYBOARD_EVENT_UNDO(ev)){this._onKeyupResetContenteditableNodes.push(...this.editable.querySelectorAll('[contenteditable=true]'),);if(this.editable.getAttribute('contenteditable')==='true'){this._onKeyupResetContenteditableNodes.push(this.editable);}
for(const node of this._onKeyupResetContenteditableNodes){this.automaticStepSkipStack();node.setAttribute('contenteditable',false);}}}}
_onDocumentKeyup(){if(this._onKeyupResetContenteditableNodes.length){for(const node of this._onKeyupResetContenteditableNodes){this.automaticStepSkipStack();node.setAttribute('contenteditable',true);}
this._onKeyupResetContenteditableNodes=[];}}
_onDocumentMouseup(ev){this._currentMouseState=ev.type;if(this.toolbar){this.toolbar.style.pointerEvents='auto';}}
_onMousemove(ev){if(this._currentMouseState==='mousedown'&&!this._isResizingTable){this._handleSelectionInTable(ev);}
if(!this._rowUi.classList.contains('o_open')&&!this._columnUi.classList.contains('o_open')){const column=closestElement(ev.target,'td');if(this._isResizingTable||!column||!column.isContentEditable||!ev.target||ev.target.nodeType!==Node.ELEMENT_NODE){this._toggleTableUi(false,false);}else{const row=closestElement(column,'tr');const isFirstColumn=column===row.querySelector('td');const table=column&&closestElement(column,'table');const isFirstRow=table&&row===table.querySelector('tr');this._toggleTableUi(isFirstColumn&&row,isFirstRow&&column);}}
const direction={top:'row',right:'col',bottom:'row',left:'col'}[this._isHoveringTdBorder(ev)]||false;if(direction||!this._isResizingTable){this._toggleTableResizeCursor(direction);}}
_onMouseLeave(ev){if(!this._isResizingTable){this._toggleTableResizeCursor(false);}}
_onDocumentClick(ev){this._rowUi.classList.remove('o_open');this._columnUi.classList.remove('o_open');}
_handleAutomaticLinkInsertion(){const selection=this.document.getSelection();if(selection&&selection.anchorNode&&isHtmlContentSupported(selection.anchorNode)&&!closestElement(selection.anchorNode).closest('a')&&selection.anchorNode.nodeType===Node.TEXT_NODE){selection.anchorNode.parentNode.normalize();const textSliced=selection.anchorNode.textContent.slice(0,selection.anchorOffset);const textNodeSplitted=textSliced.split(/\s/);const potentialUrl=textNodeSplitted.pop()||'';const match=[...potentialUrl.matchAll(new RegExp(URL_REGEX,'g'))].pop();if(match&&!EMAIL_REGEX.test(match[0])){const nodeForSelectionRestore=selection.anchorNode.splitText(selection.anchorOffset);const url=match[2]?match[0]:'http://'+match[0];const range=this.document.createRange();const startOffset=selection.anchorOffset-potentialUrl.length+match.index;range.setStart(selection.anchorNode,startOffset);range.setEnd(selection.anchorNode,startOffset+match[0].length);const link=this._createLink(range.extractContents().textContent,url);range.insertNode(link);setCursorStart(nodeForSelectionRestore,false);}}}
_createLink(label,url){const link=this.document.createElement('a');link.setAttribute('href',url);for(const[param,value]of Object.entries(this.options.defaultLinkAttributes)){link.setAttribute(param,`${value}`);}
link.innerText=label;return link;}
addImagesFiles(imageFiles){const promises=[];for(const imageFile of imageFiles){const imageNode=document.createElement('img');imageNode.classList.add('img-fluid');if(this.options.dropImageAsAttachment){imageNode.classList.add('o_b64_image_to_save');}
imageNode.dataset.fileName=imageFile.name;promises.push(getImageUrl(imageFile).then(url=>{imageNode.src=url;return imageNode;}));}
return Promise.all(promises).then(nodes=>{const fragment=document.createDocumentFragment();fragment.append(...nodes);return fragment;});}
_onPaste(ev){const sel=this.document.getSelection();if(sel.anchorNode&&isProtected(sel.anchorNode)){return;}
ev.preventDefault();const files=getImageFiles(ev.clipboardData);const odooEditorHtml=ev.clipboardData.getData('text/odoo-editor');const clipboardHtml=ev.clipboardData.getData('text/html');const targetSupportsHtmlContent=isHtmlContentSupported(sel.anchorNode);const link=closestElement(sel.anchorNode,'a');if(link&&sel.toString().replace(ZERO_WIDTH_CHARS_REGEX,'')===link.innerText.replace(ZERO_WIDTH_CHARS_REGEX,'')){const start=leftPos(link);link.remove();setSelection(...start,...start,false);}
if(!targetSupportsHtmlContent){const text=ev.clipboardData.getData("text/plain");this._applyCommand("insert",text);}else if(odooEditorHtml){const fragment=parseHTML(this.document,odooEditorHtml);const selector=this.options.renderingClasses.map(c=>`.${c}`).join(',');if(selector){for(const element of fragment.querySelectorAll(selector)){element.classList.remove(...this.options.renderingClasses);}}
this.DOMPurify??=DOMPurify(this.document.defaultView,);this.DOMPurify.sanitize(fragment,{IN_PLACE:true,ADD_TAGS:["#document-fragment","fake-el"],ADD_ATTR:["contenteditable"],});if(fragment.hasChildNodes()){this._applyCommand('insert',fragment);}}else if(files.length||clipboardHtml){const clipboardElem=this._prepareClipboardData(clipboardHtml);if(files.length&&!clipboardElem.querySelector('table')){this.addImagesFiles(files).then(html=>{this._applyCommand('insert',html);});}else{if(closestElement(sel.anchorNode,'a')){this._applyCommand('insert',clipboardElem.textContent);}
else{this._applyCommand('insert',clipboardElem);}}}else{const text=ev.clipboardData.getData('text/plain');const selectionIsInsideALink=!!closestElement(sel.anchorNode,'a');const isSelectionInsidePre=!!closestElement(sel.anchorNode,'pre');let splitAroundUrl=[text];if(!text.match(/\${.*}/gi)){splitAroundUrl=text.split(URL_REGEX);splitAroundUrl=splitAroundUrl.filter((_,index)=>((index+1)%3));}
if(splitAroundUrl.length===3&&!splitAroundUrl[0]&&!splitAroundUrl[2]&&!isSelectionInsidePre){const url=/^https?:\/\//i.test(text)?text:'http://'+text;const youtubeUrl=this.options.allowCommandVideo&&YOUTUBE_URL_GET_VIDEO_ID.exec(url);const urlFileExtention=url.split('.').pop();const isImageUrl=['jpg','jpeg','png','gif','svg','webp'].includes(urlFileExtention.toLowerCase());if(selectionIsInsideALink){if(isImageUrl){const img=document.createElement('IMG');img.setAttribute('src',url);this._applyCommand('insert',img);}else{this._applyCommand('insert',text);}}else if(isImageUrl||youtubeUrl){const stepIndexBeforeInsert=this._historySteps.length-1;this.observerFlush();const currentStepMutations=[...this._currentStep.mutations];this._applyCommand('insert',text);const revertTextInsertion=()=>{this.historyRevertUntil(stepIndexBeforeInsert);this.historyStep(true);this._historyStepsStates.set(peek(this._historySteps).id,'consumed');this.historyApply(currentStepMutations);};let commands;const pasteAsURLCommand={name:this.options._t('Paste as URL'),description:this.options._t('Create an URL.'),fontawesome:'fa-link',callback:()=>{revertTextInsertion();this._applyRawCommand('insert',this._createLink(text,url))},};if(isImageUrl){const embedImageCommand={name:this.options._t('Embed Image'),description:this.options._t('Embed the image in the document.'),fontawesome:'fa-image',callback:()=>{revertTextInsertion();const img=document.createElement('IMG');img.setAttribute('src',url);this._applyRawCommand('insert',img);},};commands=[embedImageCommand,pasteAsURLCommand];}else{const embedVideoCommand={name:this.options._t('Embed Youtube Video'),description:this.options._t('Embed the youtube video in the document.'),fontawesome:'fa-youtube-play',callback:async()=>{revertTextInsertion();let videoElement;if(this.options.getYoutubeVideoElement){videoElement=await this.options.getYoutubeVideoElement(youtubeUrl[0]);}else{videoElement=document.createElement('iframe');videoElement.setAttribute('width','560');videoElement.setAttribute('height','315');videoElement.setAttribute('src',`https://www.youtube.com/embed/${encodeURIComponent(youtubeUrl[1])}`,);videoElement.setAttribute('title','YouTube video player');videoElement.setAttribute('frameborder','0');videoElement.setAttribute('allow','accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture',);videoElement.setAttribute('allowfullscreen','1');}
this._applyRawCommand('insert',videoElement);},};commands=[embedVideoCommand,pasteAsURLCommand];}
this.powerbox.open(commands);}else{this._applyCommand('insert',this._createLink(text,url));}}else{this.historyPauseSteps();for(let i=0;i<splitAroundUrl.length;i++){const url=/^https?:\/\//gi.test(splitAroundUrl[i])?splitAroundUrl[i]:'http://'+splitAroundUrl[i];if(i%2&&!selectionIsInsideALink&&!isSelectionInsidePre){this._applyCommand('insert',this._createLink(splitAroundUrl[i],url));}else if(splitAroundUrl[i]!==''){const textFragments=splitAroundUrl[i].split(/\r?\n/);let textIndex=1;for(const textFragment of textFragments){const modifiedTextFragment=textFragment.replace(/( {2,})/g,match=>{let alertnateValue=false;return match.replace(/ /g,()=>{alertnateValue=!alertnateValue;const replaceContent=alertnateValue?'\u00A0':' ';return replaceContent;});});this._applyCommand('insert',modifiedTextFragment);if(textIndex<textFragments.length){const p=closestElement(sel.anchorNode,'p');if(isUnbreakable(closestBlock(sel.anchorNode))||closestElement(sel.anchorNode).nodeName==='PRE'){this._applyCommand('oShiftEnter');}else{this._applyCommand('oEnter');p&&(p.style.marginBottom='0px');}}
textIndex++;}}}
this.historyUnpauseSteps();this.historyStep();}}}
_onDragStart(ev){if(ev.target.nodeName==='IMG'){ev.dataTransfer.setData('text/plain',`oid:${ev.target.oid}`);}}
_onDrop(ev){ev.preventDefault();if(!isHtmlContentSupported(ev.target)){return;}
const sel=this.document.getSelection();let isInEditor=false;let ancestor=sel.anchorNode;while(ancestor&&!isInEditor){if(ancestor===this.editable){isInEditor=true;}
ancestor=ancestor.parentNode;}
const dataTransfer=(ev.originalEvent||ev).dataTransfer;const imageOidMatch=(dataTransfer.getData('text')||'').match('oid:(.*)');const imageOid=imageOidMatch&&imageOidMatch[1];const image=imageOid&&[...this.editable.querySelectorAll('*')].find(node=>node.oid===imageOid,);const fileTransferItems=getImageFiles(dataTransfer);const htmlTransferItem=[...dataTransfer.items].find(item=>item.type==='text/html',);if(image||fileTransferItems.length||htmlTransferItem){if(this.document.caretPositionFromPoint){const range=this.document.caretPositionFromPoint(ev.clientX,ev.clientY);setSelection(range.offsetNode,range.offset);}else if(this.document.caretRangeFromPoint){const range=this.document.caretRangeFromPoint(ev.clientX,ev.clientY);setSelection(range.startContainer,range.startOffset);}}
if(image){image.classList.toggle('img-fluid',true);const html=image.outerHTML;image.remove();this.execCommand('insert',this._prepareClipboardData(html));}else if(fileTransferItems.length){this.addImagesFiles(fileTransferItems).then(html=>{this.execCommand('insert',html);});}else if(htmlTransferItem){htmlTransferItem.getAsString(pastedText=>{this.execCommand('insert',this._prepareClipboardData(pastedText));});}
this.historyStep();}
_onTabulationInTable(ev){const sel=this.document.getSelection();const closestTable=closestElement(sel.anchorNode,'table');if(!closestTable){return;}
const closestTd=closestElement(sel.anchorNode,'td');const tds=[...closestTable.querySelectorAll('td')];const direction=ev.shiftKey?DIRECTIONS.LEFT:DIRECTIONS.RIGHT;const cursorDestination=tds[tds.findIndex(td=>closestTd===td)+(direction===DIRECTIONS.LEFT?-1:1)];if(cursorDestination){setCursorEnd(lastLeaf(cursorDestination));}else if(direction===DIRECTIONS.RIGHT){this.execCommand('addRow','after');this._onTabulationInTable(ev);}}
_onTableMenuTogglerClick(ev){const uiWrapper=ev.target.closest('.o_table_ui');uiWrapper.classList.toggle('o_open');if(this.options.direction==='rtl'){const menuRowEl=this._tableUiContainer.querySelector('.o_row_ui .o_table_ui_menu')
const menuRowRect=menuRowEl.getBoundingClientRect();menuRowEl.style.position='absolute';menuRowEl.style.left=`-${menuRowRect.width}px`;menuRowEl.style.margin=`0px`;}
if(uiWrapper.classList.contains('o_column_ui')){const columnIndex=getColumnIndex(this._columnUiTarget);uiWrapper.querySelector('.o_move_left').classList.toggle('o_hide',columnIndex===0);const shouldHideRight=columnIndex===[...this._columnUiTarget.parentElement.children].filter(child=>child.nodeName==='TD').length-1;uiWrapper.querySelector('.o_move_right').classList.toggle('o_hide',shouldHideRight);}else{const rowIndex=getRowIndex(this._rowUiTarget);uiWrapper.querySelector('.o_move_up').classList.toggle('o_hide',rowIndex===0);const shouldHideDown=rowIndex===[...this._rowUiTarget.parentElement.children].filter(child=>child.nodeName==='TR').length-1;uiWrapper.querySelector('.o_move_down').classList.toggle('o_hide',shouldHideDown);}
ev.stopPropagation();}
_onTableMoveUpClick(){if(this._rowUiTarget.previousSibling){if(!this._rowUiTarget.previousSibling.previousSibling){this._rowUiTarget.childNodes.forEach((cell,index)=>{cell.style.width=this._rowUiTarget.previousSibling.childNodes[index].style.width;});}
this._rowUiTarget.previousSibling.before(this._rowUiTarget);}}
_onTableMoveDownClick(){if(this._rowUiTarget.nextSibling){if(!this._rowUiTarget.previousSibling){this._rowUiTarget.nextSibling.childNodes.forEach((cell,index)=>{cell.style.width=this._rowUiTarget.childNodes[index].style.width;});}
this._rowUiTarget.nextSibling.after(this._rowUiTarget);}}
_onTableMoveRightClick(){const trs=[...this._columnUiTarget.parentElement.parentElement.children].filter(child=>child.nodeName==='TR');const columnIndex=getColumnIndex(this._columnUiTarget);const tdsToMove=trs.map(tr=>[...tr.children].filter(child=>child.nodeName==='TD')[columnIndex]);for(const tdToMove of tdsToMove){const target=[...tdToMove.parentElement.children].filter(child=>child.nodeName==='TD')[columnIndex+1];target.after(tdToMove);}}
_onTableMoveLeftClick(){const trs=[...this._columnUiTarget.parentElement.parentElement.children].filter(child=>child.nodeName==='TR');const columnIndex=getColumnIndex(this._columnUiTarget);const tdsToMove=trs.map(tr=>[...tr.children].filter(child=>child.nodeName==='TD')[columnIndex]);for(const tdToMove of tdsToMove){const target=[...tdToMove.parentElement.children].filter(child=>child.nodeName==='TD')[columnIndex-1];target.before(tdToMove);}}
_onTableDeleteColumnClick(){this.historyPauseSteps();const rows=[...closestElement(this._columnUiTarget,'tr').parentElement.children].filter(child=>child.nodeName==='TR');this.execCommand('removeColumn',this._columnUiTarget);if(rows.every(row=>!row.parentElement)){this.execCommand('deleteTable',this.editable.querySelector('.o_selected_table'));}
this.historyUnpauseSteps();this.historyStep();}
_onTableDeleteRowClick(){this.historyPauseSteps();const rows=[...this._rowUiTarget.parentElement.children].filter(child=>child.nodeName==='TR');this.execCommand('removeRow',this._rowUiTarget);if(rows.every(row=>!row.parentElement)){this.execCommand('deleteTable',this.editable.querySelector('.o_selected_table'));}
this.historyUnpauseSteps();this.historyStep();}
_fixFontAwesomeSelection(){const selection=this.document.getSelection();if(selection.isCollapsed||(selection.anchorNode&&!ancestors(selection.anchorNode,this.editable).includes(this.editable)))
return;let shouldUpdateSelection=false;const fixedSelection={anchorNode:selection.anchorNode,anchorOffset:selection.anchorOffset,focusNode:selection.focusNode,focusOffset:selection.focusOffset,};const selectionDirection=getCursorDirection(selection.anchorNode,selection.anchorOffset,selection.focusNode,selection.focusOffset,);const closestAnchorNodeEl=closestElement(selection.anchorNode);if(isIconElement(closestAnchorNodeEl)){shouldUpdateSelection=true;fixedSelection.anchorNode=selectionDirection===DIRECTIONS.RIGHT?closestAnchorNodeEl.previousSibling:closestAnchorNodeEl.nextSibling;if(fixedSelection.anchorNode){fixedSelection.anchorOffset=selectionDirection===DIRECTIONS.RIGHT?fixedSelection.anchorNode.length:0;}else{fixedSelection.anchorNode=closestAnchorNodeEl.parentElement;fixedSelection.anchorOffset=0;}}
const closestFocusNodeEl=closestElement(selection.focusNode);if(isIconElement(closestFocusNodeEl)){shouldUpdateSelection=true;fixedSelection.focusNode=selectionDirection===DIRECTIONS.RIGHT?closestFocusNodeEl.nextSibling:closestFocusNodeEl.previousSibling;if(fixedSelection.focusNode){fixedSelection.focusOffset=selectionDirection===DIRECTIONS.RIGHT?0:fixedSelection.focusNode.length;}else{fixedSelection.focusNode=closestFocusNodeEl.parentElement;fixedSelection.focusOffset=0;}}
if(shouldUpdateSelection){setSelection(fixedSelection.anchorNode,fixedSelection.anchorOffset,fixedSelection.focusNode,fixedSelection.focusOffset,false,);}}
_pluginAdd(Plugin){this._plugins.push(new Plugin({editor:this}));}
_pluginCall(method,args=[]){for(const plugin of this._plugins){if(plugin[method]){plugin[method](...args);}}}}
return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/utils/constants.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/utils/constants',[],function(require){'use strict';let __exports={};const UNBREAKABLE_ROLLBACK_CODE=__exports.UNBREAKABLE_ROLLBACK_CODE='UNBREAKABLE';const UNREMOVABLE_ROLLBACK_CODE=__exports.UNREMOVABLE_ROLLBACK_CODE='UNREMOVABLE';const REGEX_BOOTSTRAP_COLUMN=__exports.REGEX_BOOTSTRAP_COLUMN=/(?:^| )col(-[a-zA-Z]+)?(-\d+)?(?:$| )/;return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/utils/sanitize.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/utils/sanitize',['@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{closestBlock,closestElement,startPos,getListMode,isBlock,isSelfClosingElement,moveNodes,preserveCursor,isIconElement,getDeepRange,isUnbreakable,isEditorTab,isProtected,isZWS,isArtificialVoidElement,ancestors,EMAIL_REGEX,PHONE_REGEX,URL_REGEX,unwrapContents,padLinkWithZws,getTraversedNodes,ZERO_WIDTH_CHARS_REGEX,isVisible,cleanZWS,}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");const NOT_A_NUMBER=/[^\d]/g;const UNMERGEABLE_SELECTORS=__exports.UNMERGEABLE_SELECTORS=[];const FORMATTABLE_TAGS=["SPAN","FONT","B","STRONG","I","EM","U","S","SMALL"];function hasPseudoElementContent(node,pseudoSelector){const content=getComputedStyle(node,pseudoSelector).getPropertyValue('content');return content&&content!=='none';}
__exports.areSimilarElements=areSimilarElements;function areSimilarElements(node,node2){if(![node,node2].every(n=>n?.nodeType===Node.ELEMENT_NODE)){return false;}
if(node.nodeName!==node2.nodeName){return false;}
const nodeName=node.nodeName;for(const name of new Set([...node.getAttributeNames(),...node2.getAttributeNames(),])){if(node.getAttribute(name)!==node2.getAttribute(name)){return false;}}
if([node,node2].some(n=>hasPseudoElementContent(n,':before')||hasPseudoElementContent(n,':after'))){return false;}
if(isIconElement(node)||isIconElement(node2)){return false;}
if(nodeName==='LI'&&node.classList.contains('oe-nested')){return(node.lastElementChild&&node2.firstElementChild&&getListMode(node.lastElementChild)===getListMode(node2.firstElementChild));}
if(['UL','OL'].includes(nodeName)){return!isSelfClosingElement(node)&&!isSelfClosingElement(node2);}
if(isBlock(node)||isSelfClosingElement(node)||isSelfClosingElement(node2)){return false;}
const nodeStyle=getComputedStyle(node);const node2Style=getComputedStyle(node2);if(node.matches("code.o_inline_code")){if(nodeStyle.padding===node2Style.padding&&nodeStyle.margin===node2Style.margin){return true;}}
return(!+nodeStyle.padding.replace(NOT_A_NUMBER,'')&&!+node2Style.padding.replace(NOT_A_NUMBER,'')&&!+nodeStyle.margin.replace(NOT_A_NUMBER,'')&&!+node2Style.margin.replace(NOT_A_NUMBER,''));}
__exports.deduceURLfromText=deduceURLfromText;function deduceURLfromText(text,link){if(link&&link.getAttribute("role")==="tab"){return;}
const label=text.replace(ZERO_WIDTH_CHARS_REGEX,'').trim();let match=label.match(EMAIL_REGEX);if(match){return match[1]?match[0]:'mailto:'+match[0];}
match=label.match(URL_REGEX);if(match&&match[0]===label){const currentHttpProtocol=(link?.href.match(/^http(s)?:\/\//gi)||[])[0];if(match[2]){return match[0];}else if(currentHttpProtocol){return currentHttpProtocol+match[0];}else{return'http://'+match[0];}}
match=label.match(PHONE_REGEX);if(match){if(match[1]){return match[0].replace(/\s+/g,"");}else if(link?.href.startsWith("tel:")){return("tel:"+match[0]).replace(/\s+/g,"");}}
return null;}
function shouldPreserveCursor(node,root){const selection=root.ownerDocument.getSelection();return node.isConnected&&selection&&selection.anchorNode&&root.contains(selection.anchorNode)&&selection.focusNode&&root.contains(selection.focusNode);}
function sanitizeNode(node,root){if(isArtificialVoidElement(node)&&node.getAttribute('contenteditable')!=='false'){node.setAttribute('contenteditable','false');}
if(node.nodeType===Node.ELEMENT_NODE&&node.hasAttribute("data-oe-zws-empty-inline")&&node.textContent!=="\u200B"){const restoreCursor=shouldPreserveCursor(node,root)&&preserveCursor(root.ownerDocument);cleanZWS(node);delete node.dataset.oeZwsEmptyInline;restoreCursor&&restoreCursor();}
for(const attributeName of['class','style']){if(node.nodeType===Node.ELEMENT_NODE&&node.hasAttribute(attributeName)&&!node.getAttribute(attributeName)){node.removeAttribute(attributeName);}}
if(['SPAN','FONT'].includes(node.nodeName)&&!node.hasAttributes()&&!hasPseudoElementContent(node,"::before")&&!hasPseudoElementContent(node,"::after")&&!node.querySelector(".oe_currency_value")){getDeepRange(root,{select:true});const restoreCursor=shouldPreserveCursor(node,root)&&preserveCursor(root.ownerDocument);const parent=node.parentElement;unwrapContents(node);restoreCursor&&restoreCursor();node=parent;}else if(areSimilarElements(node,node.previousSibling)&&!isUnbreakable(node)&&!isEditorTab(node)&&!(node.attributes?.length===1&&node.hasAttribute('data-oe-zws-empty-inline')&&(node.textContent==='\u200B'||node.previousSibling.textContent==='\u200B'))&&!UNMERGEABLE_SELECTORS.some(selectorClass=>node.classList?.contains(selectorClass))){getDeepRange(root,{select:true});const restoreCursor=shouldPreserveCursor(node,root)&&preserveCursor(root.ownerDocument);moveNodes(...startPos(node),node.previousSibling);restoreCursor&&restoreCursor();}else if(FORMATTABLE_TAGS.includes(node.nodeName)&&isRedundantElement(node)){getDeepRange(root,{select:true});const restoreCursor=shouldPreserveCursor(node,root)&&preserveCursor(root.ownerDocument);const parent=node.parentElement;unwrapContents(node);restoreCursor&&restoreCursor();node=parent;}else if(node.nodeType===Node.COMMENT_NODE){const parent=node.parentElement;node.remove();node=parent;}else if(node.nodeName==='P'&&['LI','A'].includes(node.parentElement.nodeName)&&!node.parentElement.classList.contains('nav-item')){const previous=node.previousSibling;const attributes=node.attributes;const parent=node.parentElement;const restoreCursor=shouldPreserveCursor(node,root)&&preserveCursor(root.ownerDocument);if(attributes.length){const spanEl=document.createElement('span');for(const attribute of attributes){spanEl.setAttribute(attribute.name,attribute.value);}
if(spanEl.style.textAlign){spanEl.style.display='block';}
spanEl.append(...node.childNodes);node.replaceWith(spanEl);}else{unwrapContents(node);}
if(previous&&isVisible(previous)&&!isBlock(previous)&&previous.nodeName!=='BR'){const br=document.createElement('br');previous.after(br);}
restoreCursor&&restoreCursor(new Map([[node,parent]]));node=parent;}else if(node.nodeName==='LI'&&!node.closest('ul, ol')){if(node.children.length&&[...node.children].every(isBlock)){const restoreCursor=shouldPreserveCursor(node,root)&&preserveCursor(root.ownerDocument);const nodeToReplace=node.firstElementChild;unwrapContents(node);restoreCursor&&restoreCursor(new Map([[node,nodeToReplace]]));node=nodeToReplace;}else{const paragraph=document.createElement("p");paragraph.replaceChildren(...node.childNodes);node.replaceWith(paragraph);node=paragraph;}}else if(['UL','OL'].includes(node.nodeName)&&['UL','OL'].includes(node.parentNode.nodeName)){const restoreCursor=shouldPreserveCursor(node,root)&&preserveCursor(root.ownerDocument);const li=document.createElement('li');node.parentNode.insertBefore(li,node);li.appendChild(node);li.classList.add('oe-nested');node=li;restoreCursor&&restoreCursor();}else if(isIconElement(node)&&node.textContent!=='\u200B'){node.textContent='\u200B';}else if(isEditorTab(node)){let tabPreviousSibling=node.previousSibling;while(isZWS(tabPreviousSibling)){tabPreviousSibling=tabPreviousSibling.previousSibling;}
if(isEditorTab(tabPreviousSibling)){node.style.width='40px';node.style.tabSize='40px';}else{const editable=closestElement(node,'.odoo-editor-editable');if(editable?.firstElementChild){const nodeRect=node.getBoundingClientRect();const referenceRect=editable.firstElementChild.getBoundingClientRect();if(nodeRect.width&&referenceRect.width){const width=(nodeRect.left-referenceRect.left)%40;node.style.width=(40-width)+'px';node.style.tabSize=(40-width)+'px';}}}}else if(node.nodeName==='A'){padLinkWithZws(root,node);}else if(node.nodeType===Node.TEXT_NODE&&node.textContent.includes('\uFEFF')&&!closestElement(node,'a')&&!(closestElement(root,'[contenteditable=true]')&&getTraversedNodes(closestElement(root,'[contenteditable=true]')).includes(node))){const startsWithLegitZws=node.textContent.startsWith('\uFEFF')&&node.previousSibling&&node.previousSibling.nodeName==='A';const endsWithLegitZws=node.textContent.endsWith('\uFEFF')&&node.nextSibling&&node.nextSibling.nodeName==='A';let newText=node.textContent.replace(/\uFEFF/g,'');if(startsWithLegitZws){newText='\uFEFF'+newText;}
if(endsWithLegitZws){newText=newText+'\uFEFF';}
if(newText!==node.textContent){let replacement;if(newText.length){replacement=document.createTextNode(newText);node.before(replacement);}else{replacement=node.parentElement;}
node.remove();node=replacement;}}
return node;}
__exports.sanitize=sanitize;function sanitize(nodeToSanitize,root=nodeToSanitize){const start=nodeToSanitize.ownerDocument.getSelection()?.anchorNode;const block=closestBlock(nodeToSanitize);if(block&&root.contains(block)){const isList=['UL','OL'].includes(block.nodeName);let node=isList?block.parentElement:block;while(node&&!(root.isConnected&&!node.isConnected)&&root.contains(node)){if(!isProtected(node)){node=sanitizeNode(node,root);}
node=node.firstChild||node.nextSibling||ancestors(node,root).find(a=>a.nextSibling)?.nextSibling;}
const elementsWithId=[...block.querySelectorAll('[id^=checkId-]')];const maxId=Math.max(...[0,...elementsWithId.map(node=>+node.getAttribute('id').substring(8))]);let nextId=maxId+1;const ids=[];for(const node of block.querySelectorAll('[id^=checkId-], .o_checklist > li, .o_stars')){if(!node.classList.contains('o_stars')&&(!node.parentElement.classList.contains('o_checklist')||[...node.children].some(child=>['UL','OL'].includes(child.nodeName)))){node.removeAttribute('id')}else{let id=node.getAttribute('id');if(!id||ids.includes(id)){id=`checkId-${nextId}`;nextId++;node.setAttribute('id',id);}
ids.push(id);}}
const startEl=start&&closestElement(start,'a');if(startEl&&root.contains(startEl)){const label=startEl.innerText;const url=deduceURLfromText(label,startEl);if(url){startEl.setAttribute('href',url);}}}
return nodeToSanitize;}
function hasClassesSubset(node,node2){const getNodeClasses=(n)=>(n||"").trim().split(/\s+/).filter(Boolean);const[nodeClasses,node2Classes]=[node,node2].map(getNodeClasses);return nodeClasses.every((cls)=>node2Classes.includes(cls));}
function hasStylesSubset(node,node2){const getNodeStyles=(n)=>(n||"").split(";").map((s)=>s.trim()).filter(Boolean);const[nodeStyles,node2Styles]=[node,node2].map(getNodeStyles);return nodeStyles.every((style)=>node2Styles.includes(style));}
__exports.isRedundantElement=isRedundantElement;function isRedundantElement(node){if(!node||node.nodeType!==Node.ELEMENT_NODE||!node.parentElement){return false;}
const closestEl=closestElement(node.parentElement,node.tagName);if(!closestEl){return false;}
for(const{name:attrName,value:nodeAttrVal}of node.attributes){const closestElAttrVal=closestEl.getAttribute(attrName);if(!closestElAttrVal){return false;}
if(attrName==="class"){if(!hasClassesSubset(nodeAttrVal,closestElAttrVal)){return false;}}else if(attrName==="style"){if(!hasStylesSubset(nodeAttrVal,closestElAttrVal)){return false;}}else{if(nodeAttrVal!==closestElAttrVal){return false;}}}
return true;}
return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/utils/serialize.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/utils/serialize',[],function(require){'use strict';let __exports={};__exports.serializeNode=serializeNode;function serializeNode(node,nodesToStripFromChildren=new Set()){if(!node.oid){return;}
const result={nodeType:node.nodeType,oid:node.oid,};if(node.nodeType===Node.TEXT_NODE){result.textValue=node.nodeValue;}else if(node.nodeType===Node.ELEMENT_NODE){result.tagName=node.tagName;result.children=[];result.attributes={};for(let i=0;i<node.attributes.length;i++){result.attributes[node.attributes[i].name]=node.attributes[i].value;}
let child=node.firstChild;if(!["true",""].includes(node.dataset.oeTransientContent)){while(child){if(!nodesToStripFromChildren.has(child.oid)){const serializedChild=serializeNode(child,nodesToStripFromChildren);if(serializedChild){result.children.push(serializedChild);}}
child=child.nextSibling;}}}
return result;}
__exports.unserializeNode=unserializeNode;function unserializeNode(obj){if(!obj){return;}
let result=undefined;if(obj.nodeType===Node.TEXT_NODE){result=document.createTextNode(obj.textValue);}else if(obj.nodeType===Node.ELEMENT_NODE){result=document.createElement(obj.tagName);for(const key in obj.attributes){result.setAttribute(key,obj.attributes[key]);}
obj.children.forEach(child=>result.append(unserializeNode(child)));}else{console.warn('unknown node type');}
if(result){result.oid=obj.oid;return result;}}
__exports.serializeSelection=serializeSelection;function serializeSelection(selection){if(selection&&selection.anchorNode&&selection.anchorNode.oid&&typeof selection.anchorOffset!=='undefined'&&selection.focusNode&&selection.anchorNode.oid&&typeof selection.focusOffset!=='undefined'){return{anchorNodeOid:selection.anchorNode.oid,anchorOffset:selection.anchorOffset,focusNodeOid:selection.focusNode.oid,focusOffset:selection.focusOffset,};}else{return{anchorNodeOid:undefined,anchorOffset:undefined,focusNodeOid:undefined,focusOffset:undefined,};}}
return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/tablepicker/TablePicker.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/tablepicker/TablePicker',['@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{getRangePosition}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");const TablePicker=__exports.TablePicker=class TablePicker extends EventTarget{constructor(options={}){super();this.options=options;this.options.minRowCount=this.options.minRowCount||3;this.options.minColCount=this.options.minColCount||3;this.options.getContextFromParentRect=this.options.getContextFromParentRect||(()=>({top:0,left:0}));this.rowNumber=this.options.minRowCount;this.colNumber=this.options.minColCount;this.tablePickerWrapper=document.createElement('div');this.tablePickerWrapper.classList.add('oe-tablepicker-wrapper');this.tablePickerWrapper.innerHTML=`
            <div class="oe-tablepicker"></div>
            <div class="oe-tablepicker-size"></div>
        `;if(this.options.floating){this.tablePickerWrapper.style.position='absolute';this.tablePickerWrapper.classList.add('oe-floating');}
this.tablePickerElement=this.tablePickerWrapper.querySelector('.oe-tablepicker');this.tablePickerSizeViewElement=this.tablePickerWrapper.querySelector('.oe-tablepicker-size');this.el=this.tablePickerWrapper;this.hide();}
render(){this.tablePickerElement.innerHTML='';const colCount=Math.max(this.colNumber,this.options.minRowCount);const rowCount=Math.max(this.rowNumber,this.options.minRowCount);const extraCol=1;const extraRow=1;for(let rowNumber=1;rowNumber<=rowCount+extraRow;rowNumber++){const rowElement=document.createElement('div');rowElement.classList.add('oe-tablepicker-row');this.tablePickerElement.appendChild(rowElement);for(let colNumber=1;colNumber<=colCount+extraCol;colNumber++){const cell=this.el.ownerDocument.createElement('div');cell.classList.add('oe-tablepicker-cell','btn');rowElement.appendChild(cell);if(rowNumber<=this.rowNumber&&colNumber<=this.colNumber){cell.classList.add('active');}
const bindMouseMove=()=>{cell.addEventListener('mouseover',()=>{if(this.colNumber!==colNumber||this.rowNumber!=rowNumber){this.colNumber=colNumber;this.rowNumber=rowNumber;this.render();}});this.el.ownerDocument.removeEventListener('mousemove',bindMouseMove);};this.el.ownerDocument.addEventListener('mousemove',bindMouseMove);cell.addEventListener('mousedown',this.selectCell.bind(this));}}
this.tablePickerSizeViewElement.textContent=`${this.colNumber}x${this.rowNumber}`;}
show(){this.reset();this.el.style.display='block';if(this.options.floating){this._showFloating();}}
hide(){this.el.style.display='none';}
reset(){this.rowNumber=this.options.minRowCount;this.colNumber=this.options.minColCount;this.render();}
selectCell(){this.dispatchEvent(new CustomEvent('cell-selected',{detail:{colNumber:this.colNumber,rowNumber:this.rowNumber},}),);}
_showFloating(){const isRtl=this.options.direction==='rtl';const keydown=e=>{const actions={ArrowRight:{colNumber:(this.colNumber+(isRtl?-1:1))||1,rowNumber:this.rowNumber,},ArrowLeft:{colNumber:(this.colNumber+(isRtl?1:-1))||1,rowNumber:this.rowNumber,},ArrowUp:{colNumber:this.colNumber,rowNumber:this.rowNumber-1||1,},ArrowDown:{colNumber:this.colNumber,rowNumber:this.rowNumber+1,},};const action=actions[e.key];if(action){this.rowNumber=action.rowNumber||this.rowNumber;this.colNumber=action.colNumber||this.colNumber;this.render();e.preventDefault();}else if(e.key==='Enter'){this.selectCell();e.preventDefault();}else if(e.key==='Escape'){stop();e.preventDefault();}};const offset=getRangePosition(this.el,this.options.document,this.options);if(isRtl){this.el.style.right=`${offset.right}px`;}else{this.el.style.left=`${offset.left}px`;}
this.el.style.top=`${offset.top}px`;const stop=()=>{this.hide();this.options.document.removeEventListener('mousedown',stop);this.removeEventListener('cell-selected',stop);this.options.document.removeEventListener('keydown',keydown,true);};setTimeout(()=>{this.options.document.addEventListener('mousedown',stop);});this.options.document.addEventListener('keydown',keydown,true);this.addEventListener('cell-selected',stop);}}
return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/powerbox/patienceDiff.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/powerbox/patienceDiff',[],function(require){'use strict';let __exports={};__exports.patienceDiff=patienceDiff;function patienceDiff(aLines,bLines,diffPlusFlag){function findUnique(arr,lo,hi){var lineMap=new Map();for(let i=lo;i<=hi;i++){let line=arr[i];if(lineMap.has(line)){lineMap.get(line).count++;lineMap.get(line).index=i;}else{lineMap.set(line,{count:1,index:i});}}
lineMap.forEach((val,key,map)=>{if(val.count!==1){map.delete(key);}else{map.set(key,val.index);}});return lineMap;}
function uniqueCommon(aArray,aLo,aHi,bArray,bLo,bHi){let ma=findUnique(aArray,aLo,aHi);let mb=findUnique(bArray,bLo,bHi);ma.forEach((val,key,map)=>{if(mb.has(key)){map.set(key,{indexA:val,indexB:mb.get(key)});}else{map.delete(key);}});return ma;}
function longestCommonSubsequence(abMap){var ja=[];abMap.forEach((val,key,map)=>{let i=0;while(ja[i]&&ja[i][ja[i].length-1].indexB<val.indexB){i++;}
if(!ja[i]){ja[i]=[];}
if(0<i){val.prev=ja[i-1][ja[i-1].length-1];}
ja[i].push(val);});var lcs=[];if(0<ja.length){let n=ja.length-1;var lcs=[ja[n][ja[n].length-1]];while(lcs[lcs.length-1].prev){lcs.push(lcs[lcs.length-1].prev);}}
return lcs.reverse();}
let result=[];let deleted=0;let inserted=0;let aMove=[];let aMoveIndex=[];let bMove=[];let bMoveIndex=[];function addToResult(aIndex,bIndex){if(bIndex<0){aMove.push(aLines[aIndex]);aMoveIndex.push(result.length);deleted++;}else if(aIndex<0){bMove.push(bLines[bIndex]);bMoveIndex.push(result.length);inserted++;}
result.push({line:0<=aIndex?aLines[aIndex]:bLines[bIndex],aIndex:aIndex,bIndex:bIndex,});}
function addSubMatch(aLo,aHi,bLo,bHi){while(aLo<=aHi&&bLo<=bHi&&aLines[aLo]===bLines[bLo]){addToResult(aLo++,bLo++);}
let aHiTemp=aHi;while(aLo<=aHi&&bLo<=bHi&&aLines[aHi]===bLines[bHi]){aHi--;bHi--;}
let uniqueCommonMap=uniqueCommon(aLines,aLo,aHi,bLines,bLo,bHi);if(uniqueCommonMap.size===0){while(aLo<=aHi){addToResult(aLo++,-1);}
while(bLo<=bHi){addToResult(-1,bLo++);}}else{recurseLCS(aLo,aHi,bLo,bHi,uniqueCommonMap);}
while(aHi<aHiTemp){addToResult(++aHi,++bHi);}}
function recurseLCS(aLo,aHi,bLo,bHi,uniqueCommonMap){var x=longestCommonSubsequence(uniqueCommonMap||uniqueCommon(aLines,aLo,aHi,bLines,bLo,bHi),);if(x.length===0){addSubMatch(aLo,aHi,bLo,bHi);}else{if(aLo<x[0].indexA||bLo<x[0].indexB){addSubMatch(aLo,x[0].indexA-1,bLo,x[0].indexB-1);}
let i;for(i=0;i<x.length-1;i++){addSubMatch(x[i].indexA,x[i+1].indexA-1,x[i].indexB,x[i+1].indexB-1);}
if(x[i].indexA<=aHi||x[i].indexB<=bHi){addSubMatch(x[i].indexA,aHi,x[i].indexB,bHi);}}}
recurseLCS(0,aLines.length-1,0,bLines.length-1);if(diffPlusFlag){return{lines:result,lineCountDeleted:deleted,lineCountInserted:inserted,lineCountMoved:0,aMove:aMove,aMoveIndex:aMoveIndex,bMove:bMove,bMoveIndex:bMoveIndex,};}
return{lines:result,lineCountDeleted:deleted,lineCountInserted:inserted,lineCountMoved:0,};}
return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/powerbox/Powerbox.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/powerbox/Powerbox',['@web_editor/js/editor/odoo-editor/src/powerbox/patienceDiff','@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{patienceDiff}=require("@web_editor/js/editor/odoo-editor/src/powerbox/patienceDiff");const{closestBlock,getRangePosition}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");const REGEX_RESERVED_CHARS=/[\\^$.*+?()[\]{}|]/g;function cycle(num,max){const y=max+1;return((num%y)+y)%y;}
const Powerbox=__exports.Powerbox=class Powerbox{constructor({categories,commands,commandFilters,editable,getContextFromParentRect,onShow,onStop,beforeCommand,afterCommand}={}){this.categories=categories;this.commands=commands;this.commandFilters=commandFilters||[];this.editable=editable;this.getContextFromParentRect=getContextFromParentRect;this.onShow=onShow;this.onStop=onStop;this.beforeCommand=beforeCommand;this.afterCommand=afterCommand;this.isOpen=false;this.document=editable.ownerDocument;this.el=document.createElement('div');this.el.className='oe-powerbox-wrapper position-absolute overflow-hidden';this.el.style.display='none';document.body.append(this.el);this._mainWrapperElement=document.createElement('div');this._mainWrapperElement.className='oe-powerbox-mainWrapper flex-skrink-1 overflow-auto py-2';this.el.append(this._mainWrapperElement);this.el.addEventListener('mousedown',ev=>ev.stopPropagation());this._boundOnKeyup=this._onKeyup.bind(this);this._boundOnKeydown=this._onKeydown.bind(this);this._boundClose=this.close.bind(this);this._events=[[this.document,'keyup',this._boundOnKeyup],[this.document,'keydown',this._boundOnKeydown,true],[this.document,'mousedown',this._boundClose],]
if(document!==this.document){this._events.push([document,'mousedown',this._boundClose],);}}
destroy(){if(this.isOpen){this.close();}
this.el.remove();}
open(commands=this.commands,categories=this.categories){commands=(commands||[]).map(command=>({...command,category:command.category||'',name:command.name||'',priority:command.priority||0,description:command.description||'',callback:command.callback||(()=>{}),}));categories=(categories||[]).map(category=>({name:category.name||'',priority:category.priority||0,}));const order=(a,b)=>b.priority-a.priority||a.name.localeCompare(b.name);categories=[...categories].reverse().filter((category,index,cats)=>(cats.findIndex(cat=>cat.name===category.name)===index)).sort(order);for(let filter of this.commandFilters){commands=filter(commands);}
commands=commands.filter(command=>!command.isDisabled||!command.isDisabled()).sort(order);commands=this._groupCommands(commands,categories).flatMap(group=>group[1]);const selection=this.document.getSelection();const currentBlock=(selection&&closestBlock(selection.anchorNode))||this.editable;this._context={commands,categories,filteredCommands:commands,selectedCommand:undefined,initialTarget:currentBlock,initialValue:currentBlock.textContent,lastText:undefined,}
this.isOpen=true;this._render(this._context.commands,this._context.categories);this._bindEvents();this.show();}
close(){this.isOpen=false;this.hide();this._context=undefined;this._unbindEvents();this.onStop&&this.onStop();};show(){this.onShow&&this.onShow();this.el.style.display='flex';this._resetPosition();}
hide(){this.el.style.display='none';if(this.isOpen){this.close();}}
_render(commands,categories){const parser=new DOMParser();this._mainWrapperElement.innerHTML='';this._hoverActive=false;this._mainWrapperElement.classList.toggle('oe-powerbox-noResult',commands.length===0);this._context.selectedCommand=commands.find(command=>command===this._context.selectedCommand)||commands[0];for(const[category,categoryCommands]of this._groupCommands(commands,categories)){const categoryWrapperEl=parser.parseFromString(`
                <div class="oe-powerbox-categoryWrapper">
                    <div class="oe-powerbox-category mx-3 my-1 text-uppercase"></div>
                </div>`,'text/html').body.firstChild;this._mainWrapperElement.append(categoryWrapperEl);categoryWrapperEl.firstElementChild.innerText=category;for(const command of categoryCommands){const commandElWrapper=document.createElement('div');commandElWrapper.className='oe-powerbox-commandWrapper d-flex align-items-center px-3 py-2 cursor-pointer';commandElWrapper.classList.toggle('active',this._context.selectedCommand===command);commandElWrapper.replaceChildren(...parser.parseFromString(`
                    <div class="oe-powerbox-commandLeftCol border rounded">
                        <i class="oe-powerbox-commandImg d-flex align-items-center justify-content-center fa"></i>
                    </div>
                    <div class="oe-powerbox-commandRightCol ms-3">
                        <div class="oe-powerbox-commandName"></div>
                        <div class="oe-powerbox-commandDescription"></div>
                    </div>`,'text/html').body.children);commandElWrapper.querySelector('.oe-powerbox-commandImg').classList.add(command.fontawesome);commandElWrapper.querySelector('.oe-powerbox-commandName').innerText=command.name;commandElWrapper.querySelector('.oe-powerbox-commandDescription').innerText=command.description;categoryWrapperEl.append(commandElWrapper);commandElWrapper.addEventListener('mouseenter',()=>{this.el.querySelector('.oe-powerbox-commandWrapper.active').classList.remove('active');this._context.selectedCommand=command;commandElWrapper.classList.add('active');});commandElWrapper.addEventListener('click',ev=>{ev.preventDefault();ev.stopImmediatePropagation();this._pickCommand(command);},true,);}}
if(this._mainWrapperElement.childElementCount===1){this._mainWrapperElement.querySelector('.oe-powerbox-category').style.display='none';}
this._resetPosition();}
async _pickCommand(command=this._context.selectedCommand){if(command){if(this.beforeCommand){await this.beforeCommand();}
await command.callback();if(this.afterCommand){await this.afterCommand();}}
this.close();};_groupCommands(commands,categories){const groups=[];for(const category of categories){const categoryCommands=commands.filter(command=>command.category===category.name);commands=commands.filter(command=>command.category!==category.name);groups.push([category.name,categoryCommands]);}
const remainingCategories=[...new Set(commands.map(command=>command.category))];for(const categoryName of remainingCategories.sort((a,b)=>a.localeCompare(b))){const categoryCommands=commands.filter(command=>command.category===categoryName);groups.push([categoryName,categoryCommands]);}
return groups.filter(group=>group[1].length);}
_orderByPriority(commandsOrCategories){return[...commandsOrCategories].sort((a,b)=>b.priority-a.priority||a.name.localeCompare(b.name));}
_resetPosition(){const position=getRangePosition(this.el,this.document,{getContextFromParentRect:this.getContextFromParentRect});if(position){let{left,top}=position;this.el.style.left=`${left}px`;this.el.style.top=`${top}px`;}else{this.hide();}}
_bindEvents(){for(const[target,eventName,callback,option]of this._events){target.addEventListener(eventName,callback,option);}}
_unbindEvents(){for(const[target,eventName,callback,option]of this._events){target.removeEventListener(eventName,callback,option);}}
_onKeyup(ev){if(ev.key==='ArrowDown'||ev.key==='ArrowUp'){ev.preventDefault();}else{const diff=patienceDiff(this._context.initialValue.split(''),this._context.initialTarget.textContent.split(''),true,);this._context.lastText=diff.bMove.join('').replaceAll('\ufeff','');const selection=this.document.getSelection();if(this._context.lastText.match(/\s/)||!selection||this._context.initialTarget!==closestBlock(selection.anchorNode)){this.close();}else{const term=this._context.lastText.toLowerCase().replaceAll(/\s/g,'\\s').replaceAll('\u200B','').replace(REGEX_RESERVED_CHARS,'\\$&');if(term.length){const exactRegex=new RegExp(term,'i');const fuzzyRegex=new RegExp(term.match(/\\.|./g).join('.*'),'i');this._context.filteredCommands=this._context.commands.filter(command=>{const commandText=(command.category+' '+command.name);const commandDescription=command.description.replace(/\s/g,'');return commandText.match(fuzzyRegex)||commandDescription.match(exactRegex)||command.keywords?.some(keyword=>exactRegex.test(keyword));});}else{this._context.filteredCommands=this._context.commands;}
this._render(this._context.filteredCommands,this._context.categories);}}}
_onKeydown(ev){if(['Enter','Tab'].includes(ev.key)){ev.stopImmediatePropagation();this._pickCommand();ev.preventDefault();}else if(ev.key==='Escape'){ev.stopImmediatePropagation();this.close();ev.preventDefault();}else if(ev.key==='Backspace'&&!this._context.lastText){this.close();}else if(ev.key==='ArrowDown'||ev.key==='ArrowUp'){ev.preventDefault();ev.stopImmediatePropagation();const commandIndex=this._context.filteredCommands.findIndex(command=>command===this._context.selectedCommand,);if(this._context.filteredCommands.length&&commandIndex!==-1){const nextIndex=commandIndex+(ev.key==='ArrowDown'?1:-1);const newIndex=cycle(nextIndex,this._context.filteredCommands.length-1);this._context.selectedCommand=this._context.filteredCommands[newIndex];}else{this._context.selectedCommand=undefined;}
this._render(this._context.filteredCommands,this._context.categories);const activeCommand=this.el.querySelector('.oe-powerbox-commandWrapper.active');if(activeCommand){activeCommand.scrollIntoView({block:'nearest',inline:'nearest'});}}}}
return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/commands/align.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/commands/align',['@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{childNodeIndex,isBlock}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");Text.prototype.oAlign=function(offset,mode){this.parentElement.oAlign(childNodeIndex(this),mode);};HTMLElement.prototype.oAlign=function(offset,mode){if(!isBlock(this)){return this.parentElement.oAlign(childNodeIndex(this),mode);}
const{textAlign}=getComputedStyle(this);const alreadyAlignedLeft=textAlign==='start'||textAlign==='left';const shouldApplyStyle=!(alreadyAlignedLeft&&mode==='left');if(shouldApplyStyle){this.style.textAlign=mode;}};return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/commands/commands.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/commands/commands',['@web_editor/js/editor/odoo-editor/src/utils/constants','@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{REGEX_BOOTSTRAP_COLUMN}=require("@web_editor/js/editor/odoo-editor/src/utils/constants");const{ancestors,descendants,childNodeIndex,closestBlock,closestElement,DIRECTIONS,getCursors,getDeepRange,getInSelection,getListMode,getSelectedNodes,getTraversedNodes,insertAndSelectZws,isBlock,isColorGradient,isSelectionFormat,isShrunkBlock,isSelfClosingElement,leftLeafFirstPath,preserveCursor,rightPos,setSelection,setCursorStart,setTagName,splitAroundUntil,splitElement,splitTextNode,startPos,nodeSize,allowsParagraphRelatedElements,isUnbreakable,makeContentsInline,unwrapContents,getColumnIndex,pxToFloat,getRowIndex,parseHTML,formatSelection,getDeepestPosition,fillEmpty,isEmptyBlock,isWhitespace,isVisibleTextNode,getCursorDirection,resetOuids,FONT_SIZE_CLASSES,TEXT_STYLE_CLASSES,padLinkWithZws,isLinkEligibleForZwnbsp,paragraphRelatedElements,lastLeaf,firstLeaf,convertList,hasAnyFontSizeClass,}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");const TEXT_CLASSES_REGEX=/\btext-[^\s]*\b/;const BG_CLASSES_REGEX=/\bbg-[^\s]*\b/;function align(editor,mode){const sel=editor.document.getSelection();const visitedBlocks=new Set();const traversedNode=getTraversedNodes(editor.editable);for(const node of traversedNode){if(isVisibleTextNode(node)){const block=closestBlock(node);if(!visitedBlocks.has(block)){const hasModifier=getComputedStyle(block).textAlign===mode;if(!hasModifier&&block.isContentEditable){block.oAlign(sel.anchorOffset,mode);}
visitedBlocks.add(block);}}}}
function colorElement(element,color,mode){const newClassName=element.className.replace(mode==='color'?TEXT_CLASSES_REGEX:BG_CLASSES_REGEX,'').replace(/\btext-gradient\b/g,'').replace(/\s+/,' ');element.className!==newClassName&&(element.className=newClassName);element.style['background-image']='';if(mode==='backgroundColor'){element.style['background']='';}
if(color.startsWith('text')||color.startsWith('bg-')){element.style[mode]='';element.classList.add(color);}else if(isColorGradient(color)){element.style[mode]='';if(mode==='color'){element.style['background']='';element.style['background-image']=color;element.classList.add('text-gradient');}else{element.style['background-image']=color;}}else{element.style[mode]=color;}}
function hasColor(element,mode){const style=element.style;const parent=element.parentNode;const classRegex=mode==='color'?TEXT_CLASSES_REGEX:BG_CLASSES_REGEX;if(isColorGradient(style['background-image'])){if(element.classList.contains('text-gradient')){if(mode==='color'){return true;}}else{if(mode!=='color'){return true;}}}
return((style[mode]&&style[mode]!=='inherit'&&(!parent||style[mode]!==parent.style[mode]))||(classRegex.test(element.className)&&(!parent||getComputedStyle(element)[mode]!==getComputedStyle(parent)[mode])));}
const editorCommands=__exports.editorCommands={insert:(editor,content)=>{if(!content)return;const selection=editor.document.getSelection();let startNode;let insertBefore=false;if(!selection.isCollapsed){editor.deleteRange(selection);}
const range=selection.getRangeAt(0);const block=closestBlock(selection.anchorNode);const isSelectionAtStart=firstLeaf(block)===selection.anchorNode&&selection.anchorOffset===0;const isSelectionAtEnd=lastLeaf(block)===selection.focusNode&&selection.focusOffset===nodeSize(selection.focusNode);if(range.startContainer.nodeType===Node.TEXT_NODE){insertBefore=!range.startOffset;splitTextNode(range.startContainer,range.startOffset,DIRECTIONS.LEFT);startNode=range.startContainer;}
const container=document.createElement('fake-element');const containerFirstChild=document.createElement('fake-element-fc');const containerLastChild=document.createElement('fake-element-lc');if(typeof content==='string'){container.textContent=content;}else{container.replaceChildren(content);}
const isList=node=>['UL','OL'].includes(node.nodeName);const hasSingleChild=container.childNodes.length===1;if(closestElement(selection.anchorNode,'UL, OL')&&isList(container.firstChild)){unwrapContents(container.firstChild);}
if(closestElement(selection.focusNode,'UL, OL')&&isList(container.lastChild)&&!hasSingleChild){unwrapContents(container.lastChild);}
startNode=startNode||editor.document.getSelection().anchorNode;const shouldUnwrap=(node)=>([...paragraphRelatedElements,'LI'].includes(node.nodeName)&&block.textContent!==""&&node.textContent!==""&&[node.nodeName,'DIV'].includes(block.nodeName)&&selection.anchorNode.oid!=='root');if(container.lastElementChild&&isBlock(container.lastElementChild)&&!container.lastElementChild.hasChildNodes()){fillEmpty(container.lastElementChild);}
if(container.childElementCount===1&&(['P','LI'].includes(container.firstChild.nodeName)||shouldUnwrap(container.firstChild))&&selection.anchorNode.oid!=='root'){const p=container.firstElementChild;container.replaceChildren(...p.childNodes);}else if(container.childElementCount>1){if(shouldUnwrap(container.firstChild)&&!isSelectionAtStart){if(container.firstChild.nodeName==='LI'){const deepestBlock=closestBlock(firstLeaf(container.firstChild));splitAroundUntil(deepestBlock,container.firstChild);container.firstElementChild.replaceChildren(...deepestBlock.childNodes);}
containerFirstChild.replaceChildren(...container.firstElementChild.childNodes);container.firstElementChild.remove();}
if(shouldUnwrap(container.lastChild)&&!isSelectionAtEnd){if(container.lastChild.nodeName==='LI'){const deepestBlock=closestBlock(lastLeaf(container.lastChild));splitAroundUntil(deepestBlock,container.lastChild);container.lastElementChild.replaceChildren(...deepestBlock.childNodes);}
containerLastChild.replaceChildren(...container.lastElementChild.childNodes);container.lastElementChild.remove();}}
if(startNode.nodeType===Node.ELEMENT_NODE){if(selection.anchorOffset===0){const textNode=editor.document.createTextNode('');if(isSelfClosingElement(startNode)){startNode.parentNode.insertBefore(textNode,startNode);}else{startNode.prepend(textNode);}
startNode=textNode;}else{startNode=startNode.childNodes[selection.anchorOffset-1];}}
let currentNode=startNode;let lastChildNode=false;const currentList=currentNode&&closestElement(currentNode,'UL, OL');const mode=currentList&&getListMode(currentList);const _insertAt=(reference,nodes,insertBefore)=>{for(const child of(insertBefore?nodes.reverse():nodes)){reference[insertBefore?'before':'after'](child);reference=child;}}
const lastInsertedNodes=[...containerLastChild.childNodes];if(containerLastChild.hasChildNodes()){const toInsert=[...containerLastChild.childNodes];_insertAt(currentNode,[...toInsert],insertBefore);currentNode=insertBefore?toInsert[0]:currentNode;lastChildNode=toInsert[toInsert.length-1];}
const firstInsertedNodes=[...containerFirstChild.childNodes];if(containerFirstChild.hasChildNodes()){const toInsert=[...containerFirstChild.childNodes];_insertAt(currentNode,[...toInsert],insertBefore);currentNode=toInsert[toInsert.length-1];insertBefore=false;}
if(!container.hasChildNodes()){if(isUnbreakable(closestBlock(currentNode.nextSibling))){currentNode.nextSibling.oShiftEnter(0);}else{const parent=currentNode.nextSibling.parentElement;const index=[...parent.childNodes].indexOf(currentNode.nextSibling);parent.oEnter(index);}}
let nodeToInsert;const insertedNodes=[...container.childNodes];while((nodeToInsert=container.childNodes[0])){if(isBlock(nodeToInsert)&&!allowsParagraphRelatedElements(currentNode)){while(currentNode.parentElement!==editor.editable&&(!allowsParagraphRelatedElements(currentNode.parentElement)||(currentNode.parentElement.nodeName==="LI"&&!isUnbreakable(nodeToInsert)))){if(isUnbreakable(currentNode.parentElement)){makeContentsInline(container);nodeToInsert=container.childNodes[0];break;}
let offset=childNodeIndex(currentNode);if(!insertBefore){offset+=1;}
if(offset){const[left,right]=splitElement(currentNode.parentElement,offset);if(isUnbreakable(nodeToInsert)&&container.childNodes.length===1){fillEmpty(right);}else if(isEmptyBlock(right)&&!insertBefore){right.remove();}
currentNode=insertBefore&&right.isConnected?right:left;}else{currentNode=currentNode.parentElement;}}
if(currentNode.parentElement.nodeName==='LI'&&isUnbreakable(nodeToInsert)){const br=document.createElement('br');currentNode[currentNode.textContent?'after':'before'](br);}}
if(block.nodeName==="LI"&&paragraphRelatedElements.includes(nodeToInsert.nodeName)){setTagName(nodeToInsert,"LI");}
const isNodeToInsertContentEditable=nodeToInsert.isContentEditable;if(insertBefore){currentNode.before(nodeToInsert);insertBefore=false;}else{currentNode.after(nodeToInsert);}
let convertedList;if(currentList&&((nodeToInsert.nodeName==='LI'&&nodeToInsert.classList.contains('oe-nested'))||isList(nodeToInsert))){convertedList=convertList(nodeToInsert,mode);}
if(currentNode.tagName!=='BR'&&isShrunkBlock(currentNode)){currentNode.remove();}
if(!isNodeToInsertContentEditable&&editor.editable.firstChild===nodeToInsert&&nodeToInsert.nodeType===Node.ELEMENT_NODE&&(nodeToInsert.classList.contains("o_knowledge_behavior_type_template")||nodeToInsert.classList.contains("o_editor_banner"))){const zws=document.createTextNode("\u200B");nodeToInsert.before(zws);}
currentNode=convertedList||nodeToInsert;}
currentNode=lastChildNode||currentNode;if(!isUnbreakable(currentNode)&&currentNode.nodeName!=='BR'&&currentNode.nextSibling&&currentNode.nextSibling.nodeName==='BR'&&lastLeaf(currentNode.parentNode)===currentNode.nextSibling&&!closestElement(currentNode,'[t-field],[t-esc],[t-out]')){currentNode.nextSibling.remove();}
selection.removeAllRanges();const newRange=new Range();let lastPosition;if(currentNode.nodeName==='A'&&isLinkEligibleForZwnbsp(editor.editable,currentNode)){padLinkWithZws(editor.editable,currentNode);currentNode=currentNode.nextSibling;lastPosition=getDeepestPosition(...rightPos(currentNode));}else{lastPosition=[...paragraphRelatedElements,'LI','UL','OL'].includes(currentNode.nodeName)?rightPos(lastLeaf(currentNode)):rightPos(currentNode);}
if(lastPosition[0].nodeName==="A"&&(lastPosition[1]===nodeSize(lastPosition[0])||lastPosition[1]===0)&&isLinkEligibleForZwnbsp(editor.editable,lastPosition[0])){padLinkWithZws(editor.editable,lastPosition[0]);currentNode=lastPosition[0].nextSibling;lastPosition=getDeepestPosition(...rightPos(currentNode));}
if(!editor.options.allowInlineAtRoot&&lastPosition[0]===editor.editable){lastPosition=getDeepestPosition(...lastPosition);}
newRange.setStart(lastPosition[0],lastPosition[1]);newRange.setEnd(lastPosition[0],lastPosition[1]);selection.addRange(newRange);return[...firstInsertedNodes,...insertedNodes,...lastInsertedNodes];},insertFontAwesome:(editor,faClass='fa fa-star')=>{const insertedNode=editorCommands.insert(editor,document.createElement('i'))[0];insertedNode.className=faClass;const position=rightPos(insertedNode);setSelection(...position,...position,false);},undo:editor=>editor.historyUndo(),redo:editor=>editor.historyRedo(),setTag(editor,tagName,extraClass=""){const range=getDeepRange(editor.editable,{correctTripleClick:true});const selectedBlocks=[...new Set(getTraversedNodes(editor.editable,range).map(closestBlock).filter((block)=>block.isContentEditable)),];const deepestSelectedBlocks=selectedBlocks.filter(block=>(!descendants(block).some(descendant=>selectedBlocks.includes(descendant))&&block.isContentEditable));let{startContainer,startOffset,endContainer,endOffset}=range;const startContainerChild=startContainer.firstChild;const endContainerChild=endContainer.lastChild;for(const block of deepestSelectedBlocks){if(['P','PRE','H1','H2','H3','H4','H5','H6','LI','BLOCKQUOTE'].includes(block.nodeName,)){const inLI=block.closest('li');if(inLI&&tagName==="P"){inLI.oToggleList(0);}else{const newEl=setTagName(block,tagName);newEl.classList.remove(...FONT_SIZE_CLASSES,...TEXT_STYLE_CLASSES,"h1","h2","h3","h4","h5","h6");delete newEl.style.fontSize;if(extraClass){newEl.classList.add(extraClass);}
if(newEl.classList.length===0){newEl.removeAttribute("class");}}}else{const newBlock=editor.document.createElement(tagName);const children=[...block.childNodes];block.insertBefore(newBlock,block.firstChild);children.forEach(child=>newBlock.appendChild(child));}}
const isContextBlock=container=>['TD','DIV','LI'].includes(container.nodeName);if(!startContainer.isConnected||isContextBlock(startContainer)){startContainer=startContainerChild?.parentNode||startContainer;}
if(!endContainer.isConnected||isContextBlock(endContainer)){endContainer=endContainerChild?.parentNode||endContainer;}
const newRange=new Range();newRange.setStart(startContainer,startOffset);newRange.setEnd(endContainer,endOffset);getDeepRange(editor.editable,{range:newRange,select:true});editor.historyStep();},bold:editor=>formatSelection(editor,'bold'),italic:editor=>formatSelection(editor,'italic'),underline:editor=>formatSelection(editor,'underline'),strikeThrough:editor=>formatSelection(editor,'strikeThrough'),setFontSize:(editor,size)=>formatSelection(editor,'fontSize',{applyStyle:true,formatProps:{size}}),setFontSizeClassName:(editor,className)=>formatSelection(editor,'setFontSizeClassName',{applyStyle:true,formatProps:{className}}),switchDirection:editor=>{getDeepRange(editor.editable,{splitText:true,select:true,correctTripleClick:true});const selection=editor.document.getSelection();const selectedTextNodes=[selection.anchorNode,...getSelectedNodes(editor.editable),selection.focusNode].filter(n=>n.nodeType===Node.TEXT_NODE&&closestElement(n).isContentEditable&&n.nodeValue.trim().length);const changedElements=[];const defaultDirection=editor.options.direction;const shouldApplyStyle=!isSelectionFormat(editor.editable,'switchDirection');let blocks=new Set(selectedTextNodes.map(textNode=>closestElement(textNode,'ul,ol')||closestBlock(textNode)));blocks.forEach(block=>{blocks=[...blocks,...block.querySelectorAll('ul,ol')];})
for(const block of blocks){if(!shouldApplyStyle){block.removeAttribute('dir');}else{block.setAttribute('dir',defaultDirection==='ltr'?'rtl':'ltr');}
changedElements.push(block);}
for(const element of changedElements){const style=getComputedStyle(element);if(style.direction==='ltr'&&style.textAlign==='right'){element.style.setProperty('text-align','left');}else if(style.direction==='rtl'&&style.textAlign==='left'){element.style.setProperty('text-align','right');}}},removeFormat:editor=>{const textAlignStyles=new Map();getTraversedNodes(editor.editable).forEach((element)=>{const block=closestBlock(element);if(block.style.textAlign){textAlignStyles.set(block,block.style.textAlign);}});editor.historyPauseSteps();editor.document.execCommand('removeFormat');let hasFontSizeClass;for(const node of getTraversedNodes(editor.editable)){if(node.nodeType===Node.ELEMENT_NODE&&node.hasAttribute('color')){node.removeAttribute('color');}
const element=closestElement(node);element.style.removeProperty('color');element.style.removeProperty('background');element.style.removeProperty('-webkit-text-fill-color');if(!hasFontSizeClass&&closestElement(node,hasAnyFontSizeClass)){hasFontSizeClass=true;}}
if(hasFontSizeClass){formatSelection(editor,'setFontSizeClassName',{applyStyle:false});}
textAlignStyles.forEach((textAlign,block)=>{block.style.setProperty('text-align',textAlign);});editor.historyUnpauseSteps();},justifyLeft:editor=>align(editor,'left'),justifyRight:editor=>align(editor,'right'),justifyCenter:editor=>align(editor,'center'),justifyFull:editor=>align(editor,'justify'),unlink:editor=>{const sel=editor.document.getSelection();const isCollapsed=sel.isCollapsed;getDeepRange(editor.editable,{sel,splitText:true,select:true});if(!isCollapsed){let{anchorNode,focusNode,anchorOffset,focusOffset}=sel;const direction=getCursorDirection(anchorNode,anchorOffset,focusNode,focusOffset);const[startLink,endLink]=[closestElement(anchorNode,'a'),closestElement(focusNode,'a')];if(startLink){anchorNode=splitAroundUntil(anchorNode,startLink);anchorOffset=direction===DIRECTIONS.RIGHT?0:nodeSize(anchorNode);setSelection(anchorNode,anchorOffset,focusNode,focusOffset,true);}
if(endLink&&endLink.isConnected){focusNode=splitAroundUntil(focusNode,endLink);focusOffset=direction===DIRECTIONS.RIGHT?nodeSize(focusNode):0;setSelection(anchorNode,anchorOffset,focusNode,focusOffset,true);}}
const targetedNodes=isCollapsed?[sel.anchorNode]:getSelectedNodes(editor.editable);const links=new Set(targetedNodes.map(node=>closestElement(node,'a')).filter(a=>a&&a.isContentEditable));if(links.size){const cr=preserveCursor(editor.document);for(const link of links){unwrapContents(link);}
cr();}},indentList:(editor,mode='indent')=>{const[pos1,pos2]=getCursors(editor.document);const end=leftLeafFirstPath(...pos1).next().value;const li=new Set();for(const node of leftLeafFirstPath(...pos2)){const cli=closestElement(node,'li');if(cli&&cli.tagName=='LI'&&!li.has(cli)&&!cli.classList.contains('oe-nested')&&cli.isContentEditable&&!cli.classList.contains('nav-item')){li.add(cli);}
if(node==end)break;}
for(const node of li){if(mode=='indent'){node.oTab(0);}else{node.oShiftTab(0);}}
return true;},toggleList:(editor,mode)=>{const li=new Set();const blocks=new Set();const selectedBlocks=getTraversedNodes(editor.editable);const deepestSelectedBlocks=selectedBlocks.filter(block=>(!descendants(block).some(descendant=>selectedBlocks.includes(descendant))));for(const node of deepestSelectedBlocks){let nodeToToggle=closestBlock(node);if(![...paragraphRelatedElements,'LI'].includes(nodeToToggle.nodeName)&&node.nodeType===Node.TEXT_NODE&&isWhitespace(node)&&closestElement(node).isContentEditable){node.remove();}else{const isNavItemList=node=>node.nodeName==='LI'&&node.classList.contains('nav-item');nodeToToggle=isNavItemList(nodeToToggle)?node:nodeToToggle;if(!['OL','UL'].includes(nodeToToggle.tagName)&&(nodeToToggle.isContentEditable||nodeToToggle.nodeType===Node.TEXT_NODE)){const closestLi=closestElement(nodeToToggle,'li');nodeToToggle=closestLi&&!isNavItemList(closestLi)?closestLi:nodeToToggle;const ublock=nodeToToggle.nodeName==='LI'&&nodeToToggle.closest('ol, ul');ublock&&getListMode(ublock)==mode?li.add(nodeToToggle):blocks.add(nodeToToggle);}}}
let target=[...(blocks.size?blocks:li)];if(blocks.size){for(const block of blocks){if(block.style){block.style.padding="";}}}
while(target.length){const node=target.pop();if(!node.oToggleList(0,mode)){target=target.filter(li=>li.parentNode!=node.parentNode||li.tagName!='LI',);}}},applyColor:(editor,color,mode,element)=>{const selectedTds=[...editor.editable.querySelectorAll('td.o_selected_td')].filter(node=>closestElement(node).isContentEditable);let coloredTds=[];if(selectedTds.length&&mode==="backgroundColor"){for(const td of selectedTds){colorElement(td,color,mode);}
coloredTds=[...selectedTds];}else if(element){colorElement(element,color,mode);return[element];}
const selection=editor.document.getSelection();let wasCollapsed=false;if(selection.getRangeAt(0).collapsed&&!selectedTds.length){insertAndSelectZws(selection);wasCollapsed=true;}
const range=getDeepRange(editor.editable,{splitText:true,select:true});if(!range)return;const restoreCursor=preserveCursor(editor.document);const selectionNodes=getSelectedNodes(editor.editable).filter(node=>closestElement(node).isContentEditable);if(isEmptyBlock(range.endContainer)){selectionNodes.push(range.endContainer,...descendants(range.endContainer));}
let selectedNodes=mode==="backgroundColor"?selectionNodes.filter(node=>!closestElement(node,'table.o_selected_table')):selectionNodes;const findTopMostDecoration=(current)=>{const decoration=closestElement(current.parentNode,"s, u");return decoration?.textContent===current.textContent?findTopMostDecoration(decoration):current;};selectedNodes=selectedNodes.map((node)=>{return findTopMostDecoration(node);});const selectedFieldNodes=new Set(getSelectedNodes(editor.editable).map(n=>closestElement(n,"*[t-field],*[t-out],*[t-esc]")).filter(Boolean));function getFonts(selectedNodes){return selectedNodes.flatMap(node=>{let font=closestElement(node,'font')||closestElement(node,'span');const children=font&&descendants(font);const hasInlineGradient=font&&isColorGradient(font.style["background-image"]);if(font&&(font.nodeName==="FONT"||(font.nodeName==="SPAN"&&font.style[mode]))&&(isColorGradient(color)||color===""||!hasInlineGradient)){const selectedChildren=children.filter(child=>selectedNodes.includes(child));if(selectedChildren.length){const closestGradientEl=closestElement(node,'font[style*="background-image"], span[style*="background-image"]');const isGradientBeingUpdated=closestGradientEl&&isColorGradient(color);const splitnode=isGradientBeingUpdated?closestGradientEl:font;font=splitAroundUntil(selectedChildren,splitnode);if(isGradientBeingUpdated){const classRegex=mode==='color'?TEXT_CLASSES_REGEX:BG_CLASSES_REGEX;for(const node of descendants(font)){if(node.nodeType===Node.ELEMENT_NODE&&(node.style[mode]||classRegex.test(node.className))){colorElement(node,"",mode);node.style.webkitTextFillColor="";}}}else if(mode==="color"&&(font.style.webkitTextFillColor||closestGradientEl&&closestGradientEl.classList.contains("text-gradient"))){font.style.webkitTextFillColor=color;}}else{font=[];}}else if((node.nodeType===Node.TEXT_NODE&&!isWhitespace(node)&&node.textContent!=='\ufeff')||(node.nodeName==='BR'&&isEmptyBlock(node.parentNode))||(node.nodeType===Node.ELEMENT_NODE&&node.nodeName!=='FIGURE'&&['inline','inline-block'].includes(getComputedStyle(node).display)&&!isWhitespace(node.textContent)&&!node.classList.contains('btn')&&!node.querySelector('font'))&&node.nodeName!=='A'&&!(node.nodeName==='SPAN'&&node.style['fontSize'])){const previous=node.previousSibling;const classRegex=mode==='color'?BG_CLASSES_REGEX:TEXT_CLASSES_REGEX;if(previous&&previous.nodeName==='FONT'&&!previous.style[mode==='color'?'backgroundColor':'color']&&!classRegex.test(previous.className)&&selectedNodes.includes(previous.firstChild)&&selectedNodes.includes(previous.lastChild)){font=previous;}else{const isTextGradient=hasInlineGradient&&font.classList.contains("text-gradient");font=document.createElement('font');node.after(font);if(isTextGradient&&mode==="color"){font.style.webkitTextFillColor=color;}}
if(node.textContent){font.appendChild(node);}else{fillEmpty(font);}}else{font=[];}
return font;});}
for(const fieldNode of selectedFieldNodes){colorElement(fieldNode,color,mode);}
let fonts=getFonts(selectedNodes);if(!fonts.every((font)=>font.isConnected)){fonts=getFonts(selectedNodes);}
const fontsSet=new Set(fonts);for(const font of fontsSet){colorElement(font,color,mode);if((!hasColor(font,'color')&&!hasColor(font,'backgroundColor'))&&(!font.hasAttribute('style')||!color)){for(const child of[...font.childNodes]){font.parentNode.insertBefore(child,font);}
font.parentNode.removeChild(font);fontsSet.delete(font);}}
restoreCursor();if(wasCollapsed){const newSelection=editor.document.getSelection();const range=new Range();range.setStart(newSelection.anchorNode,newSelection.anchorOffset);range.collapse(true);newSelection.removeAllRanges();newSelection.addRange(range);}
return[...fontsSet,...coloredTds];},insertTable:(editor,{rowNumber=2,colNumber=2}={})=>{const tdsHtml=new Array(colNumber).fill('<td><p><br></p></td>').join('');const trsHtml=new Array(rowNumber).fill(`<tr>${tdsHtml}</tr>`).join('');const tableHtml=`<table class="table table-bordered o_table"><tbody>${trsHtml}</tbody></table>`;const sel=editor.document.getSelection();if(!sel.isCollapsed){editor.deleteRange(sel);}
while(!isBlock(sel.anchorNode)){const anchorNode=sel.anchorNode;const isTextNode=anchorNode.nodeType===Node.TEXT_NODE;const newAnchorNode=isTextNode?splitTextNode(anchorNode,sel.anchorOffset,DIRECTIONS.LEFT)+1&&anchorNode:splitElement(anchorNode,sel.anchorOffset).shift();const newPosition=rightPos(newAnchorNode);setSelection(...newPosition,...newPosition,false);}
const[table]=editorCommands.insert(editor,parseHTML(editor.document,tableHtml));setCursorStart(table.querySelector('p'));},addColumn:(editor,beforeOrAfter,referenceCell)=>{if(!referenceCell){getDeepRange(editor.editable,{select:true});referenceCell=getInSelection(editor.document,'td');if(!referenceCell)return;}
const columnIndex=getColumnIndex(referenceCell);const table=closestElement(referenceCell,'table');const tableWidth=table.style.width?pxToFloat(table.style.width):table.clientWidth;const referenceColumn=table.querySelectorAll(`tr td:nth-of-type(${columnIndex + 1})`);const referenceCellWidth=referenceCell.style.width?pxToFloat(referenceCell.style.width):referenceCell.clientWidth;const firstRow=table.querySelector('tr');const firstRowCells=[...firstRow.children].filter(child=>child.nodeName==='TD'||child.nodeName==='TH');let totalWidth=0;for(const cell of firstRowCells){const width=cell.style.width?pxToFloat(cell.style.width):cell.clientWidth;cell.style.width=width+'px';const newWidth=Math.max(Math.round((width*tableWidth)/(tableWidth+referenceCellWidth-1)),13);cell.style.width=newWidth+'px';totalWidth+=newWidth;}
referenceColumn.forEach((cell,rowIndex)=>{const newCell=document.createElement('td');const p=document.createElement('p');p.append(document.createElement('br'));newCell.append(p);cell[beforeOrAfter](newCell);if(rowIndex===0){newCell.style.width=cell.style.width;totalWidth+=pxToFloat(cell.style.width);}});if(totalWidth!==tableWidth-1){firstRowCells[firstRowCells.length-1].style.width=pxToFloat(firstRowCells[firstRowCells.length-1].style.width)+(tableWidth-totalWidth-1)+'px';}
table.style.width=tableWidth+'px';},addRow:(editor,beforeOrAfter,referenceRow)=>{if(!referenceRow){getDeepRange(editor.editable,{select:true});referenceRow=getInSelection(editor.document,'tr');if(!referenceRow)return;}
const referenceRowHeight=referenceRow.style.height?pxToFloat(referenceRow.style.height):referenceRow.clientHeight;const newRow=document.createElement('tr');newRow.style.height=referenceRowHeight+'px';const cells=referenceRow.querySelectorAll('td');newRow.append(...Array.from(Array(cells.length)).map(()=>{const td=document.createElement('td');const p=document.createElement('p');p.append(document.createElement('br'));td.append(p);return td;}));referenceRow[beforeOrAfter](newRow);newRow.style.height=referenceRowHeight+'px';if(getRowIndex(newRow)===0){let columnIndex=0;for(const newColumn of newRow.children){newColumn.style.width=cells[columnIndex].style.width;cells[columnIndex].style.width='';columnIndex++;}}},removeColumn:(editor,cell)=>{if(!cell){getDeepRange(editor.editable,{select:true});cell=getInSelection(editor.document,'td');if(!cell)return;}
const table=closestElement(cell,'table');const cells=[...closestElement(cell,'tr').querySelectorAll('th, td')];const index=cells.findIndex(td=>td===cell);const siblingCell=cells[index-1]||cells[index+1];if(table.style.width){const tableRect=table.getBoundingClientRect();const cellRect=cell.getBoundingClientRect();table.style.width=tableRect.width-cellRect.width+'px';}
table.querySelectorAll(`tr td:nth-of-type(${index + 1})`).forEach(td=>td.remove());siblingCell?setSelection(...startPos(siblingCell)):editorCommands.deleteTable(editor,table);},removeRow:(editor,row)=>{if(!row){getDeepRange(editor.editable,{select:true});row=getInSelection(editor.document,'tr');if(!row)return;}
const table=closestElement(row,'table');const rows=[...table.querySelectorAll('tr')];const rowIndex=rows.findIndex(tr=>tr===row);const siblingRow=rows[rowIndex-1]||rows[rowIndex+1];row.remove();siblingRow?setSelection(...startPos(siblingRow)):editorCommands.deleteTable(editor,table);},resetSize:(editor,table)=>{if(!table){getDeepRange(editor.editable,{select:true});table=getInSelection(editor.document,'table');}
table.removeAttribute('style');const cells=[...table.querySelectorAll('tr, td')];cells.forEach(cell=>{const cStyle=cell.style;if(cell.tagName==='TR'){cStyle.height='';}else{cStyle.width='';}})},deleteTable:(editor,table)=>{table=table||getInSelection(editor.document,'table');if(!table)return;const p=document.createElement('p');p.appendChild(document.createElement('br'));table.before(p);table.remove();setSelection(p,0);},columnize:(editor,numberOfColumns,addParagraphAfter=true)=>{const sel=editor.document.getSelection();const anchor=sel.anchorNode;const hasColumns=!!closestElement(anchor,'.o_text_columns');if(!numberOfColumns&&hasColumns){const restore=preserveCursor(editor.document);const container=closestElement(anchor,'.o_text_columns');const rows=unwrapContents(container);for(const row of rows){const columns=unwrapContents(row);for(const column of columns){const columnContents=unwrapContents(column);for(const node of columnContents){resetOuids(node);}}}
restore();}else if(numberOfColumns&&!hasColumns){const restore=preserveCursor(editor.document);const container=document.createElement('div');if(!closestElement(anchor,'.container')){container.classList.add('container');}
container.classList.add('o_text_columns');const row=document.createElement('div');row.classList.add('row');container.append(row);const block=closestBlock(anchor);resetOuids(block);const columnSize=Math.floor(12/numberOfColumns);const columns=[];for(let i=0;i<numberOfColumns;i++){const column=document.createElement('div');column.classList.add(`col-${columnSize}`);row.append(column);columns.push(column);}
block.before(container);columns.shift().append(block);for(const column of columns){const p=document.createElement('p');p.append(document.createElement('br'));p.classList.add('oe-hint');p.setAttribute('placeholder','New column...');column.append(p);}
restore();if(addParagraphAfter){const p=document.createElement('p');p.append(document.createElement('br'));container.after(p);}}else if(numberOfColumns&&hasColumns){const row=closestElement(anchor,'.row');const columns=[...row.children];const columnSize=Math.floor(12/numberOfColumns);const diff=numberOfColumns-columns.length;if(diff>0){const restore=preserveCursor(editor.document);for(const column of columns){column.className=column.className.replace(REGEX_BOOTSTRAP_COLUMN,`col$1-${columnSize}`);}
let lastColumn=columns[columns.length-1];for(let i=0;i<diff;i++){const column=document.createElement('div');column.classList.add(`col-${columnSize}`);const p=document.createElement('p');p.append(document.createElement('br'));p.classList.add('oe-hint');p.setAttribute('placeholder','New column...');column.append(p);lastColumn.after(column);lastColumn=column;}
restore();}else if(diff<0){const restore=preserveCursor(editor.document);for(const column of columns){column.className=column.className.replace(REGEX_BOOTSTRAP_COLUMN,`col$1-${columnSize}`);}
const contents=[];for(let i=diff;i<0;i++){const column=columns.pop();const columnContents=unwrapContents(column);for(const node of columnContents){resetOuids(node);}
contents.unshift(...columnContents);}
columns[columns.length-1].append(...contents);restore();}}},insertHorizontalRule(editor){const selection=editor.document.getSelection();const range=selection.getRangeAt(0);const element=closestElement(range.startContainer,paragraphRelatedElements)||closestBlock(range.startContainer);if(element&&ancestors(element).includes(editor.editable)){element.before(editor.document.createElement('hr'));}},};return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/commands/deleteBackward.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/commands/deleteBackward',['@web_editor/js/editor/odoo-editor/src/utils/constants','@web_editor/js/editor/odoo-editor/src/commands/deleteForward','@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{UNBREAKABLE_ROLLBACK_CODE,UNREMOVABLE_ROLLBACK_CODE,REGEX_BOOTSTRAP_COLUMN}=require("@web_editor/js/editor/odoo-editor/src/utils/constants");const{deleteText}=require("@web_editor/js/editor/odoo-editor/src/commands/deleteForward");const{boundariesOut,childNodeIndex,CTGROUPS,CTYPES,DIRECTIONS,endPos,fillEmpty,getState,isBlock,isEmptyBlock,isUnbreakable,isUnremovable,isVisible,leftPos,rightPos,moveNodes,nodeSize,paragraphRelatedElements,prepareUpdate,setSelection,isMediaElement,isSelfClosingElement,isNotEditableNode,createDOMPathGenerator,closestElement,closestBlock,getOffsetAndCharSize,ZERO_WIDTH_CHARS,isButton,}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");Text.prototype.oDeleteBackward=function(offset,alreadyMoved=false){const parentElement=this.parentElement;if(!offset){parentElement.oDeleteBackward([...parentElement.childNodes].indexOf(this),alreadyMoved);return;}
const[newOffset,charSize]=getOffsetAndCharSize(this.nodeValue,offset,DIRECTIONS.LEFT);deleteText.call(this,charSize,newOffset-charSize,DIRECTIONS.LEFT,alreadyMoved);};const isDeletable=(node)=>{return isMediaElement(node)||isNotEditableNode(node);}
HTMLElement.prototype.oDeleteBackward=function(offset,alreadyMoved=false,offsetLimit){const contentIsZWS=ZERO_WIDTH_CHARS.includes(this.textContent);let moveDest;if(offset){const leftNode=this.childNodes[offset-1];if(isUnremovable(leftNode)){throw UNREMOVABLE_ROLLBACK_CODE;}
if(isDeletable(leftNode)){const parentEl=leftNode.parentElement;leftNode.remove();fillEmpty(parentEl);return;}
if(!isBlock(leftNode)||isSelfClosingElement(leftNode)){leftNode.oDeleteBackward(nodeSize(leftNode),alreadyMoved);return;}
alreadyMoved=true;moveDest=endPos(leftNode);}else{if(isUnremovable(this)){throw UNREMOVABLE_ROLLBACK_CODE;}
if(isUnbreakable(this)&&(REGEX_BOOTSTRAP_COLUMN.test(this.className)||!isEmptyBlock(this))){throw UNBREAKABLE_ROLLBACK_CODE;}
const parentEl=this.parentElement;if(parentEl&&parentEl.getAttribute("contenteditable")==="true"&&parentEl.oid!=="root"&&parentEl.parentElement&&!parentEl.parentElement.isContentEditable&&paragraphRelatedElements.includes(this.tagName)&&!this.previousElementSibling){throw UNREMOVABLE_ROLLBACK_CODE;}
const closestLi=closestElement(this,'li');if((closestLi&&!closestLi.previousElementSibling)||!isBlock(this)||isSelfClosingElement(this)){const parentOffset=childNodeIndex(this);if(!nodeSize(this)||contentIsZWS){const visible=isVisible(this)||isButton(this);const restore=prepareUpdate(...boundariesOut(this));this.remove();restore();fillEmpty(parentEl);if(visible){setSelection(parentEl,parentOffset);return;}}
parentEl.oDeleteBackward(parentOffset,alreadyMoved);return;}
const previousElementSiblingClosestBlock=closestBlock(this.previousElementSibling);if(previousElementSiblingClosestBlock&&(isEmptyBlock(previousElementSiblingClosestBlock)||previousElementSiblingClosestBlock.textContent==='\u200B')&&paragraphRelatedElements.includes(this.nodeName)){previousElementSiblingClosestBlock.remove();setSelection(this,0);return;}
if(!this.previousElementSibling&&paragraphRelatedElements.includes(this.nodeName)&&this.nodeName!=='P'&&!closestLi){if(!this.textContent){const p=document.createElement('p');p.replaceChildren(...this.childNodes);this.replaceWith(p);setSelection(p,offset);}
return;}else{moveDest=leftPos(this);}}
const domPathGenerator=createDOMPathGenerator(DIRECTIONS.LEFT,{leafOnly:true,stopTraverseFunction:isDeletable,});const domPath=domPathGenerator(this,offset)
const leftNode=domPath.next().value;if(leftNode&&isDeletable(leftNode)){const[parent,offset]=rightPos(leftNode);return parent.oDeleteBackward(offset,alreadyMoved);}
let node=this.childNodes[offset];const nextSibling=this.nextSibling;let currentNodeIndex=offset;if(offsetLimit===undefined){while(node&&!isBlock(node)){node=node.nextSibling;currentNodeIndex++;}}else{currentNodeIndex=offsetLimit;}
let[cursorNode,cursorOffset]=moveNodes(...moveDest,this,offset,currentNodeIndex);setSelection(cursorNode,cursorOffset);if(cursorNode.nodeType===Node.TEXT_NODE&&(cursorOffset===0||cursorOffset===cursorNode.length)){cursorOffset=childNodeIndex(cursorNode)+(cursorOffset===0?0:1);cursorNode=cursorNode.parentNode;}
if(cursorNode.nodeType!==Node.TEXT_NODE){const{cType}=getState(cursorNode,cursorOffset,DIRECTIONS.LEFT);if(cType&CTGROUPS.BLOCK&&(!alreadyMoved||cType===CTYPES.BLOCK_OUTSIDE)){cursorNode.oDeleteBackward(cursorOffset,alreadyMoved,cursorOffset+currentNodeIndex-offset);}else if(!alreadyMoved){const cursorNodeNode=cursorNode.childNodes[cursorOffset];const cursorNodeRightNode=cursorNodeNode?cursorNodeNode.nextSibling:undefined;if(cursorNodeRightNode&&cursorNodeRightNode.nodeType===Node.TEXT_NODE&&nextSibling===cursorNodeRightNode){moveDest[0].insertBefore(document.createElement('br'),cursorNodeRightNode);}}}};HTMLLIElement.prototype.oDeleteBackward=function(offset,alreadyMoved=false){if(offset===0){this.oToggleList(offset);return;}
HTMLElement.prototype.oDeleteBackward.call(this,offset,alreadyMoved);};HTMLBRElement.prototype.oDeleteBackward=function(offset,alreadyMoved=false){const parentOffset=childNodeIndex(this);const rightState=getState(this.parentElement,parentOffset+1,DIRECTIONS.RIGHT).cType;if(rightState&CTYPES.BLOCK_INSIDE){this.parentElement.oDeleteBackward(parentOffset,alreadyMoved);}else{HTMLElement.prototype.oDeleteBackward.call(this,offset,alreadyMoved);}};HTMLTableCellElement.prototype.oDeleteBackward=function(offset,alreadyMoved=false){if(offset){HTMLElement.prototype.oDeleteBackward.call(this,offset,alreadyMoved);}};return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/commands/deleteForward.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/commands/deleteForward',['@web_editor/js/editor/odoo-editor/src/utils/constants','@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{UNREMOVABLE_ROLLBACK_CODE}=require("@web_editor/js/editor/odoo-editor/src/utils/constants");const{findNode,isSelfClosingElement,nodeSize,rightPos,getState,DIRECTIONS,CTYPES,leftPos,isIconElement,rightLeafOnlyNotBlockNotEditablePath,rightLeafOnlyPathNotBlockNotEditablePath,isNotEditableNode,splitTextNode,paragraphRelatedElements,prepareUpdate,isInPre,fillEmpty,setSelection,isZWS,childNodeIndex,boundariesOut,isEditorTab,isVisible,isUnbreakable,isEmptyBlock,isWhitespace,isVisibleTextNode,getOffsetAndCharSize,ZERO_WIDTH_CHARS,}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");__exports.deleteText=deleteText;function deleteText(charSize,offset,direction,alreadyMoved){const parentElement=this.parentElement;const firstSplitOffset=splitTextNode(this,offset);const secondSplitOffset=splitTextNode(parentElement.childNodes[firstSplitOffset],charSize);const middleNode=parentElement.childNodes[firstSplitOffset];const restore=prepareUpdate(parentElement,firstSplitOffset,parentElement,secondSplitOffset);const isSpace=isWhitespace(middleNode)&&!isInPre(middleNode);const isZWS=ZERO_WIDTH_CHARS.includes(middleNode.nodeValue);middleNode.remove();restore();const parentState=getState(parentElement,firstSplitOffset,direction);if(isZWS||(isSpace&&(parentState.cType!==CTYPES.CONTENT||parentState.node===undefined))){if(direction===DIRECTIONS.LEFT){parentElement.oDeleteBackward(firstSplitOffset,alreadyMoved);}else{if(isSpace&&parentState.node==undefined){this.oDeleteForward(offset,alreadyMoved);}else{parentElement.oDeleteForward(firstSplitOffset,alreadyMoved);}}
if(isZWS&&parentElement.isConnected){fillEmpty(parentElement);}
return;}
if(parentElement.tagName==="CODE"&&!parentElement.textContent.length){parentElement.remove();return;}
fillEmpty(parentElement);setSelection(parentElement,firstSplitOffset);}
Text.prototype.oDeleteForward=function(offset,alreadyMoved=false){const parentElement=this.parentElement;if(offset===this.nodeValue.length){parentElement.oDeleteForward([...parentElement.childNodes].indexOf(this)+1);return;}
const[newOffset,charSize]=getOffsetAndCharSize(this.nodeValue,offset+1,DIRECTIONS.RIGHT);deleteText.call(this,charSize,newOffset,DIRECTIONS.RIGHT,alreadyMoved);};HTMLElement.prototype.oDeleteForward=function(offset){const filterFunc=node=>isSelfClosingElement(node)||isVisibleTextNode(node)||isNotEditableNode(node);const firstLeafNode=findNode(rightLeafOnlyNotBlockNotEditablePath(this,offset),filterFunc);if(firstLeafNode&&isZWS(firstLeafNode)&&this.parentElement.hasAttribute('data-oe-zws-empty-inline')){const grandparent=this.parentElement.parentElement;if(!grandparent){return;}
const parentIndex=childNodeIndex(this.parentElement);const restore=prepareUpdate(...boundariesOut(this.parentElement));this.parentElement.remove();restore();HTMLElement.prototype.oDeleteForward.call(grandparent,parentIndex);return;}else if(firstLeafNode&&firstLeafNode.nodeType===Node.TEXT_NODE&&firstLeafNode.textContent==='\ufeff'){firstLeafNode.oDeleteForward(1);return;}
if(this.hasAttribute&&this.hasAttribute('data-oe-zws-empty-inline')&&(isZWS(this)||(this.textContent===''&&this.childNodes.length===0))){const parent=this.parentElement;if(!parent){return;}
const index=childNodeIndex(this);const restore=prepareUpdate(...boundariesOut(this));this.remove();restore();HTMLElement.prototype.oDeleteForward.call(parent,index);return;}
if(firstLeafNode&&(isIconElement(firstLeafNode)||isNotEditableNode(firstLeafNode))){const nextSibling=firstLeafNode.nextSibling;const nextSiblingText=nextSibling?nextSibling.textContent:'';const parentEl=firstLeafNode.parentElement;firstLeafNode.remove();if(isEditorTab(firstLeafNode)&&nextSiblingText[0]==='\u200B'){nextSibling.textContent=nextSiblingText.replace('\u200B','');}
fillEmpty(parentEl);return;}
if(firstLeafNode&&(firstLeafNode.nodeName!=='BR'||getState(...rightPos(firstLeafNode),DIRECTIONS.RIGHT).cType!==CTYPES.BLOCK_INSIDE)){firstLeafNode.oDeleteBackward(Math.min(1,nodeSize(firstLeafNode)));return;}
let nextSibling=this.nextSibling;while(nextSibling&&isWhitespace(nextSibling)){const index=childNodeIndex(nextSibling);const left=getState(nextSibling,index,DIRECTIONS.LEFT).cType;const right=getState(nextSibling,index,DIRECTIONS.RIGHT).cType;if(left===CTYPES.BLOCK_OUTSIDE&&right===CTYPES.BLOCK_OUTSIDE){nextSibling.remove();nextSibling=this.nextSibling;}else{break;}}
if((offset===this.childNodes.length||(this.childNodes.length===1&&this.childNodes[0].tagName==='BR'))&&this.parentElement&&nextSibling&&['LI','UL','OL'].includes(nextSibling.tagName)){const nextSiblingNestedLi=nextSibling.querySelector('li:first-child');if(nextSiblingNestedLi){this.after(nextSiblingNestedLi);if(!isVisible(nextSibling,false)||nextSibling.textContent===''){nextSibling.remove();}
HTMLElement.prototype.oDeleteBackward.call(nextSiblingNestedLi,0,true);}else{HTMLElement.prototype.oDeleteBackward.call(nextSibling,0);}
return;}
if(nextSibling&&nextSibling.nodeType===Node.ELEMENT_NODE&&!nextSibling.isContentEditable){nextSibling.remove();return;}
const parentEl=this.parentElement;if(parentEl&&parentEl.getAttribute("contenteditable")==="true"&&parentEl.oid!=="root"&&parentEl.parentElement&&!parentEl.parentElement.isContentEditable&&paragraphRelatedElements.includes(this.tagName)&&!this.nextElementSibling){throw UNREMOVABLE_ROLLBACK_CODE;}
const firstOutNode=findNode(rightLeafOnlyPathNotBlockNotEditablePath(...(firstLeafNode?rightPos(firstLeafNode):[this,offset]),),filterFunc,);if(firstOutNode){if(nextSibling&&isUnbreakable(nextSibling)&&isEmptyBlock(this)){const restore=prepareUpdate(...boundariesOut(this));this.remove();restore();setSelection(firstOutNode,0);return;}
const[node,offset]=leftPos(firstOutNode);if(node.tagName==='LI'){HTMLElement.prototype.oDeleteBackward.call(node,offset);return;}
node.oDeleteBackward(offset);return;}};return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/commands/enter.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/commands/enter',['@web_editor/js/editor/odoo-editor/src/utils/constants','@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{UNBREAKABLE_ROLLBACK_CODE}=require("@web_editor/js/editor/odoo-editor/src/utils/constants");const{childNodeIndex,fillEmpty,isBlock,isUnbreakable,prepareUpdate,setCursorStart,setCursorEnd,setTagName,splitTextNode,toggleClass,isVisible,descendants,isVisibleTextNode,nodeSize,getTraversedNodes,setSelection,}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");Text.prototype.oEnter=function(offset){this.parentElement.oEnter(splitTextNode(this,offset),true);};HTMLElement.prototype.oEnter=function(offset,firstSplit=true){let didSplit=false;if(isUnbreakable(this)){throw UNBREAKABLE_ROLLBACK_CODE;}
if(!this.textContent&&['BLOCKQUOTE','PRE'].includes(this.parentElement.nodeName)&&!this.nextSibling){const parent=this.parentElement;const index=childNodeIndex(this);if(this.previousElementSibling){this.remove();return parent.oEnter(index,!didSplit);}
return parent.oEnter(index+1,!didSplit);}
let restore;if(firstSplit){restore=prepareUpdate(this,offset);}
let splitEl=this.cloneNode(false);while(offset<this.childNodes.length){splitEl.appendChild(this.childNodes[offset]);}
if(isBlock(this)||splitEl.hasChildNodes()){this.after(splitEl);if(isBlock(splitEl)||isVisible(splitEl)||splitEl.textContent==='\u200B'){didSplit=true;}else{splitEl.remove();}}
if(!isBlock(this)||(this.nodeName!=='LI'&&this.closest('LI'))){if(this.parentElement){this.parentElement.oEnter(childNodeIndex(this)+1,!didSplit);}else{throw UNBREAKABLE_ROLLBACK_CODE;}}
if(firstSplit&&didSplit){restore();let node=this;while(!isBlock(node)&&!isVisible(node)){const toRemove=node;node=node.parentNode;toRemove.remove();}
fillEmpty(node);fillEmpty(splitEl);if(splitEl.tagName==='A'){while(!isBlock(splitEl)&&!isVisible(splitEl)){const toRemove=splitEl;splitEl=splitEl.parentNode;toRemove.remove();}}
setCursorStart(splitEl);}
return splitEl;};HTMLHeadingElement.prototype.oEnter=function(){const newEl=HTMLElement.prototype.oEnter.call(this,...arguments);if(newEl&&!descendants(newEl).some(isVisibleTextNode)){const node=setTagName(newEl,'P');node.replaceChildren(document.createElement('br'));setCursorStart(node);}};const isAtEdgeofLink=(link,offset)=>{const childNodes=[...link.childNodes];let firstVisibleIndex=childNodes.findIndex(isVisible);firstVisibleIndex=firstVisibleIndex===-1?0:firstVisibleIndex;if(offset<=firstVisibleIndex){return'start';}
let lastVisibleIndex=childNodes.reverse().findIndex(isVisible);lastVisibleIndex=lastVisibleIndex===-1?0:childNodes.length-lastVisibleIndex;if(offset>=lastVisibleIndex){return'end';}
return false;}
HTMLAnchorElement.prototype.oEnter=function(offset){const edge=isAtEdgeofLink(this,offset);if(edge==='start'){if(this.previousSibling){return HTMLElement.prototype.oEnter.call(this.previousSibling,nodeSize(this.previousSibling));}else{const index=childNodeIndex(this);return HTMLElement.prototype.oEnter.call(this.parentElement,index?index-1:0);}}else if(edge==='end'){if(this.nextSibling){return HTMLElement.prototype.oEnter.call(this.nextSibling,0);}else{return HTMLElement.prototype.oEnter.call(this.parentElement,childNodeIndex(this));}}else{HTMLElement.prototype.oEnter.call(this,...arguments);}}
HTMLQuoteElement.prototype.oEnter=HTMLHeadingElement.prototype.oEnter;HTMLLIElement.prototype.oEnter=function(){const traverseNodes=getTraversedNodes(this);const isContainUnbreakable=traverseNodes.some(isUnbreakable);if(this.textContent||isContainUnbreakable){const node=HTMLElement.prototype.oEnter.call(this,...arguments);if(node.classList.contains('o_checked')){toggleClass(node,'o_checked');}
return node;}
this.oShiftTab();};HTMLPreElement.prototype.oEnter=function(offset){if(offset<this.childNodes.length){const lineBreak=document.createElement('br');this.insertBefore(lineBreak,this.childNodes[offset]);setCursorEnd(lineBreak);}else{if(this.parentElement.nodeName==='LI'){setSelection(this.parentElement,childNodeIndex(this)+1);HTMLLIElement.prototype.oEnter.call(this.parentElement,...arguments);return;}
const node=document.createElement('p');this.parentNode.insertBefore(node,this.nextSibling);fillEmpty(node);setCursorStart(node);}};return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/commands/shiftEnter.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/commands/shiftEnter',['@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{CTYPES,DIRECTIONS,isFakeLineBreak,prepareUpdate,rightPos,setSelection,getState,leftPos,splitTextNode,isBlock,}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");Text.prototype.oShiftEnter=function(offset){return this.parentElement.oShiftEnter(splitTextNode(this,offset));};HTMLElement.prototype.oShiftEnter=function(offset){const restore=prepareUpdate(this,offset);const brEl=document.createElement('br');const brEls=[brEl];if(offset>=this.childNodes.length){this.appendChild(brEl);}else{this.insertBefore(brEl,this.childNodes[offset]);}
if(isFakeLineBreak(brEl)&&getState(...leftPos(brEl),DIRECTIONS.LEFT).cType!==CTYPES.BR){const brEl2=document.createElement('br');brEl.before(brEl2);brEls.unshift(brEl2);}
restore();for(const el of brEls){if(el.parentNode){setSelection(...rightPos(el));break;}}
return brEls;};HTMLAnchorElement.prototype.oShiftEnter=function(){const brs=HTMLElement.prototype.oShiftEnter.call(this,...arguments);const anchor=brs[0].parentElement;let firstChild=anchor.firstChild;if(firstChild&&firstChild.nodeType===Node.TEXT_NODE&&firstChild.textContent==='\uFEFF'){firstChild=anchor.childNodes[1];}
let lastChild=anchor.lastChild;if(lastChild&&lastChild.nodeType===Node.TEXT_NODE&&lastChild.textContent==='\uFEFF'){lastChild=anchor.childNodes.length>1&&anchor.childNodes[anchor.childNodes.length-2];}
if(brs.includes(firstChild)){brs.forEach(br=>anchor.before(br));}else if(brs.includes(lastChild)){const brToRemove=isBlock(anchor)&&brs.pop();brs.forEach(br=>anchor.after(br));if(brToRemove){brToRemove.remove();setSelection(...leftPos(brs[0]));}else{setSelection(...rightPos(brs[0]));}}}
return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/commands/shiftTab.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/commands/shiftTab',['@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{isUnbreakable,preserveCursor,toggleClass,isBlock,isVisible}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");Text.prototype.oShiftTab=function(){return this.parentElement.oShiftTab(0);};HTMLElement.prototype.oShiftTab=function(offset=undefined){if(!isUnbreakable(this)){return this.parentElement.oShiftTab(offset);}
return false;};HTMLLIElement.prototype.oShiftTab=function(){const li=this;if(li.nextElementSibling){const ul=li.parentElement.cloneNode(false);while(li.nextSibling){ul.append(li.nextSibling);}
if(li.parentNode.parentNode.tagName==='LI'){const lip=document.createElement('li');toggleClass(lip,'oe-nested');lip.append(ul);li.parentNode.parentNode.after(lip);}else{li.parentNode.after(ul);}}
const restoreCursor=preserveCursor(this.ownerDocument);if(li.parentNode.parentNode.tagName==='LI'&&!li.parentNode.parentNode.classList.contains('nav-item')){const ul=li.parentNode;const shouldRemoveParentLi=!li.previousElementSibling&&!ul.previousElementSibling;const toremove=shouldRemoveParentLi?ul.parentNode:null;ul.parentNode.after(li);if(toremove){if(toremove.classList.contains('oe-nested')){toremove.remove();}else{ul.remove();}}
restoreCursor();return li;}else{const ul=li.parentNode;const dir=ul.getAttribute('dir');let p;while(li.firstChild){if(isBlock(li.firstChild)){if(p&&isVisible(p)){ul.after(p);}
p=undefined;ul.after(li.firstChild);}else{p=p||document.createElement('P');if(dir){p.setAttribute('dir',dir);p.style.setProperty('text-align',ul.style.getPropertyValue('text-align'));}
p.append(li.firstChild);}}
if(p&&isVisible(p)){ul.after(p)}
restoreCursor(new Map([[li,ul.nextSibling]]));li.remove();if(!ul.firstElementChild){ul.remove();}}
return false;};return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/commands/tab.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/commands/tab',['@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{createList,getListMode,isBlock,preserveCursor,toggleClass}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");Text.prototype.oTab=function(){return this.parentElement.oTab(0);};HTMLElement.prototype.oTab=function(offset){if(!isBlock(this)){return this.parentElement.oTab(offset);}
return false;};HTMLLIElement.prototype.oTab=function(){const lip=document.createElement('li');const destul=(this.previousElementSibling&&this.previousElementSibling.querySelector('ol, ul'))||(this.nextElementSibling&&this.nextElementSibling.querySelector('ol, ul'))||this.closest('ul, ol');const ul=createList(getListMode(destul));lip.append(ul);const cr=preserveCursor(this.ownerDocument);toggleClass(lip,'oe-nested');this.before(lip);ul.append(this);cr();return true;};return __exports;});;

/* /web_editor/static/src/js/editor/odoo-editor/src/commands/toggleList.js */
odoo.define('@web_editor/js/editor/odoo-editor/src/commands/toggleList',['@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{childNodeIndex,isBlock,preserveCursor,insertListAfter,getAdjacents,closestElement,toggleList,}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");Text.prototype.oToggleList=function(offset,mode){if(closestElement(this,'li').classList.contains('nav-item')){const restoreCursor=preserveCursor(this.ownerDocument);insertListAfter(this,mode,[this]);restoreCursor();}else{this.parentElement.oToggleList(childNodeIndex(this),mode);}};HTMLElement.prototype.oToggleList=function(offset,mode='UL'){if(!isBlock(this)){return this.parentElement.oToggleList(childNodeIndex(this));}
const closestLi=this.closest('li');if(closestLi&&!closestLi.classList.contains('nav-item')){return closestLi.oToggleList(0,mode);}
const restoreCursor=preserveCursor(this.ownerDocument);if(this.oid==='root'){const callingNode=this.childNodes[offset];const group=getAdjacents(callingNode,n=>!isBlock(n));insertListAfter(callingNode,mode,[group]);restoreCursor();}else{const list=insertListAfter(this,mode,[this]);if(this.hasAttribute('dir')){list.setAttribute('dir',this.getAttribute('dir'));}
restoreCursor(new Map([[this,list.firstElementChild]]));}};HTMLParagraphElement.prototype.oToggleList=function(offset,mode='UL'){const restoreCursor=preserveCursor(this.ownerDocument);const list=insertListAfter(this,mode,[[...this.childNodes]]);const classList=[...list.classList];for(const attribute of this.attributes){if(attribute.name==='class'&&attribute.value&&list.className){list.className=`${list.className} ${attribute.value}`;}else{list.setAttribute(attribute.name,attribute.value);}}
for(const className of classList){list.classList.toggle(className,true);}
this.remove();restoreCursor(new Map([[this,list.firstChild]]));return true;};HTMLLIElement.prototype.oToggleList=function(offset,mode){const restoreCursor=preserveCursor(this.ownerDocument);toggleList(this,mode,offset);restoreCursor();return false;};HTMLTableCellElement.prototype.oToggleList=function(offset,mode){const restoreCursor=preserveCursor(this.ownerDocument);const callingNode=this.childNodes[offset];const group=getAdjacents(callingNode,n=>!isBlock(n));insertListAfter(callingNode,mode,[group]);restoreCursor();};return __exports;});;

/* /web_editor/static/src/js/editor/drag_and_drop.js */
odoo.define('@web_editor/js/editor/drag_and_drop',['@web/core/utils/draggable_hook_builder','@web/core/utils/objects','@odoo/owl','@web/core/utils/timing','@web/core/utils/ui'],function(require){'use strict';let __exports={};const{makeDraggableHook}=require("@web/core/utils/draggable_hook_builder");const{pick}=require("@web/core/utils/objects");const{reactive}=require("@odoo/owl");const{throttleForAnimation}=require("@web/core/utils/timing");const{closest,touching}=require("@web/core/utils/ui");__exports.useNativeDraggable=useNativeDraggable;function useNativeDraggable(hookParams,initialParams){const setupFunctions=new Map();const cleanupFunctions=[];const currentParams={...initialParams};const setupHooks={wrapState:reactive,throttle:throttleForAnimation,addListener:(el,type,callback,options)=>{el.addEventListener(type,callback,options);cleanupFunctions.push(()=>el.removeEventListener(type,callback));},setup:(setupFn,depsFn)=>setupFunctions.set(setupFn,depsFn),teardown:(cleanupFn)=>{cleanupFunctions.push(cleanupFn);}};const el=initialParams.ref.el;el.classList.add("o_draggable");cleanupFunctions.push(()=>el.classList.remove("o_draggable"));const draggableState=makeDraggableHook({setupHooks,...hookParams})(currentParams);draggableState.enable=true;const draggableComponent={state:draggableState,update:(newParams)=>{Object.assign(currentParams,newParams);setupFunctions.forEach((depsFn,setupFn)=>setupFn(...depsFn()));},destroy:()=>{cleanupFunctions.forEach((cleanupFn)=>cleanupFn());}};draggableComponent.update({});return draggableComponent;}
function updateElementPosition(el,{x,y},styleFn,offset={x:0,y:0}){return styleFn(el,{top:`${y - offset.y}px`,left:`${x - offset.x}px`});}
const dragAndDropHookParams={name:"useDragAndDrop",acceptedParams:{dropzones:[Function],scrollingElement:[Object,Function],helper:[Function],extraWindow:[Object,Function],},edgeScrolling:{enabled:true,speed:20},onComputeParams({ctx,params}){ctx.followCursor=false;ctx.scrollingElement=params.scrollingElement;ctx.getHelper=params.helper;ctx.getDropZones=params.dropzones;},onWillStartDrag:({ctx})=>{ctx.current.container=ctx.scrollingElement;ctx.current.helperOffset={x:0,y:0};},onDragStart:({ctx,addStyle,addCleanup,addClass})=>{ctx.current.element=ctx.getHelper({...ctx.current,...ctx.pointer});ctx.current.helper=ctx.current.element;ctx.current.helper.style.position="fixed";ctx.current.helper.classList.remove("o_dragged");ctx.current.helper.style.cursor=ctx.cursor;ctx.current.helper.style.pointerEvents="auto";const frameElement=ctx.current.helper.ownerDocument.defaultView.frameElement;if(frameElement){addClass(frameElement,"pe-auto");}
addCleanup(()=>ctx.current.helper.remove());updateElementPosition(ctx.current.helper,ctx.pointer,addStyle,ctx.current.helperOffset);return pick(ctx.current,"element","helper");},onDrag:({ctx,addStyle,callHandler})=>{ctx.current.helper.classList.add("o_draggable_dragging");updateElementPosition(ctx.current.helper,ctx.pointer,addStyle,ctx.current.helperOffset);let helperRect=ctx.current.helper.getBoundingClientRect();helperRect={x:helperRect.x,y:helperRect.y,width:helperRect.width,height:helperRect.height,};const dropzoneEl=closest(touching(ctx.getDropZones(),helperRect),helperRect);if(ctx.current.dropzone?.el&&ctx.current.dropzone.el.classList.contains("oe_grid_zone")){ctx.current.dropzone.rect=ctx.current.dropzone.el.getBoundingClientRect();}
if(ctx.current.dropzone&&(ctx.current.dropzone.el===dropzoneEl||(!dropzoneEl&&touching([ctx.current.helper],ctx.current.dropzone.rect).length>0))){return pick(ctx.current,"element","dropzone","helper");}
if(ctx.current.dropzone&&dropzoneEl!==ctx.current.dropzone.el){callHandler("dropzoneOut",{dropzone:ctx.current.dropzone});delete ctx.current.dropzone;}
if(dropzoneEl){const rect=DOMRect.fromRect(dropzoneEl.getBoundingClientRect());ctx.current.dropzone={el:dropzoneEl,rect:{x:rect.x,y:rect.y,width:rect.width,height:rect.height}};callHandler("dropzoneOver",{dropzone:ctx.current.dropzone});}
return pick(ctx.current,"element","dropzone","helper");},onDragEnd({ctx}){return pick(ctx.current,"element","dropzone","helper");}};__exports.useDragAndDrop=useDragAndDrop;function useDragAndDrop(initialParams){return useNativeDraggable(dragAndDropHookParams,initialParams);}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/linkDialogCommand.js */
odoo.define('@web_editor/js/wysiwyg/linkDialogCommand',['@web/core/registry','@web/core/commands/default_providers','@web_editor/js/wysiwyg/wysiwyg'],function(require){'use strict';let __exports={};const{registry}=require('@web/core/registry')
const{HotkeyCommandItem}=require('@web/core/commands/default_providers')
const{Wysiwyg}=require('@web_editor/js/wysiwyg/wysiwyg');let sessionActionLabel=[];const commandProviderRegistry=registry.category("command_provider");commandProviderRegistry.add("link dialog",{async provide(env,{sessionId}){let[lastSessionId,action,label]=sessionActionLabel;if(lastSessionId!==sessionId){const wysiwyg=[...Wysiwyg.activeWysiwygs].find((wysiwyg)=>{return wysiwyg.isSelectionInEditable();});const selection=wysiwyg&&wysiwyg.odooEditor&&wysiwyg.odooEditor.document.getSelection();const range=selection&&selection.rangeCount&&selection.getRangeAt(0);if(range){label=!wysiwyg.getInSelection('a')?'Create link':'Edit link';action=()=>{const selection=wysiwyg.odooEditor.document.getSelection();selection.removeAllRanges();selection.addRange(range);wysiwyg.openLinkToolsFromSelection();}
sessionActionLabel=[sessionId,action,label]}else{sessionActionLabel=[sessionId];}}
[lastSessionId,action,label]=sessionActionLabel;if(action){return[{Component:HotkeyCommandItem,action:action,category:'shortcut_conflict',name:label,props:{hotkey:'control+k'},}]}else{return[];}},});return __exports;});;

/* /web_editor/static/src/js/wysiwyg/MoveNodePlugin.js */
odoo.define('@web_editor/js/wysiwyg/MoveNodePlugin',['@web_editor/js/editor/odoo-editor/src/OdooEditor','@web_editor/js/editor/drag_and_drop'],function(require){'use strict';let __exports={};const{ancestors,closestElement,resetOuids,setSelection,}=require('@web_editor/js/editor/odoo-editor/src/OdooEditor');const{useNativeDraggable}=require("@web_editor/js/editor/drag_and_drop");const simpleDraggableHook={acceptedParams:{helper:[Function],},edgeScrolling:{enable:true},onComputeParams({ctx,params}){ctx.helper=params.helper;ctx.followCursor=false;ctx.tolerance=0;},onDragStart({ctx}){ctx.current.element=ctx.helper();ctx.current.element.style.left=`${ctx.pointer.x + 10}px`;ctx.current.element.style.top=`${ctx.pointer.y + 10}px`;ctx.current.element.style.position="fixed";document.body.classList.remove("pe-none");return ctx.current;},onDrag({ctx}){ctx.current.element.style.left=`${ctx.pointer.x}px`;ctx.current.element.style.top=`${ctx.pointer.y}px`;},onDragEnd({ctx}){ctx.current.element.remove();return ctx.current;},};const WIDGET_CONTAINER_WIDTH=25;const WIDGET_MOVE_SIZE=20;const ALLOWED_ELEMENTS='h1, h2, h3, p, hr, pre, blockquote, ul, ol, table, .o_knowledge_behavior_anchor, .o_text_columns, .o_editor_banner, .oe_movable';const MoveNodePlugin=__exports.MoveNodePlugin=class MoveNodePlugin{constructor(options={}){this._options=options;this._intersectionObserver=new IntersectionObserver(this._intersectionObserverCallback.bind(this),{root:document,});this._visibleMovableElements=new Set();}
start(){this._editor=this._options.editor;this._editable=this._options.editor.editable;this._document=this._options.editor.document;this._elementHookMap=new Map();this._editor.addDomListener(this._editable,'mousemove',this._onMousemove.bind(this),true);this._editor.addDomListener(this._editor.document,'keydown',this._onDocumentKeydown.bind(this),true);this._editor.addDomListener(this._editor.document,'mousemove',this._onDocumentMousemove.bind(this),true);const avatarContainer=this._editor.mainAbsoluteContainer.querySelector('[data-oe-absolute-container-id="oe-avatars-counters-container"]');this._widgetHookContainer=this._editor.makeAbsoluteContainer('oe-widget-hooks-container');avatarContainer.before(this._widgetHookContainer);this._widgetContainer=this._editor.makeAbsoluteContainer('oe-widgets-container');avatarContainer.before(this._widgetContainer);this._dragHelperContainer=this._editor.makeAbsoluteContainer('oe-movenode-helper-container');avatarContainer.before(this._dragHelperContainer);this._dropzonesContainer=this._editor.makeAbsoluteContainer('oe-dropzones-container');avatarContainer.before(this._dropzonesContainer);this._dropzoneHintContainer=this._editor.makeAbsoluteContainer('oe-dropzone-hint-container');avatarContainer.before(this._dropzoneHintContainer);this._scrollableElement=closestElement(this._editable.parentElement);while(this._scrollableElement&&getComputedStyle(this._scrollableElement).overflowY!=='auto'){this._scrollableElement=this._scrollableElement.parentElement;}
this._scrollableElement=this._scrollableElement||this._editable;this._resetHooksNextMousemove=true;this.mutationObserver=new MutationObserver(()=>{this._resetHooksNextMousemove=true;this._removeMoveWidget();});this.mutationObserver.observe(this._editable,{childList:true,subtree:true,characterData:true,characterDataOldValue:true,});this._editor.addDomListener(window,'resize',this._updateHooks.bind(this));if(this._editor.document.defaultView!==window){this._editor.addDomListener(this._editor.document.defaultView,'resize',this._updateHooks.bind(this));}}
destroy(){this._intersectionObserver.disconnect();this.mutationObserver.disconnect();this.smoothScrollOnDrag&&this.smoothScrollOnDrag.destroy();}
_intersectionObserverCallback(entries){for(const entry of entries){const element=entry.target;if(entry.isIntersecting){this._visibleMovableElements.add(element);this._resetHooksNextMousemove=true;}else{this._visibleMovableElements.delete(element);const hookElement=this._elementHookMap.get(element);if(hookElement){hookElement.style.display=`none`;}}}}
_updateHooks(){const editableStyles=getComputedStyle(this._editable);this._editableRect=this._editable.getBoundingClientRect();const paddingLeft=parseInt(editableStyles.paddingLeft,10)||0;this._editableRect.x=this._editableRect.x+paddingLeft-(WIDGET_CONTAINER_WIDTH+5);this._editableRect.width=this._editableRect.width-paddingLeft+(WIDGET_CONTAINER_WIDTH+5);const containerRect=this._widgetHookContainer.getBoundingClientRect();const elements=this._getMovableElements();const elementsToGarbageCollect=new Set(this._elementHookMap.keys());for(const index in elements){const element=elements[index];elementsToGarbageCollect.delete(element);let hookElement=this._elementHookMap.get(element);if(!hookElement){hookElement=document.createElement('div');this._elementHookMap.set(element,hookElement);hookElement.classList.add('oe-dropzone-hook');hookElement.addEventListener('mouseenter',()=>{if(element!==this._currentMovableElement){this._setMovableElement(element);}});this._widgetHookContainer.append(hookElement);hookElement.style.display=`none`;this._intersectionObserver.observe(element);}
hookElement.style.zIndex=index;}
for(const element of elementsToGarbageCollect){this._visibleMovableElements.delete(element);this._elementHookMap.get(element).remove();this._intersectionObserver.unobserve(element);this._elementHookMap.delete(element);}
const visibleElements=[...this._visibleMovableElements];const elementRects=visibleElements.map((element)=>element.getBoundingClientRect());for(const index in visibleElements){const element=visibleElements[index];const elementRect=elementRects[index];const hookElement=this._elementHookMap.get(element);const style=getComputedStyle(element);const marginTop=parseInt(style.marginTop,10)||0;const marginBottom=parseInt(style.marginBottom,10)||0;let hookBox;if(element.tagName==='HR'){hookBox=new DOMRect(elementRect.x-containerRect.left-WIDGET_CONTAINER_WIDTH,elementRect.y-containerRect.top-marginTop,elementRect.width+WIDGET_CONTAINER_WIDTH,elementRect.height+marginTop+marginBottom,);}else{hookBox=new DOMRect(elementRect.x-containerRect.left-WIDGET_CONTAINER_WIDTH,elementRect.y-containerRect.top-marginTop,WIDGET_CONTAINER_WIDTH,elementRect.height+marginTop+marginBottom,);}
hookElement.style.left=`${hookBox.x}px`;hookElement.style.top=`${hookBox.y}px`;hookElement.style.width=`${hookBox.width}px`;hookElement.style.height=`${hookBox.height}px`;hookElement.style.display=`block`;}}
_updateAnchorWidgets(newAnchorWidget){let movableElement=newAnchorWidget&&closestElement(newAnchorWidget,(node)=>{return isNodeMovable(node)&&node.matches(ALLOWED_ELEMENTS);});const listContainer=movableElement&&ancestors(movableElement,this._editable).reverse().find(n=>['UL','OL'].includes(n.tagName));movableElement=listContainer||movableElement;if(movableElement&&(movableElement!==this._currentMovableElement)){this._setMovableElement(movableElement);}}
_getMovableElements(){return[...new Set([...this._editable.querySelectorAll(ALLOWED_ELEMENTS)])].filter((node)=>isNodeMovable(node));}
_getDroppableElements(draggableNode){return this._getMovableElements().filter((node)=>!closestElement(node.parentElement,(n)=>n===draggableNode));}
_setMovableElement(movableElement){this._removeMoveWidget();this._currentMovableElement=movableElement;this._editor.disableAvatarForElement(movableElement);const containerRect=this._widgetContainer.getBoundingClientRect();const anchorBlockRect=this._currentMovableElement.getBoundingClientRect();const closestList=closestElement(this._currentMovableElement,'ul, ol');const anchorX=closestList?closestList.getBoundingClientRect().x:anchorBlockRect.x;let anchorY=anchorBlockRect.y;if(this._currentMovableElement.tagName.match(/H[1-6]/)){anchorY+=(anchorBlockRect.height-WIDGET_MOVE_SIZE)/2;}
this._moveWidget=this._document.createElement('div');this._moveWidget.className='oe-sidewidget-move fa fa-sort';this._widgetContainer.append(this._moveWidget);let moveWidgetOffsetTop=0;if(movableElement.tagName==='HR'){const style=getComputedStyle(movableElement);moveWidgetOffsetTop=parseInt(style.marginTop,10)||0;}
this._moveWidget.style.width=`${WIDGET_MOVE_SIZE}px`;this._moveWidget.style.height=`${WIDGET_MOVE_SIZE}px`;this._moveWidget.style.top=`${anchorY - containerRect.y - moveWidgetOffsetTop}px`;this._moveWidget.style.left=`${anchorX - containerRect.x - WIDGET_CONTAINER_WIDTH}px`;if(this._scrollableElement){this.smoothScrollOnDrag&&this.smoothScrollOnDrag.destroy();this.smoothScrollOnDrag=useNativeDraggable(simpleDraggableHook,{ref:{el:this._widgetContainer},elements:".oe-sidewidget-move",onDragStart:()=>this._startDropzones(movableElement,containerRect),onDragEnd:()=>this._stopDropzones(movableElement),helper:()=>{const container=document.createElement('div');container.append(movableElement.cloneNode(true));const style=getComputedStyle(movableElement);container.style.height=style.height;container.style.width=style.width;container.style.paddingLeft='25px';container.style.opacity='0.4';this._dragHelperContainer.append(container);return container;}});}}
_removeMoveWidget(){this._editor.enableAvatars();this._moveWidget?.remove();this._moveWidget=undefined;this._currentMovableElement=undefined;}
_startDropzones(movableElement,containerRect,directions=['north','south']){this._removeMoveWidget();const elements=this._getDroppableElements(movableElement);this._dropzonesContainer.replaceChildren();this._editable.classList.add('oe-editor-dragging');for(const element of elements){const originalRect=element.getBoundingClientRect();const style=getComputedStyle(element);const marginTop=parseInt(style.marginTop,10);const marginBottom=parseInt(style.marginBottom,10);const marginLeft=parseInt(style.marginLeft,10);const marginRight=parseInt(style.marginRight,10);const dropzoneRect=new DOMRect(originalRect.left-marginLeft-WIDGET_CONTAINER_WIDTH,originalRect.top-marginTop,originalRect.width+marginLeft+marginRight+WIDGET_CONTAINER_WIDTH,originalRect.height+marginTop+marginBottom,);const dropzoneHintRect=new DOMRect(originalRect.left-marginLeft,originalRect.top-marginTop,originalRect.width+marginLeft+marginRight,originalRect.height+marginTop+marginBottom,);const dropzoneBox=document.createElement('div');dropzoneBox.className=`oe-dropzone-box`;dropzoneBox.style.top=`${dropzoneRect.top - containerRect.top}px`;dropzoneBox.style.left=`${dropzoneRect.left - containerRect.left}px`;dropzoneBox.style.width=`${dropzoneRect.width}px`;dropzoneBox.style.height=`${dropzoneRect.height}px`;const dropzoneHintBox=document.createElement('div');dropzoneHintBox.className=`oe-dropzone-box`;dropzoneHintBox.style.top=`${dropzoneHintRect.top - containerRect.top}px`;dropzoneHintBox.style.left=`${dropzoneHintRect.left - containerRect.left}px`;dropzoneHintBox.style.width=`${dropzoneHintRect.width}px`;dropzoneHintBox.style.height=`${dropzoneHintRect.height}px`;const sideElements={};for(const direction of directions){const sideElement=document.createElement('div');sideElement.className=`oe-dropzone-box-side oe-dropzone-box-side-${direction}`;sideElements[direction]=sideElement;dropzoneBox.append(sideElement);sideElement.addEventListener('mouseenter',()=>{this._currentZone=[direction];removeDropHint();this._currentDropHint=document.createElement('div');this._currentDropHint.className=`oe-current-drop-hint`;const currentDropHintSize=4;const currentDropHintSizeHalf=currentDropHintSize/2;if(direction==='north'){this._currentDropHint.style['top']=`-${currentDropHintSizeHalf}px`;this._currentDropHint.style['width']=`100%`;this._currentDropHint.style['height']=`${currentDropHintSize}px`;dropzoneHintBox.append(this._currentDropHint);this._currentDropHintElementPosition=['top',element];}else if(direction==='south'){this._currentDropHint.style['bottom']=`-${currentDropHintSizeHalf}px`;this._currentDropHint.style['width']=`100%`;this._currentDropHint.style['height']=`${currentDropHintSize}px`;dropzoneHintBox.append(this._currentDropHint);this._currentDropHintElementPosition=['bottom',element];}else if(direction==='west'){this._currentDropHint.style['left']=`-${currentDropHintSizeHalf}px`;this._currentDropHint.style['height']=`100%`;this._currentDropHint.style['width']=`${currentDropHintSize}px`;dropzoneHintBox.append(this._currentDropHint);this._currentDropHintElementPosition=['left',element];}else if(direction==='east'){this._currentDropHint.style['right']=`-${currentDropHintSizeHalf}px`;this._currentDropHint.style['height']=`100%`;this._currentDropHint.style['width']=`${currentDropHintSize}px`;dropzoneHintBox.append(this._currentDropHint);this._currentDropHintElementPosition=['right',element];}});const removeDropHint=()=>{if(this._currentDropHint){this._currentDropHint.remove();this._currentDropHint=null;}
this._currentDropHintCommand=null;}
dropzoneBox.addEventListener('mouseleave',removeDropHint);}
this._dropzonesContainer.append(dropzoneBox);this._dropzoneHintContainer.append(dropzoneHintBox);}}
_stopDropzones(movableElement){this._editable.classList.remove('oe-editor-dragging');this._dropzonesContainer.replaceChildren();this._dropzoneHintContainer.replaceChildren();if(this._currentDropHintElementPosition){const[position,focusElelement]=this._currentDropHintElementPosition;this._currentDropHintElementPosition=undefined;const previousParent=movableElement.parentElement;if(position==='top'){focusElelement.before(movableElement);}else if(position==='bottom'){focusElelement.after(movableElement);}
if(previousParent.innerHTML.trim()===''){const p=document.createElement('p');const br=document.createElement('br');p.append(br);previousParent.append(p);}
setSelection(movableElement,movableElement.childNodes.length);resetOuids(movableElement);this._editor.historyStep();}}
_onMousemove(e){this._updateAnchorWidgets(e.target);}
_onDocumentKeydown(){this._removeMoveWidget();}
_onDocumentMousemove(e){if(this._resetHooksNextMousemove){this._resetHooksNextMousemove=false;this._removeMoveWidget();this._updateHooks();}
if(this._editableRect&&!isPointInside(this._editableRect,e.clientX,e.clientY)){this._removeMoveWidget();}}}
function isNodeMovable(node){return node.parentElement?.getAttribute('contentEditable')==='true'&&!node.parentElement.closest('.o_editor_banner');}
function isPointInside(rect,x,y){return rect.left<=x&&rect.right>=x&&rect.top<=y&&rect.bottom>=y;};return __exports;});;

/* /web_editor/static/src/js/wysiwyg/PeerToPeer.js */
odoo.define('@web_editor/js/wysiwyg/PeerToPeer',['@web/core/browser/browser'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const localStorage=browser.localStorage;const urlParams=new URLSearchParams(window.location.search);const collaborationDebug=urlParams.get('collaborationDebug');const COLLABORATION_LOCALSTORAGE_KEY='odoo_editor_collaboration_debug';if(typeof collaborationDebug==='string'){if(collaborationDebug==='false'){localStorage.removeItem(COLLABORATION_LOCALSTORAGE_KEY,urlParams.get('collaborationDebug'),);}else{localStorage.setItem(COLLABORATION_LOCALSTORAGE_KEY,urlParams.get('collaborationDebug'));}}
const debugValue=localStorage.getItem(COLLABORATION_LOCALSTORAGE_KEY);const debugShowLog=['','true','all'].includes(debugValue);const debugShowNotifications=debugValue==='all';const baseNotificationMethods={ptp_request:async function(notification){const{requestId,requestName,requestPayload,requestTransport}=notification.notificationPayload;this._onRequest(notification.fromClientId,requestId,requestName,requestPayload,requestTransport,);},ptp_request_result:function(notification){const{requestId,result}=notification.notificationPayload;if(this._pendingRequestResolver[requestId]){clearTimeout(this._pendingRequestResolver[requestId].rejectTimeout);this._pendingRequestResolver[requestId].resolve(result);delete this._pendingRequestResolver[requestId];}},ptp_join:async function(notification){const clientId=notification.fromClientId;if(this.clientsInfos[clientId]&&this.clientsInfos[clientId].peerConnection){return this.clientsInfos[clientId];}
this._createClient(clientId);},rtc_signal_icecandidate:async function(notification){if(debugShowLog)console.log(`%creceive candidate`,'background: darkgreen; color: white;');const clientInfos=this.clientsInfos[notification.fromClientId];if(!clientInfos||!clientInfos.peerConnection||clientInfos.peerConnection.connectionState==='closed'){console.groupCollapsed('=== ERROR: Handle Ice Candidate from undefined|closed ===');console.trace(clientInfos);console.groupEnd();return;}
if(!clientInfos.peerConnection.remoteDescription){clientInfos.iceCandidateBuffer.push(notification.notificationPayload);}else{this._addIceCandidate(clientInfos,notification.notificationPayload);}},rtc_signal_description:async function(notification){const description=notification.notificationPayload;if(debugShowLog)
console.log(`%cdescription received:`,'background: blueviolet; color: white;',description,);const clientInfos=this.clientsInfos[notification.fromClientId]||this._createClient(notification.fromClientId);const pc=clientInfos.peerConnection;if(!pc||pc.connectionState==='closed'){if(debugShowLog){console.groupCollapsed('=== ERROR: handle offer ===');console.log('An offer has been received for a non-existent peer connection - client: '+
notification.fromClientId,);console.trace(pc&&pc.connectionState);console.groupEnd();}
return;}
if(pc.signalingState==='have-remote-offer'){return;}
const isPolite=(''+notification.fromClientId).localeCompare(''+this._currentClientId)===1;if(debugShowLog)
console.log(`%cisPolite: %c${isPolite}`,'background: deepskyblue;',`background:${isPolite ? 'green' : 'red'}`,);const isOfferRacing=description.type==='offer'&&(clientInfos.makingOffer||pc.signalingState!=='stable');if(isOfferRacing&&!isPolite){if(debugShowLog)
console.log(`%creturn because isOfferRacing && !isPolite. pc.signalingState: ${pc.signalingState}`,'background: red;',);return;}
if(debugShowLog){console.log(`%cisOfferRacing: ${isOfferRacing}`,'background: red;');console.log(`%c SETREMOTEDESCRIPTION`,'background: navy; color:white;');}
try{await pc.setRemoteDescription(description);}catch(e){if(e instanceof DOMException&&e.name==='InvalidStateError'){console.error(e);return;}else{throw e;}}
if(clientInfos.iceCandidateBuffer.length){for(const candidate of clientInfos.iceCandidateBuffer){await this._addIceCandidate(clientInfos,candidate);}
clientInfos.iceCandidateBuffer.splice(0);}
if(description.type==='offer'){const answerDescription=await pc.createAnswer();try{await pc.setLocalDescription(answerDescription);}catch(e){if(e instanceof DOMException&&e.name==='InvalidStateError'){console.error(e);return;}else{throw e;}}
this.notifyClient(notification.fromClientId,'rtc_signal_description',pc.localDescription,);}},};const PeerToPeer=__exports.PeerToPeer=class PeerToPeer{constructor(options){this.options=options;this._currentClientId=this.options.currentClientId;if(debugShowLog)
console.log(`%c currentClientId:${this._currentClientId}`,'background: blue; color: white;',);this.clientsInfos={};this._lastRequestId=-1;this._pendingRequestResolver={};this._stopped=false;}
stop(){this.closeAllConnections();this._stopped=true;}
getConnectedClientIds(){return Object.entries(this.clientsInfos).filter(([id,infos])=>infos.peerConnection&&infos.peerConnection.iceConnectionState==='connected'&&infos.dataChannel&&infos.dataChannel.readyState==='open',).map(([id])=>id);}
removeClient(clientId){if(debugShowLog)console.log(`%c REMOVE CLIENT ${clientId}`,'background: chocolate;');this.notifySelf('ptp_remove',clientId);const clientInfos=this.clientsInfos[clientId];if(!clientInfos)return;clearTimeout(clientInfos.fallbackTimeout);clearTimeout(clientInfos.zombieTimeout);clientInfos.dataChannel&&clientInfos.dataChannel.close();clientInfos.peerConnection&&clientInfos.peerConnection.close();delete this.clientsInfos[clientId];}
closeAllConnections(){for(const clientId of Object.keys(this.clientsInfos)){this.notifyAllClients('ptp_disconnect');this.removeClient(clientId);}}
async notifyAllClients(notificationName,notificationPayload,{transport='server'}={}){if(this._stopped){return;}
const transportPayload={fromClientId:this._currentClientId,notificationName,notificationPayload,};if(transport==='server'){await this.options.broadcastAll(transportPayload);}else if(transport==='rtc'){for(const cliendId of Object.keys(this.clientsInfos)){this._channelNotify(cliendId,transportPayload);}}else{throw new Error(`Transport "${transport}" is not supported. Use "server" or "rtc" transport.`,);}}
notifyClient(clientId,notificationName,notificationPayload,{transport='server'}={}){if(this._stopped){return;}
if(debugShowNotifications){if(notificationName==='ptp_request_result'){console.log(`%c${Date.now()} - REQUEST RESULT SEND: %c${transport}:${
                        notificationPayload.requestId
                    }:${this._currentClientId.slice('-5')}:${clientId.slice('-5')}`,'color: #aaa;font-weight:bold;','color: #aaa;font-weight:normal',);}else if(notificationName==='ptp_request'){console.log(`%c${Date.now()} - REQUEST SEND: %c${transport}:${
                        notificationPayload.requestName
                    }|${notificationPayload.requestId}:${this._currentClientId.slice(
                        '-5',
                    )}:${clientId.slice('-5')}`,'color: #aaa;font-weight:bold;','color: #aaa;font-weight:normal',);}else{console.log(`%c${Date.now()} - NOTIFICATION SEND: %c${transport}:${notificationName}:${this._currentClientId.slice(
                        '-5',
                    )}:${clientId.slice('-5')}`,'color: #aaa;font-weight:bold;','color: #aaa;font-weight:normal',);}}
const transportPayload={fromClientId:this._currentClientId,toClientId:clientId,notificationName,notificationPayload,};if(transport==='server'){this.options.broadcastAll(transportPayload);}else if(transport==='rtc'){this._channelNotify(clientId,transportPayload);}else{throw new Error(`Transport "${transport}" is not supported. Use "server" or "rtc" transport.`,);}}
notifySelf(notificationName,notificationPayload){if(this._stopped){return;}
return this.handleNotification({notificationName,notificationPayload});}
handleNotification(notification){if(this._stopped){return;}
const isInternalNotification=typeof notification.fromClientId==='undefined'&&typeof notification.toClientId==='undefined';if(isInternalNotification||(notification.fromClientId!==this._currentClientId&&!notification.toClientId)||notification.toClientId===this._currentClientId){if(debugShowNotifications){if(notification.notificationName==='ptp_request_result'){console.log(`%c${Date.now()} - REQUEST RESULT RECEIVE: %c${
                            notification.notificationPayload.requestId
                        }:${notification.fromClientId.slice('-5')}:${notification.toClientId.slice(
                            '-5',
                        )}`,'color: #aaa;font-weight:bold;','color: #aaa;font-weight:normal',);}else if(notification.notificationName==='ptp_request'){console.log(`%c${Date.now()} - REQUEST RECEIVE: %c${
                            notification.notificationPayload.requestName
                        }|${
                            notification.notificationPayload.requestId
                        }:${notification.fromClientId.slice('-5')}:${notification.toClientId.slice(
                            '-5',
                        )}`,'color: #aaa;font-weight:bold;','color: #aaa;font-weight:normal',);}else{console.log(`%c${Date.now()} - NOTIFICATION RECEIVE: %c${
                            notification.notificationName
                        }:${notification.fromClientId}:${notification.toClientId}`,'color: #aaa;font-weight:bold;','color: #aaa;font-weight:normal',);}}
try{const baseMethod=baseNotificationMethods[notification.notificationName];if(baseMethod){return baseMethod.call(this,notification);}
if(this.options.onNotification){return this.options.onNotification(notification);}}catch(error){console.groupCollapsed('=== ERROR: On notification in collaboration ===');console.error(error);console.groupEnd();}}}
requestClient(clientId,requestName,requestPayload,{transport='server'}={}){if(this._stopped){return;}
return new Promise((resolve,reject)=>{const requestId=this._getRequestId();const abort=(reason)=>{clearTimeout(rejectTimeout);delete this._pendingRequestResolver[requestId];reject(new RequestError(reason||'Request was aborted.'));};const rejectTimeout=setTimeout(()=>abort('Request took too long (more than 10 seconds).'),10000);this._pendingRequestResolver[requestId]={resolve,rejectTimeout,abort,};this.notifyClient(clientId,'ptp_request',{requestId,requestName,requestPayload,requestTransport:transport,},{transport},);});}
abortCurrentRequests(){for(const{abort}of Object.values(this._pendingRequestResolver)){abort();}}
_createClient(clientId,{makeOffer=true}={}){if(this._stopped){return;}
if(debugShowLog)console.log('CREATE CONNECTION with client id:',clientId);this.clientsInfos[clientId]={makingOffer:false,iceCandidateBuffer:[],backoffFactor:0,};if(!navigator.onLine){return this.clientsInfos[clientId];}
const pc=new RTCPeerConnection(this.options.peerConnectionConfig);if(makeOffer){pc.onnegotiationneeded=async()=>{if(debugShowLog)
console.log(`%c NEGONATION NEEDED: ${pc.connectionState}`,'background: deeppink;',);try{this.clientsInfos[clientId].makingOffer=true;if(debugShowLog)
console.log(`%ccreating and sending an offer`,'background: darkmagenta; color: white;',);const offer=await pc.createOffer();if(pc.signalingState!=='stable'){return;}
await pc.setLocalDescription(offer);this.notifyClient(clientId,'rtc_signal_description',pc.localDescription);}catch(err){console.error(err);}finally{this.clientsInfos[clientId].makingOffer=false;}};}
pc.onicecandidate=async event=>{if(event.candidate){this.notifyClient(clientId,'rtc_signal_icecandidate',event.candidate);}};pc.oniceconnectionstatechange=async()=>{if(debugShowLog)console.log('ICE STATE UPDATE: '+pc.iceConnectionState);switch(pc.iceConnectionState){case'failed':case'closed':this.removeClient(clientId);break;case'disconnected':if(navigator.onLine){await this._recoverConnection(clientId,{delay:3000,reason:'ice connection disconnected',});}
break;case'connected':this.clientsInfos[clientId].backoffFactor=0;break;}};pc.onconnectionstatechange=async()=>{if(debugShowLog)console.log('CONNECTION STATE UPDATE:'+pc.connectionState);switch(pc.connectionState){case'failed':case'closed':this.removeClient(clientId);break;case'disconnected':if(navigator.onLine){await this._recoverConnection(clientId,{delay:3000,reason:'connection disconnected',});}
break;case'connected':case'completed':this.clientsInfos[clientId].backoffFactor=0;break;}};pc.onicecandidateerror=async error=>{if(debugShowLog){console.groupCollapsed('=== ERROR: onIceCandidate ===');console.log('connectionState: '+
pc.connectionState+' - iceState: '+
pc.iceConnectionState,);console.trace(error);console.groupEnd();}
this._recoverConnection(clientId,{delay:3000,reason:'ice candidate error'});};const dataChannel=pc.createDataChannel('notifications',{negotiated:true,id:1});let message=[];dataChannel.onmessage=event=>{if(event.data!=='-'){message.push(event.data);}else{this.handleNotification(JSON.parse(message.join('')));message=[];}};dataChannel.onopen=event=>{this.notifySelf('rtc_data_channel_open',{connectionClientId:clientId,});};this.clientsInfos[clientId].peerConnection=pc;this.clientsInfos[clientId].dataChannel=dataChannel;return this.clientsInfos[clientId];}
async _addIceCandidate(clientInfos,candidate){const rtcIceCandidate=new RTCIceCandidate(candidate);try{await clientInfos.peerConnection.addIceCandidate(rtcIceCandidate);}catch(error){console.groupCollapsed('=== ERROR: ADD ICE CANDIDATE ===');console.trace(error);console.groupEnd();}}
_channelNotify(clientId,transportPayload){if(this._stopped){return;}
const clientInfo=this.clientsInfos[clientId];const dataChannel=clientInfo&&clientInfo.dataChannel;if(!dataChannel||dataChannel.readyState!=='open'){if(clientInfo&&!clientInfo.zombieTimeout){if(debugShowLog)console.warn(`Impossible to communicate with client ${clientId}. The connection will be killed in 10 seconds if the datachannel state has not changed.`,);this._killPotentialZombie(clientId);}}else{const str=JSON.stringify(transportPayload);const size=str.length;const maxStringLength=5000;let from=0;let to=maxStringLength;while(from<size){dataChannel.send(str.slice(from,to));from=to;to=to+=maxStringLength;}
dataChannel.send('-');}}
_getRequestId(){this._lastRequestId++;return this._lastRequestId;}
async _onRequest(fromClientId,requestId,requestName,requestPayload,requestTransport){if(this._stopped){return;}
const requestFunction=this.options.onRequest&&this.options.onRequest[requestName];const result=await requestFunction({fromClientId,requestId,requestName,requestPayload,});this.notifyClient(fromClientId,'ptp_request_result',{requestId,result},{transport:requestTransport},);}
_recoverConnection(clientId,{delay=0,reason=''}={}){if(this._stopped){this.removeClient(clientId);return;}
const clientInfos=this.clientsInfos[clientId];if(!clientInfos||clientInfos.fallbackTimeout)return;const backoffFactor=this.clientsInfos[clientId].backoffFactor;const backoffDelay=delay*Math.pow(2,backoffFactor);if(backoffFactor>10){if(debugShowLog){console.log(`%c STOP RTC RECOVERY: impossible to connect to client ${clientId}: ${reason}`,'background: darkred; color: white;',);}
return;}
clientInfos.fallbackTimeout=setTimeout(async()=>{clientInfos.fallbackTimeout=undefined;const pc=clientInfos.peerConnection;if(!pc||pc.iceConnectionState==='connected'){return;}
if(['connected','closed'].includes(pc.connectionState)){return;}
if(debugShowLog)
console.log(`%c RTC RECOVERY: calling back client ${clientId} to salvage the connection ${pc.iceConnectionState} after ${backoffDelay}ms, reason: ${reason}`,'background: darkorange; color: white;',);this.removeClient(clientId);const newClientInfos=this._createClient(clientId);newClientInfos.backoffFactor=backoffFactor+1;},backoffDelay);}
_killPotentialZombie(clientId){if(this._stopped){this.removeClient(clientId);return;}
const clientInfos=this.clientsInfos[clientId];if(!clientInfos||clientInfos.zombieTimeout){return;}
clientInfos.zombieTimeout=setTimeout(()=>{if(clientInfos&&clientInfos.dataChannel&&clientInfos.dataChannel.readyState!=='open'){if(debugShowLog)console.log(`%c KILL ZOMBIE ${clientId}`,'background: red;');this.removeClient(clientId);}else{if(debugShowLog)console.log(`%c NOT A ZOMBIE ${clientId}`,'background: green;');}},10000);}}
const RequestError=__exports.RequestError=class RequestError extends Error{constructor(message){super(message);this.name="RequestError";}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/conflict_dialog.js */
odoo.define('@web_editor/js/wysiwyg/conflict_dialog',['@odoo/owl','@web/core/dialog/dialog'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{Dialog}=require("@web/core/dialog/dialog");const ConflictDialog=__exports.ConflictDialog=class ConflictDialog extends Component{static components={Dialog};static props=["close","content"];static template='web_editor.ConflictDialog';}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/get_color_picker_template_service.js */
odoo.define('@web_editor/js/wysiwyg/get_color_picker_template_service',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");let colorPickerTemplatePromise;const getColorPickerTemplateService=__exports.getColorPickerTemplateService={dependencies:["orm"],async:true,start(env,{orm}){return()=>{colorPickerTemplatePromise??=orm.call('ir.ui.view','render_public_asset',['web_editor.colorpicker',{}]);return colorPickerTemplatePromise;};},};registry.category("services").add("get_color_picker_template",getColorPickerTemplateService);return __exports;});;

/* /web_editor/static/src/js/editor/perspective_utils.js */
odoo.define('@web_editor/js/editor/perspective_utils',[],function(require){'use strict';let __exports={};__exports.transform=transform;function transform([[a,b,c],[d,e,f],[g,h,i]],[x,y]){let z=g*x+h*y+i;return[(a*x+b*y+c)/z,(d*x+e*y+f)/z];}
function invert([[a,b,c],[d,e,f],[g,h,i]]){const determinant=a*e*i-a*f*h-b*d*i+b*f*g+c*d*h-c*e*g;return[[(e*i-h*f)/determinant,(h*c-b*i)/determinant,(b*f-e*c)/determinant],[(g*f-d*i)/determinant,(a*i-g*c)/determinant,(d*c-a*f)/determinant],[(d*h-g*e)/determinant,(g*b-a*h)/determinant,(a*e-d*b)/determinant],];}
function multiply(a,b){const[[a0,a1,a2],[a3,a4,a5],[a6,a7,a8]]=a;const[[b0,b1,b2],[b3,b4,b5],[b6,b7,b8]]=b;return[[a0*b0+a1*b3+a2*b6,a0*b1+a1*b4+a2*b7,a0*b2+a1*b5+a2*b8],[a3*b0+a4*b3+a5*b6,a3*b1+a4*b4+a5*b7,a3*b2+a4*b5+a5*b8],[a6*b0+a7*b3+a8*b6,a6*b1+a7*b4+a8*b7,a6*b2+a7*b5+a8*b8],];}
__exports.getProjective=getProjective;function getProjective(width,height,[[x0,y0],[x1,y1],[x2,y2],[x3,y3]]){const denominator=x3*(y1-y2)+x1*(y2-y3)+x2*(y3-y1);const a=(x0*(y2-y3)+x2*(y3-y0)+x3*(y0-y2))/denominator;const b=(x0*(y3-y1)+x3*(y1-y0)+x1*(y0-y3))/denominator;const c=(x0*(y1-y2)+x1*(y2-y0)+x2*(y0-y1))/denominator;const reverse=invert([[width,-width,0],[0,-height,height],[1,-1,1]]);const forward=[[a*x1,b*x2,c*x3],[a*y1,b*y2,c*y3],[a,b,c]];return multiply(forward,reverse);}
__exports.getAffineApproximation=getAffineApproximation;function getAffineApproximation(projective,[[x0,y0],[x1,y1],[x2,y2]]){const a=transform(projective,[x0,y0]);const b=transform(projective,[x1,y1]);const c=transform(projective,[x2,y2]);return multiply([[a[0],b[0],c[0]],[a[1],b[1],c[1]],[1,1,1]],invert([[x0,x1,x2],[y0,y1,y2],[1,1,1]]),);}
return __exports;});;

/* /web_editor/static/src/js/editor/image_processing.js */
odoo.define('@web_editor/js/editor/image_processing',['@web/core/network/rpc','@web/core/utils/objects','@web_editor/js/editor/perspective_utils'],function(require){'use strict';let __exports={};const{rpc}=require("@web/core/network/rpc");const{pick}=require("@web/core/utils/objects");const{getAffineApproximation,getProjective}=require("@web_editor/js/editor/perspective_utils");const cropperDataFields=__exports.cropperDataFields=['x','y','width','height','rotate','scaleX','scaleY'];const modifierFields=['filter','quality','mimetype','glFilter','originalId','originalSrc','resizeWidth','aspectRatio',"bgSrc","mimetypeBeforeConversion",];const isGif=__exports.isGif=(mimetype)=>mimetype==='image/gif';let _isWebGLEnabled;__exports.isWebGLEnabled=isWebGLEnabled;function isWebGLEnabled(){if(_isWebGLEnabled!==undefined){return _isWebGLEnabled;}
try{const canvas=document.createElement("canvas");_isWebGLEnabled=!!(window.WebGLRenderingContext&&(canvas.getContext("webgl")||canvas.getContext("experimental-webgl")));}catch{_isWebGLEnabled=false;}
return _isWebGLEnabled;}
const _applyAll=(result,filter,filters)=>{filters.forEach(f=>{if(f[0]==='blend'){const cv=f[1];const ctx=result.getContext('2d');ctx.globalCompositeOperation=f[2];ctx.globalAlpha=f[3];ctx.drawImage(cv,0,0);ctx.globalCompositeOperation='source-over';ctx.globalAlpha=1.0;}else{filter.addFilter(...f);}});};let applyAll;const glFilters={blur:filter=>filter.addFilter('blur',10),'1977':(filter,cv)=>{const ctx=cv.getContext('2d');ctx.fillStyle='rgb(243, 106, 188)';ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[['blend',cv,'screen',.3],['brightness',.1],['contrast',.1],['saturation',.3],]);},aden:(filter,cv)=>{const ctx=cv.getContext('2d');ctx.fillStyle='rgb(66, 10, 14)';ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[['blend',cv,'darken',.2],['brightness',.2],['contrast',-.1],['saturation',-.15],['hue',20],]);},brannan:(filter,cv)=>{const ctx=cv.getContext('2d');ctx.fillStyle='rgb(161, 44, 191)';ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[['blend',cv,'lighten',.31],['sepia',.5],['contrast',.4],]);},earlybird:(filter,cv)=>{const ctx=cv.getContext('2d');const gradient=ctx.createRadialGradient(cv.width/2,cv.height/2,0,cv.width/2,cv.height/2,Math.hypot(cv.width,cv.height)/2);gradient.addColorStop(.2,'#D0BA8E');gradient.addColorStop(1,'#1D0210');ctx.fillStyle=gradient;ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[['blend',cv,'overlay',.2],['sepia',.2],['contrast',-.1],]);},inkwell:(filter,cv)=>{applyAll(filter,[['sepia',.3],['brightness',.1],['contrast',-.1],['desaturateLuminance'],]);},maven:(filter,cv)=>{applyAll(filter,[['sepia',.25],['brightness',-.05],['contrast',-.05],['saturation',.5],]);},toaster:(filter,cv)=>{const ctx=cv.getContext('2d');const gradient=ctx.createRadialGradient(cv.width/2,cv.height/2,0,cv.width/2,cv.height/2,Math.hypot(cv.width,cv.height)/2);gradient.addColorStop(0,'#0F4E80');gradient.addColorStop(1,'#3B003B');ctx.fillStyle=gradient;ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[['blend',cv,'screen',.5],['brightness',-.1],['contrast',.5],]);},walden:(filter,cv)=>{const ctx=cv.getContext('2d');ctx.fillStyle='#CC4400';ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[['blend',cv,'screen',.3],['sepia',.3],['brightness',.1],['saturation',.6],['hue',350],]);},valencia:(filter,cv)=>{const ctx=cv.getContext('2d');ctx.fillStyle='#3A0339';ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[['blend',cv,'exclusion',.5],['sepia',.08],['brightness',.08],['contrast',.08],]);},xpro:(filter,cv)=>{const ctx=cv.getContext('2d');const gradient=ctx.createRadialGradient(cv.width/2,cv.height/2,0,cv.width/2,cv.height/2,Math.hypot(cv.width,cv.height)/2);gradient.addColorStop(.4,'#E0E7E6');gradient.addColorStop(1,'#2B2AA1');ctx.fillStyle=gradient;ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[['blend',cv,'color-burn',.7],['sepia',.3],]);},custom:(filter,cv,filterOptions)=>{const options=Object.assign({blend:'normal',filterColor:'',blur:'0',desaturateLuminance:'0',saturation:'0',contrast:'0',brightness:'0',sepia:'0',},JSON.parse(filterOptions||"{}"));const filters=[];if(options.filterColor){const ctx=cv.getContext('2d');ctx.fillStyle=options.filterColor;ctx.fillRect(0,0,cv.width,cv.height);filters.push(['blend',cv,options.blend,1]);}
delete options.blend;delete options.filterColor;filters.push(...Object.entries(options).map(([filter,amount])=>[filter,parseInt(amount)/100]));applyAll(filter,filters);},};__exports.applyModifications=applyModifications;async function applyModifications(img,dataOptions={}){const data=Object.assign({glFilter:'',filter:'#0000',quality:'75',forceModification:false,},img.dataset,dataOptions);let{width,height,resizeWidth,quality,filter,mimetype,originalSrc,glFilter,filterOptions,forceModification,perspective,svgAspectRatio,imgAspectRatio,}=data;[width,height,resizeWidth]=[width,height,resizeWidth].map(s=>parseFloat(s));quality=parseInt(quality);if(isGif(mimetype)&&!forceModification){return await _loadImageDataURL(originalSrc);}
const container=document.createElement('div');const original=await loadImage(originalSrc);originalSrc=original.getAttribute('src');container.appendChild(original);await activateCropper(original,0,data);let croppedImg=$(original).cropper('getCroppedCanvas',{width,height});$(original).cropper('destroy');if(imgAspectRatio){document.createElement('div').appendChild(croppedImg);imgAspectRatio=imgAspectRatio.split(':');imgAspectRatio=parseFloat(imgAspectRatio[0])/parseFloat(imgAspectRatio[1]);await activateCropper(croppedImg,imgAspectRatio,{y:0});croppedImg=$(croppedImg).cropper('getCroppedCanvas');$(croppedImg).cropper('destroy');}
const result=document.createElement('canvas');result.width=resizeWidth||croppedImg.width;result.height=perspective?result.width/svgAspectRatio:croppedImg.height*result.width/croppedImg.width;const ctx=result.getContext('2d');ctx.imageSmoothingQuality="high";ctx.mozImageSmoothingEnabled=true;ctx.webkitImageSmoothingEnabled=true;ctx.msImageSmoothingEnabled=true;ctx.imageSmoothingEnabled=true;if(perspective){const points=JSON.parse(perspective);const divisions=10;const w=croppedImg.width,h=croppedImg.height;const project=getProjective(w,h,[[(result.width/100)*points[0][0],(result.height/100)*points[0][1]],[(result.width/100)*points[1][0],(result.height/100)*points[1][1]],[(result.width/100)*points[2][0],(result.height/100)*points[2][1]],[(result.width/100)*points[3][0],(result.height/100)*points[3][1]],]);for(let i=0;i<divisions;i++){for(let j=0;j<divisions;j++){const[dx,dy]=[w/divisions,h/divisions];const upper={origin:[i*dx,j*dy],sides:[dx,dy],flange:0.1,overlap:0};const lower={origin:[i*dx+dx,j*dy+dy],sides:[-dx,-dy],flange:0,overlap:0.1};for(let{origin,sides,flange,overlap}of[upper,lower]){const[[a,c,e],[b,d,f]]=getAffineApproximation(project,[origin,[origin[0]+sides[0],origin[1]],[origin[0],origin[1]+sides[1]]]);const ox=(i!==divisions?overlap*sides[0]:0)+flange*sides[0];const oy=(j!==divisions?overlap*sides[1]:0)+flange*sides[1];origin[0]+=flange*sides[0];origin[1]+=flange*sides[1];sides[0]-=flange*sides[0];sides[1]-=flange*sides[1];ctx.save();ctx.setTransform(a,b,c,d,e,f);ctx.beginPath();ctx.moveTo(origin[0]-ox,origin[1]-oy);ctx.lineTo(origin[0]+sides[0],origin[1]-oy);ctx.lineTo(origin[0]+sides[0],origin[1]);ctx.lineTo(origin[0],origin[1]+sides[1]);ctx.lineTo(origin[0]-ox,origin[1]+sides[1]);ctx.closePath();ctx.clip();ctx.drawImage(croppedImg,0,0);ctx.restore();}}}}else{ctx.drawImage(croppedImg,0,0,croppedImg.width,croppedImg.height,0,0,result.width,result.height);}
const canUseWebGL=glFilter&&isWebGLEnabled()&&window.WebGLImageFilter;if(canUseWebGL){const glf=new window.WebGLImageFilter();const cv=document.createElement('canvas');cv.width=result.width;cv.height=result.height;applyAll=_applyAll.bind(null,result);glFilters[glFilter](glf,cv,filterOptions);const filtered=glf.apply(result);ctx.drawImage(filtered,0,0,filtered.width,filtered.height,0,0,result.width,result.height);}
ctx.fillStyle=filter||'#0000';ctx.fillRect(0,0,result.width,result.height);const dataURL=result.toDataURL(mimetype,quality/100);const newSize=getDataURLBinarySize(dataURL);const originalSize=_getImageSizeFromCache(originalSrc);const isChanged=!!perspective||!!glFilter||original.width!==result.width||original.height!==result.height||original.width!==croppedImg.width||original.height!==croppedImg.height;return(isChanged||originalSize>=newSize)?dataURL:await _loadImageDataURL(originalSrc);}
__exports.loadImage=loadImage;function loadImage(src,img=new Image()){const handleImage=(source,resolve,reject)=>{img.addEventListener("load",()=>resolve(img),{once:true});img.addEventListener("error",reject,{once:true});img.src=source;};const placeholderHref="/web/image/__odoo__unknown__src__/";return new Promise((resolve,reject)=>{fetch(src).then(response=>{if(!response.ok){src=placeholderHref;}
handleImage(src,resolve,reject);}).catch(error=>{src=placeholderHref;handleImage(src,resolve,reject);});});}
const imageCache=new Map();function _loadImageObjectURL(src){return _updateImageData(src);}
function _loadImageDataURL(src){return _updateImageData(src,'dataURL');}
async function _updateImageData(src,key='objectURL'){const currentImageData=imageCache.get(src);if(currentImageData&&currentImageData[key]){return currentImageData[key];}
let value='';const blob=await fetch(src).then(res=>res.blob());if(key==='dataURL'){value=await createDataURL(blob);}else{value=URL.createObjectURL(blob);}
imageCache.set(src,Object.assign(currentImageData||{},{[key]:value,size:blob.size}));return value;}
function _getImageSizeFromCache(src){return imageCache.get(src).size;}
__exports.activateCropper=activateCropper;async function activateCropper(image,aspectRatio,dataset){const oldSrc=image.src;const newSrc=await _loadImageObjectURL(image.getAttribute('src'));image.src=newSrc;$(image).cropper({viewMode:2,dragMode:'move',autoCropArea:1.0,aspectRatio:aspectRatio,data:Object.fromEntries(Object.entries(pick(dataset,...cropperDataFields)).map(([key,value])=>[key,parseFloat(value)])),minContainerWidth:1,minContainerHeight:1,});if(oldSrc===newSrc&&image.complete){return;}
return new Promise(resolve=>image.addEventListener('ready',resolve,{once:true}));}
__exports.loadImageInfo=loadImageInfo;async function loadImageInfo(img,attachmentSrc=''){const src=attachmentSrc||img.getAttribute('src');if((img.dataset.originalSrc&&img.dataset.mimetypeBeforeConversion)||!src){return;}
let docHref=img.ownerDocument.defaultView.location.href;if(docHref==="about:srcdoc"){docHref=window.location.href;}
const srcUrl=new URL(src,docHref);const relativeSrc=srcUrl.pathname;const{original}=await rpc('/web_editor/get_image_info',{src:relativeSrc});if(original&&original.image_src&&!/\/web\/image\/\d+-redirect\//.test(original.image_src)){if(!img.dataset.mimetype){img.dataset.mimetype=original.mimetype;}
img.dataset.originalId=original.id;img.dataset.originalSrc=original.image_src;img.dataset.mimetypeBeforeConversion=original.mimetype;}}
__exports.isImageSupportedForProcessing=isImageSupportedForProcessing;function isImageSupportedForProcessing(mimetype,strict=false){if(isGif(mimetype)){return!strict;}
return['image/jpeg','image/png','image/webp'].includes(mimetype);}
__exports.isImageSupportedForStyle=isImageSupportedForStyle;function isImageSupportedForStyle(img){if(!img.parentElement){return false;}
const isTFieldImg=('oeType'in img.parentElement.dataset);const isEditableRootElement=('oeXpath'in img.dataset);return!isTFieldImg&&!isEditableRootElement;}
__exports.createDataURL=createDataURL;function createDataURL(blob){return new Promise((resolve,reject)=>{const reader=new FileReader();reader.addEventListener('load',()=>resolve(reader.result));reader.addEventListener('abort',reject);reader.addEventListener('error',reject);reader.readAsDataURL(blob);});}
__exports.getDataURLBinarySize=getDataURLBinarySize;function getDataURLBinarySize(dataURL){return dataURL.split(',')[1].length/4*3;}
const removeOnImageChangeAttrs=__exports.removeOnImageChangeAttrs=[...cropperDataFields,...modifierFields];__exports[Symbol.for("default")]={applyModifications,cropperDataFields,activateCropper,loadImageInfo,loadImage,removeOnImageChangeAttrs,isImageSupportedForProcessing,isImageSupportedForStyle,createDataURL,isGif,getDataURLBinarySize,};return __exports;});;

/* /web_editor/static/src/js/editor/custom_colors.js */
odoo.define('@web_editor/js/editor/custom_colors',[],function(require){'use strict';let __exports={};__exports[Symbol.for("default")]=[['#000000','#424242','#636363','#9C9C94','#CEC6CE','#EFEFEF','#F7F7F7','#FFFFFF'],['#FF0000','#FF9C00','#FFFF00','#00FF00','#00FFFF','#0000FF','#9C00FF','#FF00FF'],['#F7C6CE','#FFE7CE','#FFEFC6','#D6EFD6','#CEDEE7','#CEE7F7','#D6D6E7','#E7D6DE'],['#E79C9C','#FFC69C','#FFE79C','#B5D6A5','#A5C6CE','#9CC6EF','#B5A5D6','#D6A5BD'],['#E76363','#F7AD6B','#FFD663','#94BD7B','#73A5AD','#6BADDE','#8C7BC6','#C67BA5'],['#CE0000','#E79439','#EFC631','#6BA54A','#4A7B8C','#3984C6','#634AA5','#A54A7B'],['#9C0000','#B56308','#BD9400','#397B21','#104A5A','#085294','#311873','#731842'],['#630000','#7B3900','#846300','#295218','#083139','#003163','#21104A','#4A1031']];return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/alt_dialog.js */
odoo.define('@web_editor/js/wysiwyg/widgets/alt_dialog',['@odoo/owl','@web/core/dialog/dialog'],function(require){'use strict';let __exports={};const{Component,useRef,onMounted}=require("@odoo/owl");const{Dialog}=require("@web/core/dialog/dialog");const AltDialog=__exports.AltDialog=class AltDialog extends Component{static components={Dialog};static props={confirm:Function,close:Function,alt:String,tag_title:String,};static template='web_editor.AltDialog';altRef=useRef("alt");tagTitleRef=useRef("tag_title");setup(){this.isConfirmedOrCancelled=false;onMounted(()=>{this.altRef.el.focus();});}
async _cancel(){if(this.isConfirmedOrCancelled){return;}
this.isConfirmedOrCancelled=true;this.props.close();}
async _confirm(){if(this.isConfirmedOrCancelled){return;}
this.isConfirmedOrCancelled=true;try{const allNonEscQuots=/"/g;const alt=this.altRef.el.value.replace(allNonEscQuots,"&quot;");const title=this.tagTitleRef.el.value.replace(allNonEscQuots,"&quot;");await this.props.confirm(alt,title);}catch(e){this.props.close();throw e;}
this.props.close();}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/chatgpt_alternatives_dialog.js */
odoo.define('@web_editor/js/wysiwyg/widgets/chatgpt_alternatives_dialog',['@web_editor/js/wysiwyg/widgets/chatgpt_dialog','@odoo/owl'],function(require){'use strict';let __exports={};const{ChatGPTDialog}=require('@web_editor/js/wysiwyg/widgets/chatgpt_dialog');const{useState,status}=require("@odoo/owl");const ChatGPTAlternativesDialog=__exports.ChatGPTAlternativesDialog=class ChatGPTAlternativesDialog extends ChatGPTDialog{static template='web_editor.ChatGPTAlternativesDialog';static props={...super.props,originalText:String,alternativesModes:{type:Object,optional:true},numberOfAlternatives:{type:Number,optional:true},};static defaultProps={alternativesModes:{correct:'Correct',short:'Shorten',long:'Lengthen',friendly:'Friendly',professional:'Professional',persuasive:'Persuasive',},numberOfAlternatives:3,};setup(){super.setup();this.state=useState({...this.state,conversationHistory:[{role:'system',content:'The user wrote the following text:\n'+'<generated_text>'+this.props.originalText+'</generated_text>\n'+'Your goal is to help the user write alternatives to that text.\n'+'Conditions:\n'+'- You must respect the format (wrapping the alternative between <generated_text> and </generated_text>)\n'+'- You must detect the language of the text given to you and respond in that language\n'+'- Do not write HTML\n'+'- You must suggest one and only one alternative per answer\n'+'- Your answer must be different every time, never repeat yourself\n'+'- You must respect whatever extra conditions the user gives you\n',}],messages:[],alternativesMode:'',messagesInProgress:0,currentBatchId:null,});this._generationIndex=0;this._generateAlternatives();}
switchAlternativesMode(ev){this.state.alternativesMode=ev.currentTarget.getAttribute('data-mode');this._generateAlternatives(1);}
async _generateAlternatives(numberOfAlternatives=this.props.numberOfAlternatives){this.state.messagesInProgress=numberOfAlternatives;const batchId=new Date().getTime();this.state.currentBatchId=batchId;let wasError=false;let messageIndex=0;while(!wasError&&messageIndex<numberOfAlternatives&&this.state.currentBatchId===batchId){this._generationIndex+=1;let query=messageIndex?'Write one alternative version of the original text.':'Try again another single version of the original text.';if(this.state.alternativesMode&&!messageIndex){query+=` Make it more ${this.state.alternativesMode} than your last answer.`;}
if(this.state.alternativesMode==='correct'){query='Simply correct the text, without altering its meaning in any way. Preserve whatever language the user wrote their text in.';}
await this._generate(query,(content,isError)=>{if(this.state.currentBatchId===batchId){const alternative=content.replace(/^[\s\S]*<generated_text>/,'').replace(/<\/generated_text>[\s\S]*$/,'');if(isError){wasError=true;}else{this.state.conversationHistory.push({role:'user',content:query,},{role:'assistant',content,});}
this.state.messages.push({author:'assistant',text:alternative,isError,batchId,mode:this.state.alternativesMode,id:new Date().getTime(),});}}).catch(()=>{if(this.state.currentBatchId===batchId){wasError=true;this.state.messages=[];}});if(status(this)==='destroyed'){return;}
messageIndex+=1;this.state.messagesInProgress-=1;if(wasError){break;}}
this.state.messagesInProgress=0;}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/chatgpt_dialog.js */
odoo.define('@web_editor/js/wysiwyg/widgets/chatgpt_dialog',['@odoo/owl','@web/core/dialog/dialog','@web/core/network/rpc','@web/core/utils/strings','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{Component,useState,markup,onWillDestroy,status}=require("@odoo/owl");const{Dialog}=require("@web/core/dialog/dialog");const{rpc}=require("@web/core/network/rpc");const{escape}=require("@web/core/utils/strings");const{_t}=require("@web/core/l10n/translation");const ChatGPTDialog=__exports.ChatGPTDialog=class ChatGPTDialog extends Component{static template="";static components={Dialog};static props={close:Function,insert:Function,};setup(){this.state=useState({selectedMessageId:null});onWillDestroy(()=>this.pendingRpcPromise?.abort());}
selectMessage(ev){this.state.selectedMessageId=+ev.currentTarget.getAttribute('data-message-id');}
insertMessage(ev){this.selectMessage(ev);this._confirm();}
formatContent(content){return markup([...this._postprocessGeneratedContent(content).childNodes].map(child=>{const nodes=new Set([...child.querySelectorAll('*')].flatMap(node=>node.childNodes));nodes.forEach(node=>{if(node.nodeType===Node.TEXT_NODE){node.textContent=escape(node.textContent);}});return child.outerHTML;}).join(''));}
_postprocessGeneratedContent(content){const lines=content.split('\n').filter(line=>line.trim().length);const fragment=document.createDocumentFragment();let parentUl,parentOl;let lineIndex=0;for(const line of lines){if(line.trim().startsWith('- ')){parentUl=parentUl||document.createElement('ul');const li=document.createElement('li');li.innerText=line.trim().slice(2);parentUl.appendChild(li);}else if((parentOl&&line.startsWith(`${parentOl.children.length + 1}. `))||(!parentOl&&line.startsWith('1. ')&&lines[lineIndex+1]?.startsWith('2. '))){parentOl=parentOl||document.createElement('ol');const li=document.createElement('li');li.innerText=line.slice(line.indexOf('.')+2);parentOl.appendChild(li);}else{[parentUl,parentOl].forEach(list=>list&&fragment.appendChild(list));parentUl=parentOl=undefined;const block=document.createElement(line.startsWith('Title: ')?'h2':'p');block.innerText=line;fragment.appendChild(block);}
lineIndex+=1;}
[parentUl,parentOl].forEach(list=>list&&fragment.appendChild(list));return fragment;}
_cancel(){this.props.close();}
_confirm(){try{this.props.close();const text=this.state.messages.find(message=>message.id===this.state.selectedMessageId)?.text;this.props.insert(this._postprocessGeneratedContent(text||''));}catch(e){this.props.close();throw e;}}
_generate(prompt,callback){const protectedCallback=(...args)=>{if(status(this)!=='destroyed'){delete this.pendingRpcPromise;return callback(...args);}}
this.pendingRpcPromise=rpc('/web_editor/generate_text',{prompt,conversation_history:this.state.conversationHistory,},{shadow:true});return this.pendingRpcPromise.then(content=>protectedCallback(content)).catch(error=>protectedCallback(_t(error.data?.message||error.message),true));}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/chatgpt_prompt_dialog.js */
odoo.define('@web_editor/js/wysiwyg/widgets/chatgpt_prompt_dialog',['@web_editor/js/wysiwyg/widgets/chatgpt_dialog','@odoo/owl','@web/core/utils/hooks','@web/core/browser/browser','@web/core/user','@web/core/utils/scrolling'],function(require){'use strict';let __exports={};const{ChatGPTDialog}=require('@web_editor/js/wysiwyg/widgets/chatgpt_dialog');const{useState,useEffect,useRef}=require("@odoo/owl");const{useAutofocus,useChildRef}=require("@web/core/utils/hooks");const{browser}=require("@web/core/browser/browser");const{user}=require("@web/core/user");const{scrollTo}=require("@web/core/utils/scrolling");const ChatGPTPromptDialog=__exports.ChatGPTPromptDialog=class ChatGPTPromptDialog extends ChatGPTDialog{static template='web_editor.ChatGPTPromptDialog';static props={...super.props,initialPrompt:{type:String,optional:true},};static defaultProps={initialPrompt:'',};setup(){super.setup();this.assistantAvatarUrl=`${browser.location.origin}/web_editor/static/src/img/odoobot_transparent.png`;this.userAvatarUrl=`${browser.location.origin}/web/image?model=res.users&field=avatar_128&id=${encodeURIComponent(user.userId)}`;this.state=useState({...this.state,prompt:this.props.initialPrompt,conversationHistory:[{role:'system',content:'You are a helpful assistant, your goal is to help the user write their document.',},{role:'assistant',content:'What do you need ?',}],messages:[],});this.promptInputRef=useRef('promptInput');this.modalRef=useChildRef();useAutofocus({refName:'promptInput'});useEffect(()=>{this.promptInputRef.el.style.height=0;this.promptInputRef.el.style.height=this.promptInputRef.el.scrollHeight+'px';},()=>[this.state.prompt]);useEffect(()=>{const modalEl=this.modalRef.el.querySelector("main.modal-body");const lastMessageEl=modalEl.lastElementChild;scrollTo(lastMessageEl,{behavior:"smooth",isAnchor:true,})},()=>[this.state.conversationHistory.length]);}
onTextareaKeydown(ev){if(ev.key==='Enter'&&!ev.shiftKey){ev.stopImmediatePropagation();if(this.state.prompt.trim().length){this.submitPrompt(ev);}}}
submitPrompt(ev){this._freezeInput();ev.preventDefault();const prompt=this.state.prompt;this.state.messages.push({author:'user',text:prompt});const messageId=new Date().getTime();const conversation={role:'user',content:prompt};this.state.conversationHistory.push(conversation);this.state.messages.push({author:'assistant',id:messageId});this.state.prompt='';this._generate(prompt,(content,isError)=>{if(isError){this.state.conversationHistory=this.state.conversationHistory.filter(c=>c!==conversation);}else{this.state.conversationHistory.push({role:'assistant',content});}
const messageIndex=this.state.messages.findIndex(m=>m.id===messageId);this.state.messages[messageIndex]={author:'assistant',text:content,isError,id:messageId,};this._unfreezeInput();});}
_freezeInput(){this.promptInputRef.el.setAttribute('disabled','');}
_unfreezeInput(){this.promptInputRef.el.removeAttribute('disabled');this.promptInputRef.el.focus();}
_cancel(){this._freezeInput();super._cancel();}
_confirm(){this._freezeInput();super._confirm();}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/chatgpt_translate_dialog.js */
odoo.define('@web_editor/js/wysiwyg/widgets/chatgpt_translate_dialog',['@odoo/owl','@web_editor/js/wysiwyg/widgets/chatgpt_dialog'],function(require){'use strict';let __exports={};const{useState}=require("@odoo/owl");const{ChatGPTDialog}=require('@web_editor/js/wysiwyg/widgets/chatgpt_dialog');const ChatGPTTranslateDialog=__exports.ChatGPTTranslateDialog=class ChatGPTTranslateDialog extends ChatGPTDialog{static template='web_editor.ChatGPTTranslateDialog';static props={...super.props,originalText:String,language:String,};setup(){super.setup();this.state=useState({...this.state,conversationHistory:[{role:'system',content:'You are a translation assistant. You goal is to translate text while maintaining the original format and'+'respecting specific instructions. \n'+'Instructions: \n'+'- You must respect the format (wrapping the translated text between <generated_text> and </generated_text>)\n'+'- Do not write HTML.'}],messages:[],translationInProgress:true,});this._translate();}
async _translate(){const prompt=`Translate <generated_text>${this.props.originalText}</generated_text> to ${this.props.language}`;const messageId=new Date().getTime();const conversation={role:'user',content:prompt};this.state.conversationHistory.push(conversation);this._generate(prompt,(content,isError)=>{let translatedText=content.replace(/^[\s\S]*<generated_text>/,'').replace(/<\/generated_text>[\s\S]*$/,'');if(!this.formatContent(translatedText).length){isError=true;translatedText="You didn't select any text.";}
this.state.translationInProgress=false;if(!isError){this.state.conversationHistory.push({role:'assistant',content});}
this.state.messages.push({author:'assistant',text:translatedText,id:messageId,isError,});this.state.selectedMessageId=messageId;});}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/color_palette.js */
odoo.define('@web_editor/js/wysiwyg/widgets/color_palette',['@web/core/colorpicker/colorpicker','@web_editor/js/editor/custom_colors','@web_editor/js/common/utils','@web/core/utils/colors','@odoo/owl'],function(require){'use strict';let __exports={};const{Colorpicker}=require("@web/core/colorpicker/colorpicker");const customColors=require("@web_editor/js/editor/custom_colors")[Symbol.for("default")];const weUtils=require("@web_editor/js/common/utils")[Symbol.for("default")];const{isCSSColor,normalizeCSSColor,convertCSSColorToRgba,}=require('@web/core/utils/colors');const{Component,useRef,useState,onWillStart,onMounted,onWillUpdateProps,}=require("@odoo/owl");const ColorPalette=__exports.ColorPalette=class ColorPalette extends Component{static template='web_editor.ColorPalette';static props={document:{type:true,optional:true},resetTabCount:{type:Number,optional:true},selectedCC:{type:String,optional:true},selectedColor:{type:String,optional:true},resetButton:{type:Boolean,optional:true},excluded:{type:Array,optional:true},excludeSectionOf:{type:Array,optional:true},withCombinations:{type:Boolean,optional:true},noTransparency:{type:Boolean,optional:true},opacity:{type:Number,optional:true},selectedTab:{type:String,optional:true},withGradients:{type:Boolean,optional:true},getTemplate:{type:Function,optional:true},onSetColorNames:{type:Function,optional:true},onColorHover:{type:Function,optional:true},onColorPicked:{type:Function,optional:true},onCustomColorPicked:{type:Function,optional:true},onColorLeave:{type:Function,optional:true},onInputEnter:{type:Function,optional:true},getCustomColors:{type:Function,optional:true},getEditableCustomColors:{type:Function,optional:true},onColorpaletteTabChange:{type:Function,optional:true},};static defaultProps={document:window.document,resetTabCount:0,resetButton:true,excluded:[],excludeSectionOf:null,withCombinations:false,noTransparency:false,opacity:1,selectedTab:'theme-colors',withGradients:false,onSetColorNames:()=>{},onColorHover:()=>{},onColorPicked:()=>{},onCustomColorPicked:()=>{},onColorLeave:()=>{},onInputEnter:()=>{},getCustomColors:()=>[],getEditableCustomColors:()=>[],onColorpaletteTabChange:()=>{},}
static components={Colorpicker};elRef=useRef('el');state=useState({showGradientPicker:false,});setup(){this.init();onWillStart(async()=>{if(this.props.getTemplate){this.colorpickerTemplate=await this.props.getTemplate();}});onMounted(async()=>{if(!this.elRef.el){await new Promise(resolve=>{const observer=new MutationObserver(()=>{if(this.elRef.el){observer.disconnect();resolve();}});observer.observe(document.body,{childList:true,subtree:true});});}
this.el=this.elRef.el;const $el=$(this.el);this.$=$el.find.bind($el);$el.on('click','.o_we_color_btn',this._onColorButtonClick.bind(this));$el.on('mouseenter','.o_we_color_btn',this._onColorButtonEnter.bind(this));$el.on('mouseleave','.o_we_color_btn',this._onColorButtonLeave.bind(this));$el.on('click','.o_custom_gradient_editor .o_custom_gradient_btn',this._onGradientCustomButtonClick.bind(this));$el.on('click','.o_custom_gradient_editor',this._onPanelClick.bind(this));$el.on('change','.o_custom_gradient_editor input[type="text"]',this._onGradientInputChange.bind(this));$el.on('keypress','.o_custom_gradient_editor input[type="text"]',this._onGradientInputKeyPress.bind(this));$el.on('click','.o_custom_gradient_editor we-button:not(.o_remove_color)',this._onGradientButtonClick.bind(this));$el.on('mouseenter','.o_custom_gradient_editor we-button:not(.o_remove_color)',this._onGradientButtonEnter.bind(this));$el.on('mouseleave','.o_custom_gradient_editor we-button:not(.o_remove_color)',this._onGradientButtonLeave.bind(this));$el.on('click','.o_custom_gradient_scale',this._onGradientPreviewClick.bind(this));$el.on('click','.o_custom_gradient_editor .o_remove_color',this._onGradientDeleteClick.bind(this));await this.start();});onWillUpdateProps((newProps)=>{this._updateColorToColornames();if(this.props.resetTabCount!==newProps.resetTabCount){this._selectDefaultTab();}
if(this.props.selectedCC!==newProps.selectedCC||this.props.selectedColor!==newProps.selectedColor){this._selectColor({ccValue:newProps.selectedCC,color:newProps.selectedColor,});}
this._buildCustomColors();this._markSelectedColor();});}
init(){const editableDocument=this.props.document;this.style=editableDocument.defaultView.getComputedStyle(editableDocument.documentElement);this.selectedColor='';this.resetButton=this.props.resetButton;this.withCombinations=this.props.withCombinations;this.selectedTab=this.props.selectedTab;this.tabs=[{id:'theme-colors',pickers:['theme','common',],},{id:'custom-colors',pickers:['custom','transparent_grayscale','common_grays',],},{id:'gradients',pickers:this.props.withGradients?['predefined_gradients','custom_gradient',]:[],}];this.sections={};this.pickers={};}
async start(){const switchPaneButtons=this.el.querySelectorAll('.o_we_colorpicker_switch_pane_btn');let colorpickerEl;if(this.colorpickerTemplate){colorpickerEl=$(this.colorpickerTemplate)[0];}else{colorpickerEl=document.createElement("colorpicker");const sectionEl=document.createElement('DIV');sectionEl.classList.add('o_colorpicker_section');sectionEl.dataset.name='common';colorpickerEl.appendChild(sectionEl);}
colorpickerEl.querySelectorAll('button').forEach(el=>el.classList.add('o_we_color_btn'));this.tabs.forEach((tab,index)=>{let sectionEl=this.el.querySelector(`.o_colorpicker_sections[data-color-tab="${tab.id}"]`);const container=sectionEl.querySelector('.o_colorpicker_section_container');if(container){sectionEl=container;}
let sectionIsEmpty=true;tab.pickers.forEach((pickerId)=>{let pickerEl;switch(pickerId){case'common_grays':pickerEl=colorpickerEl.querySelector('[data-name="common"]').cloneNode(true);break;case'custom':pickerEl=document.createElement('DIV');pickerEl.classList.add("o_colorpicker_section");pickerEl.dataset.name='custom';break;default:pickerEl=colorpickerEl.querySelector(`[data-name="${pickerId}"]`);pickerEl=pickerEl&&pickerEl.cloneNode(true);}
if(pickerEl){sectionEl.appendChild(pickerEl);if(!this.props.excluded.includes(pickerId)){sectionIsEmpty=false;}
this.pickers[pickerId]=pickerEl;}});if(sectionIsEmpty){sectionEl.classList.add('d-none');switchPaneButtons[index].classList.add('d-none');if(this.selectedTab===tab.id){this.selectedTab=this.tabs[(index+1)%this.tabs.length].id;}}
this.sections[tab.id]=sectionEl;});if(this.props.withGradients&&this.props.opacity!==1){this.pickers['predefined_gradients'].querySelectorAll('button').forEach(elem=>{let gradient=elem.dataset.color;gradient=gradient.replaceAll(/rgba?(\(\s*\d+\s*,\s*\d+\s*,\s*\d+)(?:\s*,.+?)?\)/g,`rgba$1, ${this.props.opacity})`);elem.dataset.color=gradient.replaceAll(/\s+/g,'');});}
if(this.pickers['custom_gradient']){const editor=this.pickers['custom_gradient'];this.gradientEditorParts={'customButton':editor.querySelector('.o_custom_gradient_btn'),'customContent':editor.querySelector('.o_color_picker_inputs'),'linearButton':editor.querySelector('we-button[data-gradient-type="linear-gradient"]'),'angleRow':editor.querySelector('.o_angle_row'),'angle':editor.querySelector('input[data-name="angle"]'),'radialButton':editor.querySelector('we-button[data-gradient-type="radial-gradient"]'),'positionRow':editor.querySelector('.o_position_row'),'positionX':editor.querySelector('input[data-name="positionX"]'),'positionY':editor.querySelector('input[data-name="positionY"]'),'sizeRow':editor.querySelector('.o_size_row'),'scale':editor.querySelector('.o_custom_gradient_scale div'),'sliders':editor.querySelector('.o_slider_multi'),'deleteButton':editor.querySelector('.o_remove_color'),};const gradient=weUtils.isColorGradient(this.props.selectedColor)&&this.props.selectedColor;this._selectGradient(gradient);const resizeObserver=new window.ResizeObserver(()=>{this._adjustActiveSliderDelete();});resizeObserver.observe(this.gradientEditorParts.sliders);}
const selectedButtonIndex=this.tabs.map(tab=>tab.id).indexOf(this.selectedTab);this._selectTabFromButton(this.el.querySelectorAll('button')[selectedButtonIndex]);const visibleButtons=Array.from(switchPaneButtons).filter(button=>!button.classList.contains('d-none'));if(visibleButtons.length===1){visibleButtons[0].classList.add('d-none');}
this.props.excluded.forEach((exc)=>{this.$('[data-name="'+exc+'"]').addClass('d-none');});if(this.props.excludeSectionOf){this.$('[data-name]:has([data-color="'+this.props.excludeSectionOf+'"])').addClass('d-none');}
this.el.querySelectorAll('.o_colorpicker_section').forEach(elem=>{$(elem).prepend('<div>'+(elem.dataset.display||'')+'</div>');});if(!this.props.excluded.includes('common')){customColors.forEach((colorRow,i)=>{if(i===0){return;}
const $div=$('<div/>',{class:'clearfix'}).appendTo(this.pickers['common']);colorRow.forEach(color=>{$div.append(this._createColorButton(color,['o_common_color']));});});}
this.colorNames=[...weUtils.COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES];this._updateColorToColornames();this.props.onSetColorNames([...this.colorNames]);if(this.props.selectedCC){this.selectedCC=this.props.selectedCC;}
this._setSelectedColor(this.props.selectedColor);this._buildCustomColors();this._markSelectedColor();if(!this.props.excluded.includes('custom')){let defaultColor=this.selectedColor;if(defaultColor&&!isCSSColor(defaultColor)){defaultColor=weUtils.getCSSVariableValue(defaultColor,this.style);}
if(!defaultColor&&this.props.opacity!==1){defaultColor='rgba(0, 0, 0, '+this.props.opacity+')';}
this.state.customDefaultColor=defaultColor;}}
_getSelectedColors(){return{ccValue:this.selectedCC,color:this.selectedColor,};}
_setSelectedColor(color){if(color){if(color==='rgba(0, 0, 0, 0)'&&this.props.opacity!==1){color='rgba(0, 0, 0, '+this.props.opacity+')';}
let selectedColor=color;if(weUtils.COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES.includes(selectedColor)){selectedColor=weUtils.getCSSVariableValue(selectedColor,this.style)||selectedColor;}
selectedColor=normalizeCSSColor(selectedColor);if(selectedColor!=='rgba(0, 0, 0, 0)'){this.selectedColor=this.colorToColorNames[selectedColor]||selectedColor;}}}
_buildCustomColors(){if(this.props.excluded.includes('custom')){return;}
this.el.querySelectorAll('.o_custom_color').forEach(el=>el.remove());const existingColors=new Set(Object.keys(this.colorToColorNames));for(const color of this.props.getCustomColors()){this._addCustomColor(existingColors,color);}
weUtils.getCSSVariableValue('custom-colors',this.style).split(' ').forEach(v=>{const color=weUtils.getCSSVariableValue(v.substring(1,v.length-1),this.style);if(isCSSColor(color)){this._addCustomColor(existingColors,color);}});for(const color of this.props.getEditableCustomColors()){this._addCustomColor(existingColors,color);}
if(this.selectedColor){this._addCustomColor(existingColors,this.selectedColor);}}
_addCustomColor(existingColors,color){if(!color){return;}
if(!isCSSColor(color)){color=weUtils.getCSSVariableValue(color,this.style);}
const normColor=normalizeCSSColor(color);if(!existingColors.has(normColor)){this._addCustomColorButton(normColor);existingColors.add(normColor);}}
_addCustomColorButton(color,classes=[]){classes.push('o_custom_color');const $button=this._createColorButton(color,classes);return $button.appendTo(this.pickers['custom']);}
_createColorButton(color,classes){return $('<button/>',{class:'o_we_color_btn '+classes.join(' '),style:'background-color:'+color+';',});}
_getButtonInfo(buttonEl){const bgColor=buttonEl.style.backgroundColor;const value=buttonEl.dataset.color||(bgColor&&bgColor!=='initial'?normalizeCSSColor(bgColor):'')||'';const info={target:buttonEl,};if(!value){info.ccValue='';info.color='';}else if(weUtils.isColorCombinationName(value)){info.ccValue=value;}else{info.color=value;}
return info;}
_selectColor(colorInfo,eventCallback){this.selectedCC=colorInfo.ccValue;this.selectedColor=colorInfo.color=this.colorToColorNames[colorInfo.color]||colorInfo.color;if(eventCallback){eventCallback(colorInfo);}
this._buildCustomColors();this.state.customSelectedColor=isCSSColor(colorInfo.color)?colorInfo.color:weUtils.getCSSVariableValue(colorInfo.color,this.style);const customGradient=weUtils.isColorGradient(colorInfo.color)?colorInfo.color:false;if(this.pickers['custom_gradient']){this._selectGradient(customGradient);}
this._markSelectedColor();}
_selectGradient(gradient){const editor=this.gradientEditorParts;this.state.showGradientPicker=false;const colorSplits=[];if(gradient){const colorTesterEl=document.createElement("div");colorTesterEl.style.display="none";document.body.appendChild(colorTesterEl);const colorTesterStyle=window.getComputedStyle(colorTesterEl);gradient=gradient.toLowerCase();for(const entry of gradient.matchAll(/(#[0-9a-f]{6}|rgba?\(\s*[0-9]+\s*,\s*[0-9]+\s*,\s*[0-9]+\s*[,\s*[0-9.]*]?\s*\)|[a-z]+)\s*([[0-9]+%]?)/g)){colorTesterEl.style.color=entry[1];if(!colorTesterEl.style.color){continue;}
const color=colorTesterStyle.color;colorSplits.push([color,entry[2].replace('%','')]);}
colorTesterEl.remove();}
if(!gradient||colorSplits.length<2){$(editor.customContent).addClass('d-none');editor.customButton.style['background-image']='';delete editor.customButton.dataset.color;return;}
$(editor.customContent).removeClass('d-none');editor.customButton.style['background-image']=gradient;editor.customButton.dataset.color=gradient;const scaleGradient=gradient.replace(/[^,]+,/,'linear-gradient(90deg,');editor.scale.style['background-image']=scaleGradient;const isLinear=gradient.startsWith('linear-gradient(');let lastSliderPosition;const activeSlider=editor.sliders.querySelector('input.active');if(activeSlider){lastSliderPosition=activeSlider.value;}
let $lastSlider;editor.sliders.replaceChildren();for(const index in colorSplits){const colorSplit=colorSplits[index];let color=colorSplit[0];const position=colorSplit[1]||100*index/colorSplits.length;const $slider=this._createGradientSlider(position,color);if(position===lastSliderPosition){$lastSlider=$slider;}}
editor.deleteButton.classList.add('d-none');if(isLinear){editor.linearButton.classList.add('active');editor.radialButton.classList.remove('active');let angle=gradient.match(/([0-9]+)deg/);angle=angle?angle[1]:0;editor.angle.value=angle;}else{editor.linearButton.classList.remove('active');editor.radialButton.classList.add('active');const sizeMatch=gradient.match(/(closest|farthest)-(side|corner)/);const size=sizeMatch?sizeMatch[0]:'farthest-corner';const $buttons=$(editor.sizeRow).find('we-button');$buttons.removeClass('active');$(editor.sizeRow).find("we-button[data-gradient-size='"+size+"']").addClass('active');const position=gradient.match(/ at ([0-9]+)% ([0-9]+)%/)||['','50','50'];editor.positionX.value=position[1];editor.positionY.value=position[2];}
this._updateGradientVisibility(isLinear);this._activateGradientSlider($lastSlider||$(this.pickers['custom_gradient'].querySelector('.o_slider_multi input')));}
_updateGradientVisibility(isLinear){const editor=this.gradientEditorParts;if(isLinear){editor.angleRow.classList.remove('d-none');editor.angleRow.classList.add('d-flex');editor.positionRow.classList.add('d-none');editor.positionRow.classList.remove('d-flex');editor.sizeRow.classList.add('d-none');editor.sizeRow.classList.remove('d-flex');}else{editor.angleRow.classList.add('d-none');editor.angleRow.classList.remove('d-flex');editor.positionRow.classList.remove('d-none');editor.positionRow.classList.add('d-flex');editor.sizeRow.classList.remove('d-none');editor.sizeRow.classList.add('d-flex');}}
_opacifyColor(color){if(color.startsWith('rgba')){return color.replace('rgba','rgb').replace(/,\s*[0-9.]+\s*\)/,')');}
return color;}
_createGradientSlider(position,color){const $slider=$('<input class="w-100" type="range" min="0" max="100"/>');$slider.attr('value',position);$slider.attr('data-color',color);$slider.css('color',this._opacifyColor(color));$slider.on('click',this._onGradientSliderClick.bind(this));$slider.appendTo(this.gradientEditorParts.sliders);this._sortGradientSliders();return $slider;}
_activateGradientSlider($slider){const $sliders=$(this.gradientEditorParts.sliders).find('input');$sliders.removeClass('active');$slider.addClass('active');const color=$slider.data('color');this.state.showGradientPicker=true;this.state.gradientSelectedColor=color;this._sortGradientSliders();this._adjustActiveSliderDelete();}
_adjustActiveSliderDelete(){const $sliders=$(this.gradientEditorParts.sliders).find('input');const $activeSlider=$(this.gradientEditorParts.sliders).find('input.active');if($sliders.length>2&&$activeSlider.length){this.gradientEditorParts.deleteButton.classList.remove('d-none');const sliderWidth=$activeSlider.width();const thumbWidth=12;const deleteWidth=$(this.gradientEditorParts.deleteButton).width();const pixelOffset=(sliderWidth-thumbWidth)*$activeSlider[0].value/100+(thumbWidth-deleteWidth)/2;this.gradientEditorParts.deleteButton.style['margin-left']=`${pixelOffset}px`;this.gradientEditorParts.deleteButton.style['margin-right']=`-${deleteWidth / 2}px`;}else{this.gradientEditorParts.deleteButton.classList.add('d-none');}}
_sortGradientSliders(){const $sliderInputs=$(this.gradientEditorParts.sliders).find('input');for(const slider of $sliderInputs.sort((a,b)=>parseInt(a.value,10)-parseInt(b.value,10))){this.gradientEditorParts.sliders.appendChild(slider);}}
_computeGradient(){const editor=this.gradientEditorParts;const $picker=$(this.pickers['custom_gradient']);const colors=[];for(const slider of $(editor.sliders).find('input')){const color=convertCSSColorToRgba($(slider).data('color'));const colorText=color.opacity!==100?`rgba(${color.red}, ${color.green}, ${color.blue}, ${color.opacity / 100})`:`rgb(${color.red}, ${color.green}, ${color.blue})`;const position=slider.value;colors.push(`${colorText} ${position}%`);}
const type=$picker.find('.o_type_row we-button.active').data('gradientType');const isLinear=type==='linear-gradient';let typeParam;if(isLinear){const angle=editor.angle.value||0;typeParam=`${angle}deg`;}else{const positionX=editor.positionX.value||50;const positionY=editor.positionY.value||50;const size=$picker.find('.o_size_row we-button.active').data('gradientSize');typeParam=`circle ${size} at ${positionX}% ${positionY}%`;}
return`${type}(${typeParam}, ${colors.join(', ')})`;}
_updateGradient(isPreview){const gradient=this._computeGradient();if(weUtils.areCssValuesEqual(gradient,this.selectedColor)&&!isPreview){return;}
const params={...this._getSelectedColors(),color:gradient,};if(isPreview){this.props.onColorHover(params);}else{this.props.onColorPicked(params);}}
_markSelectedColor(){for(const buttonEl of this.el.querySelectorAll('button')){const value=buttonEl.dataset.color||buttonEl.style.backgroundColor;const isCommonColor=buttonEl.classList.contains('o_common_color');const selectedColor=isCommonColor?this._opacifyColor(this.selectedColor):this.selectedColor;buttonEl.classList.toggle('selected',value&&(this.selectedCC===value||weUtils.areCssValuesEqual(selectedColor,value)));}}
_selectDefaultTab(){const selectedButtonIndex=this.tabs.map(tab=>tab.id).indexOf(this.selectedTab);this._selectTabFromButton(this.el.querySelectorAll('button')[selectedButtonIndex]);}
_selectTabFromButton(buttonEl){this.el.querySelectorAll('.o_we_colorpicker_switch_pane_btn').forEach(el=>{el.classList.remove('active');});buttonEl.classList.add('active');this.el.querySelectorAll('.o_colorpicker_sections').forEach(el=>{el.classList.toggle('d-none',el.dataset.colorTab!==buttonEl.dataset.target);});this.props.onColorpaletteTabChange(buttonEl.dataset.target);}
_updateGradientColor(colorInfo,isPreview){const $slider=$(this.gradientEditorParts.sliders).find('input.active');if(!weUtils.areCssValuesEqual(colorInfo.cssColor,$slider.data('color'))){const previousColor=$slider.data('color');$slider.data('color',colorInfo.cssColor);this._updateGradient(isPreview);if(isPreview){$slider.data('color',previousColor);}}}
_updateColorToColornames(){this.colorToColorNames={};this.el.querySelectorAll('button[data-color]:not(.o_custom_gradient_btn)').forEach(elem=>{const colorName=elem.dataset.color;if(weUtils.isColorGradient(colorName)){return;}
const $color=$(elem);const isCCName=weUtils.isColorCombinationName(colorName);if(isCCName){$color.find('.o_we_cc_preview_wrapper').addClass(`o_cc o_cc${colorName}`);}else if(weUtils.EDITOR_COLOR_CSS_VARIABLES.includes(colorName)){elem.style.backgroundColor=`var(--we-cp-${colorName})`;}else{elem.classList.add(`bg-${colorName}`);}
this.colorNames.push(colorName);if(!isCCName&&!elem.classList.contains('d-none')){const color=weUtils.getCSSVariableValue(colorName,this.style);this.colorToColorNames[color]=colorName;}});}
_onColorButtonClick(ev){const buttonEl=ev.currentTarget;const colorInfo={...this._getSelectedColors(),...this._getButtonInfo(buttonEl)};this._selectColor(colorInfo,this.props.onColorPicked);}
_onColorButtonEnter(ev){this.props.onColorHover({...this._getSelectedColors(),...this._getButtonInfo(ev.currentTarget)});}
_onColorButtonLeave(ev){this.props.onColorLeave({...this._getSelectedColors(),target:ev.target,});}
_onColorPickerPreview(colorInfo){this.props.onColorHover({...this._getSelectedColors(),color:colorInfo.cssColor,});}
_onColorPickerPreviewGradient(colorInfo){this._updateGradientColor(colorInfo,true);}
_onColorPickerSelect(colorInfo){this._selectColor({...this._getSelectedColors(),color:colorInfo.cssColor,},this.props.onCustomColorPicked);}
_onColorPickerSelectGradient(colorInfo){this._updateGradientColor(colorInfo);}
_onSwitchPaneButtonClick(ev){ev.stopPropagation();this._selectTabFromButton(ev.currentTarget);}
_onGradientSliderClick(ev){ev.stopPropagation();this._activateGradientSlider($(ev.target));this._updateGradient();}
_onGradientPreviewClick(ev){ev.stopPropagation();const offset=ev.offsetX;const width=parseInt(window.getComputedStyle(ev.target).width,10);const position=100*offset/width;let previousColor;let nextColor;let previousPosition;let nextPosition;for(const slider of $(this.gradientEditorParts.sliders).find('input')){if(slider.value<position){previousColor=slider.dataset.color;previousPosition=slider.value;}else{nextColor=slider.dataset.color;nextPosition=slider.value;break;}}
let color;if(previousColor&&nextColor){previousColor=convertCSSColorToRgba(previousColor);nextColor=convertCSSColorToRgba(nextColor);const previousRatio=(nextPosition-position)/(nextPosition-previousPosition);const nextRatio=1-previousRatio;const red=Math.round(previousRatio*previousColor.red+nextRatio*nextColor.red);const green=Math.round(previousRatio*previousColor.green+nextRatio*nextColor.green);const blue=Math.round(previousRatio*previousColor.blue+nextRatio*nextColor.blue);const opacity=Math.round(previousRatio*previousColor.opacity+nextRatio*nextColor.opacity);color=`rgba(${red}, ${green}, ${blue}, ${opacity / 100})`;}else{color=nextColor||previousColor||'rgba(128, 128, 128, 0.5)';}
const $slider=this._createGradientSlider(position,color);this._activateGradientSlider($slider);this._updateGradient();}
_onPanelClick(ev){ev.stopPropagation();}
_onGradientInputChange(ev){this._updateGradient();}
_onGradientInputKeyPress(ev){if(ev.key==="Enter"){ev.preventDefault();this._onGradientInputChange();}}
_onGradientButtonClick(ev){const $buttons=$(ev.target).closest('span').find('we-button');$buttons.removeClass('active');$(ev.target).closest('we-button').addClass('active');this._updateGradient();}
_onGradientButtonEnter(ev){ev.stopPropagation();const $activeButton=$(ev.target).closest('span').find('we-button.active');const $buttons=$(ev.target).closest('span').find('we-button');$buttons.removeClass('active');$(ev.target).closest('we-button').addClass('active');this._updateGradient(true);$buttons.removeClass('active');$activeButton.addClass('active');}
_onGradientButtonLeave(ev){ev.stopPropagation();this.props.onColorLeave({...this._getSelectedColors(),target:ev.target,});}
_onGradientCustomButtonClick(ev){let gradient=this.gradientEditorParts.customButton.style['backgroundImage'];if(!gradient){gradient=this.pickers['predefined_gradients'].querySelector('button').dataset.color;}
this._selectColor({...this._getSelectedColors(),color:gradient,target:this.gradientEditorParts.customButton,},this.props.onCustomColorPicked);this._updateGradient();}
_onGradientDeleteClick(ev){ev.stopPropagation();const $activeSlider=$(this.pickers['custom_gradient'].querySelector('.o_slider_multi input.active'));$activeSlider.off();$activeSlider.remove();this.gradientEditorParts.deleteButton.classList.add('d-none');this.gradientEditorParts.deleteButton.classList.remove('active');this._updateGradient();this._activateGradientSlider($(this.pickers['custom_gradient'].querySelector('.o_slider_multi input')));}
_onColorpickerClick(ev){if(ev.target.matches(".o_colorpicker_section, .o_colorpicker_sections")){ev.stopPropagation();}}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/image_crop.js */
odoo.define('@web_editor/js/wysiwyg/widgets/image_crop',['@web_editor/js/editor/image_processing','@web/core/l10n/translation','@odoo/owl','@web/core/utils/hooks','@web/core/utils/scrolling','@web_editor/js/common/scrolling','@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{applyModifications,cropperDataFields,activateCropper,loadImage,loadImageInfo}=require("@web_editor/js/editor/image_processing");const{_t}=require("@web/core/l10n/translation");const{Component,useRef,useState,onMounted,onWillDestroy,onWillUpdateProps,markup,}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");const{closestScrollableY}=require("@web/core/utils/scrolling");const{scrollTo}=require("@web_editor/js/common/scrolling");const{preserveCursor}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");const ImageCrop=__exports.ImageCrop=class ImageCrop extends Component{static template='web_editor.ImageCrop';static props={showCount:{type:Number,optional:true},activeOnStart:{type:Boolean,optional:true},media:{optional:true},mimetype:{type:String,optional:true},};static defaultProps={activeOnStart:false,showCount:0,};aspectRatios={"0/0":{label:_t("Flexible"),value:0},"16/9":{label:"16:9",value:16/9},"4/3":{label:"4:3",value:4/3},"1/1":{label:"1:1",value:1},"2/3":{label:"2:3",value:2/3},};state=useState({active:false,});elRef=useRef('el');_cropperClosed=true;setup(){this.mountedPromise=new Promise((resolve)=>{this.mountedResolve=resolve;});this.notification=useService("notification");onMounted(async()=>{const $el=$(this.elRef.el);this.$=$el.find.bind($el);this.$('[data-action]').on('click',this._onCropOptionClick.bind(this));$el.on('zoom',this._onCropZoom.bind(this));if(this.props.activeOnStart){this.state.active=true;await this._show(this.props);}
this.mountedResolve();});onWillUpdateProps((newProps)=>{if(newProps.showCount!==this.props.showCount){this.state.active=true;}
return this._show(newProps);});onWillDestroy(()=>{this._closeCropper();});}
_closeCropper(){if(this._cropperClosed)return;this._cropperClosed=true;if(this.$cropperImage){this.$cropperImage.cropper('destroy');this.elRef.el.ownerDocument.removeEventListener('mousedown',this._onDocumentMousedown,{capture:true});this.elRef.el.ownerDocument.removeEventListener('keydown',this._onDocumentKeydown,{capture:true});}
this.media.setAttribute('src',this.initialSrc);this.$media.trigger('image_cropper_destroyed');this.state.active=false;this.restoreCursor();}
async reset(){if(this.$cropperImage){this.$cropperImage.cropper('reset');if(this.aspectRatio!=='0/0'){this.aspectRatio='0/0';this.$cropperImage.cropper('setAspectRatio',this.aspectRatios[this.aspectRatio].value);}
await this._save();delete this.media.dataset.isManualCrop;this.media.classList.remove("o_we_image_cropped");}}
async cropSquare(previewMode){if(previewMode==="reset"){if(this.$cropperImage){this.$cropperImage.cropper("setAspectRatio",this.aspectRatios[this.aspectRatio].value);await this._save(false);}}else{const ratio="1/1";if(this.$cropperImage){if(this.aspectRatio!==ratio){this.aspectRatio=previewMode?this.aspectRatio:ratio;this.$cropperImage.cropper("setAspectRatio",this.aspectRatios[ratio].value);}
await this._save(false);}}}
async _show(props){if(!props.media||!this.state.active){return;}
this._cropperClosed=false;this.media=props.media;this.$media=$(this.media);this.document=this.media.ownerDocument;this.restoreCursor=preserveCursor(this.media.ownerDocument);const src=this.media.getAttribute('src');const data={...this.media.dataset};this.initialSrc=src;this.aspectRatio=data.aspectRatio||"0/0";const mimetype=data.mimetype||src.endsWith('.png')?'image/png':src.endsWith('.webp')?'image/webp':'image/jpeg';this.mimetype=this.props.mimetype||mimetype;await loadImageInfo(this.media);const isIllustration=/^\/(?:html|web)_editor\/shape\/illustration\//.test(this.media.dataset.originalSrc);this.uncroppable=false;if(this.media.dataset.originalSrc&&!isIllustration){this.originalSrc=this.media.dataset.originalSrc;this.originalId=this.media.dataset.originalId;}else{this.uncroppable=true;}
if(this.uncroppable){this.notification.add(markup(_t("This type of image is not supported for cropping.<br/>If you want to crop it, please first download it from the original source and upload it in Odoo.")),{title:_t("This image is an external image"),type:'warning',})
return this._closeCropper();}
const $cropperWrapper=this.$('.o_we_cropper_wrapper');await this._scrollToInvisibleImage();await loadImage(this.originalSrc,this.media);this.$cropperImage=this.$('.o_we_cropper_img');const cropperImage=this.$cropperImage[0];[cropperImage.style.width,cropperImage.style.height]=[this.$media.width()+'px',this.$media.height()+'px'];const sel=this.document.getSelection();sel&&sel.removeAllRanges();const mediaRect=this.media.getBoundingClientRect();const offset={left:mediaRect.left,top:mediaRect.top};offset.left+=parseInt(this.$media.css('padding-left'));offset.top+=parseInt(this.$media.css('padding-right'));const frameElement=this.$media[0].ownerDocument.defaultView.frameElement
if(frameElement){const frameRect=frameElement.getBoundingClientRect();offset.left+=frameRect.left;offset.top+=frameRect.top;}
$cropperWrapper[0].style.left=`${offset.left}px`;$cropperWrapper[0].style.top=`${offset.top}px`;await loadImage(this.originalSrc,cropperImage);this.elRef.el.classList.remove('d-none');await activateCropper(cropperImage,this.aspectRatios[this.aspectRatio].value,this.media.dataset);this._onDocumentMousedown=this._onDocumentMousedown.bind(this);this._onDocumentKeydown=this._onDocumentKeydown.bind(this);this.elRef.el.ownerDocument.addEventListener('mousedown',this._onDocumentMousedown,{capture:true});this.elRef.el.ownerDocument.addEventListener('keydown',this._onDocumentKeydown,{capture:true});}
async _save(refreshOptions=true){this.media.classList.add('o_modified_image_to_save');[...cropperDataFields,'aspectRatio'].forEach(attr=>{delete this.media.dataset[attr];const value=this._getAttributeValue(attr);if(value){this.media.dataset[attr]=value;}});delete this.media.dataset.resizeWidth;this.initialSrc=await applyModifications(this.media,{forceModification:true,mimetype:this.mimetype});this.media.classList.add("o_we_image_cropped");if(refreshOptions){this.$media.trigger('image_cropped');}
this._closeCropper();}
_getAttributeValue(attr){if(cropperDataFields.includes(attr)){return this.$cropperImage.cropper('getData')[attr];}
return this[attr];}
_resetCropBox(){this.$cropperImage.cropper('clear');this.$cropperImage.cropper('crop');}
async _scrollToInvisibleImage(){const rect=this.media.getBoundingClientRect();const viewportTop=this.document.documentElement.scrollTop||0;const viewportBottom=viewportTop+window.innerHeight;const scrollable=closestScrollableY(this.media);if(rect.top<viewportTop||viewportBottom-rect.bottom<100){await scrollTo(this.media,{duration:500,...(scrollable&&{scrollable}),});}}
_onCropOptionClick(ev){const{action,value,scaleDirection}=ev.currentTarget.dataset;switch(action){case'ratio':this.$cropperImage.cropper('reset');this.aspectRatio=value;this.$cropperImage.cropper('setAspectRatio',this.aspectRatios[this.aspectRatio].value);break;case'zoom':case'reset':this.$cropperImage.cropper(action,value);break;case'rotate':this.$cropperImage.cropper(action,value);break;case'flip':{const amount=this.$cropperImage.cropper('getData')[scaleDirection]*-1;return this.$cropperImage.cropper(scaleDirection,amount);}
case'apply':{this.media.dataset.isManualCrop="true";return this._save();}
case'discard':return this._closeCropper();}}
_onDocumentMousedown(ev){if(this.elRef.el.ownerDocument.body.contains(ev.target)&&this.$(ev.target).length===0){return this._closeCropper();}}
_onDocumentKeydown(ev){if(ev.key==='Enter'){return this._save();}else if(ev.key==='Escape'){ev.stopImmediatePropagation();return this._closeCropper();}}
async _onCropZoom(){await new Promise(res=>setTimeout(res,0));this._resetCropBox();}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/link.js */
odoo.define('@web_editor/js/wysiwyg/widgets/link',['@web/session','@web_editor/js/editor/odoo-editor/src/OdooEditor','@web/core/l10n/translation','@web/core/utils/ui','@web_editor/js/common/utils','@odoo/owl','@web/core/utils/hooks','@web_editor/js/editor/odoo-editor/src/utils/sanitize'],function(require){'use strict';let __exports={};const{session}=require("@web/session");const OdooEditorLib=require("@web_editor/js/editor/odoo-editor/src/OdooEditor");const{_t}=require("@web/core/l10n/translation");const{isVisible}=require("@web/core/utils/ui");const weUtils=require("@web_editor/js/common/utils")[Symbol.for("default")];const{Component,onWillStart,onMounted,onWillUpdateProps,useState,useRef,}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");const{deduceURLfromText}=require("@web_editor/js/editor/odoo-editor/src/utils/sanitize");const{getDeepRange,getInSelection,EMAIL_REGEX,PHONE_REGEX}=OdooEditorLib;const Link=__exports.Link=class Link extends Component{static template="";static props={editable:true,link:true,needLabel:{type:Boolean,optional:true},forceNewWindow:{type:Boolean,optional:true},initialIsNewWindow:{type:Boolean,optional:true},shouldFocusUrl:{type:Boolean,optional:true},};static defaultProps={needLabel:true,forceNewWindow:false,initialIsNewWindow:false,shouldFocusUrl:false,}
linkComponentWrapperRef=useRef("linkComponentWrapper");colorsData=[{type:'',label:_t("Link"),btnPreview:'link'},{type:'primary',label:_t("Button Primary"),btnPreview:'primary'},{type:'secondary',label:_t("Button Secondary"),btnPreview:'secondary'},{type:'custom',label:_t("Custom"),btnPreview:'custom'},];setup(){this.orm=useService("orm");this.state=useState({});this.mountedPromise=new Promise(resolve=>this.mountedResolve=resolve);onWillStart(async()=>{await this._updateState(this.props);});let started=false;onMounted(async()=>{if(started){return;}
started=true;if(!this.linkComponentWrapperRef.el){await new Promise(resolve=>{const observer=new MutationObserver(()=>{if(this.linkComponentWrapperRef.el){observer.disconnect();resolve();}});observer.observe(document.body,{childList:true,subtree:true});});}
this.$el=$(this.linkComponentWrapperRef.el);this.$el.find('input, select').on('input',this._onAnyChange.bind(this));this.$el.find('input, select').on('change',this._onAnyChange.bind(this));this.$el.find('[name="url"]').on('input',this.__onURLInput.bind(this));this.$el.find('[name="url"]').on('change',this._onURLInputChange.bind(this));await this.start();this.mountedResolve();});onWillUpdateProps(this.willUpdateProps);}
async start(){this._setSelectOptionFromLink();this.buttonOptsCollapseEl=this.linkComponentWrapperRef.el.querySelector('#o_link_dialog_button_opts_collapse');this._updateOptionsUI();this.$el[0].querySelector('#o_link_dialog_label_input').value=this.state.originalText;this._setUrl({shouldFocus:this.props.shouldFocusUrl});}
async willUpdateProps(newProps){await this.mountedPromise;await this._updateState(newProps);this.state.url=newProps.link.getAttribute("href")||"";this._setUrl({shouldFocus:newProps.shouldFocusUrl});}
applyLinkToDom(data){if(!data.classes.split(' ').includes('btn')){for(const linkClass of this.toleratedClasses){if(this.state.iniClassName&&this.state.iniClassName.split(' ').includes(linkClass)){data.classes+=" btn "+linkClass;}}}
if(data.classes.split(" ").includes("btn")){const closestButtonSiblingEls=this._getDirectButtonSiblings(this.linkEl);if(closestButtonSiblingEls.length){data.classes+=" mb-2";closestButtonSiblingEls.forEach(btnEl=>btnEl.classList.add("mb-2"));}}
if(['btn-custom','btn-outline-custom','btn-fill-custom'].some(className=>data.classes.includes(className))){this.$link.css('color',data.classes.includes(data.customTextColor)?'':data.customTextColor);this.$link.css('background-color',data.classes.includes(data.customFill)||weUtils.isColorGradient(data.customFill)?'':data.customFill);this.$link.css('background-image',weUtils.isColorGradient(data.customFill)?data.customFill:'');this.$link.css('border-width',data.customBorderWidth);this.$link.css('border-style',data.customBorderStyle);this.$link.css('border-color',data.customBorder);}else{this.$link.css('color','');this.$link.css('background-color','');this.$link.css('background-image','');this.$link.css('border-width','');this.$link.css('border-style','');this.$link.css('border-color','');}
const attrs=Object.assign({},this.state.oldAttributes,{href:data.url,target:data.isNewWindow?'_blank':'',});if(typeof data.classes==="string"){data.classes=data.classes.replace(/o_default_snippet_text/,'');attrs.class=`${data.classes}`;}
if(data.rel){attrs.rel=`${data.rel}`;}
this.$link.attr(attrs);if(!this.$link.attr('target')){this.$link[0].removeAttribute('target');}
this._updateLinkContent(this.$link,data);}
focusUrl(){const urlInput=this.$el[0].querySelector('input[name="url"]');urlInput.focus();urlInput.select();}
_setUrl({shouldFocus}={}){if(this.state.url){const protocolLessUrl=this.state.url.replace(/^(https?|mailto|tel):(\/\/)?/i,'');this.$el.find('input[name="url"]').val(protocolLessUrl);this._onURLInput();}
if(shouldFocus){this.focusUrl();}}
_setSelectOptionFromLink(){for(const option of this._getLinkOptions()){const $option=$(option);const value=$option.is('input')?$option.val():$option.data('value')||option.getAttribute('value');let active=false;if(value){const subValues=value.split(',');let subActive=true;for(let subValue of subValues){const classPrefix=new RegExp('(^|btn-| |btn-outline-|btn-fill-)'+subValue);subActive=subActive&&classPrefix.test(this.state.iniClassName);}
active=subActive;}else{active=!this.state.iniClassName||this.toleratedClasses.some(val=>this.state.iniClassName.split(' ').includes(val))||!this.state.iniClassName.includes('btn-');}
this._setSelectOption($option,active);}}
_adaptPreview(){}
_correctLink(url){if(url&&!url.startsWith("tel:")&&!url.startsWith("mailto:")&&!url.includes("://")&&!url.startsWith("/")&&!url.startsWith("#")&&!url.startsWith("${")){url="http://"+url;}
return url;}
_deduceUrl(text){text=text.trim();if(/^(https?:|mailto:|tel:)/.test(text)){return text;}else{const match=text.match(PHONE_REGEX);if(match){return("tel:"+match[0]).replace(/\s+/g,"");}
return deduceURLfromText(text,this.linkEl)||'';}}
_doStripDomain(){}
_isAbsoluteURLInCurrentDomain(url){let hasProtocol;try{hasProtocol=!!(new URL(url).protocol);}catch{hasProtocol=false;}
if(!hasProtocol){return false;}
const urlObj=new URL(url,window.location.origin);return urlObj.origin===window.location.origin||new RegExp(`^https?://${session.db}\\.odoo\\.com(/.*)?$`).test(urlObj.origin);}
_getData(){var $url=this.$el.find('input[name="url"]');var url=$url.val();var content=this.$el.find('input[name="label"]').val()||url;if(!this.state.isButton&&$url.prop('required')&&(!url||!$url[0].checkValidity())){return null;}
const type=this._getLinkType();const customTextColor=this._getLinkCustomTextColor();const customFill=this._getLinkCustomFill();const customBorder=this._getLinkCustomBorder();const customBorderWidth=this._getLinkCustomBorderWidth();const customBorderStyle=this._getLinkCustomBorderStyle();const customClasses=this._getLinkCustomClasses();const size=this._getLinkSize();const shape=this._getLinkShape();const shapes=shape?shape.split(','):[];const style=['outline','fill'].includes(shapes[0])?`${shapes[0]}-`:'';const shapeClasses=shapes.slice(style?1:0).join(' ');const classes=(this.state.className||'')+
(type?(` btn btn-${style}${type}`):'')+
(type==='custom'?customClasses:'')+
(type&&shapeClasses?(` ${shapeClasses}`):'')+
(type&&size?(' btn-'+size):'');var isNewWindow=this._isNewWindow(url);var doStripDomain=this._doStripDomain();let urlWithoutDomain=this.state.url;if(this._isAbsoluteURLInCurrentDomain(this.state.url)){const urlObj=new URL(this.state.url,window.location.origin);urlWithoutDomain=this.state.url.replace(urlObj.origin,'');if(doStripDomain){this.state.url=urlWithoutDomain;}}else if(this._isAbsoluteURLInCurrentDomain(url)&&!doStripDomain){this.state.url=url;}
var allWhitespace=/\s+/gi;var allStartAndEndSpace=/^\s+|\s+$/gi;const isImage=this.props.link&&this.props.link.querySelector('img');let isDocument=false;let directDownload=true;if(urlWithoutDomain&&urlWithoutDomain.startsWith("/web/content/")){isDocument=!this.isLastAttachmentUrl;directDownload=urlWithoutDomain.includes("&download=true");}
return{content:content,url:this._correctLink(this.state.url),classes:classes.replace(allWhitespace,' ').replace(allStartAndEndSpace,''),customTextColor:customTextColor,customFill:customFill,customBorder:customBorder,customBorderWidth:customBorderWidth,customBorderStyle:customBorderStyle,oldAttributes:this.state.oldAttributes,isNewWindow:isDocument||isNewWindow,doStripDomain:doStripDomain,isImage,isDocument,directDownload:directDownload&&isDocument,};}
_getDescendants(rootNode){const nodes=[];for(const node of rootNode.childNodes){nodes.push(node);nodes.push(...this._getDescendants(node));}
return nodes;}
_getIsNewWindowFormRow(){}
_getLinkOptions(){}
_getLinkShape(){}
_getLinkSize(){}
_getLinkType(){}
_getLinkCustomTextColor(){}
_getLinkCustomBorder(){}
_getLinkCustomBorderWidth(){}
_getLinkCustomBorderStyle(){}
_getLinkCustomFill(){}
_getLinkCustomClasses(){}
_isFromAnotherHostName(url){if(url.includes(window.location.hostname)){return false;}
try{const Url=URL||window.URL||window.webkitURL;const urlObj=url.startsWith('/')?new Url(url,window.location.origin):new Url(url);return(urlObj.origin!==window.location.origin);}catch{return true;}}
_isNewWindow(url){}
_setSelectOption($option,active){}
_updateLinkContent($link,linkInfos,{force=false}={}){if(force||(this.props.needLabel&&(linkInfos.content!==this.state.originalText||linkInfos.url!==this.state.url))){if(linkInfos.content===this.state.originalText||linkInfos.isImage){$link.html(this.state.originalHTML.replaceAll('\u200B','').replaceAll('\uFEFF',''));}else if(linkInfos.content&&linkInfos.content.length){let contentWrapperEl=$link[0];const text=$link[0].innerText.replaceAll("\u200B","").replaceAll("\uFEFF","").trim();let child;do{contentWrapperEl=child||contentWrapperEl;child=[...contentWrapperEl.children].find((element)=>!element.hasAttribute("data-o-link-zws"));}while(child?.innerText.replaceAll('\u200B','').replaceAll('\uFEFF','').trim()===text);contentWrapperEl.innerText=linkInfos.content;}else{$link.text(linkInfos.url);}}}
_updateOptionsUI(){}
async _updateState(props){this.initialIsNewWindowFromProps=props.initialIsNewWindow;this.initialNewWindow=props.initialIsNewWindow;this.state.className="";this.state.iniClassName="";this.toleratedClasses=['btn-link','btn-success'];this.editable=props.editable;this.$editable=$(this.editable);if(props.link){const range=document.createRange();range.selectNodeContents(props.link);this.state.range=range;this.$link=$(props.link);this.linkEl=props.link;}
if(this.state.range){this.$link=this.$link||$(OdooEditorLib.getInSelection(this.editable.ownerDocument,'a'));this.linkEl=this.$link[0];this.state.iniClassName=this.$link.attr('class')||'';this.colorCombinationClass=false;let $node=this.$link;while($node.length&&!$node.is('body')){const className=$node.attr('class')||'';const m=className.match(/\b(o_cc\d+)\b/g);if(m){this.colorCombinationClass=m[0];break;}
$node=$node.parent();}
const linkNode=this.$link[0]||this.state.range.cloneContents();const linkText=weUtils.getLinkLabel(linkNode);this.state.originalText=linkText.replace(/[ \t\r\n]+/g,' ');if(linkNode instanceof DocumentFragment){this.state.originalHTML=$('<fakeEl>').append(linkNode).html();}else{this.state.originalHTML=linkNode.innerHTML;}
this.state.url=this.$link.attr('href')||'';}else{this.state.originalText=this.state.originalText?this.state.originalText.replace(/[ \t\r\n]+/g,' '):'';}
this.state.url||=this._deduceUrl(this.state.originalText,this.linkEl);if(this.linkEl){this.initialNewWindow=this.initialNewWindow||this.linkEl.target==='_blank';await this._determineAttachmentType(this.linkEl.pathname);}
const classesToKeep=['text-wrap','text-nowrap','text-start','text-center','text-end','text-truncate',];const keptClasses=this.state.iniClassName.split(' ').filter(className=>classesToKeep.includes(className));const allBtnColorPrefixes=/(^|\s+)(bg|text|border)((-[a-z0-9_-]*)|\b)/gi;const allBtnClassSuffixes=/(^|\s+)btn((-[a-z0-9_-]*)|\b)/gi;const allBtnShapes=/\s*(rounded-circle|flat)\s*/gi;const btnMarginBottom=/(^|\s+)mb-2(\s+|$)/i;this.state.className=this.state.iniClassName.replace(allBtnColorPrefixes,' ').replace(allBtnClassSuffixes,' ').replace(allBtnShapes," ").replace(btnMarginBottom," ");this.state.className+=' '+keptClasses.join(' ');if(/(?:s_website_form_send|o_submit)/.test(this.state.className)){this.state.isButton=true;}}
async _determineAttachmentType(pathname){if(pathname?.startsWith("/web/content/")){const attachmentId=parseInt(pathname.substr("/web/content/".length));if(this.lastAttachmentId===attachmentId){return;}
this.lastAttachmentId=attachmentId;try{const fetched=await this.orm.read("ir.attachment",[attachmentId],["type"]);this.isLastAttachmentUrl=fetched[0].type==="url";}catch{this.isLastAttachmentUrl=undefined;}}}
_getDirectButtonSiblings(el){return["previous","next"].reduce((buttonSiblingsEls,side)=>{let siblingNode=el[`${side}Sibling`];while(siblingNode){if((siblingNode.nodeType===3&&!!siblingNode.textContent.match(/^\s*$/))||(siblingNode.nodeType===1&&(siblingNode.nodeName==="BR"||!isVisible(siblingNode)))){siblingNode=siblingNode[`${side}Sibling`];continue;}
if(siblingNode.nodeType===1&&siblingNode.classList.contains("btn")){buttonSiblingsEls.push(siblingNode);}
break;}
return buttonSiblingsEls;},[]);}
_onAnyChange(e){if(!e.target.closest('input[type="text"]')){this._adaptPreview();}}
__onURLInput(){const inputValue=this.$el[0].querySelector('#o_link_dialog_url_input').value;this.state.url=this._deduceUrl(inputValue,this.linkEl)||inputValue;this._onURLInput(...arguments);}
_onURLInput(){var $linkUrlInput=this.$el.find('#o_link_dialog_url_input');const value=$linkUrlInput.val()||'';let isLink=!EMAIL_REGEX.test(value)&&!PHONE_REGEX.test(value);this._getIsNewWindowFormRow().toggleClass('d-none',!isLink);this.$el.find('.o_strip_domain').toggleClass('d-none',!this._isAbsoluteURLInCurrentDomain(value));}
_onURLInputChange(){this._adaptPreview();this._determineAttachmentType(this.state.url).then(()=>{this.__onURLInput();});}}
__exports.getOrCreateLink=getOrCreateLink;function getOrCreateLink({containerNode,startNode}={}){if(startNode){if($(startNode).is('a')){return{link:startNode,needLabel:false};}else{$(startNode).wrap('<a href="#"/>');return{link:startNode.parentElement,needLabel:false};}}
const doc=containerNode&&containerNode.ownerDocument||document;let needLabel=false;let link=getInSelection(doc,'a');const $link=$(link);const range=getDeepRange(containerNode,{splitText:true,select:true,correctTripleClick:true});if(!range){return{};}
const isContained=containerNode.contains(range.startContainer)&&containerNode.contains(range.endContainer);if(link&&(!$link.has(range.startContainer).length||!$link.has(range.endContainer).length)){let before=link.previousSibling;while(before!==null&&range.intersectsNode(before)){link.insertBefore(before,link.firstChild);before=link.previousSibling;}
let after=link.nextSibling;while(after!==null&&range.intersectsNode(after)){link.appendChild(after);after=link.nextSibling;}}else if(!link&&isContained){link=document.createElement('a');const commonAncestor=range.commonAncestorContainer;const commonAncestorEl=commonAncestor.nodeType!==Node.ELEMENT_NODE?commonAncestor.parentElement:commonAncestor;if(commonAncestorEl.closest("p")){link.className="o_translate_inline";}
if(range.collapsed){range.insertNode(link);needLabel=true;}else{link.appendChild(range.extractContents());range.insertNode(link);}}
return{link,needLabel};};return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/link_dialog.js */
odoo.define('@web_editor/js/wysiwyg/widgets/link_dialog',['@odoo/owl','@web/core/dialog/dialog','@web_editor/js/wysiwyg/widgets/link'],function(require){'use strict';let __exports={};const{onMounted,useRef}=require("@odoo/owl");const{Dialog}=require("@web/core/dialog/dialog");const{Link}=require("@web_editor/js/wysiwyg/widgets/link");const LinkDialog=__exports.LinkDialog=class LinkDialog extends Link{static components={Dialog};static template='web_editor.LinkDialog';static props={...Link.props,focusField:{type:String,optional:true},close:{type:Function},onClose:{type:Function},onSave:{type:Function},};inputTextRef=useRef('inputText');inputUrlRef=useRef('inputUrl');setup(){super.setup();onMounted(()=>{this.$el.find('[name="link_style_color"]').on('change',this._onTypeChange.bind(this));this.$el.find('input[name="label"]').on('input',this._adaptPreview.bind(this));const el=this.props.focusField==='url'?this.inputUrlRef.el:this.inputTextRef.el;el.focus();});this.env.dialogData.close=()=>this.onDiscard();}
start(){super.start();this.buttonOptsCollapseEl=this.linkComponentWrapperRef.el.querySelector('#o_link_dialog_button_opts_collapse');this.$styleInputs=this.$el.find('input.link-style');this.$styleInputs.prop('checked',false).filter('[value=""]').prop('checked',true);if(this.initialNewWindow){this.$el.find('we-button.o_we_checkbox_wrapper').toggleClass('active',true);}}
onSave(ev){ev.preventDefault();var data=this._getData();if(data===null){var $url=this.$el.find('input[name="url"]');$url.closest('.o_url_input').addClass('o_has_error').find('.form-control, .form-select').addClass('is-invalid');$url.focus();return;}
var allWhitespace=/\s+/gi;var allStartAndEndSpace=/^\s+|\s+$/gi;var allBtnTypes=/(^|[ ])(btn-secondary|btn-success|btn-primary|btn-info|btn-warning|btn-danger)([ ]|$)/gi;data.classes=data.classes.replace(allWhitespace,' ').replace(allStartAndEndSpace,'');if(data.classes.replace(allBtnTypes,' ')){data.style={'background-color':'','color':'',};}
data.linkDialog=this;this.props.close();this.props.onSave(data);}
onDiscard(){this.props.onClose();this.props.close();}
onUrlKeydown(ev){const isAutoCompleteDropdownOpen=document.querySelector(".o-autocomplete--dropdown-menu");if(ev.key==="Enter"&&!isAutoCompleteDropdownOpen){this.onSave(ev);}}
_adaptPreview(){var data=this._getData();if(data===null){return;}
const attrs={target:'_blank',href:data.url&&data.url.length?data.url:'#',class:`${data.classes.replace(/float-\w+/, '')} o_btn_preview`,};const $linkPreview=this.$el.find("#link-preview");$linkPreview.attr(attrs);this._updateLinkContent($linkPreview,data,{force:true});}
_doStripDomain(){return this.$el.find('#o_link_dialog_url_strip_domain').prop('checked');}
_getIsNewWindowFormRow(){return this.$el.find('input[name="is_new_window"]').closest('.row');}
_getLinkOptions(){const options=['select[name="link_style_color"] > option','select[name="link_style_size"] > option','select[name="link_style_shape"] > option',];return this.$el.find(options.join(','));}
_getLinkShape(){return this.$el.find('select[name="link_style_shape"]').val()||'';}
_getLinkSize(){return this.$el.find('select[name="link_style_size"]').val()||'';}
_getLinkType(){return this.$el.find('select[name="link_style_color"]').val()||'';}
_isNewWindow(url){if(this.props.forceNewWindow){return this._isFromAnotherHostName(url);}else{return this.$el.find('input[name="is_new_window"]').prop('checked');}}
_setSelectOption($option,active){if($option.is("input")){$option.prop("checked",active);}else if(active){$option.parent().find('option').removeAttr('selected').removeProp('selected');$option.parent().val($option.val());$option.attr('selected','selected').prop('selected','selected');}}
_updateOptionsUI(){const el=this.linkComponentWrapperRef.el.querySelector('[name="link_style_color"] option:checked');$(this.buttonOptsCollapseEl).collapse(el&&el.value?'show':'hide');}
_onTypeChange(){this._updateOptionsUI();}
_onURLInput(){super._onURLInput(...arguments);this.$el.find('#o_link_dialog_url_input').closest('.o_url_input').removeClass('o_has_error').find('.form-control, .form-select').removeClass('is-invalid');this._adaptPreview();}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/link_popover_widget.js */
odoo.define('@web_editor/js/wysiwyg/widgets/link_popover_widget',['@web/core/l10n/translation','@web_editor/js/common/wysiwyg_utils','@web/core/utils/concurrency','@web/core/browser/browser'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{ancestors}=require('@web_editor/js/common/wysiwyg_utils');const{KeepLast}=require('@web/core/utils/concurrency');const{browser}=require("@web/core/browser/browser");const LinkPopoverWidget=__exports.LinkPopoverWidget=class LinkPopoverWidget{static createFor(params){const noLinkPopoverClass=".o_no_link_popover, .carousel-control-prev, .carousel-control-next, .dropdown-toggle";const alreadyPopover=$(params.target).data('bs.popover');if(alreadyPopover||$(params.target).is(noLinkPopoverClass)||!!$(params.target).parents(noLinkPopoverClass).length){return null;}
const popoverWidget=new this(params);params.wysiwyg?.odooEditor.observerUnactive('LinkPopoverWidget');popoverWidget.start();params.wysiwyg?.odooEditor.observerActive('LinkPopoverWidget');return popoverWidget;};template=`
        <div class="d-flex">
            <span class="me-2 o_we_preview_favicon"><i class="fa fa-globe"></i><img class="align-baseline d-none"></img></span>
            <div class="w-100">
                <div class="d-flex">
                    <a href="#" target="_blank" class="o_we_url_link fw-bold flex-grow-1 text-truncate" title="${_t('Open in a new tab')}"></a>
                    <a href="#" class="mx-1 o_we_copy_link text-dark" data-bs-toggle="tooltip" data-bs-placement="top" title="${_t('Copy Link')}">
                        <i class="fa fa-clone"></i>
                    </a>
                    <a href="#" class="mx-1 o_we_edit_link text-dark" data-bs-toggle="tooltip" data-bs-placement="top" title="${_t('Edit Link')}">
                        <i class="fa fa-edit"></i>
                    </a>
                    <a href="#" class="ms-1 o_we_remove_link text-dark" data-bs-toggle="tooltip" data-bs-placement="top" title="${_t('Remove Link')}">
                        <i class="fa fa-chain-broken"></i>
                    </a>
                </div>
                <a href="#" target="_blank" class="o_we_full_url mt-1 text-muted d-none" title="${_t('Open in a new tab')}"></a>
            </div>
        </div>
    `;constructor(params){const template=document.createElement('template');template.innerHTML=this.template;this.el=template.content.firstElementChild;this.$el=$(this.el);this.wysiwyg=params.wysiwyg;this.target=params.target;this.notify=params.notify;this.$target=$(params.target);this.container=params.container||this.target.ownerDocument.body;this.href=this.$target.attr('href');this._keepLastPromise=new KeepLast();this.isDocument=!!(this.$target.attr("data-mimetype")&&this.$target[0].dataset.mimetype.startsWith("image"));}
start(){this.$urlLink=this.$el.find('.o_we_url_link');this.$previewFaviconImg=this.$el.find('.o_we_preview_favicon img');this.$previewFaviconFa=this.$el.find('.o_we_preview_favicon .fa');this.$copyLink=this.$el.find('.o_we_copy_link');this.$fullUrl=this.$el.find('.o_we_full_url');if(this.isDocument){this.$el.find('.o_we_edit_link, .o_we_remove_link, .o_we_full_url').attr('hidden',true);}
this.$urlLink.attr('href',this.href);this.$fullUrl.attr('href',this.href);this.$el.find(`.o_we_edit_link`).on('click',this._onEditLinkClick.bind(this));this.$el.find(`.o_we_remove_link`).on('click',this._onRemoveLinkClick.bind(this));this.$copyLink.on("click",this._onCopyLinkClick.bind(this));this.$el.find('[data-bs-toggle="tooltip"]').tooltip({delay:0,placement:'bottom',container:this.container,});const tooltips=[];for(const el of this.$el.find('[data-bs-toggle="tooltip"]').toArray()){tooltips.push(Tooltip.getOrCreateInstance(el));}
let popoverShown=true;const editable=this.wysiwyg.odooEditor.editable;this.$target.popover({html:true,content:this.$el,placement:'bottom',trigger:'manual',boundary:editable,container:this.container,}).on('show.bs.popover.link_popover',()=>{this._loadAsyncLinkPreview();popoverShown=true;}).on('hide.bs.popover.link_popover',()=>{popoverShown=false;}).on('hidden.bs.popover.link_popover',()=>{for(const tooltip of tooltips){tooltip.hide();}}).on('inserted.bs.popover.link_popover',()=>{const popover=Popover.getInstance(this.target);popover.tip.classList.add('o_edit_menu_popover');}).popover('show');this.popover=Popover.getInstance(this.target);this.$target.on('mousedown.link_popover',(e)=>{if(!popoverShown){this.$target.popover('show');}});this.$target.on('href_changed.link_popover',(e)=>{if(popoverShown){this._loadAsyncLinkPreview();}});const onClickDocument=(e)=>{if(popoverShown){const hierarchy=[e.target,...ancestors(e.target)];if(!(hierarchy.includes(this.$target[0])||(hierarchy.includes(this.$el[0])&&!hierarchy.some(x=>x.tagName&&x.tagName==='A'&&(x===this.$urlLink[0]||x===this.$fullUrl[0]))))){this.popover.hide();}}};$(document).on('mouseup.link_popover',onClickDocument);if(document!==this.wysiwyg.odooEditor.document){$(this.wysiwyg.odooEditor.document).on('mouseup.link_popover',onClickDocument);}
this._observer=new MutationObserver(records=>{if(!popoverShown){return;}
if(records.some(record=>record.type==='attributes')){this._loadAsyncLinkPreview();}
this.$target.popover('update');});this._observer.observe(this.target,{subtree:true,characterData:true,attributes:true,attributeFilter:['href'],});}
destroy(){this.$target.off('.link_popover');$(document).off('.link_popover');$(this.wysiwyg.odooEditor.document).off('.link_popover');this.$target.popover('dispose');this._observer.disconnect();}
hide(){this.$target.popover('hide');}
async _loadAsyncLinkPreview(){let url;if(this.target.href===''){this._resetPreview('');this.$previewFaviconFa.removeClass('fa-globe').addClass('fa-question-circle-o');return;}
try{url=new URL(this.target.href);}catch{this.notify(_t("This URL is invalid. Preview couldn't be updated."),{type:'danger',});return;}
this._resetPreview(url);const protocol=url.protocol;if(!protocol.startsWith('http')){const faMap={'mailto:':'fa-envelope-o','tel:':'fa-phone'};const icon=faMap[protocol];if(icon){this.$previewFaviconFa.toggleClass(`fa-globe ${icon}`);}}else if(window.location.hostname!==url.hostname){this.$previewFaviconImg.attr({'src':`https://www.google.com/s2/favicons?sz=16&domain=${encodeURIComponent(url)}`}).removeClass('d-none');this.$previewFaviconFa.addClass('d-none');}else{await this._keepLastPromise.add($.get(this.target.href)).then(content=>{const parser=new window.DOMParser();const doc=parser.parseFromString(content,"text/html");const favicon=doc.querySelector("link[rel~='icon']");const ogTitle=doc.querySelector("[property='og:title']");const title=doc.querySelector("title");if(favicon){this.$previewFaviconImg.attr({'src':favicon.href}).removeClass('d-none');this.$previewFaviconFa.addClass('d-none');}
if(ogTitle||title){this.$urlLink.text(ogTitle?ogTitle.getAttribute('content'):title.text.trim());}
this.$fullUrl.removeClass('d-none').addClass('o_we_webkit_box');}).catch(error=>{if(error instanceof Error){return Promise.reject(error);}}).finally(()=>{this.$target.popover('update');});}}
_resetPreview(url){this.$previewFaviconImg.addClass('d-none');this.$previewFaviconFa.removeClass('d-none fa-question-circle-o fa-envelope-o fa-phone').addClass('fa-globe');this.$urlLink.add(this.$fullUrl).text(url||_t('No URL specified')).attr('href',url||null);this.$fullUrl.addClass('d-none').removeClass('o_we_webkit_box');}
_onEditLinkClick(ev){ev.preventDefault();this.wysiwyg.toggleLinkTools({forceOpen:true,link:this.$target[0],});ev.stopImmediatePropagation();this.popover.hide();}
_onRemoveLinkClick(ev){ev.preventDefault();this.wysiwyg.removeLink();ev.stopImmediatePropagation();this.popover.hide();}
async _onCopyLinkClick(ev){ev.preventDefault();await browser.navigator.clipboard.writeText(this.target.href);this.$copyLink.tooltip('hide');this.notify(_t("Link copied to clipboard."),{type:'success',});this.popover.hide();}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/widgets/link_tools.js */
odoo.define('@web_editor/js/wysiwyg/widgets/link_tools',['@web_editor/js/wysiwyg/widgets/link','@web_editor/js/wysiwyg/widgets/color_palette','@web_editor/js/common/utils','@odoo/owl','@web/core/utils/colors','@web/core/utils/hooks','@web_editor/js/editor/odoo-editor/src/OdooEditor'],function(require){'use strict';let __exports={};const{Link}=require("@web_editor/js/wysiwyg/widgets/link");const{ColorPalette}=require('@web_editor/js/wysiwyg/widgets/color_palette');const weUtils=require("@web_editor/js/common/utils")[Symbol.for("default")];const{onMounted,onWillUnmount,onWillDestroy,useState,}=require("@odoo/owl");const{normalizeCSSColor}=require('@web/core/utils/colors');const{useService}=require("@web/core/utils/hooks");const{isButton}=require("@web_editor/js/editor/odoo-editor/src/OdooEditor");const LinkTools=__exports.LinkTools=class LinkTools extends Link{static template='web_editor.LinkTools';static props={...Link.props,wysiwyg:{type:Object},$button:{type:Object},onColorCombinationClassChange:{type:Function,optional:true},onPreApplyLink:{type:Function,optional:true},onPostApplyLink:{type:Function,optional:true},onDestroy:{type:Function,optional:true},getColorpickerTemplate:{type:Function,optional:true},};static defaultProps={...Link.defaultProps,onColorCombinationClassChange:()=>{},onPreApplyLink:()=>{},onPostApplyLink:()=>{},onDestroy:()=>{},};static components={ColorPalette};colorpickerProps=useState({'color':{selectedColor:undefined},'background-color':{selectedColor:undefined},'border-color':{selectedColor:undefined},});colorpickers={'color':{colorNames:null},'background-color':{colorNames:null},'border-color':{colorNames:null},};state=useState({showLinkSizeRow:true,showLinkCustomColor:true,showLinkShapeRow:true,isDocument:false,directDownload:true,});setup(){super.setup(...arguments);onMounted(()=>{this._observer=new MutationObserver(records=>{if(records.some(record=>record.type==='attributes')){this.state.url=this.props.link.getAttribute('href')||'';this._setUrl();}
this._updateLabelInput();});this._observerOptions={subtree:true,childList:true,characterData:true,attributes:true,attributeFilter:['href'],};this._observer.observe(this.props.link,this._observerOptions);});onWillUnmount(()=>{this._observer.disconnect();});onWillDestroy(()=>{const $contents=this.$link.contents();if(shouldUnlink(this.$link[0],this.colorCombinationClass)){$contents.unwrap();}
this.props.onDestroy();});this.uploadService=useService('uploadLocalFiles');}
async willUpdateProps(newProps){await super.willUpdateProps(newProps);this.$link=newProps.link?$(newProps.link):this.link;this._setSelectOptionFromLink();this._updateOptionsUI();this._updateLabelInput();this._checkDocumentState();}
async _updateState(){await super._updateState(...arguments);this.customColors={};this.PREFIXES={'color':'text-','background-color':'bg-',};this._updateInitialNewWindowUI();}
_updateInitialNewWindowUI(){if(this.$el&&this.$el[0]){const checkboxEl=this.$el[0].querySelector("we-checkbox[name='is_new_window'");if(checkboxEl){checkboxEl.checked=this.initialNewWindow?"checked":"";const buttonEl=checkboxEl.closest("we-button");if(buttonEl){buttonEl.classList[this.initialNewWindow?"add":"remove"]("active");}}}}
async start(){const ret=await super.start(...arguments);this.$el.on('click','we-select we-button',this._onPickSelectOption.bind(this));this.$el.on('click','we-checkbox',this._onClickCheckbox.bind(this));this.$el.on('change','.link-custom-color-border input',this._onChangeCustomBorderWidth.bind(this));this.$el.on('keypress','.link-custom-color-border input',this._onKeyPressCustomBorderWidth.bind(this));this.$el.on('click','we-select [name="link_border_style"] we-button',this._onBorderStyleSelectOption.bind(this));this.$el.on('input','input[name="label"]',this._onLabelInput.bind(this));this._setSelectOptionFromLink();this._updateOptionsUI();if(!this.linkEl.href&&this.state.url){this.__onURLInput();}
this._checkDocumentState();return ret;}
applyLinkToDom(){this._observer.disconnect();this.props.onPreApplyLink();super.applyLinkToDom(...arguments);this.props.wysiwyg.odooEditor.historyStep();this.props.onPostApplyLink();this._observer.observe(this.props.link,this._observerOptions);}
focusUrl(){this.$el[0].scrollIntoView();super.focusUrl(...arguments);}
openDocumentDialog(){this.props.wysiwyg.openMediaDialog({resModel:"ir.ui.view",useMediaLibrary:true,noImages:true,noIcons:true,noVideos:true,save:async(link)=>{this.initialNewWindow=this.initialIsNewWindowFromProps;this._updateInitialNewWindowUI();let relativeUrl=link.href.substr(window.location.origin.length);await this._determineAttachmentType(relativeUrl.split("?")[0]);if(this.isLastAttachmentUrl){relativeUrl=relativeUrl.replace("&download=true","");}
this.$el[0].querySelector("#o_link_dialog_url_input").value=relativeUrl;this.__onURLInput();},});}
async uploadFile(){const{upload,getURL}=this.uploadService;const[attachment]=await upload({resModel:"ir.ui.view"});if(!attachment){return;}
let relativeUrl=getURL(attachment,{download:true,unique:true});this.initialNewWindow=this.initialIsNewWindowFromProps;this._updateInitialNewWindowUI();this.lastAttachmentId=attachment.id;this.isLastAttachmentUrl=false;this.$el[0].querySelector("#o_link_dialog_url_input").value=relativeUrl;this.__onURLInput();}
_setSelectOptionFromLink(){super._setSelectOptionFromLink(...arguments);const link=this.$link[0];const customStyleProps=['color','background-color','background-image','border-width','border-style','border-color'];const shapeClasses=['btn-outline-primary','btn-outline-secondary','btn-fill-primary','btn-fill-secondary','rounded-circle','flat'];if(customStyleProps.some(s=>link.style[s])||shapeClasses.some(c=>link.classList.contains(c))){const customOption=this.$el[0].querySelector('[name="link_style_color"] we-button[data-value="custom"]');this._setSelectOption($(customOption),true);}}
_adaptPreview(){var data=this._getData();if(data===null){return;}
this.applyLinkToDom(data);}
_doStripDomain(){return this.$el.find('we-checkbox[name="do_strip_domain"]').closest('we-button.o_we_checkbox_wrapper').hasClass('active');}
_getIsNewWindowFormRow(){return this.$el.find('we-checkbox[name="is_new_window"]').closest('we-row');}
_getLinkOptions(){const options=['we-selection-items[name="link_style_color"] > we-button','we-selection-items[name="link_style_size"] > we-button','we-selection-items[name="link_style_shape"] > we-button',];return this.$el.find(options.join(','));}
_getLinkShape(){return this.$el.find('we-selection-items[name="link_style_shape"] we-button.active').data('value')||'';}
_getLinkSize(){return this.$el.find('we-selection-items[name="link_style_size"] we-button.active').data('value')||'';}
_getLinkType(){return this.$el.find('we-selection-items[name="link_style_color"] we-button.active').data('value')||'';}
_getLinkCustomTextColor(){return this.customColors['color'];}
_getLinkCustomBorder(){return this.customColors['border-color'];}
_getLinkCustomBorderWidth(){return this.$el.find('.link-custom-color-border input').val()||'';}
_getLinkCustomBorderStyle(){return this.$el.find('.link-custom-color-border we-button.active').data('value')||'';}
_getLinkCustomFill(){return this.customColors['background-color'];}
_getLinkCustomClasses(){let textClass=this.customColors['color'];const colorPickerFg=this.colorpickers['color'].colorNames;if(!textClass||!colorPickerFg||!weUtils.computeColorClasses(colorPickerFg,'text-').includes(textClass)){textClass='';}
let fillClass=this.customColors['background-color'];const colorPickerBg=this.colorpickers['background-color'].colorNames;if(!fillClass||!colorPickerBg||!weUtils.computeColorClasses(colorPickerBg,'bg-').includes(fillClass)){fillClass='';}
return` ${textClass} ${fillClass}`;}
_isNewWindow(url){if(this.props.forceNewWindow){return this._isFromAnotherHostName(url);}else{return this.$el.find('we-checkbox[name="is_new_window"]').closest('we-button.o_we_checkbox_wrapper').hasClass('active');}}
_setSelectOption($option,active){$option.toggleClass('active',active);if(active){$option.closest('we-select').find('we-toggler').text($option.text());$option.siblings('we-button').removeClass("active");}}
_updateOptionsUI(){const el=this.$el[0].querySelector('[name="link_style_color"] we-button.active');if(el){this.colorCombinationClass=el.dataset.value;this.state.showLinkSizeRow=Boolean(this.colorCombinationClass);this.state.showLinkCustomColor=el.dataset.value==='custom';this.state.showLinkShapeRow=el.dataset.value==='custom';this.props.onColorCombinationClassChange(this.colorCombinationClass);this._updateColorpicker('color');this._updateColorpicker('background-color');this._updateColorpicker('border-color');const borderWidth=this.linkEl.style['border-width'];const numberAndUnit=weUtils.getNumericAndUnit(borderWidth);this.$el.find('.link-custom-color-border input').val(numberAndUnit?numberAndUnit[0]:"1");let borderStyle=this.linkEl.style['border-style'];if(!borderStyle||borderStyle==='none'){borderStyle='solid';}
const $activeBorderStyleButton=this.$el.find(`.link-custom-color-border [name="link_border_style"] we-button[data-value="${borderStyle}"]`);$activeBorderStyleButton.addClass('active');$activeBorderStyleButton.siblings('we-button').removeClass("active");const $activeBorderStyleToggler=$activeBorderStyleButton.closest('we-select').find('we-toggler');$activeBorderStyleToggler.empty();$activeBorderStyleButton.find('div').clone().appendTo($activeBorderStyleToggler);}}
_updateColorpicker(cssProperty){const prefix=this.PREFIXES[cssProperty];const colorNames=this.colorpickers[cssProperty].colorNames;let color=this.linkEl.style[cssProperty];const colorClasses=prefix?weUtils.computeColorClasses(colorNames,prefix):[];const colorClass=prefix&&weUtils.getColorClass(this.linkEl,colorNames,prefix);const isColorClass=colorClasses.includes(colorClass);if(isColorClass){color=colorClass;}else if(cssProperty==='background-color'){const gradientColor=this.linkEl.style['background-image'];if(weUtils.isColorGradient(gradientColor)){color=gradientColor;}}
this.customColors[cssProperty]=color;if(cssProperty==='border-color'){const colorName=colorNames[normalizeCSSColor(color)];this.colorpickerProps[cssProperty].selectedColor=colorName||color;}else{this.colorpickerProps[cssProperty].selectedColor=isColorClass?color.replace(prefix,''):color;}
const $colorPreview=this.$el.find('.link-custom-color-'+(cssProperty==='border-color'?'border':cssProperty==='color'?'text':'fill')+' .o_we_color_preview');const previewClasses=weUtils.computeColorClasses(colorNames,'bg-');$colorPreview[0].classList.remove(...previewClasses);if(isColorClass){$colorPreview.css('background-color',`var(--we-cp-${color.replace(prefix, '')}`);$colorPreview.css('background-image','');}else{$colorPreview.css('background-color',weUtils.isColorGradient(color)?'rgba(0, 0, 0, 0)':color);$colorPreview.css('background-image',weUtils.isColorGradient(color)?color:'');}}
_onColorpaletteSetColorNames(cssProperty,colorNames){this.colorpickers[cssProperty].colorNames=colorNames;}
_onColorpaletteColorPicked(cssProperty,params){const selection=window.getSelection();const range=document.createRange();range.selectNodeContents(this.linkEl);selection.removeAllRanges();selection.addRange(range);this.props.wysiwyg.odooEditor.execCommand('applyColor','','color');this.props.wysiwyg.odooEditor.execCommand('applyColor','','backgroundColor');this._colorpaletteApply(cssProperty,params);this.props.wysiwyg.odooEditor.historyStep();this._updateOptionsUI();}
_colorpaletteApply(cssProperty,params){const prefix=this.PREFIXES[cssProperty];let color=params.color;const colorNames=this.colorpickers[cssProperty].colorNames;const colorClasses=prefix?weUtils.computeColorClasses(colorNames,prefix):[];const colorClass=`${prefix}${color}`;if(colorClasses.includes(colorClass)){color=colorClass;}else if(colorNames.includes(color)){color=weUtils.getCSSVariableValue(color);}
this.customColors[cssProperty]=color;this.applyLinkToDom(this._getData());}
_updateLabelInput(){if(this.$el){this.$el[0].querySelector('#o_link_dialog_label_input').value=weUtils.getLinkLabel(this.linkEl);}}
_onClickCheckbox(ev){const $target=$(ev.target);$target.closest('we-button.o_we_checkbox_wrapper').toggleClass('active');if(ev.target.getAttribute("name")==="direct_download"){const el=ev.target.closest("we-button.o_we_checkbox_wrapper");const urlInputEl=this.$el[0].querySelector("#o_link_dialog_url_input");let href=urlInputEl.value.replace("&download=true","");if(el.classList.contains("active")){href+="&download=true";this.state.directDownload=true;}
else{this.state.directDownload=false;}
urlInputEl.value=href;this.state.url=href;}
this._adaptPreview();}
_onPickSelectOption(ev){const $target=$(ev.target);if($target.closest('[name="link_border_style"]').length){return;}
const $select=$target.closest('we-select');$select.find('we-selection-items we-button').toggleClass('active',false);this._setSelectOption($target,true);this._updateOptionsUI();this._adaptPreview();this.props.wysiwyg.snippetsMenuBus.trigger("ACTIVATE_SNIPPET",{$snippet:$(this.linkEl),onSuccess:()=>{},});}
_onChangeCustomBorderWidth(ev){const value=ev.target.value;if(parseInt(value)>=0){this.$link.css('border-width',value+'px');}}
_onKeyPressCustomBorderWidth(ev){if(ev.key==="Enter"){this._onChangeCustomBorderWidth(ev);}}
_onBorderStyleSelectOption(ev){const value=ev.currentTarget.dataset.value;if(value){this.$link.css('border-style',value);const $target=$(ev.currentTarget);const $activeBorderStyleToggler=$target.closest('we-select').find('we-toggler');$activeBorderStyleToggler.empty();$target.find('div').clone().appendTo($activeBorderStyleToggler);$target.addClass('active');$target.siblings('we-button').removeClass("active");this.props.wysiwyg.odooEditor.historyStep();}}
_checkDocumentState(){this.state.isDocument=false;this.state.directDownload=true;const url=this.state.url;if(url&&url.startsWith("/web/content/")){this.state.isDocument=!this.isLastAttachmentUrl;this.state.directDownload=url.includes("&download=true");}}
__onURLInput(){super.__onURLInput(...arguments);this.props.wysiwyg.odooEditor.historyPauseSteps('_onURLInput');this._checkDocumentState();this._syncContent();this._adaptPreview();this.props.wysiwyg.odooEditor.historyUnpauseSteps('_onURLInput');}
_onLabelInput(ev){const data=this._getData();if(!data){return;}
this._observer.disconnect();this._updateLinkContent(this.$link,data,{force:true});this._observer.observe(this.props.link,this._observerOptions);}
_syncContent(){const previousUrl=this.linkEl.getAttribute('href');if(!previousUrl){return;}
const protocolLessPrevUrl=previousUrl.replace(/^https?:\/\/|^mailto:/i,'');const content=weUtils.getLinkLabel(this.linkEl);if((content===previousUrl||content===protocolLessPrevUrl)&&this.linkComponentWrapperRef.el){const newUrl=this.linkComponentWrapperRef.el.querySelector('input[name="url"]').value;const protocolLessNewUrl=newUrl.replace(/^https?:\/\/|^mailto:/i,'')
const newContent=content.replace(protocolLessPrevUrl,protocolLessNewUrl);this.linkComponentWrapperRef.el.querySelector('#o_link_dialog_label_input').value=newContent;this._onLabelInput();}}}
__exports.shouldUnlink=shouldUnlink;function shouldUnlink(link,colorCombinationClass){return(!link.getAttribute("href")&&!link.matches(".oe_unremovable"))&&!colorCombinationClass&&!isButton(link);}
return __exports;});;

/* /web_editor/static/src/js/editor/toolbar.js */
odoo.define('@web_editor/js/editor/toolbar',['@web/core/ui/ui_service','@web_editor/js/wysiwyg/widgets/color_palette','@odoo/owl','@web/core/utils/hooks','@web/core/user','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{utils:uiUtils}=require("@web/core/ui/ui_service");const{ColorPalette}=require("@web_editor/js/wysiwyg/widgets/color_palette");const{Component,onMounted,onWillStart,useRef,useState,}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");const{user}=require("@web/core/user");const{loadLanguages}=require("@web/core/l10n/translation");const Toolbar=__exports.Toolbar=class Toolbar extends Component{static template='web_editor.toolbar';static components={ColorPalette};static props={dropDirection:{type:String,optional:true},showChecklist:{type:Boolean,optional:true},showColors:{type:Boolean,optional:true},showFontSize:{type:Boolean,optional:true},useFontSizeInput:{type:Boolean,optional:true},showHistory:{type:Boolean,optional:true},showRemoveFormat:{type:Boolean,optional:true},showStyle:{type:Boolean,optional:true},showJustify:{type:Boolean,optional:true},showList:{type:Boolean,optional:true},showLink:{type:Boolean,optional:true},showImageShape:{type:Boolean,optional:true},showImagePadding:{type:Boolean,optional:true},showImageWidth:{type:Boolean,optional:true},showImageEdit:{type:Boolean,optional:true},showHeading1:{type:Boolean,optional:true},showHeading2:{type:Boolean,optional:true},showHeading3:{type:Boolean,optional:true},showHeading4:{type:Boolean,optional:true},showHeading5:{type:Boolean,optional:true},showHeading6:{type:Boolean,optional:true},onColorpaletteDropdownShow:{type:Function,optional:true},onColorpaletteDropdownHide:{type:Function,optional:true},textColorPaletteProps:{type:Object},backgroundColorPaletteProps:{type:Object},slots:{type:Object,optional:true},};static defaultProps={dropDirection:'dropdown',showChecklist:true,showColors:true,showFontSize:true,useFontSizeInput:false,showHistory:false,showRemoveFormat:true,showStyle:true,showJustify:true,showList:true,showLink:true,showImageShape:true,showImagePadding:true,showImageWidth:true,showImageEdit:true,showHeading1:true,showHeading2:true,showHeading3:true,showHeading4:true,showHeading5:true,showHeading6:true,onColorpaletteDropdownShow:()=>{},onColorpaletteDropdownHide:()=>{},};colorDropdownRef={text:useRef("textColorpickerDropdown"),background:useRef("backgroundColorpaletteDropdown"),}
setup(){this.orm=useService("orm");this.state=useState({languages:[]});onMounted(()=>{for(const[colorType,ref]of Object.entries(this.colorDropdownRef)){const dropdown=ref.el;if(!dropdown)continue;const $=dropdown.ownerDocument.defaultView.$;const $dropdown=$(dropdown);$dropdown.on('show.bs.dropdown',()=>{this.props.onColorpaletteDropdownShow(colorType);});$dropdown.on('hide.bs.dropdown',(ev)=>this.props.onColorpaletteDropdownHide(ev));}});onWillStart(()=>{this.state.isPublicUser=!user.userId;if(!this.state.isPublicUser){loadLanguages(this.orm).then((res)=>{this.state.languages=res;});}});}
isSmall(){return uiUtils.isSmall();}}
return __exports;});;

/* /web_editor/static/src/js/editor/add_snippet_dialog.js */
odoo.define('@web_editor/js/editor/add_snippet_dialog',['@web/core/browser/feature_detection','@web/core/dialog/dialog','@web/core/l10n/translation','@web/core/utils/hooks','@odoo/owl','@web/core/browser/cookie','@web/core/l10n/localization'],function(require){'use strict';let __exports={};const{isBrowserFirefox}=require("@web/core/browser/feature_detection");const{Dialog}=require("@web/core/dialog/dialog");const{_t}=require("@web/core/l10n/translation");const{useService}=require("@web/core/utils/hooks");const{useRef,useState,useEffect,Component,onMounted,}=require("@odoo/owl");const{cookie}=require("@web/core/browser/cookie");const{localization}=require("@web/core/l10n/localization");const RenameCustomSnippetDialog=__exports.RenameCustomSnippetDialog=class RenameCustomSnippetDialog extends Component{static template="web_editor.RenameCustomSnippetDialog";static props={close:Function,currentName:String,confirm:Function,};static components={Dialog,};setup(){this.renameInputRef=useRef("renameInput");}
onClickConfirm(){this.props.confirm(this.renameInputRef.el.value);this.props.close();}
onClickDiscard(){this.props.close();}}
const AddSnippetDialog=__exports.AddSnippetDialog=class AddSnippetDialog extends Component{static template="web_editor.AddSnippetDialog";static props={close:Function,snippets:Object,groupSelected:String,optionsSnippets:String,frontendDirection:String,installModule:Function,addSnippet:Function,deleteCustomSnippet:Function,renameCustomSnippet:Function,};static components={Dialog,RenameCustomSnippetDialog,};setup(){this.iframeRef=useRef("iframe");this.snippetGroups=this.getSnippetGroups();this.dialog=useService("dialog");this.state=useState({groupSelected:[],search:"",});onMounted(async()=>{const isFirefox=isBrowserFirefox();if(isFirefox){await new Promise(resolve=>{this.iframeDocument.body.onload=resolve;});}
this.iframeDocument.documentElement.classList.add("o_add_snippets_preview");this.iframeDocument.body.style.setProperty("direction",localization.direction);this.insertColorScheme();await this.insertStyle().then(()=>{this.iframeRef.el.classList.add("show");});this.state.groupSelected=this.props.groupSelected;});this.currentInsertSnippetsCallID=0;useEffect(()=>{this.insertSnippets();},()=>[this.state.groupSelected,this.state.search,[...this.props.snippets]]);}
get iframeDocument(){return this.iframeRef.el?.contentDocument;}
getSnippetGroups(){return[...this.props.snippets.values()].filter(snippet=>!snippet.excluded&&(snippet.category.id==="snippet_groups")&&snippet.snippetGroup).map(snippet=>({displayName:snippet.displayName,name:snippet.snippetGroup,selected:snippet.snippetGroup===this.props.groupSelected,}));}
async insertSnippets(){const insertSnippetsCallID=++this.currentInsertSnippetsCallID;let snippetsToDisplay=[...this.props.snippets.values()].filter(snippet=>{return!snippet.excluded&&snippet.group;});if(this.state.search){const search=this.state.search;const selectorSearch=/^s_[\w-]*$/.test(search)&&`[class^="${search}"], [class*=" ${search}"]`;const lowerCasedSearch=search.toLowerCase();const strMatches=str=>str.toLowerCase().includes(lowerCasedSearch);snippetsToDisplay=snippetsToDisplay.filter(snippet=>{return selectorSearch&&(snippet.baseBody.matches(selectorSearch)||snippet.baseBody.querySelector(selectorSearch))||strMatches(snippet.category.text)||strMatches(snippet.displayName)||strMatches(snippet.data.oeKeywords||'');});if(selectorSearch){snippetsToDisplay.sort((snippetA,snippetB)=>{if(snippetA.data.snippet===search){return-1;}
if(snippetB.data.snippet===search){return 1;}
const aHasExactClassOnRoot=snippetA.baseBody.classList.contains(search);const bHasExactClassOnRoot=snippetB.baseBody.classList.contains(search);if(aHasExactClassOnRoot!==bHasExactClassOnRoot){return aHasExactClassOnRoot?-1:1;}
const aHasPartialClassOnRoot=snippetA.baseBody.matches(selectorSearch);const bHasPartialClassOnRoot=snippetB.baseBody.matches(selectorSearch);if(aHasPartialClassOnRoot!==bHasPartialClassOnRoot){return aHasPartialClassOnRoot?-1:1;}
return 0;});}}else{snippetsToDisplay=snippetsToDisplay.filter(snippet=>{return snippet.group===this.state.groupSelected;});}
this.iframeDocument.body.scrollTop=0;const rowEl=document.createElement("div");rowEl.classList.add("row","g-0","o_snippets_preview_row");rowEl.style.setProperty("direction",this.props.frontendDirection);const leftColEl=document.createElement("div");leftColEl.classList.add("col-lg-6");rowEl.appendChild(leftColEl);const rightColEl=document.createElement("div");rightColEl.classList.add("col-lg-6");rowEl.appendChild(rightColEl);this.iframeDocument.body.appendChild(rowEl);const BIG_CHUNK_SIZE=6;const SMALL_CHUNK_SIZE=3;const chunks=[snippetsToDisplay.splice(0,BIG_CHUNK_SIZE)];while(snippetsToDisplay.length){chunks.push(snippetsToDisplay.splice(0,SMALL_CHUNK_SIZE));}
let leftColSize=0;let rightColSize=0;for(const chunk of chunks){const itemEls=await Promise.all(chunk.map(snippet=>{let containerEl=null;let clonedSnippetEl;let originalSnippet;if(snippet.isCustom){originalSnippet=[...this.props.snippets.values()].filter(snip=>!snip.isCustom&&snip.name===snippet.name)[0];if(originalSnippet.baseBody.querySelector(".s_dialog_preview")||originalSnippet.imagePreview||originalSnippet.name==="s_countdown"){clonedSnippetEl=originalSnippet.baseBody.cloneNode(true);}}
if(!clonedSnippetEl){clonedSnippetEl=snippet.baseBody.cloneNode(true);}
clonedSnippetEl.classList.remove("oe_snippet_body");const snippetPreviewWrapEl=document.createElement("div");snippetPreviewWrapEl.classList.add("o_snippet_preview_wrap","position-relative");snippetPreviewWrapEl.dataset.snippetId=snippet.name;snippetPreviewWrapEl.dataset.snippetKey=snippet.key;snippetPreviewWrapEl.appendChild(clonedSnippetEl);this.__onSnippetPreviewClick=this._onSnippetPreviewClick.bind(this);snippetPreviewWrapEl.addEventListener("click",this.__onSnippetPreviewClick);containerEl=snippetPreviewWrapEl;if(snippet.installable){snippetPreviewWrapEl.classList.add("o_snippet_preview_install");clonedSnippetEl.dataset.moduleId=snippet.moduleId;clonedSnippetEl.dataset.moduleDisplayName=snippet.moduleDisplayName;const installBtnEl=document.createElement("button");installBtnEl.classList.add("o_snippet_preview_install_btn","btn","text-white","rounded-1","mx-auto","p-2","bottom-50");installBtnEl.innerText=_t("Install %s",snippet.displayName);snippetPreviewWrapEl.appendChild(installBtnEl);}
const imagePreview=snippet.imagePreview||originalSnippet?.imagePreview;if(imagePreview){clonedSnippetEl.style.setProperty("padding","0","important");const previewImgDivEl=document.createElement("div");previewImgDivEl.classList.add("s_dialog_preview","s_dialog_preview_image");const previewImgEl=document.createElement("img");previewImgEl.src=imagePreview;previewImgDivEl.appendChild(previewImgEl);clonedSnippetEl.innerHTML="";clonedSnippetEl.appendChild(previewImgDivEl);}
clonedSnippetEl.classList.remove("o_dynamic_empty");if(snippet.isCustom){const editCustomSnippetEl=document.createElement("div");editCustomSnippetEl.classList.add("d-grid","mt-2","mx-5","gap-2","d-md-flex","justify-content-md-end","o_custom_snippet_edit");const spanEl=document.createElement("span");spanEl.classList.add("w-100");spanEl.textContent=snippet.displayName;const renameBtnEl=document.createElement("button");renameBtnEl.classList.add("btn","fa","fa-pencil","me-md-2");renameBtnEl.type="button";const removeBtnEl=document.createElement("button");removeBtnEl.classList.add("btn","fa","fa-trash");removeBtnEl.type="button";editCustomSnippetEl.appendChild(spanEl);editCustomSnippetEl.appendChild(renameBtnEl);editCustomSnippetEl.appendChild(removeBtnEl);const customSnippetWrapEl=document.createElement("div");customSnippetWrapEl.classList.add("o_custom_snippet_wrap");customSnippetWrapEl.appendChild(snippetPreviewWrapEl);customSnippetWrapEl.appendChild(editCustomSnippetEl);containerEl=customSnippetWrapEl;this.__onRenameCustomBtnClick=this._onRenameCustomBtnClick.bind(this);renameBtnEl.addEventListener("click",this.__onRenameCustomBtnClick);this.__onDeleteCustomBtnClick=this._onDeleteCustomBtnClick.bind(this);removeBtnEl.addEventListener("click",this.__onDeleteCustomBtnClick);}
containerEl.classList.add("invisible");leftColEl.appendChild(containerEl);const imageEls=snippetPreviewWrapEl.querySelectorAll("img");return Promise.all(Array.from(imageEls).map(imgEl=>{imgEl.setAttribute("loading","eager");return new Promise(resolve=>{if(imgEl.complete){resolve();}else{imgEl.onload=()=>resolve();imgEl.onerror=()=>resolve();}});})).then(()=>containerEl);}));if(this.currentInsertSnippetsCallID!==insertSnippetsCallID){return;}
const leftColElements=[];const rightColElements=[];for(const itemEl of itemEls){const size=itemEl.getBoundingClientRect().height;if(leftColSize<=rightColSize){leftColElements.push(itemEl);leftColSize+=size;}else{rightColElements.push(itemEl);rightColSize+=size;}}
for(const[colEl,colItemEls]of[[leftColEl,leftColElements],[rightColEl,rightColElements],]){for(const el of colItemEls){colEl.appendChild(el);el.classList.remove("invisible");}}
while(rowEl.previousSibling){rowEl.previousSibling.remove();}}
this._updateSnippetContent(this.iframeDocument);}
async insertStyle(){const pagePreviewIframeEl=document.querySelector(".o_iframe");const cssLinkEls=pagePreviewIframeEl.contentDocument.head.querySelectorAll("link[type='text/css']");const linkPromises=Array.from(cssLinkEls).map((cssLinkEl)=>{return new Promise((resolve)=>{const clonedLinkEl=cssLinkEl.cloneNode(true);this.iframeDocument.head.appendChild(clonedLinkEl);clonedLinkEl.onload=()=>resolve();});});const mainEl=pagePreviewIframeEl.contentDocument.body.querySelector("#wrapwrap > main");const mainBgColor=mainEl&&getComputedStyle(mainEl).backgroundColor;if(mainBgColor!=="rgba(0, 0, 0, 0)"){this.iframeDocument.body.style.setProperty("--body-bg",mainBgColor);}
await Promise.all(linkPromises);}
insertColorScheme(){const colorScheme=cookie.get("color_scheme")||"light";const metaElement=document.createElement("meta");const iframeDocument=this.iframeRef.el.contentDocument;metaElement.setAttribute("name","color-scheme");metaElement.content=colorScheme;iframeDocument.head.appendChild(metaElement);iframeDocument.body.parentElement.classList.add("o_add_snippets_preview--"+colorScheme);}
_onSnippetPreviewClick(ev){let selectedSnippetEl=ev.currentTarget.querySelector("[data-name]");const snippetKey=parseInt(ev.currentTarget.dataset.snippetKey);const moduleId=parseInt(selectedSnippetEl?.dataset.moduleId);if(moduleId){this.props.installModule(moduleId,selectedSnippetEl.dataset.moduleDisplayName);}else{selectedSnippetEl=this.props.snippets.get(snippetKey);selectedSnippetEl=selectedSnippetEl.baseBody.cloneNode(true);selectedSnippetEl.classList.remove("oe_snippet_body");const snippetDialogPreviews=selectedSnippetEl.querySelectorAll(".s_dialog_preview");for(const snippetDialogPreview of snippetDialogPreviews){snippetDialogPreview.remove();}
this.props.addSnippet(selectedSnippetEl);this._updateSnippetContent(selectedSnippetEl);this.props.close();}}
_onRenameCustomBtnClick(ev){const snippetKey=ev.currentTarget.closest(".o_custom_snippet_wrap").querySelector("[data-snippet-key]").dataset.snippetKey;const snippet=this.props.snippets.get(parseInt(snippetKey));this.dialog.add(RenameCustomSnippetDialog,{currentName:snippet.displayName,confirm:async(newName)=>{this.props.renameCustomSnippet(parseInt(snippetKey),newName);},});}
_onDeleteCustomBtnClick(ev){const snippetKey=ev.currentTarget.closest(".o_custom_snippet_wrap").querySelector("[data-snippet-key]").dataset.snippetKey;Promise.resolve(this.props.deleteCustomSnippet(parseInt(snippetKey))).then(()=>{const snippetsData=[...this.props.snippets.values()];const stillHasCustom=!!snippetsData.find(snippet=>snippet.group==="custom");if(!stillHasCustom){this.snippetGroups=this.snippetGroups.filter(group=>group.name!=="custom");if(this.state.groupSelected==="custom"){this.state.groupSelected=this.snippetGroups[0].name;}}});}
_updateSnippetContent(snippetEl){}}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/wysiwyg_jquery_extention.js */
odoo.define('@web_editor/js/wysiwyg/wysiwyg_jquery_extention',[],function(require){'use strict';let __exports={};$.extend($.expr[':'],{o_editable:function(node,i,m){while(node){if(node.className&&typeof node.className==="string"){if(node.className.indexOf('o_not_editable')!==-1){return false;}
if(node.className.indexOf('o_editable')!==-1){return true;}}
node=node.parentNode;}
return false;},});function firstChild(node){while(node.firstChild){node=node.firstChild;}
return node;}
function lastChild(node){while(node.lastChild){node=node.lastChild;}
return node;}
function nodeLength(node){if(node.nodeType===Node.TEXT_NODE){return node.nodeValue.length;}else{return node.childNodes.length;}}
$.fn.extend({focusIn:function(){if(this.length){const selection=this[0].ownerDocument.getSelection();selection.removeAllRanges();const range=new Range();const node=firstChild(this[0]);range.setStart(node,0);range.setEnd(node,0);selection.addRange(range);}
return this;},focusInEnd:function(){if(this.length){const selection=this[0].ownerDocument.getSelection();selection.removeAllRanges();const range=new Range();const node=lastChild(this[0]);const length=nodeLength(node);range.setStart(node,length);range.setEnd(node,length);selection.addRange(range);}
return this;},selectContent:function(){if(this.length&&!this[0].hasChildNodes()){return this.selectElement();}
if(this.length){const selection=this[0].ownerDocument.getSelection();selection.removeAllRanges();const range=new Range();range.setStart(this[0].firstChild,0);range.setEnd(this[0].lastChild,this[0].lastChild.length);selection.addRange(range);}
return this;},selectElement:function(){if(this.length){const selection=this[0].ownerDocument.getSelection();selection.removeAllRanges();const element=this[0];const parent=element.parentNode;const offsetStart=Array.from(parent.childNodes).indexOf(element);const range=new Range();range.setStart(parent,offsetStart);range.setEnd(parent,offsetStart+1);selection.addRange(range);}
return this;},});return __exports;});;

/* /web_editor/static/src/js/wysiwyg/wysiwyg.js */
odoo.define('@web_editor/js/wysiwyg/wysiwyg',['@web/session','@web/core/user','@web_editor/components/media_dialog/media_dialog','@web_editor/components/media_dialog/video_selector','@web/core/browser/browser','@web/core/utils/hooks','@web_editor/js/editor/custom_colors','@web/core/l10n/localization','@web_editor/js/editor/odoo-editor/src/OdooEditor','@web_editor/js/editor/toolbar','@web_editor/js/wysiwyg/widgets/link_popover_widget','@web_editor/js/wysiwyg/widgets/alt_dialog','@web_editor/js/wysiwyg/widgets/chatgpt_prompt_dialog','@web_editor/js/wysiwyg/widgets/chatgpt_alternatives_dialog','@web_editor/js/wysiwyg/widgets/chatgpt_translate_dialog','@web_editor/js/wysiwyg/widgets/image_crop','@web_editor/js/common/wysiwyg_utils','@web_editor/js/common/utils','@web_editor/js/editor/odoo-editor/src/utils/utils','@web_editor/js/wysiwyg/PeerToPeer','@web/core/network/rpc','@web/core/utils/functions','@web/core/utils/arrays','@web/core/utils/timing','@web/core/registry','@web/core/file_viewer/file_viewer','@web/core/browser/feature_detection','@web/core/utils/concurrency','@web/core/confirmation_dialog/confirmation_dialog','@web/core/l10n/translation','@web_editor/js/wysiwyg/conflict_dialog','@web_editor/js/wysiwyg/widgets/link','@web_editor/js/wysiwyg/widgets/link_tools','@web_editor/js/wysiwyg/widgets/link_dialog','@odoo/owl','@web/core/utils/colors','@web/core/emoji_picker/emoji_picker','@web/core/tooltip/tooltip'],function(require){'use strict';let __exports={};const{session}=require("@web/session");const{user}=require("@web/core/user");const{MediaDialog}=require("@web_editor/components/media_dialog/media_dialog");const{VideoSelector}=require("@web_editor/components/media_dialog/video_selector");const{browser}=require("@web/core/browser/browser");const{useService}=require("@web/core/utils/hooks");const customColors=require("@web_editor/js/editor/custom_colors")[Symbol.for("default")];const{localization}=require("@web/core/l10n/localization");const OdooEditorLib=require("@web_editor/js/editor/odoo-editor/src/OdooEditor");const{Toolbar}=require("@web_editor/js/editor/toolbar");const{LinkPopoverWidget}=require('@web_editor/js/wysiwyg/widgets/link_popover_widget');const{AltDialog}=require('@web_editor/js/wysiwyg/widgets/alt_dialog');const{ChatGPTPromptDialog}=require('@web_editor/js/wysiwyg/widgets/chatgpt_prompt_dialog');const{ChatGPTAlternativesDialog}=require('@web_editor/js/wysiwyg/widgets/chatgpt_alternatives_dialog');const{ChatGPTTranslateDialog}=require("@web_editor/js/wysiwyg/widgets/chatgpt_translate_dialog");const{ImageCrop}=require('@web_editor/js/wysiwyg/widgets/image_crop');const wysiwygUtils=require("@web_editor/js/common/wysiwyg_utils");const weUtils=require("@web_editor/js/common/utils")[Symbol.for("default")];const{isIconElement,isSelectionInSelectors,peek}=require('@web_editor/js/editor/odoo-editor/src/utils/utils');const{PeerToPeer,RequestError}=require("@web_editor/js/wysiwyg/PeerToPeer");const{rpc}=require("@web/core/network/rpc");const{uniqueId}=require("@web/core/utils/functions");const{groupBy}=require("@web/core/utils/arrays");const{debounce}=require("@web/core/utils/timing");const{registry}=require("@web/core/registry");const{FileViewer}=require("@web/core/file_viewer/file_viewer");const{isMobileOS}=require("@web/core/browser/feature_detection");const{Deferred,Mutex}=require("@web/core/utils/concurrency");const{AlertDialog,ConfirmationDialog}=require("@web/core/confirmation_dialog/confirmation_dialog");const{_t}=require("@web/core/l10n/translation");const{ConflictDialog}=require("@web_editor/js/wysiwyg/conflict_dialog");const{getOrCreateLink}=require("@web_editor/js/wysiwyg/widgets/link");const{shouldUnlink}=require('@web_editor/js/wysiwyg/widgets/link_tools');const{LinkDialog}=require("@web_editor/js/wysiwyg/widgets/link_dialog");const{Component,EventBus,useRef,useState,onWillStart,onMounted,onWillDestroy,onWillUpdateProps,markup,status,htmlEscape,}=require("@odoo/owl");const{isCSSColor}=require('@web/core/utils/colors');const{EmojiPicker}=require('@web/core/emoji_picker/emoji_picker');const{Tooltip}=require("@web/core/tooltip/tooltip");const OdooEditor=OdooEditorLib.OdooEditor;const getDeepRange=OdooEditorLib.getDeepRange;const getInSelection=OdooEditorLib.getInSelection;const isProtected=OdooEditorLib.isProtected;const rgbToHex=OdooEditorLib.rgbToHex;const preserveCursor=OdooEditorLib.preserveCursor;const closestElement=OdooEditorLib.closestElement;const setSelection=OdooEditorLib.setSelection;const endPos=OdooEditorLib.endPos;const hasValidSelection=OdooEditorLib.hasValidSelection;const parseHTML=OdooEditorLib.parseHTML;const closestBlock=OdooEditorLib.closestBlock;const getRangePosition=OdooEditorLib.getRangePosition;const childNodeIndex=OdooEditorLib.childNodeIndex;const fillEmpty=OdooEditorLib.fillEmpty;const isVisible=OdooEditorLib.isVisible;const getSelectedNodes=OdooEditorLib.getSelectedNodes;const getDeepestPosition=OdooEditorLib.getDeepestPosition;const paragraphRelatedElements=OdooEditorLib.paragraphRelatedElements;function getJqueryFromDocument(doc){if(doc.defaultView&&doc.defaultView.$){return doc.defaultView.$;}else{const _jquery=window.$;return(...args)=>{if(args.length<=2&&typeof args[0]==="string"){return _jquery(args[0],args[1]||doc);}else{return _jquery(...args)}}}}
var id=0;const basicMediaSelector='img, .fa, .o_image, .media_iframe_video';const mediaSelector=basicMediaSelector.split(',').map(s=>`${s}:not([data-oe-xpath])`).join(',');const CONSIDER_OFFLINE_TIME=1000;const CHECK_OFFLINE_TIME=1000;const PTP_CLIENT_DISCONNECTED_STATES=['failed','closed','disconnected',];const PTP_MAX_RECOVERY_TIME=500;const REQUEST_ERROR=Symbol('REQUEST_ERROR');let ICE_SERVERS=null;let fileViewerId=0;const Wysiwyg=__exports.Wysiwyg=class Wysiwyg extends Component{static template='web_editor.Wysiwyg';static components={MediaDialog,VideoSelector,Toolbar,ImageCrop};static props={options:Object,startWysiwyg:{type:Function,optional:true},editingValue:{type:String,optional:true},};elRef=useRef("el");toolbarRef=useRef("toolbar");imageCropRef=useRef("imageCrop");colorPalettesProps={text:useState({resetTabCount:0,}),background:useState({resetTabCount:0,}),}
imageCropProps=useState({showCount:0,media:undefined,mimetype:undefined,});state=useState({linkToolProps:false,showToolbar:true,toolbarProps:{},showSnippetsMenu:false,snippetsMenuFolded:false,});setup(){this.orm=useService('orm');this.getColorPickerTemplateService=useService('get_color_picker_template');this.notification=useService("notification");this.popover=useService("popover");this.busService=this.env.services.bus_service;this.user=user;this.snippetsMenuContainer=useRef("snippets-menu-container");this.mutex=new Mutex();this.snippetsMenuBus=new EventBus();const getColorPickedHandler=(colorType)=>{return(params)=>{if(this.hadNonCollapsedSelectionBeforeColorpicker){this.odooEditor.historyResetLatestComputedSelection(true);}
this.odooEditor.historyUnstash();this._processAndApplyColor(colorType,params.color);if(hasValidSelection(this.odooEditor.editable)){this.odooEditor.deselectTable();}
this._updateEditorUI(this.lastMediaClicked&&{target:this.lastMediaClicked});};}
const getColorHoverHandler=(colorType)=>{return(props)=>{if(this.hadNonCollapsedSelectionBeforeColorpicker){this.odooEditor.historyResetLatestComputedSelection(true);}
this.odooEditor.historyPauseSteps();try{this._processAndApplyColor(colorType,props.color,true);this.odooEditor._computeHistorySelection();}finally{this.odooEditor.historyUnpauseSteps();}}};const colorPaletteCommonOptions={excluded:['transparent_grayscale'],document:this.props.options.document,selectedTab:'theme-colors',withGradients:true,onColorLeave:()=>{this.odooEditor.withoutRollback(()=>this.odooEditor.historyRevertCurrentStep());this.odooEditor._computeHistorySelection();},onInputEnter:(ev)=>{const pickergroup=ev.target.closest('.colorpicker-group');$(pickergroup.querySelector('.dropdown-toggle')).dropdown('hide');},getTemplate:this.getColorpickerTemplate.bind(this),getEditableCustomColors:()=>{if(!this.$editable){return[];}
return[...this.$editable[0].querySelectorAll('[style*="color"]')].map(el=>{return[el.style.color,el.style.backgroundColor];}).flat();},};onWillStart(()=>{this.init();Object.assign(this.colorPalettesProps.text,colorPaletteCommonOptions,{document:this.options.document,onColorPicked:getColorPickedHandler('text'),onCustomColorPicked:getColorPickedHandler('text'),onColorHover:getColorHoverHandler('text'),onColorpaletteTabChange:this.getColorPaletteTabChangeHandler('text').bind(this),});Object.assign(this.colorPalettesProps.background,colorPaletteCommonOptions,{document:this.options.document,onColorPicked:getColorPickedHandler('background'),onCustomColorPicked:getColorPickedHandler('background'),onColorHover:getColorHoverHandler('background'),onColorpaletteTabChange:this.getColorPaletteTabChangeHandler('background').bind(this),});this._setToolbarProps();});onMounted(async()=>{this.el=this.elRef.el
this.$el=$(this.elRef.el);this._renderElement();if(this.props.startWysiwyg){await this.props.startWysiwyg(this);}else{await this.startEdition();}});onWillDestroy(()=>{this.destroy();});onWillUpdateProps((newProps)=>{this.options=this._getEditorOptions(newProps.options);this._setToolbarProps();const lastValue=String(this.props.options.value||'');const lastRecordInfo=this.props.options.recordInfo;const lastCollaborationChannel=this.props.options.collaborationChannel;const newValue=String(newProps.options.value||'');const newRecordInfo=newProps.options.recordInfo;const newCollaborationChannel=newProps.options.collaborationChannel;const isDifferentRecord=JSON.stringify(lastRecordInfo)!==JSON.stringify(newRecordInfo)||JSON.stringify(lastCollaborationChannel)!==JSON.stringify(newCollaborationChannel);const isDiscardedRecord=!isDifferentRecord&&newProps.options.record&&!newProps.options.record.dirty;if((stripHistoryIds(newValue)!==stripHistoryIds(newProps.editingValue)&&stripHistoryIds(lastValue)!==stripHistoryIds(newValue))||isDifferentRecord)
{if(isDifferentRecord||isDiscardedRecord){this.resetEditor(newValue,newProps.options);}else{this.setValue(newValue);}
this.env.onWysiwygReset&&this.env.onWysiwygReset();}});}
defaultOptions={lang:'odoo',colors:customColors,recordInfo:{context:{}},document:document,allowCommandVideo:true,allowCommandImage:true,allowCommandLink:true,insertParagraphAfterColumns:true,onHistoryResetFromSteps:()=>{},autostart:true,dropImageAsAttachment:true,editorPlugins:[],useResponsiveFontSizes:true,showResponsiveFontSizesBadges:false,showExtendedTextStylesOptions:false,getCSSVariableValue:weUtils.getCSSVariableValue,convertNumericToUnit:weUtils.convertNumericToUnit,};init(){this.id=++id;this.options=this._getEditorOptions(this.props.options);this.saving_mutex=new Mutex();this.colorpickers={};this._onDocumentMousedown=this._onDocumentMousedown.bind(this);this._onBlur=this._onBlur.bind(this);this._onScroll=this._onScroll.bind(this);this.customizableLinksSelector='a'
+':not([data-bs-toggle="tab"])'
+':not([data-bs-toggle="collapse"])'
+':not([data-bs-toggle="dropdown"])'
+':not(.dropdown-item)';this._isOnline=true;this._signalOnline=this._signalOnline.bind(this);this.tooltipTimeouts=[];Wysiwyg.activeWysiwygs.add(this);this._joinPeerToPeer=this._joinPeerToPeer.bind(this);}
async start(){if(this.options.autostart){return this.startEdition();}}
async startEdition(){const self=this;const options=this.options;this.$editable??=this.$el;if(options.value){this.$editable.html(options.value);}
this._isDocumentStale=false;this._lastCollaborationResetId=0;this._historyShareId=Math.floor(Math.random()*Math.pow(2,52)).toString();this._serverLastStepId=options.value&&this._getLastHistoryStepId(options.value);this.$editable.data('wysiwyg',this);this.$editable.data('oe-model',options.recordInfo.res_model);this.$editable.data('oe-id',options.recordInfo.res_id);document.addEventListener('mousedown',this._onDocumentMousedown,true);this._bindOnBlur();this.toolbarEl=this.toolbarRef.el.firstChild;this.imageCropEL=this.imageCropRef.el.firstChild;options.document.body.append(this.imageCropEL);const powerboxOptions=this._getPowerboxOptions();let editorCollaborationOptions;if(this._isCollaborationEnabled(options)){this._currentClientId=this._generateClientId();editorCollaborationOptions=this.setupCollaboration(options.collaborationChannel);if(this.options.collaborativeTrigger==='start'){this._joinPeerToPeer();}else if(this.options.collaborativeTrigger==='focus'){this.$editable[0].addEventListener('focus',this._joinPeerToPeer);}}
const getYoutubeVideoElement=async(url)=>{const parsedUrl=new URL(url);const urlParams=parsedUrl.searchParams;const autoplay=urlParams.get("autoplay")==="1";const loop=urlParams.get("loop")==="1";const hide_controls=urlParams.get("controls")==="0";const hide_fullscreen=urlParams.get("fs")==="0";const{embed_url:src}=await this._serviceRpc("/web_editor/video_url/data",{video_url:url,autoplay,loop,hide_controls,hide_fullscreen,});const[savedVideo]=VideoSelector.createElements([{src}]);savedVideo.classList.add(...VideoSelector.mediaSpecificClasses);return savedVideo;};weUtils.setEditableDocument(this.options.document);const _getContentEditableAreas=this.options.getContentEditableAreas;this.odooEditor=new OdooEditor(this.$editable[0],Object.assign({_t:_t,toolbar:this.toolbarEl,document:this.options.document,autohideToolbar:!!this.options.autohideToolbar,isRootEditable:this.options.isRootEditable,onPostSanitize:this._onPostSanitize.bind(this),placeholder:this.options.placeholder,powerboxFilters:this.options.powerboxFilters||[],showEmptyElementHint:this.options.showEmptyElementHint,controlHistoryFromDocument:this.options.controlHistoryFromDocument,initialHistoryId:this._serverLastStepId,getContentEditableAreas:(...args)=>{const areaEls=_getContentEditableAreas?.(...args)||[];const bannerEls=this.$editable[0].querySelectorAll('.o_editor_banner > div');return[...areaEls,...bannerEls];},getReadOnlyAreas:this.options.getReadOnlyAreas,getUnremovableElements:this.options.getUnremovableElements,defaultLinkAttributes:this.options.userGeneratedContent?{rel:'ugc'}:{},allowCommandVideo:this.options.allowCommandVideo,disableTransform:this.options.disableTransform,allowInlineAtRoot:this.options.allowInlineAtRoot,getYoutubeVideoElement:getYoutubeVideoElement,getContextFromParentRect:options.getContextFromParentRect,getScrollContainerRect:()=>{if(!this.scrollContainer||!this.scrollContainer.getBoundingClientRect){this.scrollContainer=document.querySelector('.o_action_manager')||document.body;}
return this.scrollContainer.getBoundingClientRect();},getPowerboxElement:()=>{const selection=(this.options.document||document).getSelection();if(selection.isCollapsed&&selection.rangeCount){const[deepestNode]=getDeepestPosition(selection.anchorNode,selection.anchorOffset);const elementSelectors=['LI:not([t-field])',"DIV:not([t-field]):not(.o_not_editable):not([contenteditable='false'])",...paragraphRelatedElements.map(tag=>`${tag}:not([t-field])`),];const baseNode=closestElement(deepestNode,elementSelectors.join(', '));const fieldContainer=closestElement(deepestNode,'[data-oe-field]');if(!baseNode||(fieldContainer&&!(fieldContainer.getAttribute('data-oe-field')==='arch'||fieldContainer.getAttribute('data-oe-type')==='html'))){return false;}
return baseNode;}},isHintBlacklisted:node=>{return(node.classList&&node.classList.contains('nav-item'))||(node.hasAttribute&&(node.hasAttribute('data-target')||node.hasAttribute('data-oe-model')));},filterMutationRecords:(records)=>{return records.filter((record)=>{if(record.type==='attributes'&&record.attributeName==='aria-describedby'){const value=(record.oldValue||record.target.getAttribute(record.attributeName));if(value&&['popover','tooltip'].some(type=>value.startsWith(type))){return false;}}
return!((record.target.classList&&record.target.classList.contains('o_header_standard'))||(record.type==='attributes'&&record.attributeName==='data-last-history-steps'));});},preHistoryUndo:()=>{this.destroyLinkTools();},beforeAnyCommand:this._beforeAnyCommand.bind(this),commands:powerboxOptions.commands,categories:powerboxOptions.categories,plugins:options.editorPlugins,direction:options.direction||localization.direction||'ltr',collaborationClientAvatarUrl:this._getCollaborationClientAvatarUrl(),renderingClasses:["o_dirty","o_transform_removal","oe_edited_link","o_menu_loading","o_draggable","o_link_in_selection","o_we_force_no_transition"],dropImageAsAttachment:options.dropImageAsAttachment,foldSnippets:!!options.foldSnippets,useResponsiveFontSizes:options.useResponsiveFontSizes,showResponsiveFontSizesBadges:options.showResponsiveFontSizesBadges,showExtendedTextStylesOptions:options.showExtendedTextStylesOptions,getCSSVariableValue:options.getCSSVariableValue,convertNumericToUnit:options.convertNumericToUnit,autoActivateContentEditable:this.options.autoActivateContentEditable,},editorCollaborationOptions));this.odooEditor.addEventListener('contentChanged',function(){self.$editable.trigger('content_changed');});document.addEventListener("mousemove",this._signalOnline,true);document.addEventListener("keydown",this._signalOnline,true);document.addEventListener("keyup",this._signalOnline,true);if(this.odooEditor.document!==document){this.odooEditor.document.addEventListener("mousemove",this._signalOnline,true);this.odooEditor.document.addEventListener("keydown",this._signalOnline,true);this.odooEditor.document.addEventListener("keyup",this._signalOnline,true);}
this._initialValue=this.getValue();if($('wrapwrap').length){this.multiSelectionTarget=$().getScrollingTarget(this.odooEditor.document);this.multiSelectionTarget.addEventListener('scroll',this.odooEditor.multiselectionRefresh,{passive:true});}
this.$editable.on('click','[data-oe-field][data-oe-sanitize-prevent-edition]',()=>{this.env.services.dialog.add(AlertDialog,{body:_t("Someone with escalated rights previously modified this area, you are therefore not able to modify it yourself."),});});for(const field of this.$editable[0].querySelectorAll('[data-oe-type="text"], [data-oe-type="char"]')){if(!isVisible(field)){fillEmpty(field);}}
this._observeOdooFieldChanges();this.$editable.on('mousedown touchstart','[data-oe-field]',function(){self.odooEditor.observerUnactive();const $field=$(this);if(($field.data('oe-type')==="datetime"||$field.data('oe-type')==="date")){let selector='[data-oe-id="'+$field.data('oe-id')+'"]';selector+='[data-oe-field="'+$field.data('oe-field')+'"]';selector+='[data-oe-model="'+$field.data('oe-model')+'"]';const $linkedFieldNodes=self.$editable.find(selector).addBack(selector);$linkedFieldNodes.addClass('o_editable_date_field_linked');if(!$field.hasClass('o_editable_date_field_format_changed')){$linkedFieldNodes.text($field.data('oe-original-with-format'));$linkedFieldNodes.addClass('o_editable_date_field_format_changed');$linkedFieldNodes.filter('.oe_hide_on_date_edit').addClass('d-none');setTimeout(()=>{Wysiwyg.setRange($linkedFieldNodes.filter(':not(.oe_hide_on_date_edit)')[0]);},0);}}
if($field.attr('contenteditable')!=='false'){if($field.data('oe-type')==="monetary"){$field.attr('contenteditable',false);const $currencyValue=$field.find('.oe_currency_value');$currencyValue.attr('contenteditable',true);$currencyValue.one('mouseup touchend',(e)=>{$currencyValue.selectContent();});}
if($field.data('oe-type')==="image"){$field.attr('contenteditable',false);$field.find('img').attr('contenteditable',$field.data('oe-readonly')!==1);}
if($field.is('[data-oe-many2one-id]')){$field.attr('contenteditable',false);}}
self.odooEditor.observerActive();});this.$editable.on('click','.o_image, .media_iframe_video',e=>e.preventDefault());let closeBannerEmojiPicker;this.$editable.on('click','.o_editor_banner_icon',event=>{if(closeBannerEmojiPicker){closeBannerEmojiPicker();}
closeBannerEmojiPicker=this.popover.add(event.target,EmojiPicker,{onSelect:emoji=>{event.target.innerText=emoji;}},{position:'bottom'});});this.showTooltip=true;this.$editable.on('dblclick',mediaSelector,ev=>{const targetEl=ev.currentTarget;let isEditable=targetEl.isContentEditable||(targetEl.parentElement&&targetEl.parentElement.isContentEditable);if(!isEditable&&targetEl.classList.contains('o_editable_media')){isEditable=weUtils.shouldEditableMediaBeEditable(targetEl);}
if(isEditable){this.showTooltip=false;if(!isProtected(this.odooEditor.document.getSelection().anchorNode)){if(this.options.onDblClickEditableMedia&&targetEl.nodeName==='IMG'&&targetEl.src){this.options.onDblClickEditableMedia(ev);}else{this._onDblClickEditableMedia(ev);}}}});if(options.snippets){this.snippetsMenuComponent=await this.getSnippetsMenuClass(options);await this._insertSnippetMenu();$(this.odooEditor.document.body).addClass('editor_enable');if(localization.direction==="rtl"){this.odooEditor.document.body.setAttribute("is-rtl-backend","true");}
this._onBeforeUnload=(event)=>{if(this.isDirty()){event.returnValue=_t('This document is not saved!');}};window.addEventListener('beforeunload',this._onBeforeUnload);}
if(this.options.getContentEditableAreas){$(this.options.getContentEditableAreas(this.odooEditor)).find('*').off('mousedown mouseup click');}
this._configureToolbar(options);$(this.odooEditor.editable).on('mouseup',this._updateEditorUI.bind(this));$(this.odooEditor.editable).on('keydown',this._updateEditorUI.bind(this));$(this.odooEditor.editable).on('keydown',this._handleShortcuts.bind(this));this._updateEditorUI();this.$editable.on('click.Wysiwyg',(ev)=>{const $target=$(ev.target).closest('a');if($(ev.target).parents('.o_edit_menu_popover').length&&!$target.length){ev.preventDefault();}
if($target.is(this.customizableLinksSelector)&&$target.is('a')&&($target[0].isContentEditable||($target.attr("data-mimetype")&&!$target[0].dataset.mimetype.startsWith("image")))&&!$target.attr('data-oe-model')&&!$target.find('> [data-oe-model]').length&&!$target[0].closest('.o_extra_menu_items')){if(ev.ctrlKey||ev.metaKey){window.open($target[0].href,'_blank');}
this.linkPopover=$target.data('popover-widget-initialized');if(!this.linkPopover){(async()=>{let container;if(this.state.showSnippetsMenu){await this.mutex.exec(()=>null);container=this.options.document.getElementById('oe_manipulators');}
this.linkPopover=LinkPopoverWidget.createFor({target:$target[0],wysiwyg:this,container,notify:(message,params)=>{this.notification.add(message,{type:params.type});},});;$target.data('popover-widget-initialized',this.linkPopover);})();}
$target.closest('[contenteditable=true]').focus();if($target.closest('#wrapwrap').length&&this.state.showSnippetsMenu){this.toggleLinkTools({forceOpen:true,link:$target[0],shouldFocusUrl:ev.detail!==1,});}}});this._onSelectionChange=this._onSelectionChange.bind(this);this.odooEditor.document.addEventListener('selectionchange',this._onSelectionChange);if(!this.state.showSnippetsMenu){this.setCSSVariables(this.toolbarEl);}
this.odooEditor.addEventListener('preObserverActive',()=>{this._onPostSanitize(this.odooEditor.editable);});if(this.options.autohideToolbar){if(this.odooEditor.isMobile){this.odooEditor.editable.before(this.toolbarEl);}else{document.body.append(this.toolbarEl);}}}
setupCollaboration(collaborationChannel){const modelName=collaborationChannel.collaborationModelName;const fieldName=collaborationChannel.collaborationFieldName;const resId=collaborationChannel.collaborationResId;const channelName=`editor_collaboration:${modelName}:${fieldName}:${resId}`;if(!(modelName&&fieldName&&resId)||Wysiwyg.activeCollaborationChannelNames.has(channelName)){return;}
this._collaborationChannelName=channelName;this._historyStepsBuffer=[];Wysiwyg.activeCollaborationChannelNames.add(channelName);const collaborationBusListener=(payload)=>{if(payload.model_name===modelName&&payload.field_name===fieldName&&payload.res_id===resId){if(payload.notificationName==='html_field_write'){this._onServerLastIdUpdate(payload.notificationPayload.last_step_id);}else if(this._ptpJoined){this._peerToPeerLoading.then(()=>this.ptp.handleNotification(payload));}}}
this.busService.subscribe('editor_collaboration',collaborationBusListener);this.busService.addChannel(this._collaborationChannelName);this._collaborationStopBus=()=>{Wysiwyg.activeCollaborationChannelNames.delete(this._collaborationChannelName);this.busService.unsubscribe('editor_collaboration',collaborationBusListener);this.busService.deleteChannel(this._collaborationChannelName);}
this._startCollaborationTime=new Date().getTime();this._checkConnectionChange=()=>{if(!this.ptp){return;}
if(!navigator.onLine){this._signalOffline();}else{this._signalOnline();}};window.addEventListener('online',this._checkConnectionChange);window.addEventListener('offline',this._checkConnectionChange);this._collaborationInterval=setInterval(async()=>{if(this._offlineTimeout||this.preSavePromise||!this.ptp){return;}
const clientsInfos=Object.values(this.ptp.clientsInfos);const couldBeDisconnected=Boolean(clientsInfos.length)&&clientsInfos.every((x)=>PTP_CLIENT_DISCONNECTED_STATES.includes(x.peerConnection&&x.peerConnection.connectionState));if(couldBeDisconnected){this._offlineTimeout=setTimeout(()=>{this._signalOffline();},CONSIDER_OFFLINE_TIME);}},CHECK_OFFLINE_TIME);this._peerToPeerLoading=new Promise(async(resolve)=>{if(!ICE_SERVERS){ICE_SERVERS=await this._serviceRpc('/web_editor/get_ice_servers');}
let iceServers=ICE_SERVERS;if(!iceServers.length){iceServers=[{urls:['stun:stun1.l.google.com:19302','stun:stun2.l.google.com:19302',],}];}
this._iceServers=iceServers;this.ptp=this._getNewPtp();resolve();});const editorCollaborationOptions={collaborationClientId:this._currentClientId,onHistoryStep:(historyStep)=>{if(!this.ptp)return;this.ptp.notifyAllClients('oe_history_step',historyStep,{transport:'rtc'});},onCollaborativeSelectionChange:debounce((collaborativeSelection)=>{if(!this.ptp)return;this.ptp.notifyAllClients('oe_history_set_selection',collaborativeSelection,{transport:'rtc'});},50),onHistoryMissingParentSteps:async({step,fromStepId})=>{if(!this.ptp)return;const missingSteps=await this.requestClient(step.clientId,'get_missing_steps',{fromStepId:fromStepId,toStepId:step.id},{transport:'rtc'});if(missingSteps===REQUEST_ERROR)return;this._processMissingSteps(Array.isArray(missingSteps)?missingSteps.concat(step):missingSteps);},};if(this.options.postProcessExternalSteps){editorCollaborationOptions.postProcessExternalSteps=this.options.postProcessExternalSteps;}
return editorCollaborationOptions;}
setupToolbar(toolbarEl){this.toolbarEl=toolbarEl;this.odooEditor.setupToolbar(toolbarEl);this._configureToolbar(this.options)
this._updateEditorUI();}
destroy(){this.getColorPickerTemplateService=()=>null;Wysiwyg.activeWysiwygs.delete(this);this._stopPeerToPeer();document.removeEventListener("mousemove",this._signalOnline,true);document.removeEventListener("keydown",this._signalOnline,true);document.removeEventListener("keyup",this._signalOnline,true);this._collaborationStopBus&&this._collaborationStopBus();if(this.odooEditor){this.odooEditor.document.removeEventListener("mousemove",this._signalOnline,true);this.odooEditor.document.removeEventListener("keydown",this._signalOnline,true);this.odooEditor.document.removeEventListener("keyup",this._signalOnline,true);this.odooEditor.document.removeEventListener('selectionchange',this._onSelectionChange);this.odooEditor.destroy();}
if(this._peerToPeerLoading){this._peerToPeerLoading.then(()=>{this._stopPeerToPeer();this._collaborationStopBus&&this._collaborationStopBus();});}
clearInterval(this._collaborationInterval);this.$editable&&this.$editable.off('blur',this._onBlur);document.removeEventListener('mousedown',this._onDocumentMousedown,true);const $body=$(document.body);$body.off('mousemove',this.resizerMousemove);$body.off('mouseup',this.resizerMouseup);this.multiSelectionTarget?.removeEventListener('scroll',this.odooEditor.multiselectionRefresh,{passive:true});this.$editable?.off('.Wysiwyg');this.toolbarEl?.remove();this.imageCropEL?.remove();if(this.linkPopover){this.linkPopover.hide();}
if(this._checkConnectionChange){window.removeEventListener('online',this._checkConnectionChange);window.removeEventListener('offline',this._checkConnectionChange);}
window.removeEventListener('beforeunload',this._onBeforeUnload);for(const timeout of this.tooltipTimeouts){clearTimeout(timeout);}
document.removeEventListener('scroll',this._onScroll,true);}
_renderElement(){this.$editable=this.options.editable||$('<div class="note-editable">');if(typeof this.options.fieldId!=='undefined'&&!this.options.inIframe){this.$editable.attr('id',this.options.fieldId);this.$editable.attr('contenteditable',true);}
if(this.options.height){this.$editable.height(this.options.height);}
if(this.options.minHeight){this.$editable.css('min-height',this.options.minHeight);}
if(this.options.maxHeight&&this.options.maxHeight>10){this.$editable.css('max-height',this.options.maxHeight);}
if(this.options.resizable&&!isMobileOS()){const $wrapper=$('<div class="o_wysiwyg_wrapper odoo-editor">');$wrapper.append(this.$editable);this.$resizer=$(`<div class="o_wysiwyg_resizer">
                <div class="o_wysiwyg_resizer_hook"></div>
                <div class="o_wysiwyg_resizer_hook"></div>
                <div class="o_wysiwyg_resizer_hook"></div>
            </div>`);$wrapper.append(this.$resizer);this._replaceElement($wrapper);const minHeight=this.options.minHeight||100;this.$editable.height(this.options.height||minHeight);let startOffsetTop;let startHeight;const $body=$(document.body);const resizerMousedown=(e)=>{e.preventDefault();e.stopPropagation();$body.on('mousemove',this.resizerMousemove);$body.on('mouseup',this.resizerMouseup);startHeight=this.$editable.height();startOffsetTop=e.pageY;};this.resizerMousemove=(e)=>{const offsetTop=e.pageY-startOffsetTop;let height=startHeight+offsetTop;if(height<minHeight){height=minHeight;}
this.$editable.height(height);};this.resizerMouseup=()=>{$body.off('mousemove',this.resizerMousemove);$body.off('mouseup',this.resizerMouseup);};this.$resizer.on('mousedown',resizerMousedown);}else{if(!this.options.sideAttach){this._replaceElement(this.$editable);}}}
_replaceElement($el){this.el.replaceWith($el[0]);this.el=$el[0];this.$el=$el;}
getEditable(){return this.$editable;}
isDirty(){const isDocumentDirty=this.$editable[0].ownerDocument.defaultView.$(".o_dirty").length;return this._initialValue!==(this.getValue()||this.$editable.val())&&isDocumentDirty;}
getValue(options){var $editable=options&&options.$layout||this.$editable.clone();$editable.find('[contenteditable]').removeAttr('contenteditable');$editable.find('[class=""]').removeAttr('class');$editable.find('[style=""]').removeAttr('style');$editable.find('[title=""]').removeAttr('title');$editable.find('[alt=""]').removeAttr('alt');$editable.find('[data-bs-original-title=""]').removeAttr('data-bs-original-title');$editable.find('[data-editor-message]').removeAttr('data-editor-message');$editable.find('a.o_image, span.fa, i.fa').html('');$editable.find('[aria-describedby]').removeAttr('aria-describedby').removeAttr('data-bs-original-title');if(this.odooEditor){this.odooEditor.cleanForSave($editable[0]);this._attachHistoryIds($editable[0]);}
return $editable.html();}
save(){const isDirty=this.isDirty();const html=this.getValue();if(this.$editable.is('textarea')){this.$editable.val(html);}else{this.$editable.html(html);}
return Promise.resolve({isDirty:isDirty,html:html});}
historyReset(){this.odooEditor.historyReset();}
async saveContent(reload=true,editable=false){this.savingContent=true;if(!editable){await this.cleanForSave();const editables="getContentEditableAreas"in this.options?this.options.getContentEditableAreas(this.odooEditor):[];await this.savePendingImages(editables.length?$(editables):this.$editable);await this._saveViewBlocks();}else{await this.cleanForSave(editable);await this.savePendingImages(editable);await this._saveViewBlocks(false,editable);}
this.savingContent=false;window.removeEventListener('beforeunload',this._onBeforeUnload);if(reload){window.location.reload();}}
isSaving(){return!!this.savingContent;}
cancel(reload){var self=this;return new Promise((resolve,reject)=>{this.env.services.dialog.add(ConfirmationDialog,{body:_t("If you discard the current edits, all unsaved changes will be lost. You can cancel to return to edit mode."),confirm:()=>resolve(),cancel:()=>reject()});}).then(function(){if(reload!==false){window.onbeforeunload=null;return self._reload();}});}
savePendingImages($editable=this.$editable){const defs=Array.from($editable).map(async(editableEl)=>{const{resModel,resId}=this._getRecordInfo(editableEl);const b64Proms=[...editableEl.querySelectorAll('.o_b64_image_to_save')].map(async el=>{const dirtyEditable=el.closest(".o_dirty");if(dirtyEditable&&dirtyEditable!==editableEl){return;}
await this._saveB64Image(el,resModel,resId);});const modifiedProms=[...editableEl.querySelectorAll('.o_modified_image_to_save')].map(async el=>{const dirtyEditable=el.closest(".o_dirty");if(dirtyEditable&&dirtyEditable!==editableEl){return;}
await this._saveModifiedImage(el,resModel,resId);});return Promise.all([...b64Proms,...modifiedProms]);});return Promise.all(defs);}
setValue(value){this.odooEditor.resetContent(value);}
undo(){this.odooEditor.historyUndo();}
redo(){this.odooEditor.historyRedo();}
focus(){if(this.odooEditor&&!this.odooEditor.historyResetLatestComputedSelection(true)){const range=document.createRange();const elementToTarget=this.$editable[0].lastElementChild?this.$editable[0].lastElementChild:this.$editable[0];range.selectNodeContents(elementToTarget);range.collapse();const selection=this.odooEditor.document.getSelection();selection.removeAllRanges();selection.addRange(range);}}
getDeepRange(){return getDeepRange(this.odooEditor.editable);}
closestElement(...args){return closestElement(...args);}
async cleanForSave(editable=this.odooEditor.editable){if(this.odooEditor){this.odooEditor.cleanForSave(editable);this._attachHistoryIds(editable);}
if(this.state.showSnippetsMenu){const cleanedProms=[];this.snippetsMenuBus.trigger("CLEAN_FOR_SAVE",{proms:cleanedProms});await Promise.all(cleanedProms);}}
isSelectionInEditable(){return this.odooEditor.isSelectionInEditable();}
_observeOdooFieldChanges(){const observerOptions={childList:true,subtree:true,attributes:true,characterData:true,attributeOldValue:true,};if(this.odooFieldObservers){for(let observerData of this.odooFieldObservers){observerData.observer.observe(observerData.field,observerOptions);}}else{const odooFieldSelector='[data-oe-model], [data-oe-translation-source-sha]';const $odooFields=this.$editable.find(odooFieldSelector);const renderingClassesSelector=this.odooEditor.options.renderingClasses.map(className=>`.${className}`).join(", ");this.odooFieldObservers=[];$odooFields.each((i,field)=>{const observer=new MutationObserver((mutations)=>{mutations=this.odooEditor.filterMutationRecords(mutations);mutations=mutations.filter(rec=>!(rec.type==="attributes"&&(rec.attributeName.startsWith("data-oe-t"))));if(!mutations.length){return;}
let $node=$(field);if($node.hasClass('o_translation_without_style')){return;}
let $nodes=$odooFields.filter(function(){return this!==field;});if($node.data('oe-model')){$nodes=$nodes.filter('[data-oe-model="'+$node.data('oe-model')+'"]').filter('[data-oe-id="'+$node.data('oe-id')+'"]').filter('[data-oe-field="'+$node.data('oe-field')+'"]');}
if($node.data('oe-translation-source-sha')){$nodes=$nodes.filter('[data-oe-translation-source-sha="'+$node.data('oe-translation-source-sha')+'"]');}
if($node.data('oe-type')){$nodes=$nodes.filter('[data-oe-type="'+$node.data('oe-type')+'"]');}
if($node.data('oe-expression')){$nodes=$nodes.filter('[data-oe-expression="'+$node.data('oe-expression')+'"]');}else if($node.data('oe-xpath')){$nodes=$nodes.filter('[data-oe-xpath="'+$node.data('oe-xpath')+'"]');}
if($node.data('oe-contact-options')){$nodes=$nodes.filter("[data-oe-contact-options='"+$node[0].dataset.oeContactOptions+"']");}
let nodes=$node.get();if($node.data('oe-type')==="many2one"){$nodes=$nodes.add($('[data-oe-model]').filter(function(){return this!==$node[0]&&nodes.indexOf(this)===-1;}).filter('[data-oe-many2one-model="'+$node.data('oe-many2one-model')+'"]').filter('[data-oe-many2one-id="'+$node.data('oe-many2one-id')+'"]').filter('[data-oe-type="many2one"]'));$nodes=$nodes.add($('[data-oe-model]').filter(function(){return this!==$node[0]&&nodes.indexOf(this)===-1;}).filter('[data-oe-model="'+$node.data('oe-many2one-model')+'"]').filter('[data-oe-id="'+$node.data('oe-many2one-id')+'"]').filter('[data-oe-field="name"]'));}
this.__odooFieldObserversToPause=this.odooFieldObservers.filter(observerData=>!observerData.field.dataset.oeTranslationSourceSha||!field.contains(observerData.field));this._pauseOdooFieldObservers();if($node.hasClass('o_editable_date_field_format_changed')){$nodes.addClass('o_editable_date_field_format_changed');}
const fieldNodeClone=$node[0].cloneNode(true);for(const node of fieldNodeClone.querySelectorAll(renderingClassesSelector)){node.classList.remove(...this.odooEditor.options.renderingClasses);}
const html=$(fieldNodeClone).html();this.odooEditor.observerUnactive("undo_redo_header");this.odooEditor.withoutRollback(()=>{for(const node of $nodes){if(node.classList.contains('o_translation_without_style')){const text=$node.text();if(node.innerText!==text){node.innerText=text;}
continue;}
if(node.innerHTML!==html){node.innerHTML=html;}}});this.odooEditor.observerActive("undo_redo_header");this._observeOdooFieldChanges();});observer.observe(field,observerOptions);this.odooFieldObservers.push({field:field,observer:observer});});}}
_pauseOdooFieldObservers(){const fieldObserversData=this.__odooFieldObserversToPause||this.odooFieldObservers;for(let observerData of fieldObserversData){observerData.observer.disconnect();}}
openLinkToolsFromSelection(){const selection=this.odooEditor.document.getSelection();if(!selection||selection.rangeCount===0){return;}
for(const el of getSelectedNodes(this.odooEditor.editable)){if(el.classList?.contains("media_iframe_video")||el.classList?.contains("media_iframe_video_size")){return;}}
const targetEl=selection.getRangeAt(0).startContainer;if(closestElement(targetEl,".media_iframe_video")){return;}
if(targetEl.nodeType===Node.ELEMENT_NODE&&(targetEl.tagName==='IMG'||targetEl.querySelectorAll('img').length===1)){this.odooEditor.dispatchEvent(new Event('activate_image_link_tool'));return;}
this.toggleLinkTools();}
async toggleLinkTools(options={}){const shouldFocusUrl=options.shouldFocusUrl===undefined?true:options.shouldFocusUrl;const linkEl=getInSelection(this.odooEditor.document,'a');if(linkEl&&(!linkEl.matches(this.customizableLinksSelector)||!linkEl.isContentEditable)){return;}
if(this.state.showSnippetsMenu&&!options.forceDialog){if(options.link&&options.link.querySelector(mediaSelector)&&!options.link.textContent.trim()&&wysiwygUtils.isImg(this.lastElement)){if(options.shoudFocusUrl){this.mutex.exec(()=>{this.odooEditor.dispatchEvent(new Event('activate_image_link_tool'));});}
return;}
if(options.forceOpen||!this.state.linkToolProps){const $button=$(this.toolbarEl.querySelector('#create-link'));if(!this.state.linkToolProps||![options.link,...wysiwygUtils.ancestors(options.link)].includes(this.linkToolsInfos.link)){const{link}=getOrCreateLink({containerNode:this.odooEditor.editable,startNode:options.link||this.lastMediaClicked,});if(!link){return;}
const addHintClasses=()=>{this.odooEditor.observerUnactive("hint_classes");link.classList.add('oe_edited_link');$button.addClass('active');this.odooEditor.observerActive("hint_classes");};const removeHintClasses=()=>{this.odooEditor.observerUnactive("hint_classes");link.classList.remove('oe_edited_link');$button.removeClass('active');this.odooEditor.observerActive("hint_classes");};this.linkToolsInfos={onDestroy:()=>{},link,removeHintClasses,};addHintClasses();this.state.linkToolProps={...this.options.linkOptions,wysiwyg:this,editable:this.odooEditor.editable,link,needLabel:!link.querySelector('.fa, img'),shouldFocusUrl,$button,onColorCombinationClassChange:(colorCombinationClass)=>{this.linkToolsInfos.colorCombinationClass=colorCombinationClass;},onPreApplyLink:removeHintClasses,onPostApplyLink:addHintClasses,onDestroy:()=>{removeHintClasses();this.linkToolsInfos.onDestroy();},getColorpickerTemplate:this.getColorpickerTemplate.bind(this),};}
this.state.linkToolProps.shouldFocusUrl=shouldFocusUrl;this.odooEditor.document.removeEventListener('click',this._onClick,true);document.removeEventListener('click',this._onClick,true);this._onClick=ev=>{if(!ev.target.closest('#create-link')&&!ev.target.closest(".o_technical_modal")&&!ev.target.closest('.oe-toolbar')&&!ev.target.closest('.ui-autocomplete')&&(!this.state.linkToolProps||![ev.target,...wysiwygUtils.ancestors(ev.target)].includes(this.linkToolsInfos.link))){this.destroyLinkTools();this.odooEditor.document.removeEventListener('click',this._onClick,true);document.removeEventListener('click',this._onClick,true);}};this.odooEditor.document.addEventListener('click',this._onClick,true);document.addEventListener('click',this._onClick,true);}else{this.destroyLinkTools();}}else{const historyStepIndex=this.odooEditor.historySize()-1;this.odooEditor.historyPauseSteps();let{link}=getOrCreateLink({containerNode:this.odooEditor.editable,startNode:options.link,});if(!link){this.odooEditor.historyUnpauseSteps();return}
this._shouldDelayBlur=true;this.env.services.dialog.add(LinkDialog,{...this.options.linkOptions,editable:this.odooEditor.editable,link,needLabel:true&&!link.querySelector('img'),focusField:link.innerHTML?'url':'',onSave:(data)=>{if(!data){return;}
getDeepRange(this.$editable[0],{range:data.range,select:true});if(this.options.userGeneratedContent){data.rel='ugc';}
data.linkDialog.applyLinkToDom(data);this.odooEditor.historyUnpauseSteps();this.odooEditor.historyStep();const link=data.linkDialog.$link[0];const linkIndex=childNodeIndex(link);setSelection(link.parentElement,linkIndex+1,link.parentElement,linkIndex+1,false);},onClose:()=>{this.odooEditor.historyUnpauseSteps();this.odooEditor.historyRevertUntil(historyStepIndex)}});}}
openChatGPTDialog(mode='prompt',options={}){const restore=preserveCursor(this.odooEditor.document);const params={insert:content=>{this.odooEditor.historyPauseSteps();const insertedNodes=this.odooEditor.execCommand('insert',content);this.odooEditor.historyUnpauseSteps();this.notification.add(_t('Your content was successfully generated.'),{title:_t('Content generated'),type:'success',});this.odooEditor.historyStep();const start=insertedNodes?.length&&closestElement(insertedNodes[0]);const end=insertedNodes?.length&&closestElement(insertedNodes[insertedNodes.length-1]);if(start&&end){const divContainer=this.odooEditor.editable.parentElement;let[parent,left,top]=[start.offsetParent,start.offsetLeft,start.offsetTop-start.scrollTop];while(parent&&!parent.contains(divContainer)){left+=parent.offsetLeft;top+=parent.offsetTop-parent.scrollTop;parent=parent.offsetParent;}
let[endParent,endTop]=[end.offsetParent,end.offsetTop-end.scrollTop];while(endParent&&!endParent.contains(divContainer)){endTop+=endParent.offsetTop-endParent.scrollTop;endParent=endParent.offsetParent;}
const div=document.createElement('div');div.classList.add('o-chatgpt-content');const FRAME_PADDING=3;div.style.left=`${left - FRAME_PADDING}px`;div.style.top=`${top - FRAME_PADDING}px`;div.style.width=`${Math.max(start.offsetWidth, end.offsetWidth) + (FRAME_PADDING * 2)}px`;div.style.height=`${endTop + end.offsetHeight - top + (FRAME_PADDING * 2)}px`;divContainer.prepend(div);setTimeout(()=>div.remove(),2000);}},};if(mode==='alternatives'||mode==='translate'){params.originalText=this.odooEditor.document.getSelection().toString()||'';}
if(mode==='translate'){params.language=options.language;}
this.odooEditor.document.getSelection().collapseToEnd();this.env.services.dialog.add(mode==='prompt'?ChatGPTPromptDialog:mode==='translate'?ChatGPTTranslateDialog:ChatGPTAlternativesDialog,params,{onClose:restore},);}
removeLink(){if(this.state.showSnippetsMenu&&wysiwygUtils.isImg(this.lastElement)){this.mutex.exec(()=>{this.odooEditor.dispatchEvent(new Event('deactivate_image_link_tool'));});}else{this.odooEditor.execCommand('unlink');}}
async destroyLinkTools(){if(this.state.linkToolProps){const selection=this.odooEditor.document.getSelection();const link=this.linkToolsInfos.link;let anchorNode
let focusNode;let anchorOffset=0;let focusOffset;if(selection&&link.parentElement){if(shouldUnlink(this.linkToolsInfos.link,this.linkToolsInfos.colorCombinationClass)){if(link.childNodes.length){anchorNode=link.childNodes[0];focusNode=link.childNodes[link.childNodes.length-1];}else{const parent=link.parentElement;const index=Array.from(parent.childNodes).indexOf(link);anchorNode=focusNode=parent;anchorOffset=focusOffset=index;}}else{const commonBlock=selection.rangeCount&&closestBlock(selection.getRangeAt(0).commonAncestorContainer);if(commonBlock&&link.contains(commonBlock)){[anchorNode,focusNode]=[commonBlock,commonBlock];}else if(!this.$editable[0].contains(selection.anchorNode)){[anchorNode,focusNode]=[link,link];}}
if(!focusOffset&&focusNode){focusOffset=focusNode.childNodes.length||focusNode.length;}}
this.linkToolsInfos.removeHintClasses();if(anchorNode){setSelection(anchorNode,anchorOffset,focusNode,focusOffset,false);}
this.state.linkToolProps=undefined;}}
showImageFullscreen(url){const viewerId=`web.file_viewer${fileViewerId++}`;registry.category("main_components").add(viewerId,{Component:FileViewer,props:{files:[{isImage:true,isViewable:true,displayName:url,defaultSource:url,downloadUrl:url,}],startIndex:0,close:()=>{registry.category('main_components').remove(viewerId);},},});this.odooEditor.document.getSelection()?.collapseToEnd();this.odooEditor.editable.blur();}
openMediaDialog(params={}){const sel=this.odooEditor.document.getSelection();if(!sel.rangeCount){return;}
const range=sel.getRangeAt(0);const restoreSelection=preserveCursor(this.odooEditor.document);const editable=OdooEditorLib.closestElement(params.node||range.startContainer,'.o_editable')||this.odooEditor.editable;const{resModel,resId,field,type}=this._getRecordInfo(editable);this.env.services.dialog.add(params.MediaDialog||MediaDialog,{resModel,resId,useMediaLibrary:!!(field&&(resModel==='ir.ui.view'&&field==='arch'||type==='html')),media:params.node,save:this._onMediaDialogSave.bind(this,{node:params.node,restoreSelection:restoreSelection,}),onAttachmentChange:this._onAttachmentChange.bind(this),close:()=>restoreSelection(),...this.options.mediaModalParams,...params,noVideos:!this.options.allowCommandVideo||params.noVideos,});}
showEmojiPicker(){const targetEl=this.odooEditor.document.getSelection();const closest=closestBlock(targetEl.anchorNode);const restoreSelection=preserveCursor(this.odooEditor.document);this.popover.add(closest,EmojiPicker,{onSelect:(str)=>{restoreSelection();this.odooEditor.execCommand('insert',str);},},{onPositioned:(popover)=>{restoreSelection();const rangePosition=getRangePosition(popover,this.options.document,{getContextFromParentRect:this.options.getContextFromParentRect,});popover.style.top=rangePosition.top+'px';popover.style.left=rangePosition.left+'px';const oInputBox=popover.querySelector('input');oInputBox?.focus();},},);}
setCSSVariables(element){const stylesToCopy=weUtils.EDITOR_COLOR_CSS_VARIABLES;for(const style of stylesToCopy){let value=weUtils.getCSSVariableValue(style);if(value.startsWith("'")&&value.endsWith("'")){value=value.substring(1,value.length-1);}
element.style.setProperty(`--we-cp-${style}`,value);}
element.classList.toggle('o_we_has_btn_outline_primary',weUtils.getCSSVariableValue('btn-primary-outline')==='true');element.classList.toggle('o_we_has_btn_outline_secondary',weUtils.getCSSVariableValue('btn-secondary-outline')==='true');}
async _onMediaDialogSave(params,element){params.restoreSelection();if(!element){return;}
const saveCallback=this.state.showSnippetsMenu?async element=>{const $element=$(element);await new Promise(resolve=>{this.snippetsMenuBus.trigger(params.node?"ACTIVATE_SNIPPET":"CALL_POST_SNIPPET_DROP",{$snippet:$element,onSuccess:resolve,},);});if(element.tagName!=='IMG'){return;}
return new Promise(resolve=>{this.mutex.exec(()=>{const event=$.Event("image_changed",{_complete:resolve});$element.trigger(event);});});}:()=>{};if(params.node){this.odooEditor.historyPauseSteps();const changedIcon=isIconElement(params.node)&&isIconElement(element);if(changedIcon){for(const attribute of element.attributes){params.node.setAttribute(attribute.nodeName,attribute.nodeValue);}}else{params.node.replaceWith(element);}
await saveCallback(element);this.odooEditor.historyUnpauseSteps();this.odooEditor.unbreakableStepUnactive();if(params.node.matches(".oe_unremovable")){params.node.classList.remove("oe_unremovable");element.classList.remove("oe_unremovable");this.odooEditor.historyStep();this.odooEditor.observerUnactive("unremovable");element.classList.add("oe_unremovable");this.odooEditor.observerActive("unremovable");}else{this.odooEditor.historyStep();}
this.odooEditor.editable.focus();}else{this.odooEditor.historyPauseSteps();const result=this.odooEditor.execCommand('insert',element);await saveCallback(element);this.odooEditor.historyUnpauseSteps();this.odooEditor.historyStep();this.odooEditor.editable.focus();return result;}}
getInSelection(selector){return getInSelection(this.odooEditor.document,selector);}
waitForEmptyMutexAction(){if(this.state.showSnippetsMenu){return this.mutex.exec(()=>null);}
return Promise.resolve();}
getColorpickerTemplate(){if(!session.is_website_user){return this.getColorPickerTemplateService();}}
_getRecordInfo(){const{res_model:resModel,res_id:resId}=this.options.recordInfo;return{resModel,resId};}
async getSnippetsMenuClass(){const snippetsEditor=await odoo.loader.modules.get('@web_editor/js/editor/snippets.editor')[Symbol.for('default')];const{SnippetsMenu}=snippetsEditor;return SnippetsMenu;}
get snippetsMenuOptions(){return{...this.options,wysiwyg:this,selectorEditableArea:'.o_editable',mutex:this.mutex,};}
_setToolbarProps(){this.state.toolbarProps={...this.options.toolbarOptions,onColorpaletteDropdownShow:this.onColorpaletteDropdownShow.bind(this),onColorpaletteDropdownHide:this.onColorpaletteDropdownHide.bind(this),textColorPaletteProps:this.colorPalettesProps.text,backgroundColorPaletteProps:this.colorPalettesProps.background,showRemoveFormat:this.state.snippetsMenuFolded||!this.options.snippets,};}
_configureToolbar(options){const $toolbar=$(this.toolbarEl);$toolbar.find('.btn-group').on('mousedown',e=>{if(!e.target.closest('.dropdown-menu')||e.target.closest('.btn')&&e.target.closest('.btn').getAttribute('data-call')){e.preventDefault();}});const openTools=e=>{e.preventDefault();e.stopImmediatePropagation();e.stopPropagation();switch(e.currentTarget.id){case'create-link':this.toggleLinkTools();break;case'media-insert':case'media-replace':this.openMediaDialog({node:this.lastMediaClicked});break;case'media-description':{const allEscQuots=/&quot;/g;const alt=($(this.lastMediaClicked).attr('alt')||"").replace(allEscQuots,'"');const tag_title=($(this.lastMediaClicked).attr('title')||$(this.lastMediaClicked).data('original-title')||"").replace(allEscQuots,'"');this.env.services.dialog.add(AltDialog,{alt,tag_title,confirm:(newAlt,newTitle)=>{if(newAlt){this.lastMediaClicked.setAttribute('alt',newAlt);}else{this.lastMediaClicked.removeAttribute('alt');}
if(newTitle){this.lastMediaClicked.setAttribute('title',newTitle);}else{this.lastMediaClicked.removeAttribute('title');}},});break;}
case'open-chatgpt':{this.openChatGPTDialog(this.odooEditor.document.getSelection()?.isCollapsed?'prompt':'alternatives');break;}}};if(!options.snippets){$toolbar.find('#justify, #media-insert').remove();}
$toolbar.find('#image-fullscreen').click(()=>{if(!this.lastMediaClicked?.src){return;}
this.showImageFullscreen(this.lastMediaClicked.src);});$toolbar.find('#media-insert, #media-replace, #media-description').click(openTools);$toolbar.find('#create-link').click(openTools);$toolbar.find('#open-chatgpt').click(openTools);$toolbar.on('click','#translate .lang',(e)=>{e.preventDefault();e.stopImmediatePropagation();e.stopPropagation();const language=e.target.dataset.value;this.openChatGPTDialog('translate',{language});});$toolbar.find('#image-shape div, #fa-spin').click(e=>{if(!this.lastMediaClicked){return;}
this.lastMediaClicked.classList.toggle(e.target.id);e.target.classList.toggle('active',$(this.lastMediaClicked).hasClass(e.target.id));});const $imageWidthButtons=$toolbar.find('#image-width div');$imageWidthButtons.click(e=>{if(!this.lastMediaClicked){return;}
this.lastMediaClicked.style.width=e.target.id;for(const button of $imageWidthButtons){button.classList.toggle('active',this.lastMediaClicked.style.width===button.id);}});$toolbar.find('#image-padding .dropdown-item').click(e=>{if(!this.lastMediaClicked){return;}
$(this.lastMediaClicked).removeClass((index,className)=>((className.match(/(^|\s)padding-\w+/g)||[]).join(' '))).addClass(e.target.dataset.class);});$toolbar.on('mousedown',e=>{const justifyBtn=e.target.closest('#justify div.btn');if(!justifyBtn||!this.lastMediaClicked){return;}
e.originalEvent.stopImmediatePropagation();e.originalEvent.stopPropagation();e.originalEvent.preventDefault();const mode=justifyBtn.id.replace('justify','').toLowerCase();const classes=mode==='center'?['d-block','mx-auto']:['float-'+mode];const doAdd=classes.some(className=>!this.lastMediaClicked.classList.contains(className));this.lastMediaClicked.classList.remove('float-start','float-end');if(this.lastMediaClicked.classList.contains('mx-auto')){this.lastMediaClicked.classList.remove('d-block','mx-auto');}
if(doAdd){this.lastMediaClicked.classList.add(...classes);}
this._updateMediaJustifyButton(justifyBtn.id);});$toolbar.find('#image-crop').click(()=>this._showImageCrop());$toolbar.find('#image-transform').click(e=>{if(!this.lastMediaClicked){return;}
const $image=$(this.lastMediaClicked);const imgTransformBtn=this.toolbarEl.querySelector('#image-transform');if($image.data('transfo-destroy')){$image.removeData('transfo-destroy');return;}
$image.transfo({document:this.odooEditor.document});const destroyTransfo=()=>{$image.transfo('destroy');$(this.odooEditor.document).off('mousedown',mousedown).off('mouseup',mouseup);this.odooEditor.document.removeEventListener('keydown',keydown);}
const mouseup=()=>{imgTransformBtn.classList.toggle('active',$image[0].matches('[style*="transform"]'));};$(this.odooEditor.document).on('mouseup',mouseup);const mousedown=mousedownEvent=>{if(!$(mousedownEvent.target).closest('.transfo-container').length){destroyTransfo();}
if($(mousedownEvent.target).closest('#image-transform').length){$image.data('transfo-destroy',true).attr('style',($image.attr('style')||'').replace(/[^;]*transform[\w:]*;?/g,''));imgTransformBtn.classList.remove('active');}
$image.trigger('content_changed');};$(this.odooEditor.document).on('mousedown',mousedown);const keydown=keydownEvent=>{if(keydownEvent.key==='Escape'){keydownEvent.stopImmediatePropagation();destroyTransfo();}};this.odooEditor.document.addEventListener('keydown',keydown);});$toolbar.find('#image-delete').click(e=>{if(!this.lastMediaClicked){return;}
const anchorNode=this.lastMediaClicked.parentElement;const anchorOffset=Array.from(anchorNode.childNodes).indexOf(this.lastMediaClicked);$(this.lastMediaClicked).remove();this.lastMediaClicked=undefined;setSelection(anchorNode,anchorOffset,anchorNode,anchorOffset);this.odooEditor.toolbarHide();});$toolbar.find('#fa-resize div').click(e=>{if(!this.lastMediaClicked){return;}
const $target=$(this.lastMediaClicked);const sValue=e.target.dataset.value;$target.attr('class',$target.attr('class').replace(/\s*fa-[0-9]+x/g,''));if(+sValue>1){$target.addClass('fa-'+sValue+'x');}
this._updateFaResizeButtons();});if(!options.snippets){document.addEventListener('scroll',this._onScroll,true);}}
_showImageCrop(){if(!this.lastMediaClicked){return;}
this.imageCropProps.media=this.lastMediaClicked;this.imageCropProps.showCount++;this.odooEditor.toolbarHide();$(this.lastMediaClicked).on('image_cropper_destroyed',()=>this.odooEditor.toolbarShow());}
_getSelectedColor($,colorType){const selection=this.odooEditor.document.getSelection();if(!selection)return;const range=selection.rangeCount&&selection.getRangeAt(0);const targetNode=range&&range.startContainer;const targetElement=targetNode&&targetNode.nodeType===Node.ELEMENT_NODE?targetNode:targetNode&&targetNode.parentNode;const backgroundImage=$(targetElement).css('background-image');let backgroundGradient=false;if(weUtils.isColorGradient(backgroundImage)){const textGradient=targetElement.classList.contains('text-gradient');if(colorType==="text"&&textGradient||colorType!=="text"&&!textGradient){backgroundGradient=backgroundImage;}}
return backgroundGradient||$(targetElement).css(colorType==="text"?'color':'backgroundColor');}
onColorpaletteDropdownHide(ev){const shouldHide=!(ev.clickEvent&&this._isColorpickerClick);delete this._isColorpickerClick;return shouldHide;}
onColorpaletteDropdownShow(colorType){const selectedColor=this._getSelectedColor($,colorType);this.colorPalettesProps[colorType].resetTabCount++;this.colorPalettesProps[colorType].selectedColor=selectedColor;const selection=this.odooEditor.document.getSelection();const range=selection.rangeCount&&selection.getRangeAt(0);this.hadNonCollapsedSelectionBeforeColorpicker=range&&!selection.isCollapsed;this.odooEditor.historyStash();}
getColorPaletteTabChangeHandler(colorType){return(selectedTab)=>{this.colorPalettesProps[colorType].selectedTab=selectedTab;}}
_processAndApplyColor(colorType,color,previewMode){if(color&&!isCSSColor(color)&&!weUtils.isColorGradient(color)){color=(colorType==="text"?'text-':'bg-')+color;}
const selectedTds=this.odooEditor.document.querySelectorAll('td.o_selected_td');const applyTransparency=color.startsWith('#')&&!selectedTds.length&&colorType==='background'&&this.colorPalettesProps.background.selectedTab==='theme-colors';if(applyTransparency){const HEX_OPACITY='99';color=color.concat(HEX_OPACITY);}
let coloredElements=this.odooEditor.execCommand('applyColor',color,colorType==='text'?'color':'backgroundColor',this.lastMediaClicked);coloredElements=coloredElements.filter(element=>this.odooEditor.document.contains(element));const coloredTds=coloredElements&&coloredElements.length&&Array.isArray(coloredElements)&&coloredElements.filter(coloredElement=>coloredElement.classList.contains('o_selected_td'));if(selectedTds.length===1&&!previewMode){const sel=this.odooEditor.document.getSelection();sel.collapseToEnd();}else if(coloredTds.length){const propName=colorType==='text'?'color':'background-color';for(const td of coloredTds){td.style.setProperty(propName,td.style[propName],previewMode?'important':'');}}else if(color&&!this.lastMediaClicked&&coloredElements&&coloredElements.length&&Array.isArray(coloredElements)){const first=coloredElements[0];const last=coloredElements[coloredElements.length-1];const sel=this.odooEditor.document.getSelection();const range=sel.getRangeAt(0);const isSelForward=sel.anchorNode===range.startContainer&&sel.anchorOffset===range.startOffset;range.setStart(first,0);range.setEnd(...endPos(last));const{startContainer,startOffset,endContainer,endOffset}=getDeepRange(this.odooEditor.editable,{range});if(isSelForward){sel.setBaseAndExtent(startContainer,startOffset,endContainer,endOffset);}else{sel.setBaseAndExtent(endContainer,endOffset,startContainer,startOffset);}}
const hexColor=this._colorToHex(color);this.odooEditor.updateColorpickerLabels({[colorType==='text'?'text':'hiliteColor']:hexColor,});}
_colorToHex(color){if(color.startsWith('#')){return color;}else if(weUtils.isColorGradient(color)){return color;}else{let rgbColor;if(color.startsWith('rgb')){rgbColor=color;}else{const $font=$(`<font class="${color}"/>`);$(document.body).append($font);const propertyName=color.startsWith('text')?'color':'backgroundColor';rgbColor=$font.css(propertyName);$font.remove();}
return rgbToHex(rgbColor);}}
_handleShortcuts(e){if(this.options.bindLinkTool&&e&&e.key==='k'&&(e.ctrlKey||e.metaKey)){e.preventDefault();this.openLinkToolsFromSelection();}
if(e&&e.key==='a'&&(e.ctrlKey||e.metaKey)){e.preventDefault();const selection=this.odooEditor.document.getSelection();const containerSelector='#wrap>*, .oe_structure>*, [contenteditable]';const container=(selection&&closestElement(selection.anchorNode,containerSelector))||this.$editable.find(containerSelector)[0];if(container){const range=document.createRange();range.selectNodeContents(container);selection.removeAllRanges();selection.addRange(range);}}}
_updateEditorUI(e){let selection=this.odooEditor.document.getSelection();if(!selection)return;const anchorNode=selection.anchorNode;if(isProtected(anchorNode)){return;}
if(this.odooEditor.document.querySelector(".transfo-container")){return;}
this.odooEditor.automaticStepSkipStack();const editorWindow=this.odooEditor.document.defaultView;const $target=e?editorWindow.$(e.target):editorWindow.$();this.toolbarEl.querySelector('#mediaParagraphDropdownButton')?.setAttribute('id','paragraphDropdownButton');const isInMedia=$target.is(mediaSelector)&&!$target.parent().hasClass('o_stars')&&e.target&&(e.target.isContentEditable||(e.target.parentElement&&e.target.parentElement.isContentEditable));this.toolbarEl.classList.toggle('oe-media',isInMedia);for(const el of this.toolbarEl.querySelectorAll(['#image-preview','#image-shape','#image-width','#image-padding','#image-edit','#media-replace',].join(','))){el.classList.toggle('d-none',!isInMedia);}
if(this.state.showSnippetsMenu&&!this.state.snippetsMenuFolded&&$target.is('img')){this.toolbarEl.querySelector('#media-replace')?.classList.toggle('d-none',true);}
for(const el of this.toolbarEl.querySelectorAll(['#image-transform','#image-crop','#media-description',].join(','))){el.classList.toggle('d-none',!isInMedia||!$target.is('img'));}
this.lastMediaClicked=isInMedia&&e.target;this.lastElement=$target[0];for(const el of this.toolbarEl.querySelectorAll(['#style','#decoration','#font-size','#justifyFull','#list','#colorInputButtonGroup','#media-insert','#chatgpt','#translate'].join(','))){el.classList.toggle('d-none',isInMedia);}
for(const el of this.toolbarEl.querySelectorAll('#colorInputButtonGroup')){el.classList.toggle('d-none',isInMedia&&!$target.is('.fa'));}
for(const el of this.toolbarEl.querySelectorAll('.only_fa')){el.classList.toggle('d-none',!isInMedia||!$target.is('.fa'));}
if($target.is('.fa')){for(const el of this.toolbarEl.querySelectorAll(['#image-shape','#image-width','#image-edit',].join(','))){el.classList.toggle('d-none',true);}}
this.$editable.find('.o_we_selected_image').removeClass('o_we_selected_image');if(isInMedia){if($target.attr("data-mimetype")&&!$target[0].dataset.mimetype.startsWith("image")){this.odooEditor.toolbarHide();}else{this.odooEditor.automaticStepSkipStack();const selection=this.odooEditor.document.getSelection();const range=this.odooEditor.document.createRange();range.selectNode(this.lastMediaClicked);selection.removeAllRanges();selection.addRange(range);for(const button of this.toolbarEl.querySelectorAll('#image-shape div, #fa-spin')){button.classList.toggle('active',$(e.target).hasClass(button.id));}
for(const button of this.toolbarEl.querySelectorAll('#image-width div')){button.classList.toggle('active',e.target.style.width===button.id);}
this.toolbarEl.querySelector('#image-transform').classList.toggle('active',e.target.matches('[style*="transform"]'));this._updateMediaJustifyButton();this._updateFaResizeButtons();}}
if(isInMedia&&!this.options.onDblClickEditableMedia){this.showTooltip=true;this.tooltipTimeouts.push(setTimeout(()=>{if(!this.showTooltip||$target.attr('title')!==undefined){return;}
this.saving_mutex.exec(()=>{const removeTooltip=this.popover.add(e.target,Tooltip,{tooltip:_t('Double-click to edit')});this.tooltipTimeouts.push(setTimeout(()=>removeTooltip(),800));});},400));}
this.odooEditor.updateToolbarPosition();setTimeout(()=>{for(const colorType in this.colorPalettesProps){const selectedColor=this._getSelectedColor($,colorType);if(selectedColor){this.colorPalettesProps[colorType].selectedColor=selectedColor;}}});}
_updateMediaJustifyButton(commandState){if(!this.lastMediaClicked){return;}
const $paragraphDropdownButton=$(this.toolbarEl).find('#paragraphDropdownButton, #mediaParagraphDropdownButton');$paragraphDropdownButton.attr('id','mediaParagraphDropdownButton');let resetAlignment=true;if(!commandState){const justifyMapping=[['float-start','justifyLeft'],['mx-auto','justifyCenter'],['float-end','justifyRight'],];commandState=(justifyMapping.find(pair=>(this.lastMediaClicked.classList.contains(pair[0])))||[])[1];resetAlignment=!commandState;}
let newClass;if(commandState){const direction=commandState.replace('justify','').toLowerCase();newClass=`fa-align-${direction === 'full' ? 'justify' : direction}`;resetAlignment=!['float-start','mx-auto','float-end'].some(className=>(this.lastMediaClicked.classList.contains(className)));}
for(const button of this.toolbarEl.querySelectorAll('#justify div.btn')){button.classList.toggle('active',!resetAlignment&&button.id===commandState);}
$paragraphDropdownButton.removeClass((index,className)=>((className.match(/(^|\s)fa-align-\w+/g)||[]).join(' ')));if(commandState&&!resetAlignment){$paragraphDropdownButton.addClass(newClass);}else{$paragraphDropdownButton.addClass('fa-align-justify');}}
_updateFaResizeButtons(){if(!this.lastMediaClicked){return;}
const match=this.lastMediaClicked.className.match(/\s*fa-([0-9]+)x/);const value=match&&match[1]?match[1]:'1';for(const button of this.toolbarEl.querySelectorAll('#fa-resize div')){button.classList.toggle('active',button.dataset.value===value);}}
_getEditorOptions(options){const finalOptions={...this.defaultOptions,...options};finalOptions.autohideToolbar=typeof finalOptions.autohideToolbar==='boolean'?finalOptions.autohideToolbar:!finalOptions.snippets;if(finalOptions.inlineStyle){finalOptions.dropImageAsAttachment=false;}
return finalOptions;}
_getBannerCommand(title,emoji,alertClass,iconClass,description,priority){return{category:_t('Banners'),name:title,priority:priority,description:description,fontawesome:iconClass,isDisabled:()=>isSelectionInSelectors('.o_editor_banner')||!this.odooEditor.isSelectionInBlockRoot(),callback:()=>{const bannerElement=parseHTML(this.odooEditor.document,`
                    <div class="o_editor_banner o_not_editable lh-1 d-flex align-items-center alert alert-${alertClass} pb-0 pt-3" role="status" data-oe-protected="true">
                        <i class="o_editor_banner_icon mb-3 fst-normal" aria-label="${htmlEscape(title)}">${emoji}</i>
                        <div class="w-100 px-3" data-oe-protected="false">
                            <p><br></p>
                        </div>
                    </div>
                `).childNodes[0];this.odooEditor.execCommand('insert',bannerElement);this.odooEditor.activateContenteditable();setSelection(bannerElement.querySelector('.o_editor_banner > div > p'),0);},}}
async _insertSnippetMenu(){const snippetsMenuMountedProm=new Deferred();this.state.snippetsMenuMountedProm=snippetsMenuMountedProm;this.state.showSnippetsMenu=true;await snippetsMenuMountedProm;}
_getBannerCommands(){return[this._getBannerCommand(_t('Banner Info'),'💡','info','fa-info-circle',_t('Insert an info banner'),24),this._getBannerCommand(_t('Banner Success'),'✅','success','fa-check-circle',_t('Insert a success banner'),23),this._getBannerCommand(_t('Banner Warning'),'⚠️','warning','fa-exclamation-triangle',_t('Insert a warning banner'),22),this._getBannerCommand(_t('Banner Danger'),'❌','danger','fa-exclamation-circle',_t('Insert a danger banner'),21),];}
_getBannerCategory(){return[{name:_t("Banners"),priority:65}];}
_saveTranslationElement($el,context,withLang=true){if($el.data('oe-translation-source-sha')){const $els=$el;const translations={};translations[context.lang]=Object.assign({},...$els.toArray().map((x)=>({[$(x).data('oe-translation-source-sha')]:this._getEscapedElement($(x)).html()})));return rpc('/web_editor/field/translation/update',{model:$els.data('oe-model'),record_id:[+$els.data('oe-id')],field_name:$els.data('oe-field'),translations,});}else{var viewID=$el.data('oe-id');if(!viewID){return Promise.resolve();}
return this.orm.call('ir.ui.view','save',[viewID,this._getEscapedElement($el).prop('outerHTML'),!$el.data('oe-expression')&&$el.data('oe-xpath')||null,],{context});}}
_getPowerboxOptions(){const editorOptions=this.options;const categories=[...this._getBannerCategory()];const commands=[...this._getBannerCommands(),{category:_t('Structure'),name:_t('Quote'),priority:30,description:_t('Add a blockquote section'),fontawesome:'fa-quote-right',isDisabled:()=>!this.odooEditor.isSelectionInBlockRoot(),callback:()=>{this.odooEditor.execCommand('setTag','blockquote');},},{category:_t('Structure'),name:_t('Code'),priority:20,description:_t('Add a code section'),fontawesome:'fa-code',isDisabled:()=>!this.odooEditor.isSelectionInBlockRoot(),callback:()=>{this.odooEditor.execCommand('setTag','pre');},},{category:_t('Basic blocks'),name:_t('Signature'),description:_t('Insert your signature'),fontawesome:'fa-pencil-square-o',isDisabled:()=>!this.odooEditor.isSelectionInBlockRoot(),callback:async()=>{const[currentUser]=await this.orm.read('res.users',[this.user.userId],['signature'],);if(currentUser&&currentUser.signature){this.odooEditor.execCommand('insert',parseHTML(this.odooEditor.document,currentUser.signature));}},},{category:_t('AI Tools'),name:_t('ChatGPT'),description:_t('Generate or transform content with AI.'),fontawesome:'fa-magic',priority:1,isDisabled:()=>!this.odooEditor.isSelectionInBlockRoot(),callback:async()=>this.openChatGPTDialog(),},];if(!editorOptions.inlineStyle){commands.push({category:_t('Structure'),name:_t('2 columns'),priority:13,description:_t('Convert into 2 columns'),fontawesome:'fa-columns',callback:()=>this.odooEditor.execCommand('columnize',2,editorOptions.insertParagraphAfterColumns),isDisabled:()=>{if(!this.odooEditor.isSelectionInBlockRoot()){return true;}
const anchor=this.odooEditor.document.getSelection().anchorNode;const row=closestElement(anchor,'.o_text_columns .row');return row&&row.childElementCount===2;},},{category:_t('Structure'),name:_t('3 columns'),priority:12,description:_t('Convert into 3 columns'),fontawesome:'fa-columns',callback:()=>this.odooEditor.execCommand('columnize',3,editorOptions.insertParagraphAfterColumns),isDisabled:()=>{if(!this.odooEditor.isSelectionInBlockRoot()){return true;}
const anchor=this.odooEditor.document.getSelection().anchorNode;const row=closestElement(anchor,'.o_text_columns .row');return row&&row.childElementCount===3;},},{category:_t('Structure'),name:_t('4 columns'),priority:11,description:_t('Convert into 4 columns'),fontawesome:'fa-columns',callback:()=>this.odooEditor.execCommand('columnize',4,editorOptions.insertParagraphAfterColumns),isDisabled:()=>{if(!this.odooEditor.isSelectionInBlockRoot()){return true;}
const anchor=this.odooEditor.document.getSelection().anchorNode;const row=closestElement(anchor,'.o_text_columns .row');return row&&row.childElementCount===4;},},{category:_t('Structure'),name:_t('Remove columns'),priority:10,description:_t('Back to one column'),fontawesome:'fa-columns',callback:()=>this.odooEditor.execCommand('columnize',0),isDisabled:()=>{if(!this.odooEditor.isSelectionInBlockRoot()){return true;}
const anchor=this.odooEditor.document.getSelection().anchorNode;const row=closestElement(anchor,'.o_text_columns .row');return!row;},},{category:_t('Widgets'),name:_t('Emoji'),priority:70,description:_t('Add an emoji'),fontawesome:'fa-smile-o',callback:()=>{this.showEmojiPicker();},},);}
if(editorOptions.allowCommandLink){categories.push({name:_t('Navigation'),priority:40});commands.push({category:_t('Navigation'),name:_t('Link'),priority:40,description:_t('Add a link'),fontawesome:'fa-link',callback:()=>{this.toggleLinkTools({forceDialog:true});},},{category:_t('Navigation'),name:_t('Button'),priority:30,description:_t('Add a button'),fontawesome:'fa-link',callback:()=>{this.toggleLinkTools({forceDialog:true});setTimeout(()=>{const selectEl=document.querySelector('.o_link_dialog .form-select');selectEl.value='primary';selectEl.dispatchEvent(new Event('change'));},150);},},);}
if(editorOptions.allowCommandImage||editorOptions.allowCommandVideo){categories.push({name:_t('Media'),priority:50});}
if(editorOptions.allowCommandImage){commands.push({category:_t('Media'),name:_t('Image'),priority:40,description:_t('Insert a picture'),fontawesome:'fa-file-image-o',callback:()=>{this.openMediaDialog();},});}
if(editorOptions.allowCommandVideo){commands.push({category:_t('Media'),name:_t('Video'),priority:30,description:_t('Insert a video'),fontawesome:'fa-file-video-o',callback:()=>{this.openMediaDialog({noVideos:false,noImages:true,noIcons:true,noDocuments:true});},});}
if(editorOptions.powerboxCategories){categories.push(...editorOptions.powerboxCategories);}
if(editorOptions.powerboxItems){commands.push(...editorOptions.powerboxItems);}
return{commands,categories};}
editable(){return $('#wrapwrap [data-oe-model]').not('.o_not_editable').filter(function(){return!$(this).closest('.o_not_editable').length;}).not('link, script').not('[data-oe-readonly]').not('img[data-oe-field="arch"], br[data-oe-field="arch"], input[data-oe-field="arch"]').not('.oe_snippet_editor').add('.o_editable');}
_saveViewBlocks(context,element=false){const $=element?getJqueryFromDocument(element):getJqueryFromDocument(this.$editable[0].ownerDocument);const $allBlocks=$((this.options||{}).savableSelector).filter(this.options.enableTranslation?'.o_dirty, .o_delay_translation':'.o_dirty');const $dirty=$('.o_dirty');$dirty.removeAttr('contentEditable').removeClass('o_dirty oe_carlos_danger o_is_inline_editable');const $delay_translation=$('.o_delay_translation');$delay_translation.removeClass('o_delay_translation');$('.o_editable').removeClass('o_editable o_is_inline_editable o_editable_date_field_linked o_editable_date_field_format_changed');const saveElementFuncName=this.options.enableTranslation?'_saveTranslationElement':'_saveElement';const groupedElements=groupBy($allBlocks.toArray(),el=>{const model=el.dataset.oeModel;const field=el.dataset.oeField;if(!model){return uniqueId("special-element-to-save-");}
if(!this.options.enableTranslation&&(model==='ir.ui.view'&&field==='arch')){return uniqueId("view-part-to-save-");}
return`${model}::${el.dataset.oeId}::${field}`;});const proms=Object.values(groupedElements).map(els=>{const $els=$(els);$els.find('[class]').filter(function(){if(!this.getAttribute('class').match(/\S/)){this.removeAttribute('class');}});return new Promise((resolve,reject)=>{return this.saving_mutex.exec(()=>{return this[saveElementFuncName]($els,context||this.options.context).then(function(){$els.removeClass('o_dirty');resolve();}).catch(error=>{var id=uniqueId("carlos_danger_");$els.addClass('o_dirty o_editable oe_carlos_danger '+id);$('.o_editable.'+id).removeClass(id).popover({trigger:'hover',content:error.data?.message||'',placement:'auto',}).popover('show');reject();});});});});return Promise.all(proms).then(function(){window.onbeforeunload=null;});}
_attachTooltips(){$(document.body).tooltip({selector:'[data-oe-readonly]',container:'body',trigger:'hover',delay:{'show':1000,'hide':100},placement:'bottom',title:_t("Readonly field")}).on('click',function(){$(this).tooltip('hide');});}
_getEscapedElement($el){var escaped_el=$el.clone();var to_escape=escaped_el.find('*').addBack();to_escape=to_escape.not(to_escape.filter('object,iframe,script,style,[data-oe-model][data-oe-model!="ir.ui.view"]').find('*').addBack());to_escape.contents().each(function(){if(this.nodeType===3){this.nodeValue=$('<div />').text(this.nodeValue).html();}});return escaped_el;}
async _saveElement($el,context){var viewID=$el.data('oe-id');if(!viewID){return Promise.resolve();}
let escapedHtml=this._getEscapedElement($el).prop('outerHTML');const result=this.orm.call('ir.ui.view','save',[viewID,escapedHtml,!$el.data('oe-expression')&&$el.data('oe-xpath')||null],{context:{...context,delay_translations:false,},});return result;}
_reload(){window.location.search='scrollTop='+window.document.body.scrollTop;if(window.location.search.indexOf('enable_editor')>=0){window.location.href=window.location.href.replace(/&?enable_editor(=[^&]*)?/g,'');}else{window.location.reload(true);}
return new Promise(function(){});}
_onAttachmentChange(attachment){if(this.options.onAttachmentChange){this.options.onAttachmentChange(attachment);}}
_onDblClickEditableMedia(ev){const $el=$(ev.currentTarget);$el.selectElement();if(!$el.parent().hasClass('o_stars')){this.waitForEmptyMutexAction().then(()=>{if($el[0].parentElement){this.openMediaDialog({node:$el[0]});}});}}
_onSelectionChange(){if(this.linkPopover&&this.isSelectionInEditable()){const selectionInLink=getInSelection(this.odooEditor.document,'a')===this.linkPopover.target;const isVisible=this.linkPopover.el.offsetParent;if(isVisible&&((this.options.autohideToolbar&&!this.odooEditor.document.getSelection().isCollapsed&&!(this.linkPopover.$target.attr("data-mimetype")&&this.linkPopover.$target[0].dataset.mimetype.startsWith("image")))||!selectionInLink)){this.linkPopover.hide();}}}
_getDelayBlurSelectors(){return[".oe-toolbar",".oe-powerbox-wrapper",".o_we_crop_widget"];}
_onDocumentMousedown(e){if(!e.target.classList.contains('o_editable_date_field_linked')){this.$editable.find('.o_editable_date_field_linked').removeClass('o_editable_date_field_linked');}
const closestDialog=e.target.closest('.o_dialog, .o_web_editor_dialog');if(e.target.closest("#oe_snippets")||e.target.closest(this._getDelayBlurSelectors().join(","))||(closestDialog&&closestDialog.querySelector('.o_select_media_dialog, .o_link_dialog'))){this._shouldDelayBlur=true;}else{if(this._pendingBlur&&!e.target.closest('.o_wysiwyg_wrapper')){this.options.onWysiwygBlur&&this.options.onWysiwygBlur();this._pendingBlur=false;}
this._shouldDelayBlur=false;}
if(e.target.closest(".o_colorpicker_widget")){this._isColorpickerClick=true;}}
_onBlur(){if(this._shouldDelayBlur){this._pendingBlur=true;}else{this.options.onWysiwygBlur&&this.options.onWysiwygBlur();}}
_onScroll(ev){if(ev.target.contains(this.$editable[0])){this.scrollContainer=ev.target;this.odooEditor.updateToolbarPosition();}}
_signalOffline(){this._isOnline=false;}
async _signalOnline(){clearTimeout(this._offlineTimeout);this._offlineTimeout=undefined;if(this._isOnline||!navigator.onLine){return;}
this._isOnline=true;if(!this.ptp)return;this.ptp.notifyAllClients('ptp_join');this.ptp.notifyAllClients('oe_history_step',peek(this.odooEditor.historyGetSteps()),{transport:'rtc'});}
async _processMissingSteps(missingSteps){if(missingSteps===-1||!missingSteps.length){return false;}
this.ptp&&this.odooEditor.onExternalHistorySteps(missingSteps);return true;}
_showConflictDialog(){if(this._conflictDialogOpened)return;const content=markup(this.odooEditor.editable.cloneNode(true).outerHTML);this._conflictDialogOpened=true;this.env.services.dialog.add(ConflictDialog,{content,close:()=>this._conflictDialogOpened=false,});}
_getLastHistoryStepId(value){const matchId=value.match(/data-last-history-steps="(?:[0-9]+,)*([0-9]+)"/);return matchId&&matchId[1];}
_generateClientId(){return Math.floor(Math.random()*Math.pow(2,52)).toString();}
_getNewPtp(){const rpcMutex=new Mutex();const{collaborationChannel}=this.options;const modelName=collaborationChannel.collaborationModelName;const fieldName=collaborationChannel.collaborationFieldName;const resId=collaborationChannel.collaborationResId;this._historySyncAtLeastOnce=false;return new PeerToPeer({peerConnectionConfig:{iceServers:this._iceServers},currentClientId:this._currentClientId,broadcastAll:(rpcData)=>{return rpcMutex.exec(async()=>{return this._serviceRpc('/web_editor/bus_broadcast',{model_name:modelName,field_name:fieldName,res_id:resId,bus_data:rpcData,});});},onRequest:{get_start_time:()=>this._startCollaborationTime,get_client_name:()=>user.name,get_client_avatar:()=>`${browser.location.origin}/web/image?model=res.users&field=avatar_128&id=${encodeURIComponent(user.userId)}`,get_missing_steps:(params)=>this.odooEditor.historyGetMissingSteps(params.requestPayload),get_history_from_snapshot:()=>this._getHistorySnapshot(),get_collaborative_selection:()=>this.odooEditor.getCurrentCollaborativeSelection(),recover_document:(params)=>{const{serverDocumentId,fromStepId}=params.requestPayload;if(!this.odooEditor.historyGetBranchIds().includes(serverDocumentId)){return;}
return{missingSteps:this.odooEditor.historyGetMissingSteps({fromStepId}),snapshot:this._getHistorySnapshot(),};},},onNotification:async({fromClientId,notificationName,notificationPayload})=>{switch(notificationName){case'ptp_remove':this.odooEditor.multiselectionRemove(notificationPayload);break;case'ptp_disconnect':this.ptp.removeClient(fromClientId);this.odooEditor.multiselectionRemove(fromClientId);break;case'rtc_data_channel_open':{fromClientId=notificationPayload.connectionClientId;const remoteStartTime=await this.requestClient(fromClientId,'get_start_time',undefined,{transport:'rtc'});if(remoteStartTime===REQUEST_ERROR)return;this.ptp.clientsInfos[fromClientId].startTime=remoteStartTime;if(!this._historySyncAtLeastOnce){const localClient={id:this._currentClientId,startTime:this._startCollaborationTime};const remoteClient={id:fromClientId,startTime:remoteStartTime};if(isClientFirst(localClient,remoteClient)){this._historySyncAtLeastOnce=true;this._historySyncFinished=true;}else{this._resetCollabRequests();const response=await this._resetFromClient(fromClientId,this._lastCollaborationResetId);if(response===REQUEST_ERROR){return;}}}else{this.ptp.notifyAllClients('oe_history_step',peek(this.odooEditor.historyGetSteps()),{transport:'rtc'});this._setCollaborativeSelection(fromClientId);}
const getClientNamePromise=this.requestClient(fromClientId,'get_client_name',undefined,{transport:'rtc'}).then((clientName)=>{if(clientName===REQUEST_ERROR)return;this.ptp.clientsInfos[fromClientId].clientName=clientName;this.odooEditor.multiselectionRefresh();});const getClientAvatar=this.requestClient(fromClientId,'get_client_avatar',undefined,{transport:'rtc'}).then(clientAvatarUrl=>{if(clientAvatarUrl===REQUEST_ERROR)return;this.ptp.clientsInfos[fromClientId].clientAvatarUrl=clientAvatarUrl;this.odooEditor.multiselectionRefresh();});await Promise.all([getClientAvatar,getClientNamePromise]);break;}
case'oe_history_step':if(this._historySyncFinished){this.odooEditor.onExternalHistorySteps([notificationPayload]);}else{this._historyStepsBuffer.push(notificationPayload);}
break;case'oe_history_set_selection':{const client=this.ptp.clientsInfos[fromClientId];if(!client){return;}
const selection=notificationPayload;selection.clientName=client.clientName;selection.clientAvatarUrl=client.clientAvatarUrl;this.odooEditor.onExternalMultiselectionUpdate(selection);break;}}}});}
_getCollaborationClientAvatarUrl(){return`${browser.location.origin}/web/image?model=res.users&field=avatar_128&id=${encodeURIComponent(user.userId)}`}
_stopPeerToPeer(){this._joiningPtp=false;this._ptpJoined=false;this._resetCollabRequests();this.ptp&&this.ptp.stop();}
_joinPeerToPeer(){this.$editable[0].removeEventListener('focus',this._joinPeerToPeer);if(this._peerToPeerLoading){return this._peerToPeerLoading.then(async()=>{this._joiningPtp=true;if(this._isDocumentStale){const success=await this._resetFromServerAndResyncWithClients();if(!success)return;}
this.ptp.notifyAllClients('ptp_join');this._joiningPtp=false;this._ptpJoined=true;});}}
async _setCollaborativeSelection(fromClientId){const remoteSelection=await this.requestClient(fromClientId,'get_collaborative_selection',undefined,{transport:'rtc'});if(remoteSelection===REQUEST_ERROR)return;if(remoteSelection){this.odooEditor.onExternalMultiselectionUpdate(remoteSelection);}}
_getPtpClients(){const clients=Object.entries(this.ptp.clientsInfos).map(([clientId,clientInfo])=>({id:clientId,...clientInfo}));return clients.sort((a,b)=>isClientFirst(a,b)?-1:1);}
async _getCurrentRecord(){const[record]=await this.orm.read(this.options.collaborationChannel.collaborationModelName,[this.options.collaborationChannel.collaborationResId],[this.options.collaborationChannel.collaborationFieldName],);return record;}
_isLastDocumentStale(){if(!this._serverLastStepId){return false;}
return!this.odooEditor.historyGetBranchIds().includes(this._serverLastStepId);}
_onServerLastIdUpdate(last_step_id){this._serverLastStepId=last_step_id;this._isDocumentStale=this._isLastDocumentStale();if(this._isDocumentStale&&this._ptpJoined){return this._recoverFromStaleDocument();}else if(this._isDocumentStale&&this._joiningPtp){this._resetCollabRequests();this._joinPeerToPeer();}}
async _recoverFromStaleDocument(){return new Promise((resolve)=>{const resetCollabCount=this._lastCollaborationResetId;const allPeers=this._getPtpClients().map(client=>client.id);if(allPeers.length===0){if(this._isDocumentStale){this._showConflictDialog();resolve();return this._resetFromServerAndResyncWithClients();}}
let hasRetrievalBudgetTimeout=false;let snapshots=[];let nbPendingResponses=allPeers.length;const success=()=>{resolve();clearTimeout(timeout);};for(const peerId of allPeers){this.requestClient(peerId,'recover_document',{serverDocumentId:this._serverLastStepId,fromStepId:peek(this.odooEditor.historyGetBranchIds()),},{transport:'rtc'}).then((response)=>{nbPendingResponses--;if(response===REQUEST_ERROR||resetCollabCount!==this._lastCollaborationResetId||hasRetrievalBudgetTimeout||!response||!this._isDocumentStale){if(nbPendingResponses<=0){processSnapshots();}
return;}
this._processMissingSteps(response.missingSteps);this._isDocumentStale=this._isLastDocumentStale();snapshots.push(response.snapshot);if(nbPendingResponses<1){processSnapshots();}});}
const processSnapshots=async()=>{this._isDocumentStale=this._isLastDocumentStale();if(!this._isDocumentStale){return success();}
if(snapshots[0]){this._showConflictDialog();}
for(const snapshot of snapshots){this._applySnapshot(snapshot);this._isDocumentStale=this._isLastDocumentStale();if(!this._isDocumentStale){return success();}}
if(this._isDocumentStale){this._showConflictDialog();await this._resetFromServerAndResyncWithClients();}
success();}
const timeout=setTimeout(()=>{if(resetCollabCount!==this._lastCollaborationResetId)return;hasRetrievalBudgetTimeout=true;this._onRecoveryClientTimeout(processSnapshots);},PTP_MAX_RECOVERY_TIME);});}
async _onRecoveryClientTimeout(processSnapshots){processSnapshots();}
async _resetFromServerAndResyncWithClients(){let collaborationResetId=this._lastCollaborationResetId;const record=await this._getCurrentRecord();if(collaborationResetId!==this._lastCollaborationResetId)return;const content=record[this.options.collaborationChannel.collaborationFieldName];const lastHistoryId=content&&this._getLastHistoryStepId(content);if(this._serverLastStepId!==lastHistoryId){throw new Error('Concurency detected while recovering from a stale document. The last history id of the server is different from the history id received by the html_field_write event.');}
this._isDocumentStale=false;this.resetValue(content);this._historySyncAtLeastOnce=false;this._resetCollabRequests();collaborationResetId=this._lastCollaborationResetId;this._startCollaborationTime=new Date().getTime();await Promise.all(this._getPtpClients().map((client)=>{return this._resetFromClient(client.id,collaborationResetId);}));return true;}
_resetCollabRequests(){this._lastCollaborationResetId++;this.ptp&&this.ptp.abortCurrentRequests();}
async _resetFromClient(fromClientId,resetCollabCount){this._historySyncFinished=false;this._historyStepsBuffer=[];const snapshot=await this.requestClient(fromClientId,'get_history_from_snapshot',undefined,{transport:'rtc'});if(snapshot===REQUEST_ERROR){return REQUEST_ERROR;}
if(resetCollabCount!==this._lastCollaborationResetId){return;}
if(this._historySyncAtLeastOnce){return;}
const applied=this._applySnapshot(snapshot);if(!applied){return;}
this._historySyncFinished=true;if(this._historyStepsBuffer.length){this.odooEditor.onExternalHistorySteps(this._historyStepsBuffer);this._historyStepsBuffer=[];}
this.options.onHistoryResetFromSteps();this._setCollaborativeSelection(fromClientId);}
async requestClient(clientId,requestName,requestPayload,params){return this.ptp.requestClient(clientId,requestName,requestPayload,params).catch((e)=>{if(e instanceof RequestError){return REQUEST_ERROR;}else{throw e;}});}
async resetValue(value){this.setValue(value);this.odooEditor.historyReset();this._historyShareId=Math.floor(Math.random()*Math.pow(2,52)).toString();this._serverLastStepId=value&&this._getLastHistoryStepId(value);if(this._serverLastStepId){this.odooEditor.historySetInitialId(this._serverLastStepId);}}
async resetEditor(value,options){await this._peerToPeerLoading;this.$editable[0].removeEventListener('focus',this._joinPeerToPeer);if(options){this.options=this._getEditorOptions(options);}
const{collaborationChannel}=this.options;this._stopPeerToPeer();this._collaborationStopBus&&this._collaborationStopBus();this._isDocumentStale=false;this._rulesCache=undefined;if(!this._isCollaborationEnabled(this.options)){this._currentClientId=undefined;this.resetValue(value);return;}
this._currentClientId=this._generateClientId();this.odooEditor.collaborationSetClientId(this._currentClientId);this.resetValue(value);this.setupCollaboration(collaborationChannel);if(this.options.collaborativeTrigger==='start'){this._joinPeerToPeer();}else if(this.options.collaborativeTrigger==='focus'){this.$editable[0].addEventListener('focus',this._joinPeerToPeer);}
await this._peerToPeerLoading;}
_getHistorySnapshot(){return Object.assign({},this.odooEditor.historyGetSnapshotSteps(),{historyShareId:this._historyShareId});}
_applySnapshot(snapshot){const{steps,historyIds,historyShareId}=snapshot;const isStaleDocument=this._serverLastStepId&&!historyIds.includes(this._serverLastStepId);if(isStaleDocument){return;}
this._historyShareId=historyShareId;this._historySyncAtLeastOnce=true;this.odooEditor.historyResetFromSteps(steps,historyIds);this.odooEditor.historyResetLatestComputedSelection();return true;}
_onPostSanitize(node){if(node?.querySelectorAll&&this.odooEditor&&!this.odooEditor._fixLinkMutatedElements){for(const element of node.querySelectorAll('.o_not_editable')){if(element.isContentEditable!==false){element.contentEditable=false;}}}}
_attachHistoryIds(editable=this.odooEditor.editable){if(this.options.collaborative){editable.querySelectorAll('[data-last-history-steps]').forEach(el=>el.removeAttribute('data-last-history-steps'));const historyIds=this.odooEditor.historyGetBranchIds().join(',');const firstChild=editable.children[0];if(firstChild){firstChild.setAttribute('data-last-history-steps',historyIds);}}}
_bindOnBlur(){this.$editable.on('blur',this._onBlur);}
_hasICEServers(){return this.env.services['mail.store'];}
_isCollaborationEnabled(options){return options.collaborationChannel&&options.collaborationChannel.collaborationResId&&this._hasICEServers()&&this.busService;}
async _saveB64Image(el,resModel,resId){el.classList.remove('o_b64_image_to_save');const imageData=el.getAttribute('src').split('base64,')[1];if(!imageData){return;}
const attachment=await this._serviceRpc('/web_editor/attachment/add_data',{name:el.dataset.fileName||'',data:imageData,is_image:true,res_model:resModel,res_id:resId,},);if(attachment.mimetype==='image/webp'){el.classList.add('o_modified_image_to_save');el.dataset.originalId=attachment.id;el.dataset.mimetype=attachment.mimetype;el.dataset.fileName=attachment.name;this._saveModifiedImage(el,resModel,resId);}else{let src=attachment.image_src;if(!attachment.public){let accessToken=attachment.access_token;if(!accessToken){[accessToken]=await this.orm.call('ir.attachment','generate_access_token',[attachment.id],);}
src+=`?access_token=${encodeURIComponent(accessToken)}`;}
el.setAttribute('src',src);}}
async _saveModifiedImage(el,resModel,resId){const isBackground=!el.matches('img');let altData=undefined;const isImageField=!!el.closest("[data-oe-type=image]");if(el.dataset.mimetype==='image/webp'&&isImageField){altData={};const image=document.createElement('img');image.src=isBackground?el.dataset.bgSrc:el.getAttribute('src');await new Promise(resolve=>image.addEventListener('load',resolve));const originalSize=Math.max(image.width,image.height);const smallerSizes=[1024,512,256,128].filter(size=>size<originalSize);for(const size of[originalSize,...smallerSizes]){const ratio=size/originalSize;const canvas=document.createElement('canvas');canvas.width=image.width*ratio;canvas.height=image.height*ratio;const ctx=canvas.getContext('2d');ctx.fillStyle='rgb(255, 255, 255)';ctx.fillRect(0,0,canvas.width,canvas.height);ctx.drawImage(image,0,0,image.width,image.height,0,0,canvas.width,canvas.height);altData[size]={'image/jpeg':canvas.toDataURL('image/jpeg',0.75).split(',')[1],};if(size!==originalSize){altData[size]['image/webp']=canvas.toDataURL('image/webp',0.75).split(',')[1];}}}
let newAttachmentSrc=isBackground?el.dataset.bgSrc:el.getAttribute('src');const isImageAlreadySaved=!newAttachmentSrc||!newAttachmentSrc.startsWith("data:");if(isImageAlreadySaved){el.classList.remove('o_modified_image_to_save');return;}
let attachmentNotFound=false;try{newAttachmentSrc=await this._serviceRpc(`/web_editor/modify_image/${encodeURIComponent(el.dataset.originalId)}`,{res_model:resModel,res_id:parseInt(resId),data:(isBackground?el.dataset.bgSrc:el.getAttribute('src')).split(',')[1],alt_data:altData,mimetype:(isBackground?el.dataset.mimetype:el.getAttribute('src').split(":")[1].split(";")[0]),name:(el.dataset.fileName?el.dataset.fileName:null),},);}catch{newAttachmentSrc="/html_editor/static/src/img/placeholder_thumbnail.png";attachmentNotFound=true;}
el.classList.remove('o_modified_image_to_save');if(isBackground){const parts=weUtils.backgroundImageCssToParts($(el).css('background-image'));parts.url=`url('${newAttachmentSrc}')`;const combined=weUtils.backgroundImagePartsToCss(parts);$(el).css('background-image',combined);delete el.dataset.bgSrc;}else{let targetEl=el;if(attachmentNotFound){targetEl=document.createElement("img");el.insertAdjacentElement("afterend",targetEl);el.remove();}
targetEl.src=newAttachmentSrc;weUtils.forwardToThumbnail(targetEl);}}
_beforeAnyCommand(){for(const node of OdooEditorLib.getTraversedNodes(this.$editable[0])){const el=node.nodeType===Node.TEXT_NODE?node.parentElement:node;const defaultTextEl=el.closest('.o_default_snippet_text');if(defaultTextEl){defaultTextEl.classList.remove('o_default_snippet_text');}}}
_trigger_up(ev){const evType=ev.name;const payload=ev.data;if(evType==='call_service'){this._callService(payload);}}
_callService(payload){const service=this.env.services[payload.service];const result=service[payload.method].apply(service,payload.args||[]);payload.callback(result);}
_serviceRpc(route,params,settings={}){if(status(this)==="destroyed"){return;}
if(params&&params.kwargs){params.kwargs.context={...user.context,...params.kwargs.context,};}
return rpc(route,params,{silent:settings.shadow,xhr:settings.xhr,});}}
Wysiwyg.activeCollaborationChannelNames=new Set();Wysiwyg.activeWysiwygs=new Set();Wysiwyg.getRange=function(ownerDocument){const selection=(ownerDocument||document).getSelection();if(selection.rangeCount===0){return{sc:null,so:0,ec:null,eo:0,};}
const range=selection.getRangeAt(0);return{sc:range.startContainer,so:range.startOffset,ec:range.endContainer,eo:range.endOffset,};};Wysiwyg.setRange=function(startNode,startOffset=0,endNode=startNode,endOffset=startOffset){const selection=document.getSelection();selection.removeAllRanges();const range=new Range();range.setStart(startNode,startOffset);range.setEnd(endNode,endOffset);selection.addRange(range);};function isClientFirst(clientA,clientB){if(clientA.startTime===clientB.startTime){return clientA.id.localeCompare(clientB.id)===-1;}if(clientA.startTime===undefined||clientB.startTime===undefined){return Boolean(clientA.startTime);}else{return clientA.startTime<clientB.startTime;}}
__exports.stripHistoryIds=stripHistoryIds;function stripHistoryIds(value){return value&&value.replace(/\sdata-last-history-steps="[^"]*?"/,'')||value;}
return __exports;});;

/* /web_editor/static/src/js/wysiwyg/wysiwyg_iframe.js */
odoo.define('@web_editor/js/wysiwyg/wysiwyg_iframe',['@web_editor/js/wysiwyg/wysiwyg','@web/core/utils/patch','@web/core/assets','@web/core/browser/feature_detection','@odoo/owl','@web/legacy/js/public/public_widget'],function(require){'use strict';let __exports={};const{Wysiwyg}=require('@web_editor/js/wysiwyg/wysiwyg');const{patch}=require("@web/core/utils/patch");const{getBundle}=require("@web/core/assets");const{isMobileOS}=require("@web/core/browser/feature_detection");const{useEffect}=require("@odoo/owl");var promiseJsAssets;patch(Wysiwyg.prototype,{setup(){super.setup();useEffect(()=>this.handleSnippetsDisplay(),()=>[this.state.showSnippetsMenu,this.state.snippetsMenuFolded]);},init(){super.init();if(this.options.inIframe){this._onUpdateIframeId='onLoad_'+this.id;}},async startEdition(){if(!this.options.inIframe){return super.startEdition();}else{this.defAsset=this._getAssets();await this.defAsset;await this._loadIframe();return super.startEdition();}},destroy(){if(this.options.inIframe){this.$iframe?.[0].contentDocument.removeEventListener('scroll',this._onScroll,true);}
super.destroy();},handleSnippetsDisplay(){const iframe=this.$iframe?.[0];if(!iframe||!iframe.isConnected){return;}
iframe.classList.toggle("has_snippets_sidebar",this.state.showSnippetsMenu&&!this.state.snippetsMenuFolded);},onToggleFullscreen(isFullscreen){},_getEditorOptions(){const options=super._getEditorOptions(...arguments);if(!("getContextFromParentRect"in options)){options.getContextFromParentRect=()=>{return this.$iframe&&this.$iframe.length?this.$iframe[0].getBoundingClientRect():{top:0,left:0};};}
if(this.$iframe&&this.$iframe.length){options.document=this.$iframe[0].contentWindow.document;}
return options;},_loadIframe(){var self=this;this.$editable=$('<div class="note-editable oe_structure odoo-editor-editable"></div>');this.$el.removeClass('note-editable oe_structure odoo-editor-editable');this.$iframe=$('<iframe class="wysiwyg_iframe o_iframe">').css({width:'100%',height:'100%',});this.handleSnippetsDisplay();var avoidDoubleLoad=0;var def=new Promise(function(resolve){window.top[self._onUpdateIframeId]=function(_avoidDoubleLoad){if(_avoidDoubleLoad!==avoidDoubleLoad){console.warn('Wysiwyg iframe double load detected');return;}
delete window.top[self._onUpdateIframeId];var $iframeTarget=self.$iframe.contents().find('#iframe_target');const $targetClone=$iframeTarget.clone();$targetClone.find('script').remove();$iframeTarget.html($targetClone.html());self.$iframeBody=$iframeTarget;$iframeTarget.attr("isMobile",isMobileOS());const $iframeWrapper=$('<div class="iframe-editor-wrapper odoo-editor">');const $codeview=$('<textarea class="o_codeview d-none"/>');self.$editable.addClass('o_editable oe_structure');$iframeTarget.append($codeview);$iframeTarget.append($iframeWrapper);$iframeWrapper.append(self.$editable);self.options.toolbarHandler=$('#web_editor-top-edit',self.$iframe[0].contentWindow.document);resolve();};});this.$iframe.data('loadDef',def);this.$iframe.on('load',function onLoad(ev){var _avoidDoubleLoad=++avoidDoubleLoad;self.defAsset.then(function(assets){if(_avoidDoubleLoad!==avoidDoubleLoad){console.warn('Wysiwyg immediate iframe double load detected');return;}
const iframeContent=getWysiwygIframeContent({assets:assets,updateIframeId:self._onUpdateIframeId,avoidDoubleLoad:_avoidDoubleLoad});self.$iframe[0].contentWindow.document.open("text/html","replace").write(`<!DOCTYPE html><html${
                        self.options.iframeHtmlClass ? ' class="' + self.options.iframeHtmlClass +'"' : ''
                    }>${iframeContent}</html>`);self.$iframe.off('load',onLoad);self.$iframe[0].contentWindow.document.close();});self.options.document=self.$iframe[0].contentWindow.document;});this.$el.append(this.$iframe);return def.then(()=>{this.options.onIframeUpdated();this.handleSnippetsDisplay();});},async _insertSnippetMenu(){if(this.options.inIframe){this.el.classList.add("w-100");}
return super._insertSnippetMenu();},async _getAssets(){promiseJsAssets=promiseJsAssets||await getBundle('web_editor.wysiwyg_iframe_editor_assets');const assetsPromises=[promiseJsAssets];if(this.options.iframeCssAssets){assetsPromises.push(getBundle(this.options.iframeCssAssets));}
return Promise.all(assetsPromises);},_bindOnBlur(){if(!this.options.inIframe){super._bindOnBlur(...arguments);}else{this.$iframe[0].contentWindow.addEventListener('blur',this._onBlur);}},_onScroll(ev){if(this.options.inIframe){const iframeDocument=this.$iframe[0].contentDocument;const scrollInIframe=ev.target===iframeDocument||ev.target.ownerDocument===iframeDocument;if(ev.target.contains(this.$iframe[0])){this.scrollContainer=ev.target;this.odooEditor.updateToolbarPosition();}else if(scrollInIframe){this.scrollContainer=this.$iframe[0];this.odooEditor.updateToolbarPosition();}}else{return super._onScroll(...arguments);}},_configureToolbar(options){super._configureToolbar(...arguments);if(this.options.inIframe&&!options.snippets){this.$iframe[0].contentDocument.addEventListener('scroll',this._onScroll,true);}},});function getWysiwygIframeContent(params){const assets={cssLibs:[],jsLibs:[],};for(const asset of params.assets){for(const cssLib of asset.cssLibs){assets.cssLibs.push(`<link type="text/css" rel="stylesheet" href="${cssLib}"/>`);}
for(const jsLib of asset.jsLibs){assets.jsLibs.push(`<script type="text/javascript" src="${jsLib}"/>`);}}
return`
        <meta charset="utf-8"/>
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
        ${assets.cssLibs.join('\n')}
        ${assets.jsLibs.join('\n')}

        <script type="text/javascript">
            window.odoo?.define('root.widget', ['@web/legacy/js/public/public_widget'], function (require) {
                'use strict';
                const publicWidget = require('@web/legacy/js/public/public_widget')[Symbol.for("default")];
                const widget = new publicWidget.Widget();
                widget.appendTo(document.body);
                return widget;
            });
        </script>
    </head>
    <body class="o_in_iframe">
        <div id="iframe_target"/>
        <script type="text/javascript">
            window.odoo?.define('web_editor.wysiwyg.iniframe', [], function (require) {
                'use strict';
                if (window.top.${params.updateIframeId}) {
                    window.top.${params.updateIframeId}(${params.avoidDoubleLoad});
                }
            });
        </script>
    </body>`;}
return __exports;});;

/* /website/static/src/js/editor/editor.js */
odoo.define('@website/js/editor/editor',['@web_editor/js/wysiwyg/widgets/link_dialog','@web/core/utils/patch','@website/js/utils','@odoo/owl'],function(require){'use strict';let __exports={};const{LinkDialog}=require("@web_editor/js/wysiwyg/widgets/link_dialog");const{patch}=require("@web/core/utils/patch");const wUtils=require("@website/js/utils")[Symbol.for("default")];const{useEffect}=require('@odoo/owl');patch(LinkDialog.prototype,{setup(){super.setup();useEffect(($link,container)=>{const input=container?.querySelector(`input[name="url"]`);if(!input){return;}
const options={body:$link&&$link[0].ownerDocument.body,urlChosen:()=>this.__onURLInput(),};const unmountAutocompleteWithPages=wUtils.autocompleteWithPages(input,options);return()=>unmountAutocompleteWithPages();},()=>[this.$link,this.linkComponentWrapperRef.el]);}});return __exports;});;

/* /website/static/src/js/editor/add_snippet_dialog.js */
odoo.define('@website/js/editor/add_snippet_dialog',['@web_editor/js/editor/add_snippet_dialog','@web/core/utils/patch','@website/js/text_processing'],function(require){'use strict';let __exports={};const{AddSnippetDialog}=require("@web_editor/js/editor/add_snippet_dialog");const{patch}=require("@web/core/utils/patch");const{applyTextHighlight}=require("@website/js/text_processing");patch(AddSnippetDialog.prototype,{_updateSnippetContent(targetEl){super._updateSnippetContent(...arguments);for(const textEl of targetEl?.querySelectorAll(".o_text_highlight")||[]){applyTextHighlight(textEl);}},});return __exports;});;

/* /website/static/src/js/editor/widget_link.js */
odoo.define('@website/js/editor/widget_link',['@web_editor/js/wysiwyg/widgets/link_tools','@web/core/utils/patch','@web/core/utils/hooks','@odoo/owl','@website/js/utils','@web/core/utils/timing','@web_editor/js/wysiwyg/wysiwyg'],function(require){'use strict';let __exports={};const{LinkTools}=require('@web_editor/js/wysiwyg/widgets/link_tools');const{patch}=require("@web/core/utils/patch");const{useService}=require("@web/core/utils/hooks");const{onWillStart,status,useEffect}=require('@odoo/owl');const wUtils=require("@website/js/utils")[Symbol.for("default")];const{debounce}=require("@web/core/utils/timing");const{Wysiwyg}=require("@web_editor/js/wysiwyg/wysiwyg");const LINK_DEBOUNCE=1000;patch(LinkTools.prototype,{async start(){var def=await super.start(...arguments);this._adaptPageAnchor();return def;},setup(){super.setup();this.websiteService=useService("website");onWillStart(()=>{this._adaptPageAnchor=debounce(this._adaptPageAnchor,LINK_DEBOUNCE);});useEffect((container)=>{const input=container?.querySelector(`input[name="url"]`);if(!input){return;}
const options={classes:{"ui-autocomplete":'o_website_ui_autocomplete'},body:this.$editable[0].ownerDocument.body,urlChosen:this._onAutocompleteClose.bind(this),isDestroyed:()=>status(this)==='destroyed',};const unmountAutocompleteWithPages=wUtils.autocompleteWithPages(input,options);return()=>unmountAutocompleteWithPages();},()=>[this.linkComponentWrapperRef.el]);},_adaptPageAnchor(){const urlInputValue=this.$el.find('input[name="url"]').val();const $pageAnchor=this.$el.find('.o_link_dialog_page_anchor');const showAnchorSelector=(urlInputValue[0]==='/')&&(!urlInputValue.startsWith("/web/content/"));const $selectMenu=this.$el.find('we-selection-items[name="link_anchor"]');if($selectMenu.data("anchor-for")!==urlInputValue){$pageAnchor.toggleClass('d-none',!showAnchorSelector);$selectMenu.empty();if(showAnchorSelector){const always=()=>{const anchor=`#${urlInputValue.split('#')[1]}`;let weTogglerText='\u00A0';if(anchor){const weButtonEls=$selectMenu[0].querySelectorAll('we-button');if(Array.from(weButtonEls).some(el=>el.textContent===anchor)){weTogglerText=anchor;}}
$pageAnchor[0].querySelector('we-toggler').textContent=weTogglerText;};const urlWithoutHash=urlInputValue.split("#")[0];wUtils.loadAnchors(urlWithoutHash,this.$editable[0].ownerDocument.body).then(anchors=>{for(const anchor of anchors){const $option=$('<we-button class="dropdown-item">');$option.text(anchor);$option.data('value',anchor);$selectMenu.append($option);}}).finally(always);}}
$selectMenu.data("anchor-for",urlInputValue);},_isAbsoluteURLInCurrentDomain(url){const res=super._isAbsoluteURLInCurrentDomain(url);if(res){return true;}
const w=this.websiteService.currentWebsite;if(!w){return false;}
let origin;try{origin=new URL(url,window.location.origin).origin;}catch{return false;}
return`${origin}/`.startsWith(w.domain);},_onAutocompleteClose(){this.__onURLInput();},_onURLInput(){super._onURLInput(...arguments);this._adaptPageAnchor();},_onPickSelectOption(ev){if(ev.currentTarget.closest('[name="link_anchor"]')){const anchorValue=$(ev.currentTarget).data('value');const $urlInput=this.$el.find('[name="url"]');let urlInputValue=$urlInput.val();if(urlInputValue.indexOf('#')>-1){urlInputValue=urlInputValue.substr(0,urlInputValue.indexOf('#'));}
$urlInput.val(urlInputValue+anchorValue);this.__onURLInput();}
super._onPickSelectOption(...arguments);},});patch(Wysiwyg.prototype,{_getDelayBlurSelectors(){return super._getDelayBlurSelectors().concat([".ui-autocomplete"]);},});return __exports;});

                    /*******************************************
                    *  Templates                               *
                    *******************************************/

                    odoo.define("web_editor.assets_wysiwyg.bundle.xml", ["@web/core/templates"], function(require) {
                        "use strict";
                        const { checkPrimaryTemplateParents, registerTemplate, registerTemplateExtension } = require("@web/core/templates");
                        /* web_editor.assets_wysiwyg */
                        registerTemplate("web_editor.ConflictDialog", `/web_editor/static/src/js/wysiwyg/conflict_dialog.xml`, `<t t-name="web_editor.ConflictDialog" xml:space="preserve">
            <Dialog size="'xl'" title.translate="Content conflict">
                <div>
                    <div style="color: red;">
                        <p>
                            There is a conflict between your version and the one in the database.
                        </p>
                        <p>
                            The version from the database will be used.
                            If you need to keep your changes, copy the content below and edit the new document.
                        </p>
                        <p style="font-weight: bold;">
                            Warning: after closing this dialog, the version you were working on will be discarded and will never be available anymore.
                        </p>
                    </div>
                </div>
                <t t-out="props.content"/>
            </Dialog>
    </t>
`);
registerTemplate("web_editor.AltDialog", `/web_editor/static/src/js/wysiwyg/widgets/alt_dialog.xml`, `<t t-name="web_editor.AltDialog" xml:space="preserve">
    <Dialog size="'xl'" title.translate="Change media description and tooltip">
        <form action="#">
            <div class="mb-3 row">
                <label class="col-md-3 col-form-label" for="alt" title="'Alt tag' specifies an alternate text for an image, if the image cannot be displayed (slow connection, missing image, screen reader ...).">
                Description <small>(ALT Tag)</small>
                </label>
                <div class="col-md-8">
                    <input class="form-control" t-ref="alt" required="required" t-att-value="props.alt" type="text"/>
                </div>
            </div>
            <div class="mb-3 row">
                <label class="col-md-3 col-form-label" for="title" title="'Title tag' is shown as a tooltip when you hover the picture.">
                Tooltip  <small>(TITLE Tag)</small>
                </label>
                <div class="col-md-8">
                    <input class="form-control" t-ref="tag_title" required="required" t-att-value="props.tag_title" type="text"/>
                </div>
            </div>
        </form>
        <t t-set-slot="footer">
            <button class="btn btn-primary" t-on-click="_confirm">Save</button>
            <button class="btn btn-secondary" t-on-click="_cancel">Discard</button>
        </t>
    </Dialog>
</t>

`);
registerTemplate("web_editor.ChatGPTAlternativesDialog", `/web_editor/static/src/js/wysiwyg/widgets/chatgpt_alternatives_dialog.xml`, `<t t-name="web_editor.ChatGPTAlternativesDialog" xml:space="preserve">
    <Dialog size="'lg'" title.translate="AI Copywriter">
        <div class="md-8">
            <div class="mb-3">
                <t t-foreach="Object.entries(props.alternativesModes)" t-as="alternative" t-key="alternative_index">
                    <button type="button" class="btn me-2 btn-sm btn-info" t-att-class="state.alternativesMode == alternative[0] and state.messagesInProgress ? 'btn-success' : 'btn-info'" t-on-click="switchAlternativesMode" t-att-data-mode="alternative[0]">
                        <t t-out="alternative[1]"/>
                    </button>
                </t>
            </div>
            <div class="list-group">
                <div t-if="state.messagesInProgress" class="d-flex align" t-att-class="{ 'mb-3': state.messages.length }">
                    <img src="/web/static/img/spin.svg" alt="Loading..." class="me-2" style="filter:invert(1); opacity: 0.5; width: 30px; height: 30px;"/>
                    <p class="m-0 text-muted align-self-center">
                        <em t-if="state.messagesInProgress == 1">Generating an alternative...</em>
                        <em t-else="">Generating <t t-out="state.messagesInProgress"/> alternatives...</em>
                    </p>
                </div>
                <t t-foreach="[...state.messages].reverse()" t-as="message" t-key="message.id">
                    <t t-if="message.isError">
                        <div class="list-group-item o-chatgpt-alternative border-danger bg-danger o-message-error" t-att-class="{ 'text-muted': state.currentBatchId != message.batchId }">
                            <t t-out="message.text"/>
                        </div>
                    </t>
                    <t t-else="">
                        <button type="button" class="list-group-item list-group-item-action o-chatgpt-alternative" t-on-click="selectMessage" t-att-data-message-id="message.id" t-att-class="{                                 active: state.selectedMessageId == message.id,                                 'text-muted': state.selectedMessageId != message.id and state.currentBatchId != message.batchId,                             }">
                            <span t-if="message.mode" class="badge bg-secondary float-end"><t t-out="props.alternativesModes[message.mode]"/></span>
                            <t t-out="formatContent(message.text)"/>
                        </button>
                    </t>
                </t>
            </div>
        </div>


        <t t-set-slot="footer">
            <button class="btn btn-primary" t-on-click="_confirm" t-att-disabled="typeof state.selectedMessageId !== 'number'">Insert</button>
            <button class="btn btn-secondary" t-on-click="_cancel">Cancel</button>
        </t>
    </Dialog>
</t>
`);
registerTemplate("web_editor.ChatGPTPromptDialog", `/web_editor/static/src/js/wysiwyg/widgets/chatgpt_prompt_dialog.xml`, `<t t-name="web_editor.ChatGPTPromptDialog" xml:space="preserve">
    <Dialog size="'lg'" title.translate="Generate Text with AI" modalRef="modalRef">
        <div t-foreach="state.messages" t-as="message" t-key="message_index" class="position-relative py-1 px-3" t-att-class="message_index ? 'mt-2' : 'mt-0'">
            <div class="position-relative d-flex flex-shrink-0">
                <div class="d-flex flex-shrink-0" style="flex-basis: 42px; max-width: 42px;">
                    <div class="position-relative bg-view" style="width: 36px; height: 36px;">
                        <img class="w-100 h-100 rounded" t-att-src="message.author === 'user' ? userAvatarUrl : assistantAvatarUrl"/>
                    </div>
                </div>
                <div class="w-100 o-min-width-0">
                    <div class="d-flex flex-wrap align-items-baseline mb-1 lh-1">
                        <strong class="me-1 text-truncate"><t t-esc="message.author === 'user' ? 'You' : 'OdooBot'"/></strong>
                    </div>
                    <div class="position-relative d-flex">
                        <div class="o-min-width-0">
                            <div class="position-relative d-flex">
                                <div class="position-relative overflow-x-auto d-inline-block">
                                    <div class="rounded-bottom-3 position-absolute top-0 start-0 w-100 h-100 border opacity-25" t-att-class="{                                             'border-success bg-success-light': message.author === 'user' and message.isError !== true,                                             'border-info bg-info-light': message.author === 'assistant' and message.isError !== true,                                             'border-danger bg-danger': message.isError,                                         }"/>
                                    <div class="position-relative text-break mb-0 py-2 px-3 align-self-start rounded-end-3 rounded-bottom-3 o-chatgpt-message">

                                        <button t-if="message.author === 'assistant' and 'text' in message and message.isError !== true" t-att-data-message-id="message.id" class="o-message-insert d-block float-end p-1 mb-1 btn btn-info opacity-75 fst-italic ms-3" t-on-click="insertMessage">Insert</button>
                                        <div class="d-inline">

                                            <div t-if="message.author === 'assistant' and !('text' in message)" class="d-flex align">
                                                <img src="/web/static/img/spin.svg" alt="Loading..." class="me-2" style="filter:invert(1); opacity: 0.5; width: 30px; height: 30px;"/>
                                                <p class="m-0 text-muted align-self-center">
                                                    <em>Thinking...</em>
                                                </p>
                                            </div>

                                            <div t-elif="message.isError" class="o-message-error">
                                                <t t-out="message.text"/>
                                            </div>
                                            <t t-else="">
                                                <t t-out="formatContent(message.text)"/>
                                            </t>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div t-if="!state.messages.length" style="min-height: 150px;"/> 


        <t t-set-slot="footer">
            <div class="md-8 mb-8 d-flex bg-view flex-grow-1 border rounded-3">
                <div class="o-prompt-input position-relative flex-grow-1">
                    <textarea type="text" id="promptInput" t-ref="promptInput" name="promptInput" t-on-keydown="onTextareaKeydown" class="form-control bg-view px-3 border-0 overflow-auto" placeholder="Send a message" autocomplete="off" t-model="state.prompt" required="required"/>
                </div>
                <div class="border-start-0 rounded-0 rounded-end-3 align-self-center ms-2 me-3">
                    <button class="btn" t-att-class="state.prompt.trim().length ? 'btn-success' : 'disabled'" t-on-click="submitPrompt">
                        <i class="fa fa-paper-plane"/>
                    </button>
                </div>
            </div>
        </t>
    </Dialog>
</t>
`);
registerTemplate("web_editor.ChatGPTTranslateDialog", `/web_editor/static/src/js/wysiwyg/widgets/chatgpt_translate_dialog.xml`, `<t t-name="web_editor.ChatGPTTranslateDialog" xml:space="preserve">
        <Dialog size="'lg'" title.translate="Translate with AI">
            <div t-if="state.translationInProgress" class="d-flex">
                <img src="/web/static/img/spin.svg" alt="Loading..." class="me-2" style="filter:invert(1); opacity: 0.5; width: 30px; height: 30px;"/>
                <p class="m-0 text-muted align-self-center">
                    <em>Translating...</em>
                </p>
            </div>
            <t t-else="">
                <t t-set="message" t-value="state.messages[0]"/>
                <div t-att-data-message-id="message.id" t-att-class="message.isError ? 'o-message-error border-danger bg-danger p-2' : ''" class="o-chatgpt-translated">
                    <t t-out="formatContent(message.text)"/>
                </div>
            </t>

            <t t-set-slot="footer">
                <button class="btn btn-primary" t-att-disabled="state.translationInProgress || state.messages[0].isError" t-on-click="_confirm">Insert</button>
                <button class="btn btn-secondary" t-on-click="_cancel">Cancel</button>
            </t>
        </Dialog>
    </t>
`);
registerTemplate("web_editor.AddSnippetDialog", `/web_editor/static/src/xml/add_snippet_dialog.xml`, `<t t-name="web_editor.AddSnippetDialog" xml:space="preserve">
    <Dialog title.translate="Insert a block" contentClass="'o_add_snippet_dialog h-100'" footer="false" size="'xl'">
        <div class="overflow-hidden w-100">
            <div class="d-flex w-100 h-100 vertical flex-row">
                <aside class="border-end overflow-auto">
                    <div class="d-block position-relative p-2 bg-100 border-bottom">
                        <input type="search" class="form-control bg-white pe-4" placeholder="Search for a block" aria-label="Search for a block" t-model="state.search" t-ref="search-input"/>
                        <span class="input-group-text position-absolute top-50 end-0 translate-middle-y me-2 border-0 bg-transparent text-muted">
                            <i class="oi oi-search" aria-hidden="true"/>
                        </span>
                    </div>

                    <div class="list-group list-group-flush flex-column flex-nowrap overflow-y-auto" role="tablist">
                        <t t-if="!state.search" t-foreach="snippetGroups" t-as="snippetGroup" t-key="snippetGroup.name">
                            <button class="list-group-item list-group-item-light list-group-item-action p-3" role="tab" t-att-class="{ 'active': this.state.groupSelected === snippetGroup.name}" t-on-click="() =&gt; this.state.groupSelected = snippetGroup.name">
                                <t t-out="snippetGroup.displayName"/>
                            </button>
                        </t>
                    </div>
                </aside>
                <div class="position-relative flex-grow-1 flex-shrink-1">
                    <div class="spinner-grow position-absolute top-50 start-50 translate-middle" role="status">
                        <span class="visually-hidden">Loading...</span>
                    </div>
                    <iframe class="border-0 fade bg-200 position-relative o_add_snippet_iframe" tabindex="-1" t-ref="iframe" src="about:blank" height="333%" width="333%"/>
                </div>
            </div>
        </div>
    </Dialog>
</t>

`);
registerTemplate("web_editor.RenameCustomSnippetDialog", `/web_editor/static/src/xml/add_snippet_dialog.xml`, `<t t-name="web_editor.RenameCustomSnippetDialog" xml:space="preserve">
    <Dialog title.translate="Rename the block" contentClass="'o_rename_custom_snippet_dialog'" size="'md'">
        <div class="mb-3 row">
            <label class="col-form-label col-md-2" for="customSnippetName">Name</label>
            <div class="col-md-10">
                <input type="text" class="form-control" id="customSnippetName" t-ref="renameInput" t-attf-value="#{props.currentName}" placeholder="Snippet name"/>
            </div>
        </div>
        <t t-set-slot="footer">
            <button class="btn btn-primary" t-on-click="onClickConfirm">Save</button>
            <button class="btn btn-secondary" t-on-click="onClickDiscard">Discard</button>
        </t>
    </Dialog>
</t>

`);
registerTemplate("web_editor.toolbar", `/web_editor/static/src/xml/editor.xml`, `<t t-name="web_editor.toolbar" xml:space="preserve">
        <div id="toolbar" class="oe-toolbar oe-floating d-print-none">
            <div t-if="props.showStyle" id="style" t-attf-class="btn-group {{ props.dropDirection }}">
                <button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" data-bs-original-title="Text style" tabindex="-1" aria-expanded="false">
                    <span title="Text style">Normal</span>
                </button>
                <ul class="dropdown-menu">
                    <li id="display-1-dropdown-item">
                        <a class="dropdown-item" href="#" id="display-1" data-call="setTag" data-arg1="h1,display-1">Header 1 Display 1</a>
                    </li>
                    <li id="display-2-dropdown-item">
                        <a class="dropdown-item" href="#" id="display-2" data-call="setTag" data-arg1="h1,display-2" data-extended-text-style="">Header 1 Display 2</a>
                    </li>
                    <li id="display-3-dropdown-item">
                        <a class="dropdown-item" href="#" id="display-3" data-call="setTag" data-arg1="h1,display-3" data-extended-text-style="">Header 1 Display 3</a>
                    </li>
                    <li id="display-4-dropdown-item">
                        <a class="dropdown-item" href="#" id="display-4" data-call="setTag" data-arg1="h1,display-4" data-extended-text-style="">Header 1 Display 4</a>
                    </li>
                    <li t-if="props.showHeading1" id="heading1-dropdown-item">
                        <a class="dropdown-item" href="#" id="heading1" data-call="setTag" data-arg1="h1">Header 1</a>
                    </li>
                    <li t-if="props.showHeading2" id="heading2-dropdown-item">
                        <a class="dropdown-item" href="#" id="heading2" data-call="setTag" data-arg1="h2">Header 2</a>
                    </li>
                    <li t-if="props.showHeading3" id="heading3-dropdown-item">
                        <a class="dropdown-item" href="#" id="heading3" data-call="setTag" data-arg1="h3">Header 3</a>
                    </li>
                    <li t-if="props.showHeading4" id="heading4-dropdown-item">
                        <a class="dropdown-item" href="#" id="heading4" data-call="setTag" data-arg1="h4">Header 4</a>
                    </li>
                    <li t-if="props.showHeading5" id="heading5-dropdown-item">
                        <a class="dropdown-item" href="#" id="heading5" data-call="setTag" data-arg1="h5">Header 5</a>
                    </li>
                    <li t-if="props.showHeading6" id="heading6-dropdown-item">
                        <a class="dropdown-item" href="#" id="heading6" data-call="setTag" data-arg1="h6">Header 6</a>
                    </li>
                    <li id="paragraph-dropdown-item">
                        <a class="dropdown-item" href="#" id="paragraph" data-call="setTag" data-arg1="p">Normal</a>
                    </li>
                    <li id="light-dropdown-item">
                        <a class="dropdown-item" href="#" id="light" data-call="setTag" data-arg1="p,lead" data-extended-text-style="">Light</a>
                    </li>
                    <li id="small-dropdown-item">
                        <a class="dropdown-item" href="#" id="small" data-call="setTag" data-arg1="p,o_small" data-extended-text-style="">Small</a>
                    </li>
                    <li id="pre-dropdown-item">
                        <a class="dropdown-item" href="#" id="pre" data-call="setTag" data-arg1="pre">Code</a>
                    </li>
                    <li id="blockquote-dropdown-item">
                        <a class="dropdown-item" href="#" id="blockquote" data-call="setTag" data-arg1="blockquote">Quote</a>
                    </li>
                </ul>
            </div>

            <t t-if="this.isSmall()">
                <button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" title="Decoration" tabindex="-1" data-bs-original-title="Decoration" data-bs-auto-close="outside" aria-expanded="false">
                    <i class="fa fa-bold"/>
                </button>
                <div class="dropdown-menu">
                    <div id="decoration" class="btn-group">
                        <div id="bold" data-call="bold" title="Toggle bold" class="btn fa fa-bold fa-fw"/>
                        <div id="italic" data-call="italic" title="Toggle italic" class="btn fa fa-italic fa-fw"/>
                        <div id="underline" data-call="underline" title="Toggle underline" class="btn fa fa-underline fa-fw"/>
                        <div id="strikethrough" data-call="strikeThrough" title="Toggle strikethrough" class="btn fa fa-strikethrough fa-fw"/>
                    </div>

                    <div t-if="props.showColors" id="colorInputButtonGroup" class="btn-group">
                        <div class="colorpicker-group note-fore-color-preview" data-name="color" t-ref="textColorpickerDropdown" data-color-type="text">
                            <div id="oe-text-color" class="btn color-button dropdown-toggle editor-ignore" data-bs-toggle="dropdown" tabindex="-1">
                                <i class="fa fa-font color-indicator fore-color" title="Font Color"/>
                            </div>
                            <ul class="dropdown-menu colorpicker-menu">
                                <li><ColorPalette t-props="props.textColorPaletteProps"/></li>
                            </ul>
                        </div>
                        <div class="colorpicker-group note-back-color-preview" data-name="color" t-ref="backgroundColorpaletteDropdown" data-color-type="background">
                            <button id="oe-fore-color" type="button" class="btn dropdown-toggle editor-ignore" data-bs-toggle="dropdown" tabindex="-1">
                                <i class="fa fa-paint-brush color-indicator hilite-color" title="Background Color"/>
                            </button>
                            <ul class="dropdown-menu colorpicker-menu">
                                <li><ColorPalette t-props="props.backgroundColorPaletteProps"/></li>
                            </ul>
                        </div>
                    </div>
                </div>
                <div id="removeFormat" data-call="removeFormat" title="Remove format" class="btn fa fa-eraser fa-fw" t-att-class="{ 'd-none': !props.showRemoveFormat }"/>
            </t>
            <t t-else="">
                <div id="decoration" class="btn-group">
                    <div id="bold" data-call="bold" title="Toggle bold" class="btn fa fa-bold fa-fw"/>
                    <div id="italic" data-call="italic" title="Toggle italic" class="btn fa fa-italic fa-fw"/>
                    <div id="underline" data-call="underline" title="Toggle underline" class="btn fa fa-underline fa-fw"/>
                    <div id="strikethrough" data-call="strikeThrough" title="Toggle strikethrough" class="btn fa fa-strikethrough fa-fw"/>
                    <div id="removeFormat" data-call="removeFormat" title="Remove format" class="btn fa fa-eraser fa-fw" t-att-class="{ 'd-none': !props.showRemoveFormat }"/>
                </div>

                <div t-if="props.showColors" id="colorInputButtonGroup" class="btn-group">
                    <div class="colorpicker-group note-fore-color-preview" data-name="color" t-ref="textColorpickerDropdown" data-color-type="text">
                        <div id="oe-text-color" class="btn color-button dropdown-toggle editor-ignore" data-bs-toggle="dropdown" tabindex="-1">
                            <i class="fa fa-font color-indicator fore-color" title="Font Color"/>
                        </div>
                        <ul class="dropdown-menu colorpicker-menu">
                            <li><ColorPalette t-props="props.textColorPaletteProps"/></li>
                        </ul>
                    </div>
                    <div class="colorpicker-group note-back-color-preview" data-name="color" t-ref="backgroundColorpaletteDropdown" data-color-type="background">
                        <button id="oe-fore-color" type="button" class="btn dropdown-toggle editor-ignore" data-bs-toggle="dropdown" tabindex="-1">
                            <i class="fa fa-paint-brush color-indicator hilite-color" title="Background Color"/>
                        </button>
                        <ul class="dropdown-menu colorpicker-menu">
                            <li><ColorPalette t-props="props.backgroundColorPaletteProps"/></li>
                        </ul>
                    </div>
                </div>

                <div t-if="props.useFontSizeInput or props.showFontSize" id="font-size" t-attf-class="btn-group {{ props.dropDirection }}">
                    <button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" tabindex="-1" data-bs-original-title="Font Size" aria-expanded="false">
                        <div id="font-size-input-container">
                            <input type="text" id="fontSizeCurrentValue" title="Font size" value="13" t-att-readonly="props.showFontSize" t-att-class="props.showFontSize ? 'cursor-pointer' : ''"/>
                        </div>
                    </button>
                    <ul class="dropdown-menu">

                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="display-1-font-size" data-apply-class="display-1-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Display 1</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="display-2-font-size" data-apply-class="display-2-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Display 2</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="display-3-font-size" data-apply-class="display-3-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Display 3</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="display-4-font-size" data-apply-class="display-4-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Display 4</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="h1-font-size" data-apply-class="h1-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Heading 1</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="h2-font-size" data-apply-class="h2-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Heading 2</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="h3-font-size" data-apply-class="h3-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Heading 3</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="h4-font-size" data-apply-class="h4-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Heading 4</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="h5-font-size" data-apply-class="h5-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Heading 5</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="h6-font-size" data-apply-class="h6-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Heading 6</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="font-size-base" data-apply-class="base-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Normal</span></a></li>
                        <li><a class="dropdown-item d-flex justify-content-between align-items-center" data-dynamic-value="small-font-size" data-apply-class="o_small-fs" href="#">? <span class="d-none o_we_font_size_badge badge rounded-pill text-bg-dark ms-4">Small</span></a></li>
                    </ul>
                </div>
            </t>

            <div t-if="props.showJustify" id="justify" t-attf-class="btn-group {{ props.dropDirection }}">
                <button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" tabindex="-1" data-bs-original-title="Paragraph" aria-expanded="false">
                    <i id="paragraphDropdownButton" class="fa fa-align-left fa-fw" title="Text align"/>
                </button>
                <div class="dropdown-menu">
                    <div class="btn-group">
                        <div class="btn" id="justifyLeft" data-call="justifyLeft"><i class="fa fa-align-left fa-fw"/></div>
                        <div class="btn" id="justifyCenter" data-call="justifyCenter"><i class="fa fa-align-center fa-fw"/></div>
                        <div class="btn" id="justifyRight" data-call="justifyRight"><i class="fa fa-align-right fa-fw"/></div>
                        <div class="btn" id="justifyFull" data-call="justifyFull"><i class="fa fa-align-justify fa-fw"/></div>
                    </div>
                </div>
            </div>

            <t t-if="this.isSmall()">
                <button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" title="List" tabindex="-1" data-bs-original-title="List" aria-expanded="false">
                    <i class="fa fa-list fa-fw"/>
                </button>
                <div class="dropdown-menu">
                    <div t-if="props.showList" id="list" class="btn-group">
                        <div id="unordered" data-call="toggleList" data-arg1="UL" title="Toggle unordered list" class="oe-toggle-unordered fa fa-list-ul fa-fw btn"/>
                        <div id="ordered" data-call="toggleList" data-arg1="OL" title="Toggle ordered list" class="oe-toggle-ordered fa fa-list-ol fa-fw btn"/>
                        <div t-if="props.showChecklist" id="checklist" data-call="toggleList" data-arg1="CL" title="Toggle checklist" class="oe-toggle-checklist btn fa fa-fw">
                            <div class="small">
                                <div class="fa fa-square-o d-block small"/>
                                <div class="fa fa-check-square d-block small"/>
                            </div>
                        </div>
                    </div>
                </div>
            </t>
            <t t-else="">
                <div t-if="props.showList" id="list" class="btn-group">
                    <div id="unordered" data-call="toggleList" data-arg1="UL" title="Toggle unordered list" class="oe-toggle-unordered fa fa-list-ul fa-fw btn"/>
                    <div id="ordered" data-call="toggleList" data-arg1="OL" title="Toggle ordered list" class="oe-toggle-ordered fa fa-list-ol fa-fw btn"/>
                    <div t-if="props.showChecklist" id="checklist" data-call="toggleList" data-arg1="CL" title="Toggle checklist" class="oe-toggle-checklist btn fa fa-fw">
                        <div class="small">
                            <div class="fa fa-square-o d-block small"/>
                            <div class="fa fa-check-square d-block small"/>
                        </div>
                    </div>
                </div>
            </t>

            <div id="image-preview" class="btn-group">
                <div id="image-fullscreen" title="Full screen" class="fa fa-search-plus btn editor-ignore"/>
            </div>

            <div t-if="props.showLink" id="link" class="btn-group">
                <div id="media-insert" title="Insert media" class="fa fa-file-image-o fa-fw btn editor-ignore"/>

                <div id="unlink" data-call="unlink" title="Remove link" class="fa fa-unlink fa-fw btn order-1"/>
                <div id="create-link" title="Insert or edit link" class="fa fa-link fa-fw btn editor-ignore"/>
                <a id="media-description" href="#" title="Edit media description" class="btn editor-ignore">Description</a>
            </div>

            <div id="chatgpt" class="btn-group">
                <div id="open-chatgpt" title="Generate or transform content with AI" class="btn editor-ignore">
                    <span class="fa fa-magic fa-fw"/>
                </div>
            </div>
            <div t-if="!state.isPublicUser" id="translate" t-attf-class="btn-group {{ props.dropDirection }}">
                <div t-if="state.languages.length === 1" class="btn lang" title="Translate with AI" t-att-data-value="state.languages[0][1]">
                    Translate
                </div>
                <t t-elif="state.languages.length &gt; 1">
                    <button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" data-bs-original-title="Translate with AI" tabindex="-1" aria-expanded="false">
                        <span title="Translate with AI">Translate</span>
                    </button>
                    <ul class="dropdown-menu">
                        <t t-foreach="state.languages" t-as="language" t-key="language[0]">
                            <li><a class="dropdown-item lang" t-att-data-value="language[1]" href="#">to <t t-out="language[1]"/></a></li>
                        </t>
                    </ul>
                </t>
            </div>

            <div t-if="props.showImageShape" id="image-shape" class="btn-group">
                <div id="rounded" title="Shape: Rounded" class="fa fa-square fa-fw btn editor-ignore"/>
                <div id="rounded-circle" title="Shape: Circle" class="fa fa-circle-o fa-fw btn editor-ignore"/>
                <div id="shadow" title="Shadow" class="fa fa-sun-o fa-fw btn editor-ignore"/>
                <div id="img-thumbnail" title="Shape: Thumbnail" class="fa fa-picture-o fa-fw btn editor-ignore"/>
            </div>

            <div t-if="props.showImagePadding" id="image-padding" t-attf-class="btn-group {{ props.dropDirection }}">
                <button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" tabindex="-1" aria-expanded="false">
                    <span class="fa fa-plus-square-o" title="Image padding"/>
                </button>
                <ul class="dropdown-menu">
                    <li><a class="dropdown-item editor-ignore" href="#" data-class="">None</a></li>
                    <li><a class="dropdown-item editor-ignore" href="#" data-class="padding-small">Small</a></li>
                    <li><a class="dropdown-item editor-ignore" href="#" data-class="padding-medium">Medium</a></li>
                    <li><a class="dropdown-item editor-ignore" href="#" data-class="padding-large">Large</a></li>
                    <li><a class="dropdown-item editor-ignore" href="#" data-class="padding-xl">XL</a></li>
                </ul>
            </div>

            <div t-if="props.showImageWidth" id="image-width" class="btn-group">
                <div title="Resize Default" class="btn editor-ignore">Default</div>
                <div id="100%" title="Resize Full" class="btn editor-ignore">100%</div>
                <div id="50%" title="Resize Half" class="btn editor-ignore">50%</div>
                <div id="25%" title="Resize Quarter" class="btn editor-ignore">25%</div>
            </div>

            <div t-if="props.showImageEdit" id="image-edit" class="btn-group">
                <div id="image-crop" title="Crop Image" class="btn fa fa-crop editor-ignore"/>
                <div id="image-transform" class="btn editor-ignore fa fa-object-ungroup" title="Transform the picture (click twice to reset transformation)"/>
                <span class="oe-toolbar-separator d-flex"/>
                <div id="media-replace" title="Replace media" class="btn o_we_bg_success editor-ignore">Replace</div>
                <span class="oe-toolbar-separator d-flex"/>
                <div id="image-delete" class="btn btn-link text-danger editor-ignore fa fa-trash" title="Remove (DELETE)"/>
            </div>

            <div id="fa-resize" class="btn-group only_fa">
                <div class="editor-ignore btn" title="Icon size 1x" data-value="1">1x</div>
                <div class="editor-ignore btn" title="Icon size 2x" data-value="2">2x</div>
                <div class="editor-ignore btn" title="Icon size 3x" data-value="3">3x</div>
                <div class="editor-ignore btn" title="Icon size 4x" data-value="4">4x</div>
                <div class="editor-ignore btn" title="Icon size 5x" data-value="5">5x</div>
            </div>

            <div class="btn-group only_fa">
                <div id="fa-spin" title="Toggle icon spin" class="editor-ignore btn fa fa-play"/>
            </div>

            <div t-if="props.showHistory" id="history" class="btn-group">
                <div id="undo" data-call="undo" class="btn fa fa-undo"/>
                <div id="redo" data-call="redo" class="btn fa fa-repeat"/>
            </div>

            <t t-slot="default"/>
        </div>
    </t>




    `);
registerTemplate("web_editor.toolbar.table-options", `/web_editor/static/src/xml/editor.xml`, `<t t-name="web_editor.toolbar.table-options" xml:space="preserve">
        <we-customizeblock-options id="o-we-editor-table-container">
            <we-title>
                <span>Table Options</span>
                <div id="oe-table-delete-table" data-call="deleteTable" class="o_we_hover_danger">
                    <i class="fa fa-trash"/>
                </div>
            </we-title>
            <div id="oe-table-options">
                <div class="oe-table-row">
                    <span class="oe-table-label">Add Column</span>
                    <div class="w-100">
                        <div class="oe-table-selection btn-group w-100">
                            <button class="btn w-50" data-call="addColumn" data-arg1="before">
                                <i class="small fa fa-fw fa-step-backward"/> Left
                            </button>
                            <button class="btn w-50" data-call="addColumn" data-arg1="after">
                                Right <i class="small fa fa-fw fa-step-forward"/>
                            </button>
                        </div>
                    </div>
                </div>
                <div class="oe-table-row">
                    <span class="oe-table-label">Add Row</span>
                    <div class="w-100">
                        <div class="oe-table-selection btn-group w-100">
                            <button class="btn w-50" data-call="addRow" data-arg1="before">
                                <i class="small fa fa-fw fa-step-backward fa-rotate-90"/> Above
                            </button>
                            <button class="btn w-50" data-call="addRow" data-arg1="after">
                                Below <i class="small fa fa-fw fa-step-forward fa-rotate-90"/>
                            </button>
                        </div>
                    </div>
                </div>
                <div class="oe-table-row mt-3">
                    <span class="oe-table-label">Remove Current</span>
                    <div class="w-100">
                        <div class="oe-table-selection btn-group w-100">
                            <button class="btn w-50" data-call="removeColumn">
                                <i class="small fa fa-fw fa-columns"/> Column
                            </button>
                            <button class="btn w-50" data-call="removeRow">
                                <i class="small fa fa-fw fa-bars"/> Row
                            </button>
                        </div>
                    </div>
                </div>
                 <div class="oe-table-row mt-3">
                    <span class="oe-table-label"/>
                    <div class="w-100">
                        <div class="oe-table-selection btn-group w-100">
                            <button class="btn w-50" data-call="resetSize">
                                <i class="small fa fa-fw fa-table"/> Reset Size
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </we-customizeblock-options>
    </t>






    `);
registerTemplate("web_editor.background_position_overlay", `/web_editor/static/src/xml/editor.xml`, `<t t-name="web_editor.background_position_overlay" xml:space="preserve">
        <div class="o_we_background_position_overlay oe_overlay">
            <div class="o_we_overlay_content position-absolute">
                <div class="o_overlay_background"/>
                <div class="o_we_overlay_buttons position-absolute d-flex m-1" style="top: 0">
                    <button class="btn btn-primary me-1 o_btn_apply">Apply</button>
                    <button class="btn btn-danger o_btn_discard">Discard</button>
                </div>
            </div>
        </div>
    </t>
`);
registerTemplate("web_editor.background_grid", `/web_editor/static/src/xml/grid_layout.xml`, `<t t-name="web_editor.background_grid" xml:space="preserve">
    <div t-attf-style="grid-area: 1 / 1 / #{rowCount} / -1;" class="o_we_background_grid">
        <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
            <defs>
                <pattern id="cell" t-attf-width="#{columnSize + columnGap}px" t-attf-height="#{rowSize + rowGap}px" patternUnits="userSpaceOnUse">
                    <rect class="o_we_cell" x="2" y="2" rx="4" t-attf-width="#{columnSize - 4}px" t-attf-height="#{rowSize - 4}px"/>
                </pattern>
            </defs>

            <rect fill="url(#cell)" width="100%" height="100%"/>
        </svg>
    </div>
</t>

`);
registerTemplate("web_editor.snippet_overlay", `/web_editor/static/src/xml/snippets.xml`, `<t t-name="web_editor.snippet_overlay" xml:space="preserve">
        <div class="oe_overlay o_handlers_idle">
            <div class="o_handles">

                <div class="o_handle o_column_handle o_side o_side_y n readonly"><span class="o_handle_indicator"/></div>
                <div class="o_handle o_column_handle o_side o_side_x e readonly"><span class="o_handle_indicator"/></div>
                <div class="o_handle o_column_handle o_side o_side_x w readonly"><span class="o_handle_indicator"/></div>
                <div class="o_handle o_column_handle o_side o_side_y s readonly"><span class="o_handle_indicator"/></div>


                <div class="o_handle o_grid_handle o_side o_side_y n d-none"><span class="o_handle_indicator"/></div>
                <div class="o_handle o_grid_handle o_side o_side_x e d-none"><span class="o_handle_indicator"/></div>
                <div class="o_handle o_grid_handle o_side o_side_x w d-none"><span class="o_handle_indicator"/></div>
                <div class="o_handle o_grid_handle o_side o_side_y s d-none"><span class="o_handle_indicator"/></div>
                <div class="o_handle o_grid_handle o_corner_handle ne d-none"><span class="o_handle_indicator"/></div>
                <div class="o_handle o_grid_handle o_corner_handle nw d-none"><span class="o_handle_indicator"/></div>
                <div class="o_handle o_grid_handle o_corner_handle se d-none"><span class="o_handle_indicator"/></div>
                <div class="o_handle o_grid_handle o_corner_handle sw d-none"><span class="o_handle_indicator"/></div>

                <div class="o_overlay_options_wrap">

                    <div class="o_overlay_move_options">

                        <div class="o_front_back o_send_back d-none"/>
                        <div class="o_front_back o_bring_front d-none"/>
                        <div class="o_move_handle fa fa-arrows"/>
                    </div>
                    <div class="o_overlay_edit_options">
                        <button class="o_snippet_replace o_we_bg_warning fa fa-exchange d-none"/>
                        <button class="oe_snippet_remove o_we_bg_danger fa fa-trash"/>
                    </div>
                </div>
            </div>
        </div>
    </t>
    `);
registerTemplate("web_editor.customize_block_options_section", `/web_editor/static/src/xml/snippets.xml`, `<t t-name="web_editor.customize_block_options_section" xml:space="preserve">
        <we-customizeblock-options>
            <we-title>
                <span t-esc="name"/>
                <we-top-button-group>
                    <we-button class="fa fa-fw fa-clone oe_snippet_clone o_we_link o_we_hover_success" title="Duplicate Container" aria-label="Duplicate Container"/>
                    <we-button class="fa fa-fw fa-trash oe_snippet_remove o_we_link o_we_hover_danger" title="Remove Block" aria-label="Remove Block"/>
                </we-top-button-group>
            </we-title>
        </we-customizeblock-options>
    </t>
    `);
registerTemplate("web_editor.outdated_block_message", `/web_editor/static/src/xml/snippets.xml`, `<t t-name="web_editor.outdated_block_message" xml:space="preserve">
        <we-alert class="d-flex flex-column p-3 pt-4 align-items-center text-center text-white">
            <we-title>This block is outdated.</we-title>
            <span>You might not be able to customize it anymore.</span>
            <we-button class="o_we_bg_brand_primary py-2 my-4 border-0" data-no-preview="true" data-replace-snippet="">REPLACE BY NEW VERSION</we-button>
            <span>You can still access the block options but it might be ineffective.</span>
            <we-button class="o_we_bg_brand_primary py-2 my-4 border-0" data-no-preview="true" data-discard-alert="">ACCESS OPTIONS ANYWAY</we-button>
        </we-alert>
    </t>


    `);
registerTemplate("web_editor.ColorPalette", `/web_editor/static/src/xml/snippets.xml`, `<div t-name="web_editor.ColorPalette" class="colorpicker" t-ref="el" t-on-click="this._onColorpickerClick" xml:space="preserve">
        <div class="o_we_colorpicker_switch_panel d-flex justify-content-end px-2">
            <t t-set="first_button_name"><t t-if="props.withCombinations">Theme</t><t t-else="">Solid</t></t>
            <button type="button" tabindex="1" class="o_we_colorpicker_switch_pane_btn" t-attf-data-target="#{props.withCombinations ? 'color-combinations' : 'theme-colors'}" t-att-title="first_button_name" t-on-click="this._onSwitchPaneButtonClick">
                <span t-out="first_button_name"/>
            </button>
            <button type="button" tabindex="2" class="o_we_colorpicker_switch_pane_btn" data-target="custom-colors" title="Custom" t-on-click="this._onSwitchPaneButtonClick">
                <span>Custom</span>
            </button>
            <button type="button" tabindex="3" class="o_we_colorpicker_switch_pane_btn" data-target="gradients" title="Gradient" t-on-click="this._onSwitchPaneButtonClick">
                <span>Gradient</span>
            </button>
            <t t-if="props.resetButton">
                <t t-set="trash_title"><t t-if="props.withCombinations">None</t><t t-else="">Reset</t></t>
                <button type="button" class="fa fa-trash my-1 ms-5 py-0 o_we_color_btn o_colorpicker_reset o_we_hover_danger" t-att-title="trash_title"/>
            </t>
        </div>
        <div class="o_colorpicker_sections pt-2 px-2 pb-3" data-color-tab="color-combinations">

            <t t-foreach="[1, 2, 3, 4, 5]" t-as="number" t-key="number">
                <button type="button" class="o_we_color_btn o_we_color_combination_btn" t-att-data-color="number" t-attf-title="Preset #{number}">
                    <t t-call="web_editor.color.combination.preview"/>
                </button>
            </t>
        </div>
        <div class="o_colorpicker_sections py-3 px-2" data-color-tab="theme-colors"/>
        <div class="o_colorpicker_sections py-3 px-2" data-color-tab="custom-colors">
            <div class="o_colorpicker_section_container"/>
            <t t-if="!this.props.excluded.includes('custom')">
                <Colorpicker document="this.props.document" defaultColor="this.state.customDefaultColor" noTransparency="!!this.props.noTransparency" selectedColor="this.state.customSelectedColor" onColorSelect.bind="_onColorPickerSelect" onColorPreview.bind="_onColorPickerPreview" onInputEnter="props.onInputEnter"/>
            </t>
        </div>
        <div class="o_colorpicker_sections py-3 px-2" data-color-tab="gradients">
            <div class="o_colorpicker_section_container"/>
            <t t-if="state.showGradientPicker">
                <Colorpicker document="this.props.document" stopClickPropagation="true" selectedColor="this.state.gradientSelectedColor" onColorSelect.bind="_onColorPickerSelectGradient" onColorPreview.bind="_onColorPickerPreviewGradient" onInputEnter="props.onInputEnter"/>
            </t>
        </div>
    </div>
    `);
registerTemplate("web_editor.color.combination.preview", `/web_editor/static/src/xml/snippets.xml`, `<t t-name="web_editor.color.combination.preview" xml:space="preserve">
        <div class="o_we_cc_preview_wrapper d-flex justify-content-between">
            <h1 class="o_we_color_combination_btn_title">Title</h1>
            <p class="o_we_color_combination_btn_text flex-grow-1">Text</p>
            <span class="o_we_color_combination_btn_btn btn btn-sm btn-primary o_btn_preview me-1"><small>Button</small></span>
            <span class="o_we_color_combination_btn_btn btn btn-sm btn-secondary o_btn_preview"><small>Button</small></span>
        </div>
    </t>
    `);
registerTemplate("web_editor.color.combination.preview.legacy", `/web_editor/static/src/xml/snippets.xml`, `<t t-name="web_editor.color.combination.preview.legacy" xml:space="preserve">
        <div class="o_we_cc_preview_wrapper d-flex justify-content-between">
            <h1 class="o_we_color_combination_btn_title">Title</h1>
            <p class="o_we_color_combination_btn_text flex-grow-1">Text</p>
            <span class="o_we_color_combination_btn_btn btn btn-sm btn-primary o_btn_preview me-1"><small>Button</small></span>
            <span class="o_we_color_combination_btn_btn btn btn-sm btn-secondary o_btn_preview"><small>Button</small></span>
        </div>
    </t>

    `);
registerTemplate("web_editor.SnippetsMenu", `/web_editor/static/src/xml/snippets.xml`, `<t t-name="web_editor.SnippetsMenu" xml:space="preserve">
        <div id="oe_snippets" t-ref="snippets-menu" t-on-mousedown="_onMouseDown">
            <div class="o_we_website_top_actions">
                <div class="o_we_external_history_buttons d-flex">
                    <button type="button" t-on-click="_onUndo" class="btn btn-secondary fa fa-undo" t-att-disabled="!state.canUndo"/>
                    <button type="button" t-on-click="_onRedo" class="btn btn-secondary fa fa-repeat" t-att-disabled="!state.canRedo"/>
                </div>
                <form class="ms-auto d-flex">
                    <button type="button" t-on-click="_onDiscardClick" class="btn btn-secondary" data-action="cancel" title="Tip: Esc to preview" accesskey="j">Discard</button>
                    <button type="button" t-on-click="_onSaveRequest" class="btn btn-primary" data-action="save" accesskey="s">Save</button>
                </form>
            </div>
            <div id="snippets_menu">
                <button type="button" tabindex="1" t-on-click="_onBlocksTabClick" t-att-class="{ 'active': state.currentTab === constructor.tabs.BLOCKS }" class="o_we_add_snippet_btn text-uppercase" accesskey="1">
                    <span>Blocks</span>
                </button>
                <button type="button" tabindex="2" t-on-click="_onOptionsTabClick" t-att-class="{ 'active': state.currentTab === constructor.tabs.OPTIONS }" class="o_we_customize_snippet_btn text-uppercase">
                    <span>Customize</span>
                </button>
            </div>

            <div t-if="!this.hasSnippetGroups" class="o_snippet_search_filter" t-att-class="{ 'd-none': state.currentTab !== constructor.tabs.BLOCKS }">
                <input type="text" class="o_snippet_search_filter_input" t-ref="search-input" t-model="state.search" placeholder="Search for a block (e.g. numbers, image wall, ...)"/>
                <i role="button" class="fa fa-times o_snippet_search_filter_reset" t-att-class="{ 'd-none': state.search === ''}" t-on-click="() =&gt; state.search = ''"/>
            </div>

            <div id="o_scroll" t-ref="snippets-area" t-att-class="{ 'd-none': state.currentTab !== constructor.tabs.BLOCKS }">
                <t t-set="disabledTooltip">This block cannot be dropped anywhere on this page.</t>
                <t t-foreach="getSnippetsByCategories()" t-as="category" t-key="category.id">
                    <div t-att-id="category.id" t-if="category_value.length &gt; 0" class="o_panel">
                        <div class="o_panel_header">
                            <span t-esc="category.text"/>
                        </div>
                        <div t-att-id="category.id === 'snippet_custom' ? 'snippet_custom_body' : ''" class="o_panel_body" t-on-pointerup="_onMouseUp">
                            <t t-foreach="category_value" t-as="snippet" t-key="snippet.key">
                                <div t-if="snippet.visible" class="oe_snippet" t-att-class="{ 'o_disabled': snippet.disabled, 'o_snippet_install': snippet.installable, 'o_we_draggable': !snippet.renaming and !snippet.installable and !snippet.disabled }" t-att-name="snippet.displayName" t-att-data-oe-snippet-id="snippet.id" t-att-data-module-id="snippet.moduleId" t-att-data-module-display-name="snippet.moduleDisplayName" t-on-click="this._onSnippetClick" t-att-data-tooltip="snippet.disabled ? disabledTooltip : false" t-att-data-snippet-group="snippet.snippetGroup" t-att-data-snippet-key="snippet.key">
                                    <t t-if="snippet.disabled">
                                        <img src="/web_editor/static/src/img/snippet_disabled.svg" class="o_snippet_undroppable"/>
                                    </t>
                                    <div class="oe_snippet_thumbnail" t-att-class="{ 'o_we_ongoing_insertion': snippet.renaming }" t-att-data-snippet="snippet.baseBody.dataset.snippet">
                                        <div class="oe_snippet_thumbnail_img" t-attf-style="background-image: url({{snippet.thumbnailSrc}});"/>
                                        <t t-if="snippet.isCustom and snippet.renaming">
                                            <we-input class="o_we_user_value_widget w-100 mx-1">
                                                <div>
                                                    <input type="text" autocomplete="chrome-off" t-att-value="snippet.displayName" class="text-start"/>
                                                    <we-button class="o_we_confirm_btn o_we_text_success fa fa-check" data-tooltip="Confirm" t-on-click="_onConfirmRename"/>
                                                    <we-button class="o_we_cancel_btn o_we_text_danger fa fa-times" data-tooltip="Cancel" t-on-click="() =&gt; snippet.renaming = false"/>
                                                </div>
                                            </we-input>
                                        </t>
                                        <t t-else="">
                                            <span class="oe_snippet_thumbnail_title"><t t-out="snippet.displayName"/></span>
                                        </t>
                                        <t t-if="snippet.installable">
                                            <button class="btn btn-primary o_install_btn w-100" t-on-click="_onInstallBtnClick">Install</button>
                                        </t>
                                    </div>
                                    <t t-if="snippet.isCustom and !snippet.renaming">

                                        <we-button class="o_rename_btn fa fa-pencil btn o_we_hover_success" t-att-data-tooltip="snippet.renameTitle" t-att-data-snippet-key="snippet.key" t-on-click.stop="_onRenameBtnClick" t-on-pointerup.stop=""/>
                                        <we-button class="o_delete_btn fa fa-trash btn o_we_hover_danger" t-att-data-tooltip="snippet.deleteTitle" t-att-data-snippet-key="snippet.key" t-on-click.stop="_onDeleteBtnClick" t-on-pointerup.stop=""/>
                                    </t>
                                </div>
                            </t>
                        </div>
                    </div>
                </t>
            </div>
            <div class="o_we_customize_panel" t-ref="customize-panel" t-att-class="{ 'd-none': state.currentTab === constructor.tabs.BLOCKS }">
                <we-customizeblock-options id="o_we_editor_toolbar_container" t-att-class="{ 'd-none': !state.showToolbar }">
                    <we-title>
                        <span t-out="state.toolbarTitle"/>
                        <div id="removeFormat" data-call="removeFormat" title="Remove format" class="btn fa fa-eraser fa-fw"/>
                    </we-title>
                    <div class="o_we_toolbar_wrapper" t-ref="toolbar-wrapper" style="display: contents;">
                        <Toolbar t-props="options.wysiwyg.state.toolbarProps">
                            <t t-if="options.wysiwyg.state.linkToolProps">
                                <LinkTools t-props="options.wysiwyg.state.linkToolProps"/>
                            </t>
                        </Toolbar>
                    </div>
                </we-customizeblock-options>
                <t t-call="web_editor.toolbar.table-options"/>
            </div>
            <div t-if="state.invisibleElements.length" class="o_we_invisible_el_panel">
                <div class="o_panel_header">
                    Invisible Elements
                </div>
                <t t-foreach="state.invisibleElements" t-as="invisibleEntry" t-key="invisibleEntry_index">
                    <t t-call="web_editor.invisibleSnippetEntry" t-call-context="{'entry': invisibleEntry, 'menu': this}"/>
                </t>
            </div>
        </div>
    </t>

    `);
registerTemplate("web_editor.invisibleSnippetEntry", `/web_editor/static/src/xml/snippets.xml`, `<t t-name="web_editor.invisibleSnippetEntry" xml:space="preserve">
        <div class="o_we_invisible_entry d-flex align-items-center justify-content-between" t-att-class="{'o_we_invisible_root_parent': entry.isRootParent, 'o_we_sublevel_1': entry.isDescendant}" t-on-click="() =&gt; menu.onInvisibleEntryClick(entry)">
            <we-title t-out="entry.name"/>
            <i class="fa ms-2" t-att-class="entry.isVisible ? 'fa-eye' : 'fa-eye-slash'"/>
        </div>
        <ul t-if="entry.children.length &gt; 0">
            <t t-foreach="entry.children" t-as="child" t-key="child_index">
                <li>
                    <t t-call="web_editor.invisibleSnippetEntry" t-call-context="{'entry': child, menu}"/>
                </li>
            </t>
        </ul>
    </t>

`);
registerTemplate("web_editor.Wysiwyg", `/web_editor/static/src/xml/wysiwyg.xml`, `<t t-name="web_editor.Wysiwyg" xml:space="preserve">
        <div style="display: contents;" t-ref="toolbar">
            <Toolbar t-props="this.state.toolbarProps" t-if="this.state.showToolbar"/>
        </div>
        <div style="display: contents;" t-ref="imageCrop">
            <ImageCrop t-props="this.imageCropProps"/>
        </div>
        <div t-ref="el"/>

        <div t-ref="snippets-menu-container">
            <t t-if="this.state.showSnippetsMenu" t-component="this.snippetsMenuComponent" options="this.snippetsMenuOptions" folded="this.state.snippetsMenuFolded" setCSSVariables.bind="this.setCSSVariables" trigger_up="(ev) =&gt; this._trigger_up(ev)" mountedProm="this.state.snippetsMenuMountedProm" bus="this.snippetsMenuBus"/>
        </div>
    </t>






    `);
registerTemplate("web_editor.LinkDialog", `/web_editor/static/src/xml/wysiwyg.xml`, `<div t-name="web_editor.LinkDialog" xml:space="preserve">
        <Dialog size="'xl'" title.translate="Insert a Link / Button">
            <div class="o_link_dialog">
                <div class="row" t-ref="linkComponentWrapper">
                    <form class="col-lg-8">
                        <div t-attf-class="mb-3 row#{props.needLabel ? '' : ' d-none'}">
                            <label class="col-form-label col-md-3" for="o_link_dialog_label_input">Link Label</label>
                            <div class="col-md-9">
                                <input type="text" name="label" class="form-control" id="o_link_dialog_label_input" required="required" t-ref="inputText"/>
                            </div>
                        </div>
                        <div t-attf-class="mb-3 row o_url_input#{state.isButton ? ' d-none' : ''}">
                            <label class="col-form-label col-md-3" for="o_link_dialog_url_input">URL or Email</label>
                            <div class="col-md-9">
                                <input type="text" name="url" class="form-control" id="o_link_dialog_url_input" required="required" t-ref="inputUrl" t-on-keydown="onUrlKeydown"/>
                                <div class="form-check o_strip_domain d-none">
                                    <input type="checkbox" id="o_link_dialog_url_strip_domain" checked="checked" class="form-check-input"/>
                                    <label for="o_link_dialog_url_strip_domain" class="form-check-label fw-normal">
                                        Autoconvert to relative link
                                    </label>
                                </div>
                            </div>
                        </div>
                        <div class="mb-3 row">
                            <label class="col-form-label col-md-3">Style</label>
                            <div class="col-md-9 d-flex align-items-center">
                                <div t-attf-class="#{this.colorCombinationClass ? ('p-2 ' + this.colorCombinationClass) : ''}">
                                    <select name="link_style_color" class="form-select link-style">
                                        <t t-foreach="this.colorsData" t-as="colorData" t-key="colorData.type">
                                            <t t-if="colorData.type !== 'custom'">
                                                <option t-att-value="colorData.type" t-attf-class="o_btn_preview dropdown-item">
                                                    <span t-esc="colorData.label"/>
                                                </option>
                                            </t>
                                        </t>
                                    </select>
                                </div>
                            </div>
                        </div>
                        <div id="o_link_dialog_button_opts_collapse" class="collapse">
                            <div class="mb-3 row">
                                <label class="col-form-label col-md-3">Size</label>
                                <div class="col-md-9">
                                    <select name="link_style_size" class="form-select link-style">
                                        <option value="sm">Small</option>
                                        <option value="" selected="selected">Medium</option>
                                        <option value="lg">Large</option>
                                    </select>
                                </div>
                            </div>
                            <div class="mb-3 row">
                                <label class="col-form-label col-md-3">Layout</label>
                                <div class="col-md-9">
                                    <select name="link_style_shape" class="form-select link-style">
                                        <option value="" selected="selected">Default</option>
                                        <option value="rounded-circle">Default + Rounded</option>
                                        <option value="outline">Outline</option>
                                        <option value="outline,rounded-circle">Outline + Rounded</option>
                                        <option value="fill">Fill</option>
                                        <option value="fill,rounded-circle">Fill + Rounded</option>
                                        <option value="flat">Flat</option>
                                    </select>
                                </div>
                            </div>
                        </div>
                        <div class="mb-3 row" t-if="!state.isButton and !props.forceNewWindow">
                            <div class="offset-md-3 col-md-9">
                                <label class="o_switch">
                                    <input type="checkbox" name="is_new_window" t-att-checked="this.initialNewWindow ? 'checked' : undefined"/>
                                    <span/>
                                    Open in new window
                                </label>
                            </div>
                        </div>
                    </form>
                    <div class="col-lg-4 o_link_dialog_preview">
                        <div class="mb-3 text-center">
                            <label>Preview</label>
                            <div t-attf-class="#{this.colorCombinationClass ? ('p-2 ' + this.colorCombinationClass) : ''}" style="overflow-x: auto; max-width: 100%; max-height: 200px;">
                                <a href="#" id="link-preview" aria-label="Preview" title="Preview"/>
                            </div>
                        </div>
                    </div>
                </div>
                <t t-set-slot="footer">
                    <button class="btn btn-primary" t-on-click="this.onSave" data-hotkey="c">Apply</button>
                    <button class="btn btn-secondary" t-on-click="this.onDiscard" data-hotkey="j">Discard</button>
                </t>
            </div>
        </Dialog>
    </div>

    `);
registerTemplate("web_editor.LinkTools", `/web_editor/static/src/xml/wysiwyg.xml`, `<we-customizeblock-option t-name="web_editor.LinkTools" xml:space="preserve">
        <div style="display: contents" t-ref="linkComponentWrapper">
            <we-row id="url_row" t-attf-class="#{state.isButton ? ' d-none' : ''}">
                <we-input class="o_we_user_value_widget o_we_sublevel_1">
                    <we-title class="o_short_title"/>
                    <div class="o_url_input">
                        <input name="url" id="o_link_dialog_url_input" type="text" placeholder="Your URL"/>
                        <we-button class="o_we_user_value_widget fa fa-upload" t-on-click="this.uploadFile" data-tooltip="Link to an uploaded document"/>
                    </div>
                </we-input>
            </we-row>
            <we-row class="o_strip_domain d-none" t-attf-class="#{state.isButton ? ' d-none' : ''}">
                <we-button class="o_we_user_value_widget o_we_checkbox_wrapper o_we_sublevel_1 active">
                    <we-title class="o_long_title">Autoconvert to Relative Link</we-title>
                        <div class="o_switch">
                            <we-checkbox name="do_strip_domain"/>
                        </div>
                </we-button>
            </we-row>
            <we-row t-attf-class="o_we_sublevel_1 {{props.needLabel ? '' : 'd-none'}}">
                <we-title>Label</we-title>
                <we-input class="o_we_user_value_widget">
                    <div>
                        <input name="label" id="o_link_dialog_label_input" type="text"/>
                    </div>
                </we-input>
            </we-row>
            <we-row>
                <we-select class="o_we_user_value_widget o_we_sublevel_1">
                    <we-title>Style</we-title>
                    <div class="dropdown">
                        <button class="dropdown-toggle" data-bs-toggle="dropdown" tabindex="-1" aria-expanded="false">
                            <we-toggler title="Link Style"/>
                        </button>
                        <we-selection-items class="dropdown-menu" name="link_style_color">
                            <t t-foreach="this.colorsData" t-as="colorData" t-key="colorData.type">
                                <we-button class="dropdown-item" href="#" t-att-data-value="colorData.type">
                                    <t t-esc="colorData.label"/>
                                </we-button>
                            </t>
                        </we-selection-items>
                        <span class="o_we_dropdown_caret"/>
                    </div>
                </we-select>
            </we-row>
            <we-row class="link-custom-color link-custom-color-text" t-att-class="{'d-none': !state.showLinkCustomColor}">
                <we-select title="Color" class="o_we_user_value_widget o_we_so_color_palette o_we_sublevel_2">
                    <we-title>Text Color</we-title>
                    <div class="dropdown">
                        <span data-bs-toggle="dropdown" data-css-property="color" class="o_we_color_preview"/>
                        <we-selection-items class="dropdown-menu" name="link_text_color">
                            <ColorPalette selectedColor="colorpickerProps['color'].selectedColor" excluded="['transparent_grayscale']" document="this.props.wysiwyg.options.document" onSetColorNames="(colorNames) =&gt; this._onColorpaletteSetColorNames('color', colorNames)" onColorHover="(params) =&gt; this._colorpaletteApply('color', params)" onColorLeave="(params) =&gt; this._colorpaletteApply('color', params)" onColorPicked="(params) =&gt; this._onColorpaletteColorPicked('color', params)" onCustomColorPicked="(params) =&gt; this._onColorpaletteColorPicked('color', params)" getTemplate="this.props.getColorpickerTemplate"/>
                        </we-selection-items>
                    </div>
                </we-select>
            </we-row>
            <we-row class="link-custom-color link-custom-color-fill" t-att-class="{'d-none': !state.showLinkCustomColor}">
                <we-select title="Color" class="o_we_user_value_widget o_we_so_color_palette o_we_sublevel_2">
                    <we-title>Fill Color</we-title>
                    <div class="dropdown">
                        <span data-bs-toggle="dropdown" data-css-property="background-color" class="o_we_color_preview"/>
                        <we-selection-items class="dropdown-menu" name="link_fill_color">
                            <ColorPalette selectedColor="colorpickerProps['background-color'].selectedColor" excluded="['transparent_grayscale']" document="this.props.wysiwyg.options.document" withGradients="true" onSetColorNames="(colorNames) =&gt; this._onColorpaletteSetColorNames('background-color', colorNames)" onColorHover="(params) =&gt; this._colorpaletteApply('background-color', params)" onColorLeave="(params) =&gt; this._colorpaletteApply('background-color', params)" onColorPicked="(params) =&gt; this._onColorpaletteColorPicked('background-color', params)" onCustomColorPicked="(params) =&gt; this._onColorpaletteColorPicked('background-color', params)" getTemplate="this.props.getColorpickerTemplate"/>
                        </we-selection-items>
                    </div>
                </we-select>
            </we-row>
            <we-row class="link-custom-color link-custom-color-border o_we_sublevel_2" t-att-class="{'d-none': !state.showLinkCustomColor}">
                <we-title>Border</we-title>
                <div>
                    <we-input class="o_we_user_value_widget" title="Border Width">
                        <div class="o_custom_border_width_input">
                            <input name="custom_border_width" type="number" class="text-end" size="2"/>
                            <span>px</span>
                        </div>
                    </we-input>
                    <we-select class="o_we_user_value_widget" title="Border Style">
                        <div class="dropdown">
                            <button class="dropdown-toggle" data-bs-toggle="dropdown" title="" tabindex="-1" data-bs-original-title="Link Border Style" aria-expanded="false">
                                <we-toggler/>
                            </button>
                            <we-selection-items class="dropdown-menu" name="link_border_style">
                                <we-button title="Solid" class="dropdown-item" data-value="solid"><div class="o_we_fake_img_item o_we_border_preview" style="border-style: solid;"/></we-button>
                                <we-button title="Dashed" class="dropdown-item" data-value="dashed"><div class="o_we_fake_img_item o_we_border_preview" style="border-style: dashed;"/></we-button>
                                <we-button title="Dotted" class="dropdown-item" data-value="dotted"><div class="o_we_fake_img_item o_we_border_preview" style="border-style: dotted;"/></we-button>
                                <we-button title="Double" class="dropdown-item" data-value="double"><div class="o_we_fake_img_item o_we_border_preview" style="border-style: double; border-left: none; border-right: none;"/></we-button>
                            </we-selection-items>
                        </div>
                    </we-select>
                    <we-select title="Border Color" class="o_we_user_value_widget o_we_so_color_palette">
                        <div class="dropdown">
                            <span data-bs-toggle="dropdown" data-css-property="border-color" class="o_we_color_preview"/>
                            <we-selection-items class="dropdown-menu" name="link_border_color">
                                <ColorPalette selectedColor="colorpickerProps['border-color'].selectedColor" excluded="['transparent_grayscale']" document="this.props.wysiwyg.options.document" onSetColorNames="(colorNames) =&gt; this._onColorpaletteSetColorNames('border-color', colorNames)" onColorHover="(params) =&gt; this._colorpaletteApply('border-color', params)" onColorLeave="(params) =&gt; this._colorpaletteApply('border-color', params)" onColorPicked="(params) =&gt; this._onColorpaletteColorPicked('border-color', params)" onCustomColorPicked="(params) =&gt; this._onColorpaletteColorPicked('border-color', params)" getTemplate="this.props.getColorpickerTemplate"/>
                            </we-selection-items>
                        </div>
                    </we-select>
                </div>
            </we-row>
            <we-row class="link-size-row" t-att-class="{'d-none': !state.showLinkSizeRow}">
                <we-select class="o_we_user_value_widget o_we_sublevel_2">
                    <we-title>Size</we-title>
                    <div>
                        <div class="dropdown">
                            <button class="dropdown-toggle" data-bs-toggle="dropdown" title="" tabindex="-1" aria-expanded="false">
                                <we-toggler title="Link Size">
                                    Medium
                                </we-toggler>
                            </button>
                            <we-selection-items name="link_style_size" class="dropdown-menu link-style">
                                <we-button class="dropdown-item" href="#" data-value="sm">
                                    Small
                                </we-button>
                                <we-button class="dropdown-item active" href="#" data-value="">
                                    Medium
                                </we-button>
                                <we-button class="dropdown-item" href="#" data-value="lg">
                                    Large
                                </we-button>
                            </we-selection-items>
                            <span class="o_we_dropdown_caret"/>
                        </div>
                    </div>
                </we-select>
            </we-row>
            <we-row class="link-shape-row" t-att-class="{'d-none': !state.showLinkShapeRow}">
                <we-select class="o_we_user_value_widget o_we_sublevel_2">
                    <we-title>Shape</we-title>
                    <div>
                        <div class="dropdown">
                            <button class="dropdown-toggle" data-bs-toggle="dropdown" tabindex="-1" aria-expanded="false">
                                <we-toggler title="Link Shape">
                                    Default
                                </we-toggler>
                            </button>
                            <we-selection-items name="link_style_shape" class="dropdown-menu link-style">
                                <we-button class="dropdown-item active" data-value="">Default</we-button>
                                <we-button class="dropdown-item" data-value="rounded-circle">Default + Rounded</we-button>
                                <we-button class="dropdown-item" data-value="outline">Outline</we-button>
                                <we-button class="dropdown-item" data-value="outline,rounded-circle">Outline + Rounded</we-button>
                                <we-button class="dropdown-item" data-value="fill">Fill</we-button>
                                <we-button class="dropdown-item" data-value="fill,rounded-circle">Fill + Rounded</we-button>
                                <we-button class="dropdown-item" data-value="flat">Flat</we-button>
                            </we-selection-items>
                        </div>
                    </div>
                </we-select>
            </we-row>
            <we-row t-if="!state.isButton and !props.forceNewWindow and !state.isDocument">
                <we-button t-attf-class="o_we_user_value_widget o_we_checkbox_wrapper o_we_sublevel_1 #{this.initialNewWindow ? 'active' : ''}">
                    <we-title class="o_long_title">Open in New Window</we-title>
                        <div class="o_switch">
                            <we-checkbox name="is_new_window" t-att-checked="this.initialNewWindow ? 'checked' : undefined"/>
                        </div>
                </we-button>
            </we-row>
            <we-row t-if="!state.isButton and state.isDocument">
                <we-button t-attf-class="o_we_user_value_widget o_we_checkbox_wrapper o_we_sublevel_1 #{state.directDownload ? 'active' : ''}">
                    <we-title class="o_long_title">Direct Download</we-title>
                    <div class="o_switch">
                        <we-checkbox name="direct_download" t-att-checked="state.directDownload ? 'checked' : undefined"/>
                    </div>
                </we-button>
            </we-row>
        </div>
    </we-customizeblock-option>


    `);
registerTemplate("web_editor.ImageCrop", `/web_editor/static/src/xml/wysiwyg.xml`, `<div t-name="web_editor.ImageCrop" class="o_we_crop_widget" contenteditable="false" t-att-class="this.state.active ? '' : 'd-none'" t-ref="el" xml:space="preserve">
        <div class="o_we_cropper_wrapper">
            <img class="o_we_cropper_img"/>
            <div class="o_we_crop_buttons text-center mt16 o_we_no_overlay" contenteditable="false">
                <div class="btn-group btn-group-toggle" title="Aspect Ratio" data-bs-toggle="buttons">
                    <t t-foreach="this.aspectRatios" t-as="ratio" t-key="ratio">
                        <t t-set="is_active" t-value="ratio === this.aspectRatio"/>
                        <label t-attf-class="btn #{is_active and 'active' or ''}" data-action="ratio" t-att-data-value="ratio">
                            <input type="radio"/><t t-esc="ratio_value.label"/>
                        </label>
                    </t>
                </div>
                <div class="btn-group" role="group">
                    <button type="button" title="Zoom In" data-action="zoom" data-value="0.1"><i class="fa fa-fw fa-search-plus"/></button>
                    <button type="button" title="Zoom Out" data-action="zoom" data-value="-0.1"><i class="fa fa-fw fa-search-minus"/></button>
                </div>
                <div class="btn-group" role="group">
                    <button type="button" title="Rotate Left" data-action="rotate" data-value="-90"><i class="fa fa-fw fa-rotate-left"/></button>
                    <button type="button" title="Rotate Right" data-action="rotate" data-value="90"><i class="fa fa-fw fa-rotate-right"/></button>
                </div>
                <div class="btn-group" role="group">
                    <button type="button" title="Flip Horizontal" data-action="flip" data-scale-direction="scaleX"><i class="oi oi-fw oi-arrows-h"/></button>
                    <button type="button" title="Flip Vertical" data-action="flip" data-scale-direction="scaleY"><i class="oi oi-fw oi-arrows-v"/></button>
                </div>
                <div class="btn-group" role="group">
                    <button type="button" title="Reset Image" data-action="reset"><i class="fa fa-refresh"/> Reset Image</button>
                </div>
                <div class="btn-group" role="group">
                    <button type="button" title="Apply" data-action="apply" class="btn btn-primary"><i class="fa fa-check"/> Apply</button>
                    <button type="button" title="Discard" data-action="discard" class="btn btn-danger"><i class="fa fa-times"/> Discard</button>
                </div>
            </div>
        </div>
    </div>

`);
registerTemplate("wysiwyg.plugin.font.paletteButton", `/web_editor/static/src/xml/wysiwyg_colorpicker.xml`, `<t t-name="wysiwyg.plugin.font.paletteButton" xml:space="preserve">
        <div t-attf-class="note-btn-group btn-group {{className}}">
            <button type="button" class="note-btn btn btn-light btn-sm dropdown-toggle" tabindex="-1" data-bs-toggle="dropdown"><i t-att-class="icon"/></button>
            <div class="dropdown-menu"/>
        </div>
    </t>

    `);
registerTemplate("wysiwyg.plugin.font.colorPalette", `/web_editor/static/src/xml/wysiwyg_colorpicker.xml`, `<t t-name="wysiwyg.plugin.font.colorPalette" xml:space="preserve">
        <div class="note-palette">
            <button type="button" class="note-color-reset btn btn-light note-color-btn bg-undefined">
                <t t-esc="lang.color.resetToDefault"/></button>
            <div class="note-holder">
                <div class="note-color-palette">
                    <h6 class="mt-2">Theme colors</h6>
                    <div class="o_theme_color_placeholder"/>
                    <h6 class="mt-2">Transparent colors</h6>
                    <div class="o_transparent_color_placeholder"/>
                    <h6 class="mt-2">Common colors</h6>
                    <div class="o_common_color_placeholder">
                        <div class="note-color-row" t-foreach="colors" t-as="rowColors" t-key="rowColors_index">
                            <button t-foreach="rowColors" t-as="color" t-key="color_index" type="button" class="note-color-btn" data-bs-toggle="button" tabindex="-1" t-attf-style="background-color:{{color}}" t-att-data-value="color" t-att-title="color"/>
                        </div>
                    </div>
                </div>
                <h6 class="note-custom-color mt8">
                    <t t-esc="lang.color.customColor"/>
                </h6>
                <button class="note-custom-color-btn note-color-btn" style="display: none;"/>
            </div>
        </div>
    </t>
`);
registerTemplateExtension("web_editor.LinkDialog", `/website/static/src/xml/web_editor.xml`, `<t t-inherit="web_editor.LinkDialog" t-inherit-mode="extension" xml:space="preserve">
        <xpath expr="//*[@id='o_link_dialog_url_input']" position="after">
            <small class="form-text text-muted">Hint: Type '/' to search an existing page and '#' to link to an anchor.</small>
        </xpath>
    </t>

    `);
registerTemplateExtension("web_editor.LinkTools", `/website/static/src/xml/web_editor.xml`, `<t t-inherit="web_editor.LinkTools" t-inherit-mode="extension" xml:space="preserve">
        <xpath expr="//we-row[@id='url_row']" position="after">
            <div style="text-align: center" t-attf-class="#{state.isButton ? ' d-none' : ''}">
                <small>
                    Type '<span class="highlighted-text">/</span>' to search a page.
                    '<span class="highlighted-text">#</span>' to link to an anchor.
                </small>
            </div>
            <we-row class="o_link_dialog_page_anchor d-none" t-attf-class="#{state.isButton || state.isDocument ? ' d-none' : ''}">
                <we-select class="o_we_user_value_widget o_we_sublevel_1">
                    <we-title>Page Anchor</we-title>
                    <div>
                        <div class="dropdown">
                            <button class="dropdown-toggle" data-bs-toggle="dropdown" tabindex="-1" aria-expanded="false">
                                <we-toggler>
                                    Loading...
                                </we-toggler>
                            </button>
                            <we-selection-items name="link_anchor" class="dropdown-menu link-style">
                                <we-button class="dropdown-item o_anchors_loading">Loading...</we-button>
                            </we-selection-items>
                            <span class="o_we_dropdown_caret"/>
                        </div>
                    </div>
                </we-select>
            </we-row>
        </xpath>
    </t>

    `);
registerTemplateExtension("web_editor.toolbar", `/website/static/src/xml/web_editor.xml`, `<t t-inherit="web_editor.toolbar" t-inherit-mode="extension" xml:space="preserve">
        <xpath expr="//div[@id='open-chatgpt']" position="inside">
            <span>AI</span>
        </xpath>

        <xpath expr="//div[@id='strikethrough']" position="attributes">
            <attribute name="t-if">!props.showTextHighlights</attribute>
        </xpath>
    </t>
`);
                    });
