(function() { "use strict"; (function() { try { if (typeof document < "u") { var e = document.createElement("style"); e.appendChild(document.createTextNode(".ce-hint--align-start{text-align:left}.ce-hint--align-center{text-align:center}.ce-hint__description{opacity:.6;margin-top:3px}")), document.head.appendChild(e); } } catch (t) { console.error("vite-plugin-css-injected-by-js", t); } })(); var Ce$1 = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {}; function Ke$2(n2) { return n2 && n2.__esModule && Object.prototype.hasOwnProperty.call(n2, "default") ? n2.default : n2; } function Xn$1(n2) { if (n2.__esModule) return n2; var e = n2.default; if (typeof e == "function") { var t = function o2() { return this instanceof o2 ? Reflect.construct(e, arguments, this.constructor) : e.apply(this, arguments); }; t.prototype = e.prototype; } else t = {}; return Object.defineProperty(t, "__esModule", { value: true }), Object.keys(n2).forEach(function(o2) { var i = Object.getOwnPropertyDescriptor(n2, o2); Object.defineProperty(t, o2, i.get ? i : { enumerable: true, get: function() { return n2[o2]; } }); }), t; } function ot$2() { } Object.assign(ot$2, { default: ot$2, register: ot$2, revert: function() { }, __esModule: true }); Element.prototype.matches || (Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function(n2) { const e = (this.document || this.ownerDocument).querySelectorAll(n2); let t = e.length; for (; --t >= 0 && e.item(t) !== this; ) ; return t > -1; }); Element.prototype.closest || (Element.prototype.closest = function(n2) { let e = this; if (!document.documentElement.contains(e)) return null; do { if (e.matches(n2)) return e; e = e.parentElement || e.parentNode; } while (e !== null); return null; }); Element.prototype.prepend || (Element.prototype.prepend = function(e) { const t = document.createDocumentFragment(); Array.isArray(e) || (e = [e]), e.forEach((o2) => { const i = o2 instanceof Node; t.appendChild(i ? o2 : document.createTextNode(o2)); }), this.insertBefore(t, this.firstChild); }); Element.prototype.scrollIntoViewIfNeeded || (Element.prototype.scrollIntoViewIfNeeded = function(n2) { n2 = arguments.length === 0 ? true : !!n2; const e = this.parentNode, t = window.getComputedStyle(e, null), o2 = parseInt(t.getPropertyValue("border-top-width")), i = parseInt(t.getPropertyValue("border-left-width")), s2 = this.offsetTop - e.offsetTop < e.scrollTop, r2 = this.offsetTop - e.offsetTop + this.clientHeight - o2 > e.scrollTop + e.clientHeight, a2 = this.offsetLeft - e.offsetLeft < e.scrollLeft, l2 = this.offsetLeft - e.offsetLeft + this.clientWidth - i > e.scrollLeft + e.clientWidth, c2 = s2 && !r2; (s2 || r2) && n2 && (e.scrollTop = this.offsetTop - e.offsetTop - e.clientHeight / 2 - o2 + this.clientHeight / 2), (a2 || l2) && n2 && (e.scrollLeft = this.offsetLeft - e.offsetLeft - e.clientWidth / 2 - i + this.clientWidth / 2), (s2 || r2 || a2 || l2) && !n2 && this.scrollIntoView(c2); }); window.requestIdleCallback = window.requestIdleCallback || function(n2) { const e = Date.now(); return setTimeout(function() { n2({ didTimeout: false, timeRemaining: function() { return Math.max(0, 50 - (Date.now() - e)); } }); }, 1); }; window.cancelIdleCallback = window.cancelIdleCallback || function(n2) { clearTimeout(n2); }; let Vn$1 = (n2 = 21) => crypto.getRandomValues(new Uint8Array(n2)).reduce((e, t) => (t &= 63, t < 36 ? e += t.toString(36) : t < 62 ? e += (t - 26).toString(36).toUpperCase() : t > 62 ? e += "-" : e += "_", e), ""); var Lo = /* @__PURE__ */ ((n2) => (n2.VERBOSE = "VERBOSE", n2.INFO = "INFO", n2.WARN = "WARN", n2.ERROR = "ERROR", n2))(Lo || {}); const y$3 = { BACKSPACE: 8, TAB: 9, ENTER: 13, SHIFT: 16, CTRL: 17, ALT: 18, ESC: 27, SPACE: 32, LEFT: 37, UP: 38, DOWN: 40, RIGHT: 39, DELETE: 46, META: 91, SLASH: 191 }, qn$1 = { LEFT: 0, WHEEL: 1, RIGHT: 2, BACKWARD: 3, FORWARD: 4 }; function Ie$1(n2, e, t = "log", o2, i = "color: inherit") { if (!("console" in window) || !window.console[t]) return; const s2 = ["info", "log", "warn", "error"].includes(t), r2 = []; switch (Ie$1.logLevel) { case "ERROR": if (t !== "error") return; break; case "WARN": if (!["error", "warn"].includes(t)) return; break; case "INFO": if (!s2 || n2) return; break; } o2 && r2.push(o2); const a2 = "Editor.js 2.31.0", l2 = `line-height: 1em; color: #006FEA; display: inline-block; font-size: 11px; line-height: 1em; background-color: #fff; padding: 4px 9px; border-radius: 30px; border: 1px solid rgba(56, 138, 229, 0.16); margin: 4px 5px 4px 0;`; n2 && (s2 ? (r2.unshift(l2, i), e = `%c${a2}%c ${e}`) : e = `( ${a2} )${e}`); try { s2 ? o2 ? console[t](`${e} %o`, ...r2) : console[t](e, ...r2) : console[t](e); } catch { } } Ie$1.logLevel = "VERBOSE"; function Zn$1(n2) { Ie$1.logLevel = n2; } const S$4 = Ie$1.bind(window, false), X$2 = Ie$1.bind(window, true); function le$2(n2) { return Object.prototype.toString.call(n2).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); } function A$4(n2) { return le$2(n2) === "function" || le$2(n2) === "asyncfunction"; } function D$3(n2) { return le$2(n2) === "object"; } function te$2(n2) { return le$2(n2) === "string"; } function Gn$1(n2) { return le$2(n2) === "boolean"; } function yo(n2) { return le$2(n2) === "number"; } function wo(n2) { return le$2(n2) === "undefined"; } function V$2(n2) { return n2 ? Object.keys(n2).length === 0 && n2.constructor === Object : true; } function Po(n2) { return n2 > 47 && n2 < 58 || // number keys n2 === 32 || n2 === 13 || // Space bar & return key(s) n2 === 229 || // processing key input for certain languages — Chinese, Japanese, etc. n2 > 64 && n2 < 91 || // letter keys n2 > 95 && n2 < 112 || // Numpad keys n2 > 185 && n2 < 193 || // ;=,-./` (in order) n2 > 218 && n2 < 223; } async function Qn$1(n2, e = () => { }, t = () => { }) { async function o2(i, s2, r2) { try { await i.function(i.data), await s2(wo(i.data) ? {} : i.data); } catch { r2(wo(i.data) ? {} : i.data); } } return n2.reduce(async (i, s2) => (await i, o2(s2, e, t)), Promise.resolve()); } function No(n2) { return Array.prototype.slice.call(n2); } function Fe$2(n2, e) { return function() { const t = this, o2 = arguments; window.setTimeout(() => n2.apply(t, o2), e); }; } function Jn$1(n2) { return n2.name.split(".").pop(); } function ei(n2) { return /^[-\w]+\/([-+\w]+|\*)$/.test(n2); } function Eo(n2, e, t) { let o2; return (...i) => { const s2 = this, r2 = () => { o2 = null, t || n2.apply(s2, i); }, a2 = t && !o2; window.clearTimeout(o2), o2 = window.setTimeout(r2, e), a2 && n2.apply(s2, i); }; } function dt$1(n2, e, t = void 0) { let o2, i, s2, r2 = null, a2 = 0; t || (t = {}); const l2 = function() { a2 = t.leading === false ? 0 : Date.now(), r2 = null, s2 = n2.apply(o2, i), r2 || (o2 = i = null); }; return function() { const c2 = Date.now(); !a2 && t.leading === false && (a2 = c2); const d2 = e - (c2 - a2); return o2 = this, i = arguments, d2 <= 0 || d2 > e ? (r2 && (clearTimeout(r2), r2 = null), a2 = c2, s2 = n2.apply(o2, i), r2 || (o2 = i = null)) : !r2 && t.trailing !== false && (r2 = setTimeout(l2, d2)), s2; }; } function ti() { const n2 = { win: false, mac: false, x11: false, linux: false }, e = Object.keys(n2).find((t) => window.navigator.appVersion.toLowerCase().indexOf(t) !== -1); return e && (n2[e] = true), n2; } function je$1(n2) { return n2[0].toUpperCase() + n2.slice(1); } function ut$1(n2, ...e) { if (!e.length) return n2; const t = e.shift(); if (D$3(n2) && D$3(t)) for (const o2 in t) D$3(t[o2]) ? (n2[o2] || Object.assign(n2, { [o2]: {} }), ut$1(n2[o2], t[o2])) : Object.assign(n2, { [o2]: t[o2] }); return ut$1(n2, ...e); } function vt$1(n2) { const e = ti(); return n2 = n2.replace(/shift/gi, "⇧").replace(/backspace/gi, "⌫").replace(/enter/gi, "⏎").replace(/up/gi, "↑").replace(/left/gi, "→").replace(/down/gi, "↓").replace(/right/gi, "←").replace(/escape/gi, "⎋").replace(/insert/gi, "Ins").replace(/delete/gi, "␡").replace(/\+/gi, " + "), e.mac ? n2 = n2.replace(/ctrl|cmd/gi, "⌘").replace(/alt/gi, "⌥") : n2 = n2.replace(/cmd/gi, "Ctrl").replace(/windows/gi, "WIN"), n2; } function oi(n2) { try { return new URL(n2).href; } catch { } return n2.substring(0, 2) === "//" ? window.location.protocol + n2 : window.location.origin + n2; } function ni() { return Vn$1(10); } function ii(n2) { window.open(n2, "_blank"); } function si(n2 = "") { return `${n2}${Math.floor(Math.random() * 1e8).toString(16)}`; } function ht$1(n2, e, t) { const o2 = `«${e}» is deprecated and will be removed in the next major release. Please use the «${t}» instead.`; n2 && X$2(o2, "warn"); } function me$2(n2, e, t) { const o2 = t.value ? "value" : "get", i = t[o2], s2 = `#${e}Cache`; if (t[o2] = function(...r2) { return this[s2] === void 0 && (this[s2] = i.apply(this, ...r2)), this[s2]; }, o2 === "get" && t.set) { const r2 = t.set; t.set = function(a2) { delete n2[s2], r2.apply(this, a2); }; } return t; } const Ro = 650; function be$2() { return window.matchMedia(`(max-width: ${Ro}px)`).matches; } const pt$1 = typeof window < "u" && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1); function ri(n2, e) { const t = Array.isArray(n2) || D$3(n2), o2 = Array.isArray(e) || D$3(e); return t || o2 ? JSON.stringify(n2) === JSON.stringify(e) : n2 === e; } let u$1 = class u2 { /** * Check if passed tag has no closed tag * * @param {HTMLElement} tag - element to check * @returns {boolean} */ static isSingleTag(e) { return e.tagName && [ "AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "META", "PARAM", "SOURCE", "TRACK", "WBR" ].includes(e.tagName); } /** * Check if element is BR or WBR * * @param {HTMLElement} element - element to check * @returns {boolean} */ static isLineBreakTag(e) { return e && e.tagName && [ "BR", "WBR" ].includes(e.tagName); } /** * Helper for making Elements with class name and attributes * * @param {string} tagName - new Element tag name * @param {string[]|string} [classNames] - list or name of CSS class name(s) * @param {object} [attributes] - any attributes * @returns {HTMLElement} */ static make(e, t = null, o2 = {}) { const i = document.createElement(e); if (Array.isArray(t)) { const s2 = t.filter((r2) => r2 !== void 0); i.classList.add(...s2); } else t && i.classList.add(t); for (const s2 in o2) Object.prototype.hasOwnProperty.call(o2, s2) && (i[s2] = o2[s2]); return i; } /** * Creates Text Node with the passed content * * @param {string} content - text content * @returns {Text} */ static text(e) { return document.createTextNode(e); } /** * Append one or several elements to the parent * * @param {Element|DocumentFragment} parent - where to append * @param {Element|Element[]|DocumentFragment|Text|Text[]} elements - element or elements list */ static append(e, t) { Array.isArray(t) ? t.forEach((o2) => e.appendChild(o2)) : e.appendChild(t); } /** * Append element or a couple to the beginning of the parent elements * * @param {Element} parent - where to append * @param {Element|Element[]} elements - element or elements list */ static prepend(e, t) { Array.isArray(t) ? (t = t.reverse(), t.forEach((o2) => e.prepend(o2))) : e.prepend(t); } /** * Swap two elements in parent * * @param {HTMLElement} el1 - from * @param {HTMLElement} el2 - to * @deprecated */ static swap(e, t) { const o2 = document.createElement("div"), i = e.parentNode; i.insertBefore(o2, e), i.insertBefore(e, t), i.insertBefore(t, o2), i.removeChild(o2); } /** * Selector Decorator * * Returns first match * * @param {Element} el - element we searching inside. Default - DOM Document * @param {string} selector - searching string * @returns {Element} */ static find(e = document, t) { return e.querySelector(t); } /** * Get Element by Id * * @param {string} id - id to find * @returns {HTMLElement | null} */ static get(e) { return document.getElementById(e); } /** * Selector Decorator. * * Returns all matches * * @param {Element|Document} el - element we searching inside. Default - DOM Document * @param {string} selector - searching string * @returns {NodeList} */ static findAll(e = document, t) { return e.querySelectorAll(t); } /** * Returns CSS selector for all text inputs */ static get allInputsSelector() { return "[contenteditable=true], textarea, input:not([type]), " + ["text", "password", "email", "number", "search", "tel", "url"].map((t) => `input[type="${t}"]`).join(", "); } /** * Find all contenteditable, textarea and editable input elements passed holder contains * * @param holder - element where to find inputs */ static findAllInputs(e) { return No(e.querySelectorAll(u2.allInputsSelector)).reduce((t, o2) => u2.isNativeInput(o2) || u2.containsOnlyInlineElements(o2) ? [...t, o2] : [...t, ...u2.getDeepestBlockElements(o2)], []); } /** * Search for deepest node which is Leaf. * Leaf is the vertex that doesn't have any child nodes * * @description Method recursively goes throw the all Node until it finds the Leaf * @param {Node} node - root Node. From this vertex we start Deep-first search * {@link https://en.wikipedia.org/wiki/Depth-first_search} * @param {boolean} [atLast] - find last text node * @returns - it can be text Node or Element Node, so that caret will able to work with it * Can return null if node is Document or DocumentFragment, or node is not attached to the DOM */ static getDeepestNode(e, t = false) { const o2 = t ? "lastChild" : "firstChild", i = t ? "previousSibling" : "nextSibling"; if (e && e.nodeType === Node.ELEMENT_NODE && e[o2]) { let s2 = e[o2]; if (u2.isSingleTag(s2) && !u2.isNativeInput(s2) && !u2.isLineBreakTag(s2)) if (s2[i]) s2 = s2[i]; else if (s2.parentNode[i]) s2 = s2.parentNode[i]; else return s2.parentNode; return this.getDeepestNode(s2, t); } return e; } /** * Check if object is DOM node * * @param {*} node - object to check * @returns {boolean} */ // eslint-disable-next-line @typescript-eslint/no-explicit-any static isElement(e) { return yo(e) ? false : e && e.nodeType && e.nodeType === Node.ELEMENT_NODE; } /** * Check if object is DocumentFragment node * * @param {object} node - object to check * @returns {boolean} */ // eslint-disable-next-line @typescript-eslint/no-explicit-any static isFragment(e) { return yo(e) ? false : e && e.nodeType && e.nodeType === Node.DOCUMENT_FRAGMENT_NODE; } /** * Check if passed element is contenteditable * * @param {HTMLElement} element - html element to check * @returns {boolean} */ static isContentEditable(e) { return e.contentEditable === "true"; } /** * Checks target if it is native input * * @param {*} target - HTML element or string * @returns {boolean} */ // eslint-disable-next-line @typescript-eslint/no-explicit-any static isNativeInput(e) { const t = [ "INPUT", "TEXTAREA" ]; return e && e.tagName ? t.includes(e.tagName) : false; } /** * Checks if we can set caret * * @param {HTMLElement} target - target to check * @returns {boolean} */ static canSetCaret(e) { let t = true; if (u2.isNativeInput(e)) switch (e.type) { case "file": case "checkbox": case "radio": case "hidden": case "submit": case "button": case "image": case "reset": t = false; break; } else t = u2.isContentEditable(e); return t; } /** * Checks node if it is empty * * @description Method checks simple Node without any childs for emptiness * If you have Node with 2 or more children id depth, you better use {@link Dom#isEmpty} method * @param {Node} node - node to check * @param {string} [ignoreChars] - char or substring to treat as empty * @returns {boolean} true if it is empty */ static isNodeEmpty(e, t) { let o2; return this.isSingleTag(e) && !this.isLineBreakTag(e) ? false : (this.isElement(e) && this.isNativeInput(e) ? o2 = e.value : o2 = e.textContent.replace("​", ""), t && (o2 = o2.replace(new RegExp(t, "g"), "")), o2.length === 0); } /** * checks node if it is doesn't have any child nodes * * @param {Node} node - node to check * @returns {boolean} */ static isLeaf(e) { return e ? e.childNodes.length === 0 : false; } /** * breadth-first search (BFS) * {@link https://en.wikipedia.org/wiki/Breadth-first_search} * * @description Pushes to stack all DOM leafs and checks for emptiness * @param {Node} node - node to check * @param {string} [ignoreChars] - char or substring to treat as empty * @returns {boolean} */ static isEmpty(e, t) { const o2 = [e]; for (; o2.length > 0; ) if (e = o2.shift(), !!e) { if (this.isLeaf(e) && !this.isNodeEmpty(e, t)) return false; e.childNodes && o2.push(...Array.from(e.childNodes)); } return true; } /** * Check if string contains html elements * * @param {string} str - string to check * @returns {boolean} */ static isHTMLString(e) { const t = u2.make("div"); return t.innerHTML = e, t.childElementCount > 0; } /** * Return length of node`s text content * * @param {Node} node - node with content * @returns {number} */ static getContentLength(e) { return u2.isNativeInput(e) ? e.value.length : e.nodeType === Node.TEXT_NODE ? e.length : e.textContent.length; } /** * Return array of names of block html elements * * @returns {string[]} */ static get blockElements() { return [ "address", "article", "aside", "blockquote", "canvas", "div", "dl", "dt", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "hr", "li", "main", "nav", "noscript", "ol", "output", "p", "pre", "ruby", "section", "table", "tbody", "thead", "tr", "tfoot", "ul", "video" ]; } /** * Check if passed content includes only inline elements * * @param {string|HTMLElement} data - element or html string * @returns {boolean} */ static containsOnlyInlineElements(e) { let t; te$2(e) ? (t = document.createElement("div"), t.innerHTML = e) : t = e; const o2 = (i) => !u2.blockElements.includes(i.tagName.toLowerCase()) && Array.from(i.children).every(o2); return Array.from(t.children).every(o2); } /** * Find and return all block elements in the passed parent (including subtree) * * @param {HTMLElement} parent - root element * @returns {HTMLElement[]} */ static getDeepestBlockElements(e) { return u2.containsOnlyInlineElements(e) ? [e] : Array.from(e.children).reduce((t, o2) => [...t, ...u2.getDeepestBlockElements(o2)], []); } /** * Helper for get holder from {string} or return HTMLElement * * @param {string | HTMLElement} element - holder's id or holder's HTML Element * @returns {HTMLElement} */ static getHolder(e) { return te$2(e) ? document.getElementById(e) : e; } /** * Returns true if element is anchor (is A tag) * * @param {Element} element - element to check * @returns {boolean} */ static isAnchor(e) { return e.tagName.toLowerCase() === "a"; } /** * Return element's offset related to the document * * @todo handle case when editor initialized in scrollable popup * @param el - element to compute offset */ static offset(e) { const t = e.getBoundingClientRect(), o2 = window.pageXOffset || document.documentElement.scrollLeft, i = window.pageYOffset || document.documentElement.scrollTop, s2 = t.top + i, r2 = t.left + o2; return { top: s2, left: r2, bottom: s2 + t.height, right: r2 + t.width }; } /** * Find text node and offset by total content offset * * @param {Node} root - root node to start search from * @param {number} totalOffset - offset relative to the root node content * @returns {{node: Node | null, offset: number}} - node and offset inside node */ static getNodeByOffset(e, t) { let o2 = 0, i = null; const s2 = document.createTreeWalker( e, NodeFilter.SHOW_TEXT, null ); let r2 = s2.nextNode(); for (; r2; ) { const c2 = r2.textContent, d2 = c2 === null ? 0 : c2.length; if (i = r2, o2 + d2 >= t) break; o2 += d2, r2 = s2.nextNode(); } if (!i) return { node: null, offset: 0 }; const a2 = i.textContent; if (a2 === null || a2.length === 0) return { node: null, offset: 0 }; const l2 = Math.min(t - o2, a2.length); return { node: i, offset: l2 }; } }; function ai(n2) { return !/[^\t\n\r ]/.test(n2); } function li(n2) { const e = window.getComputedStyle(n2), t = parseFloat(e.fontSize), o2 = parseFloat(e.lineHeight) || t * 1.2, i = parseFloat(e.paddingTop), s2 = parseFloat(e.borderTopWidth), r2 = parseFloat(e.marginTop), a2 = t * 0.8, l2 = (o2 - t) / 2; return r2 + s2 + i + l2 + a2; } function Do(n2) { n2.dataset.empty = u$1.isEmpty(n2) ? "true" : "false"; } const ci = { blockTunes: { toggler: { "Click to tune": "", "or drag to move": "" } }, inlineToolbar: { converter: { "Convert to": "" } }, toolbar: { toolbox: { Add: "" } }, popover: { Filter: "", "Nothing found": "", "Convert to": "" } }, di = { Text: "", Link: "", Bold: "", Italic: "" }, ui = { link: { "Add a link": "" }, stub: { "The block can not be displayed correctly.": "" } }, hi = { delete: { Delete: "", "Click to delete": "" }, moveUp: { "Move up": "" }, moveDown: { "Move down": "" } }, Fo = { ui: ci, toolNames: di, tools: ui, blockTunes: hi }, jo = class he2 { /** * Type-safe translation for internal UI texts: * Perform translation of the string by namespace and a key * * @example I18n.ui(I18nInternalNS.ui.blockTunes.toggler, 'Click to tune') * @param internalNamespace - path to translated string in dictionary * @param dictKey - dictionary key. Better to use default locale original text */ static ui(e, t) { return he2._t(e, t); } /** * Translate for external strings that is not presented in default dictionary. * For example, for user-specified tool names * * @param namespace - path to translated string in dictionary * @param dictKey - dictionary key. Better to use default locale original text */ static t(e, t) { return he2._t(e, t); } /** * Adjust module for using external dictionary * * @param dictionary - new messages list to override default */ static setDictionary(e) { he2.currentDictionary = e; } /** * Perform translation both for internal and external namespaces * If there is no translation found, returns passed key as a translated message * * @param namespace - path to translated string in dictionary * @param dictKey - dictionary key. Better to use default locale original text */ static _t(e, t) { const o2 = he2.getNamespace(e); return !o2 || !o2[t] ? t : o2[t]; } /** * Find messages section by namespace path * * @param namespace - path to section */ static getNamespace(e) { return e.split(".").reduce((o2, i) => !o2 || !Object.keys(o2).length ? {} : o2[i], he2.currentDictionary); } }; jo.currentDictionary = Fo; let z$2 = jo; class Ho extends Error { } let Oe$1 = class Oe { constructor() { this.subscribers = {}; } /** * Subscribe any event on callback * * @param eventName - event name * @param callback - subscriber */ on(e, t) { e in this.subscribers || (this.subscribers[e] = []), this.subscribers[e].push(t); } /** * Subscribe any event on callback. Callback will be called once and be removed from subscribers array after call. * * @param eventName - event name * @param callback - subscriber */ once(e, t) { e in this.subscribers || (this.subscribers[e] = []); const o2 = (i) => { const s2 = t(i), r2 = this.subscribers[e].indexOf(o2); return r2 !== -1 && this.subscribers[e].splice(r2, 1), s2; }; this.subscribers[e].push(o2); } /** * Emit callbacks with passed data * * @param eventName - event name * @param data - subscribers get this data when they were fired */ emit(e, t) { V$2(this.subscribers) || !this.subscribers[e] || this.subscribers[e].reduce((o2, i) => { const s2 = i(o2); return s2 !== void 0 ? s2 : o2; }, t); } /** * Unsubscribe callback from event * * @param eventName - event name * @param callback - event handler */ off(e, t) { if (this.subscribers[e] === void 0) { console.warn(`EventDispatcher .off(): there is no subscribers for event "${e.toString()}". Probably, .off() called before .on()`); return; } for (let o2 = 0; o2 < this.subscribers[e].length; o2++) if (this.subscribers[e][o2] === t) { delete this.subscribers[e][o2]; break; } } /** * Destroyer * clears subscribers list */ destroy() { this.subscribers = {}; } }; function J$2(n2) { Object.setPrototypeOf(this, { /** * Block id * * @returns {string} */ get id() { return n2.id; }, /** * Tool name * * @returns {string} */ get name() { return n2.name; }, /** * Tool config passed on Editor's initialization * * @returns {ToolConfig} */ get config() { return n2.config; }, /** * .ce-block element, that wraps plugin contents * * @returns {HTMLElement} */ get holder() { return n2.holder; }, /** * True if Block content is empty * * @returns {boolean} */ get isEmpty() { return n2.isEmpty; }, /** * True if Block is selected with Cross-Block selection * * @returns {boolean} */ get selected() { return n2.selected; }, /** * Set Block's stretch state * * @param {boolean} state — state to set */ set stretched(t) { n2.stretched = t; }, /** * True if Block is stretched * * @returns {boolean} */ get stretched() { return n2.stretched; }, /** * True if Block has inputs to be focused */ get focusable() { return n2.focusable; }, /** * Call Tool method with errors handler under-the-hood * * @param {string} methodName - method to call * @param {object} param - object with parameters * @returns {unknown} */ call(t, o2) { return n2.call(t, o2); }, /** * Save Block content * * @returns {Promise} */ save() { return n2.save(); }, /** * Validate Block data * * @param {BlockToolData} data - data to validate * @returns {Promise} */ validate(t) { return n2.validate(t); }, /** * Allows to say Editor that Block was changed. Used to manually trigger Editor's 'onChange' callback * Can be useful for block changes invisible for editor core. */ dispatchChange() { n2.dispatchChange(); }, /** * Tool could specify several entries to be displayed at the Toolbox (for example, "Heading 1", "Heading 2", "Heading 3") * This method returns the entry that is related to the Block (depended on the Block data) */ getActiveToolboxEntry() { return n2.getActiveToolboxEntry(); } }); } let _e$2 = class _e { constructor() { this.allListeners = []; } /** * Assigns event listener on element and returns unique identifier * * @param {EventTarget} element - DOM element that needs to be listened * @param {string} eventType - event type * @param {Function} handler - method that will be fired on event * @param {boolean|AddEventListenerOptions} options - useCapture or {capture, passive, once} */ on(e, t, o2, i = false) { const s2 = si("l"), r2 = { id: s2, element: e, eventType: t, handler: o2, options: i }; if (!this.findOne(e, t, o2)) return this.allListeners.push(r2), e.addEventListener(t, o2, i), s2; } /** * Removes event listener from element * * @param {EventTarget} element - DOM element that we removing listener * @param {string} eventType - event type * @param {Function} handler - remove handler, if element listens several handlers on the same event type * @param {boolean|AddEventListenerOptions} options - useCapture or {capture, passive, once} */ off(e, t, o2, i) { const s2 = this.findAll(e, t, o2); s2.forEach((r2, a2) => { const l2 = this.allListeners.indexOf(s2[a2]); l2 > -1 && (this.allListeners.splice(l2, 1), r2.element.removeEventListener(r2.eventType, r2.handler, r2.options)); }); } /** * Removes listener by id * * @param {string} id - listener identifier */ offById(e) { const t = this.findById(e); t && t.element.removeEventListener(t.eventType, t.handler, t.options); } /** * Finds and returns first listener by passed params * * @param {EventTarget} element - event target * @param {string} [eventType] - event type * @param {Function} [handler] - event handler * @returns {ListenerData|null} */ findOne(e, t, o2) { const i = this.findAll(e, t, o2); return i.length > 0 ? i[0] : null; } /** * Return all stored listeners by passed params * * @param {EventTarget} element - event target * @param {string} eventType - event type * @param {Function} handler - event handler * @returns {ListenerData[]} */ findAll(e, t, o2) { let i; const s2 = e ? this.findByEventTarget(e) : []; return e && t && o2 ? i = s2.filter((r2) => r2.eventType === t && r2.handler === o2) : e && t ? i = s2.filter((r2) => r2.eventType === t) : i = s2, i; } /** * Removes all listeners */ removeAll() { this.allListeners.map((e) => { e.element.removeEventListener(e.eventType, e.handler, e.options); }), this.allListeners = []; } /** * Module cleanup on destruction */ destroy() { this.removeAll(); } /** * Search method: looks for listener by passed element * * @param {EventTarget} element - searching element * @returns {Array} listeners that found on element */ findByEventTarget(e) { return this.allListeners.filter((t) => { if (t.element === e) return t; }); } /** * Search method: looks for listener by passed event type * * @param {string} eventType - event type * @returns {ListenerData[]} listeners that found on element */ findByType(e) { return this.allListeners.filter((t) => { if (t.eventType === e) return t; }); } /** * Search method: looks for listener by passed handler * * @param {Function} handler - event handler * @returns {ListenerData[]} listeners that found on element */ findByHandler(e) { return this.allListeners.filter((t) => { if (t.handler === e) return t; }); } /** * Returns listener data found by id * * @param {string} id - listener identifier * @returns {ListenerData} */ findById(e) { return this.allListeners.find((t) => t.id === e); } }; let E$3 = class E2 { /** * @class * @param options - Module options * @param options.config - Module config * @param options.eventsDispatcher - Common event bus */ constructor({ config: e, eventsDispatcher: t }) { if (this.nodes = {}, this.listeners = new _e$2(), this.readOnlyMutableListeners = { /** * Assigns event listener on DOM element and pushes into special array that might be removed * * @param {EventTarget} element - DOM Element * @param {string} eventType - Event name * @param {Function} handler - Event handler * @param {boolean|AddEventListenerOptions} options - Listening options */ on: (o2, i, s2, r2 = false) => { this.mutableListenerIds.push( this.listeners.on(o2, i, s2, r2) ); }, /** * Clears all mutable listeners */ clearAll: () => { for (const o2 of this.mutableListenerIds) this.listeners.offById(o2); this.mutableListenerIds = []; } }, this.mutableListenerIds = [], new.target === E2) throw new TypeError("Constructors for abstract class Module are not allowed."); this.config = e, this.eventsDispatcher = t; } /** * Editor modules setter * * @param {EditorModules} Editor - Editor's Modules */ set state(e) { this.Editor = e; } /** * Remove memorized nodes */ removeAllNodes() { for (const e in this.nodes) { const t = this.nodes[e]; t instanceof HTMLElement && t.remove(); } } /** * Returns true if current direction is RTL (Right-To-Left) */ get isRtl() { return this.config.i18n.direction === "rtl"; } }; let b$3 = class b2 { constructor() { this.instance = null, this.selection = null, this.savedSelectionRange = null, this.isFakeBackgroundEnabled = false, this.commandBackground = "backColor", this.commandRemoveFormat = "removeFormat"; } /** * Editor styles * * @returns {{editorWrapper: string, editorZone: string}} */ static get CSS() { return { editorWrapper: "codex-editor", editorZone: "codex-editor__redactor" }; } /** * Returns selected anchor * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorNode} * * @returns {Node|null} */ static get anchorNode() { const e = window.getSelection(); return e ? e.anchorNode : null; } /** * Returns selected anchor element * * @returns {Element|null} */ static get anchorElement() { const e = window.getSelection(); if (!e) return null; const t = e.anchorNode; return t ? u$1.isElement(t) ? t : t.parentElement : null; } /** * Returns selection offset according to the anchor node * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorOffset} * * @returns {number|null} */ static get anchorOffset() { const e = window.getSelection(); return e ? e.anchorOffset : null; } /** * Is current selection range collapsed * * @returns {boolean|null} */ static get isCollapsed() { const e = window.getSelection(); return e ? e.isCollapsed : null; } /** * Check current selection if it is at Editor's zone * * @returns {boolean} */ static get isAtEditor() { return this.isSelectionAtEditor(b2.get()); } /** * Check if passed selection is at Editor's zone * * @param selection - Selection object to check */ static isSelectionAtEditor(e) { if (!e) return false; let t = e.anchorNode || e.focusNode; t && t.nodeType === Node.TEXT_NODE && (t = t.parentNode); let o2 = null; return t && t instanceof Element && (o2 = t.closest(`.${b2.CSS.editorZone}`)), o2 ? o2.nodeType === Node.ELEMENT_NODE : false; } /** * Check if passed range at Editor zone * * @param range - range to check */ static isRangeAtEditor(e) { if (!e) return; let t = e.startContainer; t && t.nodeType === Node.TEXT_NODE && (t = t.parentNode); let o2 = null; return t && t instanceof Element && (o2 = t.closest(`.${b2.CSS.editorZone}`)), o2 ? o2.nodeType === Node.ELEMENT_NODE : false; } /** * Methods return boolean that true if selection exists on the page */ static get isSelectionExists() { return !!b2.get().anchorNode; } /** * Return first range * * @returns {Range|null} */ static get range() { return this.getRangeFromSelection(this.get()); } /** * Returns range from passed Selection object * * @param selection - Selection object to get Range from */ static getRangeFromSelection(e) { return e && e.rangeCount ? e.getRangeAt(0) : null; } /** * Calculates position and size of selected text * * @returns {DOMRect | ClientRect} */ static get rect() { let e = document.selection, t, o2 = { x: 0, y: 0, width: 0, height: 0 }; if (e && e.type !== "Control") return e = e, t = e.createRange(), o2.x = t.boundingLeft, o2.y = t.boundingTop, o2.width = t.boundingWidth, o2.height = t.boundingHeight, o2; if (!window.getSelection) return S$4("Method window.getSelection is not supported", "warn"), o2; if (e = window.getSelection(), e.rangeCount === null || isNaN(e.rangeCount)) return S$4("Method SelectionUtils.rangeCount is not supported", "warn"), o2; if (e.rangeCount === 0) return o2; if (t = e.getRangeAt(0).cloneRange(), t.getBoundingClientRect && (o2 = t.getBoundingClientRect()), o2.x === 0 && o2.y === 0) { const i = document.createElement("span"); if (i.getBoundingClientRect) { i.appendChild(document.createTextNode("​")), t.insertNode(i), o2 = i.getBoundingClientRect(); const s2 = i.parentNode; s2.removeChild(i), s2.normalize(); } } return o2; } /** * Returns selected text as String * * @returns {string} */ static get text() { return window.getSelection ? window.getSelection().toString() : ""; } /** * Returns window SelectionUtils * {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection} * * @returns {Selection} */ static get() { return window.getSelection(); } /** * Set focus to contenteditable or native input element * * @param element - element where to set focus * @param offset - offset of cursor */ static setCursor(e, t = 0) { const o2 = document.createRange(), i = window.getSelection(); return u$1.isNativeInput(e) ? u$1.canSetCaret(e) ? (e.focus(), e.selectionStart = e.selectionEnd = t, e.getBoundingClientRect()) : void 0 : (o2.setStart(e, t), o2.setEnd(e, t), i.removeAllRanges(), i.addRange(o2), o2.getBoundingClientRect()); } /** * Check if current range exists and belongs to container * * @param container - where range should be */ static isRangeInsideContainer(e) { const t = b2.range; return t === null ? false : e.contains(t.startContainer); } /** * Adds fake cursor to the current range */ static addFakeCursor() { const e = b2.range; if (e === null) return; const t = u$1.make("span", "codex-editor__fake-cursor"); t.dataset.mutationFree = "true", e.collapse(), e.insertNode(t); } /** * Check if passed element contains a fake cursor * * @param el - where to check */ static isFakeCursorInsideContainer(e) { return u$1.find(e, ".codex-editor__fake-cursor") !== null; } /** * Removes fake cursor from a container * * @param container - container to look for */ static removeFakeCursor(e = document.body) { const t = u$1.find(e, ".codex-editor__fake-cursor"); t && t.remove(); } /** * Removes fake background */ removeFakeBackground() { this.isFakeBackgroundEnabled && (this.isFakeBackgroundEnabled = false, document.execCommand(this.commandRemoveFormat)); } /** * Sets fake background */ setFakeBackground() { document.execCommand(this.commandBackground, false, "#a8d6ff"), this.isFakeBackgroundEnabled = true; } /** * Save SelectionUtils's range */ save() { this.savedSelectionRange = b2.range; } /** * Restore saved SelectionUtils's range */ restore() { if (!this.savedSelectionRange) return; const e = window.getSelection(); e.removeAllRanges(), e.addRange(this.savedSelectionRange); } /** * Clears saved selection */ clearSaved() { this.savedSelectionRange = null; } /** * Collapse current selection */ collapseToEnd() { const e = window.getSelection(), t = document.createRange(); t.selectNodeContents(e.focusNode), t.collapse(false), e.removeAllRanges(), e.addRange(t); } /** * Looks ahead to find passed tag from current selection * * @param {string} tagName - tag to found * @param {string} [className] - tag's class name * @param {number} [searchDepth] - count of tags that can be included. For better performance. * @returns {HTMLElement|null} */ findParentTag(e, t, o2 = 10) { const i = window.getSelection(); let s2 = null; return !i || !i.anchorNode || !i.focusNode ? null : ([ /** the Node in which the selection begins */ i.anchorNode, /** the Node in which the selection ends */ i.focusNode ].forEach((a2) => { let l2 = o2; for (; l2 > 0 && a2.parentNode && !(a2.tagName === e && (s2 = a2, t && a2.classList && !a2.classList.contains(t) && (s2 = null), s2)); ) a2 = a2.parentNode, l2--; }), s2); } /** * Expands selection range to the passed parent node * * @param {HTMLElement} element - element which contents should be selected */ expandToTag(e) { const t = window.getSelection(); t.removeAllRanges(); const o2 = document.createRange(); o2.selectNodeContents(e), t.addRange(o2); } }; function pi(n2, e) { const { type: t, target: o2, addedNodes: i, removedNodes: s2 } = n2; return n2.type === "attributes" && n2.attributeName === "data-empty" ? false : !!(e.contains(o2) || t === "childList" && (Array.from(i).some((l2) => l2 === e) || Array.from(s2).some((l2) => l2 === e))); } const ft$1 = "redactor dom changed", $o = "block changed", zo = "fake cursor is about to be toggled", Uo = "fake cursor have been set", Te$1 = "editor mobile layout toggled"; function gt$1(n2, e) { if (!n2.conversionConfig) return false; const t = n2.conversionConfig[e]; return A$4(t) || te$2(t); } function He$2(n2, e) { return gt$1(n2.tool, e); } function Wo(n2, e) { return Object.entries(n2).some(([t, o2]) => e[t] && ri(e[t], o2)); } async function Yo(n2, e) { const o2 = (await n2.save()).data, i = e.find((s2) => s2.name === n2.name); return i !== void 0 && !gt$1(i, "export") ? [] : e.reduce((s2, r2) => { if (!gt$1(r2, "import") || r2.toolbox === void 0) return s2; const a2 = r2.toolbox.filter((l2) => { if (V$2(l2) || l2.icon === void 0) return false; if (l2.data !== void 0) { if (Wo(l2.data, o2)) return false; } else if (r2.name === n2.name) return false; return true; }); return s2.push({ ...r2, toolbox: a2 }), s2; }, []); } function xo(n2, e) { return n2.mergeable ? n2.name === e.name ? true : He$2(e, "export") && He$2(n2, "import") : false; } function fi(n2, e) { const t = e == null ? void 0 : e.export; return A$4(t) ? t(n2) : te$2(t) ? n2[t] : (t !== void 0 && S$4("Conversion «export» property must be a string or function. String means key of saved data object to export. Function should export processed string to export."), ""); } function Bo(n2, e, t) { const o2 = e == null ? void 0 : e.import; return A$4(o2) ? o2(n2, t) : te$2(o2) ? { [o2]: n2 } : (o2 !== void 0 && S$4("Conversion «import» property must be a string or function. String means key of tool data to import. Function accepts a imported string and return composed tool data."), {}); } var _$2 = /* @__PURE__ */ ((n2) => (n2.Default = "default", n2.Separator = "separator", n2.Html = "html", n2))(_$2 || {}), ee$2 = /* @__PURE__ */ ((n2) => (n2.APPEND_CALLBACK = "appendCallback", n2.RENDERED = "rendered", n2.MOVED = "moved", n2.UPDATED = "updated", n2.REMOVED = "removed", n2.ON_PASTE = "onPaste", n2))(ee$2 || {}); let R$5 = class R2 extends Oe$1 { /** * @param options - block constructor options * @param [options.id] - block's id. Will be generated if omitted. * @param options.data - Tool's initial data * @param options.tool — block's tool * @param options.api - Editor API module for pass it to the Block Tunes * @param options.readOnly - Read-Only flag * @param [eventBus] - Editor common event bus. Allows to subscribe on some Editor events. Could be omitted when "virtual" Block is created. See BlocksAPI@composeBlockData. */ constructor({ id: e = ni(), data: t, tool: o2, readOnly: i, tunesData: s2 }, r2) { super(), this.cachedInputs = [], this.toolRenderedElement = null, this.tunesInstances = /* @__PURE__ */ new Map(), this.defaultTunesInstances = /* @__PURE__ */ new Map(), this.unavailableTunesData = {}, this.inputIndex = 0, this.editorEventBus = null, this.handleFocus = () => { this.dropInputsCache(), this.updateCurrentInput(); }, this.didMutated = (a2 = void 0) => { const l2 = a2 === void 0, c2 = a2 instanceof InputEvent; !l2 && !c2 && this.detectToolRootChange(a2); let d2; l2 || c2 ? d2 = true : d2 = !(a2.length > 0 && a2.every((p2) => { const { addedNodes: g2, removedNodes: f2, target: v2 } = p2; return [ ...Array.from(g2), ...Array.from(f2), v2 ].some((T2) => (u$1.isElement(T2) || (T2 = T2.parentElement), T2 && T2.closest('[data-mutation-free="true"]') !== null)); })), d2 && (this.dropInputsCache(), this.updateCurrentInput(), this.toggleInputsEmptyMark(), this.call( "updated" /* UPDATED */ ), this.emit("didMutated", this)); }, this.name = o2.name, this.id = e, this.settings = o2.settings, this.config = o2.settings.config || {}, this.editorEventBus = r2 || null, this.blockAPI = new J$2(this), this.tool = o2, this.toolInstance = o2.create(t, this.blockAPI, i), this.tunes = o2.tunes, this.composeTunes(s2), this.holder = this.compose(), window.requestIdleCallback(() => { this.watchBlockMutations(), this.addInputEvents(), this.toggleInputsEmptyMark(); }); } /** * CSS classes for the Block * * @returns {{wrapper: string, content: string}} */ static get CSS() { return { wrapper: "ce-block", wrapperStretched: "ce-block--stretched", content: "ce-block__content", selected: "ce-block--selected", dropTarget: "ce-block--drop-target" }; } /** * Find and return all editable elements (contenteditable and native inputs) in the Tool HTML */ get inputs() { if (this.cachedInputs.length !== 0) return this.cachedInputs; const e = u$1.findAllInputs(this.holder); return this.inputIndex > e.length - 1 && (this.inputIndex = e.length - 1), this.cachedInputs = e, e; } /** * Return current Tool`s input * If Block doesn't contain inputs, return undefined */ get currentInput() { return this.inputs[this.inputIndex]; } /** * Set input index to the passed element * * @param element - HTML Element to set as current input */ set currentInput(e) { const t = this.inputs.findIndex((o2) => o2 === e || o2.contains(e)); t !== -1 && (this.inputIndex = t); } /** * Return first Tool`s input * If Block doesn't contain inputs, return undefined */ get firstInput() { return this.inputs[0]; } /** * Return first Tool`s input * If Block doesn't contain inputs, return undefined */ get lastInput() { const e = this.inputs; return e[e.length - 1]; } /** * Return next Tool`s input or undefined if it doesn't exist * If Block doesn't contain inputs, return undefined */ get nextInput() { return this.inputs[this.inputIndex + 1]; } /** * Return previous Tool`s input or undefined if it doesn't exist * If Block doesn't contain inputs, return undefined */ get previousInput() { return this.inputs[this.inputIndex - 1]; } /** * Get Block's JSON data * * @returns {object} */ get data() { return this.save().then((e) => e && !V$2(e.data) ? e.data : {}); } /** * Returns tool's sanitizer config * * @returns {object} */ get sanitize() { return this.tool.sanitizeConfig; } /** * is block mergeable * We plugin have merge function then we call it mergeable * * @returns {boolean} */ get mergeable() { return A$4(this.toolInstance.merge); } /** * If Block contains inputs, it is focusable */ get focusable() { return this.inputs.length !== 0; } /** * Check block for emptiness * * @returns {boolean} */ get isEmpty() { const e = u$1.isEmpty(this.pluginsContent, "/"), t = !this.hasMedia; return e && t; } /** * Check if block has a media content such as images, iframe and other * * @returns {boolean} */ get hasMedia() { const e = [ "img", "iframe", "video", "audio", "source", "input", "textarea", "twitterwidget" ]; return !!this.holder.querySelector(e.join(",")); } /** * Set selected state * We don't need to mark Block as Selected when it is empty * * @param {boolean} state - 'true' to select, 'false' to remove selection */ set selected(e) { var i, s2; this.holder.classList.toggle(R2.CSS.selected, e); const t = e === true && b$3.isRangeInsideContainer(this.holder), o2 = e === false && b$3.isFakeCursorInsideContainer(this.holder); (t || o2) && ((i = this.editorEventBus) == null || i.emit(zo, { state: e }), t ? b$3.addFakeCursor() : b$3.removeFakeCursor(this.holder), (s2 = this.editorEventBus) == null || s2.emit(Uo, { state: e })); } /** * Returns True if it is Selected * * @returns {boolean} */ get selected() { return this.holder.classList.contains(R2.CSS.selected); } /** * Set stretched state * * @param {boolean} state - 'true' to enable, 'false' to disable stretched state */ set stretched(e) { this.holder.classList.toggle(R2.CSS.wrapperStretched, e); } /** * Return Block's stretched state * * @returns {boolean} */ get stretched() { return this.holder.classList.contains(R2.CSS.wrapperStretched); } /** * Toggle drop target state * * @param {boolean} state - 'true' if block is drop target, false otherwise */ set dropTarget(e) { this.holder.classList.toggle(R2.CSS.dropTarget, e); } /** * Returns Plugins content * * @returns {HTMLElement} */ get pluginsContent() { return this.toolRenderedElement; } /** * Calls Tool's method * * Method checks tool property {MethodName}. Fires method with passes params If it is instance of Function * * @param {string} methodName - method to call * @param {object} params - method argument */ call(e, t) { if (A$4(this.toolInstance[e])) { e === "appendCallback" && S$4( "`appendCallback` hook is deprecated and will be removed in the next major release. Use `rendered` hook instead", "warn" ); try { this.toolInstance[e].call(this.toolInstance, t); } catch (o2) { S$4(`Error during '${e}' call: ${o2.message}`, "error"); } } } /** * Call plugins merge method * * @param {BlockToolData} data - data to merge */ async mergeWith(e) { await this.toolInstance.merge(e); } /** * Extracts data from Block * Groups Tool's save processing time * * @returns {object} */ async save() { const e = await this.toolInstance.save(this.pluginsContent), t = this.unavailableTunesData; [ ...this.tunesInstances.entries(), ...this.defaultTunesInstances.entries() ].forEach(([s2, r2]) => { if (A$4(r2.save)) try { t[s2] = r2.save(); } catch (a2) { S$4(`Tune ${r2.constructor.name} save method throws an Error %o`, "warn", a2); } }); const o2 = window.performance.now(); let i; return Promise.resolve(e).then((s2) => (i = window.performance.now(), { id: this.id, tool: this.name, data: s2, tunes: t, time: i - o2 })).catch((s2) => { S$4(`Saving process for ${this.name} tool failed due to the ${s2}`, "log", "red"); }); } /** * Uses Tool's validation method to check the correctness of output data * Tool's validation method is optional * * @description Method returns true|false whether data passed the validation or not * @param {BlockToolData} data - data to validate * @returns {Promise} valid */ async validate(e) { let t = true; return this.toolInstance.validate instanceof Function && (t = await this.toolInstance.validate(e)), t; } /** * Returns data to render in Block Tunes menu. * Splits block tunes into 2 groups: block specific tunes and common tunes */ getTunes() { const e = [], t = [], o2 = typeof this.toolInstance.renderSettings == "function" ? this.toolInstance.renderSettings() : []; return u$1.isElement(o2) ? e.push({ type: _$2.Html, element: o2 }) : Array.isArray(o2) ? e.push(...o2) : e.push(o2), [ ...this.tunesInstances.values(), ...this.defaultTunesInstances.values() ].map((s2) => s2.render()).forEach((s2) => { u$1.isElement(s2) ? t.push({ type: _$2.Html, element: s2 }) : Array.isArray(s2) ? t.push(...s2) : t.push(s2); }), { toolTunes: e, commonTunes: t }; } /** * Update current input index with selection anchor node */ updateCurrentInput() { this.currentInput = u$1.isNativeInput(document.activeElement) || !b$3.anchorNode ? document.activeElement : b$3.anchorNode; } /** * Allows to say Editor that Block was changed. Used to manually trigger Editor's 'onChange' callback * Can be useful for block changes invisible for editor core. */ dispatchChange() { this.didMutated(); } /** * Call Tool instance destroy method */ destroy() { this.unwatchBlockMutations(), this.removeInputEvents(), super.destroy(), A$4(this.toolInstance.destroy) && this.toolInstance.destroy(); } /** * Tool could specify several entries to be displayed at the Toolbox (for example, "Heading 1", "Heading 2", "Heading 3") * This method returns the entry that is related to the Block (depended on the Block data) */ async getActiveToolboxEntry() { const e = this.tool.toolbox; if (e.length === 1) return Promise.resolve(this.tool.toolbox[0]); const t = await this.data, o2 = e; return o2 == null ? void 0 : o2.find((i) => Wo(i.data, t)); } /** * Exports Block data as string using conversion config */ async exportDataAsString() { const e = await this.data; return fi(e, this.tool.conversionConfig); } /** * Make default Block wrappers and put Tool`s content there * * @returns {HTMLDivElement} */ compose() { const e = u$1.make("div", R2.CSS.wrapper), t = u$1.make("div", R2.CSS.content), o2 = this.toolInstance.render(); e.dataset.id = this.id, this.toolRenderedElement = o2, t.appendChild(this.toolRenderedElement); let i = t; return [...this.tunesInstances.values(), ...this.defaultTunesInstances.values()].forEach((s2) => { if (A$4(s2.wrap)) try { i = s2.wrap(i); } catch (r2) { S$4(`Tune ${s2.constructor.name} wrap method throws an Error %o`, "warn", r2); } }), e.appendChild(i), e; } /** * Instantiate Block Tunes * * @param tunesData - current Block tunes data * @private */ composeTunes(e) { Array.from(this.tunes.values()).forEach((t) => { (t.isInternal ? this.defaultTunesInstances : this.tunesInstances).set(t.name, t.create(e[t.name], this.blockAPI)); }), Object.entries(e).forEach(([t, o2]) => { this.tunesInstances.has(t) || (this.unavailableTunesData[t] = o2); }); } /** * Adds focus event listeners to all inputs and contenteditable */ addInputEvents() { this.inputs.forEach((e) => { e.addEventListener("focus", this.handleFocus), u$1.isNativeInput(e) && e.addEventListener("input", this.didMutated); }); } /** * removes focus event listeners from all inputs and contenteditable */ removeInputEvents() { this.inputs.forEach((e) => { e.removeEventListener("focus", this.handleFocus), u$1.isNativeInput(e) && e.removeEventListener("input", this.didMutated); }); } /** * Listen common editor Dom Changed event and detect mutations related to the Block */ watchBlockMutations() { var e; this.redactorDomChangedCallback = (t) => { const { mutations: o2 } = t; o2.some((s2) => pi(s2, this.toolRenderedElement)) && this.didMutated(o2); }, (e = this.editorEventBus) == null || e.on(ft$1, this.redactorDomChangedCallback); } /** * Remove redactor dom change event listener */ unwatchBlockMutations() { var e; (e = this.editorEventBus) == null || e.off(ft$1, this.redactorDomChangedCallback); } /** * Sometimes Tool can replace own main element, for example H2 -> H4 or UL -> OL * We need to detect such changes and update a link to tools main element with the new one * * @param mutations - records of block content mutations */ detectToolRootChange(e) { e.forEach((t) => { if (Array.from(t.removedNodes).includes(this.toolRenderedElement)) { const i = t.addedNodes[t.addedNodes.length - 1]; this.toolRenderedElement = i; } }); } /** * Clears inputs cached value */ dropInputsCache() { this.cachedInputs = []; } /** * Mark inputs with 'data-empty' attribute with the empty state */ toggleInputsEmptyMark() { this.inputs.forEach(Do); } }; class gi extends E$3 { constructor() { super(...arguments), this.insert = (e = this.config.defaultBlock, t = {}, o2 = {}, i, s2, r2, a2) => { const l2 = this.Editor.BlockManager.insert({ id: a2, tool: e, data: t, index: i, needToFocus: s2, replace: r2 }); return new J$2(l2); }, this.composeBlockData = async (e) => { const t = this.Editor.Tools.blockTools.get(e); return new R$5({ tool: t, api: this.Editor.API, readOnly: true, data: {}, tunesData: {} }).data; }, this.update = async (e, t, o2) => { const { BlockManager: i } = this.Editor, s2 = i.getBlockById(e); if (s2 === void 0) throw new Error(`Block with id "${e}" not found`); const r2 = await i.update(s2, t, o2); return new J$2(r2); }, this.convert = async (e, t, o2) => { var h2, p2; const { BlockManager: i, Tools: s2 } = this.Editor, r2 = i.getBlockById(e); if (!r2) throw new Error(`Block with id "${e}" not found`); const a2 = s2.blockTools.get(r2.name), l2 = s2.blockTools.get(t); if (!l2) throw new Error(`Block Tool with type "${t}" not found`); const c2 = ((h2 = a2 == null ? void 0 : a2.conversionConfig) == null ? void 0 : h2.export) !== void 0, d2 = ((p2 = l2.conversionConfig) == null ? void 0 : p2.import) !== void 0; if (c2 && d2) { const g2 = await i.convert(r2, t, o2); return new J$2(g2); } else { const g2 = [ c2 ? false : je$1(r2.name), d2 ? false : je$1(t) ].filter(Boolean).join(" and "); throw new Error(`Conversion from "${r2.name}" to "${t}" is not possible. ${g2} tool(s) should provide a "conversionConfig"`); } }, this.insertMany = (e, t = this.Editor.BlockManager.blocks.length - 1) => { this.validateIndex(t); const o2 = e.map(({ id: i, type: s2, data: r2 }) => this.Editor.BlockManager.composeBlock({ id: i, tool: s2 || this.config.defaultBlock, data: r2 })); return this.Editor.BlockManager.insertMany(o2, t), o2.map((i) => new J$2(i)); }; } /** * Available methods * * @returns {Blocks} */ get methods() { return { clear: () => this.clear(), render: (e) => this.render(e), renderFromHTML: (e) => this.renderFromHTML(e), delete: (e) => this.delete(e), swap: (e, t) => this.swap(e, t), move: (e, t) => this.move(e, t), getBlockByIndex: (e) => this.getBlockByIndex(e), getById: (e) => this.getById(e), getCurrentBlockIndex: () => this.getCurrentBlockIndex(), getBlockIndex: (e) => this.getBlockIndex(e), getBlocksCount: () => this.getBlocksCount(), getBlockByElement: (e) => this.getBlockByElement(e), stretchBlock: (e, t = true) => this.stretchBlock(e, t), insertNewBlock: () => this.insertNewBlock(), insert: this.insert, insertMany: this.insertMany, update: this.update, composeBlockData: this.composeBlockData, convert: this.convert }; } /** * Returns Blocks count * * @returns {number} */ getBlocksCount() { return this.Editor.BlockManager.blocks.length; } /** * Returns current block index * * @returns {number} */ getCurrentBlockIndex() { return this.Editor.BlockManager.currentBlockIndex; } /** * Returns the index of Block by id; * * @param id - block id */ getBlockIndex(e) { const t = this.Editor.BlockManager.getBlockById(e); if (!t) { X$2("There is no block with id `" + e + "`", "warn"); return; } return this.Editor.BlockManager.getBlockIndex(t); } /** * Returns BlockAPI object by Block index * * @param {number} index - index to get */ getBlockByIndex(e) { const t = this.Editor.BlockManager.getBlockByIndex(e); if (t === void 0) { X$2("There is no block at index `" + e + "`", "warn"); return; } return new J$2(t); } /** * Returns BlockAPI object by Block id * * @param id - id of block to get */ getById(e) { const t = this.Editor.BlockManager.getBlockById(e); return t === void 0 ? (X$2("There is no block with id `" + e + "`", "warn"), null) : new J$2(t); } /** * Get Block API object by any child html element * * @param element - html element to get Block by */ getBlockByElement(e) { const t = this.Editor.BlockManager.getBlock(e); if (t === void 0) { X$2("There is no block corresponding to element `" + e + "`", "warn"); return; } return new J$2(t); } /** * Call Block Manager method that swap Blocks * * @param {number} fromIndex - position of first Block * @param {number} toIndex - position of second Block * @deprecated — use 'move' instead */ swap(e, t) { S$4( "`blocks.swap()` method is deprecated and will be removed in the next major release. Use `block.move()` method instead", "info" ), this.Editor.BlockManager.swap(e, t); } /** * Move block from one index to another * * @param {number} toIndex - index to move to * @param {number} fromIndex - index to move from */ move(e, t) { this.Editor.BlockManager.move(e, t); } /** * Deletes Block * * @param {number} blockIndex - index of Block to delete */ delete(e = this.Editor.BlockManager.currentBlockIndex) { try { const t = this.Editor.BlockManager.getBlockByIndex(e); this.Editor.BlockManager.removeBlock(t); } catch (t) { X$2(t, "warn"); return; } this.Editor.BlockManager.blocks.length === 0 && this.Editor.BlockManager.insert(), this.Editor.BlockManager.currentBlock && this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock, this.Editor.Caret.positions.END), this.Editor.Toolbar.close(); } /** * Clear Editor's area */ async clear() { await this.Editor.BlockManager.clear(true), this.Editor.InlineToolbar.close(); } /** * Fills Editor with Blocks data * * @param {OutputData} data — Saved Editor data */ async render(e) { if (e === void 0 || e.blocks === void 0) throw new Error("Incorrect data passed to the render() method"); this.Editor.ModificationsObserver.disable(), await this.Editor.BlockManager.clear(), await this.Editor.Renderer.render(e.blocks), this.Editor.ModificationsObserver.enable(); } /** * Render passed HTML string * * @param {string} data - HTML string to render * @returns {Promise} */ async renderFromHTML(e) { return await this.Editor.BlockManager.clear(), this.Editor.Paste.processText(e, true); } /** * Stretch Block's content * * @param {number} index - index of Block to stretch * @param {boolean} status - true to enable, false to disable * @deprecated Use BlockAPI interface to stretch Blocks */ stretchBlock(e, t = true) { ht$1( true, "blocks.stretchBlock()", "BlockAPI" ); const o2 = this.Editor.BlockManager.getBlockByIndex(e); o2 && (o2.stretched = t); } /** * Insert new Block * After set caret to this Block * * @todo remove in 3.0.0 * @deprecated with insert() method */ insertNewBlock() { S$4("Method blocks.insertNewBlock() is deprecated and it will be removed in the next major release. Use blocks.insert() instead.", "warn"), this.insert(); } /** * Validated block index and throws an error if it's invalid * * @param index - index to validate */ validateIndex(e) { if (typeof e != "number") throw new Error("Index should be a number"); if (e < 0) throw new Error("Index should be greater than or equal to 0"); if (e === null) throw new Error("Index should be greater than or equal to 0"); } } function mi(n2, e) { return typeof n2 == "number" ? e.BlockManager.getBlockByIndex(n2) : typeof n2 == "string" ? e.BlockManager.getBlockById(n2) : e.BlockManager.getBlockById(n2.id); } class bi extends E$3 { constructor() { super(...arguments), this.setToFirstBlock = (e = this.Editor.Caret.positions.DEFAULT, t = 0) => this.Editor.BlockManager.firstBlock ? (this.Editor.Caret.setToBlock(this.Editor.BlockManager.firstBlock, e, t), true) : false, this.setToLastBlock = (e = this.Editor.Caret.positions.DEFAULT, t = 0) => this.Editor.BlockManager.lastBlock ? (this.Editor.Caret.setToBlock(this.Editor.BlockManager.lastBlock, e, t), true) : false, this.setToPreviousBlock = (e = this.Editor.Caret.positions.DEFAULT, t = 0) => this.Editor.BlockManager.previousBlock ? (this.Editor.Caret.setToBlock(this.Editor.BlockManager.previousBlock, e, t), true) : false, this.setToNextBlock = (e = this.Editor.Caret.positions.DEFAULT, t = 0) => this.Editor.BlockManager.nextBlock ? (this.Editor.Caret.setToBlock(this.Editor.BlockManager.nextBlock, e, t), true) : false, this.setToBlock = (e, t = this.Editor.Caret.positions.DEFAULT, o2 = 0) => { const i = mi(e, this.Editor); return i === void 0 ? false : (this.Editor.Caret.setToBlock(i, t, o2), true); }, this.focus = (e = false) => e ? this.setToLastBlock(this.Editor.Caret.positions.END) : this.setToFirstBlock(this.Editor.Caret.positions.START); } /** * Available methods * * @returns {Caret} */ get methods() { return { setToFirstBlock: this.setToFirstBlock, setToLastBlock: this.setToLastBlock, setToPreviousBlock: this.setToPreviousBlock, setToNextBlock: this.setToNextBlock, setToBlock: this.setToBlock, focus: this.focus }; } } class vi extends E$3 { /** * Available methods * * @returns {Events} */ get methods() { return { emit: (e, t) => this.emit(e, t), off: (e, t) => this.off(e, t), on: (e, t) => this.on(e, t) }; } /** * Subscribe on Events * * @param {string} eventName - event name to subscribe * @param {Function} callback - event handler */ on(e, t) { this.eventsDispatcher.on(e, t); } /** * Emit event with data * * @param {string} eventName - event to emit * @param {object} data - event's data */ emit(e, t) { this.eventsDispatcher.emit(e, t); } /** * Unsubscribe from Event * * @param {string} eventName - event to unsubscribe * @param {Function} callback - event handler */ off(e, t) { this.eventsDispatcher.off(e, t); } } let kt$2 = class kt2 extends E$3 { /** * Return namespace section for tool or block tune * * @param toolName - tool name * @param isTune - is tool a block tune */ static getNamespace(e, t) { return t ? `blockTunes.${e}` : `tools.${e}`; } /** * Return I18n API methods with global dictionary access */ get methods() { return { t: () => { X$2("I18n.t() method can be accessed only from Tools", "warn"); } }; } /** * Return I18n API methods with tool namespaced dictionary * * @param toolName - tool name * @param isTune - is tool a block tune */ getMethodsForTool(e, t) { return Object.assign( this.methods, { t: (o2) => z$2.t(kt2.getNamespace(e, t), o2) } ); } }; class ki extends E$3 { /** * Editor.js Core API modules */ get methods() { return { blocks: this.Editor.BlocksAPI.methods, caret: this.Editor.CaretAPI.methods, tools: this.Editor.ToolsAPI.methods, events: this.Editor.EventsAPI.methods, listeners: this.Editor.ListenersAPI.methods, notifier: this.Editor.NotifierAPI.methods, sanitizer: this.Editor.SanitizerAPI.methods, saver: this.Editor.SaverAPI.methods, selection: this.Editor.SelectionAPI.methods, styles: this.Editor.StylesAPI.classes, toolbar: this.Editor.ToolbarAPI.methods, inlineToolbar: this.Editor.InlineToolbarAPI.methods, tooltip: this.Editor.TooltipAPI.methods, i18n: this.Editor.I18nAPI.methods, readOnly: this.Editor.ReadOnlyAPI.methods, ui: this.Editor.UiAPI.methods }; } /** * Returns Editor.js Core API methods for passed tool * * @param toolName - tool name * @param isTune - is tool a block tune */ getMethodsForTool(e, t) { return Object.assign( this.methods, { i18n: this.Editor.I18nAPI.getMethodsForTool(e, t) } ); } } class yi extends E$3 { /** * Available methods * * @returns {InlineToolbar} */ get methods() { return { close: () => this.close(), open: () => this.open() }; } /** * Open Inline Toolbar */ open() { this.Editor.InlineToolbar.tryToShow(); } /** * Close Inline Toolbar */ close() { this.Editor.InlineToolbar.close(); } } class wi extends E$3 { /** * Available methods * * @returns {Listeners} */ get methods() { return { on: (e, t, o2, i) => this.on(e, t, o2, i), off: (e, t, o2, i) => this.off(e, t, o2, i), offById: (e) => this.offById(e) }; } /** * Ads a DOM event listener. Return it's id. * * @param {HTMLElement} element - Element to set handler to * @param {string} eventType - event type * @param {() => void} handler - event handler * @param {boolean} useCapture - capture event or not */ on(e, t, o2, i) { return this.listeners.on(e, t, o2, i); } /** * Removes DOM listener from element * * @param {Element} element - Element to remove handler from * @param eventType - event type * @param handler - event handler * @param {boolean} useCapture - capture event or not */ off(e, t, o2, i) { this.listeners.off(e, t, o2, i); } /** * Removes DOM listener by the listener id * * @param id - id of the listener to remove */ offById(e) { this.listeners.offById(e); } } var Ko = { exports: {} }; (function(n2, e) { (function(t, o2) { n2.exports = o2(); })(window, function() { return function(t) { var o2 = {}; function i(s2) { if (o2[s2]) return o2[s2].exports; var r2 = o2[s2] = { i: s2, l: false, exports: {} }; return t[s2].call(r2.exports, r2, r2.exports, i), r2.l = true, r2.exports; } return i.m = t, i.c = o2, i.d = function(s2, r2, a2) { i.o(s2, r2) || Object.defineProperty(s2, r2, { enumerable: true, get: a2 }); }, i.r = function(s2) { typeof Symbol < "u" && Symbol.toStringTag && Object.defineProperty(s2, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(s2, "__esModule", { value: true }); }, i.t = function(s2, r2) { if (1 & r2 && (s2 = i(s2)), 8 & r2 || 4 & r2 && typeof s2 == "object" && s2 && s2.__esModule) return s2; var a2 = /* @__PURE__ */ Object.create(null); if (i.r(a2), Object.defineProperty(a2, "default", { enumerable: true, value: s2 }), 2 & r2 && typeof s2 != "string") for (var l2 in s2) i.d(a2, l2, (function(c2) { return s2[c2]; }).bind(null, l2)); return a2; }, i.n = function(s2) { var r2 = s2 && s2.__esModule ? function() { return s2.default; } : function() { return s2; }; return i.d(r2, "a", r2), r2; }, i.o = function(s2, r2) { return Object.prototype.hasOwnProperty.call(s2, r2); }, i.p = "/", i(i.s = 0); }([function(t, o2, i) { i(1), /*! * Codex JavaScript Notification module * https://github.com/codex-team/js-notifier */ t.exports = function() { var s2 = i(6), r2 = "cdx-notify--bounce-in", a2 = null; return { show: function(l2) { if (l2.message) { (function() { if (a2) return true; a2 = s2.getWrapper(), document.body.appendChild(a2); })(); var c2 = null, d2 = l2.time || 8e3; switch (l2.type) { case "confirm": c2 = s2.confirm(l2); break; case "prompt": c2 = s2.prompt(l2); break; default: c2 = s2.alert(l2), window.setTimeout(function() { c2.remove(); }, d2); } a2.appendChild(c2), c2.classList.add(r2); } } }; }(); }, function(t, o2, i) { var s2 = i(2); typeof s2 == "string" && (s2 = [[t.i, s2, ""]]); var r2 = { hmr: true, transform: void 0, insertInto: void 0 }; i(4)(s2, r2), s2.locals && (t.exports = s2.locals); }, function(t, o2, i) { (t.exports = i(3)(false)).push([t.i, `.cdx-notify--error{background:#fffbfb!important}.cdx-notify--error::before{background:#fb5d5d!important}.cdx-notify__input{max-width:130px;padding:5px 10px;background:#f7f7f7;border:0;border-radius:3px;font-size:13px;color:#656b7c;outline:0}.cdx-notify__input:-ms-input-placeholder{color:#656b7c}.cdx-notify__input::placeholder{color:#656b7c}.cdx-notify__input:focus:-ms-input-placeholder{color:rgba(101,107,124,.3)}.cdx-notify__input:focus::placeholder{color:rgba(101,107,124,.3)}.cdx-notify__button{border:none;border-radius:3px;font-size:13px;padding:5px 10px;cursor:pointer}.cdx-notify__button:last-child{margin-left:10px}.cdx-notify__button--cancel{background:#f2f5f7;box-shadow:0 2px 1px 0 rgba(16,19,29,0);color:#656b7c}.cdx-notify__button--cancel:hover{background:#eee}.cdx-notify__button--confirm{background:#34c992;box-shadow:0 1px 1px 0 rgba(18,49,35,.05);color:#fff}.cdx-notify__button--confirm:hover{background:#33b082}.cdx-notify__btns-wrapper{display:-ms-flexbox;display:flex;-ms-flex-flow:row nowrap;flex-flow:row nowrap;margin-top:5px}.cdx-notify__cross{position:absolute;top:5px;right:5px;width:10px;height:10px;padding:5px;opacity:.54;cursor:pointer}.cdx-notify__cross::after,.cdx-notify__cross::before{content:'';position:absolute;left:9px;top:5px;height:12px;width:2px;background:#575d67}.cdx-notify__cross::before{transform:rotate(-45deg)}.cdx-notify__cross::after{transform:rotate(45deg)}.cdx-notify__cross:hover{opacity:1}.cdx-notifies{position:fixed;z-index:2;bottom:20px;left:20px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif}.cdx-notify{position:relative;width:220px;margin-top:15px;padding:13px 16px;background:#fff;box-shadow:0 11px 17px 0 rgba(23,32,61,.13);border-radius:5px;font-size:14px;line-height:1.4em;word-wrap:break-word}.cdx-notify::before{content:'';position:absolute;display:block;top:0;left:0;width:3px;height:calc(100% - 6px);margin:3px;border-radius:5px;background:0 0}@keyframes bounceIn{0%{opacity:0;transform:scale(.3)}50%{opacity:1;transform:scale(1.05)}70%{transform:scale(.9)}100%{transform:scale(1)}}.cdx-notify--bounce-in{animation-name:bounceIn;animation-duration:.6s;animation-iteration-count:1}.cdx-notify--success{background:#fafffe!important}.cdx-notify--success::before{background:#41ffb1!important}`, ""]); }, function(t, o2) { t.exports = function(i) { var s2 = []; return s2.toString = function() { return this.map(function(r2) { var a2 = function(l2, c2) { var d2 = l2[1] || "", h2 = l2[3]; if (!h2) return d2; if (c2 && typeof btoa == "function") { var p2 = (f2 = h2, "/*# sourceMappingURL=data:application/json;charset=utf-8;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(f2)))) + " */"), g2 = h2.sources.map(function(v2) { return "/*# sourceURL=" + h2.sourceRoot + v2 + " */"; }); return [d2].concat(g2).concat([p2]).join(` `); } var f2; return [d2].join(` `); }(r2, i); return r2[2] ? "@media " + r2[2] + "{" + a2 + "}" : a2; }).join(""); }, s2.i = function(r2, a2) { typeof r2 == "string" && (r2 = [[null, r2, ""]]); for (var l2 = {}, c2 = 0; c2 < this.length; c2++) { var d2 = this[c2][0]; typeof d2 == "number" && (l2[d2] = true); } for (c2 = 0; c2 < r2.length; c2++) { var h2 = r2[c2]; typeof h2[0] == "number" && l2[h2[0]] || (a2 && !h2[2] ? h2[2] = a2 : a2 && (h2[2] = "(" + h2[2] + ") and (" + a2 + ")"), s2.push(h2)); } }, s2; }; }, function(t, o2, i) { var s2, r2, a2 = {}, l2 = (s2 = function() { return window && document && document.all && !window.atob; }, function() { return r2 === void 0 && (r2 = s2.apply(this, arguments)), r2; }), c2 = function(k2) { var m2 = {}; return function(w2) { if (typeof w2 == "function") return w2(); if (m2[w2] === void 0) { var x2 = (function(I2) { return document.querySelector(I2); }).call(this, w2); if (window.HTMLIFrameElement && x2 instanceof window.HTMLIFrameElement) try { x2 = x2.contentDocument.head; } catch { x2 = null; } m2[w2] = x2; } return m2[w2]; }; }(), d2 = null, h2 = 0, p2 = [], g2 = i(5); function f2(k2, m2) { for (var w2 = 0; w2 < k2.length; w2++) { var x2 = k2[w2], I2 = a2[x2.id]; if (I2) { I2.refs++; for (var C2 = 0; C2 < I2.parts.length; C2++) I2.parts[C2](x2.parts[C2]); for (; C2 < x2.parts.length; C2++) I2.parts.push(F2(x2.parts[C2], m2)); } else { var N2 = []; for (C2 = 0; C2 < x2.parts.length; C2++) N2.push(F2(x2.parts[C2], m2)); a2[x2.id] = { id: x2.id, refs: 1, parts: N2 }; } } } function v2(k2, m2) { for (var w2 = [], x2 = {}, I2 = 0; I2 < k2.length; I2++) { var C2 = k2[I2], N2 = m2.base ? C2[0] + m2.base : C2[0], B2 = { css: C2[1], media: C2[2], sourceMap: C2[3] }; x2[N2] ? x2[N2].parts.push(B2) : w2.push(x2[N2] = { id: N2, parts: [B2] }); } return w2; } function O2(k2, m2) { var w2 = c2(k2.insertInto); if (!w2) throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid."); var x2 = p2[p2.length - 1]; if (k2.insertAt === "top") x2 ? x2.nextSibling ? w2.insertBefore(m2, x2.nextSibling) : w2.appendChild(m2) : w2.insertBefore(m2, w2.firstChild), p2.push(m2); else if (k2.insertAt === "bottom") w2.appendChild(m2); else { if (typeof k2.insertAt != "object" || !k2.insertAt.before) throw new Error(`[Style Loader] Invalid value for parameter 'insertAt' ('options.insertAt') found. Must be 'top', 'bottom', or Object. (https://github.com/webpack-contrib/style-loader#insertat) `); var I2 = c2(k2.insertInto + " " + k2.insertAt.before); w2.insertBefore(m2, I2); } } function T2(k2) { if (k2.parentNode === null) return false; k2.parentNode.removeChild(k2); var m2 = p2.indexOf(k2); m2 >= 0 && p2.splice(m2, 1); } function M2(k2) { var m2 = document.createElement("style"); return k2.attrs.type === void 0 && (k2.attrs.type = "text/css"), q2(m2, k2.attrs), O2(k2, m2), m2; } function q2(k2, m2) { Object.keys(m2).forEach(function(w2) { k2.setAttribute(w2, m2[w2]); }); } function F2(k2, m2) { var w2, x2, I2, C2; if (m2.transform && k2.css) { if (!(C2 = m2.transform(k2.css))) return function() { }; k2.css = C2; } if (m2.singleton) { var N2 = h2++; w2 = d2 || (d2 = M2(m2)), x2 = ie2.bind(null, w2, N2, false), I2 = ie2.bind(null, w2, N2, true); } else k2.sourceMap && typeof URL == "function" && typeof URL.createObjectURL == "function" && typeof URL.revokeObjectURL == "function" && typeof Blob == "function" && typeof btoa == "function" ? (w2 = function(B2) { var W2 = document.createElement("link"); return B2.attrs.type === void 0 && (B2.attrs.type = "text/css"), B2.attrs.rel = "stylesheet", q2(W2, B2.attrs), O2(B2, W2), W2; }(m2), x2 = (function(B2, W2, ve2) { var se2 = ve2.css, tt2 = ve2.sourceMap, Yn2 = W2.convertToAbsoluteUrls === void 0 && tt2; (W2.convertToAbsoluteUrls || Yn2) && (se2 = g2(se2)), tt2 && (se2 += ` /*# sourceMappingURL=data:application/json;base64,` + btoa(unescape(encodeURIComponent(JSON.stringify(tt2)))) + " */"); var Kn2 = new Blob([se2], { type: "text/css" }), ko = B2.href; B2.href = URL.createObjectURL(Kn2), ko && URL.revokeObjectURL(ko); }).bind(null, w2, m2), I2 = function() { T2(w2), w2.href && URL.revokeObjectURL(w2.href); }) : (w2 = M2(m2), x2 = (function(B2, W2) { var ve2 = W2.css, se2 = W2.media; if (se2 && B2.setAttribute("media", se2), B2.styleSheet) B2.styleSheet.cssText = ve2; else { for (; B2.firstChild; ) B2.removeChild(B2.firstChild); B2.appendChild(document.createTextNode(ve2)); } }).bind(null, w2), I2 = function() { T2(w2); }); return x2(k2), function(B2) { if (B2) { if (B2.css === k2.css && B2.media === k2.media && B2.sourceMap === k2.sourceMap) return; x2(k2 = B2); } else I2(); }; } t.exports = function(k2, m2) { if (typeof DEBUG < "u" && DEBUG && typeof document != "object") throw new Error("The style-loader cannot be used in a non-browser environment"); (m2 = m2 || {}).attrs = typeof m2.attrs == "object" ? m2.attrs : {}, m2.singleton || typeof m2.singleton == "boolean" || (m2.singleton = l2()), m2.insertInto || (m2.insertInto = "head"), m2.insertAt || (m2.insertAt = "bottom"); var w2 = v2(k2, m2); return f2(w2, m2), function(x2) { for (var I2 = [], C2 = 0; C2 < w2.length; C2++) { var N2 = w2[C2]; (B2 = a2[N2.id]).refs--, I2.push(B2); } for (x2 && f2(v2(x2, m2), m2), C2 = 0; C2 < I2.length; C2++) { var B2; if ((B2 = I2[C2]).refs === 0) { for (var W2 = 0; W2 < B2.parts.length; W2++) B2.parts[W2](); delete a2[B2.id]; } } }; }; var H2, Q2 = (H2 = [], function(k2, m2) { return H2[k2] = m2, H2.filter(Boolean).join(` `); }); function ie2(k2, m2, w2, x2) { var I2 = w2 ? "" : x2.css; if (k2.styleSheet) k2.styleSheet.cssText = Q2(m2, I2); else { var C2 = document.createTextNode(I2), N2 = k2.childNodes; N2[m2] && k2.removeChild(N2[m2]), N2.length ? k2.insertBefore(C2, N2[m2]) : k2.appendChild(C2); } } }, function(t, o2) { t.exports = function(i) { var s2 = typeof window < "u" && window.location; if (!s2) throw new Error("fixUrls requires window.location"); if (!i || typeof i != "string") return i; var r2 = s2.protocol + "//" + s2.host, a2 = r2 + s2.pathname.replace(/\/[^\/]*$/, "/"); return i.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(l2, c2) { var d2, h2 = c2.trim().replace(/^"(.*)"$/, function(p2, g2) { return g2; }).replace(/^'(.*)'$/, function(p2, g2) { return g2; }); return /^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(h2) ? l2 : (d2 = h2.indexOf("//") === 0 ? h2 : h2.indexOf("/") === 0 ? r2 + h2 : a2 + h2.replace(/^\.\//, ""), "url(" + JSON.stringify(d2) + ")"); }); }; }, function(t, o2, i) { var s2, r2, a2, l2, c2, d2, h2, p2, g2; t.exports = (s2 = "cdx-notifies", r2 = "cdx-notify", a2 = "cdx-notify__cross", l2 = "cdx-notify__button--confirm", c2 = "cdx-notify__button--cancel", d2 = "cdx-notify__input", h2 = "cdx-notify__button", p2 = "cdx-notify__btns-wrapper", { alert: g2 = function(f2) { var v2 = document.createElement("DIV"), O2 = document.createElement("DIV"), T2 = f2.message, M2 = f2.style; return v2.classList.add(r2), M2 && v2.classList.add(r2 + "--" + M2), v2.innerHTML = T2, O2.classList.add(a2), O2.addEventListener("click", v2.remove.bind(v2)), v2.appendChild(O2), v2; }, confirm: function(f2) { var v2 = g2(f2), O2 = document.createElement("div"), T2 = document.createElement("button"), M2 = document.createElement("button"), q2 = v2.querySelector("." + a2), F2 = f2.cancelHandler, H2 = f2.okHandler; return O2.classList.add(p2), T2.innerHTML = f2.okText || "Confirm", M2.innerHTML = f2.cancelText || "Cancel", T2.classList.add(h2), M2.classList.add(h2), T2.classList.add(l2), M2.classList.add(c2), F2 && typeof F2 == "function" && (M2.addEventListener("click", F2), q2.addEventListener("click", F2)), H2 && typeof H2 == "function" && T2.addEventListener("click", H2), T2.addEventListener("click", v2.remove.bind(v2)), M2.addEventListener("click", v2.remove.bind(v2)), O2.appendChild(T2), O2.appendChild(M2), v2.appendChild(O2), v2; }, prompt: function(f2) { var v2 = g2(f2), O2 = document.createElement("div"), T2 = document.createElement("button"), M2 = document.createElement("input"), q2 = v2.querySelector("." + a2), F2 = f2.cancelHandler, H2 = f2.okHandler; return O2.classList.add(p2), T2.innerHTML = f2.okText || "Ok", T2.classList.add(h2), T2.classList.add(l2), M2.classList.add(d2), f2.placeholder && M2.setAttribute("placeholder", f2.placeholder), f2.default && (M2.value = f2.default), f2.inputType && (M2.type = f2.inputType), F2 && typeof F2 == "function" && q2.addEventListener("click", F2), H2 && typeof H2 == "function" && T2.addEventListener("click", function() { H2(M2.value); }), T2.addEventListener("click", v2.remove.bind(v2)), O2.appendChild(M2), O2.appendChild(T2), v2.appendChild(O2), v2; }, getWrapper: function() { var f2 = document.createElement("DIV"); return f2.classList.add(s2), f2; } }); }]); }); })(Ko); var Ei = Ko.exports; const xi = /* @__PURE__ */ Ke$2(Ei); class Bi { /** * Show web notification * * @param {NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions} options - notification options */ show(e) { xi.show(e); } } class Ci extends E$3 { /** * @param moduleConfiguration - Module Configuration * @param moduleConfiguration.config - Editor's config * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher */ constructor({ config: e, eventsDispatcher: t }) { super({ config: e, eventsDispatcher: t }), this.notifier = new Bi(); } /** * Available methods */ get methods() { return { show: (e) => this.show(e) }; } /** * Show notification * * @param {NotifierOptions} options - message option */ show(e) { return this.notifier.show(e); } } class Ti extends E$3 { /** * Available methods */ get methods() { const e = () => this.isEnabled; return { toggle: (t) => this.toggle(t), get isEnabled() { return e(); } }; } /** * Set or toggle read-only state * * @param {boolean|undefined} state - set or toggle state * @returns {boolean} current value */ toggle(e) { return this.Editor.ReadOnly.toggle(e); } /** * Returns current read-only state */ get isEnabled() { return this.Editor.ReadOnly.isEnabled; } } var Xo = { exports: {} }; (function(n2, e) { (function(t, o2) { n2.exports = o2(); })(Ce$1, function() { function t(h2) { var p2 = h2.tags, g2 = Object.keys(p2), f2 = g2.map(function(v2) { return typeof p2[v2]; }).every(function(v2) { return v2 === "object" || v2 === "boolean" || v2 === "function"; }); if (!f2) throw new Error("The configuration was invalid"); this.config = h2; } var o2 = ["P", "LI", "TD", "TH", "DIV", "H1", "H2", "H3", "H4", "H5", "H6", "PRE"]; function i(h2) { return o2.indexOf(h2.nodeName) !== -1; } var s2 = ["A", "B", "STRONG", "I", "EM", "SUB", "SUP", "U", "STRIKE"]; function r2(h2) { return s2.indexOf(h2.nodeName) !== -1; } t.prototype.clean = function(h2) { const p2 = document.implementation.createHTMLDocument(), g2 = p2.createElement("div"); return g2.innerHTML = h2, this._sanitize(p2, g2), g2.innerHTML; }, t.prototype._sanitize = function(h2, p2) { var g2 = a2(h2, p2), f2 = g2.firstChild(); if (f2) do { if (f2.nodeType === Node.TEXT_NODE) if (f2.data.trim() === "" && (f2.previousElementSibling && i(f2.previousElementSibling) || f2.nextElementSibling && i(f2.nextElementSibling))) { p2.removeChild(f2), this._sanitize(h2, p2); break; } else continue; if (f2.nodeType === Node.COMMENT_NODE) { p2.removeChild(f2), this._sanitize(h2, p2); break; } var v2 = r2(f2), O2; v2 && (O2 = Array.prototype.some.call(f2.childNodes, i)); var T2 = !!p2.parentNode, M2 = i(p2) && i(f2) && T2, q2 = f2.nodeName.toLowerCase(), F2 = l2(this.config, q2, f2), H2 = v2 && O2; if (H2 || c2(f2, F2) || !this.config.keepNestedBlockElements && M2) { if (!(f2.nodeName === "SCRIPT" || f2.nodeName === "STYLE")) for (; f2.childNodes.length > 0; ) p2.insertBefore(f2.childNodes[0], f2); p2.removeChild(f2), this._sanitize(h2, p2); break; } for (var Q2 = 0; Q2 < f2.attributes.length; Q2 += 1) { var ie2 = f2.attributes[Q2]; d2(ie2, F2, f2) && (f2.removeAttribute(ie2.name), Q2 = Q2 - 1); } this._sanitize(h2, f2); } while (f2 = g2.nextSibling()); }; function a2(h2, p2) { return h2.createTreeWalker( p2, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT, null, false ); } function l2(h2, p2, g2) { return typeof h2.tags[p2] == "function" ? h2.tags[p2](g2) : h2.tags[p2]; } function c2(h2, p2) { return typeof p2 > "u" ? true : typeof p2 == "boolean" ? !p2 : false; } function d2(h2, p2, g2) { var f2 = h2.name.toLowerCase(); return p2 === true ? false : typeof p2[f2] == "function" ? !p2[f2](h2.value, g2) : typeof p2[f2] > "u" || p2[f2] === false ? true : typeof p2[f2] == "string" ? p2[f2] !== h2.value : false; } return t; }); })(Xo); var Si = Xo.exports; const Ii = /* @__PURE__ */ Ke$2(Si); function yt$1(n2, e) { return n2.map((t) => { const o2 = A$4(e) ? e(t.tool) : e; return V$2(o2) || (t.data = wt$2(t.data, o2)), t; }); } function Z$2(n2, e = {}) { const t = { tags: e }; return new Ii(t).clean(n2); } function wt$2(n2, e) { return Array.isArray(n2) ? Oi(n2, e) : D$3(n2) ? _i(n2, e) : te$2(n2) ? Mi(n2, e) : n2; } function Oi(n2, e) { return n2.map((t) => wt$2(t, e)); } function _i(n2, e) { const t = {}; for (const o2 in n2) { if (!Object.prototype.hasOwnProperty.call(n2, o2)) continue; const i = n2[o2], s2 = Ai(e[o2]) ? e[o2] : e; t[o2] = wt$2(i, s2); } return t; } function Mi(n2, e) { return D$3(e) ? Z$2(n2, e) : e === false ? Z$2(n2, {}) : n2; } function Ai(n2) { return D$3(n2) || Gn$1(n2) || A$4(n2); } class Li extends E$3 { /** * Available methods * * @returns {SanitizerConfig} */ get methods() { return { clean: (e, t) => this.clean(e, t) }; } /** * Perform sanitizing of a string * * @param {string} taintString - what to sanitize * @param {SanitizerConfig} config - sanitizer config * @returns {string} */ clean(e, t) { return Z$2(e, t); } } class Pi extends E$3 { /** * Available methods * * @returns {Saver} */ get methods() { return { save: () => this.save() }; } /** * Return Editor's data * * @returns {OutputData} */ save() { const e = "Editor's content can not be saved in read-only mode"; return this.Editor.ReadOnly.isEnabled ? (X$2(e, "warn"), Promise.reject(new Error(e))) : this.Editor.Saver.save(); } } class Ni extends E$3 { constructor() { super(...arguments), this.selectionUtils = new b$3(); } /** * Available methods * * @returns {SelectionAPIInterface} */ get methods() { return { findParentTag: (e, t) => this.findParentTag(e, t), expandToTag: (e) => this.expandToTag(e), save: () => this.selectionUtils.save(), restore: () => this.selectionUtils.restore(), setFakeBackground: () => this.selectionUtils.setFakeBackground(), removeFakeBackground: () => this.selectionUtils.removeFakeBackground() }; } /** * Looks ahead from selection and find passed tag with class name * * @param {string} tagName - tag to find * @param {string} className - tag's class name * @returns {HTMLElement|null} */ findParentTag(e, t) { return this.selectionUtils.findParentTag(e, t); } /** * Expand selection to passed tag * * @param {HTMLElement} node - tag that should contain selection */ expandToTag(e) { this.selectionUtils.expandToTag(e); } } class Ri extends E$3 { /** * Available methods */ get methods() { return { getBlockTools: () => Array.from(this.Editor.Tools.blockTools.values()) }; } } class Di extends E$3 { /** * Exported classes */ get classes() { return { /** * Base Block styles */ block: "cdx-block", /** * Inline Tools styles */ inlineToolButton: "ce-inline-tool", inlineToolButtonActive: "ce-inline-tool--active", /** * UI elements */ input: "cdx-input", loader: "cdx-loader", button: "cdx-button", /** * Settings styles */ settingsButton: "cdx-settings-button", settingsButtonActive: "cdx-settings-button--active" }; } } class Fi extends E$3 { /** * Available methods * * @returns {Toolbar} */ get methods() { return { close: () => this.close(), open: () => this.open(), toggleBlockSettings: (e) => this.toggleBlockSettings(e), toggleToolbox: (e) => this.toggleToolbox(e) }; } /** * Open toolbar */ open() { this.Editor.Toolbar.moveAndOpen(); } /** * Close toolbar and all included elements */ close() { this.Editor.Toolbar.close(); } /** * Toggles Block Setting of the current block * * @param {boolean} openingState — opening state of Block Setting */ toggleBlockSettings(e) { if (this.Editor.BlockManager.currentBlockIndex === -1) { X$2("Could't toggle the Toolbar because there is no block selected ", "warn"); return; } e ?? !this.Editor.BlockSettings.opened ? (this.Editor.Toolbar.moveAndOpen(), this.Editor.BlockSettings.open()) : this.Editor.BlockSettings.close(); } /** * Open toolbox * * @param {boolean} openingState - Opening state of toolbox */ toggleToolbox(e) { if (this.Editor.BlockManager.currentBlockIndex === -1) { X$2("Could't toggle the Toolbox because there is no block selected ", "warn"); return; } e ?? !this.Editor.Toolbar.toolbox.opened ? (this.Editor.Toolbar.moveAndOpen(), this.Editor.Toolbar.toolbox.open()) : this.Editor.Toolbar.toolbox.close(); } } var Vo = { exports: {} }; /*! * CodeX.Tooltips * * @version 1.0.5 * * @licence MIT * @author CodeX * * */ (function(n2, e) { (function(t, o2) { n2.exports = o2(); })(window, function() { return function(t) { var o2 = {}; function i(s2) { if (o2[s2]) return o2[s2].exports; var r2 = o2[s2] = { i: s2, l: false, exports: {} }; return t[s2].call(r2.exports, r2, r2.exports, i), r2.l = true, r2.exports; } return i.m = t, i.c = o2, i.d = function(s2, r2, a2) { i.o(s2, r2) || Object.defineProperty(s2, r2, { enumerable: true, get: a2 }); }, i.r = function(s2) { typeof Symbol < "u" && Symbol.toStringTag && Object.defineProperty(s2, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(s2, "__esModule", { value: true }); }, i.t = function(s2, r2) { if (1 & r2 && (s2 = i(s2)), 8 & r2 || 4 & r2 && typeof s2 == "object" && s2 && s2.__esModule) return s2; var a2 = /* @__PURE__ */ Object.create(null); if (i.r(a2), Object.defineProperty(a2, "default", { enumerable: true, value: s2 }), 2 & r2 && typeof s2 != "string") for (var l2 in s2) i.d(a2, l2, (function(c2) { return s2[c2]; }).bind(null, l2)); return a2; }, i.n = function(s2) { var r2 = s2 && s2.__esModule ? function() { return s2.default; } : function() { return s2; }; return i.d(r2, "a", r2), r2; }, i.o = function(s2, r2) { return Object.prototype.hasOwnProperty.call(s2, r2); }, i.p = "", i(i.s = 0); }([function(t, o2, i) { t.exports = i(1); }, function(t, o2, i) { i.r(o2), i.d(o2, "default", function() { return s2; }); class s2 { constructor() { this.nodes = { wrapper: null, content: null }, this.showed = false, this.offsetTop = 10, this.offsetLeft = 10, this.offsetRight = 10, this.hidingDelay = 0, this.handleWindowScroll = () => { this.showed && this.hide(true); }, this.loadStyles(), this.prepare(), window.addEventListener("scroll", this.handleWindowScroll, { passive: true }); } get CSS() { return { tooltip: "ct", tooltipContent: "ct__content", tooltipShown: "ct--shown", placement: { left: "ct--left", bottom: "ct--bottom", right: "ct--right", top: "ct--top" } }; } show(a2, l2, c2) { this.nodes.wrapper || this.prepare(), this.hidingTimeout && clearTimeout(this.hidingTimeout); const d2 = Object.assign({ placement: "bottom", marginTop: 0, marginLeft: 0, marginRight: 0, marginBottom: 0, delay: 70, hidingDelay: 0 }, c2); if (d2.hidingDelay && (this.hidingDelay = d2.hidingDelay), this.nodes.content.innerHTML = "", typeof l2 == "string") this.nodes.content.appendChild(document.createTextNode(l2)); else { if (!(l2 instanceof Node)) throw Error("[CodeX Tooltip] Wrong type of «content» passed. It should be an instance of Node or String. But " + typeof l2 + " given."); this.nodes.content.appendChild(l2); } switch (this.nodes.wrapper.classList.remove(...Object.values(this.CSS.placement)), d2.placement) { case "top": this.placeTop(a2, d2); break; case "left": this.placeLeft(a2, d2); break; case "right": this.placeRight(a2, d2); break; case "bottom": default: this.placeBottom(a2, d2); } d2 && d2.delay ? this.showingTimeout = setTimeout(() => { this.nodes.wrapper.classList.add(this.CSS.tooltipShown), this.showed = true; }, d2.delay) : (this.nodes.wrapper.classList.add(this.CSS.tooltipShown), this.showed = true); } hide(a2 = false) { if (this.hidingDelay && !a2) return this.hidingTimeout && clearTimeout(this.hidingTimeout), void (this.hidingTimeout = setTimeout(() => { this.hide(true); }, this.hidingDelay)); this.nodes.wrapper.classList.remove(this.CSS.tooltipShown), this.showed = false, this.showingTimeout && clearTimeout(this.showingTimeout); } onHover(a2, l2, c2) { a2.addEventListener("mouseenter", () => { this.show(a2, l2, c2); }), a2.addEventListener("mouseleave", () => { this.hide(); }); } destroy() { this.nodes.wrapper.remove(), window.removeEventListener("scroll", this.handleWindowScroll); } prepare() { this.nodes.wrapper = this.make("div", this.CSS.tooltip), this.nodes.content = this.make("div", this.CSS.tooltipContent), this.append(this.nodes.wrapper, this.nodes.content), this.append(document.body, this.nodes.wrapper); } loadStyles() { const a2 = "codex-tooltips-style"; if (document.getElementById(a2)) return; const l2 = i(2), c2 = this.make("style", null, { textContent: l2.toString(), id: a2 }); this.prepend(document.head, c2); } placeBottom(a2, l2) { const c2 = a2.getBoundingClientRect(), d2 = c2.left + a2.clientWidth / 2 - this.nodes.wrapper.offsetWidth / 2, h2 = c2.bottom + window.pageYOffset + this.offsetTop + l2.marginTop; this.applyPlacement("bottom", d2, h2); } placeTop(a2, l2) { const c2 = a2.getBoundingClientRect(), d2 = c2.left + a2.clientWidth / 2 - this.nodes.wrapper.offsetWidth / 2, h2 = c2.top + window.pageYOffset - this.nodes.wrapper.clientHeight - this.offsetTop; this.applyPlacement("top", d2, h2); } placeLeft(a2, l2) { const c2 = a2.getBoundingClientRect(), d2 = c2.left - this.nodes.wrapper.offsetWidth - this.offsetLeft - l2.marginLeft, h2 = c2.top + window.pageYOffset + a2.clientHeight / 2 - this.nodes.wrapper.offsetHeight / 2; this.applyPlacement("left", d2, h2); } placeRight(a2, l2) { const c2 = a2.getBoundingClientRect(), d2 = c2.right + this.offsetRight + l2.marginRight, h2 = c2.top + window.pageYOffset + a2.clientHeight / 2 - this.nodes.wrapper.offsetHeight / 2; this.applyPlacement("right", d2, h2); } applyPlacement(a2, l2, c2) { this.nodes.wrapper.classList.add(this.CSS.placement[a2]), this.nodes.wrapper.style.left = l2 + "px", this.nodes.wrapper.style.top = c2 + "px"; } make(a2, l2 = null, c2 = {}) { const d2 = document.createElement(a2); Array.isArray(l2) ? d2.classList.add(...l2) : l2 && d2.classList.add(l2); for (const h2 in c2) c2.hasOwnProperty(h2) && (d2[h2] = c2[h2]); return d2; } append(a2, l2) { Array.isArray(l2) ? l2.forEach((c2) => a2.appendChild(c2)) : a2.appendChild(l2); } prepend(a2, l2) { Array.isArray(l2) ? (l2 = l2.reverse()).forEach((c2) => a2.prepend(c2)) : a2.prepend(l2); } } }, function(t, o2) { t.exports = `.ct{z-index:999;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;-webkit-transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1),-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);will-change:opacity,top,left;-webkit-box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);border-radius:9px}.ct,.ct:before{position:absolute;top:0;left:0}.ct:before{content:"";bottom:0;right:0;background-color:#1d202b;z-index:-1;border-radius:4px}@supports(-webkit-mask-box-image:url("")){.ct:before{border-radius:0;-webkit-mask-box-image:url('data:image/svg+xml;charset=utf-8,') 48% 41% 37.9% 53.3%}}@media (--mobile){.ct{display:none}}.ct__content{padding:6px 10px;color:#cdd1e0;font-size:12px;text-align:center;letter-spacing:.02em;line-height:1em}.ct:after{content:"";width:8px;height:8px;position:absolute;background-color:#1d202b;z-index:-1}.ct--bottom{-webkit-transform:translateY(5px);transform:translateY(5px)}.ct--bottom:after{top:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--top{-webkit-transform:translateY(-5px);transform:translateY(-5px)}.ct--top:after{top:auto;bottom:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--left{-webkit-transform:translateX(-5px);transform:translateX(-5px)}.ct--left:after{top:50%;left:auto;right:0;-webkit-transform:translate(41.6%,-50%) rotate(-45deg);transform:translate(41.6%,-50%) rotate(-45deg)}.ct--right{-webkit-transform:translateX(5px);transform:translateX(5px)}.ct--right:after{top:50%;left:0;-webkit-transform:translate(-41.6%,-50%) rotate(-45deg);transform:translate(-41.6%,-50%) rotate(-45deg)}.ct--shown{opacity:1;-webkit-transform:none;transform:none}`; }]).default; }); })(Vo); var ji = Vo.exports; const Hi = /* @__PURE__ */ Ke$2(ji); let U$3 = null; function Et$2() { U$3 || (U$3 = new Hi()); } function $i(n2, e, t) { Et$2(), U$3 == null || U$3.show(n2, e, t); } function $e$1(n2 = false) { Et$2(), U$3 == null || U$3.hide(n2); } function ze$2(n2, e, t) { Et$2(), U$3 == null || U$3.onHover(n2, e, t); } function zi() { U$3 == null || U$3.destroy(), U$3 = null; } class Ui extends E$3 { /** * @class * @param moduleConfiguration - Module Configuration * @param moduleConfiguration.config - Editor's config * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher */ constructor({ config: e, eventsDispatcher: t }) { super({ config: e, eventsDispatcher: t }); } /** * Available methods */ get methods() { return { show: (e, t, o2) => this.show(e, t, o2), hide: () => this.hide(), onHover: (e, t, o2) => this.onHover(e, t, o2) }; } /** * Method show tooltip on element with passed HTML content * * @param {HTMLElement} element - element on which tooltip should be shown * @param {TooltipContent} content - tooltip content * @param {TooltipOptions} options - tooltip options */ show(e, t, o2) { $i(e, t, o2); } /** * Method hides tooltip on HTML page */ hide() { $e$1(); } /** * Decorator for showing Tooltip by mouseenter/mouseleave * * @param {HTMLElement} element - element on which tooltip should be shown * @param {TooltipContent} content - tooltip content * @param {TooltipOptions} options - tooltip options */ onHover(e, t, o2) { ze$2(e, t, o2); } } class Wi extends E$3 { /** * Available methods / getters */ get methods() { return { nodes: this.editorNodes /** * There can be added some UI methods, like toggleThinMode() etc */ }; } /** * Exported classes */ get editorNodes() { return { /** * Top-level editor instance wrapper */ wrapper: this.Editor.UI.nodes.wrapper, /** * Element that holds all the Blocks */ redactor: this.Editor.UI.nodes.redactor }; } } function qo(n2, e) { const t = {}; return Object.entries(n2).forEach(([o2, i]) => { if (D$3(i)) { const s2 = e ? `${e}.${o2}` : o2; Object.values(i).every((a2) => te$2(a2)) ? t[o2] = s2 : t[o2] = qo(i, s2); return; } t[o2] = i; }), t; } const K$2 = qo(Fo); function Yi(n2, e) { const t = {}; return Object.keys(n2).forEach((o2) => { const i = e[o2]; i !== void 0 ? t[i] = n2[o2] : t[o2] = n2[o2]; }), t; } const Zo = class Ee2 { /** * @param {HTMLElement[]} nodeList — the list of iterable HTML-items * @param {string} focusedCssClass - user-provided CSS-class that will be set in flipping process */ constructor(e, t) { this.cursor = -1, this.items = [], this.items = e || [], this.focusedCssClass = t; } /** * Returns Focused button Node * * @returns {HTMLElement} */ get currentItem() { return this.cursor === -1 ? null : this.items[this.cursor]; } /** * Sets cursor to specified position * * @param cursorPosition - new cursor position */ setCursor(e) { e < this.items.length && e >= -1 && (this.dropCursor(), this.cursor = e, this.items[this.cursor].classList.add(this.focusedCssClass)); } /** * Sets items. Can be used when iterable items changed dynamically * * @param {HTMLElement[]} nodeList - nodes to iterate */ setItems(e) { this.items = e; } /** * Sets cursor next to the current */ next() { this.cursor = this.leafNodesAndReturnIndex(Ee2.directions.RIGHT); } /** * Sets cursor before current */ previous() { this.cursor = this.leafNodesAndReturnIndex(Ee2.directions.LEFT); } /** * Sets cursor to the default position and removes CSS-class from previously focused item */ dropCursor() { this.cursor !== -1 && (this.items[this.cursor].classList.remove(this.focusedCssClass), this.cursor = -1); } /** * Leafs nodes inside the target list from active element * * @param {string} direction - leaf direction. Can be 'left' or 'right' * @returns {number} index of focused node */ leafNodesAndReturnIndex(e) { if (this.items.length === 0) return this.cursor; let t = this.cursor; return t === -1 ? t = e === Ee2.directions.RIGHT ? -1 : 0 : this.items[t].classList.remove(this.focusedCssClass), e === Ee2.directions.RIGHT ? t = (t + 1) % this.items.length : t = (this.items.length + t - 1) % this.items.length, u$1.canSetCaret(this.items[t]) && Fe$2(() => b$3.setCursor(this.items[t]), 50)(), this.items[t].classList.add(this.focusedCssClass), t; } }; Zo.directions = { RIGHT: "right", LEFT: "left" }; let ke$1 = Zo; let ce$2 = class ce2 { /** * @param options - different constructing settings */ constructor(e) { this.iterator = null, this.activated = false, this.flipCallbacks = [], this.onKeyDown = (t) => { if (!(!this.isEventReadyForHandling(t) || t.shiftKey === true)) switch (ce2.usedKeys.includes(t.keyCode) && t.preventDefault(), t.keyCode) { case y$3.TAB: this.handleTabPress(t); break; case y$3.LEFT: case y$3.UP: this.flipLeft(); break; case y$3.RIGHT: case y$3.DOWN: this.flipRight(); break; case y$3.ENTER: this.handleEnterPress(t); break; } }, this.iterator = new ke$1(e.items, e.focusedItemClass), this.activateCallback = e.activateCallback, this.allowedKeys = e.allowedKeys || ce2.usedKeys; } /** * True if flipper is currently activated */ get isActivated() { return this.activated; } /** * Array of keys (codes) that is handled by Flipper * Used to: * - preventDefault only for this keys, not all keydowns (@see constructor) * - to skip external behaviours only for these keys, when filler is activated (@see BlockEvents@arrowRightAndDown) */ static get usedKeys() { return [ y$3.TAB, y$3.LEFT, y$3.RIGHT, y$3.ENTER, y$3.UP, y$3.DOWN ]; } /** * Active tab/arrows handling by flipper * * @param items - Some modules (like, InlineToolbar, BlockSettings) might refresh buttons dynamically * @param cursorPosition - index of the item that should be focused once flipper is activated */ activate(e, t) { this.activated = true, e && this.iterator.setItems(e), t !== void 0 && this.iterator.setCursor(t), document.addEventListener("keydown", this.onKeyDown, true); } /** * Disable tab/arrows handling by flipper */ deactivate() { this.activated = false, this.dropCursor(), document.removeEventListener("keydown", this.onKeyDown); } /** * Focus first item */ focusFirst() { this.dropCursor(), this.flipRight(); } /** * Focuses previous flipper iterator item */ flipLeft() { this.iterator.previous(), this.flipCallback(); } /** * Focuses next flipper iterator item */ flipRight() { this.iterator.next(), this.flipCallback(); } /** * Return true if some button is focused */ hasFocus() { return !!this.iterator.currentItem; } /** * Registeres function that should be executed on each navigation action * * @param cb - function to execute */ onFlip(e) { this.flipCallbacks.push(e); } /** * Unregisteres function that is executed on each navigation action * * @param cb - function to stop executing */ removeOnFlip(e) { this.flipCallbacks = this.flipCallbacks.filter((t) => t !== e); } /** * Drops flipper's iterator cursor * * @see DomIterator#dropCursor */ dropCursor() { this.iterator.dropCursor(); } /** * This function is fired before handling flipper keycodes * The result of this function defines if it is need to be handled or not * * @param {KeyboardEvent} event - keydown keyboard event * @returns {boolean} */ isEventReadyForHandling(e) { return this.activated && this.allowedKeys.includes(e.keyCode); } /** * When flipper is activated tab press will leaf the items * * @param {KeyboardEvent} event - tab keydown event */ handleTabPress(e) { switch (e.shiftKey ? ke$1.directions.LEFT : ke$1.directions.RIGHT) { case ke$1.directions.RIGHT: this.flipRight(); break; case ke$1.directions.LEFT: this.flipLeft(); break; } } /** * Enter press will click current item if flipper is activated * * @param {KeyboardEvent} event - enter keydown event */ handleEnterPress(e) { this.activated && (this.iterator.currentItem && (e.stopPropagation(), e.preventDefault(), this.iterator.currentItem.click()), A$4(this.activateCallback) && this.activateCallback(this.iterator.currentItem)); } /** * Fired after flipping in any direction */ flipCallback() { this.iterator.currentItem && this.iterator.currentItem.scrollIntoViewIfNeeded(), this.flipCallbacks.forEach((e) => e()); } }; const Ki = '', Xi = '', Vi = '', qi = '', Zi = '', Gi = '', Qi = '', Ji = '', Co = '', es = '', ts = '', Go = '', os = '', ns = '', is = '', ss = "__", rs = "--"; function ne$2(n2) { return (e, t) => [[n2, e].filter((i) => !!i).join(ss), t].filter((i) => !!i).join(rs); } const ye$2 = ne$2("ce-hint"), we$1 = { root: ye$2(), alignedStart: ye$2(null, "align-left"), alignedCenter: ye$2(null, "align-center"), title: ye$2("title"), description: ye$2("description") }; class as { /** * Constructs the hint content instance * * @param params - hint content parameters */ constructor(e) { this.nodes = { root: u$1.make("div", [we$1.root, e.alignment === "center" ? we$1.alignedCenter : we$1.alignedStart]), title: u$1.make("div", we$1.title, { textContent: e.title }) }, this.nodes.root.appendChild(this.nodes.title), e.description !== void 0 && (this.nodes.description = u$1.make("div", we$1.description, { textContent: e.description }), this.nodes.root.appendChild(this.nodes.description)); } /** * Returns the root element of the hint content */ getElement() { return this.nodes.root; } } let xt$2 = class xt { /** * Constructs the instance * * @param params - instance parameters */ constructor(e) { this.params = e; } /** * Item name if exists */ get name() { if (this.params !== void 0 && "name" in this.params) return this.params.name; } /** * Destroys the instance */ destroy() { $e$1(); } /** * Called when children popover is opened (if exists) */ onChildrenOpen() { var e; this.params !== void 0 && "children" in this.params && typeof ((e = this.params.children) == null ? void 0 : e.onOpen) == "function" && this.params.children.onOpen(); } /** * Called when children popover is closed (if exists) */ onChildrenClose() { var e; this.params !== void 0 && "children" in this.params && typeof ((e = this.params.children) == null ? void 0 : e.onClose) == "function" && this.params.children.onClose(); } /** * Called on popover item click */ handleClick() { var e, t; this.params !== void 0 && "onActivate" in this.params && ((t = (e = this.params).onActivate) == null || t.call(e, this.params)); } /** * Adds hint to the item element if hint data is provided * * @param itemElement - popover item root element to add hint to * @param hintData - hint data */ addHint(e, t) { const o2 = new as(t); ze$2(e, o2.getElement(), { placement: t.position, hidingDelay: 100 }); } /** * Returns item children that are represented as popover items */ get children() { var e; return this.params !== void 0 && "children" in this.params && ((e = this.params.children) == null ? void 0 : e.items) !== void 0 ? this.params.children.items : []; } /** * Returns true if item has any type of children */ get hasChildren() { return this.children.length > 0; } /** * Returns true if item children should be open instantly after popover is opened and not on item click/hover */ get isChildrenOpen() { var e; return this.params !== void 0 && "children" in this.params && ((e = this.params.children) == null ? void 0 : e.isOpen) === true; } /** * True if item children items should be navigatable via keyboard */ get isChildrenFlippable() { var e; return !(this.params === void 0 || !("children" in this.params) || ((e = this.params.children) == null ? void 0 : e.isFlippable) === false); } /** * Returns true if item has children that should be searchable */ get isChildrenSearchable() { var e; return this.params !== void 0 && "children" in this.params && ((e = this.params.children) == null ? void 0 : e.searchable) === true; } /** * True if popover should close once item is activated */ get closeOnActivate() { return this.params !== void 0 && "closeOnActivate" in this.params && this.params.closeOnActivate; } /** * True if item is active */ get isActive() { return this.params === void 0 || !("isActive" in this.params) ? false : typeof this.params.isActive == "function" ? this.params.isActive() : this.params.isActive === true; } }; const Y$2 = ne$2("ce-popover-item"), L$4 = { container: Y$2(), active: Y$2(null, "active"), disabled: Y$2(null, "disabled"), focused: Y$2(null, "focused"), hidden: Y$2(null, "hidden"), confirmationState: Y$2(null, "confirmation"), noHover: Y$2(null, "no-hover"), noFocus: Y$2(null, "no-focus"), title: Y$2("title"), secondaryTitle: Y$2("secondary-title"), icon: Y$2("icon"), iconTool: Y$2("icon", "tool"), iconChevronRight: Y$2("icon", "chevron-right"), wobbleAnimation: ne$2("wobble")() }; let re$2 = class re extends xt$2 { /** * Constructs popover item instance * * @param params - popover item construction params * @param renderParams - popover item render params. * The parameters that are not set by user via popover api but rather depend on technical implementation */ constructor(e, t) { super(e), this.params = e, this.nodes = { root: null, icon: null }, this.confirmationState = null, this.removeSpecialFocusBehavior = () => { var o2; (o2 = this.nodes.root) == null || o2.classList.remove(L$4.noFocus); }, this.removeSpecialHoverBehavior = () => { var o2; (o2 = this.nodes.root) == null || o2.classList.remove(L$4.noHover); }, this.onErrorAnimationEnd = () => { var o2, i; (o2 = this.nodes.icon) == null || o2.classList.remove(L$4.wobbleAnimation), (i = this.nodes.icon) == null || i.removeEventListener("animationend", this.onErrorAnimationEnd); }, this.nodes.root = this.make(e, t); } /** * True if item is disabled and hence not clickable */ get isDisabled() { return this.params.isDisabled === true; } /** * Exposes popover item toggle parameter */ get toggle() { return this.params.toggle; } /** * Item title */ get title() { return this.params.title; } /** * True if confirmation state is enabled for popover item */ get isConfirmationStateEnabled() { return this.confirmationState !== null; } /** * True if item is focused in keyboard navigation process */ get isFocused() { return this.nodes.root === null ? false : this.nodes.root.classList.contains(L$4.focused); } /** * Returns popover item root element */ getElement() { return this.nodes.root; } /** * Called on popover item click */ handleClick() { if (this.isConfirmationStateEnabled && this.confirmationState !== null) { this.activateOrEnableConfirmationMode(this.confirmationState); return; } this.activateOrEnableConfirmationMode(this.params); } /** * Toggles item active state * * @param isActive - true if item should strictly should become active */ toggleActive(e) { var t; (t = this.nodes.root) == null || t.classList.toggle(L$4.active, e); } /** * Toggles item hidden state * * @param isHidden - true if item should be hidden */ toggleHidden(e) { var t; (t = this.nodes.root) == null || t.classList.toggle(L$4.hidden, e); } /** * Resets popover item to its original state */ reset() { this.isConfirmationStateEnabled && this.disableConfirmationMode(); } /** * Method called once item becomes focused during keyboard navigation */ onFocus() { this.disableSpecialHoverAndFocusBehavior(); } /** * Constructs HTML element corresponding to popover item params * * @param params - item construction params * @param renderParams - popover item render params */ make(e, t) { var s2, r2; const o2 = (t == null ? void 0 : t.wrapperTag) || "div", i = u$1.make(o2, L$4.container, { type: o2 === "button" ? "button" : void 0 }); return e.name && (i.dataset.itemName = e.name), this.nodes.icon = u$1.make("div", [L$4.icon, L$4.iconTool], { innerHTML: e.icon || Qi }), i.appendChild(this.nodes.icon), e.title !== void 0 && i.appendChild(u$1.make("div", L$4.title, { innerHTML: e.title || "" })), e.secondaryLabel && i.appendChild(u$1.make("div", L$4.secondaryTitle, { textContent: e.secondaryLabel })), this.hasChildren && i.appendChild(u$1.make("div", [L$4.icon, L$4.iconChevronRight], { innerHTML: qi })), this.isActive && i.classList.add(L$4.active), e.isDisabled && i.classList.add(L$4.disabled), e.hint !== void 0 && ((s2 = t == null ? void 0 : t.hint) == null ? void 0 : s2.enabled) !== false && this.addHint(i, { ...e.hint, position: ((r2 = t == null ? void 0 : t.hint) == null ? void 0 : r2.position) || "right" }), i; } /** * Activates confirmation mode for the item. * * @param newState - new popover item params that should be applied */ enableConfirmationMode(e) { if (this.nodes.root === null) return; const t = { ...this.params, ...e, confirmation: "confirmation" in e ? e.confirmation : void 0 }, o2 = this.make(t); this.nodes.root.innerHTML = o2.innerHTML, this.nodes.root.classList.add(L$4.confirmationState), this.confirmationState = e, this.enableSpecialHoverAndFocusBehavior(); } /** * Returns item to its original state */ disableConfirmationMode() { if (this.nodes.root === null) return; const e = this.make(this.params); this.nodes.root.innerHTML = e.innerHTML, this.nodes.root.classList.remove(L$4.confirmationState), this.confirmationState = null, this.disableSpecialHoverAndFocusBehavior(); } /** * Enables special focus and hover behavior for item in confirmation state. * This is needed to prevent item from being highlighted as hovered/focused just after click. */ enableSpecialHoverAndFocusBehavior() { var e, t, o2; (e = this.nodes.root) == null || e.classList.add(L$4.noHover), (t = this.nodes.root) == null || t.classList.add(L$4.noFocus), (o2 = this.nodes.root) == null || o2.addEventListener("mouseleave", this.removeSpecialHoverBehavior, { once: true }); } /** * Disables special focus and hover behavior */ disableSpecialHoverAndFocusBehavior() { var e; this.removeSpecialFocusBehavior(), this.removeSpecialHoverBehavior(), (e = this.nodes.root) == null || e.removeEventListener("mouseleave", this.removeSpecialHoverBehavior); } /** * Executes item's onActivate callback if the item has no confirmation configured * * @param item - item to activate or bring to confirmation mode */ activateOrEnableConfirmationMode(e) { var t; if (!("confirmation" in e) || e.confirmation === void 0) try { (t = e.onActivate) == null || t.call(e, e), this.disableConfirmationMode(); } catch { this.animateError(); } else this.enableConfirmationMode(e.confirmation); } /** * Animates item which symbolizes that error occured while executing 'onActivate()' callback */ animateError() { var e, t, o2; (e = this.nodes.icon) != null && e.classList.contains(L$4.wobbleAnimation) || ((t = this.nodes.icon) == null || t.classList.add(L$4.wobbleAnimation), (o2 = this.nodes.icon) == null || o2.addEventListener("animationend", this.onErrorAnimationEnd)); } }; const nt$2 = ne$2("ce-popover-item-separator"), it$2 = { container: nt$2(), line: nt$2("line"), hidden: nt$2(null, "hidden") }; class Qo extends xt$2 { /** * Constructs the instance */ constructor() { super(), this.nodes = { root: u$1.make("div", it$2.container), line: u$1.make("div", it$2.line) }, this.nodes.root.appendChild(this.nodes.line); } /** * Returns popover separator root element */ getElement() { return this.nodes.root; } /** * Toggles item hidden state * * @param isHidden - true if item should be hidden */ toggleHidden(e) { var t; (t = this.nodes.root) == null || t.classList.toggle(it$2.hidden, e); } } var G$2 = /* @__PURE__ */ ((n2) => (n2.Closed = "closed", n2.ClosedOnActivate = "closed-on-activate", n2))(G$2 || {}); const $$2 = ne$2("ce-popover"), P$4 = { popover: $$2(), popoverContainer: $$2("container"), popoverOpenTop: $$2(null, "open-top"), popoverOpenLeft: $$2(null, "open-left"), popoverOpened: $$2(null, "opened"), search: $$2("search"), nothingFoundMessage: $$2("nothing-found-message"), nothingFoundMessageDisplayed: $$2("nothing-found-message", "displayed"), items: $$2("items"), overlay: $$2("overlay"), overlayHidden: $$2("overlay", "hidden"), popoverNested: $$2(null, "nested"), getPopoverNestedClass: (n2) => $$2(null, `nested-level-${n2.toString()}`), popoverInline: $$2(null, "inline"), popoverHeader: $$2("header") }; var fe$2 = /* @__PURE__ */ ((n2) => (n2.NestingLevel = "--nesting-level", n2.PopoverHeight = "--popover-height", n2.InlinePopoverWidth = "--inline-popover-width", n2.TriggerItemLeft = "--trigger-item-left", n2.TriggerItemTop = "--trigger-item-top", n2))(fe$2 || {}); const To = ne$2("ce-popover-item-html"), So = { root: To(), hidden: To(null, "hidden") }; let Se$1 = class Se extends xt$2 { /** * Constructs the instance * * @param params – instance parameters * @param renderParams – popover item render params. * The parameters that are not set by user via popover api but rather depend on technical implementation */ constructor(e, t) { var o2, i; super(e), this.nodes = { root: u$1.make("div", So.root) }, this.nodes.root.appendChild(e.element), e.name && (this.nodes.root.dataset.itemName = e.name), e.hint !== void 0 && ((o2 = t == null ? void 0 : t.hint) == null ? void 0 : o2.enabled) !== false && this.addHint(this.nodes.root, { ...e.hint, position: ((i = t == null ? void 0 : t.hint) == null ? void 0 : i.position) || "right" }); } /** * Returns popover item root element */ getElement() { return this.nodes.root; } /** * Toggles item hidden state * * @param isHidden - true if item should be hidden */ toggleHidden(e) { var t; (t = this.nodes.root) == null || t.classList.toggle(So.hidden, e); } /** * Returns list of buttons and inputs inside custom content */ getControls() { const e = this.nodes.root.querySelectorAll( `button, ${u$1.allInputsSelector}` ); return Array.from(e); } }; class Jo extends Oe$1 { /** * Constructs the instance * * @param params - popover construction params * @param itemsRenderParams - popover item render params. * The parameters that are not set by user via popover api but rather depend on technical implementation */ constructor(e, t = {}) { super(), this.params = e, this.itemsRenderParams = t, this.listeners = new _e$2(), this.messages = { nothingFound: "Nothing found", search: "Search" }, this.items = this.buildItems(e.items), e.messages && (this.messages = { ...this.messages, ...e.messages }), this.nodes = {}, this.nodes.popoverContainer = u$1.make("div", [P$4.popoverContainer]), this.nodes.nothingFoundMessage = u$1.make("div", [P$4.nothingFoundMessage], { textContent: this.messages.nothingFound }), this.nodes.popoverContainer.appendChild(this.nodes.nothingFoundMessage), this.nodes.items = u$1.make("div", [P$4.items]), this.items.forEach((o2) => { const i = o2.getElement(); i !== null && this.nodes.items.appendChild(i); }), this.nodes.popoverContainer.appendChild(this.nodes.items), this.listeners.on(this.nodes.popoverContainer, "click", (o2) => this.handleClick(o2)), this.nodes.popover = u$1.make("div", [ P$4.popover, this.params.class ]), this.nodes.popover.appendChild(this.nodes.popoverContainer); } /** * List of default popover items that are searchable and may have confirmation state */ get itemsDefault() { return this.items.filter((e) => e instanceof re$2); } /** * Returns HTML element corresponding to the popover */ getElement() { return this.nodes.popover; } /** * Open popover */ show() { this.nodes.popover.classList.add(P$4.popoverOpened), this.search !== void 0 && this.search.focus(); } /** * Closes popover */ hide() { this.nodes.popover.classList.remove(P$4.popoverOpened), this.nodes.popover.classList.remove(P$4.popoverOpenTop), this.itemsDefault.forEach((e) => e.reset()), this.search !== void 0 && this.search.clear(), this.emit(G$2.Closed); } /** * Clears memory */ destroy() { var e; this.items.forEach((t) => t.destroy()), this.nodes.popover.remove(), this.listeners.removeAll(), (e = this.search) == null || e.destroy(); } /** * Looks for the item by name and imitates click on it * * @param name - name of the item to activate */ activateItemByName(e) { const t = this.items.find((o2) => o2.name === e); this.handleItemClick(t); } /** * Factory method for creating popover items * * @param items - list of items params */ buildItems(e) { return e.map((t) => { switch (t.type) { case _$2.Separator: return new Qo(); case _$2.Html: return new Se$1(t, this.itemsRenderParams[_$2.Html]); default: return new re$2(t, this.itemsRenderParams[_$2.Default]); } }); } /** * Retrieves popover item that is the target of the specified event * * @param event - event to retrieve popover item from */ getTargetItem(e) { return this.items.filter((t) => t instanceof re$2 || t instanceof Se$1).find((t) => { const o2 = t.getElement(); return o2 === null ? false : e.composedPath().includes(o2); }); } /** * Handles popover item click * * @param item - item to handle click of */ handleItemClick(e) { if (!("isDisabled" in e && e.isDisabled)) { if (e.hasChildren) { this.showNestedItems(e), "handleClick" in e && typeof e.handleClick == "function" && e.handleClick(); return; } this.itemsDefault.filter((t) => t !== e).forEach((t) => t.reset()), "handleClick" in e && typeof e.handleClick == "function" && e.handleClick(), this.toggleItemActivenessIfNeeded(e), e.closeOnActivate && (this.hide(), this.emit(G$2.ClosedOnActivate)); } } /** * Handles clicks inside popover * * @param event - item to handle click of */ handleClick(e) { const t = this.getTargetItem(e); t !== void 0 && this.handleItemClick(t); } /** * - Toggles item active state, if clicked popover item has property 'toggle' set to true. * * - Performs radiobutton-like behavior if the item has property 'toggle' set to string key. * (All the other items with the same key get inactive, and the item gets active) * * @param clickedItem - popover item that was clicked */ toggleItemActivenessIfNeeded(e) { if (e instanceof re$2 && (e.toggle === true && e.toggleActive(), typeof e.toggle == "string")) { const t = this.itemsDefault.filter((o2) => o2.toggle === e.toggle); if (t.length === 1) { e.toggleActive(); return; } t.forEach((o2) => { o2.toggleActive(o2 === e); }); } } } var Ue$2 = /* @__PURE__ */ ((n2) => (n2.Search = "search", n2))(Ue$2 || {}); const st$2 = ne$2("cdx-search-field"), rt$2 = { wrapper: st$2(), icon: st$2("icon"), input: st$2("input") }; class ls extends Oe$1 { /** * @param options - available config * @param options.items - searchable items list * @param options.placeholder - input placeholder */ constructor({ items: e, placeholder: t }) { super(), this.listeners = new _e$2(), this.items = e, this.wrapper = u$1.make("div", rt$2.wrapper); const o2 = u$1.make("div", rt$2.icon, { innerHTML: os }); this.input = u$1.make("input", rt$2.input, { placeholder: t, /** * Used to prevent focusing on the input by Tab key * (Popover in the Toolbar lays below the blocks, * so Tab in the last block will focus this hidden input if this property is not set) */ tabIndex: -1 }), this.wrapper.appendChild(o2), this.wrapper.appendChild(this.input), this.listeners.on(this.input, "input", () => { this.searchQuery = this.input.value, this.emit(Ue$2.Search, { query: this.searchQuery, items: this.foundItems }); }); } /** * Returns search field element */ getElement() { return this.wrapper; } /** * Sets focus to the input */ focus() { this.input.focus(); } /** * Clears search query and results */ clear() { this.input.value = "", this.searchQuery = "", this.emit(Ue$2.Search, { query: "", items: this.foundItems }); } /** * Clears memory */ destroy() { this.listeners.removeAll(); } /** * Returns list of found items for the current search query */ get foundItems() { return this.items.filter((e) => this.checkItem(e)); } /** * Contains logic for checking whether passed item conforms the search query * * @param item - item to be checked */ checkItem(e) { var i, s2; const t = ((i = e.title) == null ? void 0 : i.toLowerCase()) || "", o2 = (s2 = this.searchQuery) == null ? void 0 : s2.toLowerCase(); return o2 !== void 0 ? t.includes(o2) : false; } } var cs = Object.defineProperty, ds = Object.getOwnPropertyDescriptor, us = (n2, e, t, o2) => { for (var i = o2 > 1 ? void 0 : o2 ? ds(e, t) : e, s2 = n2.length - 1, r2; s2 >= 0; s2--) (r2 = n2[s2]) && (i = (o2 ? r2(e, t, i) : r2(i)) || i); return o2 && i && cs(e, t, i), i; }; const en$1 = class tn2 extends Jo { /** * Construct the instance * * @param params - popover params * @param itemsRenderParams – popover item render params. * The parameters that are not set by user via popover api but rather depend on technical implementation */ constructor(e, t) { super(e, t), this.nestingLevel = 0, this.nestedPopoverTriggerItem = null, this.previouslyHoveredItem = null, this.scopeElement = document.body, this.hide = () => { var o2; super.hide(), this.destroyNestedPopoverIfExists(), (o2 = this.flipper) == null || o2.deactivate(), this.previouslyHoveredItem = null; }, this.onFlip = () => { const o2 = this.itemsDefault.find((i) => i.isFocused); o2 == null || o2.onFocus(); }, this.onSearch = (o2) => { var a2; const i = o2.query === "", s2 = o2.items.length === 0; this.items.forEach((l2) => { let c2 = false; l2 instanceof re$2 ? c2 = !o2.items.includes(l2) : (l2 instanceof Qo || l2 instanceof Se$1) && (c2 = s2 || !i), l2.toggleHidden(c2); }), this.toggleNothingFoundMessage(s2); const r2 = o2.query === "" ? this.flippableElements : o2.items.map((l2) => l2.getElement()); (a2 = this.flipper) != null && a2.isActivated && (this.flipper.deactivate(), this.flipper.activate(r2)); }, e.nestingLevel !== void 0 && (this.nestingLevel = e.nestingLevel), this.nestingLevel > 0 && this.nodes.popover.classList.add(P$4.popoverNested), e.scopeElement !== void 0 && (this.scopeElement = e.scopeElement), this.nodes.popoverContainer !== null && this.listeners.on(this.nodes.popoverContainer, "mouseover", (o2) => this.handleHover(o2)), e.searchable && this.addSearch(), e.flippable !== false && (this.flipper = new ce$2({ items: this.flippableElements, focusedItemClass: L$4.focused, allowedKeys: [ y$3.TAB, y$3.UP, y$3.DOWN, y$3.ENTER ] }), this.flipper.onFlip(this.onFlip)); } /** * Returns true if some item inside popover is focused */ hasFocus() { return this.flipper === void 0 ? false : this.flipper.hasFocus(); } /** * Scroll position inside items container of the popover */ get scrollTop() { return this.nodes.items === null ? 0 : this.nodes.items.scrollTop; } /** * Returns visible element offset top */ get offsetTop() { return this.nodes.popoverContainer === null ? 0 : this.nodes.popoverContainer.offsetTop; } /** * Open popover */ show() { var e; this.nodes.popover.style.setProperty(fe$2.PopoverHeight, this.size.height + "px"), this.shouldOpenBottom || this.nodes.popover.classList.add(P$4.popoverOpenTop), this.shouldOpenRight || this.nodes.popover.classList.add(P$4.popoverOpenLeft), super.show(), (e = this.flipper) == null || e.activate(this.flippableElements); } /** * Clears memory */ destroy() { this.hide(), super.destroy(); } /** * Handles displaying nested items for the item. * * @param item – item to show nested popover for */ showNestedItems(e) { this.nestedPopover !== null && this.nestedPopover !== void 0 || (this.nestedPopoverTriggerItem = e, this.showNestedPopoverForItem(e)); } /** * Handles hover events inside popover items container * * @param event - hover event data */ handleHover(e) { const t = this.getTargetItem(e); t !== void 0 && this.previouslyHoveredItem !== t && (this.destroyNestedPopoverIfExists(), this.previouslyHoveredItem = t, t.hasChildren && this.showNestedPopoverForItem(t)); } /** * Sets CSS variable with position of item near which nested popover should be displayed. * Is used for correct positioning of the nested popover * * @param nestedPopoverEl - nested popover element * @param item – item near which nested popover should be displayed */ setTriggerItemPosition(e, t) { const o2 = t.getElement(), i = (o2 ? o2.offsetTop : 0) - this.scrollTop, s2 = this.offsetTop + i; e.style.setProperty(fe$2.TriggerItemTop, s2 + "px"); } /** * Destroys existing nested popover */ destroyNestedPopoverIfExists() { var e, t; this.nestedPopover === void 0 || this.nestedPopover === null || (this.nestedPopover.off(G$2.ClosedOnActivate, this.hide), this.nestedPopover.hide(), this.nestedPopover.destroy(), this.nestedPopover.getElement().remove(), this.nestedPopover = null, (e = this.flipper) == null || e.activate(this.flippableElements), (t = this.nestedPopoverTriggerItem) == null || t.onChildrenClose()); } /** * Creates and displays nested popover for specified item. * Is used only on desktop * * @param item - item to display nested popover by */ showNestedPopoverForItem(e) { var o2; this.nestedPopover = new tn2({ searchable: e.isChildrenSearchable, items: e.children, nestingLevel: this.nestingLevel + 1, flippable: e.isChildrenFlippable, messages: this.messages }), e.onChildrenOpen(), this.nestedPopover.on(G$2.ClosedOnActivate, this.hide); const t = this.nestedPopover.getElement(); return this.nodes.popover.appendChild(t), this.setTriggerItemPosition(t, e), t.style.setProperty(fe$2.NestingLevel, this.nestedPopover.nestingLevel.toString()), this.nestedPopover.show(), (o2 = this.flipper) == null || o2.deactivate(), this.nestedPopover; } /** * Checks if popover should be opened bottom. * It should happen when there is enough space below or not enough space above */ get shouldOpenBottom() { if (this.nodes.popover === void 0 || this.nodes.popover === null) return false; const e = this.nodes.popoverContainer.getBoundingClientRect(), t = this.scopeElement.getBoundingClientRect(), o2 = this.size.height, i = e.top + o2, s2 = e.top - o2, r2 = Math.min(window.innerHeight, t.bottom); return s2 < t.top || i <= r2; } /** * Checks if popover should be opened left. * It should happen when there is enough space in the right or not enough space in the left */ get shouldOpenRight() { if (this.nodes.popover === void 0 || this.nodes.popover === null) return false; const e = this.nodes.popover.getBoundingClientRect(), t = this.scopeElement.getBoundingClientRect(), o2 = this.size.width, i = e.right + o2, s2 = e.left - o2, r2 = Math.min(window.innerWidth, t.right); return s2 < t.left || i <= r2; } get size() { var i; const e = { height: 0, width: 0 }; if (this.nodes.popover === null) return e; const t = this.nodes.popover.cloneNode(true); t.style.visibility = "hidden", t.style.position = "absolute", t.style.top = "-1000px", t.classList.add(P$4.popoverOpened), (i = t.querySelector("." + P$4.popoverNested)) == null || i.remove(), document.body.appendChild(t); const o2 = t.querySelector("." + P$4.popoverContainer); return e.height = o2.offsetHeight, e.width = o2.offsetWidth, t.remove(), e; } /** * Returns list of elements available for keyboard navigation. */ get flippableElements() { return this.items.map((t) => { if (t instanceof re$2) return t.getElement(); if (t instanceof Se$1) return t.getControls(); }).flat().filter((t) => t != null); } /** * Adds search to the popover */ addSearch() { this.search = new ls({ items: this.itemsDefault, placeholder: this.messages.search }), this.search.on(Ue$2.Search, this.onSearch); const e = this.search.getElement(); e.classList.add(P$4.search), this.nodes.popoverContainer.insertBefore(e, this.nodes.popoverContainer.firstChild); } /** * Toggles nothing found message visibility * * @param isDisplayed - true if the message should be displayed */ toggleNothingFoundMessage(e) { this.nodes.nothingFoundMessage.classList.toggle(P$4.nothingFoundMessageDisplayed, e); } }; us([ me$2 ], en$1.prototype, "size", 1); let Bt$2 = en$1; class hs extends Bt$2 { /** * Constructs the instance * * @param params - instance parameters */ constructor(e) { const t = !be$2(); super( { ...e, class: P$4.popoverInline }, { [_$2.Default]: { /** * We use button instead of div here to fix bug associated with focus loss (which leads to selection change) on click in safari * * @todo figure out better way to solve the issue */ wrapperTag: "button", hint: { position: "top", alignment: "center", enabled: t } }, [_$2.Html]: { hint: { position: "top", alignment: "center", enabled: t } } } ), this.items.forEach((o2) => { !(o2 instanceof re$2) && !(o2 instanceof Se$1) || o2.hasChildren && o2.isChildrenOpen && this.showNestedItems(o2); }); } /** * Returns visible element offset top */ get offsetLeft() { return this.nodes.popoverContainer === null ? 0 : this.nodes.popoverContainer.offsetLeft; } /** * Open popover */ show() { this.nestingLevel === 0 && this.nodes.popover.style.setProperty( fe$2.InlinePopoverWidth, this.size.width + "px" ), super.show(); } /** * Disable hover event handling. * Overrides parent's class behavior */ handleHover() { } /** * Sets CSS variable with position of item near which nested popover should be displayed. * Is used to position nested popover right below clicked item * * @param nestedPopoverEl - nested popover element * @param item – item near which nested popover should be displayed */ setTriggerItemPosition(e, t) { const o2 = t.getElement(), i = o2 ? o2.offsetLeft : 0, s2 = this.offsetLeft + i; e.style.setProperty( fe$2.TriggerItemLeft, s2 + "px" ); } /** * Handles displaying nested items for the item. * Overriding in order to add toggling behaviour * * @param item – item to toggle nested popover for */ showNestedItems(e) { if (this.nestedPopoverTriggerItem === e) { this.destroyNestedPopoverIfExists(), this.nestedPopoverTriggerItem = null; return; } super.showNestedItems(e); } /** * Creates and displays nested popover for specified item. * Is used only on desktop * * @param item - item to display nested popover by */ showNestedPopoverForItem(e) { const t = super.showNestedPopoverForItem(e); return t.getElement().classList.add(P$4.getPopoverNestedClass(t.nestingLevel)), t; } /** * Overrides default item click handling. * Helps to close nested popover once other item is clicked. * * @param item - clicked item */ handleItemClick(e) { var t; e !== this.nestedPopoverTriggerItem && ((t = this.nestedPopoverTriggerItem) == null || t.handleClick(), super.destroyNestedPopoverIfExists()), super.handleItemClick(e); } } const on$1 = class xe2 { constructor() { this.scrollPosition = null; } /** * Locks body element scroll */ lock() { pt$1 ? this.lockHard() : document.body.classList.add(xe2.CSS.scrollLocked); } /** * Unlocks body element scroll */ unlock() { pt$1 ? this.unlockHard() : document.body.classList.remove(xe2.CSS.scrollLocked); } /** * Locks scroll in a hard way (via setting fixed position to body element) */ lockHard() { this.scrollPosition = window.pageYOffset, document.documentElement.style.setProperty( "--window-scroll-offset", `${this.scrollPosition}px` ), document.body.classList.add(xe2.CSS.scrollLockedHard); } /** * Unlocks hard scroll lock */ unlockHard() { document.body.classList.remove(xe2.CSS.scrollLockedHard), this.scrollPosition !== null && window.scrollTo(0, this.scrollPosition), this.scrollPosition = null; } }; on$1.CSS = { scrollLocked: "ce-scroll-locked", scrollLockedHard: "ce-scroll-locked--hard" }; let ps = on$1; const at$2 = ne$2("ce-popover-header"), lt$2 = { root: at$2(), text: at$2("text"), backButton: at$2("back-button") }; class fs { /** * Constructs the instance * * @param params - popover header params */ constructor({ text: e, onBackButtonClick: t }) { this.listeners = new _e$2(), this.text = e, this.onBackButtonClick = t, this.nodes = { root: u$1.make("div", [lt$2.root]), backButton: u$1.make("button", [lt$2.backButton]), text: u$1.make("div", [lt$2.text]) }, this.nodes.backButton.innerHTML = Vi, this.nodes.root.appendChild(this.nodes.backButton), this.listeners.on(this.nodes.backButton, "click", this.onBackButtonClick), this.nodes.text.innerText = this.text, this.nodes.root.appendChild(this.nodes.text); } /** * Returns popover header root html element */ getElement() { return this.nodes.root; } /** * Destroys the instance */ destroy() { this.nodes.root.remove(), this.listeners.destroy(); } } class gs { constructor() { this.history = []; } /** * Push new popover state * * @param state - new state */ push(e) { this.history.push(e); } /** * Pop last popover state */ pop() { return this.history.pop(); } /** * Title retrieved from the current state */ get currentTitle() { return this.history.length === 0 ? "" : this.history[this.history.length - 1].title; } /** * Items list retrieved from the current state */ get currentItems() { return this.history.length === 0 ? [] : this.history[this.history.length - 1].items; } /** * Returns history to initial popover state */ reset() { for (; this.history.length > 1; ) this.pop(); } } let nn$1 = class nn extends Jo { /** * Construct the instance * * @param params - popover params */ constructor(e) { super(e, { [_$2.Default]: { hint: { enabled: false } }, [_$2.Html]: { hint: { enabled: false } } }), this.scrollLocker = new ps(), this.history = new gs(), this.isHidden = true, this.nodes.overlay = u$1.make("div", [P$4.overlay, P$4.overlayHidden]), this.nodes.popover.insertBefore(this.nodes.overlay, this.nodes.popover.firstChild), this.listeners.on(this.nodes.overlay, "click", () => { this.hide(); }), this.history.push({ items: e.items }); } /** * Open popover */ show() { this.nodes.overlay.classList.remove(P$4.overlayHidden), super.show(), this.scrollLocker.lock(), this.isHidden = false; } /** * Closes popover */ hide() { this.isHidden || (super.hide(), this.nodes.overlay.classList.add(P$4.overlayHidden), this.scrollLocker.unlock(), this.history.reset(), this.isHidden = true); } /** * Clears memory */ destroy() { super.destroy(), this.scrollLocker.unlock(); } /** * Handles displaying nested items for the item * * @param item – item to show nested popover for */ showNestedItems(e) { this.updateItemsAndHeader(e.children, e.title), this.history.push({ title: e.title, items: e.children }); } /** * Removes rendered popover items and header and displays new ones * * @param items - new popover items * @param title - new popover header text */ updateItemsAndHeader(e, t) { if (this.header !== null && this.header !== void 0 && (this.header.destroy(), this.header = null), t !== void 0) { this.header = new fs({ text: t, onBackButtonClick: () => { this.history.pop(), this.updateItemsAndHeader(this.history.currentItems, this.history.currentTitle); } }); const o2 = this.header.getElement(); o2 !== null && this.nodes.popoverContainer.insertBefore(o2, this.nodes.popoverContainer.firstChild); } this.items.forEach((o2) => { var i; return (i = o2.getElement()) == null ? void 0 : i.remove(); }), this.items = this.buildItems(e), this.items.forEach((o2) => { var s2; const i = o2.getElement(); i !== null && ((s2 = this.nodes.items) == null || s2.appendChild(i)); }); } }; class ms extends E$3 { constructor() { super(...arguments), this.opened = false, this.selection = new b$3(), this.popover = null, this.close = () => { this.opened && (this.opened = false, b$3.isAtEditor || this.selection.restore(), this.selection.clearSaved(), !this.Editor.CrossBlockSelection.isCrossBlockSelectionStarted && this.Editor.BlockManager.currentBlock && this.Editor.BlockSelection.unselectBlock(this.Editor.BlockManager.currentBlock), this.eventsDispatcher.emit(this.events.closed), this.popover && (this.popover.off(G$2.Closed, this.onPopoverClose), this.popover.destroy(), this.popover.getElement().remove(), this.popover = null)); }, this.onPopoverClose = () => { this.close(); }; } /** * Module Events */ get events() { return { opened: "block-settings-opened", closed: "block-settings-closed" }; } /** * Block Settings CSS */ get CSS() { return { settings: "ce-settings" }; } /** * Getter for inner popover's flipper instance * * @todo remove once BlockSettings becomes standalone non-module class */ get flipper() { var e; if (this.popover !== null) return "flipper" in this.popover ? (e = this.popover) == null ? void 0 : e.flipper : void 0; } /** * Panel with block settings with 2 sections: * - Tool's Settings * - Default Settings [Move, Remove, etc] */ make() { this.nodes.wrapper = u$1.make("div", [this.CSS.settings]), this.eventsDispatcher.on(Te$1, this.close); } /** * Destroys module */ destroy() { this.removeAllNodes(), this.listeners.destroy(), this.eventsDispatcher.off(Te$1, this.close); } /** * Open Block Settings pane * * @param targetBlock - near which Block we should open BlockSettings */ async open(e = this.Editor.BlockManager.currentBlock) { var s2; this.opened = true, this.selection.save(), this.Editor.BlockSelection.selectBlock(e), this.Editor.BlockSelection.clearCache(); const { toolTunes: t, commonTunes: o2 } = e.getTunes(); this.eventsDispatcher.emit(this.events.opened); const i = be$2() ? nn$1 : Bt$2; this.popover = new i({ searchable: true, items: await this.getTunesItems(e, o2, t), scopeElement: this.Editor.API.methods.ui.nodes.redactor, messages: { nothingFound: z$2.ui(K$2.ui.popover, "Nothing found"), search: z$2.ui(K$2.ui.popover, "Filter") } }), this.popover.on(G$2.Closed, this.onPopoverClose), (s2 = this.nodes.wrapper) == null || s2.append(this.popover.getElement()), this.popover.show(); } /** * Returns root block settings element */ getElement() { return this.nodes.wrapper; } /** * Returns list of items to be displayed in block tunes menu. * Merges tool specific tunes, conversion menu and common tunes in one list in predefined order * * @param currentBlock – block we are about to open block tunes for * @param commonTunes – common tunes * @param toolTunes - tool specific tunes */ async getTunesItems(e, t, o2) { const i = []; o2 !== void 0 && o2.length > 0 && (i.push(...o2), i.push({ type: _$2.Separator })); const s2 = Array.from(this.Editor.Tools.blockTools.values()), a2 = (await Yo(e, s2)).reduce((l2, c2) => (c2.toolbox.forEach((d2) => { l2.push({ icon: d2.icon, title: z$2.t(K$2.toolNames, d2.title), name: c2.name, closeOnActivate: true, onActivate: async () => { const { BlockManager: h2, Caret: p2, Toolbar: g2 } = this.Editor, f2 = await h2.convert(e, c2.name, d2.data); g2.close(), p2.setToBlock(f2, p2.positions.END); } }); }), l2), []); return a2.length > 0 && (i.push({ icon: Go, name: "convert-to", title: z$2.ui(K$2.ui.popover, "Convert to"), children: { searchable: true, items: a2 } }), i.push({ type: _$2.Separator })), i.push(...t), i.map((l2) => this.resolveTuneAliases(l2)); } /** * Resolves aliases in tunes menu items * * @param item - item with resolved aliases */ resolveTuneAliases(e) { if (e.type === _$2.Separator || e.type === _$2.Html) return e; const t = Yi(e, { label: "title" }); return e.confirmation && (t.confirmation = this.resolveTuneAliases(e.confirmation)), t; } } var sn$1 = { exports: {} }; /*! * Library for handling keyboard shortcuts * @copyright CodeX (https://codex.so) * @license MIT * @author CodeX (https://codex.so) * @version 1.2.0 */ (function(n2, e) { (function(t, o2) { n2.exports = o2(); })(window, function() { return function(t) { var o2 = {}; function i(s2) { if (o2[s2]) return o2[s2].exports; var r2 = o2[s2] = { i: s2, l: false, exports: {} }; return t[s2].call(r2.exports, r2, r2.exports, i), r2.l = true, r2.exports; } return i.m = t, i.c = o2, i.d = function(s2, r2, a2) { i.o(s2, r2) || Object.defineProperty(s2, r2, { enumerable: true, get: a2 }); }, i.r = function(s2) { typeof Symbol < "u" && Symbol.toStringTag && Object.defineProperty(s2, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(s2, "__esModule", { value: true }); }, i.t = function(s2, r2) { if (1 & r2 && (s2 = i(s2)), 8 & r2 || 4 & r2 && typeof s2 == "object" && s2 && s2.__esModule) return s2; var a2 = /* @__PURE__ */ Object.create(null); if (i.r(a2), Object.defineProperty(a2, "default", { enumerable: true, value: s2 }), 2 & r2 && typeof s2 != "string") for (var l2 in s2) i.d(a2, l2, (function(c2) { return s2[c2]; }).bind(null, l2)); return a2; }, i.n = function(s2) { var r2 = s2 && s2.__esModule ? function() { return s2.default; } : function() { return s2; }; return i.d(r2, "a", r2), r2; }, i.o = function(s2, r2) { return Object.prototype.hasOwnProperty.call(s2, r2); }, i.p = "", i(i.s = 0); }([function(t, o2, i) { function s2(l2, c2) { for (var d2 = 0; d2 < c2.length; d2++) { var h2 = c2[d2]; h2.enumerable = h2.enumerable || false, h2.configurable = true, "value" in h2 && (h2.writable = true), Object.defineProperty(l2, h2.key, h2); } } function r2(l2, c2, d2) { return c2 && s2(l2.prototype, c2), d2 && s2(l2, d2), l2; } i.r(o2); var a2 = function() { function l2(c2) { var d2 = this; (function(h2, p2) { if (!(h2 instanceof p2)) throw new TypeError("Cannot call a class as a function"); })(this, l2), this.commands = {}, this.keys = {}, this.name = c2.name, this.parseShortcutName(c2.name), this.element = c2.on, this.callback = c2.callback, this.executeShortcut = function(h2) { d2.execute(h2); }, this.element.addEventListener("keydown", this.executeShortcut, false); } return r2(l2, null, [{ key: "supportedCommands", get: function() { return { SHIFT: ["SHIFT"], CMD: ["CMD", "CONTROL", "COMMAND", "WINDOWS", "CTRL"], ALT: ["ALT", "OPTION"] }; } }, { key: "keyCodes", get: function() { return { 0: 48, 1: 49, 2: 50, 3: 51, 4: 52, 5: 53, 6: 54, 7: 55, 8: 56, 9: 57, A: 65, B: 66, C: 67, D: 68, E: 69, F: 70, G: 71, H: 72, I: 73, J: 74, K: 75, L: 76, M: 77, N: 78, O: 79, P: 80, Q: 81, R: 82, S: 83, T: 84, U: 85, V: 86, W: 87, X: 88, Y: 89, Z: 90, BACKSPACE: 8, ENTER: 13, ESCAPE: 27, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, INSERT: 45, DELETE: 46, ".": 190 }; } }]), r2(l2, [{ key: "parseShortcutName", value: function(c2) { c2 = c2.split("+"); for (var d2 = 0; d2 < c2.length; d2++) { c2[d2] = c2[d2].toUpperCase(); var h2 = false; for (var p2 in l2.supportedCommands) if (l2.supportedCommands[p2].includes(c2[d2])) { h2 = this.commands[p2] = true; break; } h2 || (this.keys[c2[d2]] = true); } for (var g2 in l2.supportedCommands) this.commands[g2] || (this.commands[g2] = false); } }, { key: "execute", value: function(c2) { var d2, h2 = { CMD: c2.ctrlKey || c2.metaKey, SHIFT: c2.shiftKey, ALT: c2.altKey }, p2 = true; for (d2 in this.commands) this.commands[d2] !== h2[d2] && (p2 = false); var g2, f2 = true; for (g2 in this.keys) f2 = f2 && c2.keyCode === l2.keyCodes[g2]; p2 && f2 && this.callback(c2); } }, { key: "remove", value: function() { this.element.removeEventListener("keydown", this.executeShortcut); } }]), l2; }(); o2.default = a2; }]).default; }); })(sn$1); var bs = sn$1.exports; const vs = /* @__PURE__ */ Ke$2(bs); class ks { constructor() { this.registeredShortcuts = /* @__PURE__ */ new Map(); } /** * Register shortcut * * @param shortcut - shortcut options */ add(e) { if (this.findShortcut(e.on, e.name)) throw Error( `Shortcut ${e.name} is already registered for ${e.on}. Please remove it before add a new handler.` ); const o2 = new vs({ name: e.name, on: e.on, callback: e.handler }), i = this.registeredShortcuts.get(e.on) || []; this.registeredShortcuts.set(e.on, [...i, o2]); } /** * Remove shortcut * * @param element - Element shortcut is set for * @param name - shortcut name */ remove(e, t) { const o2 = this.findShortcut(e, t); if (!o2) return; o2.remove(); const s2 = this.registeredShortcuts.get(e).filter((r2) => r2 !== o2); if (s2.length === 0) { this.registeredShortcuts.delete(e); return; } this.registeredShortcuts.set(e, s2); } /** * Get Shortcut instance if exist * * @param element - Element shorcut is set for * @param shortcut - shortcut name * @returns {number} index - shortcut index if exist */ findShortcut(e, t) { return (this.registeredShortcuts.get(e) || []).find(({ name: i }) => i === t); } } const ge$2 = new ks(); var ys = Object.defineProperty, ws = Object.getOwnPropertyDescriptor, rn$1 = (n2, e, t, o2) => { for (var i = o2 > 1 ? void 0 : o2 ? ws(e, t) : e, s2 = n2.length - 1, r2; s2 >= 0; s2--) (r2 = n2[s2]) && (i = (o2 ? r2(e, t, i) : r2(i)) || i); return o2 && i && ys(e, t, i), i; }, Le$1 = /* @__PURE__ */ ((n2) => (n2.Opened = "toolbox-opened", n2.Closed = "toolbox-closed", n2.BlockAdded = "toolbox-block-added", n2))(Le$1 || {}); const Ct$2 = class an2 extends Oe$1 { /** * Toolbox constructor * * @param options - available parameters * @param options.api - Editor API methods * @param options.tools - Tools available to check whether some of them should be displayed at the Toolbox or not */ constructor({ api: e, tools: t, i18nLabels: o2 }) { super(), this.opened = false, this.listeners = new _e$2(), this.popover = null, this.handleMobileLayoutToggle = () => { this.destroyPopover(), this.initPopover(); }, this.onPopoverClose = () => { this.opened = false, this.emit( "toolbox-closed" /* Closed */ ); }, this.api = e, this.tools = t, this.i18nLabels = o2, this.enableShortcuts(), this.nodes = { toolbox: u$1.make("div", an2.CSS.toolbox) }, this.initPopover(), this.api.events.on(Te$1, this.handleMobileLayoutToggle); } /** * Returns True if Toolbox is Empty and nothing to show * * @returns {boolean} */ get isEmpty() { return this.toolsToBeDisplayed.length === 0; } /** * CSS styles */ static get CSS() { return { toolbox: "ce-toolbox" }; } /** * Returns root block settings element */ getElement() { return this.nodes.toolbox; } /** * Returns true if the Toolbox has the Flipper activated and the Flipper has selected button */ hasFocus() { if (this.popover !== null) return "hasFocus" in this.popover ? this.popover.hasFocus() : void 0; } /** * Destroy Module */ destroy() { var e; super.destroy(), this.nodes && this.nodes.toolbox && this.nodes.toolbox.remove(), this.removeAllShortcuts(), (e = this.popover) == null || e.off(G$2.Closed, this.onPopoverClose), this.listeners.destroy(), this.api.events.off(Te$1, this.handleMobileLayoutToggle); } /** * Toolbox Tool's button click handler * * @param toolName - tool type to be activated * @param blockDataOverrides - Block data predefined by the activated Toolbox item */ toolButtonActivated(e, t) { this.insertNewBlock(e, t); } /** * Open Toolbox with Tools */ open() { var e; this.isEmpty || ((e = this.popover) == null || e.show(), this.opened = true, this.emit( "toolbox-opened" /* Opened */ )); } /** * Close Toolbox */ close() { var e; (e = this.popover) == null || e.hide(), this.opened = false, this.emit( "toolbox-closed" /* Closed */ ); } /** * Close Toolbox */ toggle() { this.opened ? this.close() : this.open(); } /** * Creates toolbox popover and appends it inside wrapper element */ initPopover() { var t; const e = be$2() ? nn$1 : Bt$2; this.popover = new e({ scopeElement: this.api.ui.nodes.redactor, searchable: true, messages: { nothingFound: this.i18nLabels.nothingFound, search: this.i18nLabels.filter }, items: this.toolboxItemsToBeDisplayed }), this.popover.on(G$2.Closed, this.onPopoverClose), (t = this.nodes.toolbox) == null || t.append(this.popover.getElement()); } /** * Destroys popover instance and removes it from DOM */ destroyPopover() { this.popover !== null && (this.popover.hide(), this.popover.off(G$2.Closed, this.onPopoverClose), this.popover.destroy(), this.popover = null), this.nodes.toolbox !== null && (this.nodes.toolbox.innerHTML = ""); } get toolsToBeDisplayed() { const e = []; return this.tools.forEach((t) => { t.toolbox && e.push(t); }), e; } get toolboxItemsToBeDisplayed() { const e = (t, o2, i = true) => ({ icon: t.icon, title: z$2.t(K$2.toolNames, t.title || je$1(o2.name)), name: o2.name, onActivate: () => { this.toolButtonActivated(o2.name, t.data); }, secondaryLabel: o2.shortcut && i ? vt$1(o2.shortcut) : "" }); return this.toolsToBeDisplayed.reduce((t, o2) => (Array.isArray(o2.toolbox) ? o2.toolbox.forEach((i, s2) => { t.push(e(i, o2, s2 === 0)); }) : o2.toolbox !== void 0 && t.push(e(o2.toolbox, o2)), t), []); } /** * Iterate all tools and enable theirs shortcuts if specified */ enableShortcuts() { this.toolsToBeDisplayed.forEach((e) => { const t = e.shortcut; t && this.enableShortcutForTool(e.name, t); }); } /** * Enable shortcut Block Tool implemented shortcut * * @param {string} toolName - Tool name * @param {string} shortcut - shortcut according to the ShortcutData Module format */ enableShortcutForTool(e, t) { ge$2.add({ name: t, on: this.api.ui.nodes.redactor, handler: async (o2) => { o2.preventDefault(); const i = this.api.blocks.getCurrentBlockIndex(), s2 = this.api.blocks.getBlockByIndex(i); if (s2) try { const r2 = await this.api.blocks.convert(s2.id, e); this.api.caret.setToBlock(r2, "end"); return; } catch { } this.insertNewBlock(e); } }); } /** * Removes all added shortcuts * Fired when the Read-Only mode is activated */ removeAllShortcuts() { this.toolsToBeDisplayed.forEach((e) => { const t = e.shortcut; t && ge$2.remove(this.api.ui.nodes.redactor, t); }); } /** * Inserts new block * Can be called when button clicked on Toolbox or by ShortcutData * * @param {string} toolName - Tool name * @param blockDataOverrides - predefined Block data */ async insertNewBlock(e, t) { const o2 = this.api.blocks.getCurrentBlockIndex(), i = this.api.blocks.getBlockByIndex(o2); if (!i) return; const s2 = i.isEmpty ? o2 : o2 + 1; let r2; if (t) { const l2 = await this.api.blocks.composeBlockData(e); r2 = Object.assign(l2, t); } const a2 = this.api.blocks.insert( e, r2, void 0, s2, void 0, i.isEmpty ); a2.call(ee$2.APPEND_CALLBACK), this.api.caret.setToBlock(s2), this.emit("toolbox-block-added", { block: a2 }), this.api.toolbar.close(); } }; rn$1([ me$2 ], Ct$2.prototype, "toolsToBeDisplayed", 1); rn$1([ me$2 ], Ct$2.prototype, "toolboxItemsToBeDisplayed", 1); let Es = Ct$2; const ln$1 = "block hovered"; async function xs(n2, e) { const t = navigator.keyboard; if (!t) return e; try { return (await t.getLayoutMap()).get(n2) || e; } catch (o2) { return console.error(o2), e; } } class Bs extends E$3 { /** * @class * @param moduleConfiguration - Module Configuration * @param moduleConfiguration.config - Editor's config * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher */ constructor({ config: e, eventsDispatcher: t }) { super({ config: e, eventsDispatcher: t }), this.toolboxInstance = null; } /** * CSS styles * * @returns {object} */ get CSS() { return { toolbar: "ce-toolbar", content: "ce-toolbar__content", actions: "ce-toolbar__actions", actionsOpened: "ce-toolbar__actions--opened", toolbarOpened: "ce-toolbar--opened", openedToolboxHolderModifier: "codex-editor--toolbox-opened", plusButton: "ce-toolbar__plus", plusButtonShortcut: "ce-toolbar__plus-shortcut", settingsToggler: "ce-toolbar__settings-btn", settingsTogglerHidden: "ce-toolbar__settings-btn--hidden" }; } /** * Returns the Toolbar opening state * * @returns {boolean} */ get opened() { return this.nodes.wrapper.classList.contains(this.CSS.toolbarOpened); } /** * Public interface for accessing the Toolbox */ get toolbox() { var e; return { opened: (e = this.toolboxInstance) == null ? void 0 : e.opened, close: () => { var t; (t = this.toolboxInstance) == null || t.close(); }, open: () => { if (this.toolboxInstance === null) { S$4("toolbox.open() called before initialization is finished", "warn"); return; } this.Editor.BlockManager.currentBlock = this.hoveredBlock, this.toolboxInstance.open(); }, toggle: () => { if (this.toolboxInstance === null) { S$4("toolbox.toggle() called before initialization is finished", "warn"); return; } this.toolboxInstance.toggle(); }, hasFocus: () => { var t; return (t = this.toolboxInstance) == null ? void 0 : t.hasFocus(); } }; } /** * Block actions appearance manipulations */ get blockActions() { return { hide: () => { this.nodes.actions.classList.remove(this.CSS.actionsOpened); }, show: () => { this.nodes.actions.classList.add(this.CSS.actionsOpened); } }; } /** * Methods for working with Block Tunes toggler */ get blockTunesToggler() { return { hide: () => this.nodes.settingsToggler.classList.add(this.CSS.settingsTogglerHidden), show: () => this.nodes.settingsToggler.classList.remove(this.CSS.settingsTogglerHidden) }; } /** * Toggles read-only mode * * @param {boolean} readOnlyEnabled - read-only mode */ toggleReadOnly(e) { e ? (this.destroy(), this.Editor.BlockSettings.destroy(), this.disableModuleBindings()) : window.requestIdleCallback(() => { this.drawUI(), this.enableModuleBindings(); }, { timeout: 2e3 }); } /** * Move Toolbar to the passed (or current) Block * * @param block - block to move Toolbar near it */ moveAndOpen(e = this.Editor.BlockManager.currentBlock) { if (this.toolboxInstance === null) { S$4("Can't open Toolbar since Editor initialization is not finished yet", "warn"); return; } if (this.toolboxInstance.opened && this.toolboxInstance.close(), this.Editor.BlockSettings.opened && this.Editor.BlockSettings.close(), !e) return; this.hoveredBlock = e; const t = e.holder, { isMobile: o2 } = this.Editor.UI; let i; const s2 = 20, r2 = e.firstInput, a2 = t.getBoundingClientRect(), l2 = r2 !== void 0 ? r2.getBoundingClientRect() : null, c2 = l2 !== null ? l2.top - a2.top : null, d2 = c2 !== null ? c2 > s2 : void 0; if (o2) i = t.offsetTop + t.offsetHeight; else if (r2 === void 0 || d2) { const h2 = parseInt(window.getComputedStyle(e.pluginsContent).paddingTop); i = t.offsetTop + h2; } else { const h2 = li(r2), p2 = parseInt(window.getComputedStyle(this.nodes.plusButton).height, 10), g2 = 8; i = t.offsetTop + h2 - p2 + g2 + c2; } this.nodes.wrapper.style.top = `${Math.floor(i)}px`, this.Editor.BlockManager.blocks.length === 1 && e.isEmpty ? this.blockTunesToggler.hide() : this.blockTunesToggler.show(), this.open(); } /** * Close the Toolbar */ close() { var e, t; this.Editor.ReadOnly.isEnabled || ((e = this.nodes.wrapper) == null || e.classList.remove(this.CSS.toolbarOpened), this.blockActions.hide(), (t = this.toolboxInstance) == null || t.close(), this.Editor.BlockSettings.close(), this.reset()); } /** * Reset the Toolbar position to prevent DOM height growth, for example after blocks deletion */ reset() { this.nodes.wrapper.style.top = "unset"; } /** * Open Toolbar with Plus Button and Actions * * @param {boolean} withBlockActions - by default, Toolbar opens with Block Actions. * This flag allows to open Toolbar without Actions. */ open(e = true) { this.nodes.wrapper.classList.add(this.CSS.toolbarOpened), e ? this.blockActions.show() : this.blockActions.hide(); } /** * Draws Toolbar elements */ async make() { this.nodes.wrapper = u$1.make("div", this.CSS.toolbar), ["content", "actions"].forEach((s2) => { this.nodes[s2] = u$1.make("div", this.CSS[s2]); }), u$1.append(this.nodes.wrapper, this.nodes.content), u$1.append(this.nodes.content, this.nodes.actions), this.nodes.plusButton = u$1.make("div", this.CSS.plusButton, { innerHTML: ts }), u$1.append(this.nodes.actions, this.nodes.plusButton), this.readOnlyMutableListeners.on(this.nodes.plusButton, "click", () => { $e$1(true), this.plusButtonClicked(); }, false); const e = u$1.make("div"); e.appendChild(document.createTextNode(z$2.ui(K$2.ui.toolbar.toolbox, "Add"))), e.appendChild(u$1.make("div", this.CSS.plusButtonShortcut, { textContent: "/" })), ze$2(this.nodes.plusButton, e, { hidingDelay: 400 }), this.nodes.settingsToggler = u$1.make("span", this.CSS.settingsToggler, { innerHTML: es }), u$1.append(this.nodes.actions, this.nodes.settingsToggler); const t = u$1.make("div"), o2 = u$1.text(z$2.ui(K$2.ui.blockTunes.toggler, "Click to tune")), i = await xs("Slash", "/"); t.appendChild(o2), t.appendChild(u$1.make("div", this.CSS.plusButtonShortcut, { textContent: vt$1(`CMD + ${i}`) })), ze$2(this.nodes.settingsToggler, t, { hidingDelay: 400 }), u$1.append(this.nodes.actions, this.makeToolbox()), u$1.append(this.nodes.actions, this.Editor.BlockSettings.getElement()), u$1.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper); } /** * Creates the Toolbox instance and return it's rendered element */ makeToolbox() { return this.toolboxInstance = new Es({ api: this.Editor.API.methods, tools: this.Editor.Tools.blockTools, i18nLabels: { filter: z$2.ui(K$2.ui.popover, "Filter"), nothingFound: z$2.ui(K$2.ui.popover, "Nothing found") } }), this.toolboxInstance.on(Le$1.Opened, () => { this.Editor.UI.nodes.wrapper.classList.add(this.CSS.openedToolboxHolderModifier); }), this.toolboxInstance.on(Le$1.Closed, () => { this.Editor.UI.nodes.wrapper.classList.remove(this.CSS.openedToolboxHolderModifier); }), this.toolboxInstance.on(Le$1.BlockAdded, ({ block: e }) => { const { BlockManager: t, Caret: o2 } = this.Editor, i = t.getBlockById(e.id); i.inputs.length === 0 && (i === t.lastBlock ? (t.insertAtEnd(), o2.setToBlock(t.lastBlock)) : o2.setToBlock(t.nextBlock)); }), this.toolboxInstance.getElement(); } /** * Handler for Plus Button */ plusButtonClicked() { var e; this.Editor.BlockManager.currentBlock = this.hoveredBlock, (e = this.toolboxInstance) == null || e.toggle(); } /** * Enable bindings */ enableModuleBindings() { this.readOnlyMutableListeners.on(this.nodes.settingsToggler, "mousedown", (e) => { var t; e.stopPropagation(), this.settingsTogglerClicked(), (t = this.toolboxInstance) != null && t.opened && this.toolboxInstance.close(), $e$1(true); }, true), be$2() || this.eventsDispatcher.on(ln$1, (e) => { var t; this.Editor.BlockSettings.opened || (t = this.toolboxInstance) != null && t.opened || this.moveAndOpen(e.block); }); } /** * Disable bindings */ disableModuleBindings() { this.readOnlyMutableListeners.clearAll(); } /** * Clicks on the Block Settings toggler */ settingsTogglerClicked() { this.Editor.BlockManager.currentBlock = this.hoveredBlock, this.Editor.BlockSettings.opened ? this.Editor.BlockSettings.close() : this.Editor.BlockSettings.open(this.hoveredBlock); } /** * Draws Toolbar UI * * Toolbar contains BlockSettings and Toolbox. * That's why at first we draw its components and then Toolbar itself * * Steps: * - Make Toolbar dependent components like BlockSettings, Toolbox and so on * - Make itself and append dependent nodes to itself * */ drawUI() { this.Editor.BlockSettings.make(), this.make(); } /** * Removes all created and saved HTMLElements * It is used in Read-Only mode */ destroy() { this.removeAllNodes(), this.toolboxInstance && this.toolboxInstance.destroy(); } } var ae$2 = /* @__PURE__ */ ((n2) => (n2[n2.Block = 0] = "Block", n2[n2.Inline = 1] = "Inline", n2[n2.Tune = 2] = "Tune", n2))(ae$2 || {}), Pe$1 = /* @__PURE__ */ ((n2) => (n2.Shortcut = "shortcut", n2.Toolbox = "toolbox", n2.EnabledInlineTools = "inlineToolbar", n2.EnabledBlockTunes = "tunes", n2.Config = "config", n2))(Pe$1 || {}), cn$1 = /* @__PURE__ */ ((n2) => (n2.Shortcut = "shortcut", n2.SanitizeConfig = "sanitize", n2))(cn$1 || {}), pe$2 = /* @__PURE__ */ ((n2) => (n2.IsEnabledLineBreaks = "enableLineBreaks", n2.Toolbox = "toolbox", n2.ConversionConfig = "conversionConfig", n2.IsReadOnlySupported = "isReadOnlySupported", n2.PasteConfig = "pasteConfig", n2))(pe$2 || {}), We$2 = /* @__PURE__ */ ((n2) => (n2.IsInline = "isInline", n2.Title = "title", n2.IsReadOnlySupported = "isReadOnlySupported", n2))(We$2 || {}), mt$1 = /* @__PURE__ */ ((n2) => (n2.IsTune = "isTune", n2))(mt$1 || {}); let Tt$2 = class Tt { /** * @class * @param {ConstructorOptions} options - Constructor options */ constructor({ name: e, constructable: t, config: o2, api: i, isDefault: s2, isInternal: r2 = false, defaultPlaceholder: a2 }) { this.api = i, this.name = e, this.constructable = t, this.config = o2, this.isDefault = s2, this.isInternal = r2, this.defaultPlaceholder = a2; } /** * Returns Tool user configuration */ get settings() { const e = this.config.config || {}; return this.isDefault && !("placeholder" in e) && this.defaultPlaceholder && (e.placeholder = this.defaultPlaceholder), e; } /** * Calls Tool's reset method */ reset() { if (A$4(this.constructable.reset)) return this.constructable.reset(); } /** * Calls Tool's prepare method */ prepare() { if (A$4(this.constructable.prepare)) return this.constructable.prepare({ toolName: this.name, config: this.settings }); } /** * Returns shortcut for Tool (internal or specified by user) */ get shortcut() { const e = this.constructable.shortcut; return this.config.shortcut || e; } /** * Returns Tool's sanitizer configuration */ get sanitizeConfig() { return this.constructable.sanitize || {}; } /** * Returns true if Tools is inline */ isInline() { return this.type === ae$2.Inline; } /** * Returns true if Tools is block */ isBlock() { return this.type === ae$2.Block; } /** * Returns true if Tools is tune */ isTune() { return this.type === ae$2.Tune; } }; class Cs extends E$3 { /** * @param moduleConfiguration - Module Configuration * @param moduleConfiguration.config - Editor's config * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher */ constructor({ config: e, eventsDispatcher: t }) { super({ config: e, eventsDispatcher: t }), this.CSS = { inlineToolbar: "ce-inline-toolbar" }, this.opened = false, this.popover = null, this.toolbarVerticalMargin = be$2() ? 20 : 6, this.tools = /* @__PURE__ */ new Map(), window.requestIdleCallback(() => { this.make(); }, { timeout: 2e3 }); } /** * Moving / appearance * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** * Shows Inline Toolbar if something is selected * * @param [needToClose] - pass true to close toolbar if it is not allowed. * Avoid to use it just for closing IT, better call .close() clearly. */ async tryToShow(e = false) { e && this.close(), this.allowedToShow() && (await this.open(), this.Editor.Toolbar.close()); } /** * Hides Inline Toolbar */ close() { var e, t; if (this.opened) { for (const [o2, i] of this.tools) { const s2 = this.getToolShortcut(o2.name); s2 !== void 0 && ge$2.remove(this.Editor.UI.nodes.redactor, s2), A$4(i.clear) && i.clear(); } this.tools = /* @__PURE__ */ new Map(), this.reset(), this.opened = false, (e = this.popover) == null || e.hide(), (t = this.popover) == null || t.destroy(), this.popover = null; } } /** * Check if node is contained by Inline Toolbar * * @param {Node} node — node to check */ containsNode(e) { return this.nodes.wrapper === void 0 ? false : this.nodes.wrapper.contains(e); } /** * Removes UI and its components */ destroy() { var e; this.removeAllNodes(), (e = this.popover) == null || e.destroy(), this.popover = null; } /** * Making DOM */ make() { this.nodes.wrapper = u$1.make("div", [ this.CSS.inlineToolbar, ...this.isRtl ? [this.Editor.UI.CSS.editorRtlFix] : [] ]), u$1.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper); } /** * Shows Inline Toolbar */ async open() { var t; if (this.opened) return; this.opened = true, this.popover !== null && this.popover.destroy(), this.createToolsInstances(); const e = await this.getPopoverItems(); this.popover = new hs({ items: e, scopeElement: this.Editor.API.methods.ui.nodes.redactor, messages: { nothingFound: z$2.ui(K$2.ui.popover, "Nothing found"), search: z$2.ui(K$2.ui.popover, "Filter") } }), this.move(this.popover.size.width), (t = this.nodes.wrapper) == null || t.append(this.popover.getElement()), this.popover.show(); } /** * Move Toolbar to the selected text * * @param popoverWidth - width of the toolbar popover */ move(e) { const t = b$3.rect, o2 = this.Editor.UI.nodes.wrapper.getBoundingClientRect(), i = { x: t.x - o2.x, y: t.y + t.height - // + window.scrollY o2.top + this.toolbarVerticalMargin }; i.x + e + o2.x > this.Editor.UI.contentRect.right && (i.x = this.Editor.UI.contentRect.right - e - o2.x), this.nodes.wrapper.style.left = Math.floor(i.x) + "px", this.nodes.wrapper.style.top = Math.floor(i.y) + "px"; } /** * Clear orientation classes and reset position */ reset() { this.nodes.wrapper.style.left = "0", this.nodes.wrapper.style.top = "0"; } /** * Need to show Inline Toolbar or not */ allowedToShow() { const e = ["IMG", "INPUT"], t = b$3.get(), o2 = b$3.text; if (!t || !t.anchorNode || t.isCollapsed || o2.length < 1) return false; const i = u$1.isElement(t.anchorNode) ? t.anchorNode : t.anchorNode.parentElement; if (i === null || t !== null && e.includes(i.tagName)) return false; const s2 = this.Editor.BlockManager.getBlock(t.anchorNode); return !s2 || this.getTools().some((c2) => s2.tool.inlineTools.has(c2.name)) === false ? false : i.closest("[contenteditable]") !== null; } /** * Working with Tools * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** * Returns tools that are available for current block * * Used to check if Inline Toolbar could be shown * and to render tools in the Inline Toolbar */ getTools() { const e = this.Editor.BlockManager.currentBlock; return e ? Array.from(e.tool.inlineTools.values()).filter((o2) => !(this.Editor.ReadOnly.isEnabled && o2.isReadOnlySupported !== true)) : []; } /** * Constructs tools instances and saves them to this.tools */ createToolsInstances() { this.tools = /* @__PURE__ */ new Map(), this.getTools().forEach((t) => { const o2 = t.create(); this.tools.set(t, o2); }); } /** * Returns Popover Items for tools segregated by their appearance type: regular items and custom html elements. */ async getPopoverItems() { const e = []; let t = 0; for (const [o2, i] of this.tools) { const s2 = await i.render(), r2 = this.getToolShortcut(o2.name); if (r2 !== void 0) try { this.enableShortcuts(o2.name, r2); } catch { } const a2 = r2 !== void 0 ? vt$1(r2) : void 0, l2 = z$2.t( K$2.toolNames, o2.title || je$1(o2.name) ); [s2].flat().forEach((c2) => { var h2, p2; const d2 = { name: o2.name, onActivate: () => { this.toolClicked(i); }, hint: { title: l2, description: a2 } }; if (u$1.isElement(c2)) { const g2 = { ...d2, element: c2, type: _$2.Html }; if (A$4(i.renderActions)) { const f2 = i.renderActions(); g2.children = { isOpen: (h2 = i.checkState) == null ? void 0 : h2.call(i, b$3.get()), /** Disable keyboard navigation in actions, as it might conflict with enter press handling */ isFlippable: false, items: [ { type: _$2.Html, element: f2 } ] }; } else (p2 = i.checkState) == null || p2.call(i, b$3.get()); e.push(g2); } else if (c2.type === _$2.Html) e.push({ ...d2, ...c2, type: _$2.Html }); else if (c2.type === _$2.Separator) e.push({ type: _$2.Separator }); else { const g2 = { ...d2, ...c2, type: _$2.Default }; "children" in g2 && t !== 0 && e.push({ type: _$2.Separator }), e.push(g2), "children" in g2 && t < this.tools.size - 1 && e.push({ type: _$2.Separator }); } }), t++; } return e; } /** * Get shortcut name for tool * * @param toolName — Tool name */ getToolShortcut(e) { const { Tools: t } = this.Editor, o2 = t.inlineTools.get(e), i = t.internal.inlineTools; return Array.from(i.keys()).includes(e) ? this.inlineTools[e][cn$1.Shortcut] : o2 == null ? void 0 : o2.shortcut; } /** * Enable Tool shortcut with Editor Shortcuts Module * * @param toolName - tool name * @param shortcut - shortcut according to the ShortcutData Module format */ enableShortcuts(e, t) { ge$2.add({ name: t, handler: (o2) => { var s2; const { currentBlock: i } = this.Editor.BlockManager; i && i.tool.enabledInlineTools && (o2.preventDefault(), (s2 = this.popover) == null || s2.activateItemByName(e)); }, /** * We need to bind shortcut to the document to make it work in read-only mode */ on: document }); } /** * Inline Tool button clicks * * @param tool - Tool's instance */ toolClicked(e) { var o2; const t = b$3.range; (o2 = e.surround) == null || o2.call(e, t), this.checkToolsState(); } /** * Check Tools` state by selection */ checkToolsState() { var e; (e = this.tools) == null || e.forEach((t) => { var o2; (o2 = t.checkState) == null || o2.call(t, b$3.get()); }); } /** * Get inline tools tools * Tools that has isInline is true */ get inlineTools() { const e = {}; return Array.from(this.Editor.Tools.inlineTools.entries()).forEach(([t, o2]) => { e[t] = o2.create(); }), e; } } function dn$1() { const n2 = window.getSelection(); if (n2 === null) return [null, 0]; let e = n2.focusNode, t = n2.focusOffset; return e === null ? [null, 0] : (e.nodeType !== Node.TEXT_NODE && e.childNodes.length > 0 && (e.childNodes[t] ? (e = e.childNodes[t], t = 0) : (e = e.childNodes[t - 1], t = e.textContent.length)), [e, t]); } function un$1(n2, e, t, o2) { const i = document.createRange(); o2 === "left" ? (i.setStart(n2, 0), i.setEnd(e, t)) : (i.setStart(e, t), i.setEnd(n2, n2.childNodes.length)); const s2 = i.cloneContents(), r2 = document.createElement("div"); r2.appendChild(s2); const a2 = r2.textContent || ""; return ai(a2); } function Ne$1(n2) { const e = u$1.getDeepestNode(n2); if (e === null || u$1.isEmpty(n2)) return true; if (u$1.isNativeInput(e)) return e.selectionEnd === 0; if (u$1.isEmpty(n2)) return true; const [t, o2] = dn$1(); return t === null ? false : un$1(n2, t, o2, "left"); } function Re$2(n2) { const e = u$1.getDeepestNode(n2, true); if (e === null) return true; if (u$1.isNativeInput(e)) return e.selectionEnd === e.value.length; const [t, o2] = dn$1(); return t === null ? false : un$1(n2, t, o2, "right"); } var hn$1 = {}, St$2 = {}, Xe$2 = {}, de$2 = {}, It$2 = {}, Ot$2 = {}; Object.defineProperty(Ot$2, "__esModule", { value: true }); Ot$2.allInputsSelector = Ts; function Ts() { var n2 = ["text", "password", "email", "number", "search", "tel", "url"]; return "[contenteditable=true], textarea, input:not([type]), " + n2.map(function(e) { return 'input[type="'.concat(e, '"]'); }).join(", "); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.allInputsSelector = void 0; var e = Ot$2; Object.defineProperty(n2, "allInputsSelector", { enumerable: true, get: function() { return e.allInputsSelector; } }); })(It$2); var ue$2 = {}, _t$2 = {}; Object.defineProperty(_t$2, "__esModule", { value: true }); _t$2.isNativeInput = Ss; function Ss(n2) { var e = [ "INPUT", "TEXTAREA" ]; return n2 && n2.tagName ? e.includes(n2.tagName) : false; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isNativeInput = void 0; var e = _t$2; Object.defineProperty(n2, "isNativeInput", { enumerable: true, get: function() { return e.isNativeInput; } }); })(ue$2); var pn$1 = {}, Mt$2 = {}; Object.defineProperty(Mt$2, "__esModule", { value: true }); Mt$2.append = Is; function Is(n2, e) { Array.isArray(e) ? e.forEach(function(t) { n2.appendChild(t); }) : n2.appendChild(e); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.append = void 0; var e = Mt$2; Object.defineProperty(n2, "append", { enumerable: true, get: function() { return e.append; } }); })(pn$1); var At$2 = {}, Lt$2 = {}; Object.defineProperty(Lt$2, "__esModule", { value: true }); Lt$2.blockElements = Os; function Os() { return [ "address", "article", "aside", "blockquote", "canvas", "div", "dl", "dt", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "hr", "li", "main", "nav", "noscript", "ol", "output", "p", "pre", "ruby", "section", "table", "tbody", "thead", "tr", "tfoot", "ul", "video" ]; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.blockElements = void 0; var e = Lt$2; Object.defineProperty(n2, "blockElements", { enumerable: true, get: function() { return e.blockElements; } }); })(At$2); var fn$1 = {}, Pt$2 = {}; Object.defineProperty(Pt$2, "__esModule", { value: true }); Pt$2.calculateBaseline = _s; function _s(n2) { var e = window.getComputedStyle(n2), t = parseFloat(e.fontSize), o2 = parseFloat(e.lineHeight) || t * 1.2, i = parseFloat(e.paddingTop), s2 = parseFloat(e.borderTopWidth), r2 = parseFloat(e.marginTop), a2 = t * 0.8, l2 = (o2 - t) / 2, c2 = r2 + s2 + i + l2 + a2; return c2; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.calculateBaseline = void 0; var e = Pt$2; Object.defineProperty(n2, "calculateBaseline", { enumerable: true, get: function() { return e.calculateBaseline; } }); })(fn$1); var gn$1 = {}, Nt$2 = {}, Rt$2 = {}, Dt$2 = {}; Object.defineProperty(Dt$2, "__esModule", { value: true }); Dt$2.isContentEditable = Ms; function Ms(n2) { return n2.contentEditable === "true"; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isContentEditable = void 0; var e = Dt$2; Object.defineProperty(n2, "isContentEditable", { enumerable: true, get: function() { return e.isContentEditable; } }); })(Rt$2); Object.defineProperty(Nt$2, "__esModule", { value: true }); Nt$2.canSetCaret = Ps; var As = ue$2, Ls = Rt$2; function Ps(n2) { var e = true; if ((0, As.isNativeInput)(n2)) switch (n2.type) { case "file": case "checkbox": case "radio": case "hidden": case "submit": case "button": case "image": case "reset": e = false; break; } else e = (0, Ls.isContentEditable)(n2); return e; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.canSetCaret = void 0; var e = Nt$2; Object.defineProperty(n2, "canSetCaret", { enumerable: true, get: function() { return e.canSetCaret; } }); })(gn$1); var Ve$2 = {}, Ft$2 = {}; function Ns(n2, e, t) { const o2 = t.value !== void 0 ? "value" : "get", i = t[o2], s2 = `#${e}Cache`; if (t[o2] = function(...r2) { return this[s2] === void 0 && (this[s2] = i.apply(this, r2)), this[s2]; }, o2 === "get" && t.set) { const r2 = t.set; t.set = function(a2) { delete n2[s2], r2.apply(this, a2); }; } return t; } function mn$1() { const n2 = { win: false, mac: false, x11: false, linux: false }, e = Object.keys(n2).find((t) => window.navigator.appVersion.toLowerCase().indexOf(t) !== -1); return e !== void 0 && (n2[e] = true), n2; } function jt$2(n2) { return n2 != null && n2 !== "" && (typeof n2 != "object" || Object.keys(n2).length > 0); } function Rs(n2) { return !jt$2(n2); } const Ds = () => typeof window < "u" && window.navigator !== null && jt$2(window.navigator.platform) && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1); function Fs(n2) { const e = mn$1(); return n2 = n2.replace(/shift/gi, "⇧").replace(/backspace/gi, "⌫").replace(/enter/gi, "⏎").replace(/up/gi, "↑").replace(/left/gi, "→").replace(/down/gi, "↓").replace(/right/gi, "←").replace(/escape/gi, "⎋").replace(/insert/gi, "Ins").replace(/delete/gi, "␡").replace(/\+/gi, "+"), e.mac ? n2 = n2.replace(/ctrl|cmd/gi, "⌘").replace(/alt/gi, "⌥") : n2 = n2.replace(/cmd/gi, "Ctrl").replace(/windows/gi, "WIN"), n2; } function js(n2) { return n2[0].toUpperCase() + n2.slice(1); } function Hs(n2) { const e = document.createElement("div"); e.style.position = "absolute", e.style.left = "-999px", e.style.bottom = "-999px", e.innerHTML = n2, document.body.appendChild(e); const t = window.getSelection(), o2 = document.createRange(); if (o2.selectNode(e), t === null) throw new Error("Cannot copy text to clipboard"); t.removeAllRanges(), t.addRange(o2), document.execCommand("copy"), document.body.removeChild(e); } function $s(n2, e, t) { let o2; return (...i) => { const s2 = this, r2 = () => { o2 = void 0, t !== true && n2.apply(s2, i); }, a2 = t === true && o2 !== void 0; window.clearTimeout(o2), o2 = window.setTimeout(r2, e), a2 && n2.apply(s2, i); }; } function oe$2(n2) { return Object.prototype.toString.call(n2).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); } function zs(n2) { return oe$2(n2) === "boolean"; } function bn$1(n2) { return oe$2(n2) === "function" || oe$2(n2) === "asyncfunction"; } function Us(n2) { return bn$1(n2) && /^\s*class\s+/.test(n2.toString()); } function Ws(n2) { return oe$2(n2) === "number"; } function De$2(n2) { return oe$2(n2) === "object"; } function Ys(n2) { return Promise.resolve(n2) === n2; } function Ks(n2) { return oe$2(n2) === "string"; } function Xs(n2) { return oe$2(n2) === "undefined"; } function bt$1(n2, ...e) { if (!e.length) return n2; const t = e.shift(); if (De$2(n2) && De$2(t)) for (const o2 in t) De$2(t[o2]) ? (n2[o2] === void 0 && Object.assign(n2, { [o2]: {} }), bt$1(n2[o2], t[o2])) : Object.assign(n2, { [o2]: t[o2] }); return bt$1(n2, ...e); } function Vs(n2, e, t) { const o2 = `«${e}» is deprecated and will be removed in the next major release. Please use the «${t}» instead.`; n2 && console.warn(o2); } function qs(n2) { try { return new URL(n2).href; } catch { } return n2.substring(0, 2) === "//" ? window.location.protocol + n2 : window.location.origin + n2; } function Zs(n2) { return n2 > 47 && n2 < 58 || n2 === 32 || n2 === 13 || n2 === 229 || n2 > 64 && n2 < 91 || n2 > 95 && n2 < 112 || n2 > 185 && n2 < 193 || n2 > 218 && n2 < 223; } const Gs = { BACKSPACE: 8, TAB: 9, ENTER: 13, SHIFT: 16, CTRL: 17, ALT: 18, ESC: 27, SPACE: 32, LEFT: 37, UP: 38, DOWN: 40, RIGHT: 39, DELETE: 46, META: 91, SLASH: 191 }, Qs = { LEFT: 0, WHEEL: 1, RIGHT: 2, BACKWARD: 3, FORWARD: 4 }; let Js = class { constructor() { this.completed = Promise.resolve(); } /** * Add new promise to queue * @param operation - promise should be added to queue */ add(e) { return new Promise((t, o2) => { this.completed = this.completed.then(e).then(t).catch(o2); }); } }; function er$1(n2, e, t = void 0) { let o2, i, s2, r2 = null, a2 = 0; t || (t = {}); const l2 = function() { a2 = t.leading === false ? 0 : Date.now(), r2 = null, s2 = n2.apply(o2, i), r2 === null && (o2 = i = null); }; return function() { const c2 = Date.now(); !a2 && t.leading === false && (a2 = c2); const d2 = e - (c2 - a2); return o2 = this, i = arguments, d2 <= 0 || d2 > e ? (r2 && (clearTimeout(r2), r2 = null), a2 = c2, s2 = n2.apply(o2, i), r2 === null && (o2 = i = null)) : !r2 && t.trailing !== false && (r2 = setTimeout(l2, d2)), s2; }; } const tr$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, PromiseQueue: Js, beautifyShortcut: Fs, cacheable: Ns, capitalize: js, copyTextToClipboard: Hs, debounce: $s, deepMerge: bt$1, deprecationAssert: Vs, getUserOS: mn$1, getValidUrl: qs, isBoolean: zs, isClass: Us, isEmpty: Rs, isFunction: bn$1, isIosDevice: Ds, isNumber: Ws, isObject: De$2, isPrintableKey: Zs, isPromise: Ys, isString: Ks, isUndefined: Xs, keyCodes: Gs, mouseButtons: Qs, notEmpty: jt$2, throttle: er$1, typeOf: oe$2 }, Symbol.toStringTag, { value: "Module" })), Ht$2 = /* @__PURE__ */ Xn$1(tr$1); Object.defineProperty(Ft$2, "__esModule", { value: true }); Ft$2.containsOnlyInlineElements = ir$1; var or$1 = Ht$2, nr$1 = At$2; function ir$1(n2) { var e; (0, or$1.isString)(n2) ? (e = document.createElement("div"), e.innerHTML = n2) : e = n2; var t = function(o2) { return !(0, nr$1.blockElements)().includes(o2.tagName.toLowerCase()) && Array.from(o2.children).every(t); }; return Array.from(e.children).every(t); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.containsOnlyInlineElements = void 0; var e = Ft$2; Object.defineProperty(n2, "containsOnlyInlineElements", { enumerable: true, get: function() { return e.containsOnlyInlineElements; } }); })(Ve$2); var vn$1 = {}, $t$2 = {}, qe$2 = {}, zt$2 = {}; Object.defineProperty(zt$2, "__esModule", { value: true }); zt$2.make = sr$1; function sr$1(n2, e, t) { var o2; e === void 0 && (e = null), t === void 0 && (t = {}); var i = document.createElement(n2); if (Array.isArray(e)) { var s2 = e.filter(function(a2) { return a2 !== void 0; }); (o2 = i.classList).add.apply(o2, s2); } else e !== null && i.classList.add(e); for (var r2 in t) Object.prototype.hasOwnProperty.call(t, r2) && (i[r2] = t[r2]); return i; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.make = void 0; var e = zt$2; Object.defineProperty(n2, "make", { enumerable: true, get: function() { return e.make; } }); })(qe$2); Object.defineProperty($t$2, "__esModule", { value: true }); $t$2.fragmentToString = ar$1; var rr$1 = qe$2; function ar$1(n2) { var e = (0, rr$1.make)("div"); return e.appendChild(n2), e.innerHTML; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.fragmentToString = void 0; var e = $t$2; Object.defineProperty(n2, "fragmentToString", { enumerable: true, get: function() { return e.fragmentToString; } }); })(vn$1); var kn$1 = {}, Ut$2 = {}; Object.defineProperty(Ut$2, "__esModule", { value: true }); Ut$2.getContentLength = cr$1; var lr$1 = ue$2; function cr$1(n2) { var e, t; return (0, lr$1.isNativeInput)(n2) ? n2.value.length : n2.nodeType === Node.TEXT_NODE ? n2.length : (t = (e = n2.textContent) === null || e === void 0 ? void 0 : e.length) !== null && t !== void 0 ? t : 0; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.getContentLength = void 0; var e = Ut$2; Object.defineProperty(n2, "getContentLength", { enumerable: true, get: function() { return e.getContentLength; } }); })(kn$1); var Wt$2 = {}, Yt$2 = {}, Io = Ce$1 && Ce$1.__spreadArray || function(n2, e, t) { if (t || arguments.length === 2) for (var o2 = 0, i = e.length, s2; o2 < i; o2++) (s2 || !(o2 in e)) && (s2 || (s2 = Array.prototype.slice.call(e, 0, o2)), s2[o2] = e[o2]); return n2.concat(s2 || Array.prototype.slice.call(e)); }; Object.defineProperty(Yt$2, "__esModule", { value: true }); Yt$2.getDeepestBlockElements = yn$1; var dr$1 = Ve$2; function yn$1(n2) { return (0, dr$1.containsOnlyInlineElements)(n2) ? [n2] : Array.from(n2.children).reduce(function(e, t) { return Io(Io([], e, true), yn$1(t), true); }, []); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.getDeepestBlockElements = void 0; var e = Yt$2; Object.defineProperty(n2, "getDeepestBlockElements", { enumerable: true, get: function() { return e.getDeepestBlockElements; } }); })(Wt$2); var wn$1 = {}, Kt$2 = {}, Ze$2 = {}, Xt$2 = {}; Object.defineProperty(Xt$2, "__esModule", { value: true }); Xt$2.isLineBreakTag = ur$1; function ur$1(n2) { return [ "BR", "WBR" ].includes(n2.tagName); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isLineBreakTag = void 0; var e = Xt$2; Object.defineProperty(n2, "isLineBreakTag", { enumerable: true, get: function() { return e.isLineBreakTag; } }); })(Ze$2); var Ge$2 = {}, Vt$2 = {}; Object.defineProperty(Vt$2, "__esModule", { value: true }); Vt$2.isSingleTag = hr; function hr(n2) { return [ "AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "META", "PARAM", "SOURCE", "TRACK", "WBR" ].includes(n2.tagName); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isSingleTag = void 0; var e = Vt$2; Object.defineProperty(n2, "isSingleTag", { enumerable: true, get: function() { return e.isSingleTag; } }); })(Ge$2); Object.defineProperty(Kt$2, "__esModule", { value: true }); Kt$2.getDeepestNode = En$1; var pr$1 = ue$2, fr$1 = Ze$2, gr = Ge$2; function En$1(n2, e) { e === void 0 && (e = false); var t = e ? "lastChild" : "firstChild", o2 = e ? "previousSibling" : "nextSibling"; if (n2.nodeType === Node.ELEMENT_NODE && n2[t]) { var i = n2[t]; if ((0, gr.isSingleTag)(i) && !(0, pr$1.isNativeInput)(i) && !(0, fr$1.isLineBreakTag)(i)) if (i[o2]) i = i[o2]; else if (i.parentNode !== null && i.parentNode[o2]) i = i.parentNode[o2]; else return i.parentNode; return En$1(i, e); } return n2; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.getDeepestNode = void 0; var e = Kt$2; Object.defineProperty(n2, "getDeepestNode", { enumerable: true, get: function() { return e.getDeepestNode; } }); })(wn$1); var xn$1 = {}, qt$2 = {}, Me$1 = Ce$1 && Ce$1.__spreadArray || function(n2, e, t) { if (t || arguments.length === 2) for (var o2 = 0, i = e.length, s2; o2 < i; o2++) (s2 || !(o2 in e)) && (s2 || (s2 = Array.prototype.slice.call(e, 0, o2)), s2[o2] = e[o2]); return n2.concat(s2 || Array.prototype.slice.call(e)); }; Object.defineProperty(qt$2, "__esModule", { value: true }); qt$2.findAllInputs = yr; var mr = Ve$2, br = Wt$2, vr = It$2, kr = ue$2; function yr(n2) { return Array.from(n2.querySelectorAll((0, vr.allInputsSelector)())).reduce(function(e, t) { return (0, kr.isNativeInput)(t) || (0, mr.containsOnlyInlineElements)(t) ? Me$1(Me$1([], e, true), [t], false) : Me$1(Me$1([], e, true), (0, br.getDeepestBlockElements)(t), true); }, []); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.findAllInputs = void 0; var e = qt$2; Object.defineProperty(n2, "findAllInputs", { enumerable: true, get: function() { return e.findAllInputs; } }); })(xn$1); var Bn$1 = {}, Zt$2 = {}; Object.defineProperty(Zt$2, "__esModule", { value: true }); Zt$2.isCollapsedWhitespaces = wr; function wr(n2) { return !/[^\t\n\r ]/.test(n2); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isCollapsedWhitespaces = void 0; var e = Zt$2; Object.defineProperty(n2, "isCollapsedWhitespaces", { enumerable: true, get: function() { return e.isCollapsedWhitespaces; } }); })(Bn$1); var Gt$2 = {}, Qt$2 = {}; Object.defineProperty(Qt$2, "__esModule", { value: true }); Qt$2.isElement = xr; var Er = Ht$2; function xr(n2) { return (0, Er.isNumber)(n2) ? false : !!n2 && !!n2.nodeType && n2.nodeType === Node.ELEMENT_NODE; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isElement = void 0; var e = Qt$2; Object.defineProperty(n2, "isElement", { enumerable: true, get: function() { return e.isElement; } }); })(Gt$2); var Cn$1 = {}, Jt$2 = {}, eo = {}, to = {}; Object.defineProperty(to, "__esModule", { value: true }); to.isLeaf = Br; function Br(n2) { return n2 === null ? false : n2.childNodes.length === 0; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isLeaf = void 0; var e = to; Object.defineProperty(n2, "isLeaf", { enumerable: true, get: function() { return e.isLeaf; } }); })(eo); var oo = {}, no = {}; Object.defineProperty(no, "__esModule", { value: true }); no.isNodeEmpty = Or; var Cr = Ze$2, Tr = Gt$2, Sr = ue$2, Ir = Ge$2; function Or(n2, e) { var t = ""; return (0, Ir.isSingleTag)(n2) && !(0, Cr.isLineBreakTag)(n2) ? false : ((0, Tr.isElement)(n2) && (0, Sr.isNativeInput)(n2) ? t = n2.value : n2.textContent !== null && (t = n2.textContent.replace("​", "")), e !== void 0 && (t = t.replace(new RegExp(e, "g"), "")), t.trim().length === 0); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isNodeEmpty = void 0; var e = no; Object.defineProperty(n2, "isNodeEmpty", { enumerable: true, get: function() { return e.isNodeEmpty; } }); })(oo); Object.defineProperty(Jt$2, "__esModule", { value: true }); Jt$2.isEmpty = Ar; var _r = eo, Mr = oo; function Ar(n2, e) { n2.normalize(); for (var t = [n2]; t.length > 0; ) { var o2 = t.shift(); if (o2) { if (n2 = o2, (0, _r.isLeaf)(n2) && !(0, Mr.isNodeEmpty)(n2, e)) return false; t.push.apply(t, Array.from(n2.childNodes)); } } return true; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isEmpty = void 0; var e = Jt$2; Object.defineProperty(n2, "isEmpty", { enumerable: true, get: function() { return e.isEmpty; } }); })(Cn$1); var Tn$1 = {}, io = {}; Object.defineProperty(io, "__esModule", { value: true }); io.isFragment = Pr; var Lr = Ht$2; function Pr(n2) { return (0, Lr.isNumber)(n2) ? false : !!n2 && !!n2.nodeType && n2.nodeType === Node.DOCUMENT_FRAGMENT_NODE; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isFragment = void 0; var e = io; Object.defineProperty(n2, "isFragment", { enumerable: true, get: function() { return e.isFragment; } }); })(Tn$1); var Sn$1 = {}, so = {}; Object.defineProperty(so, "__esModule", { value: true }); so.isHTMLString = Rr; var Nr = qe$2; function Rr(n2) { var e = (0, Nr.make)("div"); return e.innerHTML = n2, e.childElementCount > 0; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isHTMLString = void 0; var e = so; Object.defineProperty(n2, "isHTMLString", { enumerable: true, get: function() { return e.isHTMLString; } }); })(Sn$1); var In$1 = {}, ro = {}; Object.defineProperty(ro, "__esModule", { value: true }); ro.offset = Dr; function Dr(n2) { var e = n2.getBoundingClientRect(), t = window.pageXOffset || document.documentElement.scrollLeft, o2 = window.pageYOffset || document.documentElement.scrollTop, i = e.top + o2, s2 = e.left + t; return { top: i, left: s2, bottom: i + e.height, right: s2 + e.width }; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.offset = void 0; var e = ro; Object.defineProperty(n2, "offset", { enumerable: true, get: function() { return e.offset; } }); })(In$1); var On$1 = {}, ao = {}; Object.defineProperty(ao, "__esModule", { value: true }); ao.prepend = Fr; function Fr(n2, e) { Array.isArray(e) ? (e = e.reverse(), e.forEach(function(t) { return n2.prepend(t); })) : n2.prepend(e); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.prepend = void 0; var e = ao; Object.defineProperty(n2, "prepend", { enumerable: true, get: function() { return e.prepend; } }); })(On$1); (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.prepend = n2.offset = n2.make = n2.isLineBreakTag = n2.isSingleTag = n2.isNodeEmpty = n2.isLeaf = n2.isHTMLString = n2.isFragment = n2.isEmpty = n2.isElement = n2.isContentEditable = n2.isCollapsedWhitespaces = n2.findAllInputs = n2.isNativeInput = n2.allInputsSelector = n2.getDeepestNode = n2.getDeepestBlockElements = n2.getContentLength = n2.fragmentToString = n2.containsOnlyInlineElements = n2.canSetCaret = n2.calculateBaseline = n2.blockElements = n2.append = void 0; var e = It$2; Object.defineProperty(n2, "allInputsSelector", { enumerable: true, get: function() { return e.allInputsSelector; } }); var t = ue$2; Object.defineProperty(n2, "isNativeInput", { enumerable: true, get: function() { return t.isNativeInput; } }); var o2 = pn$1; Object.defineProperty(n2, "append", { enumerable: true, get: function() { return o2.append; } }); var i = At$2; Object.defineProperty(n2, "blockElements", { enumerable: true, get: function() { return i.blockElements; } }); var s2 = fn$1; Object.defineProperty(n2, "calculateBaseline", { enumerable: true, get: function() { return s2.calculateBaseline; } }); var r2 = gn$1; Object.defineProperty(n2, "canSetCaret", { enumerable: true, get: function() { return r2.canSetCaret; } }); var a2 = Ve$2; Object.defineProperty(n2, "containsOnlyInlineElements", { enumerable: true, get: function() { return a2.containsOnlyInlineElements; } }); var l2 = vn$1; Object.defineProperty(n2, "fragmentToString", { enumerable: true, get: function() { return l2.fragmentToString; } }); var c2 = kn$1; Object.defineProperty(n2, "getContentLength", { enumerable: true, get: function() { return c2.getContentLength; } }); var d2 = Wt$2; Object.defineProperty(n2, "getDeepestBlockElements", { enumerable: true, get: function() { return d2.getDeepestBlockElements; } }); var h2 = wn$1; Object.defineProperty(n2, "getDeepestNode", { enumerable: true, get: function() { return h2.getDeepestNode; } }); var p2 = xn$1; Object.defineProperty(n2, "findAllInputs", { enumerable: true, get: function() { return p2.findAllInputs; } }); var g2 = Bn$1; Object.defineProperty(n2, "isCollapsedWhitespaces", { enumerable: true, get: function() { return g2.isCollapsedWhitespaces; } }); var f2 = Rt$2; Object.defineProperty(n2, "isContentEditable", { enumerable: true, get: function() { return f2.isContentEditable; } }); var v2 = Gt$2; Object.defineProperty(n2, "isElement", { enumerable: true, get: function() { return v2.isElement; } }); var O2 = Cn$1; Object.defineProperty(n2, "isEmpty", { enumerable: true, get: function() { return O2.isEmpty; } }); var T2 = Tn$1; Object.defineProperty(n2, "isFragment", { enumerable: true, get: function() { return T2.isFragment; } }); var M2 = Sn$1; Object.defineProperty(n2, "isHTMLString", { enumerable: true, get: function() { return M2.isHTMLString; } }); var q2 = eo; Object.defineProperty(n2, "isLeaf", { enumerable: true, get: function() { return q2.isLeaf; } }); var F2 = oo; Object.defineProperty(n2, "isNodeEmpty", { enumerable: true, get: function() { return F2.isNodeEmpty; } }); var H2 = Ze$2; Object.defineProperty(n2, "isLineBreakTag", { enumerable: true, get: function() { return H2.isLineBreakTag; } }); var Q2 = Ge$2; Object.defineProperty(n2, "isSingleTag", { enumerable: true, get: function() { return Q2.isSingleTag; } }); var ie2 = qe$2; Object.defineProperty(n2, "make", { enumerable: true, get: function() { return ie2.make; } }); var k2 = In$1; Object.defineProperty(n2, "offset", { enumerable: true, get: function() { return k2.offset; } }); var m2 = On$1; Object.defineProperty(n2, "prepend", { enumerable: true, get: function() { return m2.prepend; } }); })(de$2); var Qe$2 = {}; Object.defineProperty(Qe$2, "__esModule", { value: true }); Qe$2.getContenteditableSlice = Hr; var jr = de$2; function Hr(n2, e, t, o2, i) { var s2; i === void 0 && (i = false); var r2 = document.createRange(); if (o2 === "left" ? (r2.setStart(n2, 0), r2.setEnd(e, t)) : (r2.setStart(e, t), r2.setEnd(n2, n2.childNodes.length)), i === true) { var a2 = r2.extractContents(); return (0, jr.fragmentToString)(a2); } var l2 = r2.cloneContents(), c2 = document.createElement("div"); c2.appendChild(l2); var d2 = (s2 = c2.textContent) !== null && s2 !== void 0 ? s2 : ""; return d2; } Object.defineProperty(Xe$2, "__esModule", { value: true }); Xe$2.checkContenteditableSliceForEmptiness = Ur; var $r = de$2, zr = Qe$2; function Ur(n2, e, t, o2) { var i = (0, zr.getContenteditableSlice)(n2, e, t, o2); return (0, $r.isCollapsedWhitespaces)(i); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.checkContenteditableSliceForEmptiness = void 0; var e = Xe$2; Object.defineProperty(n2, "checkContenteditableSliceForEmptiness", { enumerable: true, get: function() { return e.checkContenteditableSliceForEmptiness; } }); })(St$2); var _n$1 = {}; (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.getContenteditableSlice = void 0; var e = Qe$2; Object.defineProperty(n2, "getContenteditableSlice", { enumerable: true, get: function() { return e.getContenteditableSlice; } }); })(_n$1); var Mn$1 = {}, lo = {}; Object.defineProperty(lo, "__esModule", { value: true }); lo.focus = Yr; var Wr = de$2; function Yr(n2, e) { var t, o2; if (e === void 0 && (e = true), (0, Wr.isNativeInput)(n2)) { n2.focus(); var i = e ? 0 : n2.value.length; n2.setSelectionRange(i, i); } else { var s2 = document.createRange(), r2 = window.getSelection(); if (!r2) return; var a2 = function(p2) { var g2 = document.createTextNode(""); p2.appendChild(g2), s2.setStart(g2, 0), s2.setEnd(g2, 0); }, l2 = function(p2) { return p2 != null; }, c2 = n2.childNodes, d2 = e ? c2[0] : c2[c2.length - 1]; if (l2(d2)) { for (; l2(d2) && d2.nodeType !== Node.TEXT_NODE; ) d2 = e ? d2.firstChild : d2.lastChild; if (l2(d2) && d2.nodeType === Node.TEXT_NODE) { var h2 = (o2 = (t = d2.textContent) === null || t === void 0 ? void 0 : t.length) !== null && o2 !== void 0 ? o2 : 0, i = e ? 0 : h2; s2.setStart(d2, i), s2.setEnd(d2, i); } else a2(n2); } else a2(n2); r2.removeAllRanges(), r2.addRange(s2); } } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.focus = void 0; var e = lo; Object.defineProperty(n2, "focus", { enumerable: true, get: function() { return e.focus; } }); })(Mn$1); var co = {}, Je$2 = {}; Object.defineProperty(Je$2, "__esModule", { value: true }); Je$2.getCaretNodeAndOffset = Kr; function Kr() { var n2 = window.getSelection(); if (n2 === null) return [null, 0]; var e = n2.focusNode, t = n2.focusOffset; return e === null ? [null, 0] : (e.nodeType !== Node.TEXT_NODE && e.childNodes.length > 0 && (e.childNodes[t] !== void 0 ? (e = e.childNodes[t], t = 0) : (e = e.childNodes[t - 1], e.textContent !== null && (t = e.textContent.length))), [e, t]); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.getCaretNodeAndOffset = void 0; var e = Je$2; Object.defineProperty(n2, "getCaretNodeAndOffset", { enumerable: true, get: function() { return e.getCaretNodeAndOffset; } }); })(co); var An$1 = {}, et$2 = {}; Object.defineProperty(et$2, "__esModule", { value: true }); et$2.getRange = Xr; function Xr() { var n2 = window.getSelection(); return n2 && n2.rangeCount ? n2.getRangeAt(0) : null; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.getRange = void 0; var e = et$2; Object.defineProperty(n2, "getRange", { enumerable: true, get: function() { return e.getRange; } }); })(An$1); var Ln$1 = {}, uo = {}; Object.defineProperty(uo, "__esModule", { value: true }); uo.isCaretAtEndOfInput = Zr; var Oo = de$2, Vr = co, qr = St$2; function Zr(n2) { var e = (0, Oo.getDeepestNode)(n2, true); if (e === null) return true; if ((0, Oo.isNativeInput)(e)) return e.selectionEnd === e.value.length; var t = (0, Vr.getCaretNodeAndOffset)(), o2 = t[0], i = t[1]; return o2 === null ? false : (0, qr.checkContenteditableSliceForEmptiness)(n2, o2, i, "right"); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isCaretAtEndOfInput = void 0; var e = uo; Object.defineProperty(n2, "isCaretAtEndOfInput", { enumerable: true, get: function() { return e.isCaretAtEndOfInput; } }); })(Ln$1); var Pn$1 = {}, ho = {}; Object.defineProperty(ho, "__esModule", { value: true }); ho.isCaretAtStartOfInput = Jr; var Ae$1 = de$2, Gr = Je$2, Qr = Xe$2; function Jr(n2) { var e = (0, Ae$1.getDeepestNode)(n2); if (e === null || (0, Ae$1.isEmpty)(n2)) return true; if ((0, Ae$1.isNativeInput)(e)) return e.selectionEnd === 0; if ((0, Ae$1.isEmpty)(n2)) return true; var t = (0, Gr.getCaretNodeAndOffset)(), o2 = t[0], i = t[1]; return o2 === null ? false : (0, Qr.checkContenteditableSliceForEmptiness)(n2, o2, i, "left"); } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.isCaretAtStartOfInput = void 0; var e = ho; Object.defineProperty(n2, "isCaretAtStartOfInput", { enumerable: true, get: function() { return e.isCaretAtStartOfInput; } }); })(Pn$1); var Nn$1 = {}, po = {}; Object.defineProperty(po, "__esModule", { value: true }); po.save = oa; var ea = de$2, ta = et$2; function oa() { var n2 = (0, ta.getRange)(), e = (0, ea.make)("span"); if (e.id = "cursor", e.hidden = true, !!n2) return n2.insertNode(e), function() { var o2 = window.getSelection(); o2 && (n2.setStartAfter(e), n2.setEndAfter(e), o2.removeAllRanges(), o2.addRange(n2), setTimeout(function() { e.remove(); }, 150)); }; } (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.save = void 0; var e = po; Object.defineProperty(n2, "save", { enumerable: true, get: function() { return e.save; } }); })(Nn$1); (function(n2) { Object.defineProperty(n2, "__esModule", { value: true }), n2.save = n2.isCaretAtStartOfInput = n2.isCaretAtEndOfInput = n2.getRange = n2.getCaretNodeAndOffset = n2.focus = n2.getContenteditableSlice = n2.checkContenteditableSliceForEmptiness = void 0; var e = St$2; Object.defineProperty(n2, "checkContenteditableSliceForEmptiness", { enumerable: true, get: function() { return e.checkContenteditableSliceForEmptiness; } }); var t = _n$1; Object.defineProperty(n2, "getContenteditableSlice", { enumerable: true, get: function() { return t.getContenteditableSlice; } }); var o2 = Mn$1; Object.defineProperty(n2, "focus", { enumerable: true, get: function() { return o2.focus; } }); var i = co; Object.defineProperty(n2, "getCaretNodeAndOffset", { enumerable: true, get: function() { return i.getCaretNodeAndOffset; } }); var s2 = An$1; Object.defineProperty(n2, "getRange", { enumerable: true, get: function() { return s2.getRange; } }); var r2 = Ln$1; Object.defineProperty(n2, "isCaretAtEndOfInput", { enumerable: true, get: function() { return r2.isCaretAtEndOfInput; } }); var a2 = Pn$1; Object.defineProperty(n2, "isCaretAtStartOfInput", { enumerable: true, get: function() { return a2.isCaretAtStartOfInput; } }); var l2 = Nn$1; Object.defineProperty(n2, "save", { enumerable: true, get: function() { return l2.save; } }); })(hn$1); class na extends E$3 { /** * All keydowns on Block * * @param {KeyboardEvent} event - keydown */ keydown(e) { switch (this.beforeKeydownProcessing(e), e.keyCode) { case y$3.BACKSPACE: this.backspace(e); break; case y$3.DELETE: this.delete(e); break; case y$3.ENTER: this.enter(e); break; case y$3.DOWN: case y$3.RIGHT: this.arrowRightAndDown(e); break; case y$3.UP: case y$3.LEFT: this.arrowLeftAndUp(e); break; case y$3.TAB: this.tabPressed(e); break; } e.key === "/" && !e.ctrlKey && !e.metaKey && this.slashPressed(e), e.code === "Slash" && (e.ctrlKey || e.metaKey) && (e.preventDefault(), this.commandSlashPressed()); } /** * Fires on keydown before event processing * * @param {KeyboardEvent} event - keydown */ beforeKeydownProcessing(e) { this.needToolbarClosing(e) && Po(e.keyCode) && (this.Editor.Toolbar.close(), e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || this.Editor.BlockSelection.clearSelection(e)); } /** * Key up on Block: * - shows Inline Toolbar if something selected * - shows conversion toolbar with 85% of block selection * * @param {KeyboardEvent} event - keyup event */ keyup(e) { e.shiftKey || this.Editor.UI.checkEmptiness(); } /** * Add drop target styles * * @param {DragEvent} event - drag over event */ dragOver(e) { const t = this.Editor.BlockManager.getBlockByChildNode(e.target); t.dropTarget = true; } /** * Remove drop target style * * @param {DragEvent} event - drag leave event */ dragLeave(e) { const t = this.Editor.BlockManager.getBlockByChildNode(e.target); t.dropTarget = false; } /** * Copying selected blocks * Before putting to the clipboard we sanitize all blocks and then copy to the clipboard * * @param {ClipboardEvent} event - clipboard event */ handleCommandC(e) { const { BlockSelection: t } = this.Editor; t.anyBlockSelected && t.copySelectedBlocks(e); } /** * Copy and Delete selected Blocks * * @param {ClipboardEvent} event - clipboard event */ handleCommandX(e) { const { BlockSelection: t, BlockManager: o2, Caret: i } = this.Editor; t.anyBlockSelected && t.copySelectedBlocks(e).then(() => { const s2 = o2.removeSelectedBlocks(), r2 = o2.insertDefaultBlockAtIndex(s2, true); i.setToBlock(r2, i.positions.START), t.clearSelection(e); }); } /** * Tab pressed inside a Block. * * @param {KeyboardEvent} event - keydown */ tabPressed(e) { const { InlineToolbar: t, Caret: o2 } = this.Editor; if (t.opened) return; (e.shiftKey ? o2.navigatePrevious(true) : o2.navigateNext(true)) && e.preventDefault(); } /** * '/' + 'command' keydown inside a Block */ commandSlashPressed() { this.Editor.BlockSelection.selectedBlocks.length > 1 || this.activateBlockSettings(); } /** * '/' keydown inside a Block * * @param event - keydown */ slashPressed(e) { !this.Editor.UI.nodes.wrapper.contains(e.target) || !this.Editor.BlockManager.currentBlock.isEmpty || (e.preventDefault(), this.Editor.Caret.insertContentAtCaretPosition("/"), this.activateToolbox()); } /** * ENTER pressed on block * * @param {KeyboardEvent} event - keydown */ enter(e) { const { BlockManager: t, UI: o2 } = this.Editor, i = t.currentBlock; if (i === void 0 || i.tool.isLineBreaksEnabled || o2.someToolbarOpened && o2.someFlipperButtonFocused || e.shiftKey && !pt$1) return; let s2 = i; i.currentInput !== void 0 && Ne$1(i.currentInput) && !i.hasMedia ? this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex) : i.currentInput && Re$2(i.currentInput) ? s2 = this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex + 1) : s2 = this.Editor.BlockManager.split(), this.Editor.Caret.setToBlock(s2), this.Editor.Toolbar.moveAndOpen(s2), e.preventDefault(); } /** * Handle backspace keydown on Block * * @param {KeyboardEvent} event - keydown */ backspace(e) { const { BlockManager: t, Caret: o2 } = this.Editor, { currentBlock: i, previousBlock: s2 } = t; if (i === void 0 || !b$3.isCollapsed || !i.currentInput || !Ne$1(i.currentInput)) return; if (e.preventDefault(), this.Editor.Toolbar.close(), !(i.currentInput === i.firstInput)) { o2.navigatePrevious(); return; } if (s2 === null) return; if (s2.isEmpty) { t.removeBlock(s2); return; } if (i.isEmpty) { t.removeBlock(i); const l2 = t.currentBlock; o2.setToBlock(l2, o2.positions.END); return; } xo(s2, i) ? this.mergeBlocks(s2, i) : o2.setToBlock(s2, o2.positions.END); } /** * Handles delete keydown on Block * Removes char after the caret. * If caret is at the end of the block, merge next block with current * * @param {KeyboardEvent} event - keydown */ delete(e) { const { BlockManager: t, Caret: o2 } = this.Editor, { currentBlock: i, nextBlock: s2 } = t; if (!b$3.isCollapsed || !Re$2(i.currentInput)) return; if (e.preventDefault(), this.Editor.Toolbar.close(), !(i.currentInput === i.lastInput)) { o2.navigateNext(); return; } if (s2 === null) return; if (s2.isEmpty) { t.removeBlock(s2); return; } if (i.isEmpty) { t.removeBlock(i), o2.setToBlock(s2, o2.positions.START); return; } xo(i, s2) ? this.mergeBlocks(i, s2) : o2.setToBlock(s2, o2.positions.START); } /** * Merge passed Blocks * * @param targetBlock - to which Block we want to merge * @param blockToMerge - what Block we want to merge */ mergeBlocks(e, t) { const { BlockManager: o2, Toolbar: i } = this.Editor; e.lastInput !== void 0 && (hn$1.focus(e.lastInput, false), o2.mergeBlocks(e, t).then(() => { i.close(); })); } /** * Handle right and down keyboard keys * * @param {KeyboardEvent} event - keyboard event */ arrowRightAndDown(e) { const t = ce$2.usedKeys.includes(e.keyCode) && (!e.shiftKey || e.keyCode === y$3.TAB); if (this.Editor.UI.someToolbarOpened && t) return; this.Editor.Toolbar.close(); const { currentBlock: o2 } = this.Editor.BlockManager, s2 = ((o2 == null ? void 0 : o2.currentInput) !== void 0 ? Re$2(o2.currentInput) : void 0) || this.Editor.BlockSelection.anyBlockSelected; if (e.shiftKey && e.keyCode === y$3.DOWN && s2) { this.Editor.CrossBlockSelection.toggleBlockSelectedState(); return; } if (e.keyCode === y$3.DOWN || e.keyCode === y$3.RIGHT && !this.isRtl ? this.Editor.Caret.navigateNext() : this.Editor.Caret.navigatePrevious()) { e.preventDefault(); return; } Fe$2(() => { this.Editor.BlockManager.currentBlock && this.Editor.BlockManager.currentBlock.updateCurrentInput(); }, 20)(), this.Editor.BlockSelection.clearSelection(e); } /** * Handle left and up keyboard keys * * @param {KeyboardEvent} event - keyboard event */ arrowLeftAndUp(e) { if (this.Editor.UI.someToolbarOpened) { if (ce$2.usedKeys.includes(e.keyCode) && (!e.shiftKey || e.keyCode === y$3.TAB)) return; this.Editor.UI.closeAllToolbars(); } this.Editor.Toolbar.close(); const { currentBlock: t } = this.Editor.BlockManager, i = ((t == null ? void 0 : t.currentInput) !== void 0 ? Ne$1(t.currentInput) : void 0) || this.Editor.BlockSelection.anyBlockSelected; if (e.shiftKey && e.keyCode === y$3.UP && i) { this.Editor.CrossBlockSelection.toggleBlockSelectedState(false); return; } if (e.keyCode === y$3.UP || e.keyCode === y$3.LEFT && !this.isRtl ? this.Editor.Caret.navigatePrevious() : this.Editor.Caret.navigateNext()) { e.preventDefault(); return; } Fe$2(() => { this.Editor.BlockManager.currentBlock && this.Editor.BlockManager.currentBlock.updateCurrentInput(); }, 20)(), this.Editor.BlockSelection.clearSelection(e); } /** * Cases when we need to close Toolbar * * @param {KeyboardEvent} event - keyboard event */ needToolbarClosing(e) { const t = e.keyCode === y$3.ENTER && this.Editor.Toolbar.toolbox.opened, o2 = e.keyCode === y$3.ENTER && this.Editor.BlockSettings.opened, i = e.keyCode === y$3.ENTER && this.Editor.InlineToolbar.opened, s2 = e.keyCode === y$3.TAB; return !(e.shiftKey || s2 || t || o2 || i); } /** * If Toolbox is not open, then just open it and show plus button */ activateToolbox() { this.Editor.Toolbar.opened || this.Editor.Toolbar.moveAndOpen(), this.Editor.Toolbar.toolbox.open(); } /** * Open Toolbar and show BlockSettings before flipping Tools */ activateBlockSettings() { this.Editor.Toolbar.opened || this.Editor.Toolbar.moveAndOpen(), this.Editor.BlockSettings.opened || this.Editor.BlockSettings.open(); } } let ct$1 = class ct { /** * @class * @param {HTMLElement} workingArea — editor`s working node */ constructor(e) { this.blocks = [], this.workingArea = e; } /** * Get length of Block instances array * * @returns {number} */ get length() { return this.blocks.length; } /** * Get Block instances array * * @returns {Block[]} */ get array() { return this.blocks; } /** * Get blocks html elements array * * @returns {HTMLElement[]} */ get nodes() { return No(this.workingArea.children); } /** * Proxy trap to implement array-like setter * * @example * blocks[0] = new Block(...) * @param {Blocks} instance — Blocks instance * @param {PropertyKey} property — block index or any Blocks class property key to set * @param {Block} value — value to set * @returns {boolean} */ static set(e, t, o2) { return isNaN(Number(t)) ? (Reflect.set(e, t, o2), true) : (e.insert(+t, o2), true); } /** * Proxy trap to implement array-like getter * * @param {Blocks} instance — Blocks instance * @param {PropertyKey} property — Blocks class property key * @returns {Block|*} */ static get(e, t) { return isNaN(Number(t)) ? Reflect.get(e, t) : e.get(+t); } /** * Push new Block to the blocks array and append it to working area * * @param {Block} block - Block to add */ push(e) { this.blocks.push(e), this.insertToDOM(e); } /** * Swaps blocks with indexes first and second * * @param {number} first - first block index * @param {number} second - second block index * @deprecated — use 'move' instead */ swap(e, t) { const o2 = this.blocks[t]; u$1.swap(this.blocks[e].holder, o2.holder), this.blocks[t] = this.blocks[e], this.blocks[e] = o2; } /** * Move a block from one to another index * * @param {number} toIndex - new index of the block * @param {number} fromIndex - block to move */ move(e, t) { const o2 = this.blocks.splice(t, 1)[0], i = e - 1, s2 = Math.max(0, i), r2 = this.blocks[s2]; e > 0 ? this.insertToDOM(o2, "afterend", r2) : this.insertToDOM(o2, "beforebegin", r2), this.blocks.splice(e, 0, o2); const a2 = this.composeBlockEvent("move", { fromIndex: t, toIndex: e }); o2.call(ee$2.MOVED, a2); } /** * Insert new Block at passed index * * @param {number} index — index to insert Block * @param {Block} block — Block to insert * @param {boolean} replace — it true, replace block on given index */ insert(e, t, o2 = false) { if (!this.length) { this.push(t); return; } e > this.length && (e = this.length), o2 && (this.blocks[e].holder.remove(), this.blocks[e].call(ee$2.REMOVED)); const i = o2 ? 1 : 0; if (this.blocks.splice(e, i, t), e > 0) { const s2 = this.blocks[e - 1]; this.insertToDOM(t, "afterend", s2); } else { const s2 = this.blocks[e + 1]; s2 ? this.insertToDOM(t, "beforebegin", s2) : this.insertToDOM(t); } } /** * Replaces block under passed index with passed block * * @param index - index of existed block * @param block - new block */ replace(e, t) { if (this.blocks[e] === void 0) throw Error("Incorrect index"); this.blocks[e].holder.replaceWith(t.holder), this.blocks[e] = t; } /** * Inserts several blocks at once * * @param blocks - blocks to insert * @param index - index to insert blocks at */ insertMany(e, t) { const o2 = new DocumentFragment(); for (const i of e) o2.appendChild(i.holder); if (this.length > 0) { if (t > 0) { const i = Math.min(t - 1, this.length - 1); this.blocks[i].holder.after(o2); } else t === 0 && this.workingArea.prepend(o2); this.blocks.splice(t, 0, ...e); } else this.blocks.push(...e), this.workingArea.appendChild(o2); e.forEach((i) => i.call(ee$2.RENDERED)); } /** * Remove block * * @param {number} index - index of Block to remove */ remove(e) { isNaN(e) && (e = this.length - 1), this.blocks[e].holder.remove(), this.blocks[e].call(ee$2.REMOVED), this.blocks.splice(e, 1); } /** * Remove all blocks */ removeAll() { this.workingArea.innerHTML = "", this.blocks.forEach((e) => e.call(ee$2.REMOVED)), this.blocks.length = 0; } /** * Insert Block after passed target * * @todo decide if this method is necessary * @param {Block} targetBlock — target after which Block should be inserted * @param {Block} newBlock — Block to insert */ insertAfter(e, t) { const o2 = this.blocks.indexOf(e); this.insert(o2 + 1, t); } /** * Get Block by index * * @param {number} index — Block index * @returns {Block} */ get(e) { return this.blocks[e]; } /** * Return index of passed Block * * @param {Block} block - Block to find * @returns {number} */ indexOf(e) { return this.blocks.indexOf(e); } /** * Insert new Block into DOM * * @param {Block} block - Block to insert * @param {InsertPosition} position — insert position (if set, will use insertAdjacentElement) * @param {Block} target — Block related to position */ insertToDOM(e, t, o2) { t ? o2.holder.insertAdjacentElement(t, e.holder) : this.workingArea.appendChild(e.holder), e.call(ee$2.RENDERED); } /** * Composes Block event with passed type and details * * @param {string} type - event type * @param {object} detail - event detail */ composeBlockEvent(e, t) { return new CustomEvent(e, { detail: t }); } }; const _o = "block-removed", Mo = "block-added", ia = "block-moved", Ao = "block-changed"; class sa { constructor() { this.completed = Promise.resolve(); } /** * Add new promise to queue * * @param operation - promise should be added to queue */ add(e) { return new Promise((t, o2) => { this.completed = this.completed.then(e).then(t).catch(o2); }); } } class ra extends E$3 { constructor() { super(...arguments), this._currentBlockIndex = -1, this._blocks = null; } /** * Returns current Block index * * @returns {number} */ get currentBlockIndex() { return this._currentBlockIndex; } /** * Set current Block index and fire Block lifecycle callbacks * * @param {number} newIndex - index of Block to set as current */ set currentBlockIndex(e) { this._currentBlockIndex = e; } /** * returns first Block * * @returns {Block} */ get firstBlock() { return this._blocks[0]; } /** * returns last Block * * @returns {Block} */ get lastBlock() { return this._blocks[this._blocks.length - 1]; } /** * Get current Block instance * * @returns {Block} */ get currentBlock() { return this._blocks[this.currentBlockIndex]; } /** * Set passed Block as a current * * @param block - block to set as a current */ set currentBlock(e) { this.currentBlockIndex = this.getBlockIndex(e); } /** * Returns next Block instance * * @returns {Block|null} */ get nextBlock() { return this.currentBlockIndex === this._blocks.length - 1 ? null : this._blocks[this.currentBlockIndex + 1]; } /** * Return first Block with inputs after current Block * * @returns {Block | undefined} */ get nextContentfulBlock() { return this.blocks.slice(this.currentBlockIndex + 1).find((t) => !!t.inputs.length); } /** * Return first Block with inputs before current Block * * @returns {Block | undefined} */ get previousContentfulBlock() { return this.blocks.slice(0, this.currentBlockIndex).reverse().find((t) => !!t.inputs.length); } /** * Returns previous Block instance * * @returns {Block|null} */ get previousBlock() { return this.currentBlockIndex === 0 ? null : this._blocks[this.currentBlockIndex - 1]; } /** * Get array of Block instances * * @returns {Block[]} {@link Blocks#array} */ get blocks() { return this._blocks.array; } /** * Check if each Block is empty * * @returns {boolean} */ get isEditorEmpty() { return this.blocks.every((e) => e.isEmpty); } /** * Should be called after Editor.UI preparation * Define this._blocks property */ prepare() { const e = new ct$1(this.Editor.UI.nodes.redactor); this._blocks = new Proxy(e, { set: ct$1.set, get: ct$1.get }), this.listeners.on( document, "copy", (t) => this.Editor.BlockEvents.handleCommandC(t) ); } /** * Toggle read-only state * * If readOnly is true: * - Unbind event handlers from created Blocks * * if readOnly is false: * - Bind event handlers to all existing Blocks * * @param {boolean} readOnlyEnabled - "read only" state */ toggleReadOnly(e) { e ? this.disableModuleBindings() : this.enableModuleBindings(); } /** * Creates Block instance by tool name * * @param {object} options - block creation options * @param {string} options.tool - tools passed in editor config {@link EditorConfig#tools} * @param {string} [options.id] - unique id for this block * @param {BlockToolData} [options.data] - constructor params * @returns {Block} */ composeBlock({ tool: e, data: t = {}, id: o2 = void 0, tunes: i = {} }) { const s2 = this.Editor.ReadOnly.isEnabled, r2 = this.Editor.Tools.blockTools.get(e), a2 = new R$5({ id: o2, data: t, tool: r2, api: this.Editor.API, readOnly: s2, tunesData: i }, this.eventsDispatcher); return s2 || window.requestIdleCallback(() => { this.bindBlockEvents(a2); }, { timeout: 2e3 }), a2; } /** * Insert new block into _blocks * * @param {object} options - insert options * @param {string} [options.id] - block's unique id * @param {string} [options.tool] - plugin name, by default method inserts the default block type * @param {object} [options.data] - plugin data * @param {number} [options.index] - index where to insert new Block * @param {boolean} [options.needToFocus] - flag shows if needed to update current Block index * @param {boolean} [options.replace] - flag shows if block by passed index should be replaced with inserted one * @returns {Block} */ insert({ id: e = void 0, tool: t = this.config.defaultBlock, data: o2 = {}, index: i, needToFocus: s2 = true, replace: r2 = false, tunes: a2 = {} } = {}) { let l2 = i; l2 === void 0 && (l2 = this.currentBlockIndex + (r2 ? 0 : 1)); const c2 = this.composeBlock({ id: e, tool: t, data: o2, tunes: a2 }); return r2 && this.blockDidMutated(_o, this.getBlockByIndex(l2), { index: l2 }), this._blocks.insert(l2, c2, r2), this.blockDidMutated(Mo, c2, { index: l2 }), s2 ? this.currentBlockIndex = l2 : l2 <= this.currentBlockIndex && this.currentBlockIndex++, c2; } /** * Inserts several blocks at once * * @param blocks - blocks to insert * @param index - index where to insert */ insertMany(e, t = 0) { this._blocks.insertMany(e, t); } /** * Update Block data. * * Currently we don't have an 'update' method in the Tools API, so we just create a new block with the same id and type * Should not trigger 'block-removed' or 'block-added' events. * * If neither data nor tunes is provided, return the provided block instead. * * @param block - block to update * @param data - (optional) new data * @param tunes - (optional) tune data */ async update(e, t, o2) { if (!t && !o2) return e; const i = await e.data, s2 = this.composeBlock({ id: e.id, tool: e.name, data: Object.assign({}, i, t ?? {}), tunes: o2 ?? e.tunes }), r2 = this.getBlockIndex(e); return this._blocks.replace(r2, s2), this.blockDidMutated(Ao, s2, { index: r2 }), s2; } /** * Replace passed Block with the new one with specified Tool and data * * @param block - block to replace * @param newTool - new Tool name * @param data - new Tool data */ replace(e, t, o2) { const i = this.getBlockIndex(e); return this.insert({ tool: t, data: o2, index: i, replace: true }); } /** * Insert pasted content. Call onPaste callback after insert. * * @param {string} toolName - name of Tool to insert * @param {PasteEvent} pasteEvent - pasted data * @param {boolean} replace - should replace current block */ paste(e, t, o2 = false) { const i = this.insert({ tool: e, replace: o2 }); try { window.requestIdleCallback(() => { i.call(ee$2.ON_PASTE, t); }); } catch (s2) { S$4(`${e}: onPaste callback call is failed`, "error", s2); } return i; } /** * Insert new default block at passed index * * @param {number} index - index where Block should be inserted * @param {boolean} needToFocus - if true, updates current Block index * * TODO: Remove method and use insert() with index instead (?) * @returns {Block} inserted Block */ insertDefaultBlockAtIndex(e, t = false) { const o2 = this.composeBlock({ tool: this.config.defaultBlock }); return this._blocks[e] = o2, this.blockDidMutated(Mo, o2, { index: e }), t ? this.currentBlockIndex = e : e <= this.currentBlockIndex && this.currentBlockIndex++, o2; } /** * Always inserts at the end * * @returns {Block} */ insertAtEnd() { return this.currentBlockIndex = this.blocks.length - 1, this.insert(); } /** * Merge two blocks * * @param {Block} targetBlock - previous block will be append to this block * @param {Block} blockToMerge - block that will be merged with target block * @returns {Promise} - the sequence that can be continued */ async mergeBlocks(e, t) { let o2; if (e.name === t.name && e.mergeable) { const i = await t.data; if (V$2(i)) { console.error("Could not merge Block. Failed to extract original Block data."); return; } const [s2] = yt$1([i], e.tool.sanitizeConfig); o2 = s2; } else if (e.mergeable && He$2(t, "export") && He$2(e, "import")) { const i = await t.exportDataAsString(), s2 = Z$2(i, e.tool.sanitizeConfig); o2 = Bo(s2, e.tool.conversionConfig); } o2 !== void 0 && (await e.mergeWith(o2), this.removeBlock(t), this.currentBlockIndex = this._blocks.indexOf(e)); } /** * Remove passed Block * * @param block - Block to remove * @param addLastBlock - if true, adds new default block at the end. @todo remove this logic and use event-bus instead */ removeBlock(e, t = true) { return new Promise((o2) => { const i = this._blocks.indexOf(e); if (!this.validateIndex(i)) throw new Error("Can't find a Block to remove"); this._blocks.remove(i), e.destroy(), this.blockDidMutated(_o, e, { index: i }), this.currentBlockIndex >= i && this.currentBlockIndex--, this.blocks.length ? i === 0 && (this.currentBlockIndex = 0) : (this.unsetCurrentBlock(), t && this.insert()), o2(); }); } /** * Remove only selected Blocks * and returns first Block index where started removing... * * @returns {number|undefined} */ removeSelectedBlocks() { let e; for (let t = this.blocks.length - 1; t >= 0; t--) this.blocks[t].selected && (this.removeBlock(this.blocks[t]), e = t); return e; } /** * Attention! * After removing insert the new default typed Block and focus on it * Removes all blocks */ removeAllBlocks() { for (let e = this.blocks.length - 1; e >= 0; e--) this._blocks.remove(e); this.unsetCurrentBlock(), this.insert(), this.currentBlock.firstInput.focus(); } /** * Split current Block * 1. Extract content from Caret position to the Block`s end * 2. Insert a new Block below current one with extracted content * * @returns {Block} */ split() { const e = this.Editor.Caret.extractFragmentFromCaretPosition(), t = u$1.make("div"); t.appendChild(e); const o2 = { text: u$1.isEmpty(t) ? "" : t.innerHTML }; return this.insert({ data: o2 }); } /** * Returns Block by passed index * * @param {number} index - index to get. -1 to get last * @returns {Block} */ getBlockByIndex(e) { return e === -1 && (e = this._blocks.length - 1), this._blocks[e]; } /** * Returns an index for passed Block * * @param block - block to find index */ getBlockIndex(e) { return this._blocks.indexOf(e); } /** * Returns the Block by passed id * * @param id - id of block to get * @returns {Block} */ getBlockById(e) { return this._blocks.array.find((t) => t.id === e); } /** * Get Block instance by html element * * @param {Node} element - html element to get Block by */ getBlock(e) { u$1.isElement(e) || (e = e.parentNode); const t = this._blocks.nodes, o2 = e.closest(`.${R$5.CSS.wrapper}`), i = t.indexOf(o2); if (i >= 0) return this._blocks[i]; } /** * 1) Find first-level Block from passed child Node * 2) Mark it as current * * @param {Node} childNode - look ahead from this node. * @returns {Block | undefined} can return undefined in case when the passed child note is not a part of the current editor instance */ setCurrentBlockByChildNode(e) { u$1.isElement(e) || (e = e.parentNode); const t = e.closest(`.${R$5.CSS.wrapper}`); if (!t) return; const o2 = t.closest(`.${this.Editor.UI.CSS.editorWrapper}`); if (o2 != null && o2.isEqualNode(this.Editor.UI.nodes.wrapper)) return this.currentBlockIndex = this._blocks.nodes.indexOf(t), this.currentBlock.updateCurrentInput(), this.currentBlock; } /** * Return block which contents passed node * * @param {Node} childNode - node to get Block by * @returns {Block} */ getBlockByChildNode(e) { if (!e || !(e instanceof Node)) return; u$1.isElement(e) || (e = e.parentNode); const t = e.closest(`.${R$5.CSS.wrapper}`); return this.blocks.find((o2) => o2.holder === t); } /** * Swap Blocks Position * * @param {number} fromIndex - index of first block * @param {number} toIndex - index of second block * @deprecated — use 'move' instead */ swap(e, t) { this._blocks.swap(e, t), this.currentBlockIndex = t; } /** * Move a block to a new index * * @param {number} toIndex - index where to move Block * @param {number} fromIndex - index of Block to move */ move(e, t = this.currentBlockIndex) { if (isNaN(e) || isNaN(t)) { S$4("Warning during 'move' call: incorrect indices provided.", "warn"); return; } if (!this.validateIndex(e) || !this.validateIndex(t)) { S$4("Warning during 'move' call: indices cannot be lower than 0 or greater than the amount of blocks.", "warn"); return; } this._blocks.move(e, t), this.currentBlockIndex = e, this.blockDidMutated(ia, this.currentBlock, { fromIndex: t, toIndex: e }); } /** * Converts passed Block to the new Tool * Uses Conversion Config * * @param blockToConvert - Block that should be converted * @param targetToolName - name of the Tool to convert to * @param blockDataOverrides - optional new Block data overrides */ async convert(e, t, o2) { if (!await e.save()) throw new Error("Could not convert Block. Failed to extract original Block data."); const s2 = this.Editor.Tools.blockTools.get(t); if (!s2) throw new Error(`Could not convert Block. Tool «${t}» not found.`); const r2 = await e.exportDataAsString(), a2 = Z$2( r2, s2.sanitizeConfig ); let l2 = Bo(a2, s2.conversionConfig, s2.settings); return o2 && (l2 = Object.assign(l2, o2)), this.replace(e, s2.name, l2); } /** * Sets current Block Index -1 which means unknown * and clear highlights */ unsetCurrentBlock() { this.currentBlockIndex = -1; } /** * Clears Editor * * @param {boolean} needToAddDefaultBlock - 1) in internal calls (for example, in api.blocks.render) * we don't need to add an empty default block * 2) in api.blocks.clear we should add empty block */ async clear(e = false) { const t = new sa(); [...this.blocks].forEach((i) => { t.add(async () => { await this.removeBlock(i, false); }); }), await t.completed, this.unsetCurrentBlock(), e && this.insert(), this.Editor.UI.checkEmptiness(); } /** * Cleans up all the block tools' resources * This is called when editor is destroyed */ async destroy() { await Promise.all(this.blocks.map((e) => e.destroy())); } /** * Bind Block events * * @param {Block} block - Block to which event should be bound */ bindBlockEvents(e) { const { BlockEvents: t } = this.Editor; this.readOnlyMutableListeners.on(e.holder, "keydown", (o2) => { t.keydown(o2); }), this.readOnlyMutableListeners.on(e.holder, "keyup", (o2) => { t.keyup(o2); }), this.readOnlyMutableListeners.on(e.holder, "dragover", (o2) => { t.dragOver(o2); }), this.readOnlyMutableListeners.on(e.holder, "dragleave", (o2) => { t.dragLeave(o2); }), e.on("didMutated", (o2) => this.blockDidMutated(Ao, o2, { index: this.getBlockIndex(o2) })); } /** * Disable mutable handlers and bindings */ disableModuleBindings() { this.readOnlyMutableListeners.clearAll(); } /** * Enables all module handlers and bindings for all Blocks */ enableModuleBindings() { this.readOnlyMutableListeners.on( document, "cut", (e) => this.Editor.BlockEvents.handleCommandX(e) ), this.blocks.forEach((e) => { this.bindBlockEvents(e); }); } /** * Validates that the given index is not lower than 0 or higher than the amount of blocks * * @param {number} index - index of blocks array to validate * @returns {boolean} */ validateIndex(e) { return !(e < 0 || e >= this._blocks.length); } /** * Block mutation callback * * @param mutationType - what happened with block * @param block - mutated block * @param detailData - additional data to pass with change event */ blockDidMutated(e, t, o2) { const i = new CustomEvent(e, { detail: { target: new J$2(t), ...o2 } }); return this.eventsDispatcher.emit($o, { event: i }), t; } } class aa extends E$3 { constructor() { super(...arguments), this.anyBlockSelectedCache = null, this.needToSelectAll = false, this.nativeInputSelected = false, this.readyToBlockSelection = false; } /** * Sanitizer Config * * @returns {SanitizerConfig} */ get sanitizerConfig() { return { p: {}, h1: {}, h2: {}, h3: {}, h4: {}, h5: {}, h6: {}, ol: {}, ul: {}, li: {}, br: true, img: { src: true, width: true, height: true }, a: { href: true }, b: {}, i: {}, u: {} }; } /** * Flag that identifies all Blocks selection * * @returns {boolean} */ get allBlocksSelected() { const { BlockManager: e } = this.Editor; return e.blocks.every((t) => t.selected === true); } /** * Set selected all blocks * * @param {boolean} state - state to set */ set allBlocksSelected(e) { const { BlockManager: t } = this.Editor; t.blocks.forEach((o2) => { o2.selected = e; }), this.clearCache(); } /** * Flag that identifies any Block selection * * @returns {boolean} */ get anyBlockSelected() { const { BlockManager: e } = this.Editor; return this.anyBlockSelectedCache === null && (this.anyBlockSelectedCache = e.blocks.some((t) => t.selected === true)), this.anyBlockSelectedCache; } /** * Return selected Blocks array * * @returns {Block[]} */ get selectedBlocks() { return this.Editor.BlockManager.blocks.filter((e) => e.selected); } /** * Module Preparation * Registers Shortcuts CMD+A and CMD+C * to select all and copy them */ prepare() { this.selection = new b$3(), ge$2.add({ name: "CMD+A", handler: (e) => { const { BlockManager: t, ReadOnly: o2 } = this.Editor; if (o2.isEnabled) { e.preventDefault(), this.selectAllBlocks(); return; } t.currentBlock && this.handleCommandA(e); }, on: this.Editor.UI.nodes.redactor }); } /** * Toggle read-only state * * - Remove all ranges * - Unselect all Blocks */ toggleReadOnly() { b$3.get().removeAllRanges(), this.allBlocksSelected = false; } /** * Remove selection of Block * * @param {number?} index - Block index according to the BlockManager's indexes */ unSelectBlockByIndex(e) { const { BlockManager: t } = this.Editor; let o2; isNaN(e) ? o2 = t.currentBlock : o2 = t.getBlockByIndex(e), o2.selected = false, this.clearCache(); } /** * Clear selection from Blocks * * @param {Event} reason - event caused clear of selection * @param {boolean} restoreSelection - if true, restore saved selection */ clearSelection(e, t = false) { const { BlockManager: o2, Caret: i, RectangleSelection: s2 } = this.Editor; this.needToSelectAll = false, this.nativeInputSelected = false, this.readyToBlockSelection = false; const r2 = e && e instanceof KeyboardEvent, a2 = r2 && Po(e.keyCode); if (this.anyBlockSelected && r2 && a2 && !b$3.isSelectionExists) { const l2 = o2.removeSelectedBlocks(); o2.insertDefaultBlockAtIndex(l2, true), i.setToBlock(o2.currentBlock), Fe$2(() => { const c2 = e.key; i.insertContentAtCaretPosition(c2.length > 1 ? "" : c2); }, 20)(); } if (this.Editor.CrossBlockSelection.clear(e), !this.anyBlockSelected || s2.isRectActivated()) { this.Editor.RectangleSelection.clearSelection(); return; } t && this.selection.restore(), this.allBlocksSelected = false; } /** * Reduce each Block and copy its content * * @param {ClipboardEvent} e - copy/cut event * @returns {Promise} */ copySelectedBlocks(e) { e.preventDefault(); const t = u$1.make("div"); this.selectedBlocks.forEach((s2) => { const r2 = Z$2(s2.holder.innerHTML, this.sanitizerConfig), a2 = u$1.make("p"); a2.innerHTML = r2, t.appendChild(a2); }); const o2 = Array.from(t.childNodes).map((s2) => s2.textContent).join(` `), i = t.innerHTML; return e.clipboardData.setData("text/plain", o2), e.clipboardData.setData("text/html", i), Promise.all(this.selectedBlocks.map((s2) => s2.save())).then((s2) => { try { e.clipboardData.setData(this.Editor.Paste.MIME_TYPE, JSON.stringify(s2)); } catch { } }); } /** * Select Block by its index * * @param {number?} index - Block index according to the BlockManager's indexes */ selectBlockByIndex(e) { const { BlockManager: t } = this.Editor, o2 = t.getBlockByIndex(e); o2 !== void 0 && this.selectBlock(o2); } /** * Select passed Block * * @param {Block} block - Block to select */ selectBlock(e) { this.selection.save(), b$3.get().removeAllRanges(), e.selected = true, this.clearCache(), this.Editor.InlineToolbar.close(); } /** * Remove selection from passed Block * * @param {Block} block - Block to unselect */ unselectBlock(e) { e.selected = false, this.clearCache(); } /** * Clear anyBlockSelected cache */ clearCache() { this.anyBlockSelectedCache = null; } /** * Module destruction * De-registers Shortcut CMD+A */ destroy() { ge$2.remove(this.Editor.UI.nodes.redactor, "CMD+A"); } /** * First CMD+A selects all input content by native behaviour, * next CMD+A keypress selects all blocks * * @param {KeyboardEvent} event - keyboard event */ handleCommandA(e) { if (this.Editor.RectangleSelection.clearSelection(), u$1.isNativeInput(e.target) && !this.readyToBlockSelection) { this.readyToBlockSelection = true; return; } const t = this.Editor.BlockManager.getBlock(e.target), o2 = t.inputs; if (o2.length > 1 && !this.readyToBlockSelection) { this.readyToBlockSelection = true; return; } if (o2.length === 1 && !this.needToSelectAll) { this.needToSelectAll = true; return; } this.needToSelectAll ? (e.preventDefault(), this.selectAllBlocks(), this.needToSelectAll = false, this.readyToBlockSelection = false) : this.readyToBlockSelection && (e.preventDefault(), this.selectBlock(t), this.needToSelectAll = true); } /** * Select All Blocks * Each Block has selected setter that makes Block copyable */ selectAllBlocks() { this.selection.save(), b$3.get().removeAllRanges(), this.allBlocksSelected = true, this.Editor.InlineToolbar.close(); } } let Ye$2 = class Ye2 extends E$3 { /** * Allowed caret positions in input * * @static * @returns {{START: string, END: string, DEFAULT: string}} */ get positions() { return { START: "start", END: "end", DEFAULT: "default" }; } /** * Elements styles that can be useful for Caret Module */ static get CSS() { return { shadowCaret: "cdx-shadow-caret" }; } /** * Method gets Block instance and puts caret to the text node with offset * There two ways that method applies caret position: * - first found text node: sets at the beginning, but you can pass an offset * - last found text node: sets at the end of the node. Also, you can customize the behaviour * * @param {Block} block - Block class * @param {string} position - position where to set caret. * If default - leave default behaviour and apply offset if it's passed * @param {number} offset - caret offset regarding to the block content */ setToBlock(e, t = this.positions.DEFAULT, o2 = 0) { var c2; const { BlockManager: i, BlockSelection: s2 } = this.Editor; if (s2.clearSelection(), !e.focusable) { (c2 = window.getSelection()) == null || c2.removeAllRanges(), s2.selectBlock(e), i.currentBlock = e; return; } let r2; switch (t) { case this.positions.START: r2 = e.firstInput; break; case this.positions.END: r2 = e.lastInput; break; default: r2 = e.currentInput; } if (!r2) return; let a2, l2 = o2; if (t === this.positions.START) a2 = u$1.getDeepestNode(r2, false), l2 = 0; else if (t === this.positions.END) a2 = u$1.getDeepestNode(r2, true), l2 = u$1.getContentLength(a2); else { const { node: d2, offset: h2 } = u$1.getNodeByOffset(r2, o2); d2 ? (a2 = d2, l2 = h2) : (a2 = u$1.getDeepestNode(r2, false), l2 = 0); } this.set(a2, l2), i.setCurrentBlockByChildNode(e.holder), i.currentBlock.currentInput = r2; } /** * Set caret to the current input of current Block. * * @param {HTMLElement} input - input where caret should be set * @param {string} position - position of the caret. * If default - leave default behaviour and apply offset if it's passed * @param {number} offset - caret offset regarding to the text node */ setToInput(e, t = this.positions.DEFAULT, o2 = 0) { const { currentBlock: i } = this.Editor.BlockManager, s2 = u$1.getDeepestNode(e); switch (t) { case this.positions.START: this.set(s2, 0); break; case this.positions.END: this.set(s2, u$1.getContentLength(s2)); break; default: o2 && this.set(s2, o2); } i.currentInput = e; } /** * Creates Document Range and sets caret to the element with offset * * @param {HTMLElement} element - target node. * @param {number} offset - offset */ set(e, t = 0) { const { top: i, bottom: s2 } = b$3.setCursor(e, t), { innerHeight: r2 } = window; i < 0 ? window.scrollBy(0, i - 30) : s2 > r2 && window.scrollBy(0, s2 - r2 + 30); } /** * Set Caret to the last Block * If last block is not empty, append another empty block */ setToTheLastBlock() { const e = this.Editor.BlockManager.lastBlock; if (e) if (e.tool.isDefault && e.isEmpty) this.setToBlock(e); else { const t = this.Editor.BlockManager.insertAtEnd(); this.setToBlock(t); } } /** * Extract content fragment of current Block from Caret position to the end of the Block */ extractFragmentFromCaretPosition() { const e = b$3.get(); if (e.rangeCount) { const t = e.getRangeAt(0), o2 = this.Editor.BlockManager.currentBlock.currentInput; if (t.deleteContents(), o2) if (u$1.isNativeInput(o2)) { const i = o2, s2 = document.createDocumentFragment(), r2 = i.value.substring(0, i.selectionStart), a2 = i.value.substring(i.selectionStart); return s2.textContent = a2, i.value = r2, s2; } else { const i = t.cloneRange(); return i.selectNodeContents(o2), i.setStart(t.endContainer, t.endOffset), i.extractContents(); } } } /** * Set's caret to the next Block or Tool`s input * Before moving caret, we should check if caret position is at the end of Plugins node * Using {@link Dom#getDeepestNode} to get a last node and match with current selection * * @param {boolean} force - pass true to skip check for caret position */ navigateNext(e = false) { const { BlockManager: t } = this.Editor, { currentBlock: o2, nextBlock: i } = t; if (o2 === void 0) return false; const { nextInput: s2, currentInput: r2 } = o2, a2 = r2 !== void 0 ? Re$2(r2) : void 0; let l2 = i; const c2 = e || a2 || !o2.focusable; if (s2 && c2) return this.setToInput(s2, this.positions.START), true; if (l2 === null) { if (o2.tool.isDefault || !c2) return false; l2 = t.insertAtEnd(); } return c2 ? (this.setToBlock(l2, this.positions.START), true) : false; } /** * Set's caret to the previous Tool`s input or Block * Before moving caret, we should check if caret position is start of the Plugins node * Using {@link Dom#getDeepestNode} to get a last node and match with current selection * * @param {boolean} force - pass true to skip check for caret position */ navigatePrevious(e = false) { const { currentBlock: t, previousBlock: o2 } = this.Editor.BlockManager; if (!t) return false; const { previousInput: i, currentInput: s2 } = t, r2 = s2 !== void 0 ? Ne$1(s2) : void 0, a2 = e || r2 || !t.focusable; return i && a2 ? (this.setToInput(i, this.positions.END), true) : o2 !== null && a2 ? (this.setToBlock(o2, this.positions.END), true) : false; } /** * Inserts shadow element after passed element where caret can be placed * * @param {Element} element - element after which shadow caret should be inserted */ createShadow(e) { const t = document.createElement("span"); t.classList.add(Ye2.CSS.shadowCaret), e.insertAdjacentElement("beforeend", t); } /** * Restores caret position * * @param {HTMLElement} element - element where caret should be restored */ restoreCaret(e) { const t = e.querySelector(`.${Ye2.CSS.shadowCaret}`); if (!t) return; new b$3().expandToTag(t); const i = document.createRange(); i.selectNode(t), i.extractContents(); } /** * Inserts passed content at caret position * * @param {string} content - content to insert */ insertContentAtCaretPosition(e) { const t = document.createDocumentFragment(), o2 = document.createElement("div"), i = b$3.get(), s2 = b$3.range; o2.innerHTML = e, Array.from(o2.childNodes).forEach((c2) => t.appendChild(c2)), t.childNodes.length === 0 && t.appendChild(new Text()); const r2 = t.lastChild; s2.deleteContents(), s2.insertNode(t); const a2 = document.createRange(), l2 = r2.nodeType === Node.TEXT_NODE ? r2 : r2.firstChild; l2 !== null && l2.textContent !== null && a2.setStart(l2, l2.textContent.length), i.removeAllRanges(), i.addRange(a2); } }; class la extends E$3 { constructor() { super(...arguments), this.onMouseUp = () => { this.listeners.off(document, "mouseover", this.onMouseOver), this.listeners.off(document, "mouseup", this.onMouseUp); }, this.onMouseOver = (e) => { const { BlockManager: t, BlockSelection: o2 } = this.Editor; if (e.relatedTarget === null && e.target === null) return; const i = t.getBlockByChildNode(e.relatedTarget) || this.lastSelectedBlock, s2 = t.getBlockByChildNode(e.target); if (!(!i || !s2) && s2 !== i) { if (i === this.firstSelectedBlock) { b$3.get().removeAllRanges(), i.selected = true, s2.selected = true, o2.clearCache(); return; } if (s2 === this.firstSelectedBlock) { i.selected = false, s2.selected = false, o2.clearCache(); return; } this.Editor.InlineToolbar.close(), this.toggleBlocksSelectedState(i, s2), this.lastSelectedBlock = s2; } }; } /** * Module preparation * * @returns {Promise} */ async prepare() { this.listeners.on(document, "mousedown", (e) => { this.enableCrossBlockSelection(e); }); } /** * Sets up listeners * * @param {MouseEvent} event - mouse down event */ watchSelection(e) { if (e.button !== qn$1.LEFT) return; const { BlockManager: t } = this.Editor; this.firstSelectedBlock = t.getBlock(e.target), this.lastSelectedBlock = this.firstSelectedBlock, this.listeners.on(document, "mouseover", this.onMouseOver), this.listeners.on(document, "mouseup", this.onMouseUp); } /** * Return boolean is cross block selection started: * there should be at least 2 selected blocks */ get isCrossBlockSelectionStarted() { return !!this.firstSelectedBlock && !!this.lastSelectedBlock && this.firstSelectedBlock !== this.lastSelectedBlock; } /** * Change selection state of the next Block * Used for CBS via Shift + arrow keys * * @param {boolean} next - if true, toggle next block. Previous otherwise */ toggleBlockSelectedState(e = true) { const { BlockManager: t, BlockSelection: o2 } = this.Editor; this.lastSelectedBlock || (this.lastSelectedBlock = this.firstSelectedBlock = t.currentBlock), this.firstSelectedBlock === this.lastSelectedBlock && (this.firstSelectedBlock.selected = true, o2.clearCache(), b$3.get().removeAllRanges()); const i = t.blocks.indexOf(this.lastSelectedBlock) + (e ? 1 : -1), s2 = t.blocks[i]; s2 && (this.lastSelectedBlock.selected !== s2.selected ? (s2.selected = true, o2.clearCache()) : (this.lastSelectedBlock.selected = false, o2.clearCache()), this.lastSelectedBlock = s2, this.Editor.InlineToolbar.close(), s2.holder.scrollIntoView({ block: "nearest" })); } /** * Clear saved state * * @param {Event} reason - event caused clear of selection */ clear(e) { const { BlockManager: t, BlockSelection: o2, Caret: i } = this.Editor, s2 = t.blocks.indexOf(this.firstSelectedBlock), r2 = t.blocks.indexOf(this.lastSelectedBlock); if (o2.anyBlockSelected && s2 > -1 && r2 > -1 && e && e instanceof KeyboardEvent) switch (e.keyCode) { case y$3.DOWN: case y$3.RIGHT: i.setToBlock(t.blocks[Math.max(s2, r2)], i.positions.END); break; case y$3.UP: case y$3.LEFT: i.setToBlock(t.blocks[Math.min(s2, r2)], i.positions.START); break; default: i.setToBlock(t.blocks[Math.max(s2, r2)], i.positions.END); } this.firstSelectedBlock = this.lastSelectedBlock = null; } /** * Enables Cross Block Selection * * @param {MouseEvent} event - mouse down event */ enableCrossBlockSelection(e) { const { UI: t } = this.Editor; b$3.isCollapsed || this.Editor.BlockSelection.clearSelection(e), t.nodes.redactor.contains(e.target) ? this.watchSelection(e) : this.Editor.BlockSelection.clearSelection(e); } /** * Change blocks selection state between passed two blocks. * * @param {Block} firstBlock - first block in range * @param {Block} lastBlock - last block in range */ toggleBlocksSelectedState(e, t) { const { BlockManager: o2, BlockSelection: i } = this.Editor, s2 = o2.blocks.indexOf(e), r2 = o2.blocks.indexOf(t), a2 = e.selected !== t.selected; for (let l2 = Math.min(s2, r2); l2 <= Math.max(s2, r2); l2++) { const c2 = o2.blocks[l2]; c2 !== this.firstSelectedBlock && c2 !== (a2 ? e : t) && (o2.blocks[l2].selected = !o2.blocks[l2].selected, i.clearCache()); } } } class ca extends E$3 { constructor() { super(...arguments), this.isStartedAtEditor = false; } /** * Toggle read-only state * * if state is true: * - disable all drag-n-drop event handlers * * if state is false: * - restore drag-n-drop event handlers * * @param {boolean} readOnlyEnabled - "read only" state */ toggleReadOnly(e) { e ? this.disableModuleBindings() : this.enableModuleBindings(); } /** * Add drag events listeners to editor zone */ enableModuleBindings() { const { UI: e } = this.Editor; this.readOnlyMutableListeners.on(e.nodes.holder, "drop", async (t) => { await this.processDrop(t); }, true), this.readOnlyMutableListeners.on(e.nodes.holder, "dragstart", () => { this.processDragStart(); }), this.readOnlyMutableListeners.on(e.nodes.holder, "dragover", (t) => { this.processDragOver(t); }, true); } /** * Unbind drag-n-drop event handlers */ disableModuleBindings() { this.readOnlyMutableListeners.clearAll(); } /** * Handle drop event * * @param {DragEvent} dropEvent - drop event */ async processDrop(e) { const { BlockManager: t, Paste: o2, Caret: i } = this.Editor; e.preventDefault(), t.blocks.forEach((r2) => { r2.dropTarget = false; }), b$3.isAtEditor && !b$3.isCollapsed && this.isStartedAtEditor && document.execCommand("delete"), this.isStartedAtEditor = false; const s2 = t.setCurrentBlockByChildNode(e.target); if (s2) this.Editor.Caret.setToBlock(s2, i.positions.END); else { const r2 = t.setCurrentBlockByChildNode(t.lastBlock.holder); this.Editor.Caret.setToBlock(r2, i.positions.END); } await o2.processDataTransfer(e.dataTransfer, true); } /** * Handle drag start event */ processDragStart() { b$3.isAtEditor && !b$3.isCollapsed && (this.isStartedAtEditor = true), this.Editor.InlineToolbar.close(); } /** * @param {DragEvent} dragEvent - drag event */ processDragOver(e) { e.preventDefault(); } } const da = 180, ua = 400; class ha extends E$3 { /** * Prepare the module * * @param options - options used by the modification observer module * @param options.config - Editor configuration object * @param options.eventsDispatcher - common Editor event bus */ constructor({ config: e, eventsDispatcher: t }) { super({ config: e, eventsDispatcher: t }), this.disabled = false, this.batchingTimeout = null, this.batchingOnChangeQueue = /* @__PURE__ */ new Map(), this.batchTime = ua, this.mutationObserver = new MutationObserver((o2) => { this.redactorChanged(o2); }), this.eventsDispatcher.on($o, (o2) => { this.particularBlockChanged(o2.event); }), this.eventsDispatcher.on(zo, () => { this.disable(); }), this.eventsDispatcher.on(Uo, () => { this.enable(); }); } /** * Enables onChange event */ enable() { this.mutationObserver.observe( this.Editor.UI.nodes.redactor, { childList: true, subtree: true, characterData: true, attributes: true } ), this.disabled = false; } /** * Disables onChange event */ disable() { this.mutationObserver.disconnect(), this.disabled = true; } /** * Call onChange event passed to Editor.js configuration * * @param event - some of our custom change events */ particularBlockChanged(e) { this.disabled || !A$4(this.config.onChange) || (this.batchingOnChangeQueue.set(`block:${e.detail.target.id}:event:${e.type}`, e), this.batchingTimeout && clearTimeout(this.batchingTimeout), this.batchingTimeout = setTimeout(() => { let t; this.batchingOnChangeQueue.size === 1 ? t = this.batchingOnChangeQueue.values().next().value : t = Array.from(this.batchingOnChangeQueue.values()), this.config.onChange && this.config.onChange(this.Editor.API.methods, t), this.batchingOnChangeQueue.clear(); }, this.batchTime)); } /** * Fired on every blocks wrapper dom change * * @param mutations - mutations happened */ redactorChanged(e) { this.eventsDispatcher.emit(ft$1, { mutations: e }); } } const Rn$1 = class Dn2 extends E$3 { constructor() { super(...arguments), this.MIME_TYPE = "application/x-editor-js", this.toolsTags = {}, this.tagsByTool = {}, this.toolsPatterns = [], this.toolsFiles = {}, this.exceptionList = [], this.processTool = (e) => { try { const t = e.create({}, {}, false); if (e.pasteConfig === false) { this.exceptionList.push(e.name); return; } if (!A$4(t.onPaste)) return; this.getTagsConfig(e), this.getFilesConfig(e), this.getPatternsConfig(e); } catch (t) { S$4( `Paste handling for «${e.name}» Tool hasn't been set up because of the error`, "warn", t ); } }, this.handlePasteEvent = async (e) => { const { BlockManager: t, Toolbar: o2 } = this.Editor, i = t.setCurrentBlockByChildNode(e.target); !i || this.isNativeBehaviour(e.target) && !e.clipboardData.types.includes("Files") || i && this.exceptionList.includes(i.name) || (e.preventDefault(), this.processDataTransfer(e.clipboardData), o2.close()); }; } /** * Set onPaste callback and collect tools` paste configurations */ async prepare() { this.processTools(); } /** * Set read-only state * * @param {boolean} readOnlyEnabled - read only flag value */ toggleReadOnly(e) { e ? this.unsetCallback() : this.setCallback(); } /** * Handle pasted or dropped data transfer object * * @param {DataTransfer} dataTransfer - pasted or dropped data transfer object * @param {boolean} isDragNDrop - true if data transfer comes from drag'n'drop events */ async processDataTransfer(e, t = false) { const { Tools: o2 } = this.Editor, i = e.types; if ((i.includes ? i.includes("Files") : i.contains("Files")) && !V$2(this.toolsFiles)) { await this.processFiles(e.files); return; } const r2 = e.getData(this.MIME_TYPE), a2 = e.getData("text/plain"); let l2 = e.getData("text/html"); if (r2) try { this.insertEditorJSData(JSON.parse(r2)); return; } catch { } t && a2.trim() && l2.trim() && (l2 = "

" + (l2.trim() ? l2 : a2) + "

"); const c2 = Object.keys(this.toolsTags).reduce((p2, g2) => (p2[g2.toLowerCase()] = this.toolsTags[g2].sanitizationConfig ?? {}, p2), {}), d2 = Object.assign({}, c2, o2.getAllInlineToolsSanitizeConfig(), { br: {} }), h2 = Z$2(l2, d2); !h2.trim() || h2.trim() === a2 || !u$1.isHTMLString(h2) ? await this.processText(a2) : await this.processText(h2, true); } /** * Process pasted text and divide them into Blocks * * @param {string} data - text to process. Can be HTML or plain. * @param {boolean} isHTML - if passed string is HTML, this parameter should be true */ async processText(e, t = false) { const { Caret: o2, BlockManager: i } = this.Editor, s2 = t ? this.processHTML(e) : this.processPlain(e); if (!s2.length) return; if (s2.length === 1) { s2[0].isBlock ? this.processSingleBlock(s2.pop()) : this.processInlinePaste(s2.pop()); return; } const a2 = i.currentBlock && i.currentBlock.tool.isDefault && i.currentBlock.isEmpty; s2.map( async (l2, c2) => this.insertBlock(l2, c2 === 0 && a2) ), i.currentBlock && o2.setToBlock(i.currentBlock, o2.positions.END); } /** * Set onPaste callback handler */ setCallback() { this.listeners.on(this.Editor.UI.nodes.holder, "paste", this.handlePasteEvent); } /** * Unset onPaste callback handler */ unsetCallback() { this.listeners.off(this.Editor.UI.nodes.holder, "paste", this.handlePasteEvent); } /** * Get and process tool`s paste configs */ processTools() { const e = this.Editor.Tools.blockTools; Array.from(e.values()).forEach(this.processTool); } /** * Get tags name list from either tag name or sanitization config. * * @param {string | object} tagOrSanitizeConfig - tag name or sanitize config object. * @returns {string[]} array of tags. */ collectTagNames(e) { return te$2(e) ? [e] : D$3(e) ? Object.keys(e) : []; } /** * Get tags to substitute by Tool * * @param tool - BlockTool object */ getTagsConfig(e) { if (e.pasteConfig === false) return; const t = e.pasteConfig.tags || [], o2 = []; t.forEach((i) => { const s2 = this.collectTagNames(i); o2.push(...s2), s2.forEach((r2) => { if (Object.prototype.hasOwnProperty.call(this.toolsTags, r2)) { S$4( `Paste handler for «${e.name}» Tool on «${r2}» tag is skipped because it is already used by «${this.toolsTags[r2].tool.name}» Tool.`, "warn" ); return; } const a2 = D$3(i) ? i[r2] : null; this.toolsTags[r2.toUpperCase()] = { tool: e, sanitizationConfig: a2 }; }); }), this.tagsByTool[e.name] = o2.map((i) => i.toUpperCase()); } /** * Get files` types and extensions to substitute by Tool * * @param tool - BlockTool object */ getFilesConfig(e) { if (e.pasteConfig === false) return; const { files: t = {} } = e.pasteConfig; let { extensions: o2, mimeTypes: i } = t; !o2 && !i || (o2 && !Array.isArray(o2) && (S$4(`«extensions» property of the onDrop config for «${e.name}» Tool should be an array`), o2 = []), i && !Array.isArray(i) && (S$4(`«mimeTypes» property of the onDrop config for «${e.name}» Tool should be an array`), i = []), i && (i = i.filter((s2) => ei(s2) ? true : (S$4(`MIME type value «${s2}» for the «${e.name}» Tool is not a valid MIME type`, "warn"), false))), this.toolsFiles[e.name] = { extensions: o2 || [], mimeTypes: i || [] }); } /** * Get RegExp patterns to substitute by Tool * * @param tool - BlockTool object */ getPatternsConfig(e) { e.pasteConfig === false || !e.pasteConfig.patterns || V$2(e.pasteConfig.patterns) || Object.entries(e.pasteConfig.patterns).forEach(([t, o2]) => { o2 instanceof RegExp || S$4( `Pattern ${o2} for «${e.name}» Tool is skipped because it should be a Regexp instance.`, "warn" ), this.toolsPatterns.push({ key: t, pattern: o2, tool: e }); }); } /** * Check if browser behavior suits better * * @param {EventTarget} element - element where content has been pasted * @returns {boolean} */ isNativeBehaviour(e) { return u$1.isNativeInput(e); } /** * Get files from data transfer object and insert related Tools * * @param {FileList} items - pasted or dropped items */ async processFiles(e) { const { BlockManager: t } = this.Editor; let o2; o2 = await Promise.all( Array.from(e).map((r2) => this.processFile(r2)) ), o2 = o2.filter((r2) => !!r2); const s2 = t.currentBlock.tool.isDefault && t.currentBlock.isEmpty; o2.forEach( (r2, a2) => { t.paste(r2.type, r2.event, a2 === 0 && s2); } ); } /** * Get information about file and find Tool to handle it * * @param {File} file - file to process */ async processFile(e) { const t = Jn$1(e), o2 = Object.entries(this.toolsFiles).find(([r2, { mimeTypes: a2, extensions: l2 }]) => { const [c2, d2] = e.type.split("/"), h2 = l2.find((g2) => g2.toLowerCase() === t.toLowerCase()), p2 = a2.find((g2) => { const [f2, v2] = g2.split("/"); return f2 === c2 && (v2 === d2 || v2 === "*"); }); return !!h2 || !!p2; }); if (!o2) return; const [i] = o2; return { event: this.composePasteEvent("file", { file: e }), type: i }; } /** * Split HTML string to blocks and return it as array of Block data * * @param {string} innerHTML - html string to process * @returns {PasteData[]} */ processHTML(e) { const { Tools: t } = this.Editor, o2 = u$1.make("DIV"); return o2.innerHTML = e, this.getNodes(o2).map((s2) => { let r2, a2 = t.defaultTool, l2 = false; switch (s2.nodeType) { case Node.DOCUMENT_FRAGMENT_NODE: r2 = u$1.make("div"), r2.appendChild(s2); break; case Node.ELEMENT_NODE: r2 = s2, l2 = true, this.toolsTags[r2.tagName] && (a2 = this.toolsTags[r2.tagName].tool); break; } const { tags: c2 } = a2.pasteConfig || { tags: [] }, d2 = c2.reduce((g2, f2) => (this.collectTagNames(f2).forEach((O2) => { const T2 = D$3(f2) ? f2[O2] : null; g2[O2.toLowerCase()] = T2 || {}; }), g2), {}), h2 = Object.assign({}, d2, a2.baseSanitizeConfig); if (r2.tagName.toLowerCase() === "table") { const g2 = Z$2(r2.outerHTML, h2); r2 = u$1.make("div", void 0, { innerHTML: g2 }).firstChild; } else r2.innerHTML = Z$2(r2.innerHTML, h2); const p2 = this.composePasteEvent("tag", { data: r2 }); return { content: r2, isBlock: l2, tool: a2.name, event: p2 }; }).filter((s2) => { const r2 = u$1.isEmpty(s2.content), a2 = u$1.isSingleTag(s2.content); return !r2 || a2; }); } /** * Split plain text by new line symbols and return it as array of Block data * * @param {string} plain - string to process * @returns {PasteData[]} */ processPlain(e) { const { defaultBlock: t } = this.config; if (!e) return []; const o2 = t; return e.split(/\r?\n/).filter((i) => i.trim()).map((i) => { const s2 = u$1.make("div"); s2.textContent = i; const r2 = this.composePasteEvent("tag", { data: s2 }); return { content: s2, tool: o2, isBlock: false, event: r2 }; }); } /** * Process paste of single Block tool content * * @param {PasteData} dataToInsert - data of Block to insert */ async processSingleBlock(e) { const { Caret: t, BlockManager: o2 } = this.Editor, { currentBlock: i } = o2; if (!i || e.tool !== i.name || !u$1.containsOnlyInlineElements(e.content.innerHTML)) { this.insertBlock(e, (i == null ? void 0 : i.tool.isDefault) && i.isEmpty); return; } t.insertContentAtCaretPosition(e.content.innerHTML); } /** * Process paste to single Block: * 1. Find patterns` matches * 2. Insert new block if it is not the same type as current one * 3. Just insert text if there is no substitutions * * @param {PasteData} dataToInsert - data of Block to insert */ async processInlinePaste(e) { const { BlockManager: t, Caret: o2 } = this.Editor, { content: i } = e; if (t.currentBlock && t.currentBlock.tool.isDefault && i.textContent.length < Dn2.PATTERN_PROCESSING_MAX_LENGTH) { const r2 = await this.processPattern(i.textContent); if (r2) { const a2 = t.currentBlock && t.currentBlock.tool.isDefault && t.currentBlock.isEmpty, l2 = t.paste(r2.tool, r2.event, a2); o2.setToBlock(l2, o2.positions.END); return; } } if (t.currentBlock && t.currentBlock.currentInput) { const r2 = t.currentBlock.tool.baseSanitizeConfig; document.execCommand( "insertHTML", false, Z$2(i.innerHTML, r2) ); } else this.insertBlock(e); } /** * Get patterns` matches * * @param {string} text - text to process * @returns {Promise<{event: PasteEvent, tool: string}>} */ async processPattern(e) { const t = this.toolsPatterns.find((i) => { const s2 = i.pattern.exec(e); return s2 ? e === s2.shift() : false; }); return t ? { event: this.composePasteEvent("pattern", { key: t.key, data: e }), tool: t.tool.name } : void 0; } /** * Insert pasted Block content to Editor * * @param {PasteData} data - data to insert * @param {boolean} canReplaceCurrentBlock - if true and is current Block is empty, will replace current Block * @returns {void} */ insertBlock(e, t = false) { const { BlockManager: o2, Caret: i } = this.Editor, { currentBlock: s2 } = o2; let r2; if (t && s2 && s2.isEmpty) { r2 = o2.paste(e.tool, e.event, true), i.setToBlock(r2, i.positions.END); return; } r2 = o2.paste(e.tool, e.event), i.setToBlock(r2, i.positions.END); } /** * Insert data passed as application/x-editor-js JSON * * @param {Array} blocks — Blocks' data to insert * @returns {void} */ insertEditorJSData(e) { const { BlockManager: t, Caret: o2, Tools: i } = this.Editor; yt$1( e, (r2) => i.blockTools.get(r2).sanitizeConfig ).forEach(({ tool: r2, data: a2 }, l2) => { let c2 = false; l2 === 0 && (c2 = t.currentBlock && t.currentBlock.tool.isDefault && t.currentBlock.isEmpty); const d2 = t.insert({ tool: r2, data: a2, replace: c2 }); o2.setToBlock(d2, o2.positions.END); }); } /** * Fetch nodes from Element node * * @param {Node} node - current node * @param {Node[]} nodes - processed nodes * @param {Node} destNode - destination node */ processElementNode(e, t, o2) { const i = Object.keys(this.toolsTags), s2 = e, { tool: r2 } = this.toolsTags[s2.tagName] || {}, a2 = this.tagsByTool[r2 == null ? void 0 : r2.name] || [], l2 = i.includes(s2.tagName), c2 = u$1.blockElements.includes(s2.tagName.toLowerCase()), d2 = Array.from(s2.children).some( ({ tagName: p2 }) => i.includes(p2) && !a2.includes(p2) ), h2 = Array.from(s2.children).some( ({ tagName: p2 }) => u$1.blockElements.includes(p2.toLowerCase()) ); if (!c2 && !l2 && !d2) return o2.appendChild(s2), [...t, o2]; if (l2 && !d2 || c2 && !h2 && !d2) return [...t, o2, s2]; } /** * Recursively divide HTML string to two types of nodes: * 1. Block element * 2. Document Fragments contained text and markup tags like a, b, i etc. * * @param {Node} wrapper - wrapper of paster HTML content * @returns {Node[]} */ getNodes(e) { const t = Array.from(e.childNodes); let o2; const i = (s2, r2) => { if (u$1.isEmpty(r2) && !u$1.isSingleTag(r2)) return s2; const a2 = s2[s2.length - 1]; let l2 = new DocumentFragment(); switch (a2 && u$1.isFragment(a2) && (l2 = s2.pop()), r2.nodeType) { case Node.ELEMENT_NODE: if (o2 = this.processElementNode(r2, s2, l2), o2) return o2; break; case Node.TEXT_NODE: return l2.appendChild(r2), [...s2, l2]; default: return [...s2, l2]; } return [...s2, ...Array.from(r2.childNodes).reduce(i, [])]; }; return t.reduce(i, []); } /** * Compose paste event with passed type and detail * * @param {string} type - event type * @param {PasteEventDetail} detail - event detail */ composePasteEvent(e, t) { return new CustomEvent(e, { detail: t }); } }; Rn$1.PATTERN_PROCESSING_MAX_LENGTH = 450; let pa = Rn$1; class fa extends E$3 { constructor() { super(...arguments), this.toolsDontSupportReadOnly = [], this.readOnlyEnabled = false; } /** * Returns state of read only mode */ get isEnabled() { return this.readOnlyEnabled; } /** * Set initial state */ async prepare() { const { Tools: e } = this.Editor, { blockTools: t } = e, o2 = []; Array.from(t.entries()).forEach(([i, s2]) => { s2.isReadOnlySupported || o2.push(i); }), this.toolsDontSupportReadOnly = o2, this.config.readOnly && o2.length > 0 && this.throwCriticalError(), this.toggle(this.config.readOnly, true); } /** * Set read-only mode or toggle current state * Call all Modules `toggleReadOnly` method and re-render Editor * * @param state - (optional) read-only state or toggle * @param isInitial - (optional) true when editor is initializing */ async toggle(e = !this.readOnlyEnabled, t = false) { e && this.toolsDontSupportReadOnly.length > 0 && this.throwCriticalError(); const o2 = this.readOnlyEnabled; this.readOnlyEnabled = e; for (const s2 in this.Editor) this.Editor[s2].toggleReadOnly && this.Editor[s2].toggleReadOnly(e); if (o2 === e) return this.readOnlyEnabled; if (t) return this.readOnlyEnabled; this.Editor.ModificationsObserver.disable(); const i = await this.Editor.Saver.save(); return await this.Editor.BlockManager.clear(), await this.Editor.Renderer.render(i.blocks), this.Editor.ModificationsObserver.enable(), this.readOnlyEnabled; } /** * Throws an error about tools which don't support read-only mode */ throwCriticalError() { throw new Ho( `To enable read-only mode all connected tools should support it. Tools ${this.toolsDontSupportReadOnly.join(", ")} don't support read-only mode.` ); } } let Be$1 = class Be2 extends E$3 { constructor() { super(...arguments), this.isRectSelectionActivated = false, this.SCROLL_SPEED = 3, this.HEIGHT_OF_SCROLL_ZONE = 40, this.BOTTOM_SCROLL_ZONE = 1, this.TOP_SCROLL_ZONE = 2, this.MAIN_MOUSE_BUTTON = 0, this.mousedown = false, this.isScrolling = false, this.inScrollZone = null, this.startX = 0, this.startY = 0, this.mouseX = 0, this.mouseY = 0, this.stackOfSelected = [], this.listenerIds = []; } /** * CSS classes for the Block * * @returns {{wrapper: string, content: string}} */ static get CSS() { return { overlay: "codex-editor-overlay", overlayContainer: "codex-editor-overlay__container", rect: "codex-editor-overlay__rectangle", topScrollZone: "codex-editor-overlay__scroll-zone--top", bottomScrollZone: "codex-editor-overlay__scroll-zone--bottom" }; } /** * Module Preparation * Creating rect and hang handlers */ prepare() { this.enableModuleBindings(); } /** * Init rect params * * @param {number} pageX - X coord of mouse * @param {number} pageY - Y coord of mouse */ startSelection(e, t) { const o2 = document.elementFromPoint(e - window.pageXOffset, t - window.pageYOffset); o2.closest(`.${this.Editor.Toolbar.CSS.toolbar}`) || (this.Editor.BlockSelection.allBlocksSelected = false, this.clearSelection(), this.stackOfSelected = []); const s2 = [ `.${R$5.CSS.content}`, `.${this.Editor.Toolbar.CSS.toolbar}`, `.${this.Editor.InlineToolbar.CSS.inlineToolbar}` ], r2 = o2.closest("." + this.Editor.UI.CSS.editorWrapper), a2 = s2.some((l2) => !!o2.closest(l2)); !r2 || a2 || (this.mousedown = true, this.startX = e, this.startY = t); } /** * Clear all params to end selection */ endSelection() { this.mousedown = false, this.startX = 0, this.startY = 0, this.overlayRectangle.style.display = "none"; } /** * is RectSelection Activated */ isRectActivated() { return this.isRectSelectionActivated; } /** * Mark that selection is end */ clearSelection() { this.isRectSelectionActivated = false; } /** * Sets Module necessary event handlers */ enableModuleBindings() { const { container: e } = this.genHTML(); this.listeners.on(e, "mousedown", (t) => { this.processMouseDown(t); }, false), this.listeners.on(document.body, "mousemove", dt$1((t) => { this.processMouseMove(t); }, 10), { passive: true }), this.listeners.on(document.body, "mouseleave", () => { this.processMouseLeave(); }), this.listeners.on(window, "scroll", dt$1((t) => { this.processScroll(t); }, 10), { passive: true }), this.listeners.on(document.body, "mouseup", () => { this.processMouseUp(); }, false); } /** * Handle mouse down events * * @param {MouseEvent} mouseEvent - mouse event payload */ processMouseDown(e) { if (e.button !== this.MAIN_MOUSE_BUTTON) return; e.target.closest(u$1.allInputsSelector) !== null || this.startSelection(e.pageX, e.pageY); } /** * Handle mouse move events * * @param {MouseEvent} mouseEvent - mouse event payload */ processMouseMove(e) { this.changingRectangle(e), this.scrollByZones(e.clientY); } /** * Handle mouse leave */ processMouseLeave() { this.clearSelection(), this.endSelection(); } /** * @param {MouseEvent} mouseEvent - mouse event payload */ processScroll(e) { this.changingRectangle(e); } /** * Handle mouse up */ processMouseUp() { this.clearSelection(), this.endSelection(); } /** * Scroll If mouse in scroll zone * * @param {number} clientY - Y coord of mouse */ scrollByZones(e) { if (this.inScrollZone = null, e <= this.HEIGHT_OF_SCROLL_ZONE && (this.inScrollZone = this.TOP_SCROLL_ZONE), document.documentElement.clientHeight - e <= this.HEIGHT_OF_SCROLL_ZONE && (this.inScrollZone = this.BOTTOM_SCROLL_ZONE), !this.inScrollZone) { this.isScrolling = false; return; } this.isScrolling || (this.scrollVertical(this.inScrollZone === this.TOP_SCROLL_ZONE ? -this.SCROLL_SPEED : this.SCROLL_SPEED), this.isScrolling = true); } /** * Generates required HTML elements * * @returns {Object} */ genHTML() { const { UI: e } = this.Editor, t = e.nodes.holder.querySelector("." + e.CSS.editorWrapper), o2 = u$1.make("div", Be2.CSS.overlay, {}), i = u$1.make("div", Be2.CSS.overlayContainer, {}), s2 = u$1.make("div", Be2.CSS.rect, {}); return i.appendChild(s2), o2.appendChild(i), t.appendChild(o2), this.overlayRectangle = s2, { container: t, overlay: o2 }; } /** * Activates scrolling if blockSelection is active and mouse is in scroll zone * * @param {number} speed - speed of scrolling */ scrollVertical(e) { if (!(this.inScrollZone && this.mousedown)) return; const t = window.pageYOffset; window.scrollBy(0, e), this.mouseY += window.pageYOffset - t, setTimeout(() => { this.scrollVertical(e); }, 0); } /** * Handles the change in the rectangle and its effect * * @param {MouseEvent} event - mouse event */ changingRectangle(e) { if (!this.mousedown) return; e.pageY !== void 0 && (this.mouseX = e.pageX, this.mouseY = e.pageY); const { rightPos: t, leftPos: o2, index: i } = this.genInfoForMouseSelection(), s2 = this.startX > t && this.mouseX > t, r2 = this.startX < o2 && this.mouseX < o2; this.rectCrossesBlocks = !(s2 || r2), this.isRectSelectionActivated || (this.rectCrossesBlocks = false, this.isRectSelectionActivated = true, this.shrinkRectangleToPoint(), this.overlayRectangle.style.display = "block"), this.updateRectangleSize(), this.Editor.Toolbar.close(), i !== void 0 && (this.trySelectNextBlock(i), this.inverseSelection(), b$3.get().removeAllRanges()); } /** * Shrink rect to singular point */ shrinkRectangleToPoint() { this.overlayRectangle.style.left = `${this.startX - window.pageXOffset}px`, this.overlayRectangle.style.top = `${this.startY - window.pageYOffset}px`, this.overlayRectangle.style.bottom = `calc(100% - ${this.startY - window.pageYOffset}px`, this.overlayRectangle.style.right = `calc(100% - ${this.startX - window.pageXOffset}px`; } /** * Select or unselect all of blocks in array if rect is out or in selectable area */ inverseSelection() { const t = this.Editor.BlockManager.getBlockByIndex(this.stackOfSelected[0]).selected; if (this.rectCrossesBlocks && !t) for (const o2 of this.stackOfSelected) this.Editor.BlockSelection.selectBlockByIndex(o2); if (!this.rectCrossesBlocks && t) for (const o2 of this.stackOfSelected) this.Editor.BlockSelection.unSelectBlockByIndex(o2); } /** * Updates size of rectangle */ updateRectangleSize() { this.mouseY >= this.startY ? (this.overlayRectangle.style.top = `${this.startY - window.pageYOffset}px`, this.overlayRectangle.style.bottom = `calc(100% - ${this.mouseY - window.pageYOffset}px`) : (this.overlayRectangle.style.bottom = `calc(100% - ${this.startY - window.pageYOffset}px`, this.overlayRectangle.style.top = `${this.mouseY - window.pageYOffset}px`), this.mouseX >= this.startX ? (this.overlayRectangle.style.left = `${this.startX - window.pageXOffset}px`, this.overlayRectangle.style.right = `calc(100% - ${this.mouseX - window.pageXOffset}px`) : (this.overlayRectangle.style.right = `calc(100% - ${this.startX - window.pageXOffset}px`, this.overlayRectangle.style.left = `${this.mouseX - window.pageXOffset}px`); } /** * Collects information needed to determine the behavior of the rectangle * * @returns {object} index - index next Block, leftPos - start of left border of Block, rightPos - right border */ genInfoForMouseSelection() { const t = document.body.offsetWidth / 2, o2 = this.mouseY - window.pageYOffset, i = document.elementFromPoint(t, o2), s2 = this.Editor.BlockManager.getBlockByChildNode(i); let r2; s2 !== void 0 && (r2 = this.Editor.BlockManager.blocks.findIndex((h2) => h2.holder === s2.holder)); const a2 = this.Editor.BlockManager.lastBlock.holder.querySelector("." + R$5.CSS.content), l2 = Number.parseInt(window.getComputedStyle(a2).width, 10) / 2, c2 = t - l2, d2 = t + l2; return { index: r2, leftPos: c2, rightPos: d2 }; } /** * Select block with index index * * @param index - index of block in redactor */ addBlockInSelection(e) { this.rectCrossesBlocks && this.Editor.BlockSelection.selectBlockByIndex(e), this.stackOfSelected.push(e); } /** * Adds a block to the selection and determines which blocks should be selected * * @param {object} index - index of new block in the reactor */ trySelectNextBlock(e) { const t = this.stackOfSelected[this.stackOfSelected.length - 1] === e, o2 = this.stackOfSelected.length, i = 1, s2 = -1, r2 = 0; if (t) return; const a2 = this.stackOfSelected[o2 - 1] - this.stackOfSelected[o2 - 2] > 0; let l2 = r2; o2 > 1 && (l2 = a2 ? i : s2); const c2 = e > this.stackOfSelected[o2 - 1] && l2 === i, d2 = e < this.stackOfSelected[o2 - 1] && l2 === s2, p2 = !(c2 || d2 || l2 === r2); if (!p2 && (e > this.stackOfSelected[o2 - 1] || this.stackOfSelected[o2 - 1] === void 0)) { let v2 = this.stackOfSelected[o2 - 1] + 1 || e; for (v2; v2 <= e; v2++) this.addBlockInSelection(v2); return; } if (!p2 && e < this.stackOfSelected[o2 - 1]) { for (let v2 = this.stackOfSelected[o2 - 1] - 1; v2 >= e; v2--) this.addBlockInSelection(v2); return; } if (!p2) return; let g2 = o2 - 1, f2; for (e > this.stackOfSelected[o2 - 1] ? f2 = () => e > this.stackOfSelected[g2] : f2 = () => e < this.stackOfSelected[g2]; f2(); ) this.rectCrossesBlocks && this.Editor.BlockSelection.unSelectBlockByIndex(this.stackOfSelected[g2]), this.stackOfSelected.pop(), g2--; } }; class ga extends E$3 { /** * Renders passed blocks as one batch * * @param blocksData - blocks to render */ async render(e) { return new Promise((t) => { const { Tools: o2, BlockManager: i } = this.Editor; if (e.length === 0) i.insert(); else { const s2 = e.map(({ type: r2, data: a2, tunes: l2, id: c2 }) => { o2.available.has(r2) === false && (X$2(`Tool «${r2}» is not found. Check 'tools' property at the Editor.js config.`, "warn"), a2 = this.composeStubDataForTool(r2, a2, c2), r2 = o2.stubTool); let d2; try { d2 = i.composeBlock({ id: c2, tool: r2, data: a2, tunes: l2 }); } catch (h2) { S$4(`Block «${r2}» skipped because of plugins error`, "error", { data: a2, error: h2 }), a2 = this.composeStubDataForTool(r2, a2, c2), r2 = o2.stubTool, d2 = i.composeBlock({ id: c2, tool: r2, data: a2, tunes: l2 }); } return d2; }); i.insertMany(s2); } window.requestIdleCallback(() => { t(); }, { timeout: 2e3 }); }); } /** * Create data for the Stub Tool that will be used instead of unavailable tool * * @param tool - unavailable tool name to stub * @param data - data of unavailable block * @param [id] - id of unavailable block */ composeStubDataForTool(e, t, o2) { const { Tools: i } = this.Editor; let s2 = e; if (i.unavailable.has(e)) { const r2 = i.unavailable.get(e).toolbox; r2 !== void 0 && r2[0].title !== void 0 && (s2 = r2[0].title); } return { savedData: { id: o2, type: e, data: t }, title: s2 }; } } class ma extends E$3 { /** * Composes new chain of Promises to fire them alternatelly * * @returns {OutputData} */ async save() { const { BlockManager: e, Tools: t } = this.Editor, o2 = e.blocks, i = []; try { o2.forEach((a2) => { i.push(this.getSavedData(a2)); }); const s2 = await Promise.all(i), r2 = await yt$1(s2, (a2) => t.blockTools.get(a2).sanitizeConfig); return this.makeOutput(r2); } catch (s2) { X$2("Saving failed due to the Error %o", "error", s2); } } /** * Saves and validates * * @param {Block} block - Editor's Tool * @returns {ValidatedData} - Tool's validated data */ async getSavedData(e) { const t = await e.save(), o2 = t && await e.validate(t.data); return { ...t, isValid: o2 }; } /** * Creates output object with saved data, time and version of editor * * @param {ValidatedData} allExtractedData - data extracted from Blocks * @returns {OutputData} */ makeOutput(e) { const t = []; return e.forEach(({ id: o2, tool: i, data: s2, tunes: r2, isValid: a2 }) => { if (!a2) { S$4(`Block «${i}» skipped because saved data is invalid`); return; } if (i === this.Editor.Tools.stubTool) { t.push(s2); return; } const l2 = { id: o2, type: i, data: s2, ...!V$2(r2) && { tunes: r2 } }; t.push(l2); }), { time: +/* @__PURE__ */ new Date(), blocks: t, version: "2.31.0" }; } } (function() { try { if (typeof document < "u") { var n2 = document.createElement("style"); n2.appendChild(document.createTextNode(".ce-paragraph{line-height:1.6em;outline:none}.ce-block:only-of-type .ce-paragraph[data-placeholder-active]:empty:before,.ce-block:only-of-type .ce-paragraph[data-placeholder-active][data-empty=true]:before{content:attr(data-placeholder-active)}.ce-paragraph p:first-of-type{margin-top:0}.ce-paragraph p:last-of-type{margin-bottom:0}")), document.head.appendChild(n2); } } catch (e) { console.error("vite-plugin-css-injected-by-js", e); } })(); const ba = ''; function va(n2) { const e = document.createElement("div"); e.innerHTML = n2.trim(); const t = document.createDocumentFragment(); return t.append(...Array.from(e.childNodes)), t; } /** * Base Paragraph Block for the Editor.js. * Represents a regular text block * * @author CodeX (team@codex.so) * @copyright CodeX 2018 * @license The MIT License (MIT) */ class fo { /** * Default placeholder for Paragraph Tool * * @returns {string} * @class */ static get DEFAULT_PLACEHOLDER() { return ""; } /** * Render plugin`s main Element and fill it with saved data * * @param {object} params - constructor params * @param {ParagraphData} params.data - previously saved data * @param {ParagraphConfig} params.config - user config for Tool * @param {object} params.api - editor.js api * @param {boolean} readOnly - read only mode flag */ constructor({ data: e, config: t, api: o2, readOnly: i }) { this.api = o2, this.readOnly = i, this._CSS = { block: this.api.styles.block, wrapper: "ce-paragraph" }, this.readOnly || (this.onKeyUp = this.onKeyUp.bind(this)), this._placeholder = t.placeholder ? t.placeholder : fo.DEFAULT_PLACEHOLDER, this._data = e ?? {}, this._element = null, this._preserveBlank = t.preserveBlank ?? false; } /** * Check if text content is empty and set empty string to inner html. * We need this because some browsers (e.g. Safari) insert
into empty contenteditanle elements * * @param {KeyboardEvent} e - key up event */ onKeyUp(e) { if (e.code !== "Backspace" && e.code !== "Delete" || !this._element) return; const { textContent: t } = this._element; t === "" && (this._element.innerHTML = ""); } /** * Create Tool's view * * @returns {HTMLDivElement} * @private */ drawView() { const e = document.createElement("DIV"); return e.classList.add(this._CSS.wrapper, this._CSS.block), e.contentEditable = "false", e.dataset.placeholderActive = this.api.i18n.t(this._placeholder), this._data.text && (e.innerHTML = this._data.text), this.readOnly || (e.contentEditable = "true", e.addEventListener("keyup", this.onKeyUp)), e; } /** * Return Tool's view * * @returns {HTMLDivElement} */ render() { return this._element = this.drawView(), this._element; } /** * Method that specified how to merge two Text blocks. * Called by Editor.js by backspace at the beginning of the Block * * @param {ParagraphData} data * @public */ merge(e) { if (!this._element) return; this._data.text += e.text; const t = va(e.text); this._element.appendChild(t), this._element.normalize(); } /** * Validate Paragraph block data: * - check for emptiness * * @param {ParagraphData} savedData — data received after saving * @returns {boolean} false if saved data is not correct, otherwise true * @public */ validate(e) { return !(e.text.trim() === "" && !this._preserveBlank); } /** * Extract Tool's data from the view * * @param {HTMLDivElement} toolsContent - Paragraph tools rendered view * @returns {ParagraphData} - saved data * @public */ save(e) { return { text: e.innerHTML }; } /** * On paste callback fired from Editor. * * @param {HTMLPasteEvent} event - event with pasted data */ onPaste(e) { const t = { text: e.detail.data.innerHTML }; this._data = t, window.requestAnimationFrame(() => { this._element && (this._element.innerHTML = this._data.text || ""); }); } /** * Enable Conversion Toolbar. Paragraph can be converted to/from other tools * @returns {ConversionConfig} */ static get conversionConfig() { return { export: "text", // to convert Paragraph to other block, use 'text' property of saved data import: "text" // to covert other block's exported string to Paragraph, fill 'text' property of tool data }; } /** * Sanitizer rules * @returns {SanitizerConfig} - Edtior.js sanitizer config */ static get sanitize() { return { text: { br: true } }; } /** * Returns true to notify the core that read-only mode is supported * * @returns {boolean} */ static get isReadOnlySupported() { return true; } /** * Used by Editor paste handling API. * Provides configuration to handle P tags. * * @returns {PasteConfig} - Paragraph Paste Setting */ static get pasteConfig() { return { tags: ["P"] }; } /** * Icon and title for displaying at the Toolbox * * @returns {ToolboxConfig} - Paragraph Toolbox Setting */ static get toolbox() { return { icon: ba, title: "Text" }; } } class go { constructor() { this.commandName = "bold"; } /** * Sanitizer Rule * Leave tags * * @returns {object} */ static get sanitize() { return { b: {} }; } /** * Create button for Inline Toolbar */ render() { return { icon: Ki, name: "bold", onActivate: () => { document.execCommand(this.commandName); }, isActive: () => document.queryCommandState(this.commandName) }; } /** * Set a shortcut * * @returns {boolean} */ get shortcut() { return "CMD+B"; } } go.isInline = true; go.title = "Bold"; class mo { constructor() { this.commandName = "italic", this.CSS = { button: "ce-inline-tool", buttonActive: "ce-inline-tool--active", buttonModifier: "ce-inline-tool--italic" }, this.nodes = { button: null }; } /** * Sanitizer Rule * Leave tags * * @returns {object} */ static get sanitize() { return { i: {} }; } /** * Create button for Inline Toolbar */ render() { return this.nodes.button = document.createElement("button"), this.nodes.button.type = "button", this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier), this.nodes.button.innerHTML = Ji, this.nodes.button; } /** * Wrap range with tag */ surround() { document.execCommand(this.commandName); } /** * Check selection and set activated state to button if there are tag */ checkState() { const e = document.queryCommandState(this.commandName); return this.nodes.button.classList.toggle(this.CSS.buttonActive, e), e; } /** * Set a shortcut */ get shortcut() { return "CMD+I"; } } mo.isInline = true; mo.title = "Italic"; class bo { /** * @param api - Editor.js API */ constructor({ api: e }) { this.commandLink = "createLink", this.commandUnlink = "unlink", this.ENTER_KEY = 13, this.CSS = { button: "ce-inline-tool", buttonActive: "ce-inline-tool--active", buttonModifier: "ce-inline-tool--link", buttonUnlink: "ce-inline-tool--unlink", input: "ce-inline-tool-input", inputShowed: "ce-inline-tool-input--showed" }, this.nodes = { button: null, input: null }, this.inputOpened = false, this.toolbar = e.toolbar, this.inlineToolbar = e.inlineToolbar, this.notifier = e.notifier, this.i18n = e.i18n, this.selection = new b$3(); } /** * Sanitizer Rule * Leave tags * * @returns {object} */ static get sanitize() { return { a: { href: true, target: "_blank", rel: "nofollow" } }; } /** * Create button for Inline Toolbar */ render() { return this.nodes.button = document.createElement("button"), this.nodes.button.type = "button", this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier), this.nodes.button.innerHTML = Co, this.nodes.button; } /** * Input for the link */ renderActions() { return this.nodes.input = document.createElement("input"), this.nodes.input.placeholder = this.i18n.t("Add a link"), this.nodes.input.enterKeyHint = "done", this.nodes.input.classList.add(this.CSS.input), this.nodes.input.addEventListener("keydown", (e) => { e.keyCode === this.ENTER_KEY && this.enterPressed(e); }), this.nodes.input; } /** * Handle clicks on the Inline Toolbar icon * * @param {Range} range - range to wrap with link */ surround(e) { if (e) { this.inputOpened ? (this.selection.restore(), this.selection.removeFakeBackground()) : (this.selection.setFakeBackground(), this.selection.save()); const t = this.selection.findParentTag("A"); if (t) { this.selection.expandToTag(t), this.unlink(), this.closeActions(), this.checkState(), this.toolbar.close(); return; } } this.toggleActions(); } /** * Check selection and set activated state to button if there are tag */ checkState() { const e = this.selection.findParentTag("A"); if (e) { this.nodes.button.innerHTML = ns, this.nodes.button.classList.add(this.CSS.buttonUnlink), this.nodes.button.classList.add(this.CSS.buttonActive), this.openActions(); const t = e.getAttribute("href"); this.nodes.input.value = t !== "null" ? t : "", this.selection.save(); } else this.nodes.button.innerHTML = Co, this.nodes.button.classList.remove(this.CSS.buttonUnlink), this.nodes.button.classList.remove(this.CSS.buttonActive); return !!e; } /** * Function called with Inline Toolbar closing */ clear() { this.closeActions(); } /** * Set a shortcut */ get shortcut() { return "CMD+K"; } /** * Show/close link input */ toggleActions() { this.inputOpened ? this.closeActions(false) : this.openActions(true); } /** * @param {boolean} needFocus - on link creation we need to focus input. On editing - nope. */ openActions(e = false) { this.nodes.input.classList.add(this.CSS.inputShowed), e && this.nodes.input.focus(), this.inputOpened = true; } /** * Close input * * @param {boolean} clearSavedSelection — we don't need to clear saved selection * on toggle-clicks on the icon of opened Toolbar */ closeActions(e = true) { if (this.selection.isFakeBackgroundEnabled) { const t = new b$3(); t.save(), this.selection.restore(), this.selection.removeFakeBackground(), t.restore(); } this.nodes.input.classList.remove(this.CSS.inputShowed), this.nodes.input.value = "", e && this.selection.clearSaved(), this.inputOpened = false; } /** * Enter pressed on input * * @param {KeyboardEvent} event - enter keydown event */ enterPressed(e) { let t = this.nodes.input.value || ""; if (!t.trim()) { this.selection.restore(), this.unlink(), e.preventDefault(), this.closeActions(); return; } if (!this.validateURL(t)) { this.notifier.show({ message: "Pasted link is not valid.", style: "error" }), S$4("Incorrect Link pasted", "warn", t); return; } t = this.prepareLink(t), this.selection.restore(), this.selection.removeFakeBackground(), this.insertLink(t), e.preventDefault(), e.stopPropagation(), e.stopImmediatePropagation(), this.selection.collapseToEnd(), this.inlineToolbar.close(); } /** * Detects if passed string is URL * * @param {string} str - string to validate * @returns {boolean} */ validateURL(e) { return !/\s/.test(e); } /** * Process link before injection * - sanitize * - add protocol for links like 'google.com' * * @param {string} link - raw user input */ prepareLink(e) { return e = e.trim(), e = this.addProtocol(e), e; } /** * Add 'http' protocol to the links like 'vc.ru', 'google.com' * * @param {string} link - string to process */ addProtocol(e) { if (/^(\w+):(\/\/)?/.test(e)) return e; const t = /^\/[^/\s]/.test(e), o2 = e.substring(0, 1) === "#", i = /^\/\/[^/\s]/.test(e); return !t && !o2 && !i && (e = "http://" + e), e; } /** * Inserts tag with "href" * * @param {string} link - "href" value */ insertLink(e) { const t = this.selection.findParentTag("A"); t && this.selection.expandToTag(t), document.execCommand(this.commandLink, false, e); } /** * Removes tag */ unlink() { document.execCommand(this.commandUnlink); } } bo.isInline = true; bo.title = "Link"; let Fn$1 = class Fn { /** * @param api - Editor.js API */ constructor({ api: e }) { this.i18nAPI = e.i18n, this.blocksAPI = e.blocks, this.selectionAPI = e.selection, this.toolsAPI = e.tools, this.caretAPI = e.caret; } /** * Returns tool's UI config */ async render() { const e = b$3.get(), t = this.blocksAPI.getBlockByElement(e.anchorNode); if (t === void 0) return []; const o2 = this.toolsAPI.getBlockTools(), i = await Yo(t, o2); if (i.length === 0) return []; const s2 = i.reduce((c2, d2) => { var h2; return (h2 = d2.toolbox) == null || h2.forEach((p2) => { c2.push({ icon: p2.icon, title: z$2.t(K$2.toolNames, p2.title), name: d2.name, closeOnActivate: true, onActivate: async () => { const g2 = await this.blocksAPI.convert(t.id, d2.name, p2.data); this.caretAPI.setToBlock(g2, "end"); } }); }), c2; }, []), r2 = await t.getActiveToolboxEntry(), a2 = r2 !== void 0 ? r2.icon : Go, l2 = !be$2(); return { icon: a2, name: "convert-to", hint: { title: this.i18nAPI.t("Convert to") }, children: { searchable: l2, items: s2, onOpen: () => { l2 && (this.selectionAPI.setFakeBackground(), this.selectionAPI.save()); }, onClose: () => { l2 && (this.selectionAPI.restore(), this.selectionAPI.removeFakeBackground()); } } }; } }; Fn$1.isInline = true; let jn$1 = class jn { /** * @param options - constructor options * @param options.data - stub tool data * @param options.api - Editor.js API */ constructor({ data: e, api: t }) { this.CSS = { wrapper: "ce-stub", info: "ce-stub__info", title: "ce-stub__title", subtitle: "ce-stub__subtitle" }, this.api = t, this.title = e.title || this.api.i18n.t("Error"), this.subtitle = this.api.i18n.t("The block can not be displayed correctly."), this.savedData = e.savedData, this.wrapper = this.make(); } /** * Returns stub holder * * @returns {HTMLElement} */ render() { return this.wrapper; } /** * Return original Tool data * * @returns {BlockToolData} */ save() { return this.savedData; } /** * Create Tool html markup * * @returns {HTMLElement} */ make() { const e = u$1.make("div", this.CSS.wrapper), t = is, o2 = u$1.make("div", this.CSS.info), i = u$1.make("div", this.CSS.title, { textContent: this.title }), s2 = u$1.make("div", this.CSS.subtitle, { textContent: this.subtitle }); return e.innerHTML = t, o2.appendChild(i), o2.appendChild(s2), e.appendChild(o2), e; } }; jn$1.isReadOnlySupported = true; class ka extends Tt$2 { constructor() { super(...arguments), this.type = ae$2.Inline; } /** * Returns title for Inline Tool if specified by user */ get title() { return this.constructable[We$2.Title]; } /** * Constructs new InlineTool instance from constructable */ create() { return new this.constructable({ api: this.api, config: this.settings }); } /** * Allows inline tool to be available in read-only mode * Can be used, for example, by comments tool */ get isReadOnlySupported() { return this.constructable[We$2.IsReadOnlySupported] ?? false; } } class ya extends Tt$2 { constructor() { super(...arguments), this.type = ae$2.Tune; } /** * Constructs new BlockTune instance from constructable * * @param data - Tune data * @param block - Block API object */ create(e, t) { return new this.constructable({ api: this.api, config: this.settings, block: t, data: e }); } } let j$4 = class j2 extends Map { /** * Returns Block Tools collection */ get blockTools() { const e = Array.from(this.entries()).filter(([, t]) => t.isBlock()); return new j2(e); } /** * Returns Inline Tools collection */ get inlineTools() { const e = Array.from(this.entries()).filter(([, t]) => t.isInline()); return new j2(e); } /** * Returns Block Tunes collection */ get blockTunes() { const e = Array.from(this.entries()).filter(([, t]) => t.isTune()); return new j2(e); } /** * Returns internal Tools collection */ get internalTools() { const e = Array.from(this.entries()).filter(([, t]) => t.isInternal); return new j2(e); } /** * Returns Tools collection provided by user */ get externalTools() { const e = Array.from(this.entries()).filter(([, t]) => !t.isInternal); return new j2(e); } }; var wa = Object.defineProperty, Ea = Object.getOwnPropertyDescriptor, Hn$1 = (n2, e, t, o2) => { for (var i = o2 > 1 ? void 0 : o2 ? Ea(e, t) : e, s2 = n2.length - 1, r2; s2 >= 0; s2--) (r2 = n2[s2]) && (i = (o2 ? r2(e, t, i) : r2(i)) || i); return o2 && i && wa(e, t, i), i; }; class vo extends Tt$2 { constructor() { super(...arguments), this.type = ae$2.Block, this.inlineTools = new j$4(), this.tunes = new j$4(); } /** * Creates new Tool instance * * @param data - Tool data * @param block - BlockAPI for current Block * @param readOnly - True if Editor is in read-only mode */ create(e, t, o2) { return new this.constructable({ data: e, block: t, readOnly: o2, api: this.api, config: this.settings }); } /** * Returns true if read-only mode is supported by Tool */ get isReadOnlySupported() { return this.constructable[pe$2.IsReadOnlySupported] === true; } /** * Returns true if Tool supports linebreaks */ get isLineBreaksEnabled() { return this.constructable[pe$2.IsEnabledLineBreaks]; } /** * Returns Tool toolbox configuration (internal or user-specified). * * Merges internal and user-defined toolbox configs based on the following rules: * * - If both internal and user-defined toolbox configs are arrays their items are merged. * Length of the second one is kept. * * - If both are objects their properties are merged. * * - If one is an object and another is an array than internal config is replaced with user-defined * config. This is made to allow user to override default tool's toolbox representation (single/multiple entries) */ get toolbox() { const e = this.constructable[pe$2.Toolbox], t = this.config[Pe$1.Toolbox]; if (!V$2(e) && t !== false) return t ? Array.isArray(e) ? Array.isArray(t) ? t.map((o2, i) => { const s2 = e[i]; return s2 ? { ...s2, ...o2 } : o2; }) : [t] : Array.isArray(t) ? t : [ { ...e, ...t } ] : Array.isArray(e) ? e : [e]; } /** * Returns Tool conversion configuration */ get conversionConfig() { return this.constructable[pe$2.ConversionConfig]; } /** * Returns enabled inline tools for Tool */ get enabledInlineTools() { return this.config[Pe$1.EnabledInlineTools] || false; } /** * Returns enabled tunes for Tool */ get enabledBlockTunes() { return this.config[Pe$1.EnabledBlockTunes]; } /** * Returns Tool paste configuration */ get pasteConfig() { return this.constructable[pe$2.PasteConfig] ?? {}; } get sanitizeConfig() { const e = super.sanitizeConfig, t = this.baseSanitizeConfig; if (V$2(e)) return t; const o2 = {}; for (const i in e) if (Object.prototype.hasOwnProperty.call(e, i)) { const s2 = e[i]; D$3(s2) ? o2[i] = Object.assign({}, t, s2) : o2[i] = s2; } return o2; } get baseSanitizeConfig() { const e = {}; return Array.from(this.inlineTools.values()).forEach((t) => Object.assign(e, t.sanitizeConfig)), Array.from(this.tunes.values()).forEach((t) => Object.assign(e, t.sanitizeConfig)), e; } } Hn$1([ me$2 ], vo.prototype, "sanitizeConfig", 1); Hn$1([ me$2 ], vo.prototype, "baseSanitizeConfig", 1); class xa { /** * @class * @param config - tools config * @param editorConfig - EditorJS config * @param api - EditorJS API module */ constructor(e, t, o2) { this.api = o2, this.config = e, this.editorConfig = t; } /** * Returns Tool object based on it's type * * @param name - tool name */ get(e) { const { class: t, isInternal: o2 = false, ...i } = this.config[e], s2 = this.getConstructor(t), r2 = t[mt$1.IsTune]; return new s2({ name: e, constructable: t, config: i, api: this.api.getMethodsForTool(e, r2), isDefault: e === this.editorConfig.defaultBlock, defaultPlaceholder: this.editorConfig.placeholder, isInternal: o2 }); } /** * Find appropriate Tool object constructor for Tool constructable * * @param constructable - Tools constructable */ getConstructor(e) { switch (true) { case e[We$2.IsInline]: return ka; case e[mt$1.IsTune]: return ya; default: return vo; } } } let $n$1 = class $n { /** * MoveDownTune constructor * * @param {API} api — Editor's API */ constructor({ api: e }) { this.CSS = { animation: "wobble" }, this.api = e; } /** * Tune's appearance in block settings menu */ render() { return { icon: Xi, title: this.api.i18n.t("Move down"), onActivate: () => this.handleClick(), name: "move-down" }; } /** * Handle clicks on 'move down' button */ handleClick() { const e = this.api.blocks.getCurrentBlockIndex(), t = this.api.blocks.getBlockByIndex(e + 1); if (!t) throw new Error("Unable to move Block down since it is already the last"); const o2 = t.holder, i = o2.getBoundingClientRect(); let s2 = Math.abs(window.innerHeight - o2.offsetHeight); i.top < window.innerHeight && (s2 = window.scrollY + o2.offsetHeight), window.scrollTo(0, s2), this.api.blocks.move(e + 1), this.api.toolbar.toggleBlockSettings(true); } }; $n$1.isTune = true; let zn$1 = class zn { /** * DeleteTune constructor * * @param {API} api - Editor's API */ constructor({ api: e }) { this.api = e; } /** * Tune's appearance in block settings menu */ render() { return { icon: Gi, title: this.api.i18n.t("Delete"), name: "delete", confirmation: { title: this.api.i18n.t("Click to delete"), onActivate: () => this.handleClick() } }; } /** * Delete block conditions passed */ handleClick() { this.api.blocks.delete(); } }; zn$1.isTune = true; let Un$1 = class Un { /** * MoveUpTune constructor * * @param {API} api - Editor's API */ constructor({ api: e }) { this.CSS = { animation: "wobble" }, this.api = e; } /** * Tune's appearance in block settings menu */ render() { return { icon: Zi, title: this.api.i18n.t("Move up"), onActivate: () => this.handleClick(), name: "move-up" }; } /** * Move current block up */ handleClick() { const e = this.api.blocks.getCurrentBlockIndex(), t = this.api.blocks.getBlockByIndex(e), o2 = this.api.blocks.getBlockByIndex(e - 1); if (e === 0 || !t || !o2) throw new Error("Unable to move Block up since it is already the first"); const i = t.holder, s2 = o2.holder, r2 = i.getBoundingClientRect(), a2 = s2.getBoundingClientRect(); let l2; a2.top > 0 ? l2 = Math.abs(r2.top) - Math.abs(a2.top) : l2 = Math.abs(r2.top) + a2.height, window.scrollBy(0, -1 * l2), this.api.blocks.move(e - 1), this.api.toolbar.toggleBlockSettings(true); } }; Un$1.isTune = true; var Ba = Object.defineProperty, Ca = Object.getOwnPropertyDescriptor, Ta = (n2, e, t, o2) => { for (var i = o2 > 1 ? void 0 : o2 ? Ca(e, t) : e, s2 = n2.length - 1, r2; s2 >= 0; s2--) (r2 = n2[s2]) && (i = (o2 ? r2(e, t, i) : r2(i)) || i); return o2 && i && Ba(e, t, i), i; }; let Wn$1 = class Wn extends E$3 { constructor() { super(...arguments), this.stubTool = "stub", this.toolsAvailable = new j$4(), this.toolsUnavailable = new j$4(); } /** * Returns available Tools */ get available() { return this.toolsAvailable; } /** * Returns unavailable Tools */ get unavailable() { return this.toolsUnavailable; } /** * Return Tools for the Inline Toolbar */ get inlineTools() { return this.available.inlineTools; } /** * Return editor block tools */ get blockTools() { return this.available.blockTools; } /** * Return available Block Tunes * * @returns {object} - object of Inline Tool's classes */ get blockTunes() { return this.available.blockTunes; } /** * Returns default Tool object */ get defaultTool() { return this.blockTools.get(this.config.defaultBlock); } /** * Returns internal tools */ get internal() { return this.available.internalTools; } /** * Creates instances via passed or default configuration * * @returns {Promise} */ async prepare() { if (this.validateTools(), this.config.tools = ut$1({}, this.internalTools, this.config.tools), !Object.prototype.hasOwnProperty.call(this.config, "tools") || Object.keys(this.config.tools).length === 0) throw Error("Can't start without tools"); const e = this.prepareConfig(); this.factory = new xa(e, this.config, this.Editor.API); const t = this.getListOfPrepareFunctions(e); if (t.length === 0) return Promise.resolve(); await Qn$1(t, (o2) => { this.toolPrepareMethodSuccess(o2); }, (o2) => { this.toolPrepareMethodFallback(o2); }), this.prepareBlockTools(); } getAllInlineToolsSanitizeConfig() { const e = {}; return Array.from(this.inlineTools.values()).forEach((t) => { Object.assign(e, t.sanitizeConfig); }), e; } /** * Calls each Tool reset method to clean up anything set by Tool */ destroy() { Object.values(this.available).forEach(async (e) => { A$4(e.reset) && await e.reset(); }); } /** * Returns internal tools * Includes Bold, Italic, Link and Paragraph */ get internalTools() { return { convertTo: { class: Fn$1, isInternal: true }, link: { class: bo, isInternal: true }, bold: { class: go, isInternal: true }, italic: { class: mo, isInternal: true }, paragraph: { class: fo, inlineToolbar: true, isInternal: true }, stub: { class: jn$1, isInternal: true }, moveUp: { class: Un$1, isInternal: true }, delete: { class: zn$1, isInternal: true }, moveDown: { class: $n$1, isInternal: true } }; } /** * Tool prepare method success callback * * @param {object} data - append tool to available list */ toolPrepareMethodSuccess(e) { const t = this.factory.get(e.toolName); if (t.isInline()) { const i = ["render"].filter((s2) => !t.create()[s2]); if (i.length) { S$4( `Incorrect Inline Tool: ${t.name}. Some of required methods is not implemented %o`, "warn", i ), this.toolsUnavailable.set(t.name, t); return; } } this.toolsAvailable.set(t.name, t); } /** * Tool prepare method fail callback * * @param {object} data - append tool to unavailable list */ toolPrepareMethodFallback(e) { this.toolsUnavailable.set(e.toolName, this.factory.get(e.toolName)); } /** * Binds prepare function of plugins with user or default config * * @returns {Array} list of functions that needs to be fired sequentially * @param config - tools config */ getListOfPrepareFunctions(e) { const t = []; return Object.entries(e).forEach(([o2, i]) => { t.push({ // eslint-disable-next-line @typescript-eslint/no-empty-function function: A$4(i.class.prepare) ? i.class.prepare : () => { }, data: { toolName: o2, config: i.config } }); }), t; } /** * Assign enabled Inline Tools and Block Tunes for Block Tool */ prepareBlockTools() { Array.from(this.blockTools.values()).forEach((e) => { this.assignInlineToolsToBlockTool(e), this.assignBlockTunesToBlockTool(e); }); } /** * Assign enabled Inline Tools for Block Tool * * @param tool - Block Tool */ assignInlineToolsToBlockTool(e) { if (this.config.inlineToolbar !== false) { if (e.enabledInlineTools === true) { e.inlineTools = new j$4( Array.isArray(this.config.inlineToolbar) ? this.config.inlineToolbar.map((t) => [t, this.inlineTools.get(t)]) : Array.from(this.inlineTools.entries()) ); return; } Array.isArray(e.enabledInlineTools) && (e.inlineTools = new j$4( /** Prepend ConvertTo Inline Tool */ ["convertTo", ...e.enabledInlineTools].map((t) => [t, this.inlineTools.get(t)]) )); } } /** * Assign enabled Block Tunes for Block Tool * * @param tool — Block Tool */ assignBlockTunesToBlockTool(e) { if (e.enabledBlockTunes !== false) { if (Array.isArray(e.enabledBlockTunes)) { const t = new j$4( e.enabledBlockTunes.map((o2) => [o2, this.blockTunes.get(o2)]) ); e.tunes = new j$4([...t, ...this.blockTunes.internalTools]); return; } if (Array.isArray(this.config.tunes)) { const t = new j$4( this.config.tunes.map((o2) => [o2, this.blockTunes.get(o2)]) ); e.tunes = new j$4([...t, ...this.blockTunes.internalTools]); return; } e.tunes = this.blockTunes.internalTools; } } /** * Validate Tools configuration objects and throw Error for user if it is invalid */ validateTools() { for (const e in this.config.tools) if (Object.prototype.hasOwnProperty.call(this.config.tools, e)) { if (e in this.internalTools) return; const t = this.config.tools[e]; if (!A$4(t) && !A$4(t.class)) throw Error( `Tool «${e}» must be a constructor function or an object with function in the «class» property` ); } } /** * Unify tools config */ prepareConfig() { const e = {}; for (const t in this.config.tools) D$3(this.config.tools[t]) ? e[t] = this.config.tools[t] : e[t] = { class: this.config.tools[t] }; return e; } }; Ta([ me$2 ], Wn$1.prototype, "getAllInlineToolsSanitizeConfig", 1); const Sa = `:root{--selectionColor: #e1f2ff;--inlineSelectionColor: #d4ecff;--bg-light: #eff2f5;--grayText: #707684;--color-dark: #1D202B;--color-active-icon: #388AE5;--color-gray-border: rgba(201, 201, 204, .48);--content-width: 650px;--narrow-mode-right-padding: 50px;--toolbox-buttons-size: 26px;--toolbox-buttons-size--mobile: 36px;--icon-size: 20px;--icon-size--mobile: 28px;--block-padding-vertical: .4em;--color-line-gray: #EFF0F1 }.codex-editor{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;z-index:1}.codex-editor .hide{display:none}.codex-editor__redactor [contenteditable]:empty:after{content:"\\feff"}@media (min-width: 651px){.codex-editor--narrow .codex-editor__redactor{margin-right:50px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .codex-editor__redactor{margin-left:50px;margin-right:0}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__actions{right:-5px}}.codex-editor-copyable{position:absolute;height:1px;width:1px;top:-400%;opacity:.001}.codex-editor-overlay{position:fixed;top:0;left:0;right:0;bottom:0;z-index:999;pointer-events:none;overflow:hidden}.codex-editor-overlay__container{position:relative;pointer-events:auto;z-index:0}.codex-editor-overlay__rectangle{position:absolute;pointer-events:none;background-color:#2eaadc33;border:1px solid transparent}.codex-editor svg{max-height:100%}.codex-editor path{stroke:currentColor}.codex-editor ::-moz-selection{background-color:#d4ecff}.codex-editor ::selection{background-color:#d4ecff}.codex-editor--toolbox-opened [contentEditable=true][data-placeholder]:focus:before{opacity:0!important}.ce-scroll-locked{overflow:hidden}.ce-scroll-locked--hard{overflow:hidden;top:calc(-1 * var(--window-scroll-offset));position:fixed;width:100%}.ce-toolbar{position:absolute;left:0;right:0;top:0;-webkit-transition:opacity .1s ease;transition:opacity .1s ease;will-change:opacity,top;display:none}.ce-toolbar--opened{display:block}.ce-toolbar__content{max-width:650px;margin:0 auto;position:relative}.ce-toolbar__plus{color:#1d202b;cursor:pointer;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-flex-negative:0;flex-shrink:0}@media (max-width: 650px){.ce-toolbar__plus{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__plus:hover{background-color:#eff2f5}}.ce-toolbar__plus--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.ce-toolbar__plus-shortcut{opacity:.6;word-spacing:-2px;margin-top:5px}@media (max-width: 650px){.ce-toolbar__plus{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__plus--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__plus--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__actions{position:absolute;right:100%;opacity:0;display:-webkit-box;display:-ms-flexbox;display:flex;padding-right:5px}.ce-toolbar__actions--opened{opacity:1}@media (max-width: 650px){.ce-toolbar__actions{right:auto}}.ce-toolbar__settings-btn{color:#1d202b;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;margin-left:3px;cursor:pointer;user-select:none}@media (max-width: 650px){.ce-toolbar__settings-btn{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__settings-btn:hover{background-color:#eff2f5}}.ce-toolbar__settings-btn--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@media (min-width: 651px){.ce-toolbar__settings-btn{width:24px}}.ce-toolbar__settings-btn--hidden{display:none}@media (max-width: 650px){.ce-toolbar__settings-btn{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__settings-btn--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__settings-btn--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__plus svg,.ce-toolbar__settings-btn svg{width:24px;height:24px}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__plus{left:5px}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbox .ce-popover{right:0;left:auto;left:initial}}.ce-inline-toolbar{--y-offset: 8px;--color-background-icon-active: rgba(56, 138, 229, .1);--color-text-icon-active: #388AE5;--color-text-primary: black;position:absolute;visibility:hidden;-webkit-transition:opacity .25s ease;transition:opacity .25s ease;will-change:opacity,left,top;top:0;left:0;z-index:3;opacity:1;visibility:visible}.ce-inline-toolbar [hidden]{display:none!important}.ce-inline-toolbar__toggler-and-button-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;padding:0 6px}.ce-inline-toolbar__buttons{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown{display:-webkit-box;display:-ms-flexbox;display:flex;padding:6px;margin:0 6px 0 -6px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;border-right:1px solid rgba(201,201,204,.48);-webkit-box-sizing:border-box;box-sizing:border-box}@media (hover: hover){.ce-inline-toolbar__dropdown:hover{background:#eff2f5}}.ce-inline-toolbar__dropdown--hidden{display:none}.ce-inline-toolbar__dropdown-content,.ce-inline-toolbar__dropdown-arrow{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown-content svg,.ce-inline-toolbar__dropdown-arrow svg{width:20px;height:20px}.ce-inline-toolbar__shortcut{opacity:.6;word-spacing:-3px;margin-top:3px}.ce-inline-tool{color:var(--color-text-primary);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;border-radius:4px;line-height:normal;height:100%;padding:0;width:28px;background-color:transparent;cursor:pointer}@media (max-width: 650px){.ce-inline-tool{width:36px;height:36px}}@media (hover: hover){.ce-inline-tool:hover{background-color:#f8f8f8}}.ce-inline-tool svg{display:block;width:20px;height:20px}@media (max-width: 650px){.ce-inline-tool svg{width:28px;height:28px}}.ce-inline-tool--link .icon--unlink,.ce-inline-tool--unlink .icon--link{display:none}.ce-inline-tool--unlink .icon--unlink{display:inline-block;margin-bottom:-1px}.ce-inline-tool-input{background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:4px 8px;font-size:14px;line-height:22px;outline:none;margin:0;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;display:none;font-weight:500;-webkit-appearance:none;font-family:inherit}@media (max-width: 650px){.ce-inline-tool-input{font-size:15px;font-weight:500}}.ce-inline-tool-input::-webkit-input-placeholder{color:#707684}.ce-inline-tool-input::-moz-placeholder{color:#707684}.ce-inline-tool-input:-ms-input-placeholder{color:#707684}.ce-inline-tool-input::-ms-input-placeholder{color:#707684}.ce-inline-tool-input::placeholder{color:#707684}.ce-inline-tool-input--showed{display:block}.ce-inline-tool--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}@-webkit-keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.ce-block{-webkit-animation:fade-in .3s ease;animation:fade-in .3s ease;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-animation-fill-mode:initial;animation-fill-mode:initial}.ce-block:first-of-type{margin-top:0}.ce-block--selected .ce-block__content{background:#e1f2ff}.ce-block--selected .ce-block__content [contenteditable]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ce-block--selected .ce-block__content img,.ce-block--selected .ce-block__content .ce-stub{opacity:.55}.ce-block--stretched .ce-block__content{max-width:none}.ce-block__content{position:relative;max-width:650px;margin:0 auto;-webkit-transition:background-color .15s ease;transition:background-color .15s ease}.ce-block--drop-target .ce-block__content:before{content:"";position:absolute;top:100%;left:-20px;margin-top:-1px;height:8px;width:8px;border:solid #388AE5;border-width:1px 1px 0 0;-webkit-transform-origin:right;transform-origin:right;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.ce-block--drop-target .ce-block__content:after{content:"";position:absolute;top:100%;height:1px;width:100%;color:#388ae5;background:repeating-linear-gradient(90deg,#388AE5,#388AE5 1px,#fff 1px,#fff 6px)}.ce-block a{cursor:pointer;-webkit-text-decoration:underline;text-decoration:underline}.ce-block b{font-weight:700}.ce-block i{font-style:italic}@-webkit-keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}.cdx-block{padding:.4em 0}.cdx-block::-webkit-input-placeholder{line-height:normal!important}.cdx-input{border:1px solid rgba(201,201,204,.48);-webkit-box-shadow:inset 0 1px 2px 0 rgba(35,44,72,.06);box-shadow:inset 0 1px 2px #232c480f;border-radius:3px;padding:10px 12px;outline:none;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.cdx-input[data-placeholder]:before{position:static!important}.cdx-input[data-placeholder]:before{display:inline-block;width:0;white-space:nowrap;pointer-events:none}.cdx-settings-button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:3px;cursor:pointer;border:0;outline:none;background-color:transparent;vertical-align:bottom;color:inherit;margin:0;min-width:26px;min-height:26px}.cdx-settings-button--focused{background:rgba(34,186,255,.08)!important}.cdx-settings-button--focused{-webkit-box-shadow:inset 0 0 0px 1px rgba(7,161,227,.08);box-shadow:inset 0 0 0 1px #07a1e314}.cdx-settings-button--focused-animated{-webkit-animation-name:buttonClicked;animation-name:buttonClicked;-webkit-animation-duration:.25s;animation-duration:.25s}.cdx-settings-button--active{color:#388ae5}.cdx-settings-button svg{width:auto;height:auto}@media (max-width: 650px){.cdx-settings-button svg{width:28px;height:28px}}@media (max-width: 650px){.cdx-settings-button{width:36px;height:36px;border-radius:8px}}@media (hover: hover){.cdx-settings-button:hover{background-color:#eff2f5}}.cdx-loader{position:relative;border:1px solid rgba(201,201,204,.48)}.cdx-loader:before{content:"";position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-11px 0 0 -11px;border:2px solid rgba(201,201,204,.48);border-left-color:#388ae5;border-radius:50%;-webkit-animation:cdxRotation 1.2s infinite linear;animation:cdxRotation 1.2s infinite linear}@-webkit-keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.cdx-button{padding:13px;border-radius:3px;border:1px solid rgba(201,201,204,.48);font-size:14.9px;background:#fff;-webkit-box-shadow:0 2px 2px 0 rgba(18,30,57,.04);box-shadow:0 2px 2px #121e390a;color:#707684;text-align:center;cursor:pointer}@media (hover: hover){.cdx-button:hover{background:#FBFCFE;-webkit-box-shadow:0 1px 3px 0 rgba(18,30,57,.08);box-shadow:0 1px 3px #121e3914}}.cdx-button svg{height:20px;margin-right:.2em;margin-top:-2px}.ce-stub{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:12px 18px;margin:10px 0;border-radius:10px;background:#eff2f5;border:1px solid #EFF0F1;color:#707684;font-size:14px}.ce-stub svg{width:20px;height:20px}.ce-stub__info{margin-left:14px}.ce-stub__title{font-weight:500;text-transform:capitalize}.codex-editor.codex-editor--rtl{direction:rtl}.codex-editor.codex-editor--rtl .cdx-list{padding-left:0;padding-right:40px}.codex-editor.codex-editor--rtl .ce-toolbar__plus{right:-26px;left:auto}.codex-editor.codex-editor--rtl .ce-toolbar__actions{right:auto;left:-26px}@media (max-width: 650px){.codex-editor.codex-editor--rtl .ce-toolbar__actions{margin-left:0;margin-right:auto;padding-right:0;padding-left:10px}}.codex-editor.codex-editor--rtl .ce-settings{left:5px;right:auto}.codex-editor.codex-editor--rtl .ce-settings:before{right:auto;left:25px}.codex-editor.codex-editor--rtl .ce-settings__button:not(:nth-child(3n+3)){margin-left:3px;margin-right:0}.codex-editor.codex-editor--rtl .ce-conversion-tool__icon{margin-right:0;margin-left:10px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown{border-right:0px solid transparent;border-left:1px solid rgba(201,201,204,.48);margin:0 -6px 0 6px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown .icon--toggler-down{margin-left:0;margin-right:4px}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__plus{left:0;right:5px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__actions{left:-5px}}.cdx-search-field{--icon-margin-right: 10px;background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:2px;display:grid;grid-template-columns:auto auto 1fr;grid-template-rows:auto}.cdx-search-field__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-right:var(--icon-margin-right)}.cdx-search-field__icon svg{width:20px;height:20px;color:#707684}.cdx-search-field__input{font-size:14px;outline:none;font-weight:500;font-family:inherit;border:0;background:transparent;margin:0;padding:0;line-height:22px;min-width:calc(100% - 26px - var(--icon-margin-right))}.cdx-search-field__input::-webkit-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-moz-placeholder{color:#707684;font-weight:500}.cdx-search-field__input:-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::placeholder{color:#707684;font-weight:500}.ce-popover{--border-radius: 6px;--width: 200px;--max-height: 270px;--padding: 6px;--offset-from-target: 8px;--color-border: #EFF0F1;--color-shadow: rgba(13, 20, 33, .1);--color-background: white;--color-text-primary: black;--color-text-secondary: #707684;--color-border-icon: rgba(201, 201, 204, .48);--color-border-icon-disabled: #EFF0F1;--color-text-icon-active: #388AE5;--color-background-icon-active: rgba(56, 138, 229, .1);--color-background-item-focus: rgba(34, 186, 255, .08);--color-shadow-item-focus: rgba(7, 161, 227, .08);--color-background-item-hover: #F8F8F8;--color-background-item-confirm: #E24A4A;--color-background-item-confirm-hover: #CE4343;--popover-top: calc(100% + var(--offset-from-target));--popover-left: 0;--nested-popover-overlap: 4px;--icon-size: 20px;--item-padding: 3px;--item-height: calc(var(--icon-size) + 2 * var(--item-padding))}.ce-popover__container{min-width:var(--width);width:var(--width);max-height:var(--max-height);border-radius:var(--border-radius);overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:0px 3px 15px -3px var(--color-shadow);box-shadow:0 3px 15px -3px var(--color-shadow);position:absolute;left:var(--popover-left);top:var(--popover-top);background:var(--color-background);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;z-index:4;opacity:0;max-height:0;pointer-events:none;padding:0;border:none}.ce-popover--opened>.ce-popover__container{opacity:1;padding:var(--padding);max-height:var(--max-height);pointer-events:auto;-webkit-animation:panelShowing .1s ease;animation:panelShowing .1s ease;border:1px solid var(--color-border)}@media (max-width: 650px){.ce-popover--opened>.ce-popover__container{-webkit-animation:panelShowingMobile .25s ease;animation:panelShowingMobile .25s ease}}.ce-popover--open-top .ce-popover__container{--popover-top: calc(-1 * (var(--offset-from-target) + var(--popover-height)))}.ce-popover--open-left .ce-popover__container{--popover-left: calc(-1 * var(--width) + 100%)}.ce-popover__items{overflow-y:auto;-ms-scroll-chaining:none;overscroll-behavior:contain}@media (max-width: 650px){.ce-popover__overlay{position:fixed;top:0;bottom:0;left:0;right:0;background:#1D202B;z-index:3;opacity:.5;-webkit-transition:opacity .12s ease-in;transition:opacity .12s ease-in;will-change:opacity;visibility:visible}}.ce-popover__overlay--hidden{display:none}@media (max-width: 650px){.ce-popover .ce-popover__container{--offset: 5px;position:fixed;max-width:none;min-width:calc(100% - var(--offset) * 2);left:var(--offset);right:var(--offset);bottom:calc(var(--offset) + env(safe-area-inset-bottom));top:auto;border-radius:10px}}.ce-popover__search{margin-bottom:5px}.ce-popover__nothing-found-message{color:#707684;display:none;cursor:default;padding:3px;font-size:14px;line-height:20px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ce-popover__nothing-found-message--displayed{display:block}.ce-popover--nested .ce-popover__container{--popover-left: calc(var(--nesting-level) * (var(--width) - var(--nested-popover-overlap)));top:calc(var(--trigger-item-top) - var(--nested-popover-overlap));position:absolute}.ce-popover--open-top.ce-popover--nested .ce-popover__container{top:calc(var(--trigger-item-top) - var(--popover-height) + var(--item-height) + var(--offset-from-target) + var(--nested-popover-overlap))}.ce-popover--open-left .ce-popover--nested .ce-popover__container{--popover-left: calc(-1 * (var(--nesting-level) + 1) * var(--width) + 100%)}.ce-popover-item-separator{padding:4px 3px}.ce-popover-item-separator--hidden{display:none}.ce-popover-item-separator__line{height:1px;background:var(--color-border);width:100%}.ce-popover-item-html--hidden{display:none}.ce-popover-item{--border-radius: 6px;border-radius:var(--border-radius);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:var(--item-padding);color:var(--color-text-primary);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:none;background:transparent}@media (max-width: 650px){.ce-popover-item{padding:4px}}.ce-popover-item:not(:last-of-type){margin-bottom:1px}.ce-popover-item__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover-item__icon{width:36px;height:36px;border-radius:8px}.ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover-item__icon--tool{margin-right:4px}.ce-popover-item__title{font-size:14px;line-height:20px;font-weight:500;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-right:auto}@media (max-width: 650px){.ce-popover-item__title{font-size:16px}}.ce-popover-item__secondary-title{color:var(--color-text-secondary);font-size:12px;white-space:nowrap;letter-spacing:-.1em;padding-right:5px;opacity:.6}@media (max-width: 650px){.ce-popover-item__secondary-title{display:none}}.ce-popover-item--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}.ce-popover-item--disabled{color:var(--color-text-secondary);cursor:default;pointer-events:none}.ce-popover-item--focused:not(.ce-popover-item--no-focus){background:var(--color-background-item-focus)!important}.ce-popover-item--hidden{display:none}@media (hover: hover){.ce-popover-item:hover{cursor:pointer}.ce-popover-item:hover:not(.ce-popover-item--no-hover){background-color:var(--color-background-item-hover)}}.ce-popover-item--confirmation{background:var(--color-background-item-confirm)}.ce-popover-item--confirmation .ce-popover-item__title,.ce-popover-item--confirmation .ce-popover-item__icon{color:#fff}@media (hover: hover){.ce-popover-item--confirmation:not(.ce-popover-item--no-hover):hover{background:var(--color-background-item-confirm-hover)}}.ce-popover-item--confirmation:not(.ce-popover-item--no-focus).ce-popover-item--focused{background:var(--color-background-item-confirm-hover)!important}@-webkit-keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}.wobble{-webkit-animation-name:wobble;animation-name:wobble;-webkit-animation-duration:.4s;animation-duration:.4s}@-webkit-keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}@keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}.ce-popover-header{margin-bottom:8px;margin-top:4px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover-header__text{font-size:18px;font-weight:600}.ce-popover-header__back-button{border:0;background:transparent;width:36px;height:36px;color:var(--color-text-primary)}.ce-popover-header__back-button svg{display:block;width:28px;height:28px}.ce-popover--inline{--height: 38px;--height-mobile: 46px;--container-padding: 4px;position:relative}.ce-popover--inline .ce-popover__custom-content{margin-bottom:0}.ce-popover--inline .ce-popover__items{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-popover--inline .ce-popover__container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;padding:var(--container-padding);height:var(--height);top:0;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;width:-webkit-max-content;width:-moz-max-content;width:max-content;-webkit-animation:none;animation:none}@media (max-width: 650px){.ce-popover--inline .ce-popover__container{height:var(--height-mobile);position:absolute}}.ce-popover--inline .ce-popover-item-separator{padding:0 4px}.ce-popover--inline .ce-popover-item-separator__line{height:100%;width:1px}.ce-popover--inline .ce-popover-item{border-radius:4px;padding:4px}.ce-popover--inline .ce-popover-item__icon--tool{-webkit-box-shadow:none;box-shadow:none;background:transparent;margin-right:0}.ce-popover--inline .ce-popover-item__icon{width:auto;width:initial;height:auto;height:initial}.ce-popover--inline .ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover--inline .ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover--inline .ce-popover-item:not(:last-of-type){margin-bottom:0;margin-bottom:initial}.ce-popover--inline .ce-popover-item-html{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover--inline .ce-popover-item__icon--chevron-right{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{--offset: 3px;left:0;top:calc(var(--height) + var(--offset))}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{top:calc(var(--height-mobile) + var(--offset))}}.ce-popover--inline .ce-popover--nested .ce-popover__container{min-width:var(--width);width:var(--width);height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;padding:6px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.ce-popover--inline .ce-popover--nested .ce-popover__items{display:block;width:100%}.ce-popover--inline .ce-popover--nested .ce-popover-item{border-radius:6px;padding:3px}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested .ce-popover-item{padding:4px}}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon--tool{margin-right:4px}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon{width:26px;height:26px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator{padding:4px 3px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator__line{width:100%;height:1px}.codex-editor [data-placeholder]:empty:before,.codex-editor [data-placeholder][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text;content:attr(data-placeholder)}.codex-editor [data-placeholder-active]:empty:before,.codex-editor [data-placeholder-active][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text}.codex-editor [data-placeholder-active]:empty:focus:before,.codex-editor [data-placeholder-active][data-empty=true]:focus:before{content:attr(data-placeholder-active)} `; class Ia extends E$3 { constructor() { super(...arguments), this.isMobile = false, this.contentRectCache = null, this.resizeDebouncer = Eo(() => { this.windowResize(); }, 200), this.selectionChangeDebounced = Eo(() => { this.selectionChanged(); }, da), this.documentTouchedListener = (e) => { this.documentTouched(e); }; } /** * Editor.js UI CSS class names * * @returns {{editorWrapper: string, editorZone: string}} */ get CSS() { return { editorWrapper: "codex-editor", editorWrapperNarrow: "codex-editor--narrow", editorZone: "codex-editor__redactor", editorZoneHidden: "codex-editor__redactor--hidden", editorEmpty: "codex-editor--empty", editorRtlFix: "codex-editor--rtl" }; } /** * Return Width of center column of Editor * * @returns {DOMRect} */ get contentRect() { if (this.contentRectCache !== null) return this.contentRectCache; const e = this.nodes.wrapper.querySelector(`.${R$5.CSS.content}`); return e ? (this.contentRectCache = e.getBoundingClientRect(), this.contentRectCache) : { width: 650, left: 0, right: 0 }; } /** * Making main interface */ async prepare() { this.setIsMobile(), this.make(), this.loadStyles(); } /** * Toggle read-only state * * If readOnly is true: * - removes all listeners from main UI module elements * * if readOnly is false: * - enables all listeners to UI module elements * * @param {boolean} readOnlyEnabled - "read only" state */ toggleReadOnly(e) { e ? this.unbindReadOnlySensitiveListeners() : window.requestIdleCallback(() => { this.bindReadOnlySensitiveListeners(); }, { timeout: 2e3 }); } /** * Check if Editor is empty and set CSS class to wrapper */ checkEmptiness() { const { BlockManager: e } = this.Editor; this.nodes.wrapper.classList.toggle(this.CSS.editorEmpty, e.isEditorEmpty); } /** * Check if one of Toolbar is opened * Used to prevent global keydowns (for example, Enter) conflicts with Enter-on-toolbar * * @returns {boolean} */ get someToolbarOpened() { const { Toolbar: e, BlockSettings: t, InlineToolbar: o2 } = this.Editor; return !!(t.opened || o2.opened || e.toolbox.opened); } /** * Check for some Flipper-buttons is under focus */ get someFlipperButtonFocused() { return this.Editor.Toolbar.toolbox.hasFocus() ? true : Object.entries(this.Editor).filter(([e, t]) => t.flipper instanceof ce$2).some(([e, t]) => t.flipper.hasFocus()); } /** * Clean editor`s UI */ destroy() { this.nodes.holder.innerHTML = "", this.unbindReadOnlyInsensitiveListeners(); } /** * Close all Editor's toolbars */ closeAllToolbars() { const { Toolbar: e, BlockSettings: t, InlineToolbar: o2 } = this.Editor; t.close(), o2.close(), e.toolbox.close(); } /** * Check for mobile mode and save the result */ setIsMobile() { const e = window.innerWidth < Ro; e !== this.isMobile && this.eventsDispatcher.emit(Te$1, { isEnabled: this.isMobile }), this.isMobile = e; } /** * Makes Editor.js interface */ make() { this.nodes.holder = u$1.getHolder(this.config.holder), this.nodes.wrapper = u$1.make("div", [ this.CSS.editorWrapper, ...this.isRtl ? [this.CSS.editorRtlFix] : [] ]), this.nodes.redactor = u$1.make("div", this.CSS.editorZone), this.nodes.holder.offsetWidth < this.contentRect.width && this.nodes.wrapper.classList.add(this.CSS.editorWrapperNarrow), this.nodes.redactor.style.paddingBottom = this.config.minHeight + "px", this.nodes.wrapper.appendChild(this.nodes.redactor), this.nodes.holder.appendChild(this.nodes.wrapper), this.bindReadOnlyInsensitiveListeners(); } /** * Appends CSS */ loadStyles() { const e = "editor-js-styles"; if (u$1.get(e)) return; const t = u$1.make("style", null, { id: e, textContent: Sa.toString() }); this.config.style && !V$2(this.config.style) && this.config.style.nonce && t.setAttribute("nonce", this.config.style.nonce), u$1.prepend(document.head, t); } /** * Adds listeners that should work both in read-only and read-write modes */ bindReadOnlyInsensitiveListeners() { this.listeners.on(document, "selectionchange", this.selectionChangeDebounced), this.listeners.on(window, "resize", this.resizeDebouncer, { passive: true }), this.listeners.on(this.nodes.redactor, "mousedown", this.documentTouchedListener, { capture: true, passive: true }), this.listeners.on(this.nodes.redactor, "touchstart", this.documentTouchedListener, { capture: true, passive: true }); } /** * Removes listeners that should work both in read-only and read-write modes */ unbindReadOnlyInsensitiveListeners() { this.listeners.off(document, "selectionchange", this.selectionChangeDebounced), this.listeners.off(window, "resize", this.resizeDebouncer), this.listeners.off(this.nodes.redactor, "mousedown", this.documentTouchedListener), this.listeners.off(this.nodes.redactor, "touchstart", this.documentTouchedListener); } /** * Adds listeners that should work only in read-only mode */ bindReadOnlySensitiveListeners() { this.readOnlyMutableListeners.on(this.nodes.redactor, "click", (e) => { this.redactorClicked(e); }, false), this.readOnlyMutableListeners.on(document, "keydown", (e) => { this.documentKeydown(e); }, true), this.readOnlyMutableListeners.on(document, "mousedown", (e) => { this.documentClicked(e); }, true), this.watchBlockHoveredEvents(), this.enableInputsEmptyMark(); } /** * Listen redactor mousemove to emit 'block-hovered' event */ watchBlockHoveredEvents() { let e; this.readOnlyMutableListeners.on(this.nodes.redactor, "mousemove", dt$1((t) => { const o2 = t.target.closest(".ce-block"); this.Editor.BlockSelection.anyBlockSelected || o2 && e !== o2 && (e = o2, this.eventsDispatcher.emit(ln$1, { block: this.Editor.BlockManager.getBlockByChildNode(o2) })); }, 20), { passive: true }); } /** * Unbind events that should work only in read-only mode */ unbindReadOnlySensitiveListeners() { this.readOnlyMutableListeners.clearAll(); } /** * Resize window handler */ windowResize() { this.contentRectCache = null, this.setIsMobile(); } /** * All keydowns on document * * @param {KeyboardEvent} event - keyboard event */ documentKeydown(e) { switch (e.keyCode) { case y$3.ENTER: this.enterPressed(e); break; case y$3.BACKSPACE: case y$3.DELETE: this.backspacePressed(e); break; case y$3.ESC: this.escapePressed(e); break; default: this.defaultBehaviour(e); break; } } /** * Ignore all other document's keydown events * * @param {KeyboardEvent} event - keyboard event */ defaultBehaviour(e) { const { currentBlock: t } = this.Editor.BlockManager, o2 = e.target.closest(`.${this.CSS.editorWrapper}`), i = e.altKey || e.ctrlKey || e.metaKey || e.shiftKey; if (t !== void 0 && o2 === null) { this.Editor.BlockEvents.keydown(e); return; } o2 || t && i || (this.Editor.BlockManager.unsetCurrentBlock(), this.Editor.Toolbar.close()); } /** * @param {KeyboardEvent} event - keyboard event */ backspacePressed(e) { const { BlockManager: t, BlockSelection: o2, Caret: i } = this.Editor; if (o2.anyBlockSelected && !b$3.isSelectionExists) { const s2 = t.removeSelectedBlocks(), r2 = t.insertDefaultBlockAtIndex(s2, true); i.setToBlock(r2, i.positions.START), o2.clearSelection(e), e.preventDefault(), e.stopPropagation(), e.stopImmediatePropagation(); } } /** * Escape pressed * If some of Toolbar components are opened, then close it otherwise close Toolbar * * @param {Event} event - escape keydown event */ escapePressed(e) { this.Editor.BlockSelection.clearSelection(e), this.Editor.Toolbar.toolbox.opened ? (this.Editor.Toolbar.toolbox.close(), this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock, this.Editor.Caret.positions.END)) : this.Editor.BlockSettings.opened ? this.Editor.BlockSettings.close() : this.Editor.InlineToolbar.opened ? this.Editor.InlineToolbar.close() : this.Editor.Toolbar.close(); } /** * Enter pressed on document * * @param {KeyboardEvent} event - keyboard event */ enterPressed(e) { const { BlockManager: t, BlockSelection: o2 } = this.Editor; if (this.someToolbarOpened) return; const i = t.currentBlockIndex >= 0; if (o2.anyBlockSelected && !b$3.isSelectionExists) { o2.clearSelection(e), e.preventDefault(), e.stopImmediatePropagation(), e.stopPropagation(); return; } if (!this.someToolbarOpened && i && e.target.tagName === "BODY") { const s2 = this.Editor.BlockManager.insert(); e.preventDefault(), this.Editor.Caret.setToBlock(s2), this.Editor.Toolbar.moveAndOpen(s2); } this.Editor.BlockSelection.clearSelection(e); } /** * All clicks on document * * @param {MouseEvent} event - Click event */ documentClicked(e) { var a2, l2; if (!e.isTrusted) return; const t = e.target; this.nodes.holder.contains(t) || b$3.isAtEditor || (this.Editor.BlockManager.unsetCurrentBlock(), this.Editor.Toolbar.close()); const i = (a2 = this.Editor.BlockSettings.nodes.wrapper) == null ? void 0 : a2.contains(t), s2 = (l2 = this.Editor.Toolbar.nodes.settingsToggler) == null ? void 0 : l2.contains(t), r2 = i || s2; if (this.Editor.BlockSettings.opened && !r2) { this.Editor.BlockSettings.close(); const c2 = this.Editor.BlockManager.getBlockByChildNode(t); this.Editor.Toolbar.moveAndOpen(c2); } this.Editor.BlockSelection.clearSelection(e); } /** * First touch on editor * Fired before click * * Used to change current block — we need to do it before 'selectionChange' event. * Also: * - Move and show the Toolbar * - Set a Caret * * @param event - touch or mouse event */ documentTouched(e) { let t = e.target; if (t === this.nodes.redactor) { const o2 = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX, i = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY; t = document.elementFromPoint(o2, i); } try { this.Editor.BlockManager.setCurrentBlockByChildNode(t); } catch { this.Editor.RectangleSelection.isRectActivated() || this.Editor.Caret.setToTheLastBlock(); } this.Editor.ReadOnly.isEnabled || this.Editor.Toolbar.moveAndOpen(); } /** * All clicks on the redactor zone * * @param {MouseEvent} event - click event * @description * - By clicks on the Editor's bottom zone: * - if last Block is empty, set a Caret to this * - otherwise, add a new empty Block and set a Caret to that */ redactorClicked(e) { if (!b$3.isCollapsed) return; const t = e.target, o2 = e.metaKey || e.ctrlKey; if (u$1.isAnchor(t) && o2) { e.stopImmediatePropagation(), e.stopPropagation(); const i = t.getAttribute("href"), s2 = oi(i); ii(s2); return; } this.processBottomZoneClick(e); } /** * Check if user clicks on the Editor's bottom zone: * - set caret to the last block * - or add new empty block * * @param event - click event */ processBottomZoneClick(e) { const t = this.Editor.BlockManager.getBlockByIndex(-1), o2 = u$1.offset(t.holder).bottom, i = e.pageY, { BlockSelection: s2 } = this.Editor; if (e.target instanceof Element && e.target.isEqualNode(this.nodes.redactor) && /** * If there is cross block selection started, target will be equal to redactor so we need additional check */ !s2.anyBlockSelected && /** * Prevent caret jumping (to last block) when clicking between blocks */ o2 < i) { e.stopImmediatePropagation(), e.stopPropagation(); const { BlockManager: a2, Caret: l2, Toolbar: c2 } = this.Editor; (!a2.lastBlock.tool.isDefault || !a2.lastBlock.isEmpty) && a2.insertAtEnd(), l2.setToTheLastBlock(), c2.moveAndOpen(a2.lastBlock); } } /** * Handle selection changes on mobile devices * Uses for showing the Inline Toolbar */ selectionChanged() { const { CrossBlockSelection: e, BlockSelection: t } = this.Editor, o2 = b$3.anchorElement; if (e.isCrossBlockSelectionStarted && t.anyBlockSelected && b$3.get().removeAllRanges(), !o2) { b$3.range || this.Editor.InlineToolbar.close(); return; } const i = o2.closest(`.${R$5.CSS.content}`); (i === null || i.closest(`.${b$3.CSS.editorWrapper}`) !== this.nodes.wrapper) && (this.Editor.InlineToolbar.containsNode(o2) || this.Editor.InlineToolbar.close(), !(o2.dataset.inlineToolbar === "true")) || (this.Editor.BlockManager.currentBlock || this.Editor.BlockManager.setCurrentBlockByChildNode(o2), this.Editor.InlineToolbar.tryToShow(true)); } /** * Editor.js provides and ability to show placeholders for empty contenteditable elements * * This method watches for input and focus events and toggles 'data-empty' attribute * to workaroud the case, when inputs contains only
s and has no visible content * Then, CSS could rely on this attribute to show placeholders */ enableInputsEmptyMark() { function e(t) { const o2 = t.target; Do(o2); } this.readOnlyMutableListeners.on(this.nodes.wrapper, "input", e), this.readOnlyMutableListeners.on(this.nodes.wrapper, "focusin", e), this.readOnlyMutableListeners.on(this.nodes.wrapper, "focusout", e); } } const Oa = { // API Modules BlocksAPI: gi, CaretAPI: bi, EventsAPI: vi, I18nAPI: kt$2, API: ki, InlineToolbarAPI: yi, ListenersAPI: wi, NotifierAPI: Ci, ReadOnlyAPI: Ti, SanitizerAPI: Li, SaverAPI: Pi, SelectionAPI: Ni, ToolsAPI: Ri, StylesAPI: Di, ToolbarAPI: Fi, TooltipAPI: Ui, UiAPI: Wi, // Toolbar Modules BlockSettings: ms, Toolbar: Bs, InlineToolbar: Cs, // Modules BlockEvents: na, BlockManager: ra, BlockSelection: aa, Caret: Ye$2, CrossBlockSelection: la, DragNDrop: ca, ModificationsObserver: ha, Paste: pa, ReadOnly: fa, RectangleSelection: Be$1, Renderer: ga, Saver: ma, Tools: Wn$1, UI: Ia }; class _a { /** * @param {EditorConfig} config - user configuration */ constructor(e) { this.moduleInstances = {}, this.eventsDispatcher = new Oe$1(); let t, o2; this.isReady = new Promise((i, s2) => { t = i, o2 = s2; }), Promise.resolve().then(async () => { this.configuration = e, this.validate(), this.init(), await this.start(), await this.render(); const { BlockManager: i, Caret: s2, UI: r2, ModificationsObserver: a2 } = this.moduleInstances; r2.checkEmptiness(), a2.enable(), this.configuration.autofocus === true && this.configuration.readOnly !== true && s2.setToBlock(i.blocks[0], s2.positions.START), t(); }).catch((i) => { S$4(`Editor.js is not ready because of ${i}`, "error"), o2(i); }); } /** * Setting for configuration * * @param {EditorConfig|string} config - Editor's config to set */ set configuration(e) { var o2, i; D$3(e) ? this.config = { ...e } : this.config = { holder: e }, ht$1(!!this.config.holderId, "config.holderId", "config.holder"), this.config.holderId && !this.config.holder && (this.config.holder = this.config.holderId, this.config.holderId = null), this.config.holder == null && (this.config.holder = "editorjs"), this.config.logLevel || (this.config.logLevel = Lo.VERBOSE), Zn$1(this.config.logLevel), ht$1(!!this.config.initialBlock, "config.initialBlock", "config.defaultBlock"), this.config.defaultBlock = this.config.defaultBlock || this.config.initialBlock || "paragraph", this.config.minHeight = this.config.minHeight !== void 0 ? this.config.minHeight : 300; const t = { type: this.config.defaultBlock, data: {} }; this.config.placeholder = this.config.placeholder || false, this.config.sanitizer = this.config.sanitizer || { p: true, b: true, a: true }, this.config.hideToolbar = this.config.hideToolbar ? this.config.hideToolbar : false, this.config.tools = this.config.tools || {}, this.config.i18n = this.config.i18n || {}, this.config.data = this.config.data || { blocks: [] }, this.config.onReady = this.config.onReady || (() => { }), this.config.onChange = this.config.onChange || (() => { }), this.config.inlineToolbar = this.config.inlineToolbar !== void 0 ? this.config.inlineToolbar : true, (V$2(this.config.data) || !this.config.data.blocks || this.config.data.blocks.length === 0) && (this.config.data = { blocks: [t] }), this.config.readOnly = this.config.readOnly || false, (o2 = this.config.i18n) != null && o2.messages && z$2.setDictionary(this.config.i18n.messages), this.config.i18n.direction = ((i = this.config.i18n) == null ? void 0 : i.direction) || "ltr"; } /** * Returns private property * * @returns {EditorConfig} */ get configuration() { return this.config; } /** * Checks for required fields in Editor's config */ validate() { const { holderId: e, holder: t } = this.config; if (e && t) throw Error("«holderId» and «holder» param can't assign at the same time."); if (te$2(t) && !u$1.get(t)) throw Error(`element with ID «${t}» is missing. Pass correct holder's ID.`); if (t && D$3(t) && !u$1.isElement(t)) throw Error("«holder» value must be an Element node"); } /** * Initializes modules: * - make and save instances * - configure */ init() { this.constructModules(), this.configureModules(); } /** * Start Editor! * * Get list of modules that needs to be prepared and return a sequence (Promise) * * @returns {Promise} */ async start() { await [ "Tools", "UI", "BlockManager", "Paste", "BlockSelection", "RectangleSelection", "CrossBlockSelection", "ReadOnly" ].reduce( (t, o2) => t.then(async () => { try { await this.moduleInstances[o2].prepare(); } catch (i) { if (i instanceof Ho) throw new Error(i.message); S$4(`Module ${o2} was skipped because of %o`, "warn", i); } }), Promise.resolve() ); } /** * Render initial data */ render() { return this.moduleInstances.Renderer.render(this.config.data.blocks); } /** * Make modules instances and save it to the @property this.moduleInstances */ constructModules() { Object.entries(Oa).forEach(([e, t]) => { try { this.moduleInstances[e] = new t({ config: this.configuration, eventsDispatcher: this.eventsDispatcher }); } catch (o2) { S$4("[constructModules]", `Module ${e} skipped because`, "error", o2); } }); } /** * Modules instances configuration: * - pass other modules to the 'state' property * - ... */ configureModules() { for (const e in this.moduleInstances) Object.prototype.hasOwnProperty.call(this.moduleInstances, e) && (this.moduleInstances[e].state = this.getModulesDiff(e)); } /** * Return modules without passed name * * @param {string} name - module for witch modules difference should be calculated */ getModulesDiff(e) { const t = {}; for (const o2 in this.moduleInstances) o2 !== e && (t[o2] = this.moduleInstances[o2]); return t; } } /** * Editor.js * * @license Apache-2.0 * @see Editor.js * @author CodeX Team */ class Aa { /** Editor version */ static get version() { return "2.31.0"; } /** * @param {EditorConfig|string|undefined} [configuration] - user configuration */ constructor(e) { let t = () => { }; D$3(e) && A$4(e.onReady) && (t = e.onReady); const o2 = new _a(e); this.isReady = o2.isReady.then(() => { this.exportAPI(o2), t(); }); } /** * Export external API methods * * @param {Core} editor — Editor's instance */ exportAPI(e) { const t = ["configuration"], o2 = () => { Object.values(e.moduleInstances).forEach((s2) => { A$4(s2.destroy) && s2.destroy(), s2.listeners.removeAll(); }), zi(), e = null; for (const s2 in this) Object.prototype.hasOwnProperty.call(this, s2) && delete this[s2]; Object.setPrototypeOf(this, null); }; t.forEach((s2) => { this[s2] = e[s2]; }), this.destroy = o2, Object.setPrototypeOf(this, e.moduleInstances.API.methods), delete this.exportAPI, Object.entries({ blocks: { clear: "clear", render: "render" }, caret: { focus: "focus" }, events: { on: "on", off: "off", emit: "emit" }, saver: { save: "save" } }).forEach(([s2, r2]) => { Object.entries(r2).forEach(([a2, l2]) => { this[l2] = e.moduleInstances.API.methods[s2][a2]; }); }); } } (function() { try { if (typeof document < "u") { var e = document.createElement("style"); e.appendChild(document.createTextNode(".ce-header{padding:.6em 0 3px;margin:0;line-height:1.25em;outline:none}.ce-header p,.ce-header div{padding:0!important;margin:0!important}")), document.head.appendChild(e); } } catch (n2) { console.error("vite-plugin-css-injected-by-js", n2); } })(); const a$1 = '', l = '', o$1 = '', h$3 = '', d$1 = '', u = '', g$2 = ''; /** * Header block for the Editor.js. * * @author CodeX (team@ifmo.su) * @copyright CodeX 2018 * @license MIT * @version 2.0.0 */ let v$3 = class v { constructor({ data: e, config: t, api: s2, readOnly: r2 }) { this.api = s2, this.readOnly = r2, this._settings = t, this._data = this.normalizeData(e), this._element = this.getTag(); } /** * Styles */ get _CSS() { return { block: this.api.styles.block, wrapper: "ce-header" }; } /** * Check if data is valid * * @param {any} data - data to check * @returns {data is HeaderData} * @private */ isHeaderData(e) { return e.text !== void 0; } /** * Normalize input data * * @param {HeaderData} data - saved data to process * * @returns {HeaderData} * @private */ normalizeData(e) { const t = { text: "", level: this.defaultLevel.number }; return this.isHeaderData(e) && (t.text = e.text || "", e.level !== void 0 && !isNaN(parseInt(e.level.toString())) && (t.level = parseInt(e.level.toString()))), t; } /** * Return Tool's view * * @returns {HTMLHeadingElement} * @public */ render() { return this._element; } /** * Returns header block tunes config * * @returns {Array} */ renderSettings() { return this.levels.map((e) => ({ icon: e.svg, label: this.api.i18n.t(`Heading ${e.number}`), onActivate: () => this.setLevel(e.number), closeOnActivate: true, isActive: this.currentLevel.number === e.number, render: () => document.createElement("div") })); } /** * Callback for Block's settings buttons * * @param {number} level - level to set */ setLevel(e) { this.data = { level: e, text: this.data.text }; } /** * Method that specified how to merge two Text blocks. * Called by Editor.js by backspace at the beginning of the Block * * @param {HeaderData} data - saved data to merger with current block * @public */ merge(e) { this._element.insertAdjacentHTML("beforeend", e.text); } /** * Validate Text block data: * - check for emptiness * * @param {HeaderData} blockData — data received after saving * @returns {boolean} false if saved data is not correct, otherwise true * @public */ validate(e) { return e.text.trim() !== ""; } /** * Extract Tool's data from the view * * @param {HTMLHeadingElement} toolsContent - Text tools rendered view * @returns {HeaderData} - saved data * @public */ save(e) { return { text: e.innerHTML, level: this.currentLevel.number }; } /** * Allow Header to be converted to/from other blocks */ static get conversionConfig() { return { export: "text", // use 'text' property for other blocks import: "text" // fill 'text' property from other block's export string }; } /** * Sanitizer Rules */ static get sanitize() { return { level: false, text: {} }; } /** * Returns true to notify core that read-only is supported * * @returns {boolean} */ static get isReadOnlySupported() { return true; } /** * Get current Tools`s data * * @returns {HeaderData} Current data * @private */ get data() { return this._data.text = this._element.innerHTML, this._data.level = this.currentLevel.number, this._data; } /** * Store data in plugin: * - at the this._data property * - at the HTML * * @param {HeaderData} data — data to set * @private */ set data(e) { if (this._data = this.normalizeData(e), e.level !== void 0 && this._element.parentNode) { const t = this.getTag(); t.innerHTML = this._element.innerHTML, this._element.parentNode.replaceChild(t, this._element), this._element = t; } e.text !== void 0 && (this._element.innerHTML = this._data.text || ""); } /** * Get tag for target level * By default returns second-leveled header * * @returns {HTMLElement} */ getTag() { const e = document.createElement(this.currentLevel.tag); return e.innerHTML = this._data.text || "", e.classList.add(this._CSS.wrapper), e.contentEditable = this.readOnly ? "false" : "true", e.dataset.placeholder = this.api.i18n.t(this._settings.placeholder || ""), e; } /** * Get current level * * @returns {level} */ get currentLevel() { let e = this.levels.find((t) => t.number === this._data.level); return e || (e = this.defaultLevel), e; } /** * Return default level * * @returns {level} */ get defaultLevel() { if (this._settings.defaultLevel) { const e = this.levels.find((t) => t.number === this._settings.defaultLevel); if (e) return e; console.warn("(ง'̀-'́)ง Heading Tool: the default level specified was not found in available levels"); } return this.levels[1]; } /** * @typedef {object} level * @property {number} number - level number * @property {string} tag - tag corresponds with level number * @property {string} svg - icon */ /** * Available header levels * * @returns {level[]} */ get levels() { const e = [ { number: 1, tag: "H1", svg: a$1 }, { number: 2, tag: "H2", svg: l }, { number: 3, tag: "H3", svg: o$1 }, { number: 4, tag: "H4", svg: h$3 }, { number: 5, tag: "H5", svg: d$1 }, { number: 6, tag: "H6", svg: u } ]; return this._settings.levels ? e.filter( (t) => this._settings.levels.includes(t.number) ) : e; } /** * Handle H1-H6 tags on paste to substitute it with header Tool * * @param {PasteEvent} event - event with pasted content */ onPaste(e) { const t = e.detail; if ("data" in t) { const s2 = t.data; let r2 = this.defaultLevel.number; switch (s2.tagName) { case "H1": r2 = 1; break; case "H2": r2 = 2; break; case "H3": r2 = 3; break; case "H4": r2 = 4; break; case "H5": r2 = 5; break; case "H6": r2 = 6; break; } this._settings.levels && (r2 = this._settings.levels.reduce((n2, i) => Math.abs(i - r2) < Math.abs(n2 - r2) ? i : n2)), this.data = { level: r2, text: s2.innerHTML }; } } /** * Used by Editor.js paste handling API. * Provides configuration to handle H1-H6 tags. * * @returns {{handler: (function(HTMLElement): {text: string}), tags: string[]}} */ static get pasteConfig() { return { tags: ["H1", "H2", "H3", "H4", "H5", "H6"] }; } /** * Get Tool toolbox settings * icon - Tool icon's SVG * title - title to show in toolbox * * @returns {{icon: string, title: string}} */ static get toolbox() { return { icon: g$2, title: "Heading" }; } }; (function() { try { if (typeof document < "u") { var e = document.createElement("style"); e.appendChild(document.createTextNode('.cdx-list{margin:0;padding:0;outline:none;display:grid;counter-reset:item;gap:var(--spacing-s);padding:var(--spacing-xs);--spacing-s: 8px;--spacing-xs: 6px;--list-counter-type: numeric;--radius-border: 5px;--checkbox-background: #fff;--color-border: #C9C9C9;--color-bg-checked: #369FFF;--line-height: 1.45em;--color-bg-checked-hover: #0059AB;--color-tick: #fff;--size-checkbox: 1.2em}.cdx-list__item{line-height:var(--line-height);display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto;grid-template-areas:"checkbox content" ". child"}.cdx-list__item-children{display:grid;grid-area:child;gap:var(--spacing-s);padding-top:var(--spacing-s)}.cdx-list__item [contenteditable]{outline:none}.cdx-list__item-content{word-break:break-word;white-space:pre-wrap;grid-area:content;padding-left:var(--spacing-s)}.cdx-list__item:before{counter-increment:item;white-space:nowrap}.cdx-list-ordered .cdx-list__item:before{content:counters(item,".",var(--list-counter-type)) "."}.cdx-list-ordered{counter-reset:item}.cdx-list-unordered .cdx-list__item:before{content:"•"}.cdx-list-checklist .cdx-list__item:before{content:""}.cdx-list__settings .cdx-settings-button{width:50%}.cdx-list__checkbox{padding-top:calc((var(--line-height) - var(--size-checkbox)) / 2);grid-area:checkbox;width:var(--size-checkbox);height:var(--size-checkbox);display:flex;cursor:pointer}.cdx-list__checkbox svg{opacity:0;height:var(--size-checkbox);width:var(--size-checkbox);left:-1px;top:-1px;position:absolute}@media (hover: hover){.cdx-list__checkbox:not(.cdx-list__checkbox--no-hover):hover .cdx-list__checkbox-check svg{opacity:1}}.cdx-list__checkbox--checked{line-height:var(--line-height)}@media (hover: hover){.cdx-list__checkbox--checked:not(.cdx-list__checkbox--checked--no-hover):hover .cdx-checklist__checkbox-check{background:var(--color-bg-checked-hover);border-color:var(--color-bg-checked-hover)}}.cdx-list__checkbox--checked .cdx-list__checkbox-check{background:var(--color-bg-checked);border-color:var(--color-bg-checked)}.cdx-list__checkbox--checked .cdx-list__checkbox-check svg{opacity:1}.cdx-list__checkbox--checked .cdx-list__checkbox-check svg path{stroke:var(--color-tick)}.cdx-list__checkbox--checked .cdx-list__checkbox-check:before{opacity:0;visibility:visible;transform:scale(2.5)}.cdx-list__checkbox-check{cursor:pointer;display:inline-block;position:relative;margin:0 auto;width:var(--size-checkbox);height:var(--size-checkbox);box-sizing:border-box;border-radius:var(--radius-border);border:1px solid var(--color-border);background:var(--checkbox-background)}.cdx-list__checkbox-check:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:100%;background-color:var(--color-bg-checked);visibility:hidden;pointer-events:none;transform:scale(1);transition:transform .4s ease-out,opacity .4s}.cdx-list__checkbox-check--disabled{pointer-events:none}.cdx-list-start-with-field{background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:2px;display:grid;grid-template-columns:auto auto 1fr;grid-template-rows:auto}.cdx-list-start-with-field--invalid{background:#FFECED;border:1px solid #E13F3F}.cdx-list-start-with-field--invalid .cdx-list-start-with-field__input{color:#e13f3f}.cdx-list-start-with-field__input{font-size:14px;outline:none;font-weight:500;font-family:inherit;border:0;background:transparent;margin:0;padding:0;line-height:22px;min-width:calc(100% - var(--toolbox-buttons-size) - var(--icon-margin-right))}.cdx-list-start-with-field__input::placeholder{color:var(--grayText);font-weight:500}')), document.head.appendChild(e); } } catch (c2) { console.error("vite-plugin-css-injected-by-js", c2); } })(); const Ct$1 = '', Ae = '', $e = '', Be = '', St$1 = '', Ot$1 = '', kt$1 = '', _t$1 = '', Et$1 = '', It$1 = ''; var A$3 = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {}; function wt$1(e) { if (e.__esModule) return e; var t = e.default; if (typeof t == "function") { var n2 = function r2() { return this instanceof r2 ? Reflect.construct(t, arguments, this.constructor) : t.apply(this, arguments); }; n2.prototype = t.prototype; } else n2 = {}; return Object.defineProperty(n2, "__esModule", { value: true }), Object.keys(e).forEach(function(r2) { var i = Object.getOwnPropertyDescriptor(e, r2); Object.defineProperty(n2, r2, i.get ? i : { enumerable: true, get: function() { return e[r2]; } }); }), n2; } var c$3 = {}, V$1 = {}, Y$1 = {}; Object.defineProperty(Y$1, "__esModule", { value: true }); Y$1.allInputsSelector = Pt$1; function Pt$1() { var e = ["text", "password", "email", "number", "search", "tel", "url"]; return "[contenteditable=true], textarea, input:not([type]), " + e.map(function(t) { return 'input[type="'.concat(t, '"]'); }).join(", "); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.allInputsSelector = void 0; var t = Y$1; Object.defineProperty(e, "allInputsSelector", { enumerable: true, get: function() { return t.allInputsSelector; } }); })(V$1); var k$2 = {}, J$1 = {}; Object.defineProperty(J$1, "__esModule", { value: true }); J$1.isNativeInput = jt$1; function jt$1(e) { var t = [ "INPUT", "TEXTAREA" ]; return e && e.tagName ? t.includes(e.tagName) : false; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isNativeInput = void 0; var t = J$1; Object.defineProperty(e, "isNativeInput", { enumerable: true, get: function() { return t.isNativeInput; } }); })(k$2); var Fe$1 = {}, Q$1 = {}; Object.defineProperty(Q$1, "__esModule", { value: true }); Q$1.append = Tt$1; function Tt$1(e, t) { Array.isArray(t) ? t.forEach(function(n2) { e.appendChild(n2); }) : e.appendChild(t); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.append = void 0; var t = Q$1; Object.defineProperty(e, "append", { enumerable: true, get: function() { return t.append; } }); })(Fe$1); var Z$1 = {}, x$3 = {}; Object.defineProperty(x$3, "__esModule", { value: true }); x$3.blockElements = Lt$1; function Lt$1() { return [ "address", "article", "aside", "blockquote", "canvas", "div", "dl", "dt", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "hr", "li", "main", "nav", "noscript", "ol", "output", "p", "pre", "ruby", "section", "table", "tbody", "thead", "tr", "tfoot", "ul", "video" ]; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.blockElements = void 0; var t = x$3; Object.defineProperty(e, "blockElements", { enumerable: true, get: function() { return t.blockElements; } }); })(Z$1); var Re$1 = {}, ee$1 = {}; Object.defineProperty(ee$1, "__esModule", { value: true }); ee$1.calculateBaseline = Mt$1; function Mt$1(e) { var t = window.getComputedStyle(e), n2 = parseFloat(t.fontSize), r2 = parseFloat(t.lineHeight) || n2 * 1.2, i = parseFloat(t.paddingTop), a2 = parseFloat(t.borderTopWidth), l2 = parseFloat(t.marginTop), s2 = n2 * 0.8, o2 = (r2 - n2) / 2, d2 = l2 + a2 + i + o2 + s2; return d2; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.calculateBaseline = void 0; var t = ee$1; Object.defineProperty(e, "calculateBaseline", { enumerable: true, get: function() { return t.calculateBaseline; } }); })(Re$1); var qe$1 = {}, te$1 = {}, ne$1 = {}, re$1 = {}; Object.defineProperty(re$1, "__esModule", { value: true }); re$1.isContentEditable = Nt$1; function Nt$1(e) { return e.contentEditable === "true"; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isContentEditable = void 0; var t = re$1; Object.defineProperty(e, "isContentEditable", { enumerable: true, get: function() { return t.isContentEditable; } }); })(ne$1); Object.defineProperty(te$1, "__esModule", { value: true }); te$1.canSetCaret = Bt$1; var At$1 = k$2, $t$1 = ne$1; function Bt$1(e) { var t = true; if ((0, At$1.isNativeInput)(e)) switch (e.type) { case "file": case "checkbox": case "radio": case "hidden": case "submit": case "button": case "image": case "reset": t = false; break; } else t = (0, $t$1.isContentEditable)(e); return t; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.canSetCaret = void 0; var t = te$1; Object.defineProperty(e, "canSetCaret", { enumerable: true, get: function() { return t.canSetCaret; } }); })(qe$1); var $$1 = {}, ie$1 = {}; function Wt$1(e, t, n2) { const r2 = n2.value !== void 0 ? "value" : "get", i = n2[r2], a2 = `#${t}Cache`; if (n2[r2] = function(...l2) { return this[a2] === void 0 && (this[a2] = i.apply(this, l2)), this[a2]; }, r2 === "get" && n2.set) { const l2 = n2.set; n2.set = function(s2) { delete e[a2], l2.apply(this, s2); }; } return n2; } function Ue$1() { const e = { win: false, mac: false, x11: false, linux: false }, t = Object.keys(e).find((n2) => window.navigator.appVersion.toLowerCase().indexOf(n2) !== -1); return t !== void 0 && (e[t] = true), e; } function ae$1(e) { return e != null && e !== "" && (typeof e != "object" || Object.keys(e).length > 0); } function Dt$1(e) { return !ae$1(e); } const Ht$1 = () => typeof window < "u" && window.navigator !== null && ae$1(window.navigator.platform) && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1); function Ft$1(e) { const t = Ue$1(); return e = e.replace(/shift/gi, "⇧").replace(/backspace/gi, "⌫").replace(/enter/gi, "⏎").replace(/up/gi, "↑").replace(/left/gi, "→").replace(/down/gi, "↓").replace(/right/gi, "←").replace(/escape/gi, "⎋").replace(/insert/gi, "Ins").replace(/delete/gi, "␡").replace(/\+/gi, "+"), t.mac ? e = e.replace(/ctrl|cmd/gi, "⌘").replace(/alt/gi, "⌥") : e = e.replace(/cmd/gi, "Ctrl").replace(/windows/gi, "WIN"), e; } function Rt$1(e) { return e[0].toUpperCase() + e.slice(1); } function qt$1(e) { const t = document.createElement("div"); t.style.position = "absolute", t.style.left = "-999px", t.style.bottom = "-999px", t.innerHTML = e, document.body.appendChild(t); const n2 = window.getSelection(), r2 = document.createRange(); if (r2.selectNode(t), n2 === null) throw new Error("Cannot copy text to clipboard"); n2.removeAllRanges(), n2.addRange(r2), document.execCommand("copy"), document.body.removeChild(t); } function Ut$1(e, t, n2) { let r2; return (...i) => { const a2 = this, l2 = () => { r2 = void 0, n2 !== true && e.apply(a2, i); }, s2 = n2 === true && r2 !== void 0; window.clearTimeout(r2), r2 = window.setTimeout(l2, t), s2 && e.apply(a2, i); }; } function S$3(e) { return Object.prototype.toString.call(e).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); } function Kt$1(e) { return S$3(e) === "boolean"; } function Ke$1(e) { return S$3(e) === "function" || S$3(e) === "asyncfunction"; } function zt$1(e) { return Ke$1(e) && /^\s*class\s+/.test(e.toString()); } function Xt$1(e) { return S$3(e) === "number"; } function M$2(e) { return S$3(e) === "object"; } function Gt$1(e) { return Promise.resolve(e) === e; } function Vt$1(e) { return S$3(e) === "string"; } function Yt$1(e) { return S$3(e) === "undefined"; } function X$1(e, ...t) { if (!t.length) return e; const n2 = t.shift(); if (M$2(e) && M$2(n2)) for (const r2 in n2) M$2(n2[r2]) ? (e[r2] === void 0 && Object.assign(e, { [r2]: {} }), X$1(e[r2], n2[r2])) : Object.assign(e, { [r2]: n2[r2] }); return X$1(e, ...t); } function Jt$1(e, t, n2) { const r2 = `«${t}» is deprecated and will be removed in the next major release. Please use the «${n2}» instead.`; e && console.warn(r2); } function Qt$1(e) { try { return new URL(e).href; } catch { } return e.substring(0, 2) === "//" ? window.location.protocol + e : window.location.origin + e; } function Zt$1(e) { return e > 47 && e < 58 || e === 32 || e === 13 || e === 229 || e > 64 && e < 91 || e > 95 && e < 112 || e > 185 && e < 193 || e > 218 && e < 223; } const xt$1 = { BACKSPACE: 8, TAB: 9, ENTER: 13, SHIFT: 16, CTRL: 17, ALT: 18, ESC: 27, SPACE: 32, LEFT: 37, UP: 38, DOWN: 40, RIGHT: 39, DELETE: 46, META: 91, SLASH: 191 }, en = { LEFT: 0, WHEEL: 1, RIGHT: 2, BACKWARD: 3, FORWARD: 4 }; class tn { constructor() { this.completed = Promise.resolve(); } /** * Add new promise to queue * @param operation - promise should be added to queue */ add(t) { return new Promise((n2, r2) => { this.completed = this.completed.then(t).then(n2).catch(r2); }); } } function nn(e, t, n2 = void 0) { let r2, i, a2, l2 = null, s2 = 0; n2 || (n2 = {}); const o2 = function() { s2 = n2.leading === false ? 0 : Date.now(), l2 = null, a2 = e.apply(r2, i), l2 === null && (r2 = i = null); }; return function() { const d2 = Date.now(); !s2 && n2.leading === false && (s2 = d2); const u2 = t - (d2 - s2); return r2 = this, i = arguments, u2 <= 0 || u2 > t ? (l2 && (clearTimeout(l2), l2 = null), s2 = d2, a2 = e.apply(r2, i), l2 === null && (r2 = i = null)) : !l2 && n2.trailing !== false && (l2 = setTimeout(o2, u2)), a2; }; } const rn = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, PromiseQueue: tn, beautifyShortcut: Ft$1, cacheable: Wt$1, capitalize: Rt$1, copyTextToClipboard: qt$1, debounce: Ut$1, deepMerge: X$1, deprecationAssert: Jt$1, getUserOS: Ue$1, getValidUrl: Qt$1, isBoolean: Kt$1, isClass: zt$1, isEmpty: Dt$1, isFunction: Ke$1, isIosDevice: Ht$1, isNumber: Xt$1, isObject: M$2, isPrintableKey: Zt$1, isPromise: Gt$1, isString: Vt$1, isUndefined: Yt$1, keyCodes: xt$1, mouseButtons: en, notEmpty: ae$1, throttle: nn, typeOf: S$3 }, Symbol.toStringTag, { value: "Module" })), le$1 = /* @__PURE__ */ wt$1(rn); Object.defineProperty(ie$1, "__esModule", { value: true }); ie$1.containsOnlyInlineElements = sn; var an = le$1, ln = Z$1; function sn(e) { var t; (0, an.isString)(e) ? (t = document.createElement("div"), t.innerHTML = e) : t = e; var n2 = function(r2) { return !(0, ln.blockElements)().includes(r2.tagName.toLowerCase()) && Array.from(r2.children).every(n2); }; return Array.from(t.children).every(n2); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.containsOnlyInlineElements = void 0; var t = ie$1; Object.defineProperty(e, "containsOnlyInlineElements", { enumerable: true, get: function() { return t.containsOnlyInlineElements; } }); })($$1); var ze$1 = {}, se$1 = {}, B$3 = {}, oe$1 = {}; Object.defineProperty(oe$1, "__esModule", { value: true }); oe$1.make = on; function on(e, t, n2) { var r2; t === void 0 && (t = null), n2 === void 0 && (n2 = {}); var i = document.createElement(e); if (Array.isArray(t)) { var a2 = t.filter(function(s2) { return s2 !== void 0; }); (r2 = i.classList).add.apply(r2, a2); } else t !== null && i.classList.add(t); for (var l2 in n2) Object.prototype.hasOwnProperty.call(n2, l2) && (i[l2] = n2[l2]); return i; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.make = void 0; var t = oe$1; Object.defineProperty(e, "make", { enumerable: true, get: function() { return t.make; } }); })(B$3); Object.defineProperty(se$1, "__esModule", { value: true }); se$1.fragmentToString = cn; var un = B$3; function cn(e) { var t = (0, un.make)("div"); return t.appendChild(e), t.innerHTML; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.fragmentToString = void 0; var t = se$1; Object.defineProperty(e, "fragmentToString", { enumerable: true, get: function() { return t.fragmentToString; } }); })(ze$1); var Xe$1 = {}, ue$1 = {}; Object.defineProperty(ue$1, "__esModule", { value: true }); ue$1.getContentLength = fn; var dn = k$2; function fn(e) { var t, n2; return (0, dn.isNativeInput)(e) ? e.value.length : e.nodeType === Node.TEXT_NODE ? e.length : (n2 = (t = e.textContent) === null || t === void 0 ? void 0 : t.length) !== null && n2 !== void 0 ? n2 : 0; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.getContentLength = void 0; var t = ue$1; Object.defineProperty(e, "getContentLength", { enumerable: true, get: function() { return t.getContentLength; } }); })(Xe$1); var ce$1 = {}, de$1 = {}, We$1 = A$3 && A$3.__spreadArray || function(e, t, n2) { if (n2 || arguments.length === 2) for (var r2 = 0, i = t.length, a2; r2 < i; r2++) (a2 || !(r2 in t)) && (a2 || (a2 = Array.prototype.slice.call(t, 0, r2)), a2[r2] = t[r2]); return e.concat(a2 || Array.prototype.slice.call(t)); }; Object.defineProperty(de$1, "__esModule", { value: true }); de$1.getDeepestBlockElements = Ge$1; var pn = $$1; function Ge$1(e) { return (0, pn.containsOnlyInlineElements)(e) ? [e] : Array.from(e.children).reduce(function(t, n2) { return We$1(We$1([], t, true), Ge$1(n2), true); }, []); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.getDeepestBlockElements = void 0; var t = de$1; Object.defineProperty(e, "getDeepestBlockElements", { enumerable: true, get: function() { return t.getDeepestBlockElements; } }); })(ce$1); var Ve$1 = {}, fe$1 = {}, W$1 = {}, pe$1 = {}; Object.defineProperty(pe$1, "__esModule", { value: true }); pe$1.isLineBreakTag = hn; function hn(e) { return [ "BR", "WBR" ].includes(e.tagName); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isLineBreakTag = void 0; var t = pe$1; Object.defineProperty(e, "isLineBreakTag", { enumerable: true, get: function() { return t.isLineBreakTag; } }); })(W$1); var D$2 = {}, he$1 = {}; Object.defineProperty(he$1, "__esModule", { value: true }); he$1.isSingleTag = mn; function mn(e) { return [ "AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "META", "PARAM", "SOURCE", "TRACK", "WBR" ].includes(e.tagName); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isSingleTag = void 0; var t = he$1; Object.defineProperty(e, "isSingleTag", { enumerable: true, get: function() { return t.isSingleTag; } }); })(D$2); Object.defineProperty(fe$1, "__esModule", { value: true }); fe$1.getDeepestNode = Ye$1; var gn = k$2, vn = W$1, bn = D$2; function Ye$1(e, t) { t === void 0 && (t = false); var n2 = t ? "lastChild" : "firstChild", r2 = t ? "previousSibling" : "nextSibling"; if (e.nodeType === Node.ELEMENT_NODE && e[n2]) { var i = e[n2]; if ((0, bn.isSingleTag)(i) && !(0, gn.isNativeInput)(i) && !(0, vn.isLineBreakTag)(i)) if (i[r2]) i = i[r2]; else if (i.parentNode !== null && i.parentNode[r2]) i = i.parentNode[r2]; else return i.parentNode; return Ye$1(i, t); } return e; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.getDeepestNode = void 0; var t = fe$1; Object.defineProperty(e, "getDeepestNode", { enumerable: true, get: function() { return t.getDeepestNode; } }); })(Ve$1); var Je$1 = {}, me$1 = {}, T$2 = A$3 && A$3.__spreadArray || function(e, t, n2) { if (n2 || arguments.length === 2) for (var r2 = 0, i = t.length, a2; r2 < i; r2++) (a2 || !(r2 in t)) && (a2 || (a2 = Array.prototype.slice.call(t, 0, r2)), a2[r2] = t[r2]); return e.concat(a2 || Array.prototype.slice.call(t)); }; Object.defineProperty(me$1, "__esModule", { value: true }); me$1.findAllInputs = kn; var yn = $$1, Cn = ce$1, Sn = V$1, On = k$2; function kn(e) { return Array.from(e.querySelectorAll((0, Sn.allInputsSelector)())).reduce(function(t, n2) { return (0, On.isNativeInput)(n2) || (0, yn.containsOnlyInlineElements)(n2) ? T$2(T$2([], t, true), [n2], false) : T$2(T$2([], t, true), (0, Cn.getDeepestBlockElements)(n2), true); }, []); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.findAllInputs = void 0; var t = me$1; Object.defineProperty(e, "findAllInputs", { enumerable: true, get: function() { return t.findAllInputs; } }); })(Je$1); var Qe$1 = {}, ge$1 = {}; Object.defineProperty(ge$1, "__esModule", { value: true }); ge$1.isCollapsedWhitespaces = _n; function _n(e) { return !/[^\t\n\r ]/.test(e); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isCollapsedWhitespaces = void 0; var t = ge$1; Object.defineProperty(e, "isCollapsedWhitespaces", { enumerable: true, get: function() { return t.isCollapsedWhitespaces; } }); })(Qe$1); var ve$1 = {}, be$1 = {}; Object.defineProperty(be$1, "__esModule", { value: true }); be$1.isElement = In; var En = le$1; function In(e) { return (0, En.isNumber)(e) ? false : !!e && !!e.nodeType && e.nodeType === Node.ELEMENT_NODE; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isElement = void 0; var t = be$1; Object.defineProperty(e, "isElement", { enumerable: true, get: function() { return t.isElement; } }); })(ve$1); var Ze$1 = {}, ye$1 = {}, Ce = {}, Se = {}; Object.defineProperty(Se, "__esModule", { value: true }); Se.isLeaf = wn; function wn(e) { return e === null ? false : e.childNodes.length === 0; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isLeaf = void 0; var t = Se; Object.defineProperty(e, "isLeaf", { enumerable: true, get: function() { return t.isLeaf; } }); })(Ce); var Oe = {}, ke = {}; Object.defineProperty(ke, "__esModule", { value: true }); ke.isNodeEmpty = Mn; var Pn = W$1, jn = ve$1, Tn = k$2, Ln = D$2; function Mn(e, t) { var n2 = ""; return (0, Ln.isSingleTag)(e) && !(0, Pn.isLineBreakTag)(e) ? false : ((0, jn.isElement)(e) && (0, Tn.isNativeInput)(e) ? n2 = e.value : e.textContent !== null && (n2 = e.textContent.replace("​", "")), t !== void 0 && (n2 = n2.replace(new RegExp(t, "g"), "")), n2.trim().length === 0); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isNodeEmpty = void 0; var t = ke; Object.defineProperty(e, "isNodeEmpty", { enumerable: true, get: function() { return t.isNodeEmpty; } }); })(Oe); Object.defineProperty(ye$1, "__esModule", { value: true }); ye$1.isEmpty = $n; var Nn = Ce, An = Oe; function $n(e, t) { e.normalize(); for (var n2 = [e]; n2.length > 0; ) { var r2 = n2.shift(); if (r2) { if (e = r2, (0, Nn.isLeaf)(e) && !(0, An.isNodeEmpty)(e, t)) return false; n2.push.apply(n2, Array.from(e.childNodes)); } } return true; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isEmpty = void 0; var t = ye$1; Object.defineProperty(e, "isEmpty", { enumerable: true, get: function() { return t.isEmpty; } }); })(Ze$1); var xe$1 = {}, _e$1 = {}; Object.defineProperty(_e$1, "__esModule", { value: true }); _e$1.isFragment = Wn; var Bn = le$1; function Wn(e) { return (0, Bn.isNumber)(e) ? false : !!e && !!e.nodeType && e.nodeType === Node.DOCUMENT_FRAGMENT_NODE; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isFragment = void 0; var t = _e$1; Object.defineProperty(e, "isFragment", { enumerable: true, get: function() { return t.isFragment; } }); })(xe$1); var et$1 = {}, Ee$1 = {}; Object.defineProperty(Ee$1, "__esModule", { value: true }); Ee$1.isHTMLString = Hn; var Dn = B$3; function Hn(e) { var t = (0, Dn.make)("div"); return t.innerHTML = e, t.childElementCount > 0; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isHTMLString = void 0; var t = Ee$1; Object.defineProperty(e, "isHTMLString", { enumerable: true, get: function() { return t.isHTMLString; } }); })(et$1); var tt$1 = {}, Ie = {}; Object.defineProperty(Ie, "__esModule", { value: true }); Ie.offset = Fn; function Fn(e) { var t = e.getBoundingClientRect(), n2 = window.pageXOffset || document.documentElement.scrollLeft, r2 = window.pageYOffset || document.documentElement.scrollTop, i = t.top + r2, a2 = t.left + n2; return { top: i, left: a2, bottom: i + t.height, right: a2 + t.width }; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.offset = void 0; var t = Ie; Object.defineProperty(e, "offset", { enumerable: true, get: function() { return t.offset; } }); })(tt$1); var nt$1 = {}, we = {}; Object.defineProperty(we, "__esModule", { value: true }); we.prepend = Rn; function Rn(e, t) { Array.isArray(t) ? (t = t.reverse(), t.forEach(function(n2) { return e.prepend(n2); })) : e.prepend(t); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.prepend = void 0; var t = we; Object.defineProperty(e, "prepend", { enumerable: true, get: function() { return t.prepend; } }); })(nt$1); (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.prepend = e.offset = e.make = e.isLineBreakTag = e.isSingleTag = e.isNodeEmpty = e.isLeaf = e.isHTMLString = e.isFragment = e.isEmpty = e.isElement = e.isContentEditable = e.isCollapsedWhitespaces = e.findAllInputs = e.isNativeInput = e.allInputsSelector = e.getDeepestNode = e.getDeepestBlockElements = e.getContentLength = e.fragmentToString = e.containsOnlyInlineElements = e.canSetCaret = e.calculateBaseline = e.blockElements = e.append = void 0; var t = V$1; Object.defineProperty(e, "allInputsSelector", { enumerable: true, get: function() { return t.allInputsSelector; } }); var n2 = k$2; Object.defineProperty(e, "isNativeInput", { enumerable: true, get: function() { return n2.isNativeInput; } }); var r2 = Fe$1; Object.defineProperty(e, "append", { enumerable: true, get: function() { return r2.append; } }); var i = Z$1; Object.defineProperty(e, "blockElements", { enumerable: true, get: function() { return i.blockElements; } }); var a2 = Re$1; Object.defineProperty(e, "calculateBaseline", { enumerable: true, get: function() { return a2.calculateBaseline; } }); var l2 = qe$1; Object.defineProperty(e, "canSetCaret", { enumerable: true, get: function() { return l2.canSetCaret; } }); var s2 = $$1; Object.defineProperty(e, "containsOnlyInlineElements", { enumerable: true, get: function() { return s2.containsOnlyInlineElements; } }); var o2 = ze$1; Object.defineProperty(e, "fragmentToString", { enumerable: true, get: function() { return o2.fragmentToString; } }); var d2 = Xe$1; Object.defineProperty(e, "getContentLength", { enumerable: true, get: function() { return d2.getContentLength; } }); var u2 = ce$1; Object.defineProperty(e, "getDeepestBlockElements", { enumerable: true, get: function() { return u2.getDeepestBlockElements; } }); var p2 = Ve$1; Object.defineProperty(e, "getDeepestNode", { enumerable: true, get: function() { return p2.getDeepestNode; } }); var g2 = Je$1; Object.defineProperty(e, "findAllInputs", { enumerable: true, get: function() { return g2.findAllInputs; } }); var w2 = Qe$1; Object.defineProperty(e, "isCollapsedWhitespaces", { enumerable: true, get: function() { return w2.isCollapsedWhitespaces; } }); var _2 = ne$1; Object.defineProperty(e, "isContentEditable", { enumerable: true, get: function() { return _2.isContentEditable; } }); var ut2 = ve$1; Object.defineProperty(e, "isElement", { enumerable: true, get: function() { return ut2.isElement; } }); var ct2 = Ze$1; Object.defineProperty(e, "isEmpty", { enumerable: true, get: function() { return ct2.isEmpty; } }); var dt2 = xe$1; Object.defineProperty(e, "isFragment", { enumerable: true, get: function() { return dt2.isFragment; } }); var ft2 = et$1; Object.defineProperty(e, "isHTMLString", { enumerable: true, get: function() { return ft2.isHTMLString; } }); var pt2 = Ce; Object.defineProperty(e, "isLeaf", { enumerable: true, get: function() { return pt2.isLeaf; } }); var ht2 = Oe; Object.defineProperty(e, "isNodeEmpty", { enumerable: true, get: function() { return ht2.isNodeEmpty; } }); var mt2 = W$1; Object.defineProperty(e, "isLineBreakTag", { enumerable: true, get: function() { return mt2.isLineBreakTag; } }); var gt2 = D$2; Object.defineProperty(e, "isSingleTag", { enumerable: true, get: function() { return gt2.isSingleTag; } }); var vt2 = B$3; Object.defineProperty(e, "make", { enumerable: true, get: function() { return vt2.make; } }); var bt2 = tt$1; Object.defineProperty(e, "offset", { enumerable: true, get: function() { return bt2.offset; } }); var yt2 = nt$1; Object.defineProperty(e, "prepend", { enumerable: true, get: function() { return yt2.prepend; } }); })(c$3); const m$2 = "cdx-list", h$2 = { wrapper: m$2, item: `${m$2}__item`, itemContent: `${m$2}__item-content`, itemChildren: `${m$2}__item-children` }; let v$2 = class v2 { /** * Getter for all CSS classes used in unordered list rendering */ static get CSS() { return { ...h$2, orderedList: `${m$2}-ordered` }; } /** * Assign passed readonly mode and config to relevant class properties * @param readonly - read-only mode flag * @param config - user config for Tool */ constructor(t, n2) { this.config = n2, this.readOnly = t; } /** * Renders ol wrapper for list * @param isRoot - boolean variable that represents level of the wrappre (root or childList) * @returns - created html ol element */ renderWrapper(t) { let n2; return t === true ? n2 = c$3.make("ol", [v2.CSS.wrapper, v2.CSS.orderedList]) : n2 = c$3.make("ol", [v2.CSS.orderedList, v2.CSS.itemChildren]), n2; } /** * Redners list item element * @param content - content used in list item rendering * @param _meta - meta of the list item unused in rendering of the ordered list * @returns - created html list item element */ renderItem(t, n2) { const r2 = c$3.make("li", v2.CSS.item), i = c$3.make("div", v2.CSS.itemContent, { innerHTML: t, contentEditable: (!this.readOnly).toString() }); return r2.appendChild(i), r2; } /** * Return the item content * @param item - item wrapper (
  • ) * @returns - item content string */ getItemContent(t) { const n2 = t.querySelector(`.${v2.CSS.itemContent}`); return !n2 || c$3.isEmpty(n2) ? "" : n2.innerHTML; } /** * Returns item meta, for ordered list * @returns item meta object */ getItemMeta() { return {}; } /** * Returns default item meta used on creation of the new item */ composeDefaultMeta() { return {}; } }; let b$2 = class b2 { /** * Getter for all CSS classes used in unordered list rendering */ static get CSS() { return { ...h$2, unorderedList: `${m$2}-unordered` }; } /** * Assign passed readonly mode and config to relevant class properties * @param readonly - read-only mode flag * @param config - user config for Tool */ constructor(t, n2) { this.config = n2, this.readOnly = t; } /** * Renders ol wrapper for list * @param isRoot - boolean variable that represents level of the wrappre (root or childList) * @returns - created html ul element */ renderWrapper(t) { let n2; return t === true ? n2 = c$3.make("ul", [b2.CSS.wrapper, b2.CSS.unorderedList]) : n2 = c$3.make("ul", [b2.CSS.unorderedList, b2.CSS.itemChildren]), n2; } /** * Redners list item element * @param content - content used in list item rendering * @param _meta - meta of the list item unused in rendering of the unordered list * @returns - created html list item element */ renderItem(t, n2) { const r2 = c$3.make("li", b2.CSS.item), i = c$3.make("div", b2.CSS.itemContent, { innerHTML: t, contentEditable: (!this.readOnly).toString() }); return r2.appendChild(i), r2; } /** * Return the item content * @param item - item wrapper (
  • ) * @returns - item content string */ getItemContent(t) { const n2 = t.querySelector(`.${b2.CSS.itemContent}`); return !n2 || c$3.isEmpty(n2) ? "" : n2.innerHTML; } /** * Returns item meta, for unordered list * @returns Item meta object */ getItemMeta() { return {}; } /** * Returns default item meta used on creation of the new item */ composeDefaultMeta() { return {}; } }; function O$4(e) { return e.nodeType === Node.ELEMENT_NODE; } var j$3 = {}, Pe = {}, H$3 = {}, F$3 = {}; Object.defineProperty(F$3, "__esModule", { value: true }); F$3.getContenteditableSlice = Un; var qn = c$3; function Un(e, t, n2, r2, i) { var a2; i === void 0 && (i = false); var l2 = document.createRange(); if (r2 === "left" ? (l2.setStart(e, 0), l2.setEnd(t, n2)) : (l2.setStart(t, n2), l2.setEnd(e, e.childNodes.length)), i === true) { var s2 = l2.extractContents(); return (0, qn.fragmentToString)(s2); } var o2 = l2.cloneContents(), d2 = document.createElement("div"); d2.appendChild(o2); var u2 = (a2 = d2.textContent) !== null && a2 !== void 0 ? a2 : ""; return u2; } Object.defineProperty(H$3, "__esModule", { value: true }); H$3.checkContenteditableSliceForEmptiness = Xn; var Kn = c$3, zn = F$3; function Xn(e, t, n2, r2) { var i = (0, zn.getContenteditableSlice)(e, t, n2, r2); return (0, Kn.isCollapsedWhitespaces)(i); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.checkContenteditableSliceForEmptiness = void 0; var t = H$3; Object.defineProperty(e, "checkContenteditableSliceForEmptiness", { enumerable: true, get: function() { return t.checkContenteditableSliceForEmptiness; } }); })(Pe); var rt$1 = {}; (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.getContenteditableSlice = void 0; var t = F$3; Object.defineProperty(e, "getContenteditableSlice", { enumerable: true, get: function() { return t.getContenteditableSlice; } }); })(rt$1); var it$1 = {}, je = {}; Object.defineProperty(je, "__esModule", { value: true }); je.focus = Vn; var Gn = c$3; function Vn(e, t) { var n2, r2; if (t === void 0 && (t = true), (0, Gn.isNativeInput)(e)) { e.focus(); var i = t ? 0 : e.value.length; e.setSelectionRange(i, i); } else { var a2 = document.createRange(), l2 = window.getSelection(); if (!l2) return; var s2 = function(g2, w2) { w2 === void 0 && (w2 = false); var _2 = document.createTextNode(""); w2 ? g2.insertBefore(_2, g2.firstChild) : g2.appendChild(_2), a2.setStart(_2, 0), a2.setEnd(_2, 0); }, o2 = function(g2) { return g2 != null; }, d2 = e.childNodes, u2 = t ? d2[0] : d2[d2.length - 1]; if (o2(u2)) { for (; o2(u2) && u2.nodeType !== Node.TEXT_NODE; ) u2 = t ? u2.firstChild : u2.lastChild; if (o2(u2) && u2.nodeType === Node.TEXT_NODE) { var p2 = (r2 = (n2 = u2.textContent) === null || n2 === void 0 ? void 0 : n2.length) !== null && r2 !== void 0 ? r2 : 0, i = t ? 0 : p2; a2.setStart(u2, i), a2.setEnd(u2, i); } else s2(e, t); } else s2(e); l2.removeAllRanges(), l2.addRange(a2); } } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.focus = void 0; var t = je; Object.defineProperty(e, "focus", { enumerable: true, get: function() { return t.focus; } }); })(it$1); var Te = {}, R$4 = {}; Object.defineProperty(R$4, "__esModule", { value: true }); R$4.getCaretNodeAndOffset = Yn; function Yn() { var e = window.getSelection(); if (e === null) return [null, 0]; var t = e.focusNode, n2 = e.focusOffset; return t === null ? [null, 0] : (t.nodeType !== Node.TEXT_NODE && t.childNodes.length > 0 && (t.childNodes[n2] !== void 0 ? (t = t.childNodes[n2], n2 = 0) : (t = t.childNodes[n2 - 1], t.textContent !== null && (n2 = t.textContent.length))), [t, n2]); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.getCaretNodeAndOffset = void 0; var t = R$4; Object.defineProperty(e, "getCaretNodeAndOffset", { enumerable: true, get: function() { return t.getCaretNodeAndOffset; } }); })(Te); var at$1 = {}, q$2 = {}; Object.defineProperty(q$2, "__esModule", { value: true }); q$2.getRange = Jn; function Jn() { var e = window.getSelection(); return e && e.rangeCount ? e.getRangeAt(0) : null; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.getRange = void 0; var t = q$2; Object.defineProperty(e, "getRange", { enumerable: true, get: function() { return t.getRange; } }); })(at$1); var lt$1 = {}, Le = {}; Object.defineProperty(Le, "__esModule", { value: true }); Le.isCaretAtEndOfInput = xn; var De$1 = c$3, Qn = Te, Zn = Pe; function xn(e) { var t = (0, De$1.getDeepestNode)(e, true); if (t === null) return true; if ((0, De$1.isNativeInput)(t)) return t.selectionEnd === t.value.length; var n2 = (0, Qn.getCaretNodeAndOffset)(), r2 = n2[0], i = n2[1]; return r2 === null ? false : (0, Zn.checkContenteditableSliceForEmptiness)(e, r2, i, "right"); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isCaretAtEndOfInput = void 0; var t = Le; Object.defineProperty(e, "isCaretAtEndOfInput", { enumerable: true, get: function() { return t.isCaretAtEndOfInput; } }); })(lt$1); var st$1 = {}, Me = {}; Object.defineProperty(Me, "__esModule", { value: true }); Me.isCaretAtStartOfInput = nr; var L$3 = c$3, er = R$4, tr = H$3; function nr(e) { var t = (0, L$3.getDeepestNode)(e); if (t === null || (0, L$3.isEmpty)(e)) return true; if ((0, L$3.isNativeInput)(t)) return t.selectionEnd === 0; if ((0, L$3.isEmpty)(e)) return true; var n2 = (0, er.getCaretNodeAndOffset)(), r2 = n2[0], i = n2[1]; return r2 === null ? false : (0, tr.checkContenteditableSliceForEmptiness)(e, r2, i, "left"); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isCaretAtStartOfInput = void 0; var t = Me; Object.defineProperty(e, "isCaretAtStartOfInput", { enumerable: true, get: function() { return t.isCaretAtStartOfInput; } }); })(st$1); var ot$1 = {}, Ne = {}; Object.defineProperty(Ne, "__esModule", { value: true }); Ne.save = ar; var rr = c$3, ir = q$2; function ar() { var e = (0, ir.getRange)(), t = (0, rr.make)("span"); if (t.id = "cursor", t.hidden = true, !!e) return e.insertNode(t), function() { var r2 = window.getSelection(); r2 && (e.setStartAfter(t), e.setEndAfter(t), r2.removeAllRanges(), r2.addRange(e), setTimeout(function() { t.remove(); }, 150)); }; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.save = void 0; var t = Ne; Object.defineProperty(e, "save", { enumerable: true, get: function() { return t.save; } }); })(ot$1); (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.save = e.isCaretAtStartOfInput = e.isCaretAtEndOfInput = e.getRange = e.getCaretNodeAndOffset = e.focus = e.getContenteditableSlice = e.checkContenteditableSliceForEmptiness = void 0; var t = Pe; Object.defineProperty(e, "checkContenteditableSliceForEmptiness", { enumerable: true, get: function() { return t.checkContenteditableSliceForEmptiness; } }); var n2 = rt$1; Object.defineProperty(e, "getContenteditableSlice", { enumerable: true, get: function() { return n2.getContenteditableSlice; } }); var r2 = it$1; Object.defineProperty(e, "focus", { enumerable: true, get: function() { return r2.focus; } }); var i = Te; Object.defineProperty(e, "getCaretNodeAndOffset", { enumerable: true, get: function() { return i.getCaretNodeAndOffset; } }); var a2 = at$1; Object.defineProperty(e, "getRange", { enumerable: true, get: function() { return a2.getRange; } }); var l2 = lt$1; Object.defineProperty(e, "isCaretAtEndOfInput", { enumerable: true, get: function() { return l2.isCaretAtEndOfInput; } }); var s2 = st$1; Object.defineProperty(e, "isCaretAtStartOfInput", { enumerable: true, get: function() { return s2.isCaretAtStartOfInput; } }); var o2 = ot$1; Object.defineProperty(e, "save", { enumerable: true, get: function() { return o2.save; } }); })(j$3); let f$1 = class f2 { /** * Getter for all CSS classes used in unordered list rendering */ static get CSS() { return { ...h$2, checklist: `${m$2}-checklist`, itemChecked: `${m$2}__checkbox--checked`, noHover: `${m$2}__checkbox--no-hover`, checkbox: `${m$2}__checkbox-check`, checkboxContainer: `${m$2}__checkbox`, checkboxCheckDisabled: `${m$2}__checkbox-check--disabled` }; } /** * Assign passed readonly mode and config to relevant class properties * @param readonly - read-only mode flag * @param config - user config for Tool */ constructor(t, n2) { this.config = n2, this.readOnly = t; } /** * Renders ul wrapper for list * @param isRoot - boolean variable that represents level of the wrappre (root or childList) * @returns - created html ul element */ renderWrapper(t) { let n2; return t === true ? (n2 = c$3.make("ul", [f2.CSS.wrapper, f2.CSS.checklist]), n2.addEventListener("click", (r2) => { const i = r2.target; if (i) { const a2 = i.closest(`.${f2.CSS.checkboxContainer}`); a2 && a2.contains(i) && this.toggleCheckbox(a2); } })) : n2 = c$3.make("ul", [f2.CSS.checklist, f2.CSS.itemChildren]), n2; } /** * Redners list item element * @param content - content used in list item rendering * @param meta - meta of the list item used in rendering of the checklist * @returns - created html list item element */ renderItem(t, n2) { const r2 = c$3.make("li", [f2.CSS.item, f2.CSS.item]), i = c$3.make("div", f2.CSS.itemContent, { innerHTML: t, contentEditable: (!this.readOnly).toString() }), a2 = c$3.make("span", f2.CSS.checkbox), l2 = c$3.make("div", f2.CSS.checkboxContainer); return n2.checked === true && l2.classList.add(f2.CSS.itemChecked), this.readOnly && l2.classList.add(f2.CSS.checkboxCheckDisabled), a2.innerHTML = Ct$1, l2.appendChild(a2), r2.appendChild(l2), r2.appendChild(i), r2; } /** * Return the item content * @param item - item wrapper (
  • ) * @returns - item content string */ getItemContent(t) { const n2 = t.querySelector(`.${f2.CSS.itemContent}`); return !n2 || c$3.isEmpty(n2) ? "" : n2.innerHTML; } /** * Return meta object of certain element * @param item - will be returned meta information of this item * @returns Item meta object */ getItemMeta(t) { const n2 = t.querySelector(`.${f2.CSS.checkboxContainer}`); return { checked: n2 ? n2.classList.contains(f2.CSS.itemChecked) : false }; } /** * Returns default item meta used on creation of the new item */ composeDefaultMeta() { return { checked: false }; } /** * Toggle checklist item state * @param checkbox - checkbox element to be toggled */ toggleCheckbox(t) { t.classList.toggle(f2.CSS.itemChecked), t.classList.add(f2.CSS.noHover), t.addEventListener("mouseleave", () => this.removeSpecialHoverBehavior(t), { once: true }); } /** * Removes class responsible for special hover behavior on an item * @param el - item wrapper */ removeSpecialHoverBehavior(t) { t.classList.remove(f2.CSS.noHover); } }; function U$2(e, t = "after") { const n2 = []; let r2; function i(a2) { switch (t) { case "after": return a2.nextElementSibling; case "before": return a2.previousElementSibling; } } for (r2 = i(e); r2 !== null; ) n2.push(r2), r2 = i(r2); return n2.length !== 0 ? n2 : null; } function y$2(e, t = true) { let n2 = e; return e.classList.contains(h$2.item) && (n2 = e.querySelector(`.${h$2.itemChildren}`)), n2 === null ? [] : t ? Array.from(n2.querySelectorAll(`:scope > .${h$2.item}`)) : Array.from(n2.querySelectorAll(`.${h$2.item}`)); } function lr(e) { return e.nextElementSibling === null; } function sr(e) { return e.querySelector(`.${h$2.itemChildren}`) !== null; } function C$3(e) { return e.querySelector(`.${h$2.itemChildren}`); } function K$1(e) { let t = e; e.classList.contains(h$2.item) && (t = C$3(e)), t !== null && y$2(t).length === 0 && t.remove(); } function N$1(e) { return e.querySelector(`.${h$2.itemContent}`); } function E$2(e, t = true) { const n2 = N$1(e); n2 && j$3.focus(n2, t); } let z$1 = class z { /** * Getter method to get current item * @returns current list item or null if caret position is not undefined */ get currentItem() { const t = window.getSelection(); if (!t) return null; let n2 = t.anchorNode; return !n2 || (O$4(n2) || (n2 = n2.parentNode), !n2) || !O$4(n2) ? null : n2.closest(`.${h$2.item}`); } /** * Method that returns nesting level of the current item, null if there is no selection */ get currentItemLevel() { const t = this.currentItem; if (t === null) return null; let n2 = t.parentNode, r2 = 0; for (; n2 !== null && n2 !== this.listWrapper; ) O$4(n2) && n2.classList.contains(h$2.item) && (r2 += 1), n2 = n2.parentNode; return r2 + 1; } /** * Assign all passed params and renderer to relevant class properties * @param params - tool constructor options * @param params.data - previously saved data * @param params.config - user config for Tool * @param params.api - Editor.js API * @param params.readOnly - read-only mode flag * @param renderer - renderer instance initialized in tool class */ constructor({ data: t, config: n2, api: r2, readOnly: i, block: a2 }, l2) { this.config = n2, this.data = t, this.readOnly = i, this.api = r2, this.block = a2, this.renderer = l2; } /** * Function that is responsible for rendering list with contents * @returns Filled with content wrapper element of the list */ render() { return this.listWrapper = this.renderer.renderWrapper(true), this.data.items.length ? this.appendItems(this.data.items, this.listWrapper) : this.appendItems( [ { content: "", meta: {}, items: [] } ], this.listWrapper ), this.readOnly || this.listWrapper.addEventListener( "keydown", (t) => { switch (t.key) { case "Enter": t.shiftKey || this.enterPressed(t); break; case "Backspace": this.backspace(t); break; case "Tab": t.shiftKey ? this.shiftTab(t) : this.addTab(t); break; } }, false ), "start" in this.data.meta && this.data.meta.start !== void 0 && this.changeStartWith(this.data.meta.start), "counterType" in this.data.meta && this.data.meta.counterType !== void 0 && this.changeCounters(this.data.meta.counterType), this.listWrapper; } /** * Function that is responsible for list content saving * @param wrapper - optional argument wrapper * @returns whole list saved data if wrapper not passes, otherwise will return data of the passed wrapper */ save(t) { const n2 = t ?? this.listWrapper, r2 = (l2) => y$2(l2).map((o2) => { const d2 = C$3(o2), u2 = this.renderer.getItemContent(o2), p2 = this.renderer.getItemMeta(o2), g2 = d2 ? r2(d2) : []; return { content: u2, meta: p2, items: g2 }; }), i = n2 ? r2(n2) : []; let a2 = { style: this.data.style, meta: {}, items: i }; return this.data.style === "ordered" && (a2.meta = { start: this.data.meta.start, counterType: this.data.meta.counterType }), a2; } /** * On paste sanitzation config. Allow only tags that are allowed in the Tool. * @returns - config that determines tags supposted by paste handler * @todo - refactor and move to list instance */ static get pasteConfig() { return { tags: ["OL", "UL", "LI"] }; } /** * Method that specified hot to merge two List blocks. * Called by Editor.js by backspace at the beginning of the Block * * Content of the first item of the next List would be merged with deepest item in current list * Other items of the next List would be appended to the current list without any changes in nesting levels * @param data - data of the second list to be merged with current */ merge(t) { const n2 = this.block.holder.querySelectorAll(`.${h$2.item}`), r2 = n2[n2.length - 1], i = N$1(r2); if (r2 === null || i === null || (i.insertAdjacentHTML("beforeend", t.items[0].content), this.listWrapper === void 0)) return; const a2 = y$2(this.listWrapper); if (a2.length === 0) return; const l2 = a2[a2.length - 1]; let s2 = C$3(l2); const o2 = t.items.shift(); o2 !== void 0 && (o2.items.length !== 0 && (s2 === null && (s2 = this.renderer.renderWrapper(false)), this.appendItems(o2.items, s2)), t.items.length > 0 && this.appendItems(t.items, this.listWrapper)); } /** * On paste callback that is fired from Editor. * @param event - event with pasted data * @todo - refactor and move to list instance */ onPaste(t) { const n2 = t.detail.data; this.data = this.pasteHandler(n2); const r2 = this.listWrapper; r2 && r2.parentNode && r2.parentNode.replaceChild(this.render(), r2); } /** * Handle UL, OL and LI tags paste and returns List data * @param element - html element that contains whole list * @todo - refactor and move to list instance */ pasteHandler(t) { const { tagName: n2 } = t; let r2 = "unordered", i; switch (n2) { case "OL": r2 = "ordered", i = "ol"; break; case "UL": case "LI": r2 = "unordered", i = "ul"; } const a2 = { style: r2, meta: {}, items: [] }; r2 === "ordered" && (this.data.meta.counterType = "numeric", this.data.meta.start = 1); const l2 = (s2) => Array.from(s2.querySelectorAll(":scope > li")).map((d2) => { const u2 = d2.querySelector(`:scope > ${i}`), p2 = u2 ? l2(u2) : []; return { content: d2.innerHTML ?? "", meta: {}, items: p2 }; }); return a2.items = l2(t), a2; } /** * Changes ordered list start property value * @param index - new value of the start property */ changeStartWith(t) { this.listWrapper.style.setProperty("counter-reset", `item ${t - 1}`), this.data.meta.start = t; } /** * Changes ordered list counterType property value * @param counterType - new value of the counterType value */ changeCounters(t) { this.listWrapper.style.setProperty("--list-counter-type", t), this.data.meta.counterType = t; } /** * Handles Enter keypress * @param event - keydown */ enterPressed(t) { var s2; const n2 = this.currentItem; if (t.stopPropagation(), t.preventDefault(), t.isComposing || n2 === null) return; const r2 = ((s2 = this.renderer) == null ? void 0 : s2.getItemContent(n2).trim().length) === 0, i = n2.parentNode === this.listWrapper, a2 = n2.previousElementSibling === null, l2 = this.api.blocks.getCurrentBlockIndex(); if (i && r2) if (lr(n2) && !sr(n2)) { a2 ? this.convertItemToDefaultBlock(l2, true) : this.convertItemToDefaultBlock(); return; } else { this.splitList(n2); return; } else if (r2) { this.unshiftItem(n2); return; } else this.splitItem(n2); } /** * Handle backspace * @param event - keydown */ backspace(t) { var r2; const n2 = this.currentItem; if (n2 !== null && j$3.isCaretAtStartOfInput(n2) && ((r2 = window.getSelection()) == null ? void 0 : r2.isCollapsed) !== false) { if (t.stopPropagation(), n2.parentNode === this.listWrapper && n2.previousElementSibling === null) { this.convertFirstItemToDefaultBlock(); return; } t.preventDefault(), this.mergeItemWithPrevious(n2); } } /** * Reduce indentation for current item * @param event - keydown */ shiftTab(t) { t.stopPropagation(), t.preventDefault(), this.currentItem !== null && this.unshiftItem(this.currentItem); } /** * Decrease indentation of the passed item * @param item - list item to be unshifted */ unshiftItem(t) { if (!t.parentNode || !O$4(t.parentNode)) return; const n2 = t.parentNode.closest(`.${h$2.item}`); if (!n2) return; let r2 = C$3(t); if (t.parentElement === null) return; const i = U$2(t); i !== null && (r2 === null && (r2 = this.renderer.renderWrapper(false)), i.forEach((a2) => { r2.appendChild(a2); }), t.appendChild(r2)), n2.after(t), E$2(t, false), K$1(n2); } /** * Method that is used for list splitting and moving trailing items to the new separated list * @param item - current item html element */ splitList(t) { const n2 = y$2(t), r2 = this.block, i = this.api.blocks.getCurrentBlockIndex(); if (n2.length !== 0) { const o2 = n2[0]; this.unshiftItem(o2), E$2(t, false); } if (t.previousElementSibling === null && t.parentNode === this.listWrapper) { this.convertItemToDefaultBlock(i); return; } const a2 = U$2(t); if (a2 === null) return; const l2 = this.renderer.renderWrapper(true); a2.forEach((o2) => { l2.appendChild(o2); }); const s2 = this.save(l2); s2.meta.start = this.data.style == "ordered" ? 1 : void 0, this.api.blocks.insert(r2 == null ? void 0 : r2.name, s2, this.config, i + 1), this.convertItemToDefaultBlock(i + 1), l2.remove(); } /** * Method that is used for splitting item content and moving trailing content to the new sibling item * @param currentItem - current item html element */ splitItem(t) { const [n2, r2] = j$3.getCaretNodeAndOffset(); if (n2 === null) return; const i = N$1(t); let a2; i === null ? a2 = "" : a2 = j$3.getContenteditableSlice(i, n2, r2, "right", true); const l2 = C$3(t), s2 = this.renderItem(a2); t == null || t.after(s2), l2 && s2.appendChild(l2), E$2(s2); } /** * Method that is used for merging current item with previous one * Content of the current item would be appended to the previous item * Current item children would not change nesting level * @param item - current item html element */ mergeItemWithPrevious(t) { const n2 = t.previousElementSibling, r2 = t.parentNode; if (r2 === null || !O$4(r2)) return; const i = r2.closest(`.${h$2.item}`); if (!n2 && !i || n2 && !O$4(n2)) return; let a2; if (n2) { const p2 = y$2(n2, false); p2.length !== 0 && p2.length !== 0 ? a2 = p2[p2.length - 1] : a2 = n2; } else a2 = i; const l2 = this.renderer.getItemContent(t); if (!a2) return; E$2(a2, false); const s2 = N$1(a2); if (s2 === null) return; s2.insertAdjacentHTML("beforeend", l2); const o2 = y$2(t); if (o2.length === 0) { t.remove(), K$1(a2); return; } const d2 = n2 || i, u2 = C$3(d2) ?? this.renderer.renderWrapper(false); n2 ? o2.forEach((p2) => { u2.appendChild(p2); }) : o2.forEach((p2) => { u2.prepend(p2); }), C$3(d2) === null && a2.appendChild(u2), t.remove(); } /** * Add indentation to current item * @param event - keydown */ addTab(t) { var a2; t.stopPropagation(), t.preventDefault(); const n2 = this.currentItem; if (!n2) return; if (((a2 = this.config) == null ? void 0 : a2.maxLevel) !== void 0) { const l2 = this.currentItemLevel; if (l2 !== null && l2 === this.config.maxLevel) return; } const r2 = n2.previousSibling; if (r2 === null || !O$4(r2)) return; const i = C$3(r2); if (i) i.appendChild(n2), y$2(n2).forEach((s2) => { i.appendChild(s2); }); else { const l2 = this.renderer.renderWrapper(false); l2.appendChild(n2), y$2(n2).forEach((o2) => { l2.appendChild(o2); }), r2.appendChild(l2); } K$1(n2), E$2(n2, false); } /** * Convert current item to default block with passed index * @param newBloxkIndex - optional parameter represents index, where would be inseted default block * @param removeList - optional parameter, that represents condition, if List should be removed */ convertItemToDefaultBlock(t, n2) { let r2; const i = this.currentItem, a2 = i !== null ? this.renderer.getItemContent(i) : ""; n2 === true && this.api.blocks.delete(), t !== void 0 ? r2 = this.api.blocks.insert(void 0, { text: a2 }, void 0, t) : r2 = this.api.blocks.insert(), i == null || i.remove(), this.api.caret.setToBlock(r2, "start"); } /** * Convert first item of the list to default block * This method could be called when backspace button pressed at start of the first item of the list * First item of the list would be converted to the paragraph and first item children would be unshifted */ convertFirstItemToDefaultBlock() { const t = this.currentItem; if (t === null) return; const n2 = y$2(t); if (n2.length !== 0) { const l2 = n2[0]; this.unshiftItem(l2), E$2(t); } const r2 = U$2(t), i = this.api.blocks.getCurrentBlockIndex(), a2 = r2 === null; this.convertItemToDefaultBlock(i, a2); } /** * Method that calls render function of the renderer with a necessary item meta cast * @param itemContent - content to be rendered in new item * @param meta - meta used in list item rendering * @returns html element of the rendered item */ renderItem(t, n2) { const r2 = n2 ?? this.renderer.composeDefaultMeta(); switch (true) { case this.renderer instanceof v$2: return this.renderer.renderItem(t, r2); case this.renderer instanceof b$2: return this.renderer.renderItem(t, r2); default: return this.renderer.renderItem(t, r2); } } /** * Renders children list * @param items - list data used in item rendering * @param parentElement - where to append passed items */ appendItems(t, n2) { t.forEach((r2) => { var a2; const i = this.renderItem(r2.content, r2.meta); if (n2.appendChild(i), r2.items.length) { const l2 = (a2 = this.renderer) == null ? void 0 : a2.renderWrapper(false); this.appendItems(r2.items, l2), i.appendChild(l2); } }); } }; const I$3 = { wrapper: `${m$2}-start-with-field`, input: `${m$2}-start-with-field__input`, startWithElementWrapperInvalid: `${m$2}-start-with-field--invalid` }; function or(e, { value: t, placeholder: n2, attributes: r2, sanitize: i }) { const a2 = c$3.make("div", I$3.wrapper), l2 = c$3.make("input", I$3.input, { placeholder: n2, /** * Used to prevent focusing on the input by Tab key * (Popover in the Toolbar lays below the blocks, * so Tab in the last block will focus this hidden input if this property is not set) */ tabIndex: -1, /** * Value of the start property, if it is not specified, then it is set to one */ value: t }); for (const s2 in r2) l2.setAttribute(s2, r2[s2]); return a2.appendChild(l2), l2.addEventListener("input", () => { i !== void 0 && (l2.value = i(l2.value)); const s2 = l2.checkValidity(); !s2 && !a2.classList.contains(I$3.startWithElementWrapperInvalid) && a2.classList.add(I$3.startWithElementWrapperInvalid), s2 && a2.classList.contains(I$3.startWithElementWrapperInvalid) && a2.classList.remove(I$3.startWithElementWrapperInvalid), s2 && e(l2.value); }), a2; } const P$3 = /* @__PURE__ */ new Map([ /** * Value that represents default arabic numbers for counters */ ["Numeric", "numeric"], /** * Value that represents lower roman numbers for counteres */ ["Lower Roman", "lower-roman"], /** * Value that represents upper roman numbers for counters */ ["Upper Roman", "upper-roman"], /** * Value that represents lower alpha characters for counters */ ["Lower Alpha", "lower-alpha"], /** * Value that represents upper alpha characters for counters */ ["Upper Alpha", "upper-alpha"] ]), He$1 = /* @__PURE__ */ new Map([ /** * Value that represents Icon for Numeric counter type */ ["numeric", St$1], /** * Value that represents Icon for Lower Roman counter type */ ["lower-roman", Ot$1], /** * Value that represents Icon for Upper Roman counter type */ ["upper-roman", kt$1], /** * Value that represents Icon for Lower Alpha counter type */ ["lower-alpha", Et$1], /** * Value that represents Icon for Upper Alpha counter type */ ["upper-alpha", _t$1] ]); function ur(e) { return e.replace(/\D+/g, ""); } function cr(e) { return typeof e.items[0] == "string"; } function dr(e) { return !("meta" in e); } function fr(e) { return typeof e.items[0] != "string" && "text" in e.items[0] && "checked" in e.items[0] && typeof e.items[0].text == "string" && typeof e.items[0].checked == "boolean"; } function pr(e) { const t = []; return cr(e) ? (e.items.forEach((n2) => { t.push({ content: n2, meta: {}, items: [] }); }), { style: e.style, meta: {}, items: t }) : fr(e) ? (e.items.forEach((n2) => { t.push({ content: n2.text, meta: { checked: n2.checked }, items: [] }); }), { style: "checklist", meta: {}, items: t }) : dr(e) ? { style: e.style, meta: {}, items: e.items } : structuredClone(e); } let G$1 = class G2 { /** * Notify core that read-only mode is supported */ static get isReadOnlySupported() { return true; } /** * Allow to use native Enter behaviour */ static get enableLineBreaks() { return true; } /** * Get Tool toolbox settings * icon - Tool icon's SVG * title - title to show in toolbox */ static get toolbox() { return [ { icon: $e, title: "Unordered List", data: { style: "unordered" } }, { icon: Be, title: "Ordered List", data: { style: "ordered" } }, { icon: Ae, title: "Checklist", data: { style: "checklist" } } ]; } /** * On paste sanitzation config. Allow only tags that are allowed in the Tool. * @returns - paste config object used in editor */ static get pasteConfig() { return { tags: ["OL", "UL", "LI"] }; } /** * Convert from text to list with import and export list to text */ static get conversionConfig() { return { export: (t) => G2.joinRecursive(t), import: (t, n2) => ({ meta: {}, items: [ { content: t, meta: {}, items: [] } ], style: (n2 == null ? void 0 : n2.defaultStyle) !== void 0 ? n2.defaultStyle : "unordered" }) }; } /** * Get list style name */ get listStyle() { return this.data.style || this.defaultListStyle; } /** * Set list style * @param style - new style to set */ set listStyle(t) { var r2; this.data.style = t, this.changeTabulatorByStyle(); const n2 = this.list.render(); (r2 = this.listElement) == null || r2.replaceWith(n2), this.listElement = n2; } /** * Render plugin`s main Element and fill it with saved data * @param params - tool constructor options * @param params.data - previously saved data * @param params.config - user config for Tool * @param params.api - Editor.js API * @param params.readOnly - read-only mode flag */ constructor({ data: t, config: n2, api: r2, readOnly: i, block: a2 }) { var s2; this.api = r2, this.readOnly = i, this.config = n2, this.block = a2, this.defaultListStyle = ((s2 = this.config) == null ? void 0 : s2.defaultStyle) || "unordered", this.defaultCounterTypes = this.config.counterTypes || Array.from(P$3.values()); const l2 = { style: this.defaultListStyle, meta: {}, items: [] }; this.data = Object.keys(t).length ? pr(t) : l2, this.listStyle === "ordered" && this.data.meta.counterType === void 0 && (this.data.meta.counterType = "numeric"), this.changeTabulatorByStyle(); } /** * Convert from list to text for conversionConfig * @param data - current data of the list * @returns - string of the recursively merged contents of the items of the list */ static joinRecursive(t) { return t.items.map((n2) => `${n2.content} ${G2.joinRecursive(n2)}`).join(""); } /** * Function that is responsible for content rendering * @returns rendered list wrapper with all contents */ render() { return this.listElement = this.list.render(), this.listElement; } /** * Function that is responsible for content saving * @returns formatted content used in editor */ save() { return this.data = this.list.save(), this.data; } /** * Function that is responsible for mergind two lists into one * @param data - data of the next standing list, that should be merged with current */ merge(t) { this.list.merge(t); } /** * Creates Block Tune allowing to change the list style * @returns array of tune configs */ renderSettings() { const t = [ { label: this.api.i18n.t("Unordered"), icon: $e, closeOnActivate: true, isActive: this.listStyle == "unordered", onActivate: () => { this.listStyle = "unordered"; } }, { label: this.api.i18n.t("Ordered"), icon: Be, closeOnActivate: true, isActive: this.listStyle == "ordered", onActivate: () => { this.listStyle = "ordered"; } }, { label: this.api.i18n.t("Checklist"), icon: Ae, closeOnActivate: true, isActive: this.listStyle == "checklist", onActivate: () => { this.listStyle = "checklist"; } } ]; if (this.listStyle === "ordered") { const n2 = or( (a2) => this.changeStartWith(Number(a2)), { value: String(this.data.meta.start ?? 1), placeholder: "", attributes: { required: "true" }, sanitize: (a2) => ur(a2) } ), r2 = [ { label: this.api.i18n.t("Start with"), icon: It$1, children: { items: [ { element: n2, // @ts-expect-error ts(2820) can not use PopoverItem enum from editor.js types type: "html" } ] } } ], i = { label: this.api.i18n.t("Counter type"), icon: He$1.get(this.data.meta.counterType), children: { items: [] } }; P$3.forEach((a2, l2) => { const s2 = P$3.get(l2); this.defaultCounterTypes.includes(s2) && i.children.items.push({ title: this.api.i18n.t(l2), icon: He$1.get(s2), isActive: this.data.meta.counterType === P$3.get(l2), closeOnActivate: true, onActivate: () => { this.changeCounters(P$3.get(l2)); } }); }), i.children.items.length > 1 && r2.push(i), t.push({ type: "separator" }, ...r2); } return t; } /** * On paste callback that is fired from Editor. * @param event - event with pasted data */ onPaste(t) { const { tagName: n2 } = t.detail.data; switch (n2) { case "OL": this.listStyle = "ordered"; break; case "UL": case "LI": this.listStyle = "unordered"; } this.list.onPaste(t); } /** * Handle UL, OL and LI tags paste and returns List data * @param element - html element that contains whole list */ pasteHandler(t) { return this.list.pasteHandler(t); } /** * Changes ordered list counterType property value * @param counterType - new value of the counterType value */ changeCounters(t) { var n2; (n2 = this.list) == null || n2.changeCounters(t), this.data.meta.counterType = t; } /** * Changes ordered list start property value * @param index - new value of the start property */ changeStartWith(t) { var n2; (n2 = this.list) == null || n2.changeStartWith(t), this.data.meta.start = t; } /** * This method allows changing tabulator respectfully to passed style */ changeTabulatorByStyle() { switch (this.listStyle) { case "ordered": this.list = new z$1( { data: this.data, readOnly: this.readOnly, api: this.api, config: this.config, block: this.block }, new v$2(this.readOnly, this.config) ); break; case "unordered": this.list = new z$1( { data: this.data, readOnly: this.readOnly, api: this.api, config: this.config, block: this.block }, new b$2(this.readOnly, this.config) ); break; case "checklist": this.list = new z$1( { data: this.data, readOnly: this.readOnly, api: this.api, config: this.config, block: this.block }, new f$1(this.readOnly, this.config) ); break; } } }; (function() { try { if (typeof document < "u") { var t = document.createElement("style"); t.appendChild(document.createTextNode(".cdx-quote-icon svg{transform:rotate(180deg)}.cdx-quote{margin:0}.cdx-quote__text{min-height:158px;margin-bottom:10px}.cdx-quote [contentEditable=true][data-placeholder]:before{position:absolute;content:attr(data-placeholder);color:#707684;font-weight:400;opacity:0}.cdx-quote [contentEditable=true][data-placeholder]:empty:before{opacity:1}.cdx-quote [contentEditable=true][data-placeholder]:empty:focus:before{opacity:0}.cdx-quote-settings{display:flex}.cdx-quote-settings .cdx-settings-button{width:50%}")), document.head.appendChild(t); } } catch (e) { console.error("vite-plugin-css-injected-by-js", e); } })(); const De = '', He = '', Re = ''; var b$1 = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {}; function Fe(e) { if (e.__esModule) return e; var t = e.default; if (typeof t == "function") { var n2 = function r2() { return this instanceof r2 ? Reflect.construct(t, arguments, this.constructor) : t.apply(this, arguments); }; n2.prototype = t.prototype; } else n2 = {}; return Object.defineProperty(n2, "__esModule", { value: true }), Object.keys(e).forEach(function(r2) { var i = Object.getOwnPropertyDescriptor(e, r2); Object.defineProperty(n2, r2, i.get ? i : { enumerable: true, get: function() { return e[r2]; } }); }), n2; } var v$1 = {}, P$2 = {}, j$2 = {}; Object.defineProperty(j$2, "__esModule", { value: true }); j$2.allInputsSelector = We; function We() { var e = ["text", "password", "email", "number", "search", "tel", "url"]; return "[contenteditable=true], textarea, input:not([type]), " + e.map(function(t) { return 'input[type="'.concat(t, '"]'); }).join(", "); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.allInputsSelector = void 0; var t = j$2; Object.defineProperty(e, "allInputsSelector", { enumerable: true, get: function() { return t.allInputsSelector; } }); })(P$2); var c$2 = {}, T$1 = {}; Object.defineProperty(T$1, "__esModule", { value: true }); T$1.isNativeInput = Ue; function Ue(e) { var t = [ "INPUT", "TEXTAREA" ]; return e && e.tagName ? t.includes(e.tagName) : false; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isNativeInput = void 0; var t = T$1; Object.defineProperty(e, "isNativeInput", { enumerable: true, get: function() { return t.isNativeInput; } }); })(c$2); var ie = {}, C$2 = {}; Object.defineProperty(C$2, "__esModule", { value: true }); C$2.append = qe; function qe(e, t) { Array.isArray(t) ? t.forEach(function(n2) { e.appendChild(n2); }) : e.appendChild(t); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.append = void 0; var t = C$2; Object.defineProperty(e, "append", { enumerable: true, get: function() { return t.append; } }); })(ie); var L$2 = {}, S$2 = {}; Object.defineProperty(S$2, "__esModule", { value: true }); S$2.blockElements = ze; function ze() { return [ "address", "article", "aside", "blockquote", "canvas", "div", "dl", "dt", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "hr", "li", "main", "nav", "noscript", "ol", "output", "p", "pre", "ruby", "section", "table", "tbody", "thead", "tr", "tfoot", "ul", "video" ]; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.blockElements = void 0; var t = S$2; Object.defineProperty(e, "blockElements", { enumerable: true, get: function() { return t.blockElements; } }); })(L$2); var ae = {}, M$1 = {}; Object.defineProperty(M$1, "__esModule", { value: true }); M$1.calculateBaseline = Ge; function Ge(e) { var t = window.getComputedStyle(e), n2 = parseFloat(t.fontSize), r2 = parseFloat(t.lineHeight) || n2 * 1.2, i = parseFloat(t.paddingTop), a2 = parseFloat(t.borderTopWidth), l2 = parseFloat(t.marginTop), u2 = n2 * 0.8, d2 = (r2 - n2) / 2, s2 = l2 + a2 + i + d2 + u2; return s2; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.calculateBaseline = void 0; var t = M$1; Object.defineProperty(e, "calculateBaseline", { enumerable: true, get: function() { return t.calculateBaseline; } }); })(ae); var le = {}, k$1 = {}, w$1 = {}, N = {}; Object.defineProperty(N, "__esModule", { value: true }); N.isContentEditable = Ke; function Ke(e) { return e.contentEditable === "true"; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isContentEditable = void 0; var t = N; Object.defineProperty(e, "isContentEditable", { enumerable: true, get: function() { return t.isContentEditable; } }); })(w$1); Object.defineProperty(k$1, "__esModule", { value: true }); k$1.canSetCaret = Qe; var Xe = c$2, Ye = w$1; function Qe(e) { var t = true; if ((0, Xe.isNativeInput)(e)) switch (e.type) { case "file": case "checkbox": case "radio": case "hidden": case "submit": case "button": case "image": case "reset": t = false; break; } else t = (0, Ye.isContentEditable)(e); return t; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.canSetCaret = void 0; var t = k$1; Object.defineProperty(e, "canSetCaret", { enumerable: true, get: function() { return t.canSetCaret; } }); })(le); var y$1 = {}, I$2 = {}; function Ve(e, t, n2) { const r2 = n2.value !== void 0 ? "value" : "get", i = n2[r2], a2 = `#${t}Cache`; if (n2[r2] = function(...l2) { return this[a2] === void 0 && (this[a2] = i.apply(this, l2)), this[a2]; }, r2 === "get" && n2.set) { const l2 = n2.set; n2.set = function(u2) { delete e[a2], l2.apply(this, u2); }; } return n2; } function ue() { const e = { win: false, mac: false, x11: false, linux: false }, t = Object.keys(e).find((n2) => window.navigator.appVersion.toLowerCase().indexOf(n2) !== -1); return t !== void 0 && (e[t] = true), e; } function A$2(e) { return e != null && e !== "" && (typeof e != "object" || Object.keys(e).length > 0); } function Ze(e) { return !A$2(e); } const Je = () => typeof window < "u" && window.navigator !== null && A$2(window.navigator.platform) && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1); function xe(e) { const t = ue(); return e = e.replace(/shift/gi, "⇧").replace(/backspace/gi, "⌫").replace(/enter/gi, "⏎").replace(/up/gi, "↑").replace(/left/gi, "→").replace(/down/gi, "↓").replace(/right/gi, "←").replace(/escape/gi, "⎋").replace(/insert/gi, "Ins").replace(/delete/gi, "␡").replace(/\+/gi, "+"), t.mac ? e = e.replace(/ctrl|cmd/gi, "⌘").replace(/alt/gi, "⌥") : e = e.replace(/cmd/gi, "Ctrl").replace(/windows/gi, "WIN"), e; } function et(e) { return e[0].toUpperCase() + e.slice(1); } function tt(e) { const t = document.createElement("div"); t.style.position = "absolute", t.style.left = "-999px", t.style.bottom = "-999px", t.innerHTML = e, document.body.appendChild(t); const n2 = window.getSelection(), r2 = document.createRange(); if (r2.selectNode(t), n2 === null) throw new Error("Cannot copy text to clipboard"); n2.removeAllRanges(), n2.addRange(r2), document.execCommand("copy"), document.body.removeChild(t); } function nt(e, t, n2) { let r2; return (...i) => { const a2 = this, l2 = () => { r2 = void 0, n2 !== true && e.apply(a2, i); }, u2 = n2 === true && r2 !== void 0; window.clearTimeout(r2), r2 = window.setTimeout(l2, t), u2 && e.apply(a2, i); }; } function o(e) { return Object.prototype.toString.call(e).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); } function rt(e) { return o(e) === "boolean"; } function oe(e) { return o(e) === "function" || o(e) === "asyncfunction"; } function it(e) { return oe(e) && /^\s*class\s+/.test(e.toString()); } function at(e) { return o(e) === "number"; } function g$1(e) { return o(e) === "object"; } function lt(e) { return Promise.resolve(e) === e; } function ut(e) { return o(e) === "string"; } function ot(e) { return o(e) === "undefined"; } function O$3(e, ...t) { if (!t.length) return e; const n2 = t.shift(); if (g$1(e) && g$1(n2)) for (const r2 in n2) g$1(n2[r2]) ? (e[r2] === void 0 && Object.assign(e, { [r2]: {} }), O$3(e[r2], n2[r2])) : Object.assign(e, { [r2]: n2[r2] }); return O$3(e, ...t); } function st(e, t, n2) { const r2 = `«${t}» is deprecated and will be removed in the next major release. Please use the «${n2}» instead.`; e && console.warn(r2); } function ct(e) { try { return new URL(e).href; } catch { } return e.substring(0, 2) === "//" ? window.location.protocol + e : window.location.origin + e; } function dt(e) { return e > 47 && e < 58 || e === 32 || e === 13 || e === 229 || e > 64 && e < 91 || e > 95 && e < 112 || e > 185 && e < 193 || e > 218 && e < 223; } const ft = { BACKSPACE: 8, TAB: 9, ENTER: 13, SHIFT: 16, CTRL: 17, ALT: 18, ESC: 27, SPACE: 32, LEFT: 37, UP: 38, DOWN: 40, RIGHT: 39, DELETE: 46, META: 91, SLASH: 191 }, pt = { LEFT: 0, WHEEL: 1, RIGHT: 2, BACKWARD: 3, FORWARD: 4 }; class vt { constructor() { this.completed = Promise.resolve(); } /** * Add new promise to queue * @param operation - promise should be added to queue */ add(t) { return new Promise((n2, r2) => { this.completed = this.completed.then(t).then(n2).catch(r2); }); } } function gt(e, t, n2 = void 0) { let r2, i, a2, l2 = null, u2 = 0; n2 || (n2 = {}); const d2 = function() { u2 = n2.leading === false ? 0 : Date.now(), l2 = null, a2 = e.apply(r2, i), l2 === null && (r2 = i = null); }; return function() { const s2 = Date.now(); !u2 && n2.leading === false && (u2 = s2); const f2 = t - (s2 - u2); return r2 = this, i = arguments, f2 <= 0 || f2 > t ? (l2 && (clearTimeout(l2), l2 = null), u2 = s2, a2 = e.apply(r2, i), l2 === null && (r2 = i = null)) : !l2 && n2.trailing !== false && (l2 = setTimeout(d2, f2)), a2; }; } const mt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, PromiseQueue: vt, beautifyShortcut: xe, cacheable: Ve, capitalize: et, copyTextToClipboard: tt, debounce: nt, deepMerge: O$3, deprecationAssert: st, getUserOS: ue, getValidUrl: ct, isBoolean: rt, isClass: it, isEmpty: Ze, isFunction: oe, isIosDevice: Je, isNumber: at, isObject: g$1, isPrintableKey: dt, isPromise: lt, isString: ut, isUndefined: ot, keyCodes: ft, mouseButtons: pt, notEmpty: A$2, throttle: gt, typeOf: o }, Symbol.toStringTag, { value: "Module" })), $ = /* @__PURE__ */ Fe(mt); Object.defineProperty(I$2, "__esModule", { value: true }); I$2.containsOnlyInlineElements = _t; var bt = $, yt = L$2; function _t(e) { var t; (0, bt.isString)(e) ? (t = document.createElement("div"), t.innerHTML = e) : t = e; var n2 = function(r2) { return !(0, yt.blockElements)().includes(r2.tagName.toLowerCase()) && Array.from(r2.children).every(n2); }; return Array.from(t.children).every(n2); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.containsOnlyInlineElements = void 0; var t = I$2; Object.defineProperty(e, "containsOnlyInlineElements", { enumerable: true, get: function() { return t.containsOnlyInlineElements; } }); })(y$1); var se = {}, B$2 = {}, _$1 = {}, D$1 = {}; Object.defineProperty(D$1, "__esModule", { value: true }); D$1.make = ht; function ht(e, t, n2) { var r2; t === void 0 && (t = null), n2 === void 0 && (n2 = {}); var i = document.createElement(e); if (Array.isArray(t)) { var a2 = t.filter(function(u2) { return u2 !== void 0; }); (r2 = i.classList).add.apply(r2, a2); } else t !== null && i.classList.add(t); for (var l2 in n2) Object.prototype.hasOwnProperty.call(n2, l2) && (i[l2] = n2[l2]); return i; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.make = void 0; var t = D$1; Object.defineProperty(e, "make", { enumerable: true, get: function() { return t.make; } }); })(_$1); Object.defineProperty(B$2, "__esModule", { value: true }); B$2.fragmentToString = Ot; var Et = _$1; function Ot(e) { var t = (0, Et.make)("div"); return t.appendChild(e), t.innerHTML; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.fragmentToString = void 0; var t = B$2; Object.defineProperty(e, "fragmentToString", { enumerable: true, get: function() { return t.fragmentToString; } }); })(se); var ce = {}, H$2 = {}; Object.defineProperty(H$2, "__esModule", { value: true }); H$2.getContentLength = jt; var Pt = c$2; function jt(e) { var t, n2; return (0, Pt.isNativeInput)(e) ? e.value.length : e.nodeType === Node.TEXT_NODE ? e.length : (n2 = (t = e.textContent) === null || t === void 0 ? void 0 : t.length) !== null && n2 !== void 0 ? n2 : 0; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.getContentLength = void 0; var t = H$2; Object.defineProperty(e, "getContentLength", { enumerable: true, get: function() { return t.getContentLength; } }); })(ce); var R$3 = {}, F$2 = {}, re = b$1 && b$1.__spreadArray || function(e, t, n2) { if (n2 || arguments.length === 2) for (var r2 = 0, i = t.length, a2; r2 < i; r2++) (a2 || !(r2 in t)) && (a2 || (a2 = Array.prototype.slice.call(t, 0, r2)), a2[r2] = t[r2]); return e.concat(a2 || Array.prototype.slice.call(t)); }; Object.defineProperty(F$2, "__esModule", { value: true }); F$2.getDeepestBlockElements = de; var Tt = y$1; function de(e) { return (0, Tt.containsOnlyInlineElements)(e) ? [e] : Array.from(e.children).reduce(function(t, n2) { return re(re([], t, true), de(n2), true); }, []); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.getDeepestBlockElements = void 0; var t = F$2; Object.defineProperty(e, "getDeepestBlockElements", { enumerable: true, get: function() { return t.getDeepestBlockElements; } }); })(R$3); var fe = {}, W = {}, h$1 = {}, U$1 = {}; Object.defineProperty(U$1, "__esModule", { value: true }); U$1.isLineBreakTag = Ct; function Ct(e) { return [ "BR", "WBR" ].includes(e.tagName); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isLineBreakTag = void 0; var t = U$1; Object.defineProperty(e, "isLineBreakTag", { enumerable: true, get: function() { return t.isLineBreakTag; } }); })(h$1); var E$1 = {}, q$1 = {}; Object.defineProperty(q$1, "__esModule", { value: true }); q$1.isSingleTag = Lt; function Lt(e) { return [ "AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "META", "PARAM", "SOURCE", "TRACK", "WBR" ].includes(e.tagName); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isSingleTag = void 0; var t = q$1; Object.defineProperty(e, "isSingleTag", { enumerable: true, get: function() { return t.isSingleTag; } }); })(E$1); Object.defineProperty(W, "__esModule", { value: true }); W.getDeepestNode = pe; var St = c$2, Mt = h$1, kt = E$1; function pe(e, t) { t === void 0 && (t = false); var n2 = t ? "lastChild" : "firstChild", r2 = t ? "previousSibling" : "nextSibling"; if (e.nodeType === Node.ELEMENT_NODE && e[n2]) { var i = e[n2]; if ((0, kt.isSingleTag)(i) && !(0, St.isNativeInput)(i) && !(0, Mt.isLineBreakTag)(i)) if (i[r2]) i = i[r2]; else if (i.parentNode !== null && i.parentNode[r2]) i = i.parentNode[r2]; else return i.parentNode; return pe(i, t); } return e; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.getDeepestNode = void 0; var t = W; Object.defineProperty(e, "getDeepestNode", { enumerable: true, get: function() { return t.getDeepestNode; } }); })(fe); var ve = {}, z = {}, p = b$1 && b$1.__spreadArray || function(e, t, n2) { if (n2 || arguments.length === 2) for (var r2 = 0, i = t.length, a2; r2 < i; r2++) (a2 || !(r2 in t)) && (a2 || (a2 = Array.prototype.slice.call(t, 0, r2)), a2[r2] = t[r2]); return e.concat(a2 || Array.prototype.slice.call(t)); }; Object.defineProperty(z, "__esModule", { value: true }); z.findAllInputs = $t; var wt = y$1, Nt = R$3, It = P$2, At = c$2; function $t(e) { return Array.from(e.querySelectorAll((0, It.allInputsSelector)())).reduce(function(t, n2) { return (0, At.isNativeInput)(n2) || (0, wt.containsOnlyInlineElements)(n2) ? p(p([], t, true), [n2], false) : p(p([], t, true), (0, Nt.getDeepestBlockElements)(n2), true); }, []); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.findAllInputs = void 0; var t = z; Object.defineProperty(e, "findAllInputs", { enumerable: true, get: function() { return t.findAllInputs; } }); })(ve); var ge = {}, G = {}; Object.defineProperty(G, "__esModule", { value: true }); G.isCollapsedWhitespaces = Bt; function Bt(e) { return !/[^\t\n\r ]/.test(e); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isCollapsedWhitespaces = void 0; var t = G; Object.defineProperty(e, "isCollapsedWhitespaces", { enumerable: true, get: function() { return t.isCollapsedWhitespaces; } }); })(ge); var K = {}, X = {}; Object.defineProperty(X, "__esModule", { value: true }); X.isElement = Ht; var Dt = $; function Ht(e) { return (0, Dt.isNumber)(e) ? false : !!e && !!e.nodeType && e.nodeType === Node.ELEMENT_NODE; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isElement = void 0; var t = X; Object.defineProperty(e, "isElement", { enumerable: true, get: function() { return t.isElement; } }); })(K); var me = {}, Y = {}, Q = {}, V = {}; Object.defineProperty(V, "__esModule", { value: true }); V.isLeaf = Rt; function Rt(e) { return e === null ? false : e.childNodes.length === 0; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isLeaf = void 0; var t = V; Object.defineProperty(e, "isLeaf", { enumerable: true, get: function() { return t.isLeaf; } }); })(Q); var Z = {}, J = {}; Object.defineProperty(J, "__esModule", { value: true }); J.isNodeEmpty = zt; var Ft = h$1, Wt = K, Ut = c$2, qt = E$1; function zt(e, t) { var n2 = ""; return (0, qt.isSingleTag)(e) && !(0, Ft.isLineBreakTag)(e) ? false : ((0, Wt.isElement)(e) && (0, Ut.isNativeInput)(e) ? n2 = e.value : e.textContent !== null && (n2 = e.textContent.replace("​", "")), t !== void 0 && (n2 = n2.replace(new RegExp(t, "g"), "")), n2.trim().length === 0); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isNodeEmpty = void 0; var t = J; Object.defineProperty(e, "isNodeEmpty", { enumerable: true, get: function() { return t.isNodeEmpty; } }); })(Z); Object.defineProperty(Y, "__esModule", { value: true }); Y.isEmpty = Xt; var Gt = Q, Kt = Z; function Xt(e, t) { e.normalize(); for (var n2 = [e]; n2.length > 0; ) { var r2 = n2.shift(); if (r2) { if (e = r2, (0, Gt.isLeaf)(e) && !(0, Kt.isNodeEmpty)(e, t)) return false; n2.push.apply(n2, Array.from(e.childNodes)); } } return true; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isEmpty = void 0; var t = Y; Object.defineProperty(e, "isEmpty", { enumerable: true, get: function() { return t.isEmpty; } }); })(me); var be = {}, x$2 = {}; Object.defineProperty(x$2, "__esModule", { value: true }); x$2.isFragment = Qt; var Yt = $; function Qt(e) { return (0, Yt.isNumber)(e) ? false : !!e && !!e.nodeType && e.nodeType === Node.DOCUMENT_FRAGMENT_NODE; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isFragment = void 0; var t = x$2; Object.defineProperty(e, "isFragment", { enumerable: true, get: function() { return t.isFragment; } }); })(be); var ye = {}, ee = {}; Object.defineProperty(ee, "__esModule", { value: true }); ee.isHTMLString = Zt; var Vt = _$1; function Zt(e) { var t = (0, Vt.make)("div"); return t.innerHTML = e, t.childElementCount > 0; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.isHTMLString = void 0; var t = ee; Object.defineProperty(e, "isHTMLString", { enumerable: true, get: function() { return t.isHTMLString; } }); })(ye); var _e = {}, te = {}; Object.defineProperty(te, "__esModule", { value: true }); te.offset = Jt; function Jt(e) { var t = e.getBoundingClientRect(), n2 = window.pageXOffset || document.documentElement.scrollLeft, r2 = window.pageYOffset || document.documentElement.scrollTop, i = t.top + r2, a2 = t.left + n2; return { top: i, left: a2, bottom: i + t.height, right: a2 + t.width }; } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.offset = void 0; var t = te; Object.defineProperty(e, "offset", { enumerable: true, get: function() { return t.offset; } }); })(_e); var he = {}, ne = {}; Object.defineProperty(ne, "__esModule", { value: true }); ne.prepend = xt; function xt(e, t) { Array.isArray(t) ? (t = t.reverse(), t.forEach(function(n2) { return e.prepend(n2); })) : e.prepend(t); } (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.prepend = void 0; var t = ne; Object.defineProperty(e, "prepend", { enumerable: true, get: function() { return t.prepend; } }); })(he); (function(e) { Object.defineProperty(e, "__esModule", { value: true }), e.prepend = e.offset = e.make = e.isLineBreakTag = e.isSingleTag = e.isNodeEmpty = e.isLeaf = e.isHTMLString = e.isFragment = e.isEmpty = e.isElement = e.isContentEditable = e.isCollapsedWhitespaces = e.findAllInputs = e.isNativeInput = e.allInputsSelector = e.getDeepestNode = e.getDeepestBlockElements = e.getContentLength = e.fragmentToString = e.containsOnlyInlineElements = e.canSetCaret = e.calculateBaseline = e.blockElements = e.append = void 0; var t = P$2; Object.defineProperty(e, "allInputsSelector", { enumerable: true, get: function() { return t.allInputsSelector; } }); var n2 = c$2; Object.defineProperty(e, "isNativeInput", { enumerable: true, get: function() { return n2.isNativeInput; } }); var r2 = ie; Object.defineProperty(e, "append", { enumerable: true, get: function() { return r2.append; } }); var i = L$2; Object.defineProperty(e, "blockElements", { enumerable: true, get: function() { return i.blockElements; } }); var a2 = ae; Object.defineProperty(e, "calculateBaseline", { enumerable: true, get: function() { return a2.calculateBaseline; } }); var l2 = le; Object.defineProperty(e, "canSetCaret", { enumerable: true, get: function() { return l2.canSetCaret; } }); var u2 = y$1; Object.defineProperty(e, "containsOnlyInlineElements", { enumerable: true, get: function() { return u2.containsOnlyInlineElements; } }); var d2 = se; Object.defineProperty(e, "fragmentToString", { enumerable: true, get: function() { return d2.fragmentToString; } }); var s2 = ce; Object.defineProperty(e, "getContentLength", { enumerable: true, get: function() { return s2.getContentLength; } }); var f2 = R$3; Object.defineProperty(e, "getDeepestBlockElements", { enumerable: true, get: function() { return f2.getDeepestBlockElements; } }); var Oe2 = fe; Object.defineProperty(e, "getDeepestNode", { enumerable: true, get: function() { return Oe2.getDeepestNode; } }); var Pe2 = ve; Object.defineProperty(e, "findAllInputs", { enumerable: true, get: function() { return Pe2.findAllInputs; } }); var je2 = ge; Object.defineProperty(e, "isCollapsedWhitespaces", { enumerable: true, get: function() { return je2.isCollapsedWhitespaces; } }); var Te2 = w$1; Object.defineProperty(e, "isContentEditable", { enumerable: true, get: function() { return Te2.isContentEditable; } }); var Ce2 = K; Object.defineProperty(e, "isElement", { enumerable: true, get: function() { return Ce2.isElement; } }); var Le2 = me; Object.defineProperty(e, "isEmpty", { enumerable: true, get: function() { return Le2.isEmpty; } }); var Se2 = be; Object.defineProperty(e, "isFragment", { enumerable: true, get: function() { return Se2.isFragment; } }); var Me2 = ye; Object.defineProperty(e, "isHTMLString", { enumerable: true, get: function() { return Me2.isHTMLString; } }); var ke2 = Q; Object.defineProperty(e, "isLeaf", { enumerable: true, get: function() { return ke2.isLeaf; } }); var we2 = Z; Object.defineProperty(e, "isNodeEmpty", { enumerable: true, get: function() { return we2.isNodeEmpty; } }); var Ne2 = h$1; Object.defineProperty(e, "isLineBreakTag", { enumerable: true, get: function() { return Ne2.isLineBreakTag; } }); var Ie2 = E$1; Object.defineProperty(e, "isSingleTag", { enumerable: true, get: function() { return Ie2.isSingleTag; } }); var Ae2 = _$1; Object.defineProperty(e, "make", { enumerable: true, get: function() { return Ae2.make; } }); var $e2 = _e; Object.defineProperty(e, "offset", { enumerable: true, get: function() { return $e2.offset; } }); var Be2 = he; Object.defineProperty(e, "prepend", { enumerable: true, get: function() { return Be2.prepend; } }); })(v$1); var Ee = /* @__PURE__ */ ((e) => (e.Left = "left", e.Center = "center", e))(Ee || {}); let m$1 = class m2 { /** * Render plugin`s main Element and fill it with saved data * @param params - Quote Tool constructor params * @param params.data - previously saved data * @param params.config - user config for Tool * @param params.api - editor.js api * @param params.readOnly - read only mode flag */ constructor({ data: t, config: n2, api: r2, readOnly: i, block: a2 }) { const { DEFAULT_ALIGNMENT: l2 } = m2; this.api = r2, this.readOnly = i, this.quotePlaceholder = r2.i18n.t((n2 == null ? void 0 : n2.quotePlaceholder) ?? m2.DEFAULT_QUOTE_PLACEHOLDER), this.captionPlaceholder = r2.i18n.t((n2 == null ? void 0 : n2.captionPlaceholder) ?? m2.DEFAULT_CAPTION_PLACEHOLDER), this.data = { text: t.text || "", caption: t.caption || "", alignment: Object.values(Ee).includes(t.alignment) ? t.alignment : (n2 == null ? void 0 : n2.defaultAlignment) ?? l2 }, this.css = { baseClass: this.api.styles.block, wrapper: "cdx-quote", text: "cdx-quote__text", input: this.api.styles.input, caption: "cdx-quote__caption" }, this.block = a2; } /** * Notify core that read-only mode is supported * @returns true */ static get isReadOnlySupported() { return true; } /** * Get Tool toolbox settings * icon - Tool icon's SVG * title - title to show in toolbox * @returns icon and title of the toolbox */ static get toolbox() { return { icon: Re, title: "Quote" }; } /** * Empty Quote is not empty Block * @returns true */ static get contentless() { return true; } /** * Allow to press Enter inside the Quote * @returns true */ static get enableLineBreaks() { return true; } /** * Default placeholder for quote text * @returns 'Enter a quote' */ static get DEFAULT_QUOTE_PLACEHOLDER() { return "Enter a quote"; } /** * Default placeholder for quote caption * @returns 'Enter a caption' */ static get DEFAULT_CAPTION_PLACEHOLDER() { return "Enter a caption"; } /** * Default quote alignment * @returns Alignment.Left */ static get DEFAULT_ALIGNMENT() { return "left"; } /** * Allow Quote to be converted to/from other blocks * @returns conversion config object */ static get conversionConfig() { return { /** * To create Quote data from string, simple fill 'text' property */ import: "text", /** * To create string from Quote data, concatenate text and caption * @param quoteData - Quote data object * @returns string */ export: function(t) { return t.caption ? `${t.text} — ${t.caption}` : t.text; } }; } /** * Tool`s styles * @returns CSS classes names */ get CSS() { return { baseClass: this.api.styles.block, wrapper: "cdx-quote", text: "cdx-quote__text", input: this.api.styles.input, caption: "cdx-quote__caption" }; } /** * Tool`s settings properties * @returns settings properties */ get settings() { return [ { name: "left", icon: He }, { name: "center", icon: De } ]; } /** * Create Quote Tool container with inputs * @returns blockquote DOM element - Quote Tool container */ render() { const t = v$1.make("blockquote", [ this.css.baseClass, this.css.wrapper ]), n2 = v$1.make("div", [this.css.input, this.css.text], { contentEditable: !this.readOnly, innerHTML: this.data.text }), r2 = v$1.make("div", [this.css.input, this.css.caption], { contentEditable: !this.readOnly, innerHTML: this.data.caption }); return n2.dataset.placeholder = this.quotePlaceholder, r2.dataset.placeholder = this.captionPlaceholder, t.appendChild(n2), t.appendChild(r2), t; } /** * Extract Quote data from Quote Tool element * @param quoteElement - Quote DOM element to save * @returns Quote data object */ save(t) { const n2 = t.querySelector(`.${this.css.text}`), r2 = t.querySelector(`.${this.css.caption}`); return Object.assign(this.data, { text: (n2 == null ? void 0 : n2.innerHTML) ?? "", caption: (r2 == null ? void 0 : r2.innerHTML) ?? "" }); } /** * Sanitizer rules * @returns sanitizer rules */ static get sanitize() { return { text: { br: true }, caption: { br: true }, alignment: {} }; } /** * Create wrapper for Tool`s settings buttons: * 1. Left alignment * 2. Center alignment * @returns settings menu */ renderSettings() { const t = (n2) => n2 && n2[0].toUpperCase() + n2.slice(1); return this.settings.map((n2) => ({ icon: n2.icon, label: this.api.i18n.t(`Align ${t(n2.name)}`), onActivate: () => this._toggleTune(n2.name), isActive: this.data.alignment === n2.name, closeOnActivate: true })); } /** * Toggle quote`s alignment * @param tune - alignment */ _toggleTune(t) { this.data.alignment = t, this.block.dispatchChange(); } }; (function() { try { if (typeof document < "u") { var e = document.createElement("style"); e.appendChild(document.createTextNode(".ce-code__textarea{min-height:200px;font-family:Menlo,Monaco,Consolas,Courier New,monospace;color:#41314e;line-height:1.6em;font-size:12px;background:#f8f7fa;border:1px solid #f1f1f4;box-shadow:none;white-space:pre;word-wrap:normal;overflow-x:auto;resize:vertical}")), document.head.appendChild(e); } } catch (o2) { console.error("vite-plugin-css-injected-by-js", o2); } })(); function c$1(l2, t) { let a2 = ""; for (; a2 !== ` ` && t > 0; ) t = t - 1, a2 = l2.substr(t, 1); return a2 === ` ` && (t += 1), t; } const h = ''; /** * CodeTool for Editor.js * @version 2.0.0 * @license MIT */ class d { /** * Notify core that read-only mode is supported * @returns true if read-only mode is supported */ static get isReadOnlySupported() { return true; } /** * Allows pressing Enter key to create line breaks inside the CodeTool textarea * This enables multi-line input within the code editor. * @returns true if line breaks are allowed in the textarea */ static get enableLineBreaks() { return true; } /** * Render plugin`s main Element and fill it with saved data * @param options - tool constricting options * @param options.data — previously saved plugin code * @param options.config - user config for Tool * @param options.api - Editor.js API * @param options.readOnly - read only mode flag */ constructor({ data: t, config: e, api: a2, readOnly: s2 }) { this.api = a2, this.readOnly = s2, this.placeholder = this.api.i18n.t(e.placeholder || d.DEFAULT_PLACEHOLDER), this.CSS = { baseClass: this.api.styles.block, input: this.api.styles.input, wrapper: "ce-code", textarea: "ce-code__textarea" }, this.nodes = { holder: null, textarea: null }, this.data = { code: t.code ?? "" }, this.nodes.holder = this.drawView(); } /** * Return Tool's view * @returns this.nodes.holder - Code's wrapper */ render() { return this.nodes.holder; } /** * Extract Tool's data from the view * @param codeWrapper - CodeTool's wrapper, containing textarea with code * @returns - saved plugin code */ save(t) { return { code: t.querySelector("textarea").value }; } /** * onPaste callback fired from Editor`s core * @param event - event with pasted content */ onPaste(t) { switch (t.type) { case "tag": { const e = t.detail.data; this.handleHTMLPaste(e); break; } } } /** * Returns Tool`s data from private property * @returns */ get data() { return this._data; } /** * Set Tool`s data to private property and update view * @param data - saved tool data */ set data(t) { this._data = t, this.nodes.textarea && (this.nodes.textarea.value = t.code); } /** * Get Tool toolbox settings. * Provides the icon and title to display in the toolbox for the CodeTool. * @returns An object containing: * - icon: SVG representation of the Tool's icon * - title: Title to show in the toolbox */ static get toolbox() { return { icon: h, title: "Code" }; } /** * Default placeholder for CodeTool's textarea * @returns */ static get DEFAULT_PLACEHOLDER() { return "Enter a code"; } /** * Used by Editor.js paste handling API. * Provides configuration to handle CODE tag. * @returns */ static get pasteConfig() { return { tags: ["pre"] }; } /** * Automatic sanitize config * @returns */ static get sanitize() { return { code: true // Allow HTML tags }; } /** * Handles Tab key pressing (adds/removes indentations) * @param event - keydown */ tabHandler(t) { t.stopPropagation(), t.preventDefault(); const e = t.target, a2 = t.shiftKey, s2 = e.selectionStart, r2 = e.value, n2 = " "; let i; if (!a2) i = s2 + n2.length, e.value = r2.substring(0, s2) + n2 + r2.substring(s2); else { const o2 = c$1(r2, s2); if (r2.substr(o2, n2.length) !== n2) return; e.value = r2.substring(0, o2) + r2.substring(o2 + n2.length), i = s2 - n2.length; } e.setSelectionRange(i, i); } /** * Create Tool's view * @returns */ drawView() { const t = document.createElement("div"), e = document.createElement("textarea"); return t.classList.add(this.CSS.baseClass, this.CSS.wrapper), e.classList.add(this.CSS.textarea, this.CSS.input), e.value = this.data.code, e.placeholder = this.placeholder, this.readOnly && (e.disabled = true), t.appendChild(e), e.addEventListener("keydown", (a2) => { switch (a2.code) { case "Tab": this.tabHandler(a2); break; } }), this.nodes.textarea = e, t; } /** * Extracts the code content from the pasted element's innerHTML and populates the tool's data. * @param element - pasted HTML element */ handleHTMLPaste(t) { this.data = { code: t.innerHTML }; } } (function() { var r2; try { if (typeof document < "u") { var o2 = document.createElement("style"); o2.nonce = (r2 = document.head.querySelector("meta[property=csp-nonce]")) == null ? void 0 : r2.content, o2.appendChild(document.createTextNode('.tc-wrap{--color-background:#f9f9fb;--color-text-secondary:#7b7e89;--color-border:#e8e8eb;--cell-size:34px;--toolbox-icon-size:18px;--toolbox-padding:6px;--toolbox-aiming-field-size:calc(var(--toolbox-icon-size) + var(--toolbox-padding)*2);border-left:0;position:relative;height:100%;width:100%;margin-top:var(--toolbox-icon-size);box-sizing:border-box;display:grid;grid-template-columns:calc(100% - var(--cell-size)) var(--cell-size);z-index:0}.tc-wrap--readonly{grid-template-columns:100% var(--cell-size)}.tc-wrap svg{vertical-align:top}@media print{.tc-wrap{border-left-color:var(--color-border);border-left-style:solid;border-left-width:1px;grid-template-columns:100% var(--cell-size)}}@media print{.tc-wrap .tc-row:after{display:none}}.tc-table{position:relative;width:100%;height:100%;display:grid;font-size:14px;border-top:1px solid var(--color-border);line-height:1.4}.tc-table:after{width:calc(var(--cell-size));height:100%;left:calc(var(--cell-size)*-1);top:0}.tc-table:after,.tc-table:before{position:absolute;content:""}.tc-table:before{width:100%;height:var(--toolbox-aiming-field-size);top:calc(var(--toolbox-aiming-field-size)*-1);left:0}.tc-table--heading .tc-row:first-child{font-weight:600;border-bottom:2px solid var(--color-border);position:sticky;top:0;z-index:2;background:var(--color-background)}.tc-table--heading .tc-row:first-child [contenteditable]:empty:before{content:attr(heading);color:var(--color-text-secondary)}.tc-table--heading .tc-row:first-child:after{bottom:-2px;border-bottom:2px solid var(--color-border)}.tc-add-column,.tc-add-row{display:flex;color:var(--color-text-secondary)}@media print{.tc-add{display:none}}.tc-add-column{display:grid;border-top:1px solid var(--color-border);grid-template-columns:var(--cell-size);grid-auto-rows:var(--cell-size);place-items:center}.tc-add-column svg{padding:5px;position:sticky;top:0;background-color:var(--color-background)}.tc-add-column--disabled{visibility:hidden}@media print{.tc-add-column{display:none}}.tc-add-row{height:var(--cell-size);align-items:center;padding-left:4px;position:relative}.tc-add-row--disabled{display:none}.tc-add-row:before{content:"";position:absolute;right:calc(var(--cell-size)*-1);width:var(--cell-size);height:100%}@media print{.tc-add-row{display:none}}.tc-add-column,.tc-add-row{transition:0s;cursor:pointer;will-change:background-color}.tc-add-column:hover,.tc-add-row:hover{transition:background-color .1s ease;background-color:var(--color-background)}.tc-add-row{margin-top:1px}.tc-add-row:hover:before{transition:.1s;background-color:var(--color-background)}.tc-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(10px,1fr));position:relative;border-bottom:1px solid var(--color-border)}.tc-row:after{content:"";pointer-events:none;position:absolute;width:var(--cell-size);height:100%;bottom:-1px;right:calc(var(--cell-size)*-1);border-bottom:1px solid var(--color-border)}.tc-row--selected{background:var(--color-background)}.tc-row--selected:after{background:var(--color-background)}.tc-cell{border-right:1px solid var(--color-border);padding:6px 12px;overflow:hidden;outline:none;line-break:normal}.tc-cell--selected{background:var(--color-background)}.tc-wrap--readonly .tc-row:after{display:none}.tc-toolbox{--toolbox-padding:6px;--popover-margin:30px;--toggler-click-zone-size:30px;--toggler-dots-color:#7b7e89;--toggler-dots-color-hovered:#1d202b;position:absolute;cursor:pointer;z-index:1;opacity:0;transition:opacity .1s;will-change:left,opacity}.tc-toolbox--column{top:calc(var(--toggler-click-zone-size)*-1);transform:translate(calc(var(--toggler-click-zone-size)*-1/2));will-change:left,opacity}.tc-toolbox--row{left:calc(var(--popover-margin)*-1);transform:translateY(calc(var(--toggler-click-zone-size)*-1/2));margin-top:-1px;will-change:top,opacity}.tc-toolbox--showed{opacity:1}.tc-toolbox .tc-popover{position:absolute;top:0;left:var(--popover-margin)}.tc-toolbox__toggler{display:flex;align-items:center;justify-content:center;width:var(--toggler-click-zone-size);height:var(--toggler-click-zone-size);color:var(--toggler-dots-color);opacity:0;transition:opacity .15s ease;will-change:opacity}.tc-toolbox__toggler:hover{color:var(--toggler-dots-color-hovered)}.tc-toolbox__toggler svg{fill:currentColor}.tc-wrap:hover .tc-toolbox__toggler{opacity:1}.tc-settings .cdx-settings-button{width:50%;margin:0}.tc-popover{--color-border:#eaeaea;--color-background:#fff;--color-background-hover:rgba(232,232,235,.49);--color-background-confirm:#e24a4a;--color-background-confirm-hover:#d54040;--color-text-confirm:#fff;background:var(--color-background);border:1px solid var(--color-border);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;padding:6px;display:none;will-change:opacity,transform}.tc-popover--opened{display:block;animation:menuShowing .1s cubic-bezier(.215,.61,.355,1) forwards}.tc-popover__item{display:flex;align-items:center;padding:2px 14px 2px 2px;border-radius:5px;cursor:pointer;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tc-popover__item:hover{background:var(--color-background-hover)}.tc-popover__item:not(:last-of-type){margin-bottom:2px}.tc-popover__item-icon{display:inline-flex;width:26px;height:26px;align-items:center;justify-content:center;background:var(--color-background);border-radius:5px;border:1px solid var(--color-border);margin-right:8px}.tc-popover__item-label{line-height:22px;font-size:14px;font-weight:500}.tc-popover__item--confirm{background:var(--color-background-confirm);color:var(--color-text-confirm)}.tc-popover__item--confirm:hover{background-color:var(--color-background-confirm-hover)}.tc-popover__item--confirm .tc-popover__item-icon{background:var(--color-background-confirm);border-color:#0000001a}.tc-popover__item--confirm .tc-popover__item-icon svg{transition:transform .2s ease-in;transform:rotate(90deg) scale(1.2)}.tc-popover__item--hidden{display:none}@keyframes menuShowing{0%{opacity:0;transform:translateY(-8px) scale(.9)}70%{opacity:1;transform:translateY(2px)}to{transform:translateY(0)}}')), document.head.appendChild(o2); } } catch (e) { console.error("vite-plugin-css-injected-by-js", e); } })(); function c(d2, t, e = {}) { const o2 = document.createElement(d2); Array.isArray(t) ? o2.classList.add(...t) : t && o2.classList.add(t); for (const i in e) Object.prototype.hasOwnProperty.call(e, i) && (o2[i] = e[i]); return o2; } function f(d2) { const t = d2.getBoundingClientRect(); return { y1: Math.floor(t.top + window.pageYOffset), x1: Math.floor(t.left + window.pageXOffset), x2: Math.floor(t.right + window.pageXOffset), y2: Math.floor(t.bottom + window.pageYOffset) }; } function g(d2, t) { const e = f(d2), o2 = f(t); return { fromTopBorder: o2.y1 - e.y1, fromLeftBorder: o2.x1 - e.x1, fromRightBorder: e.x2 - o2.x2, fromBottomBorder: e.y2 - o2.y2 }; } function k(d2, t) { const e = d2.getBoundingClientRect(), { width: o2, height: i, x: n2, y: r2 } = e, { clientX: h2, clientY: l2 } = t; return { width: o2, height: i, x: h2 - n2, y: l2 - r2 }; } function m(d2, t) { return t.parentNode.insertBefore(d2, t); } function C$1(d2, t = true) { const e = document.createRange(), o2 = window.getSelection(); e.selectNodeContents(d2), e.collapse(t), o2.removeAllRanges(), o2.addRange(e); } class a { /** * @param {object} options - constructor options * @param {PopoverItem[]} options.items - constructor options */ constructor({ items: t }) { this.items = t, this.wrapper = void 0, this.itemEls = []; } /** * Set of CSS classnames used in popover * * @returns {object} */ static get CSS() { return { popover: "tc-popover", popoverOpened: "tc-popover--opened", item: "tc-popover__item", itemHidden: "tc-popover__item--hidden", itemConfirmState: "tc-popover__item--confirm", itemIcon: "tc-popover__item-icon", itemLabel: "tc-popover__item-label" }; } /** * Returns the popover element * * @returns {Element} */ render() { return this.wrapper = c("div", a.CSS.popover), this.items.forEach((t, e) => { const o2 = c("div", a.CSS.item), i = c("div", a.CSS.itemIcon, { innerHTML: t.icon }), n2 = c("div", a.CSS.itemLabel, { textContent: t.label }); o2.dataset.index = e, o2.appendChild(i), o2.appendChild(n2), this.wrapper.appendChild(o2), this.itemEls.push(o2); }), this.wrapper.addEventListener("click", (t) => { this.popoverClicked(t); }), this.wrapper; } /** * Popover wrapper click listener * Used to delegate clicks in items * * @returns {void} */ popoverClicked(t) { const e = t.target.closest(`.${a.CSS.item}`); if (!e) return; const o2 = e.dataset.index, i = this.items[o2]; if (i.confirmationRequired && !this.hasConfirmationState(e)) { this.setConfirmationState(e); return; } i.onClick(); } /** * Enable the confirmation state on passed item * * @returns {void} */ setConfirmationState(t) { t.classList.add(a.CSS.itemConfirmState); } /** * Disable the confirmation state on passed item * * @returns {void} */ clearConfirmationState(t) { t.classList.remove(a.CSS.itemConfirmState); } /** * Check if passed item has the confirmation state * * @returns {boolean} */ hasConfirmationState(t) { return t.classList.contains(a.CSS.itemConfirmState); } /** * Return an opening state * * @returns {boolean} */ get opened() { return this.wrapper.classList.contains(a.CSS.popoverOpened); } /** * Opens the popover * * @returns {void} */ open() { this.items.forEach((t, e) => { typeof t.hideIf == "function" && this.itemEls[e].classList.toggle(a.CSS.itemHidden, t.hideIf()); }), this.wrapper.classList.add(a.CSS.popoverOpened); } /** * Closes the popover * * @returns {void} */ close() { this.wrapper.classList.remove(a.CSS.popoverOpened), this.itemEls.forEach((t) => { this.clearConfirmationState(t); }); } } const R$2 = '', b = '', x$1 = '', S$1 = '', y = '', L$1 = '', M = '', v = '', O$2 = '', T = '', H$1 = '', A$1 = ''; class w { /** * Creates toolbox buttons and toolbox menus * * @param {Object} config * @param {any} config.api - Editor.js api * @param {PopoverItem[]} config.items - Editor.js api * @param {function} config.onOpen - callback fired when the Popover is opening * @param {function} config.onClose - callback fired when the Popover is closing * @param {string} config.cssModifier - the modifier for the Toolbox. Allows to add some specific styles. */ constructor({ api: t, items: e, onOpen: o2, onClose: i, cssModifier: n2 = "" }) { this.api = t, this.items = e, this.onOpen = o2, this.onClose = i, this.cssModifier = n2, this.popover = null, this.wrapper = this.createToolbox(); } /** * Style classes */ static get CSS() { return { toolbox: "tc-toolbox", toolboxShowed: "tc-toolbox--showed", toggler: "tc-toolbox__toggler" }; } /** * Returns rendered Toolbox element */ get element() { return this.wrapper; } /** * Creating a toolbox to open menu for a manipulating columns * * @returns {Element} */ createToolbox() { const t = c("div", [ w.CSS.toolbox, this.cssModifier ? `${w.CSS.toolbox}--${this.cssModifier}` : "" ]); t.dataset.mutationFree = "true"; const e = this.createPopover(), o2 = this.createToggler(); return t.appendChild(o2), t.appendChild(e), t; } /** * Creates the Toggler * * @returns {Element} */ createToggler() { const t = c("div", w.CSS.toggler, { innerHTML: M }); return t.addEventListener("click", () => { this.togglerClicked(); }), t; } /** * Creates the Popover instance and render it * * @returns {Element} */ createPopover() { return this.popover = new a({ items: this.items }), this.popover.render(); } /** * Toggler click handler. Opens/Closes the popover * * @returns {void} */ togglerClicked() { this.popover.opened ? (this.popover.close(), this.onClose()) : (this.popover.open(), this.onOpen()); } /** * Shows the Toolbox * * @param {function} computePositionMethod - method that returns the position coordinate * @returns {void} */ show(t) { const e = t(); Object.entries(e).forEach(([o2, i]) => { this.wrapper.style[o2] = i; }), this.wrapper.classList.add(w.CSS.toolboxShowed); } /** * Hides the Toolbox * * @returns {void} */ hide() { this.popover.close(), this.wrapper.classList.remove(w.CSS.toolboxShowed); } } function B$1(d2, t) { let e = 0; return function(...o2) { const i = (/* @__PURE__ */ new Date()).getTime(); if (!(i - e < d2)) return e = i, t(...o2); }; } const s = { wrapper: "tc-wrap", wrapperReadOnly: "tc-wrap--readonly", table: "tc-table", row: "tc-row", withHeadings: "tc-table--heading", rowSelected: "tc-row--selected", cell: "tc-cell", cellSelected: "tc-cell--selected", addRow: "tc-add-row", addRowDisabled: "tc-add-row--disabled", addColumn: "tc-add-column", addColumnDisabled: "tc-add-column--disabled" }; class E { /** * Creates * * @constructor * @param {boolean} readOnly - read-only mode flag * @param {object} api - Editor.js API * @param {TableData} data - Editor.js API * @param {TableConfig} config - Editor.js API */ constructor(t, e, o2, i) { this.readOnly = t, this.api = e, this.data = o2, this.config = i, this.wrapper = null, this.table = null, this.toolboxColumn = this.createColumnToolbox(), this.toolboxRow = this.createRowToolbox(), this.createTableWrapper(), this.hoveredRow = 0, this.hoveredColumn = 0, this.selectedRow = 0, this.selectedColumn = 0, this.tunes = { withHeadings: false }, this.resize(), this.fill(), this.focusedCell = { row: 0, column: 0 }, this.documentClicked = (n2) => { const r2 = n2.target.closest(`.${s.table}`) !== null, h2 = n2.target.closest(`.${s.wrapper}`) === null; (r2 || h2) && this.hideToolboxes(); const u2 = n2.target.closest(`.${s.addRow}`), p2 = n2.target.closest(`.${s.addColumn}`); u2 && u2.parentNode === this.wrapper ? (this.addRow(void 0, true), this.hideToolboxes()) : p2 && p2.parentNode === this.wrapper && (this.addColumn(void 0, true), this.hideToolboxes()); }, this.readOnly || this.bindEvents(); } /** * Returns the rendered table wrapper * * @returns {Element} */ getWrapper() { return this.wrapper; } /** * Hangs the necessary handlers to events */ bindEvents() { document.addEventListener("click", this.documentClicked), this.table.addEventListener("mousemove", B$1(150, (t) => this.onMouseMoveInTable(t)), { passive: true }), this.table.onkeypress = (t) => this.onKeyPressListener(t), this.table.addEventListener("keydown", (t) => this.onKeyDownListener(t)), this.table.addEventListener("focusin", (t) => this.focusInTableListener(t)); } /** * Configures and creates the toolbox for manipulating with columns * * @returns {Toolbox} */ createColumnToolbox() { return new w({ api: this.api, cssModifier: "column", items: [ { label: this.api.i18n.t("Add column to left"), icon: S$1, hideIf: () => this.numberOfColumns === this.config.maxcols, onClick: () => { this.addColumn(this.selectedColumn, true), this.hideToolboxes(); } }, { label: this.api.i18n.t("Add column to right"), icon: y, hideIf: () => this.numberOfColumns === this.config.maxcols, onClick: () => { this.addColumn(this.selectedColumn + 1, true), this.hideToolboxes(); } }, { label: this.api.i18n.t("Delete column"), icon: b, hideIf: () => this.numberOfColumns === 1, confirmationRequired: true, onClick: () => { this.deleteColumn(this.selectedColumn), this.hideToolboxes(); } } ], onOpen: () => { this.selectColumn(this.hoveredColumn), this.hideRowToolbox(); }, onClose: () => { this.unselectColumn(); } }); } /** * Configures and creates the toolbox for manipulating with rows * * @returns {Toolbox} */ createRowToolbox() { return new w({ api: this.api, cssModifier: "row", items: [ { label: this.api.i18n.t("Add row above"), icon: L$1, hideIf: () => this.numberOfRows === this.config.maxrows, onClick: () => { this.addRow(this.selectedRow, true), this.hideToolboxes(); } }, { label: this.api.i18n.t("Add row below"), icon: x$1, hideIf: () => this.numberOfRows === this.config.maxrows, onClick: () => { this.addRow(this.selectedRow + 1, true), this.hideToolboxes(); } }, { label: this.api.i18n.t("Delete row"), icon: b, hideIf: () => this.numberOfRows === 1, confirmationRequired: true, onClick: () => { this.deleteRow(this.selectedRow), this.hideToolboxes(); } } ], onOpen: () => { this.selectRow(this.hoveredRow), this.hideColumnToolbox(); }, onClose: () => { this.unselectRow(); } }); } /** * When you press enter it moves the cursor down to the next row * or creates it if the click occurred on the last one */ moveCursorToNextRow() { this.focusedCell.row !== this.numberOfRows ? (this.focusedCell.row += 1, this.focusCell(this.focusedCell)) : (this.addRow(), this.focusedCell.row += 1, this.focusCell(this.focusedCell), this.updateToolboxesPosition(0, 0)); } /** * Get table cell by row and col index * * @param {number} row - cell row coordinate * @param {number} column - cell column coordinate * @returns {HTMLElement} */ getCell(t, e) { return this.table.querySelectorAll(`.${s.row}:nth-child(${t}) .${s.cell}`)[e - 1]; } /** * Get table row by index * * @param {number} row - row coordinate * @returns {HTMLElement} */ getRow(t) { return this.table.querySelector(`.${s.row}:nth-child(${t})`); } /** * The parent of the cell which is the row * * @param {HTMLElement} cell - cell element * @returns {HTMLElement} */ getRowByCell(t) { return t.parentElement; } /** * Ger row's first cell * * @param {Element} row - row to find its first cell * @returns {Element} */ getRowFirstCell(t) { return t.querySelector(`.${s.cell}:first-child`); } /** * Set the sell's content by row and column numbers * * @param {number} row - cell row coordinate * @param {number} column - cell column coordinate * @param {string} content - cell HTML content */ setCellContent(t, e, o2) { const i = this.getCell(t, e); i.innerHTML = o2; } /** * Add column in table on index place * Add cells in each row * * @param {number} columnIndex - number in the array of columns, where new column to insert, -1 if insert at the end * @param {boolean} [setFocus] - pass true to focus the first cell */ addColumn(t = -1, e = false) { var n2; let o2 = this.numberOfColumns; if (this.config && this.config.maxcols && this.numberOfColumns >= this.config.maxcols) return; for (let r2 = 1; r2 <= this.numberOfRows; r2++) { let h2; const l2 = this.createCell(); if (t > 0 && t <= o2 ? (h2 = this.getCell(r2, t), m(l2, h2)) : h2 = this.getRow(r2).appendChild(l2), r2 === 1) { const u2 = this.getCell(r2, t > 0 ? t : o2 + 1); u2 && e && C$1(u2); } } const i = this.wrapper.querySelector(`.${s.addColumn}`); (n2 = this.config) != null && n2.maxcols && this.numberOfColumns > this.config.maxcols - 1 && i && i.classList.add(s.addColumnDisabled), this.addHeadingAttrToFirstRow(); } /** * Add row in table on index place * * @param {number} index - number in the array of rows, where new column to insert, -1 if insert at the end * @param {boolean} [setFocus] - pass true to focus the inserted row * @returns {HTMLElement} row */ addRow(t = -1, e = false) { let o2, i = c("div", s.row); this.tunes.withHeadings && this.removeHeadingAttrFromFirstRow(); let n2 = this.numberOfColumns; if (this.config && this.config.maxrows && this.numberOfRows >= this.config.maxrows && h2) return; if (t > 0 && t <= this.numberOfRows) { let l2 = this.getRow(t); o2 = m(i, l2); } else o2 = this.table.appendChild(i); this.fillRow(o2, n2), this.tunes.withHeadings && this.addHeadingAttrToFirstRow(); const r2 = this.getRowFirstCell(o2); r2 && e && C$1(r2); const h2 = this.wrapper.querySelector(`.${s.addRow}`); return this.config && this.config.maxrows && this.numberOfRows >= this.config.maxrows && h2 && h2.classList.add(s.addRowDisabled), o2; } /** * Delete a column by index * * @param {number} index */ deleteColumn(t) { for (let o2 = 1; o2 <= this.numberOfRows; o2++) { const i = this.getCell(o2, t); if (!i) return; i.remove(); } const e = this.wrapper.querySelector(`.${s.addColumn}`); e && e.classList.remove(s.addColumnDisabled); } /** * Delete a row by index * * @param {number} index */ deleteRow(t) { this.getRow(t).remove(); const e = this.wrapper.querySelector(`.${s.addRow}`); e && e.classList.remove(s.addRowDisabled), this.addHeadingAttrToFirstRow(); } /** * Create a wrapper containing a table, toolboxes * and buttons for adding rows and columns * * @returns {HTMLElement} wrapper - where all buttons for a table and the table itself will be */ createTableWrapper() { if (this.wrapper = c("div", s.wrapper), this.table = c("div", s.table), this.readOnly && this.wrapper.classList.add(s.wrapperReadOnly), this.wrapper.appendChild(this.toolboxRow.element), this.wrapper.appendChild(this.toolboxColumn.element), this.wrapper.appendChild(this.table), !this.readOnly) { const t = c("div", s.addColumn, { innerHTML: v }), e = c("div", s.addRow, { innerHTML: v }); this.wrapper.appendChild(t), this.wrapper.appendChild(e); } } /** * Returns the size of the table based on initial data or config "size" property * * @return {{rows: number, cols: number}} - number of cols and rows */ computeInitialSize() { const t = this.data && this.data.content, e = Array.isArray(t), o2 = e ? t.length : false, i = e ? t.length : void 0, n2 = o2 ? t[0].length : void 0, r2 = Number.parseInt(this.config && this.config.rows), h2 = Number.parseInt(this.config && this.config.cols), l2 = !isNaN(r2) && r2 > 0 ? r2 : void 0, u2 = !isNaN(h2) && h2 > 0 ? h2 : void 0; return { rows: i || l2 || 2, cols: n2 || u2 || 2 }; } /** * Resize table to match config size or transmitted data size * * @return {{rows: number, cols: number}} - number of cols and rows */ resize() { const { rows: t, cols: e } = this.computeInitialSize(); for (let o2 = 0; o2 < t; o2++) this.addRow(); for (let o2 = 0; o2 < e; o2++) this.addColumn(); } /** * Fills the table with data passed to the constructor * * @returns {void} */ fill() { const t = this.data; if (t && t.content) for (let e = 0; e < t.content.length; e++) for (let o2 = 0; o2 < t.content[e].length; o2++) this.setCellContent(e + 1, o2 + 1, t.content[e][o2]); } /** * Fills a row with cells * * @param {HTMLElement} row - row to fill * @param {number} numberOfColumns - how many cells should be in a row */ fillRow(t, e) { for (let o2 = 1; o2 <= e; o2++) { const i = this.createCell(); t.appendChild(i); } } /** * Creating a cell element * * @return {Element} */ createCell() { return c("div", s.cell, { contentEditable: !this.readOnly }); } /** * Get number of rows in the table */ get numberOfRows() { return this.table.childElementCount; } /** * Get number of columns in the table */ get numberOfColumns() { return this.numberOfRows ? this.table.querySelectorAll(`.${s.row}:first-child .${s.cell}`).length : 0; } /** * Is the column toolbox menu displayed or not * * @returns {boolean} */ get isColumnMenuShowing() { return this.selectedColumn !== 0; } /** * Is the row toolbox menu displayed or not * * @returns {boolean} */ get isRowMenuShowing() { return this.selectedRow !== 0; } /** * Recalculate position of toolbox icons * * @param {Event} event - mouse move event */ onMouseMoveInTable(t) { const { row: e, column: o2 } = this.getHoveredCell(t); this.hoveredColumn = o2, this.hoveredRow = e, this.updateToolboxesPosition(); } /** * Prevents default Enter behaviors * Adds Shift+Enter processing * * @param {KeyboardEvent} event - keypress event */ onKeyPressListener(t) { if (t.key === "Enter") { if (t.shiftKey) return true; this.moveCursorToNextRow(); } return t.key !== "Enter"; } /** * Prevents tab keydown event from bubbling * so that it only works inside the table * * @param {KeyboardEvent} event - keydown event */ onKeyDownListener(t) { t.key === "Tab" && t.stopPropagation(); } /** * Set the coordinates of the cell that the focus has moved to * * @param {FocusEvent} event - focusin event */ focusInTableListener(t) { const e = t.target, o2 = this.getRowByCell(e); this.focusedCell = { row: Array.from(this.table.querySelectorAll(`.${s.row}`)).indexOf(o2) + 1, column: Array.from(o2.querySelectorAll(`.${s.cell}`)).indexOf(e) + 1 }; } /** * Unselect row/column * Close toolbox menu * Hide toolboxes * * @returns {void} */ hideToolboxes() { this.hideRowToolbox(), this.hideColumnToolbox(), this.updateToolboxesPosition(); } /** * Unselect row, close toolbox * * @returns {void} */ hideRowToolbox() { this.unselectRow(), this.toolboxRow.hide(); } /** * Unselect column, close toolbox * * @returns {void} */ hideColumnToolbox() { this.unselectColumn(), this.toolboxColumn.hide(); } /** * Set the cursor focus to the focused cell * * @returns {void} */ focusCell() { this.focusedCellElem.focus(); } /** * Get current focused element * * @returns {HTMLElement} - focused cell */ get focusedCellElem() { const { row: t, column: e } = this.focusedCell; return this.getCell(t, e); } /** * Update toolboxes position * * @param {number} row - hovered row * @param {number} column - hovered column */ updateToolboxesPosition(t = this.hoveredRow, e = this.hoveredColumn) { this.isColumnMenuShowing || e > 0 && e <= this.numberOfColumns && this.toolboxColumn.show(() => ({ left: `calc((100% - var(--cell-size)) / (${this.numberOfColumns} * 2) * (1 + (${e} - 1) * 2))` })), this.isRowMenuShowing || t > 0 && t <= this.numberOfRows && this.toolboxRow.show(() => { const o2 = this.getRow(t), { fromTopBorder: i } = g(this.table, o2), { height: n2 } = o2.getBoundingClientRect(); return { top: `${Math.ceil(i + n2 / 2)}px` }; }); } /** * Makes the first row headings * * @param {boolean} withHeadings - use headings row or not */ setHeadingsSetting(t) { this.tunes.withHeadings = t, t ? (this.table.classList.add(s.withHeadings), this.addHeadingAttrToFirstRow()) : (this.table.classList.remove(s.withHeadings), this.removeHeadingAttrFromFirstRow()); } /** * Adds an attribute for displaying the placeholder in the cell */ addHeadingAttrToFirstRow() { for (let t = 1; t <= this.numberOfColumns; t++) { let e = this.getCell(1, t); e && e.setAttribute("heading", this.api.i18n.t("Heading")); } } /** * Removes an attribute for displaying the placeholder in the cell */ removeHeadingAttrFromFirstRow() { for (let t = 1; t <= this.numberOfColumns; t++) { let e = this.getCell(1, t); e && e.removeAttribute("heading"); } } /** * Add effect of a selected row * * @param {number} index */ selectRow(t) { const e = this.getRow(t); e && (this.selectedRow = t, e.classList.add(s.rowSelected)); } /** * Remove effect of a selected row */ unselectRow() { if (this.selectedRow <= 0) return; const t = this.table.querySelector(`.${s.rowSelected}`); t && t.classList.remove(s.rowSelected), this.selectedRow = 0; } /** * Add effect of a selected column * * @param {number} index */ selectColumn(t) { for (let e = 1; e <= this.numberOfRows; e++) { const o2 = this.getCell(e, t); o2 && o2.classList.add(s.cellSelected); } this.selectedColumn = t; } /** * Remove effect of a selected column */ unselectColumn() { if (this.selectedColumn <= 0) return; let t = this.table.querySelectorAll(`.${s.cellSelected}`); Array.from(t).forEach((e) => { e.classList.remove(s.cellSelected); }), this.selectedColumn = 0; } /** * Calculates the row and column that the cursor is currently hovering over * The search was optimized from O(n) to O (log n) via bin search to reduce the number of calculations * * @param {Event} event - mousemove event * @returns hovered cell coordinates as an integer row and column */ getHoveredCell(t) { let e = this.hoveredRow, o2 = this.hoveredColumn; const { width: i, height: n2, x: r2, y: h2 } = k(this.table, t); return r2 >= 0 && (o2 = this.binSearch( this.numberOfColumns, (l2) => this.getCell(1, l2), ({ fromLeftBorder: l2 }) => r2 < l2, ({ fromRightBorder: l2 }) => r2 > i - l2 )), h2 >= 0 && (e = this.binSearch( this.numberOfRows, (l2) => this.getCell(l2, 1), ({ fromTopBorder: l2 }) => h2 < l2, ({ fromBottomBorder: l2 }) => h2 > n2 - l2 )), { row: e || this.hoveredRow, column: o2 || this.hoveredColumn }; } /** * Looks for the index of the cell the mouse is hovering over. * Cells can be represented as ordered intervals with left and * right (upper and lower for rows) borders inside the table, if the mouse enters it, then this is our index * * @param {number} numberOfCells - upper bound of binary search * @param {function} getCell - function to take the currently viewed cell * @param {function} beforeTheLeftBorder - determines the cursor position, to the left of the cell or not * @param {function} afterTheRightBorder - determines the cursor position, to the right of the cell or not * @returns {number} */ binSearch(t, e, o2, i) { let n2 = 0, r2 = t + 1, h2 = 0, l2; for (; n2 < r2 - 1 && h2 < 10; ) { l2 = Math.ceil((n2 + r2) / 2); const u2 = e(l2), p2 = g(this.table, u2); if (o2(p2)) r2 = l2; else if (i(p2)) n2 = l2; else break; h2++; } return l2; } /** * Collects data from cells into a two-dimensional array * * @returns {string[][]} */ getData() { const t = []; for (let e = 1; e <= this.numberOfRows; e++) { const o2 = this.table.querySelector(`.${s.row}:nth-child(${e})`), i = Array.from(o2.querySelectorAll(`.${s.cell}`)); i.every((r2) => !r2.textContent.trim()) || t.push(i.map((r2) => r2.innerHTML)); } return t; } /** * Remove listeners on the document */ destroy() { document.removeEventListener("click", this.documentClicked); } } let F$1 = class F { /** * Notify core that read-only mode is supported * * @returns {boolean} */ static get isReadOnlySupported() { return true; } /** * Allow to press Enter inside the CodeTool textarea * * @returns {boolean} * @public */ static get enableLineBreaks() { return true; } /** * Render plugin`s main Element and fill it with saved data * * @param {TableConstructor} init */ constructor({ data: t, config: e, api: o2, readOnly: i, block: n2 }) { this.api = o2, this.readOnly = i, this.config = e, this.data = { withHeadings: this.getConfig("withHeadings", false, t), stretched: this.getConfig("stretched", false, t), content: t && t.content ? t.content : [] }, this.table = null, this.block = n2; } /** * Get Tool toolbox settings * icon - Tool icon's SVG * title - title to show in toolbox * * @returns {{icon: string, title: string}} */ static get toolbox() { return { icon: A$1, title: "Table" }; } /** * Return Tool's view * * @returns {HTMLDivElement} */ render() { return this.table = new E(this.readOnly, this.api, this.data, this.config), this.container = c("div", this.api.styles.block), this.container.appendChild(this.table.getWrapper()), this.table.setHeadingsSetting(this.data.withHeadings), this.container; } /** * Returns plugin settings * * @returns {Array} */ renderSettings() { return [ { label: this.api.i18n.t("With headings"), icon: T, isActive: this.data.withHeadings, closeOnActivate: true, toggle: true, onActivate: () => { this.data.withHeadings = true, this.table.setHeadingsSetting(this.data.withHeadings); } }, { label: this.api.i18n.t("Without headings"), icon: H$1, isActive: !this.data.withHeadings, closeOnActivate: true, toggle: true, onActivate: () => { this.data.withHeadings = false, this.table.setHeadingsSetting(this.data.withHeadings); } }, { label: this.data.stretched ? this.api.i18n.t("Collapse") : this.api.i18n.t("Stretch"), icon: this.data.stretched ? R$2 : O$2, closeOnActivate: true, toggle: true, onActivate: () => { this.data.stretched = !this.data.stretched, this.block.stretched = this.data.stretched; } } ]; } /** * Extract table data from the view * * @returns {TableData} - saved data */ save() { const t = this.table.getData(); return { withHeadings: this.data.withHeadings, stretched: this.data.stretched, content: t }; } /** * Plugin destroyer * * @returns {void} */ destroy() { this.table.destroy(); } /** * A helper to get config value. * * @param {string} configName - the key to get from the config. * @param {any} defaultValue - default value if config doesn't have passed key * @param {object} savedData - previously saved data. If passed, the key will be got from there, otherwise from the config * @returns {any} - config value. */ getConfig(t, e = void 0, o2 = void 0) { const i = this.data || o2; return i ? i[t] ? i[t] : e : this.config && this.config[t] ? this.config[t] : e; } /** * Table onPaste configuration * * @public */ static get pasteConfig() { return { tags: ["TABLE", "TR", "TH", "TD"] }; } /** * On paste callback that is fired from Editor * * @param {PasteEvent} event - event with pasted data */ onPaste(t) { const e = t.detail.data, o2 = e.querySelector(":scope > thead, tr:first-of-type th"), n2 = Array.from(e.querySelectorAll("tr")).map((r2) => Array.from(r2.querySelectorAll("th, td")).map((l2) => l2.innerHTML)); this.data = { withHeadings: o2 !== null, content: n2 }, this.table.wrapper && this.table.wrapper.replaceWith(this.render()); } }; (function() { try { if (typeof document < "u") { var e = document.createElement("style"); e.appendChild(document.createTextNode('.ce-delimiter{line-height:1.6em;width:100%;text-align:center}.ce-delimiter:before{display:inline-block;content:"***";font-size:30px;line-height:65px;height:30px;letter-spacing:.2em}')), document.head.appendChild(e); } } catch (t) { console.error("vite-plugin-css-injected-by-js", t); } })(); const r = ''; /** * Delimiter Block for the Editor.js. * * @author CodeX (team@ifmo.su) * @copyright CodeX 2018 * @license The MIT License (MIT) * @version 2.0.0 */ class n { /** * Notify core that read-only mode is supported * @return {boolean} */ static get isReadOnlySupported() { return true; } /** * Allow Tool to have no content * @return {boolean} */ static get contentless() { return true; } /** * Render plugin`s main Element and fill it with saved data * * @param {{data: DelimiterData, config: object, api: object}} * data — previously saved data * config - user config for Tool * api - Editor.js API */ constructor({ data: t, config: s2, api: e }) { this.api = e, this._CSS = { block: this.api.styles.block, wrapper: "ce-delimiter" }, this._element = this.drawView(), this.data = t; } /** * Create Tool's view * @return {HTMLDivElement} * @private */ drawView() { let t = document.createElement("div"); return t.classList.add(this._CSS.wrapper, this._CSS.block), t; } /** * Return Tool's view * @returns {HTMLDivElement} * @public */ render() { return this._element; } /** * Extract Tool's data from the view * @param {HTMLDivElement} toolsContent - Paragraph tools rendered view * @returns {DelimiterData} - saved data * @public */ save(t) { return {}; } /** * Get Tool toolbox settings * icon - Tool icon's SVG * title - title to show in toolbox * * @return {{icon: string, title: string}} */ static get toolbox() { return { icon: r, title: "Delimiter" }; } /** * Delimiter onPaste configuration * * @public */ static get pasteConfig() { return { tags: ["HR"] }; } /** * On paste callback that is fired from Editor * * @param {PasteEvent} event - event with pasted data */ onPaste(t) { this.data = {}; } } (function() { try { if (typeof document < "u") { var o2 = document.createElement("style"); o2.appendChild(document.createTextNode('.image-tool{--bg-color: #cdd1e0;--front-color: #388ae5;--border-color: #e8e8eb}.image-tool__image{border-radius:3px;overflow:hidden;margin-bottom:10px;padding-bottom:0}.image-tool__image-picture{max-width:100%;vertical-align:bottom;display:block}.image-tool__image-preloader{width:50px;height:50px;border-radius:50%;background-size:cover;margin:auto;position:relative;background-color:var(--bg-color);background-position:center center}.image-tool__image-preloader:after{content:"";position:absolute;z-index:3;width:60px;height:60px;border-radius:50%;border:2px solid var(--bg-color);border-top-color:var(--front-color);left:50%;top:50%;margin-top:-30px;margin-left:-30px;animation:image-preloader-spin 2s infinite linear;box-sizing:border-box}.image-tool__caption{visibility:hidden;position:absolute;bottom:0;left:0;margin-bottom:10px}.image-tool__caption[contentEditable=true][data-placeholder]:before{position:absolute!important;content:attr(data-placeholder);color:#707684;font-weight:400;display:none}.image-tool__caption[contentEditable=true][data-placeholder]:empty:before{display:block}.image-tool__caption[contentEditable=true][data-placeholder]:empty:focus:before{display:none}.image-tool--empty .image-tool__image,.image-tool--empty .image-tool__image-preloader{display:none}.image-tool--empty .image-tool__caption,.image-tool--uploading .image-tool__caption{visibility:hidden!important}.image-tool .cdx-button{display:flex;align-items:center;justify-content:center}.image-tool .cdx-button svg{height:auto;margin:0 6px 0 0}.image-tool--filled .cdx-button,.image-tool--filled .image-tool__image-preloader{display:none}.image-tool--uploading .image-tool__image{min-height:200px;display:flex;border:1px solid var(--border-color);background-color:#fff}.image-tool--uploading .image-tool__image-picture,.image-tool--uploading .cdx-button{display:none}.image-tool--withBorder .image-tool__image{border:1px solid var(--border-color)}.image-tool--withBackground .image-tool__image{padding:15px;background:var(--bg-color)}.image-tool--withBackground .image-tool__image-picture{max-width:60%;margin:0 auto}.image-tool--stretched .image-tool__image-picture{width:100%}.image-tool--caption .image-tool__caption{visibility:visible}.image-tool--caption{padding-bottom:50px}@keyframes image-preloader-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}')), document.head.appendChild(o2); } } catch (e) { console.error("vite-plugin-css-injected-by-js", e); } })(); const R$1 = '', I$1 = '', L = '', x = '', B = ''; function S(C2, i = null, a2 = {}) { const s2 = document.createElement(C2); Array.isArray(i) ? s2.classList.add(...i) : i !== null && s2.classList.add(i); for (const r2 in a2) a2.hasOwnProperty(r2) && (s2[r2] = a2[r2]); return s2; } var _ = /* @__PURE__ */ ((C2) => (C2.Empty = "empty", C2.Uploading = "uploading", C2.Filled = "filled", C2))(_ || {}); class D { /** * @param ui - image tool Ui module * @param ui.api - Editor.js API * @param ui.config - user config * @param ui.onSelectFile - callback for clicks on Select file button * @param ui.readOnly - read-only mode flag */ constructor({ api: i, config: a2, onSelectFile: s2, readOnly: r2 }) { this.api = i, this.config = a2, this.onSelectFile = s2, this.readOnly = r2, this.nodes = { wrapper: S("div", [this.CSS.baseClass, this.CSS.wrapper]), imageContainer: S("div", [this.CSS.imageContainer]), fileButton: this.createFileButton(), imageEl: void 0, imagePreloader: S("div", this.CSS.imagePreloader), caption: S("div", [this.CSS.input, this.CSS.caption], { contentEditable: !this.readOnly }) }, this.nodes.caption.dataset.placeholder = this.config.captionPlaceholder, this.nodes.imageContainer.appendChild(this.nodes.imagePreloader), this.nodes.wrapper.appendChild(this.nodes.imageContainer), this.nodes.wrapper.appendChild(this.nodes.caption), this.nodes.wrapper.appendChild(this.nodes.fileButton); } /** * Apply visual representation of activated tune * @param tuneName - one of available tunes {@link Tunes.tunes} * @param status - true for enable, false for disable */ applyTune(i, a2) { this.nodes.wrapper.classList.toggle(`${this.CSS.wrapper}--${i}`, a2); } /** * Renders tool UI */ render() { return this.toggleStatus( "empty" /* Empty */ ), this.nodes.wrapper; } /** * Shows uploading preloader * @param src - preview source */ showPreloader(i) { this.nodes.imagePreloader.style.backgroundImage = `url(${i})`, this.toggleStatus( "uploading" /* Uploading */ ); } /** * Hide uploading preloader */ hidePreloader() { this.nodes.imagePreloader.style.backgroundImage = "", this.toggleStatus( "empty" /* Empty */ ); } /** * Shows an image * @param url - image source */ fillImage(i) { const a2 = /\.mp4$/.test(i) ? "VIDEO" : "IMG", s2 = { src: i }; let r2 = "load"; a2 === "VIDEO" && (s2.autoplay = true, s2.loop = true, s2.muted = true, s2.playsinline = true, r2 = "loadeddata"), this.nodes.imageEl = S(a2, this.CSS.imageEl, s2), this.nodes.imageEl.addEventListener(r2, () => { this.toggleStatus( "filled" /* Filled */ ), this.nodes.imagePreloader !== void 0 && (this.nodes.imagePreloader.style.backgroundImage = ""); }), this.nodes.imageContainer.appendChild(this.nodes.imageEl); } /** * Shows caption input * @param text - caption content text */ fillCaption(i) { this.nodes.caption !== void 0 && (this.nodes.caption.innerHTML = i); } /** * Changes UI status * @param status - see {@link Ui.status} constants */ toggleStatus(i) { for (const a2 in _) if (Object.prototype.hasOwnProperty.call(_, a2)) { const s2 = _[a2]; this.nodes.wrapper.classList.toggle(`${this.CSS.wrapper}--${s2}`, s2 === i); } } /** * CSS classes */ get CSS() { return { baseClass: this.api.styles.block, loading: this.api.styles.loader, input: this.api.styles.input, button: this.api.styles.button, /** * Tool's classes */ wrapper: "image-tool", imageContainer: "image-tool__image", imagePreloader: "image-tool__image-preloader", imageEl: "image-tool__image-picture", caption: "image-tool__caption" }; } /** * Creates upload-file button */ createFileButton() { const i = S("div", [this.CSS.button]); return i.innerHTML = this.config.buttonContent ?? `${L} ${this.api.i18n.t("Select an Image")}`, i.addEventListener("click", () => { this.onSelectFile(); }), i; } } function U(C2) { return C2 && C2.__esModule && Object.prototype.hasOwnProperty.call(C2, "default") ? C2.default : C2; } var H = { exports: {} }; (function(C2, i) { (function(a2, s2) { C2.exports = s2(); })(window, function() { return function(a2) { var s2 = {}; function r2(o2) { if (s2[o2]) return s2[o2].exports; var e = s2[o2] = { i: o2, l: false, exports: {} }; return a2[o2].call(e.exports, e, e.exports, r2), e.l = true, e.exports; } return r2.m = a2, r2.c = s2, r2.d = function(o2, e, d2) { r2.o(o2, e) || Object.defineProperty(o2, e, { enumerable: true, get: d2 }); }, r2.r = function(o2) { typeof Symbol < "u" && Symbol.toStringTag && Object.defineProperty(o2, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(o2, "__esModule", { value: true }); }, r2.t = function(o2, e) { if (1 & e && (o2 = r2(o2)), 8 & e || 4 & e && typeof o2 == "object" && o2 && o2.__esModule) return o2; var d2 = /* @__PURE__ */ Object.create(null); if (r2.r(d2), Object.defineProperty(d2, "default", { enumerable: true, value: o2 }), 2 & e && typeof o2 != "string") for (var v2 in o2) r2.d(d2, v2, (function(l2) { return o2[l2]; }).bind(null, v2)); return d2; }, r2.n = function(o2) { var e = o2 && o2.__esModule ? function() { return o2.default; } : function() { return o2; }; return r2.d(e, "a", e), e; }, r2.o = function(o2, e) { return Object.prototype.hasOwnProperty.call(o2, e); }, r2.p = "", r2(r2.s = 3); }([function(a2, s2) { var r2; r2 = /* @__PURE__ */ function() { return this; }(); try { r2 = r2 || new Function("return this")(); } catch { typeof window == "object" && (r2 = window); } a2.exports = r2; }, function(a2, s2, r2) { (function(o2) { var e = r2(2), d2 = setTimeout; function v2() { } function l2(n2) { if (!(this instanceof l2)) throw new TypeError("Promises must be constructed via new"); if (typeof n2 != "function") throw new TypeError("not a function"); this._state = 0, this._handled = false, this._value = void 0, this._deferreds = [], t(n2, this); } function f2(n2, c2) { for (; n2._state === 3; ) n2 = n2._value; n2._state !== 0 ? (n2._handled = true, l2._immediateFn(function() { var u2 = n2._state === 1 ? c2.onFulfilled : c2.onRejected; if (u2 !== null) { var g2; try { g2 = u2(n2._value); } catch (m2) { return void y2(c2.promise, m2); } p2(c2.promise, g2); } else (n2._state === 1 ? p2 : y2)(c2.promise, n2._value); })) : n2._deferreds.push(c2); } function p2(n2, c2) { try { if (c2 === n2) throw new TypeError("A promise cannot be resolved with itself."); if (c2 && (typeof c2 == "object" || typeof c2 == "function")) { var u2 = c2.then; if (c2 instanceof l2) return n2._state = 3, n2._value = c2, void w2(n2); if (typeof u2 == "function") return void t((g2 = u2, m2 = c2, function() { g2.apply(m2, arguments); }), n2); } n2._state = 1, n2._value = c2, w2(n2); } catch (h2) { y2(n2, h2); } var g2, m2; } function y2(n2, c2) { n2._state = 2, n2._value = c2, w2(n2); } function w2(n2) { n2._state === 2 && n2._deferreds.length === 0 && l2._immediateFn(function() { n2._handled || l2._unhandledRejectionFn(n2._value); }); for (var c2 = 0, u2 = n2._deferreds.length; c2 < u2; c2++) f2(n2, n2._deferreds[c2]); n2._deferreds = null; } function b2(n2, c2, u2) { this.onFulfilled = typeof n2 == "function" ? n2 : null, this.onRejected = typeof c2 == "function" ? c2 : null, this.promise = u2; } function t(n2, c2) { var u2 = false; try { n2(function(g2) { u2 || (u2 = true, p2(c2, g2)); }, function(g2) { u2 || (u2 = true, y2(c2, g2)); }); } catch (g2) { if (u2) return; u2 = true, y2(c2, g2); } } l2.prototype.catch = function(n2) { return this.then(null, n2); }, l2.prototype.then = function(n2, c2) { var u2 = new this.constructor(v2); return f2(this, new b2(n2, c2, u2)), u2; }, l2.prototype.finally = e.a, l2.all = function(n2) { return new l2(function(c2, u2) { if (!n2 || n2.length === void 0) throw new TypeError("Promise.all accepts an array"); var g2 = Array.prototype.slice.call(n2); if (g2.length === 0) return c2([]); var m2 = g2.length; function h2(T2, E2) { try { if (E2 && (typeof E2 == "object" || typeof E2 == "function")) { var M2 = E2.then; if (typeof M2 == "function") return void M2.call(E2, function(F2) { h2(T2, F2); }, u2); } g2[T2] = E2, --m2 == 0 && c2(g2); } catch (F2) { u2(F2); } } for (var k2 = 0; k2 < g2.length; k2++) h2(k2, g2[k2]); }); }, l2.resolve = function(n2) { return n2 && typeof n2 == "object" && n2.constructor === l2 ? n2 : new l2(function(c2) { c2(n2); }); }, l2.reject = function(n2) { return new l2(function(c2, u2) { u2(n2); }); }, l2.race = function(n2) { return new l2(function(c2, u2) { for (var g2 = 0, m2 = n2.length; g2 < m2; g2++) n2[g2].then(c2, u2); }); }, l2._immediateFn = typeof o2 == "function" && function(n2) { o2(n2); } || function(n2) { d2(n2, 0); }, l2._unhandledRejectionFn = function(n2) { typeof console < "u" && console && console.warn("Possible Unhandled Promise Rejection:", n2); }, s2.a = l2; }).call(this, r2(5).setImmediate); }, function(a2, s2, r2) { s2.a = function(o2) { var e = this.constructor; return this.then(function(d2) { return e.resolve(o2()).then(function() { return d2; }); }, function(d2) { return e.resolve(o2()).then(function() { return e.reject(d2); }); }); }; }, function(a2, s2, r2) { function o2(t) { return (o2 = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(n2) { return typeof n2; } : function(n2) { return n2 && typeof Symbol == "function" && n2.constructor === Symbol && n2 !== Symbol.prototype ? "symbol" : typeof n2; })(t); } r2(4); var e, d2, v2, l2, f2, p2, y2, w2 = r2(8), b2 = (d2 = function(t) { return new Promise(function(n2, c2) { t = l2(t), (t = f2(t)).beforeSend && t.beforeSend(); var u2 = window.XMLHttpRequest ? new window.XMLHttpRequest() : new window.ActiveXObject("Microsoft.XMLHTTP"); u2.open(t.method, t.url), u2.setRequestHeader("X-Requested-With", "XMLHttpRequest"), Object.keys(t.headers).forEach(function(m2) { var h2 = t.headers[m2]; u2.setRequestHeader(m2, h2); }); var g2 = t.ratio; u2.upload.addEventListener("progress", function(m2) { var h2 = Math.round(m2.loaded / m2.total * 100), k2 = Math.ceil(h2 * g2 / 100); t.progress(Math.min(k2, 100)); }, false), u2.addEventListener("progress", function(m2) { var h2 = Math.round(m2.loaded / m2.total * 100), k2 = Math.ceil(h2 * (100 - g2) / 100) + g2; t.progress(Math.min(k2, 100)); }, false), u2.onreadystatechange = function() { if (u2.readyState === 4) { var m2 = u2.response; try { m2 = JSON.parse(m2); } catch { } var h2 = w2.parseHeaders(u2.getAllResponseHeaders()), k2 = { body: m2, code: u2.status, headers: h2 }; y2(u2.status) ? n2(k2) : c2(k2); } }, u2.send(t.data); }); }, v2 = function(t) { return t.method = "POST", d2(t); }, l2 = function() { var t = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; if (t.url && typeof t.url != "string") throw new Error("Url must be a string"); if (t.url = t.url || "", t.method && typeof t.method != "string") throw new Error("`method` must be a string or null"); if (t.method = t.method ? t.method.toUpperCase() : "GET", t.headers && o2(t.headers) !== "object") throw new Error("`headers` must be an object or null"); if (t.headers = t.headers || {}, t.type && (typeof t.type != "string" || !Object.values(e).includes(t.type))) throw new Error("`type` must be taken from module's «contentType» library"); if (t.progress && typeof t.progress != "function") throw new Error("`progress` must be a function or null"); if (t.progress = t.progress || function(n2) { }, t.beforeSend = t.beforeSend || function(n2) { }, t.ratio && typeof t.ratio != "number") throw new Error("`ratio` must be a number"); if (t.ratio < 0 || t.ratio > 100) throw new Error("`ratio` must be in a 0-100 interval"); if (t.ratio = t.ratio || 90, t.accept && typeof t.accept != "string") throw new Error("`accept` must be a string with a list of allowed mime-types"); if (t.accept = t.accept || "*/*", t.multiple && typeof t.multiple != "boolean") throw new Error("`multiple` must be a true or false"); if (t.multiple = t.multiple || false, t.fieldName && typeof t.fieldName != "string") throw new Error("`fieldName` must be a string"); return t.fieldName = t.fieldName || "files", t; }, f2 = function(t) { switch (t.method) { case "GET": var n2 = p2(t.data, e.URLENCODED); delete t.data, t.url = /\?/.test(t.url) ? t.url + "&" + n2 : t.url + "?" + n2; break; case "POST": case "PUT": case "DELETE": case "UPDATE": var c2 = function() { return (arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}).type || e.JSON; }(t); (w2.isFormData(t.data) || w2.isFormElement(t.data)) && (c2 = e.FORM), t.data = p2(t.data, c2), c2 !== b2.contentType.FORM && (t.headers["content-type"] = c2); } return t; }, p2 = function() { var t = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; switch (arguments.length > 1 ? arguments[1] : void 0) { case e.URLENCODED: return w2.urlEncode(t); case e.JSON: return w2.jsonEncode(t); case e.FORM: return w2.formEncode(t); default: return t; } }, y2 = function(t) { return t >= 200 && t < 300; }, { contentType: e = { URLENCODED: "application/x-www-form-urlencoded; charset=utf-8", FORM: "multipart/form-data", JSON: "application/json; charset=utf-8" }, request: d2, get: function(t) { return t.method = "GET", d2(t); }, post: v2, transport: function(t) { return t = l2(t), w2.selectFiles(t).then(function(n2) { for (var c2 = new FormData(), u2 = 0; u2 < n2.length; u2++) c2.append(t.fieldName, n2[u2], n2[u2].name); w2.isObject(t.data) && Object.keys(t.data).forEach(function(m2) { var h2 = t.data[m2]; c2.append(m2, h2); }); var g2 = t.beforeSend; return t.beforeSend = function() { return g2(n2); }, t.data = c2, v2(t); }); }, selectFiles: function(t) { return delete (t = l2(t)).beforeSend, w2.selectFiles(t); } }); a2.exports = b2; }, function(a2, s2, r2) { r2.r(s2); var o2 = r2(1); window.Promise = window.Promise || o2.a; }, function(a2, s2, r2) { (function(o2) { var e = o2 !== void 0 && o2 || typeof self < "u" && self || window, d2 = Function.prototype.apply; function v2(l2, f2) { this._id = l2, this._clearFn = f2; } s2.setTimeout = function() { return new v2(d2.call(setTimeout, e, arguments), clearTimeout); }, s2.setInterval = function() { return new v2(d2.call(setInterval, e, arguments), clearInterval); }, s2.clearTimeout = s2.clearInterval = function(l2) { l2 && l2.close(); }, v2.prototype.unref = v2.prototype.ref = function() { }, v2.prototype.close = function() { this._clearFn.call(e, this._id); }, s2.enroll = function(l2, f2) { clearTimeout(l2._idleTimeoutId), l2._idleTimeout = f2; }, s2.unenroll = function(l2) { clearTimeout(l2._idleTimeoutId), l2._idleTimeout = -1; }, s2._unrefActive = s2.active = function(l2) { clearTimeout(l2._idleTimeoutId); var f2 = l2._idleTimeout; f2 >= 0 && (l2._idleTimeoutId = setTimeout(function() { l2._onTimeout && l2._onTimeout(); }, f2)); }, r2(6), s2.setImmediate = typeof self < "u" && self.setImmediate || o2 !== void 0 && o2.setImmediate || this && this.setImmediate, s2.clearImmediate = typeof self < "u" && self.clearImmediate || o2 !== void 0 && o2.clearImmediate || this && this.clearImmediate; }).call(this, r2(0)); }, function(a2, s2, r2) { (function(o2, e) { (function(d2, v2) { if (!d2.setImmediate) { var l2, f2, p2, y2, w2, b2 = 1, t = {}, n2 = false, c2 = d2.document, u2 = Object.getPrototypeOf && Object.getPrototypeOf(d2); u2 = u2 && u2.setTimeout ? u2 : d2, {}.toString.call(d2.process) === "[object process]" ? l2 = function(h2) { e.nextTick(function() { m2(h2); }); } : function() { if (d2.postMessage && !d2.importScripts) { var h2 = true, k2 = d2.onmessage; return d2.onmessage = function() { h2 = false; }, d2.postMessage("", "*"), d2.onmessage = k2, h2; } }() ? (y2 = "setImmediate$" + Math.random() + "$", w2 = function(h2) { h2.source === d2 && typeof h2.data == "string" && h2.data.indexOf(y2) === 0 && m2(+h2.data.slice(y2.length)); }, d2.addEventListener ? d2.addEventListener("message", w2, false) : d2.attachEvent("onmessage", w2), l2 = function(h2) { d2.postMessage(y2 + h2, "*"); }) : d2.MessageChannel ? ((p2 = new MessageChannel()).port1.onmessage = function(h2) { m2(h2.data); }, l2 = function(h2) { p2.port2.postMessage(h2); }) : c2 && "onreadystatechange" in c2.createElement("script") ? (f2 = c2.documentElement, l2 = function(h2) { var k2 = c2.createElement("script"); k2.onreadystatechange = function() { m2(h2), k2.onreadystatechange = null, f2.removeChild(k2), k2 = null; }, f2.appendChild(k2); }) : l2 = function(h2) { setTimeout(m2, 0, h2); }, u2.setImmediate = function(h2) { typeof h2 != "function" && (h2 = new Function("" + h2)); for (var k2 = new Array(arguments.length - 1), T2 = 0; T2 < k2.length; T2++) k2[T2] = arguments[T2 + 1]; var E2 = { callback: h2, args: k2 }; return t[b2] = E2, l2(b2), b2++; }, u2.clearImmediate = g2; } function g2(h2) { delete t[h2]; } function m2(h2) { if (n2) setTimeout(m2, 0, h2); else { var k2 = t[h2]; if (k2) { n2 = true; try { (function(T2) { var E2 = T2.callback, M2 = T2.args; switch (M2.length) { case 0: E2(); break; case 1: E2(M2[0]); break; case 2: E2(M2[0], M2[1]); break; case 3: E2(M2[0], M2[1], M2[2]); break; default: E2.apply(v2, M2); } })(k2); } finally { g2(h2), n2 = false; } } } } })(typeof self > "u" ? o2 === void 0 ? this : o2 : self); }).call(this, r2(0), r2(7)); }, function(a2, s2) { var r2, o2, e = a2.exports = {}; function d2() { throw new Error("setTimeout has not been defined"); } function v2() { throw new Error("clearTimeout has not been defined"); } function l2(u2) { if (r2 === setTimeout) return setTimeout(u2, 0); if ((r2 === d2 || !r2) && setTimeout) return r2 = setTimeout, setTimeout(u2, 0); try { return r2(u2, 0); } catch { try { return r2.call(null, u2, 0); } catch { return r2.call(this, u2, 0); } } } (function() { try { r2 = typeof setTimeout == "function" ? setTimeout : d2; } catch { r2 = d2; } try { o2 = typeof clearTimeout == "function" ? clearTimeout : v2; } catch { o2 = v2; } })(); var f2, p2 = [], y2 = false, w2 = -1; function b2() { y2 && f2 && (y2 = false, f2.length ? p2 = f2.concat(p2) : w2 = -1, p2.length && t()); } function t() { if (!y2) { var u2 = l2(b2); y2 = true; for (var g2 = p2.length; g2; ) { for (f2 = p2, p2 = []; ++w2 < g2; ) f2 && f2[w2].run(); w2 = -1, g2 = p2.length; } f2 = null, y2 = false, function(m2) { if (o2 === clearTimeout) return clearTimeout(m2); if ((o2 === v2 || !o2) && clearTimeout) return o2 = clearTimeout, clearTimeout(m2); try { o2(m2); } catch { try { return o2.call(null, m2); } catch { return o2.call(this, m2); } } }(u2); } } function n2(u2, g2) { this.fun = u2, this.array = g2; } function c2() { } e.nextTick = function(u2) { var g2 = new Array(arguments.length - 1); if (arguments.length > 1) for (var m2 = 1; m2 < arguments.length; m2++) g2[m2 - 1] = arguments[m2]; p2.push(new n2(u2, g2)), p2.length !== 1 || y2 || l2(t); }, n2.prototype.run = function() { this.fun.apply(null, this.array); }, e.title = "browser", e.browser = true, e.env = {}, e.argv = [], e.version = "", e.versions = {}, e.on = c2, e.addListener = c2, e.once = c2, e.off = c2, e.removeListener = c2, e.removeAllListeners = c2, e.emit = c2, e.prependListener = c2, e.prependOnceListener = c2, e.listeners = function(u2) { return []; }, e.binding = function(u2) { throw new Error("process.binding is not supported"); }, e.cwd = function() { return "/"; }, e.chdir = function(u2) { throw new Error("process.chdir is not supported"); }, e.umask = function() { return 0; }; }, function(a2, s2, r2) { function o2(d2, v2) { for (var l2 = 0; l2 < v2.length; l2++) { var f2 = v2[l2]; f2.enumerable = f2.enumerable || false, f2.configurable = true, "value" in f2 && (f2.writable = true), Object.defineProperty(d2, f2.key, f2); } } var e = r2(9); a2.exports = function() { function d2() { (function(p2, y2) { if (!(p2 instanceof y2)) throw new TypeError("Cannot call a class as a function"); })(this, d2); } var v2, l2, f2; return v2 = d2, f2 = [{ key: "urlEncode", value: function(p2) { return e(p2); } }, { key: "jsonEncode", value: function(p2) { return JSON.stringify(p2); } }, { key: "formEncode", value: function(p2) { if (this.isFormData(p2)) return p2; if (this.isFormElement(p2)) return new FormData(p2); if (this.isObject(p2)) { var y2 = new FormData(); return Object.keys(p2).forEach(function(w2) { var b2 = p2[w2]; y2.append(w2, b2); }), y2; } throw new Error("`data` must be an instance of Object, FormData or
    HTMLElement"); } }, { key: "isObject", value: function(p2) { return Object.prototype.toString.call(p2) === "[object Object]"; } }, { key: "isFormData", value: function(p2) { return p2 instanceof FormData; } }, { key: "isFormElement", value: function(p2) { return p2 instanceof HTMLFormElement; } }, { key: "selectFiles", value: function() { var p2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; return new Promise(function(y2, w2) { var b2 = document.createElement("INPUT"); b2.type = "file", p2.multiple && b2.setAttribute("multiple", "multiple"), p2.accept && b2.setAttribute("accept", p2.accept), b2.style.display = "none", document.body.appendChild(b2), b2.addEventListener("change", function(t) { var n2 = t.target.files; y2(n2), document.body.removeChild(b2); }, false), b2.click(); }); } }, { key: "parseHeaders", value: function(p2) { var y2 = p2.trim().split(/[\r\n]+/), w2 = {}; return y2.forEach(function(b2) { var t = b2.split(": "), n2 = t.shift(), c2 = t.join(": "); n2 && (w2[n2] = c2); }), w2; } }], (l2 = null) && o2(v2.prototype, l2), f2 && o2(v2, f2), d2; }(); }, function(a2, s2) { var r2 = function(e) { return encodeURIComponent(e).replace(/[!'()*]/g, escape).replace(/%20/g, "+"); }, o2 = function(e, d2, v2, l2) { return d2 = d2 || null, v2 = v2 || "&", l2 = l2 || null, e ? function(f2) { for (var p2 = new Array(), y2 = 0; y2 < f2.length; y2++) f2[y2] && p2.push(f2[y2]); return p2; }(Object.keys(e).map(function(f2) { var p2, y2, w2 = f2; if (l2 && (w2 = l2 + "[" + w2 + "]"), typeof e[f2] == "object" && e[f2] !== null) p2 = o2(e[f2], null, v2, w2); else { d2 && (y2 = w2, w2 = !isNaN(parseFloat(y2)) && isFinite(y2) ? d2 + Number(w2) : w2); var b2 = e[f2]; b2 = (b2 = (b2 = (b2 = b2 === true ? "1" : b2) === false ? "0" : b2) === 0 ? "0" : b2) || "", p2 = r2(w2) + "=" + r2(b2); } return p2; })).join(v2).replace(/[!'()*]/g, "") : ""; }; a2.exports = o2; }]); }); })(H); var q = H.exports; const j$1 = /* @__PURE__ */ U(q); function O$1(C2) { return C2 !== void 0 && typeof C2.then == "function"; } class A { /** * @param params - uploader module params * @param params.config - image tool config * @param params.onUpload - one callback for all uploading (file, url, d-n-d, pasting) * @param params.onError - callback for uploading errors */ constructor({ config: i, onUpload: a2, onError: s2 }) { this.config = i, this.onUpload = a2, this.onError = s2; } /** * Handle clicks on the upload file button * Fires ajax.transport() * @param onPreview - callback fired when preview is ready */ uploadSelectedFile({ onPreview: i }) { const a2 = function(r2) { const o2 = new FileReader(); o2.readAsDataURL(r2), o2.onload = (e) => { i(e.target.result); }; }; let s2; if (this.config.uploader && typeof this.config.uploader.uploadByFile == "function") { const r2 = this.config.uploader.uploadByFile; s2 = j$1.selectFiles({ accept: this.config.types ?? "image/*" }).then((o2) => { a2(o2[0]); const e = r2(o2[0]); return O$1(e) || console.warn("Custom uploader method uploadByFile should return a Promise"), e; }); } else s2 = j$1.transport({ url: this.config.endpoints.byFile, data: this.config.additionalRequestData, accept: this.config.types ?? "image/*", headers: this.config.additionalRequestHeaders, beforeSend: (r2) => { a2(r2[0]); }, fieldName: this.config.field ?? "image" }).then((r2) => r2.body); s2.then((r2) => { this.onUpload(r2); }).catch((r2) => { this.onError(r2); }); } /** * Handle clicks on the upload file button * Fires ajax.post() * @param url - image source url */ uploadByUrl(i) { let a2; this.config.uploader && typeof this.config.uploader.uploadByUrl == "function" ? (a2 = this.config.uploader.uploadByUrl(i), O$1(a2) || console.warn("Custom uploader method uploadByUrl should return a Promise")) : a2 = j$1.post({ url: this.config.endpoints.byUrl, data: Object.assign({ url: i }, this.config.additionalRequestData), type: j$1.contentType.JSON, headers: this.config.additionalRequestHeaders }).then((s2) => s2.body), a2.then((s2) => { this.onUpload(s2); }).catch((s2) => { this.onError(s2); }); } /** * Handle clicks on the upload file button * Fires ajax.post() * @param file - file pasted by drag-n-drop * @param onPreview - file pasted by drag-n-drop */ uploadByFile(i, { onPreview: a2 }) { const s2 = new FileReader(); s2.readAsDataURL(i), s2.onload = (o2) => { a2(o2.target.result); }; let r2; if (this.config.uploader && typeof this.config.uploader.uploadByFile == "function") r2 = this.config.uploader.uploadByFile(i), O$1(r2) || console.warn("Custom uploader method uploadByFile should return a Promise"); else { const o2 = new FormData(); o2.append(this.config.field ?? "image", i), this.config.additionalRequestData && Object.keys(this.config.additionalRequestData).length && Object.entries(this.config.additionalRequestData).forEach(([e, d2]) => { o2.append(e, d2); }), r2 = j$1.post({ url: this.config.endpoints.byFile, data: o2, type: j$1.contentType.JSON, headers: this.config.additionalRequestHeaders }).then((e) => e.body); } r2.then((o2) => { this.onUpload(o2); }).catch((o2) => { this.onError(o2); }); } } /** * Image Tool for the Editor.js * @author CodeX * @license MIT * @see {@link https://github.com/editor-js/image} * * To developers. * To simplify Tool structure, we split it to 4 parts: * 1) index.ts — main Tool's interface, public API and methods for working with data * 2) uploader.ts — module that has methods for sending files via AJAX: from device, by URL or File pasting * 3) ui.ts — module for UI manipulations: render, showing preloader, etc * * For debug purposes there is a testing server * that can save uploaded files and return a Response {@link UploadResponseFormat} * * $ node dev/server.js * * It will expose 8008 port, so you can pass http://localhost:8008 with the Tools config: * * image: { * class: ImageTool, * config: { * endpoints: { * byFile: 'http://localhost:8008/uploadFile', * byUrl: 'http://localhost:8008/fetchUrl', * } * }, * }, */ let P$1 = class P2 { /** * @param tool - tool properties got from editor.js * @param tool.data - previously saved data * @param tool.config - user config for Tool * @param tool.api - Editor.js API * @param tool.readOnly - read-only mode flag * @param tool.block - current Block API */ constructor({ data: i, config: a2, api: s2, readOnly: r2, block: o2 }) { this.isCaptionEnabled = null, this.api = s2, this.block = o2, this.config = { endpoints: a2.endpoints, additionalRequestData: a2.additionalRequestData, additionalRequestHeaders: a2.additionalRequestHeaders, field: a2.field, types: a2.types, captionPlaceholder: this.api.i18n.t(a2.captionPlaceholder ?? "Caption"), buttonContent: a2.buttonContent, uploader: a2.uploader, actions: a2.actions, features: a2.features || {} }, this.uploader = new A({ config: this.config, onUpload: (e) => this.onUpload(e), onError: (e) => this.uploadingFailed(e) }), this.ui = new D({ api: s2, config: this.config, onSelectFile: () => { this.uploader.uploadSelectedFile({ onPreview: (e) => { this.ui.showPreloader(e); } }); }, readOnly: r2 }), this._data = { caption: "", withBorder: false, withBackground: false, stretched: false, file: { url: "" } }, this.data = i; } /** * Notify core that read-only mode is supported */ static get isReadOnlySupported() { return true; } /** * Get Tool toolbox settings * icon - Tool icon's SVG * title - title to show in toolbox */ static get toolbox() { return { icon: L, title: "Image" }; } /** * Available image tools */ static get tunes() { return [ { name: "withBorder", icon: I$1, title: "With border", toggle: true }, { name: "stretched", icon: x, title: "Stretch image", toggle: true }, { name: "withBackground", icon: R$1, title: "With background", toggle: true } ]; } /** * Renders Block content */ render() { var i, a2, s2; return (((i = this.config.features) == null ? void 0 : i.caption) === true || ((a2 = this.config.features) == null ? void 0 : a2.caption) === void 0 || ((s2 = this.config.features) == null ? void 0 : s2.caption) === "optional" && this.data.caption) && (this.isCaptionEnabled = true, this.ui.applyTune("caption", true)), this.ui.render(); } /** * Validate data: check if Image exists * @param savedData — data received after saving * @returns false if saved data is not correct, otherwise true */ validate(i) { return !!i.file.url; } /** * Return Block data */ save() { const i = this.ui.nodes.caption; return this._data.caption = i.innerHTML, this.data; } /** * Returns configuration for block tunes: add background, add border, stretch image * @returns TunesMenuConfig */ renderSettings() { var o2; const i = P2.tunes.concat(this.config.actions || []), a2 = { border: "withBorder", background: "withBackground", stretch: "stretched", caption: "caption" }; ((o2 = this.config.features) == null ? void 0 : o2.caption) === "optional" && i.push({ name: "caption", icon: B, title: "With caption", toggle: true }); const s2 = i.filter((e) => { var v2, l2; const d2 = Object.keys(a2).find((f2) => a2[f2] === e.name); return d2 === "caption" ? ((v2 = this.config.features) == null ? void 0 : v2.caption) !== false : d2 == null || ((l2 = this.config.features) == null ? void 0 : l2[d2]) !== false; }), r2 = (e) => { let d2 = this.data[e.name]; return e.name === "caption" && (d2 = this.isCaptionEnabled ?? d2), d2; }; return s2.map((e) => ({ icon: e.icon, label: this.api.i18n.t(e.title), name: e.name, toggle: e.toggle, isActive: r2(e), onActivate: () => { if (typeof e.action == "function") { e.action(e.name); return; } let d2 = !r2(e); e.name === "caption" && (this.isCaptionEnabled = !(this.isCaptionEnabled ?? false), d2 = this.isCaptionEnabled), this.tuneToggled(e.name, d2); } })); } /** * Fires after clicks on the Toolbox Image Icon * Initiates click on the Select File button */ appendCallback() { this.ui.nodes.fileButton.click(); } /** * Specify paste substitutes * @see {@link https://github.com/codex-team/editor.js/blob/master/docs/tools.md#paste-handling} */ static get pasteConfig() { return { /** * Paste HTML into Editor */ tags: [ { img: { src: true } } ], /** * Paste URL of image into the Editor */ patterns: { image: /https?:\/\/\S+\.(gif|jpe?g|tiff|png|svg|webp)(\?[a-z0-9=]*)?$/i }, /** * Drag n drop file from into the Editor */ files: { mimeTypes: ["image/*"] } }; } /** * Specify paste handlers * @see {@link https://github.com/codex-team/editor.js/blob/master/docs/tools.md#paste-handling} * @param event - editor.js custom paste event * {@link https://github.com/codex-team/editor.js/blob/master/types/tools/paste-events.d.ts} */ async onPaste(i) { switch (i.type) { case "tag": { const a2 = i.detail.data; if (/^blob:/.test(a2.src)) { const r2 = await (await fetch(a2.src)).blob(); this.uploadFile(r2); break; } this.uploadUrl(a2.src); break; } case "pattern": { const a2 = i.detail.data; this.uploadUrl(a2); break; } case "file": { const a2 = i.detail.file; this.uploadFile(a2); break; } } } /** * Private methods * ̿̿ ̿̿ ̿̿ ̿'̿'\̵͇̿̿\з= ( ▀ ͜͞ʖ▀) =ε/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿ ̿̿ */ /** * Stores all Tool's data * @param data - data in Image Tool format */ set data(i) { var a2; this.image = i.file, this._data.caption = i.caption || "", this.ui.fillCaption(this._data.caption), P2.tunes.forEach(({ name: s2 }) => { const r2 = typeof i[s2] < "u" ? i[s2] === true || i[s2] === "true" : false; this.setTune(s2, r2); }), i.caption ? this.setTune("caption", true) : ((a2 = this.config.features) == null ? void 0 : a2.caption) === true && this.setTune("caption", true); } /** * Return Tool data */ get data() { return this._data; } /** * Set new image file * @param file - uploaded file data */ set image(i) { this._data.file = i || { url: "" }, i && i.url && this.ui.fillImage(i.url); } /** * File uploading callback * @param response - uploading server response */ onUpload(i) { i.success && i.file ? this.image = i.file : this.uploadingFailed("incorrect response: " + JSON.stringify(i)); } /** * Handle uploader errors * @param errorText - uploading error info */ uploadingFailed(i) { console.log("Image Tool: uploading failed because of", i), this.api.notifier.show({ message: this.api.i18n.t("Couldn’t upload image. Please try another."), style: "error" }), this.ui.hidePreloader(); } /** * Callback fired when Block Tune is activated * @param tuneName - tune that has been clicked * @param state - new state */ tuneToggled(i, a2) { i === "caption" ? (this.ui.applyTune(i, a2), a2 == false && (this._data.caption = "", this.ui.fillCaption(""))) : this.setTune(i, a2); } /** * Set one tune * @param tuneName - {@link Tunes.tunes} * @param value - tune state */ setTune(i, a2) { this._data[i] = a2, this.ui.applyTune(i, a2), i === "stretched" && Promise.resolve().then(() => { this.block.stretched = a2; }).catch((s2) => { console.error(s2); }); } /** * Show preloader and upload image file * @param file - file that is currently uploading (from paste) */ uploadFile(i) { this.uploader.uploadByFile(i, { onPreview: (a2) => { this.ui.showPreloader(a2); } }); } /** * Show preloader and upload image by target url * @param url - url pasted */ uploadUrl(i) { this.ui.showPreloader(i), this.uploader.uploadByUrl(i); } }; (function() { try { if (typeof document < "u") { var o2 = document.createElement("style"); o2.appendChild(document.createTextNode(`.link-tool{position:relative}.link-tool__input{padding-left:38px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none'%3E%3Cpath stroke='%23707684' stroke-linecap='round' stroke-width='2' d='m7.7 12.6-.021.02a2.795 2.795 0 0 0-.044 4.005v0a2.795 2.795 0 0 0 3.936.006l1.455-1.438a3 3 0 0 0 .34-3.866l-.146-.207'/%3E%3Cpath stroke='%23707684' stroke-linecap='round' stroke-width='2' d='m16.22 11.12.136-.14c.933-.954.992-2.46.135-3.483v0a2.597 2.597 0 0 0-3.664-.32L11.39 8.386a3 3 0 0 0-.301 4.3l.031.034'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:10px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.link-tool__input-holder{position:relative}.link-tool__input-holder--error .link-tool__input{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none'%3E%3Cpath stroke='rgb(224, 147, 147)' stroke-linecap='round' stroke-width='2' d='m7.7 12.6-.021.02a2.795 2.795 0 0 0-.044 4.005v0a2.795 2.795 0 0 0 3.936.006l1.455-1.438a3 3 0 0 0 .34-3.866l-.146-.207'/%3E%3Cpath stroke='rgb(224, 147, 147)' stroke-linecap='round' stroke-width='2' d='m16.22 11.12.136-.14c.933-.954.992-2.46.135-3.483v0a2.597 2.597 0 0 0-3.664-.32L11.39 8.386a3 3 0 0 0-.301 4.3l.031.034'/%3E%3C/svg%3E");background-color:#fff3f6;border-color:#f3e0e0;color:#a95a5a;box-shadow:inset 0 1px 3px #923e3e0d}.link-tool__input[contentEditable=true][data-placeholder]:before{position:absolute;content:attr(data-placeholder);color:#707684;font-weight:400;opacity:0}.link-tool__input[contentEditable=true][data-placeholder]:empty:before{opacity:1}.link-tool__input[contentEditable=true][data-placeholder]:empty:focus:before{opacity:0}.link-tool__progress{position:absolute;box-shadow:inset 0 1px 3px #66556b0a;height:100%;width:0;background-color:#f4f5f7;z-index:-1}.link-tool__progress--loading{-webkit-animation:progress .5s ease-in;-webkit-animation-fill-mode:forwards}.link-tool__progress--loaded{width:100%}.link-tool__content{display:block;padding:25px;border-radius:2px;box-shadow:0 0 0 2px #fff;color:initial!important;text-decoration:none!important}.link-tool__content:after{content:"";clear:both;display:table}.link-tool__content--rendered{background:#fff;border:1px solid rgba(201,201,204,.48);box-shadow:0 1px 3px #0000001a;border-radius:6px;will-change:filter;animation:link-in .45s 1 cubic-bezier(.215,.61,.355,1)}.link-tool__content--rendered:hover{box-shadow:0 0 3px #00000029}.link-tool__image{background-position:center center;background-repeat:no-repeat;background-size:cover;margin:0 0 0 30px;width:65px;height:65px;border-radius:3px;float:right}.link-tool__title{font-size:17px;font-weight:600;line-height:1.5em;margin:0 0 10px}.link-tool__title+.link-tool__anchor{margin-top:25px}.link-tool__description{margin:0 0 20px;font-size:15px;line-height:1.55em;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.link-tool__anchor{display:block;font-size:15px;line-height:1em;color:#888!important;border:0!important;padding:0!important}@keyframes link-in{0%{filter:blur(5px)}to{filter:none}}.codex-editor--narrow .link-tool__image{display:none}@-webkit-keyframes progress{0%{width:0}to{width:85%}}`)), document.head.appendChild(o2); } } catch (t) { console.error("vite-plugin-css-injected-by-js", t); } })(); var C = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {}; function O(k2) { return k2 && k2.__esModule && Object.prototype.hasOwnProperty.call(k2, "default") ? k2.default : k2; } (function(k2) { var w2 = function() { try { return !!Symbol.iterator; } catch { return false; } }, d2 = w2(), v2 = function(n2) { var o2 = { next: function() { var e = n2.shift(); return { done: e === void 0, value: e }; } }; return d2 && (o2[Symbol.iterator] = function() { return o2; }), o2; }, c2 = function(n2) { return encodeURIComponent(n2).replace(/%20/g, "+"); }, i = function(n2) { return decodeURIComponent(String(n2).replace(/\+/g, " ")); }, a2 = function() { var n2 = function(e) { Object.defineProperty(this, "_entries", { writable: true, value: {} }); var s2 = typeof e; if (s2 !== "undefined") if (s2 === "string") e !== "" && this._fromString(e); else if (e instanceof n2) { var h2 = this; e.forEach(function(u2, f2) { h2.append(f2, u2); }); } else if (e !== null && s2 === "object") if (Object.prototype.toString.call(e) === "[object Array]") for (var t = 0; t < e.length; t++) { var y2 = e[t]; if (Object.prototype.toString.call(y2) === "[object Array]" || y2.length !== 2) this.append(y2[0], y2[1]); else throw new TypeError("Expected [string, any] as entry at index " + t + " of URLSearchParams's input"); } else for (var r2 in e) e.hasOwnProperty(r2) && this.append(r2, e[r2]); else throw new TypeError("Unsupported input's type for URLSearchParams"); }, o2 = n2.prototype; o2.append = function(e, s2) { e in this._entries ? this._entries[e].push(String(s2)) : this._entries[e] = [String(s2)]; }, o2.delete = function(e) { delete this._entries[e]; }, o2.get = function(e) { return e in this._entries ? this._entries[e][0] : null; }, o2.getAll = function(e) { return e in this._entries ? this._entries[e].slice(0) : []; }, o2.has = function(e) { return e in this._entries; }, o2.set = function(e, s2) { this._entries[e] = [String(s2)]; }, o2.forEach = function(e, s2) { var h2; for (var t in this._entries) if (this._entries.hasOwnProperty(t)) { h2 = this._entries[t]; for (var y2 = 0; y2 < h2.length; y2++) e.call(s2, h2[y2], t, this); } }, o2.keys = function() { var e = []; return this.forEach(function(s2, h2) { e.push(h2); }), v2(e); }, o2.values = function() { var e = []; return this.forEach(function(s2) { e.push(s2); }), v2(e); }, o2.entries = function() { var e = []; return this.forEach(function(s2, h2) { e.push([h2, s2]); }), v2(e); }, d2 && (o2[Symbol.iterator] = o2.entries), o2.toString = function() { var e = []; return this.forEach(function(s2, h2) { e.push(c2(h2) + "=" + c2(s2)); }), e.join("&"); }, k2.URLSearchParams = n2; }, p2 = function() { try { var n2 = k2.URLSearchParams; return new n2("?a=1").toString() === "a=1" && typeof n2.prototype.set == "function"; } catch { return false; } }; p2() || a2(); var l2 = k2.URLSearchParams.prototype; typeof l2.sort != "function" && (l2.sort = function() { var n2 = this, o2 = []; this.forEach(function(s2, h2) { o2.push([h2, s2]), n2._entries || n2.delete(h2); }), o2.sort(function(s2, h2) { return s2[0] < h2[0] ? -1 : s2[0] > h2[0] ? 1 : 0; }), n2._entries && (n2._entries = {}); for (var e = 0; e < o2.length; e++) this.append(o2[e][0], o2[e][1]); }), typeof l2._fromString != "function" && Object.defineProperty(l2, "_fromString", { enumerable: false, configurable: false, writable: false, value: function(n2) { if (this._entries) this._entries = {}; else { var o2 = []; this.forEach(function(t, y2) { o2.push(y2); }); for (var e = 0; e < o2.length; e++) this.delete(o2[e]); } n2 = n2.replace(/^\?/, ""); for (var s2 = n2.split("&"), h2, e = 0; e < s2.length; e++) h2 = s2[e].split("="), this.append( i(h2[0]), h2.length > 1 ? i(h2[1]) : "" ); } }); })( typeof C < "u" ? C : typeof window < "u" ? window : typeof self < "u" ? self : C ); (function(k2) { var w2 = function() { try { var c2 = new k2.URL("b", "http://a"); return c2.pathname = "c d", c2.href === "http://a/c%20d" && c2.searchParams; } catch { return false; } }, d2 = function() { var c2 = k2.URL, i = function(l2, n2) { typeof l2 != "string" && (l2 = String(l2)); var o2 = document, e; if (n2 && (k2.location === void 0 || n2 !== k2.location.href)) { o2 = document.implementation.createHTMLDocument(""), e = o2.createElement("base"), e.href = n2, o2.head.appendChild(e); try { if (e.href.indexOf(n2) !== 0) throw new Error(e.href); } catch (m2) { throw new Error("URL unable to set base " + n2 + " due to " + m2); } } var s2 = o2.createElement("a"); s2.href = l2, e && (o2.body.appendChild(s2), s2.href = s2.href); var h2 = o2.createElement("input"); if (h2.type = "url", h2.value = l2, s2.protocol === ":" || !/:/.test(s2.href) || !h2.checkValidity() && !n2) throw new TypeError("Invalid URL"); Object.defineProperty(this, "_anchorElement", { value: s2 }); var t = new k2.URLSearchParams(this.search), y2 = true, r2 = true, u2 = this; ["append", "delete", "set"].forEach(function(m2) { var b2 = t[m2]; t[m2] = function() { b2.apply(t, arguments), y2 && (r2 = false, u2.search = t.toString(), r2 = true); }; }), Object.defineProperty(this, "searchParams", { value: t, enumerable: true }); var f2 = void 0; Object.defineProperty(this, "_updateSearchParams", { enumerable: false, configurable: false, writable: false, value: function() { this.search !== f2 && (f2 = this.search, r2 && (y2 = false, this.searchParams._fromString(this.search), y2 = true)); } }); }, a2 = i.prototype, p2 = function(l2) { Object.defineProperty(a2, l2, { get: function() { return this._anchorElement[l2]; }, set: function(n2) { this._anchorElement[l2] = n2; }, enumerable: true }); }; ["hash", "host", "hostname", "port", "protocol"].forEach(function(l2) { p2(l2); }), Object.defineProperty(a2, "search", { get: function() { return this._anchorElement.search; }, set: function(l2) { this._anchorElement.search = l2, this._updateSearchParams(); }, enumerable: true }), Object.defineProperties(a2, { toString: { get: function() { var l2 = this; return function() { return l2.href; }; } }, href: { get: function() { return this._anchorElement.href.replace(/\?$/, ""); }, set: function(l2) { this._anchorElement.href = l2, this._updateSearchParams(); }, enumerable: true }, pathname: { get: function() { return this._anchorElement.pathname.replace(/(^\/?)/, "/"); }, set: function(l2) { this._anchorElement.pathname = l2; }, enumerable: true }, origin: { get: function() { var l2 = { "http:": 80, "https:": 443, "ftp:": 21 }[this._anchorElement.protocol], n2 = this._anchorElement.port != l2 && this._anchorElement.port !== ""; return this._anchorElement.protocol + "//" + this._anchorElement.hostname + (n2 ? ":" + this._anchorElement.port : ""); }, enumerable: true }, password: { // TODO get: function() { return ""; }, set: function(l2) { }, enumerable: true }, username: { // TODO get: function() { return ""; }, set: function(l2) { }, enumerable: true } }), i.createObjectURL = function(l2) { return c2.createObjectURL.apply(c2, arguments); }, i.revokeObjectURL = function(l2) { return c2.revokeObjectURL.apply(c2, arguments); }, k2.URL = i; }; if (w2() || d2(), k2.location !== void 0 && !("origin" in k2.location)) { var v2 = function() { return k2.location.protocol + "//" + k2.location.hostname + (k2.location.port ? ":" + k2.location.port : ""); }; try { Object.defineProperty(k2.location, "origin", { get: v2, enumerable: true }); } catch { setInterval(function() { k2.location.origin = v2(); }, 100); } } })( typeof C < "u" ? C : typeof window < "u" ? window : typeof self < "u" ? self : C ); var j = { exports: {} }; (function(k2, w2) { (function(d2, v2) { k2.exports = v2(); })(window, function() { return function(d2) { var v2 = {}; function c2(i) { if (v2[i]) return v2[i].exports; var a2 = v2[i] = { i, l: false, exports: {} }; return d2[i].call(a2.exports, a2, a2.exports, c2), a2.l = true, a2.exports; } return c2.m = d2, c2.c = v2, c2.d = function(i, a2, p2) { c2.o(i, a2) || Object.defineProperty(i, a2, { enumerable: true, get: p2 }); }, c2.r = function(i) { typeof Symbol < "u" && Symbol.toStringTag && Object.defineProperty(i, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(i, "__esModule", { value: true }); }, c2.t = function(i, a2) { if (1 & a2 && (i = c2(i)), 8 & a2 || 4 & a2 && typeof i == "object" && i && i.__esModule) return i; var p2 = /* @__PURE__ */ Object.create(null); if (c2.r(p2), Object.defineProperty(p2, "default", { enumerable: true, value: i }), 2 & a2 && typeof i != "string") for (var l2 in i) c2.d(p2, l2, (function(n2) { return i[n2]; }).bind(null, l2)); return p2; }, c2.n = function(i) { var a2 = i && i.__esModule ? function() { return i.default; } : function() { return i; }; return c2.d(a2, "a", a2), a2; }, c2.o = function(i, a2) { return Object.prototype.hasOwnProperty.call(i, a2); }, c2.p = "", c2(c2.s = 3); }([function(d2, v2) { var c2; c2 = function() { return this; }(); try { c2 = c2 || new Function("return this")(); } catch { typeof window == "object" && (c2 = window); } d2.exports = c2; }, function(d2, v2, c2) { (function(i) { var a2 = c2(2), p2 = setTimeout; function l2() { } function n2(r2) { if (!(this instanceof n2)) throw new TypeError("Promises must be constructed via new"); if (typeof r2 != "function") throw new TypeError("not a function"); this._state = 0, this._handled = false, this._value = void 0, this._deferreds = [], y2(r2, this); } function o2(r2, u2) { for (; r2._state === 3; ) r2 = r2._value; r2._state !== 0 ? (r2._handled = true, n2._immediateFn(function() { var f2 = r2._state === 1 ? u2.onFulfilled : u2.onRejected; if (f2 !== null) { var m2; try { m2 = f2(r2._value); } catch (b2) { return void s2(u2.promise, b2); } e(u2.promise, m2); } else (r2._state === 1 ? e : s2)(u2.promise, r2._value); })) : r2._deferreds.push(u2); } function e(r2, u2) { try { if (u2 === r2) throw new TypeError("A promise cannot be resolved with itself."); if (u2 && (typeof u2 == "object" || typeof u2 == "function")) { var f2 = u2.then; if (u2 instanceof n2) return r2._state = 3, r2._value = u2, void h2(r2); if (typeof f2 == "function") return void y2((m2 = f2, b2 = u2, function() { m2.apply(b2, arguments); }), r2); } r2._state = 1, r2._value = u2, h2(r2); } catch (g2) { s2(r2, g2); } var m2, b2; } function s2(r2, u2) { r2._state = 2, r2._value = u2, h2(r2); } function h2(r2) { r2._state === 2 && r2._deferreds.length === 0 && n2._immediateFn(function() { r2._handled || n2._unhandledRejectionFn(r2._value); }); for (var u2 = 0, f2 = r2._deferreds.length; u2 < f2; u2++) o2(r2, r2._deferreds[u2]); r2._deferreds = null; } function t(r2, u2, f2) { this.onFulfilled = typeof r2 == "function" ? r2 : null, this.onRejected = typeof u2 == "function" ? u2 : null, this.promise = f2; } function y2(r2, u2) { var f2 = false; try { r2(function(m2) { f2 || (f2 = true, e(u2, m2)); }, function(m2) { f2 || (f2 = true, s2(u2, m2)); }); } catch (m2) { if (f2) return; f2 = true, s2(u2, m2); } } n2.prototype.catch = function(r2) { return this.then(null, r2); }, n2.prototype.then = function(r2, u2) { var f2 = new this.constructor(l2); return o2(this, new t(r2, u2, f2)), f2; }, n2.prototype.finally = a2.a, n2.all = function(r2) { return new n2(function(u2, f2) { if (!r2 || r2.length === void 0) throw new TypeError("Promise.all accepts an array"); var m2 = Array.prototype.slice.call(r2); if (m2.length === 0) return u2([]); var b2 = m2.length; function g2(T2, E2) { try { if (E2 && (typeof E2 == "object" || typeof E2 == "function")) { var S2 = E2.then; if (typeof S2 == "function") return void S2.call(E2, function(L2) { g2(T2, L2); }, f2); } m2[T2] = E2, --b2 == 0 && u2(m2); } catch (L2) { f2(L2); } } for (var _2 = 0; _2 < m2.length; _2++) g2(_2, m2[_2]); }); }, n2.resolve = function(r2) { return r2 && typeof r2 == "object" && r2.constructor === n2 ? r2 : new n2(function(u2) { u2(r2); }); }, n2.reject = function(r2) { return new n2(function(u2, f2) { f2(r2); }); }, n2.race = function(r2) { return new n2(function(u2, f2) { for (var m2 = 0, b2 = r2.length; m2 < b2; m2++) r2[m2].then(u2, f2); }); }, n2._immediateFn = typeof i == "function" && function(r2) { i(r2); } || function(r2) { p2(r2, 0); }, n2._unhandledRejectionFn = function(r2) { typeof console < "u" && console && console.warn("Possible Unhandled Promise Rejection:", r2); }, v2.a = n2; }).call(this, c2(5).setImmediate); }, function(d2, v2, c2) { v2.a = function(i) { var a2 = this.constructor; return this.then(function(p2) { return a2.resolve(i()).then(function() { return p2; }); }, function(p2) { return a2.resolve(i()).then(function() { return a2.reject(p2); }); }); }; }, function(d2, v2, c2) { function i(t) { return (i = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(y2) { return typeof y2; } : function(y2) { return y2 && typeof Symbol == "function" && y2.constructor === Symbol && y2 !== Symbol.prototype ? "symbol" : typeof y2; })(t); } c2(4); var a2, p2, l2, n2, o2, e, s2 = c2(8), h2 = (p2 = function(t) { return new Promise(function(y2, r2) { t = n2(t), t = o2(t); var u2 = window.XMLHttpRequest ? new window.XMLHttpRequest() : new window.ActiveXObject("Microsoft.XMLHTTP"); u2.open(t.method, t.url), u2.setRequestHeader("X-Requested-With", "XMLHttpRequest"), Object.keys(t.headers).forEach(function(m2) { var b2 = t.headers[m2]; u2.setRequestHeader(m2, b2); }); var f2 = t.ratio; u2.upload.addEventListener("progress", function(m2) { var b2 = Math.round(m2.loaded / m2.total * 100), g2 = Math.ceil(b2 * f2 / 100); t.progress(g2); }, false), u2.addEventListener("progress", function(m2) { var b2 = Math.round(m2.loaded / m2.total * 100), g2 = Math.ceil(b2 * (100 - f2) / 100) + f2; t.progress(g2); }, false), u2.onreadystatechange = function() { if (u2.readyState === 4) { var m2 = u2.response; try { m2 = JSON.parse(m2); } catch { } var b2 = s2.parseHeaders(u2.getAllResponseHeaders()), g2 = { body: m2, code: u2.status, headers: b2 }; u2.status === 200 ? y2(g2) : r2(g2); } }, u2.send(t.data); }); }, l2 = function(t) { return t.method = "POST", p2(t); }, n2 = function() { var t = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; if (t.url && typeof t.url != "string") throw new Error("Url must be a string"); if (t.url = t.url || "", t.method && typeof t.method != "string") throw new Error("`method` must be a string or null"); if (t.method = t.method ? t.method.toUpperCase() : "GET", t.headers && i(t.headers) !== "object") throw new Error("`headers` must be an object or null"); if (t.headers = t.headers || {}, t.type && (typeof t.type != "string" || !Object.values(a2).includes(t.type))) throw new Error("`type` must be taken from module's «contentType» library"); if (t.progress && typeof t.progress != "function") throw new Error("`progress` must be a function or null"); if (t.progress = t.progress || function(y2) { }, t.beforeSend = t.beforeSend || function(y2) { }, t.ratio && typeof t.ratio != "number") throw new Error("`ratio` must be a number"); if (t.ratio < 0 || t.ratio > 100) throw new Error("`ratio` must be in a 0-100 interval"); if (t.ratio = t.ratio || 90, t.accept && typeof t.accept != "string") throw new Error("`accept` must be a string with a list of allowed mime-types"); if (t.accept = t.accept || "*/*", t.multiple && typeof t.multiple != "boolean") throw new Error("`multiple` must be a true or false"); if (t.multiple = t.multiple || false, t.fieldName && typeof t.fieldName != "string") throw new Error("`fieldName` must be a string"); return t.fieldName = t.fieldName || "files", t; }, o2 = function(t) { switch (t.method) { case "GET": var y2 = e(t.data, a2.URLENCODED); delete t.data, t.url = /\?/.test(t.url) ? t.url + "&" + y2 : t.url + "?" + y2; break; case "POST": case "PUT": case "DELETE": case "UPDATE": var r2 = function() { return (arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}).type || a2.JSON; }(t); (s2.isFormData(t.data) || s2.isFormElement(t.data)) && (r2 = a2.FORM), t.data = e(t.data, r2), r2 !== h2.contentType.FORM && (t.headers["content-type"] = r2); } return t; }, e = function() { var t = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; switch (arguments.length > 1 ? arguments[1] : void 0) { case a2.URLENCODED: return s2.urlEncode(t); case a2.JSON: return s2.jsonEncode(t); case a2.FORM: return s2.formEncode(t); default: return t; } }, { contentType: a2 = { URLENCODED: "application/x-www-form-urlencoded; charset=utf-8", FORM: "multipart/form-data", JSON: "application/json; charset=utf-8" }, request: p2, get: function(t) { return t.method = "GET", p2(t); }, post: l2, transport: function(t) { return t = n2(t), s2.selectFiles(t).then(function(y2) { for (var r2 = new FormData(), u2 = 0; u2 < y2.length; u2++) r2.append(t.fieldName, y2[u2], y2[u2].name); return s2.isObject(t.data) && Object.keys(t.data).forEach(function(f2) { var m2 = t.data[f2]; r2.append(f2, m2); }), t.beforeSend && t.beforeSend(y2), t.data = r2, l2(t); }); }, selectFiles: function(t) { return delete (t = n2(t)).beforeSend, s2.selectFiles(t); } }); d2.exports = h2; }, function(d2, v2, c2) { c2.r(v2); var i = c2(1); window.Promise = window.Promise || i.a; }, function(d2, v2, c2) { (function(i) { var a2 = i !== void 0 && i || typeof self < "u" && self || window, p2 = Function.prototype.apply; function l2(n2, o2) { this._id = n2, this._clearFn = o2; } v2.setTimeout = function() { return new l2(p2.call(setTimeout, a2, arguments), clearTimeout); }, v2.setInterval = function() { return new l2(p2.call(setInterval, a2, arguments), clearInterval); }, v2.clearTimeout = v2.clearInterval = function(n2) { n2 && n2.close(); }, l2.prototype.unref = l2.prototype.ref = function() { }, l2.prototype.close = function() { this._clearFn.call(a2, this._id); }, v2.enroll = function(n2, o2) { clearTimeout(n2._idleTimeoutId), n2._idleTimeout = o2; }, v2.unenroll = function(n2) { clearTimeout(n2._idleTimeoutId), n2._idleTimeout = -1; }, v2._unrefActive = v2.active = function(n2) { clearTimeout(n2._idleTimeoutId); var o2 = n2._idleTimeout; o2 >= 0 && (n2._idleTimeoutId = setTimeout(function() { n2._onTimeout && n2._onTimeout(); }, o2)); }, c2(6), v2.setImmediate = typeof self < "u" && self.setImmediate || i !== void 0 && i.setImmediate || this && this.setImmediate, v2.clearImmediate = typeof self < "u" && self.clearImmediate || i !== void 0 && i.clearImmediate || this && this.clearImmediate; }).call(this, c2(0)); }, function(d2, v2, c2) { (function(i, a2) { (function(p2, l2) { if (!p2.setImmediate) { var n2, o2, e, s2, h2, t = 1, y2 = {}, r2 = false, u2 = p2.document, f2 = Object.getPrototypeOf && Object.getPrototypeOf(p2); f2 = f2 && f2.setTimeout ? f2 : p2, {}.toString.call(p2.process) === "[object process]" ? n2 = function(g2) { a2.nextTick(function() { b2(g2); }); } : function() { if (p2.postMessage && !p2.importScripts) { var g2 = true, _2 = p2.onmessage; return p2.onmessage = function() { g2 = false; }, p2.postMessage("", "*"), p2.onmessage = _2, g2; } }() ? (s2 = "setImmediate$" + Math.random() + "$", h2 = function(g2) { g2.source === p2 && typeof g2.data == "string" && g2.data.indexOf(s2) === 0 && b2(+g2.data.slice(s2.length)); }, p2.addEventListener ? p2.addEventListener("message", h2, false) : p2.attachEvent("onmessage", h2), n2 = function(g2) { p2.postMessage(s2 + g2, "*"); }) : p2.MessageChannel ? ((e = new MessageChannel()).port1.onmessage = function(g2) { b2(g2.data); }, n2 = function(g2) { e.port2.postMessage(g2); }) : u2 && "onreadystatechange" in u2.createElement("script") ? (o2 = u2.documentElement, n2 = function(g2) { var _2 = u2.createElement("script"); _2.onreadystatechange = function() { b2(g2), _2.onreadystatechange = null, o2.removeChild(_2), _2 = null; }, o2.appendChild(_2); }) : n2 = function(g2) { setTimeout(b2, 0, g2); }, f2.setImmediate = function(g2) { typeof g2 != "function" && (g2 = new Function("" + g2)); for (var _2 = new Array(arguments.length - 1), T2 = 0; T2 < _2.length; T2++) _2[T2] = arguments[T2 + 1]; var E2 = { callback: g2, args: _2 }; return y2[t] = E2, n2(t), t++; }, f2.clearImmediate = m2; } function m2(g2) { delete y2[g2]; } function b2(g2) { if (r2) setTimeout(b2, 0, g2); else { var _2 = y2[g2]; if (_2) { r2 = true; try { (function(T2) { var E2 = T2.callback, S2 = T2.args; switch (S2.length) { case 0: E2(); break; case 1: E2(S2[0]); break; case 2: E2(S2[0], S2[1]); break; case 3: E2(S2[0], S2[1], S2[2]); break; default: E2.apply(l2, S2); } })(_2); } finally { m2(g2), r2 = false; } } } } })(typeof self > "u" ? i === void 0 ? this : i : self); }).call(this, c2(0), c2(7)); }, function(d2, v2) { var c2, i, a2 = d2.exports = {}; function p2() { throw new Error("setTimeout has not been defined"); } function l2() { throw new Error("clearTimeout has not been defined"); } function n2(f2) { if (c2 === setTimeout) return setTimeout(f2, 0); if ((c2 === p2 || !c2) && setTimeout) return c2 = setTimeout, setTimeout(f2, 0); try { return c2(f2, 0); } catch { try { return c2.call(null, f2, 0); } catch { return c2.call(this, f2, 0); } } } (function() { try { c2 = typeof setTimeout == "function" ? setTimeout : p2; } catch { c2 = p2; } try { i = typeof clearTimeout == "function" ? clearTimeout : l2; } catch { i = l2; } })(); var o2, e = [], s2 = false, h2 = -1; function t() { s2 && o2 && (s2 = false, o2.length ? e = o2.concat(e) : h2 = -1, e.length && y2()); } function y2() { if (!s2) { var f2 = n2(t); s2 = true; for (var m2 = e.length; m2; ) { for (o2 = e, e = []; ++h2 < m2; ) o2 && o2[h2].run(); h2 = -1, m2 = e.length; } o2 = null, s2 = false, function(b2) { if (i === clearTimeout) return clearTimeout(b2); if ((i === l2 || !i) && clearTimeout) return i = clearTimeout, clearTimeout(b2); try { i(b2); } catch { try { return i.call(null, b2); } catch { return i.call(this, b2); } } }(f2); } } function r2(f2, m2) { this.fun = f2, this.array = m2; } function u2() { } a2.nextTick = function(f2) { var m2 = new Array(arguments.length - 1); if (arguments.length > 1) for (var b2 = 1; b2 < arguments.length; b2++) m2[b2 - 1] = arguments[b2]; e.push(new r2(f2, m2)), e.length !== 1 || s2 || n2(y2); }, r2.prototype.run = function() { this.fun.apply(null, this.array); }, a2.title = "browser", a2.browser = true, a2.env = {}, a2.argv = [], a2.version = "", a2.versions = {}, a2.on = u2, a2.addListener = u2, a2.once = u2, a2.off = u2, a2.removeListener = u2, a2.removeAllListeners = u2, a2.emit = u2, a2.prependListener = u2, a2.prependOnceListener = u2, a2.listeners = function(f2) { return []; }, a2.binding = function(f2) { throw new Error("process.binding is not supported"); }, a2.cwd = function() { return "/"; }, a2.chdir = function(f2) { throw new Error("process.chdir is not supported"); }, a2.umask = function() { return 0; }; }, function(d2, v2, c2) { function i(p2, l2) { for (var n2 = 0; n2 < l2.length; n2++) { var o2 = l2[n2]; o2.enumerable = o2.enumerable || false, o2.configurable = true, "value" in o2 && (o2.writable = true), Object.defineProperty(p2, o2.key, o2); } } var a2 = c2(9); d2.exports = function() { function p2() { (function(e, s2) { if (!(e instanceof s2)) throw new TypeError("Cannot call a class as a function"); })(this, p2); } var l2, n2, o2; return l2 = p2, o2 = [{ key: "urlEncode", value: function(e) { return a2(e); } }, { key: "jsonEncode", value: function(e) { return JSON.stringify(e); } }, { key: "formEncode", value: function(e) { if (this.isFormData(e)) return e; if (this.isFormElement(e)) return new FormData(e); if (this.isObject(e)) { var s2 = new FormData(); return Object.keys(e).forEach(function(h2) { var t = e[h2]; s2.append(h2, t); }), s2; } throw new Error("`data` must be an instance of Object, FormData or HTMLElement"); } }, { key: "isObject", value: function(e) { return Object.prototype.toString.call(e) === "[object Object]"; } }, { key: "isFormData", value: function(e) { return e instanceof FormData; } }, { key: "isFormElement", value: function(e) { return e instanceof HTMLFormElement; } }, { key: "selectFiles", value: function() { var e = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; return new Promise(function(s2, h2) { var t = document.createElement("INPUT"); t.type = "file", e.multiple && t.setAttribute("multiple", "multiple"), e.accept && t.setAttribute("accept", e.accept), t.style.display = "none", document.body.appendChild(t), t.addEventListener("change", function(y2) { var r2 = y2.target.files; s2(r2), document.body.removeChild(t); }, false), t.click(); }); } }, { key: "parseHeaders", value: function(e) { var s2 = e.trim().split(/[\r\n]+/), h2 = {}; return s2.forEach(function(t) { var y2 = t.split(": "), r2 = y2.shift(), u2 = y2.join(": "); r2 && (h2[r2] = u2); }), h2; } }], (n2 = null) && i(l2.prototype, n2), o2 && i(l2, o2), p2; }(); }, function(d2, v2) { var c2 = function(a2) { return encodeURIComponent(a2).replace(/[!'()*]/g, escape).replace(/%20/g, "+"); }, i = function(a2, p2, l2, n2) { return p2 = p2 || null, l2 = l2 || "&", n2 = n2 || null, a2 ? function(o2) { for (var e = new Array(), s2 = 0; s2 < o2.length; s2++) o2[s2] && e.push(o2[s2]); return e; }(Object.keys(a2).map(function(o2) { var e, s2, h2 = o2; if (n2 && (h2 = n2 + "[" + h2 + "]"), typeof a2[o2] == "object" && a2[o2] !== null) e = i(a2[o2], null, l2, h2); else { p2 && (s2 = h2, h2 = !isNaN(parseFloat(s2)) && isFinite(s2) ? p2 + Number(h2) : h2); var t = a2[o2]; t = (t = (t = (t = t === true ? "1" : t) === false ? "0" : t) === 0 ? "0" : t) || "", e = c2(h2) + "=" + c2(t); } return e; })).join(l2).replace(/[!'()*]/g, "") : ""; }; d2.exports = i; }]); }); })(j); var P = j.exports; const R = /* @__PURE__ */ O(P), F = ''; class I { /** * Notify core that read-only mode supported * * @returns {boolean} */ static get isReadOnlySupported() { return true; } /** * Get Tool toolbox settings * icon - Tool icon's SVG * title - title to show in toolbox * * @returns {{icon: string, title: string}} */ static get toolbox() { return { icon: F, title: "Link" }; } /** * Allow to press Enter inside the LinkTool input * * @returns {boolean} * @public */ static get enableLineBreaks() { return true; } /** * @param {object} options - Tool constructor options fot from Editor.js * @param {LinkToolData} options.data - previously saved data * @param {LinkToolConfig} options.config - user config for Tool * @param {object} options.api - Editor.js API * @param {boolean} options.readOnly - read-only mode flag */ constructor({ data: w2, config: d2, api: v2, readOnly: c2 }) { this.api = v2, this.readOnly = c2, this.config = { endpoint: d2.endpoint || "", headers: d2.headers || {} }, this.nodes = { wrapper: null, container: null, progress: null, input: null, inputHolder: null, linkContent: null, linkImage: null, linkTitle: null, linkDescription: null, linkText: null }, this._data = { link: "", meta: {} }, this.data = w2; } /** * Renders Block content * * @public * * @returns {HTMLDivElement} */ render() { return this.nodes.wrapper = this.make("div", this.CSS.baseClass), this.nodes.container = this.make("div", this.CSS.container), this.nodes.inputHolder = this.makeInputHolder(), this.nodes.linkContent = this.prepareLinkPreview(), Object.keys(this.data.meta).length ? (this.nodes.container.appendChild(this.nodes.linkContent), this.showLinkPreview(this.data.meta)) : this.nodes.container.appendChild(this.nodes.inputHolder), this.nodes.wrapper.appendChild(this.nodes.container), this.nodes.wrapper; } /** * Return Block data * * @public * * @returns {LinkToolData} */ save() { return this.data; } /** * Validate Block data * - check if given link is an empty string or not. * * @public * * @returns {boolean} false if saved data is incorrect, otherwise true */ validate() { return this.data.link.trim() !== ""; } /** * Stores all Tool's data * * @param {LinkToolData} data - data to store */ set data(w2) { this._data = Object.assign({}, { link: w2.link || this._data.link, meta: w2.meta || this._data.meta }); } /** * Return Tool data * * @returns {LinkToolData} */ get data() { return this._data; } /** * @returns {object} - Link Tool styles */ get CSS() { return { baseClass: this.api.styles.block, input: this.api.styles.input, /** * Tool's classes */ container: "link-tool", inputEl: "link-tool__input", inputHolder: "link-tool__input-holder", inputError: "link-tool__input-holder--error", linkContent: "link-tool__content", linkContentRendered: "link-tool__content--rendered", linkImage: "link-tool__image", linkTitle: "link-tool__title", linkDescription: "link-tool__description", linkText: "link-tool__anchor", progress: "link-tool__progress", progressLoading: "link-tool__progress--loading", progressLoaded: "link-tool__progress--loaded" }; } /** * Prepare input holder * * @returns {HTMLElement} */ makeInputHolder() { const w2 = this.make("div", this.CSS.inputHolder); return this.nodes.progress = this.make("label", this.CSS.progress), this.nodes.input = this.make("div", [this.CSS.input, this.CSS.inputEl], { contentEditable: !this.readOnly }), this.nodes.input.dataset.placeholder = this.api.i18n.t("Link"), this.readOnly || (this.nodes.input.addEventListener("paste", (d2) => { this.startFetching(d2); }), this.nodes.input.addEventListener("keydown", (d2) => { const [v2, c2] = [13, 65], i = d2.ctrlKey || d2.metaKey; switch (d2.keyCode) { case v2: d2.preventDefault(), d2.stopPropagation(), this.startFetching(d2); break; case c2: i && this.selectLinkUrl(d2); break; } })), w2.appendChild(this.nodes.progress), w2.appendChild(this.nodes.input), w2; } /** * Activates link data fetching by url * * @param {PasteEvent|KeyboardEvent} event - fetching could be fired by a pase or keydown events */ startFetching(w2) { let d2 = this.nodes.input.textContent; w2.type === "paste" && (d2 = (w2.clipboardData || window.clipboardData).getData("text")), this.removeErrorStyle(), this.fetchLinkData(d2); } /** * If previous link data fetching failed, remove error styles */ removeErrorStyle() { this.nodes.inputHolder.classList.remove(this.CSS.inputError), this.nodes.inputHolder.insertBefore(this.nodes.progress, this.nodes.input); } /** * Select LinkTool input content by CMD+A * * @param {KeyboardEvent} event - keydown */ selectLinkUrl(w2) { w2.preventDefault(), w2.stopPropagation(); const d2 = window.getSelection(), v2 = new Range(), a2 = d2.anchorNode.parentNode.closest(`.${this.CSS.inputHolder}`).querySelector(`.${this.CSS.inputEl}`); v2.selectNodeContents(a2), d2.removeAllRanges(), d2.addRange(v2); } /** * Prepare link preview holder * * @returns {HTMLElement} */ prepareLinkPreview() { const w2 = this.make("a", this.CSS.linkContent, { target: "_blank", rel: "nofollow noindex noreferrer" }); return this.nodes.linkImage = this.make("div", this.CSS.linkImage), this.nodes.linkTitle = this.make("div", this.CSS.linkTitle), this.nodes.linkDescription = this.make("p", this.CSS.linkDescription), this.nodes.linkText = this.make("span", this.CSS.linkText), w2; } /** * Compose link preview from fetched data * * @param {metaData} meta - link meta data */ showLinkPreview({ image: w2, title: d2, description: v2 }) { this.nodes.container.appendChild(this.nodes.linkContent), w2 && w2.url && (this.nodes.linkImage.style.backgroundImage = "url(" + w2.url + ")", this.nodes.linkContent.appendChild(this.nodes.linkImage)), d2 && (this.nodes.linkTitle.textContent = d2, this.nodes.linkContent.appendChild(this.nodes.linkTitle)), v2 && (this.nodes.linkDescription.textContent = v2, this.nodes.linkContent.appendChild(this.nodes.linkDescription)), this.nodes.linkContent.classList.add(this.CSS.linkContentRendered), this.nodes.linkContent.setAttribute("href", this.data.link), this.nodes.linkContent.appendChild(this.nodes.linkText); try { this.nodes.linkText.textContent = new URL(this.data.link).hostname; } catch { this.nodes.linkText.textContent = this.data.link; } } /** * Show loading progress bar */ showProgress() { this.nodes.progress.classList.add(this.CSS.progressLoading); } /** * Hide loading progress bar * * @returns {Promise} */ hideProgress() { return new Promise((w2) => { this.nodes.progress.classList.remove(this.CSS.progressLoading), this.nodes.progress.classList.add(this.CSS.progressLoaded), setTimeout(w2, 500); }); } /** * If data fetching failed, set input error style */ applyErrorStyle() { this.nodes.inputHolder.classList.add(this.CSS.inputError), this.nodes.progress.remove(); } /** * Sends to backend pasted url and receives link data * * @param {string} url - link source url */ async fetchLinkData(w2) { this.showProgress(), this.data = { link: w2 }; try { const { body: d2 } = await R.get({ url: this.config.endpoint, headers: this.config.headers, data: { url: w2 } }); this.onFetch(d2); } catch { this.fetchingFailed(this.api.i18n.t("Couldn't fetch the link data")); } } /** * Link data fetching callback * * @param {UploadResponseFormat} response - backend response */ onFetch(w2) { if (!w2 || !w2.success) { this.fetchingFailed(this.api.i18n.t("Couldn't get this link data, try the other one")); return; } const d2 = w2.meta, v2 = w2.link || this.data.link; if (this.data = { meta: d2, link: v2 }, !d2) { this.fetchingFailed(this.api.i18n.t("Wrong response format from the server")); return; } this.hideProgress().then(() => { this.nodes.inputHolder.remove(), this.showLinkPreview(d2); }); } /** * Handle link fetching errors * * @private * * @param {string} errorMessage - message to explain user what he should do */ fetchingFailed(w2) { this.api.notifier.show({ message: w2, style: "error" }), this.applyErrorStyle(); } /** * Helper method for elements creation * * @param {string} tagName - name of creating element * @param {string|string[]} [classNames] - list of CSS classes to add * @param {object} [attributes] - object with attributes to add * @returns {HTMLElement} */ make(w2, d2 = null, v2 = {}) { const c2 = document.createElement(w2); Array.isArray(d2) ? c2.classList.add(...d2) : d2 && c2.classList.add(d2); for (const i in v2) c2[i] = v2[i]; return c2; } } document.addEventListener("DOMContentLoaded", function() { const editorContainer = document.getElementById("editorjs"); if (!editorContainer) { console.warn("Editor.js container not found"); return; } const contentJsonInput = document.getElementById("content_json"); const contentHtmlInput = document.getElementById("content_html"); const contentInput = document.getElementById("content"); const excerptInput = document.getElementById("excerpt"); document.getElementById("featured_image"); document.getElementById("status"); function convertHtmlToEditorJs(html) { if (!html || html.trim() === "") { return null; } const tempDiv = document.createElement("div"); tempDiv.innerHTML = html.trim(); const blocks = []; let blockId = 0; function processNode(node) { var _a2, _b, _c, _d; if (node.nodeType === Node.TEXT_NODE) { const text = node.textContent.trim(); if (text) { blocks.push({ type: "paragraph", data: { text }, id: `block-${blockId++}` }); } return; } if (node.nodeType !== Node.ELEMENT_NODE) { return; } const tagName = node.tagName.toLowerCase(); switch (tagName) { case "p": const pText = node.textContent.trim(); if (pText) { blocks.push({ type: "paragraph", data: { text: pText }, id: `block-${blockId++}` }); } break; case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": const level = parseInt(tagName.charAt(1)); const headerText = node.textContent.trim(); if (headerText) { blocks.push({ type: "header", data: { text: headerText, level }, id: `block-${blockId++}` }); } break; case "ul": case "ol": const items = []; const listItems = node.querySelectorAll("li"); listItems.forEach((li2) => { const itemText = li2.textContent.trim(); if (itemText) { items.push(itemText); } }); if (items.length > 0) { blocks.push({ type: "list", data: { style: tagName === "ol" ? "ordered" : "unordered", items }, id: `block-${blockId++}` }); } break; case "blockquote": const quoteText = ((_a2 = node.querySelector("p")) == null ? void 0 : _a2.textContent.trim()) || node.textContent.trim(); const quoteCaption = ((_b = node.querySelector("cite")) == null ? void 0 : _b.textContent.trim()) || ""; if (quoteText) { blocks.push({ type: "quote", data: { text: quoteText, caption: quoteCaption }, id: `block-${blockId++}` }); } break; case "pre": const codeText = ((_c = node.querySelector("code")) == null ? void 0 : _c.textContent) || node.textContent.trim(); if (codeText) { blocks.push({ type: "code", data: { code: codeText }, id: `block-${blockId++}` }); } break; case "table": const rows = []; const tableRows = node.querySelectorAll("tr"); tableRows.forEach((tr2) => { const cells = []; const tableCells = tr2.querySelectorAll("td, th"); tableCells.forEach((cell) => { cells.push(cell.textContent.trim()); }); if (cells.length > 0) { rows.push(cells); } }); if (rows.length > 0) { blocks.push({ type: "table", data: { content: rows }, id: `block-${blockId++}` }); } break; case "hr": blocks.push({ type: "delimiter", data: {}, id: `block-${blockId++}` }); break; case "figure": case "img": const img = node.tagName === "img" ? node : node.querySelector("img"); if (img && img.src) { const caption = ((_d = node.querySelector("figcaption")) == null ? void 0 : _d.textContent.trim()) || img.alt || ""; blocks.push({ type: "image", data: { file: { url: img.src }, caption }, id: `block-${blockId++}` }); } break; default: Array.from(node.childNodes).forEach((child) => { processNode(child); }); break; } } Array.from(tempDiv.childNodes).forEach((child) => { processNode(child); }); if (blocks.length === 0) { blocks.push({ type: "paragraph", data: { text: "" }, id: `block-${blockId++}` }); } return { time: Date.now(), blocks, version: "2.31.0" }; } let initialData = null; if (contentJsonInput && contentJsonInput.value) { try { initialData = JSON.parse(contentJsonInput.value); } catch (e) { console.error("Failed to parse initial JSON:", e); } } if (!initialData) { const htmlContent = contentHtmlInput && contentHtmlInput.value ? contentHtmlInput.value : contentInput && contentInput.value ? contentInput.value : ""; if (htmlContent) { console.log("Converting HTML to Editor.js format..."); initialData = convertHtmlToEditorJs(htmlContent); if (initialData && contentJsonInput) { contentJsonInput.value = JSON.stringify(initialData); } } } const editor = new Aa({ holder: "editorjs", data: initialData, placeholder: "Mulai menulis konten...", tools: { header: { class: v$3, config: { placeholder: "Masukkan heading", levels: [1, 2, 3, 4, 5, 6], defaultLevel: 2 }, inlineToolbar: true }, list: { class: G$1, inlineToolbar: true, config: { defaultStyle: "unordered" } }, quote: { class: m$1, inlineToolbar: true, shortcut: "CMD+SHIFT+O", config: { quotePlaceholder: "Masukkan kutipan", captionPlaceholder: "Penulis kutipan" } }, code: { class: d, config: { placeholder: "Masukkan kode" } }, table: { class: F$1, inlineToolbar: true, config: { rows: 2, cols: 2 } }, delimiter: n, image: { class: P$1, config: { endpoints: { byFile: window.uploadEndpoint || "/admin/upload" }, field: "image", types: "image/jpeg,image/png,image/webp", captionPlaceholder: "Masukkan caption gambar", buttonContent: "Pilih gambar", uploader: { async uploadByFile(file) { const formData = new FormData(); formData.append("image", file); formData.append(window.csrfTokenName, window.csrfTokenValue); const response = await fetch(window.uploadEndpoint || "/admin/upload", { method: "POST", headers: { [window.csrfHeaderName]: window.csrfTokenValue }, body: formData }); if (!response.ok) { throw new Error("Upload failed"); } const result = await response.json(); return { success: 1, file: { url: result.url } }; } } } }, linkTool: { class: I, config: { endpoint: window.linkPreviewEndpoint || "/admin/link-preview" } } }, autofocus: false, onChange: async () => { clearTimeout(window.autosaveTimeout); window.autosaveTimeout = setTimeout(async () => { await saveEditorContent(true); }, 1e4); } }); async function saveEditorContent(isAutosave = false) { try { const outputData = await editor.save(); const jsonString = JSON.stringify(outputData); if (contentJsonInput) { contentJsonInput.value = jsonString; } const htmlContent = renderEditorJsToHtml(outputData.blocks); if (contentHtmlInput) { contentHtmlInput.value = htmlContent; } const firstParagraph = outputData.blocks.find((b2) => b2.type === "paragraph"); if (firstParagraph && excerptInput) { const excerpt = firstParagraph.data.text.substring(0, 160).replace(/<[^>]*>/g, ""); excerptInput.value = excerpt; } if (isAutosave && window.pageId) { const formData = new FormData(); formData.append("content_json", jsonString); formData.append("content_html", htmlContent); formData.append(window.csrfTokenName, window.csrfTokenValue); await fetch(`/admin/pages/autosave/${window.pageId}`, { method: "POST", headers: { [window.csrfHeaderName]: window.csrfTokenValue }, body: formData }); const indicator = document.getElementById("autosave-indicator"); if (indicator) { indicator.textContent = "Disimpan otomatis"; indicator.classList.remove("hidden"); setTimeout(() => { indicator.classList.add("hidden"); }, 2e3); } } return outputData; } catch (error) { console.error("Error saving editor content:", error); throw error; } } function renderEditorJsToHtml(blocks) { let html = ""; blocks.forEach((block) => { var _a2; switch (block.type) { case "paragraph": html += `

    ${escapeHtml(block.data.text)}

    `; break; case "header": html += `${escapeHtml(block.data.text)}`; break; case "list": const listTag = block.data.style === "ordered" ? "ol" : "ul"; html += `<${listTag}>`; block.data.items.forEach((item) => { html += `
  • ${escapeHtml(item)}
  • `; }); html += ``; break; case "quote": html += `

    ${escapeHtml(block.data.text)}

    `; if (block.data.caption) { html += `${escapeHtml(block.data.caption)}`; } html += `
    `; break; case "code": html += `
    ${escapeHtml(block.data.code)}
    `; break; case "table": html += ""; block.data.content.forEach((row) => { html += ""; row.forEach((cell) => { html += ``; }); html += ""; }); html += "
    ${escapeHtml(cell)}
    "; break; case "delimiter": html += "
    "; break; case "image": html += `
    ${escapeHtml(block.data.caption || `; if (block.data.caption) { html += `
    ${escapeHtml(block.data.caption)}
    `; } html += "
    "; break; case "linkTool": html += `
    `; break; default: console.warn("Unknown block type:", block.type); } }); return html; } function escapeHtml(text) { if (!text) return ""; const div = document.createElement("div"); div.textContent = text; return div.innerHTML; } const form = editorContainer.closest("form"); if (form) { form.addEventListener("submit", async function(e) { e.preventDefault(); try { await saveEditorContent(false); form.submit(); } catch (error) { console.error("Error saving before submit:", error); alert("Error saat menyimpan konten. Silakan coba lagi."); } }); } const previewBtn = document.getElementById("preview-btn"); if (previewBtn) { previewBtn.addEventListener("click", async function() { try { const outputData = await editor.save(); const htmlContent = renderEditorJsToHtml(outputData.blocks); const previewWindow = window.open("", "_blank"); previewWindow.document.write(` Preview ${htmlContent} `); } catch (error) { console.error("Error generating preview:", error); alert("Error saat membuat preview."); } }); } console.log("Editor.js initialized successfully"); }); })();