{"version":3,"file":"wysiwyg4all.cjs","mappings":"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","sources":["webpack://wysiwyg4all/webpack/bootstrap","webpack://wysiwyg4all/webpack/runtime/define property getters","webpack://wysiwyg4all/webpack/runtime/hasOwnProperty shorthand","webpack://wysiwyg4all/webpack/runtime/make namespace object","webpack://wysiwyg4all/./node_modules/colormangle/colormangle.js","webpack://wysiwyg4all/./wysiwyg4all.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const colorNames = {\n    aliceblue: \"#f0f8ff\",\n    antiquewhite: \"#faebd7\",\n    aqua: \"#00ffff\",\n    aquamarine: \"#7fffd4\",\n    azure: \"#f0ffff\",\n    beige: \"#f5f5dc\",\n    bisque: \"#ffe4c4\",\n    black: \"#000000\",\n    blanchedalmond: \"#ffebcd\",\n    blue: \"#0000ff\",\n    blueviolet: \"#8a2be2\",\n    brown: \"#a52a2a\",\n    burlywood: \"#deb887\",\n    cadetblue: \"#5f9ea0\",\n    chartreuse: \"#7fff00\",\n    chocolate: \"#d2691e\",\n    coral: \"#ff7f50\",\n    cornflowerblue: \"#6495ed\",\n    cornsilk: \"#fff8dc\",\n    crimson: \"#dc143c\",\n    cyan: \"#00ffff\",\n    darkblue: \"#00008b\",\n    darkcyan: \"#008b8b\",\n    darkgoldenrod: \"#b8860b\",\n    darkgray: \"#a9a9a9\",\n    darkgreen: \"#006400\",\n    darkgrey: \"#a9a9a9\",\n    darkkhaki: \"#bdb76b\",\n    darkmagenta: \"#8b008b\",\n    darkolivegreen: \"#556b2f\",\n    darkorange: \"#ff8c00\",\n    darkorchid: \"#9932cc\",\n    darkred: \"#8b0000\",\n    darksalmon: \"#e9967a\",\n    darkseagreen: \"#8fbc8f\",\n    darkslateblue: \"#483d8b\",\n    darkslategray: \"#2f4f4f\",\n    darkslategrey: \"#2f4f4f\",\n    darkturquoise: \"#00ced1\",\n    darkviolet: \"#9400d3\",\n    deeppink: \"#ff1493\",\n    deepskyblue: \"#00bfff\",\n    dimgray: \"#696969\",\n    dimgrey: \"#696969\",\n    dodgerblue: \"#1e90ff\",\n    firebrick: \"#b22222\",\n    floralwhite: \"#fffaf0\",\n    forestgreen: \"#228b22\",\n    fuchsia: \"#ff00ff\",\n    gainsboro: \"#dcdcdc\",\n    ghostwhite: \"#f8f8ff\",\n    goldenrod: \"#daa520\",\n    gold: \"#ffd700\",\n    gray: \"#808080\",\n    green: \"#008000\",\n    greenyellow: \"#adff2f\",\n    grey: \"#808080\",\n    honeydew: \"#f0fff0\",\n    hotpink: \"#ff69b4\",\n    indianred: \"#cd5c5c\",\n    indigo: \"#4b0082\",\n    ivory: \"#fffff0\",\n    khaki: \"#f0e68c\",\n    lavenderblush: \"#fff0f5\",\n    lavender: \"#e6e6fa\",\n    lawngreen: \"#7cfc00\",\n    lemonchiffon: \"#fffacd\",\n    lightblue: \"#add8e6\",\n    lightcoral: \"#f08080\",\n    lightcyan: \"#e0ffff\",\n    lightgoldenrodyellow: \"#fafad2\",\n    lightgray: \"#d3d3d3\",\n    lightgreen: \"#90ee90\",\n    lightgrey: \"#d3d3d3\",\n    lightpink: \"#ffb6c1\",\n    lightsalmon: \"#ffa07a\",\n    lightseagreen: \"#20b2aa\",\n    lightskyblue: \"#87cefa\",\n    lightslategray: \"#778899\",\n    lightslategrey: \"#778899\",\n    lightsteelblue: \"#b0c4de\",\n    lightyellow: \"#ffffe0\",\n    lime: \"#00ff00\",\n    limegreen: \"#32cd32\",\n    linen: \"#faf0e6\",\n    magenta: \"#ff00ff\",\n    maroon: \"#800000\",\n    mediumaquamarine: \"#66cdaa\",\n    mediumblue: \"#0000cd\",\n    mediumorchid: \"#ba55d3\",\n    mediumpurple: \"#9370db\",\n    mediumseagreen: \"#3cb371\",\n    mediumslateblue: \"#7b68ee\",\n    mediumspringgreen: \"#00fa9a\",\n    mediumturquoise: \"#48d1cc\",\n    mediumvioletred: \"#c71585\",\n    midnightblue: \"#191970\",\n    mintcream: \"#f5fffa\",\n    mistyrose: \"#ffe4e1\",\n    moccasin: \"#ffe4b5\",\n    navajowhite: \"#ffdead\",\n    navy: \"#000080\",\n    oldlace: \"#fdf5e6\",\n    olive: \"#808000\",\n    olivedrab: \"#6b8e23\",\n    orange: \"#ffa500\",\n    orangered: \"#ff4500\",\n    orchid: \"#da70d6\",\n    palegoldenrod: \"#eee8aa\",\n    palegreen: \"#98fb98\",\n    paleturquoise: \"#afeeee\",\n    palevioletred: \"#db7093\",\n    papayawhip: \"#ffefd5\",\n    peachpuff: \"#ffdab9\",\n    peru: \"#cd853f\",\n    pink: \"#ffc0cb\",\n    plum: \"#dda0dd\",\n    powderblue: \"#b0e0e6\",\n    purple: \"#800080\",\n    rebeccapurple: \"#663399\",\n    red: \"#ff0000\",\n    rosybrown: \"#bc8f8f\",\n    royalblue: \"#4169e1\",\n    saddlebrown: \"#8b4513\",\n    salmon: \"#fa8072\",\n    sandybrown: \"#f4a460\",\n    seagreen: \"#2e8b57\",\n    seashell: \"#fff5ee\",\n    sienna: \"#a0522d\",\n    silver: \"#c0c0c0\",\n    skyblue: \"#87ceeb\",\n    slateblue: \"#6a5acd\",\n    slategray: \"#708090\",\n    slategrey: \"#708090\",\n    snow: \"#fffafa\",\n    springgreen: \"#00ff7f\",\n    steelblue: \"#4682b4\",\n    tan: \"#d2b48c\",\n    teal: \"#008080\",\n    thistle: \"#d8bfd8\",\n    tomato: \"#ff6347\",\n    turquoise: \"#40e0d0\",\n    violet: \"#ee82ee\",\n    wheat: \"#f5deb3\",\n    white: \"#ffffff\",\n    whitesmoke: \"#f5f5f5\",\n    yellow: \"#ffff00\",\n    yellowgreen: \"#9acd32\",\n};\n\nclass ColorMangle {\n    /**\n     * @param {string} [color='#4848db'] - Argument string can be either color name string or any type of HTML color codes (hex, rgb, hsl).\n     */\n    constructor(color = '#4848db', fineTuned = true) {\n        this.fineTuned = fineTuned;\n\n        let format = this._colorType(color);\n        this.type = format.type;\n        this.color = format.color;\n    }\n\n    _colorType(color = this.color, throwErr = true) {\n        let chkType, type;\n\n        try {\n            if (!color)\n                throw 'invalid color';\n\n            if (typeof color === 'object' && color.string)\n                color = color.string;\n\n            if (typeof color === 'string')\n                color = color.toLowerCase();\n            else\n                throw 'invalid color';\n\n            if (color === this.color)\n                return { type: this.type, color: this.color };\n\n            if (colorNames[color])\n                return { type: 'hex', color: colorNames[color] };\n\n            chkType = color.match(/^(rgba?|rgb?|hsla?|#)/g);\n\n            if (Array.isArray(chkType)) {\n\n                if (chkType[0] === '#') {\n\n                    if (color.length === 4)\n                        // convert shorthand hex\n                        color = color[0] + color[1] + color[1] + color[2] + color[2] + color[3] + color[3];\n\n                    if (/^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(color))\n                        // is valid hex\n                        type = 'hex';\n\n                    else\n                        throw 'invalid hex';\n\n                } else if (color[color.length - 1] === ')')\n                    // hex, rgb, rgba, hsl, hsla\n                    type = chkType[0];\n\n                return { type, color };\n\n            }\n\n        } catch (err) {\n            if (throwErr)\n                throw err + ':' + color;\n        }\n\n        return {};\n    }\n\n    _extractDigit(color_arg = this.color) {\n        let { type = this.type, color = this.color } = this._colorType(color_arg);\n\n        if (type === 'hex')\n            color = this.rgba(1, color).string;\n\n        const value = [];\n\n        for (const i of color.match(/\\d+(\\.\\d+)?/g))\n            value.push(parseFloat(i));\n\n        if (value.length < 4) value.push(1);\n\n        return value;\n    }\n\n    /**\n     * @return {number} - Retrieves color alpha value (range 0 ~ 1)\n     */\n    getAlpha(color_arg = this.color) {\n        let extract = this._extractDigit(color_arg);\n        return extract ? extract[3] || 1 : 1;\n    }\n\n    /**\n     * Generates color scheme object.\n     * @typedef {Object} colorScheme\n     * @property {string} --alert\n     * @property {string} --alert-text\n     * @property {string} --analogous\n     * @property {string} --analogous-text\n     * @property {string} --background\n     * @property {string} --background-focus\n     * @property {string} --background-focus-text\n     * @property {string} --background-text\n     * @property {string} --background-text_focus\n     * @property {string} --button\n     * @property {string} --button-text\n     * @property {string} --complementary\n     * @property {string} --complementary-text\n     * @property {string} --content\n     * @property {string} --content-focus\n     * @property {string} --content-focus-text\n     * @property {string} --content-text\n     * @property {string} --content-text_focus\n     * @property {string} --focus\n     * @property {string} --focus-text\n     * @property {string} --placeholder\n     * @property {string} --saturate\n     * @property {string} --saturate-text\n     * @property {string} --success\n     * @property {string} --success-text\n     * @property {string} --text-button\n     * @param {string} [color=this.color] - Focus color for color scheme\n     * @param {boolean} [darkMode=false] - Dark mode when true\n     * @return {colorScheme} - { [&lt;CSS Variable names&gt;] : &lt;string | HTML color string&gt; }\n     */\n    colorScheme(color = this.color, darkMode = false) {\n\n        let opacity = {\n            text: { black: 0.88, white: 1 },\n            // soft: { black: 0.66, white: 0.88 },\n            placeholder: { black: 0.44, white: 0.55 },\n            // transparent: { black: 0.22, white: 0.33 },\n            // shade: { black: 0.066, white: 0.11 },\n            // shadow: { black: 0.033, white: 0.066 }\n        };\n\n        let template = {\n            '--background': darkMode ? '#121212' : '#f7f7f7',\n            '--content': darkMode ? '#2b2b2b' : '#ffffff',\n            // '--toolbar': darkMode ? '#2b2b2b' : '#ffffff'\n        };\n\n        let focusOriginal;\n        let focusSat;\n        let content_isHighLuminance = this.isHighLuminance(template['--content']);\n        let focus = (() => {\n            if (color && typeof color === 'object') {\n                if (color['--button']) {\n                    focusOriginal = color['--button'];\n                    return focusOriginal;\n                }\n                for (let key of color)\n                    if (key.includes('focus')) {\n                        focusOriginal = color[key];\n                        return focusOriginal;\n                    }\n            }\n\n            focusOriginal = color;\n            focusSat = this.matchLuminance(color, template['--content'], content_isHighLuminance ? 1.5 : 4.5);\n            return darkMode ? focusSat : color;\n        })();\n\n        let compDir = 1;\n        let analogous = (() => {\n            let deg = 30;\n            let analogous = this.analogous(focusOriginal, deg);\n            let focusHSL = this.hsla(1, focusOriginal).h;\n            let an1HSL = this.hsla(1, analogous[0]).h;\n            let an2HSL = this.hsla(1, analogous[1]).h;\n\n            if (focusHSL + deg > 360)\n                an1HSL = an1HSL + 360;\n            if (focusHSL - deg < 0)\n                an2HSL = 360 - an2HSL;\n\n            if (Math.abs(focusHSL - an1HSL) > Math.abs(focusHSL - an2HSL)) {\n                compDir = -1;\n                return analogous[1];\n            }\n\n            return analogous[0];\n        })();\n\n        let complementary = this.matchLuminance(this.complementary(focus, 60 * compDir), template['--background'], 3.1);\n        let fixedValue = {\n            // '--shadow': 'rgba(0, 0, 0, 0.033)',\n            // '--shade': 'rgba(0, 0, 0, 0.066)',\n            // '--transparent': 'rgba(0, 0, 0, 0.22)',\n            '--placeholder': darkMode ? 'rgba(255, 255, 255, 0.55)' : 'rgba(0, 0, 0, 0.44)'\n        };\n\n        let darkModeAnalogous = darkMode ? this.matchLuminance(analogous, template['--background'], 4.5) : analogous;\n        let analogousNude = this.matchLuminance(analogous, template['--background'], 4.5);\n\n        for (let k in template) {\n            template[k + '-text'] = this.textColor(opacity.text, template[k]);\n            template[k + '-focus'] = k.includes('--background') ? darkModeAnalogous : focus;\n            template[k + '-text_focus'] = k.includes('--background') ? analogousNude : this.matchLuminance(darkMode ? focus : focusSat, template[k], 1.66);\n            template[k + '-focus-text'] = this.textColor(1, k.includes('--background') ? darkModeAnalogous : focus);\n        }\n\n        template['--focus'] = focusOriginal;\n        template['--focus-text'] = this.textColor(1, focusOriginal);\n        template['--saturate'] = focusSat;\n        template['--saturate-text'] = this.textColor(1, focusSat);\n\n        Object.assign(template, {\n            '--complementary': complementary,\n            '--complementary-text': this.textColor(1, complementary),\n            '--analogous': analogous,\n            '--analogous-text': this.textColor(1, analogous),\n            '--alert': 'tomato',\n            // '--alert-text': 'white',\n            '--success': 'limegreen',\n            // '--success-text': 'black',\n            '--button': focus,\n            '--text-button': darkMode ? this.matchLuminance(focusSat, template[\"--content\"], 7) : this.contrastRatio(template[\"--content\"], focusSat) < 4.5 ? \"inherit\" : focusSat,\n            '--button-text': this.textColor(1, focus)\n        });\n\n        // for (let k in template) {\n        //     if (!template[k] || template[k] === \"\")\n        //         continue;\n\n        //     let highLum = this.isHighLuminance(template[k]);\n        //     for (let op of ['soft', 'placeholder', 'transparent', 'shadow', 'shade']) {\n\n        //         template[k + '_' + op] = this.rgba(opacity[op][highLum ? 'white' : 'black'], template[k]).string;\n        //     }\n        // }\n\n        // template['--button-border'] = (() => {\n        //     let focus_isHighLuminance = this.isHighLuminance(focus);\n        //     let border = this.matchLuminance(this.adjustLuminance(-1, template['--button']), template['--button'], 1.15, -1, focus_isHighLuminance ? 'luminance' : 'brightness');\n        //     return focus_isHighLuminance ? this.rgba(0.5, border).string : border;\n        // })();\n\n        if (color && typeof color === 'object') {\n            for (let key of color)\n                if (key[0] !== '-')\n                    throw 'invalid color scheme';\n            Object.assign(template, color);\n        }\n\n        let unordered = Object.assign(template, fixedValue);\n        return Object.keys(unordered).sort().reduce(\n            (obj, key) => {\n                obj[key] = unordered[key];\n                return obj;\n            },\n            {}\n        );\n    }\n\n    /**\n     * Match luminance of target_color with base color\n     * @param {string} target_color - Target color\n     * @param {string} [color_arg=this.color] - Base color\n     * @param {number} [target_ratio] - Set contrast ratio difference\n     * @param {number} [direction] - Adjust direction. Adjust to darker luminance when -1. Brighter when 1, otherwise auto.\n     * @param {string} [method] - Luminance adjustment mode: 'brightness | luminance | saturation'\n     * @return {string} - HTML color string\n     */\n    matchLuminance(target_color, color_arg = this.color, target_ratio, direction, method) {\n        let { color } = this._colorType(color_arg);\n        let target = this._colorType(target_color).color;\n\n        if (target_ratio) {\n            let adj = target;\n            let m = this.contrastRatio(adj, color);\n            if (m < target_ratio) {\n                let dir = direction || this.isHighLuminance(color) ? -1 : 1;\n                let count = 100;\n                while (m < target_ratio && count--) {\n                    let adj_set;\n\n                    switch (method) {\n                        case 'brightness':\n                            adj_set = this.adjustBrightness(1 * dir, adj);\n                            break;\n                        case 'luminance':\n                            adj_set = this.adjustLuminance(1 * dir, adj);\n                            break;\n                        default:\n                            adj_set = this.adjustBrightness(1 * dir, { legacy: true, color: adj });\n                    }\n\n                    if (adj === adj_set)\n                        break;\n                    adj = adj_set;\n\n                    m = this.contrastRatio(adj, color);\n                }\n            }\n            return this.hex(adj);\n        } else {\n            let main_lum = this._luminance(color);\n            let lum = this._luminance(target);\n\n            if (Math.abs(lum - main_lum) < 0.01)\n                return target;\n\n            let adj = this.hex(target);\n\n            let dir = (lum, main_lum) => {\n                return lum < main_lum ? 1 : -1;\n            };\n\n            let currDir = dir(lum, main_lum);\n            while (Math.abs(lum - main_lum) > 0.01 && currDir === dir(lum, main_lum)) {\n                let adj_set;\n                switch (method) {\n                    case 'saturation':\n                        adj_set = this.adjustBrightness(currDir, { color: adj, legacy: true });\n                        break;\n                    case 'luminance':\n                        adj_set = this.adjustLuminance(currDir, adj);\n                        break;\n                    default:\n                        adj_set = this.adjustBrightness(currDir, adj);\n                }\n                let lum_pre = this._luminance(adj_set);\n                if (lum_pre === lum || currDir !== dir(lum_pre, main_lum))\n                    break;\n                lum = lum_pre;\n                adj = adj_set;\n            }\n            return this.hex(adj);\n        }\n    }\n\n    /**\n     * Generate analogous color\n     * @param {string} [color_arg=this.color] - Target color\n     * @param {number} [deg=30] - Amount of hue separation\n     * @return {Array} - 2 analogous color is returned. [&lt;hsla color&gt;, ... ]\n     */\n    analogous(color_arg = this.color, deg = 30) {\n        let { color } = this._colorType(color_arg);\n\n        let spin = (h, v) => {\n            let val = h + v;\n            return val < 0 ? 360 + val : val > 360 ? val - 360 : val;\n        };\n\n        let hsl = this.hsla(this.getAlpha(color), color);\n        let plus = 'hsla(' + spin(hsl.h, deg) + ', ' + hsl.s + '%, ' + hsl.l + '%, ' + hsl.a + ')';\n        let minus = 'hsla(' + spin(hsl.h, -deg) + ', ' + hsl.s + '%, ' + hsl.l + '%, ' + hsl.a + ')';\n\n        return [this.matchLuminance(plus, color), this.matchLuminance(minus, color)];\n    }\n\n    /**\n     * Generate complementary color\n     * @param {string} [color_arg=this.color] - Target color\n     * @param {number} [add=0] - Add or subtract hue from complementary color\n     * @return {string} - HEX color string\n     */\n    complementary(color_arg = this.color, add = 0) {\n        let { color } = this._colorType(color_arg);\n\n        let hsl = this.hsla(this.getAlpha(color), color);\n\n        if (hsl.h < 180)\n            hsl.h += 180;\n        else\n            hsl.h -= 180;\n\n        hsl.h += add;\n        hsl.h = hsl.h > 360 ? hsl.h - 360 : hsl.h < 0 ? 360 - hsl.h : hsl.h;\n\n        return this.hex(this._toString(hsl));\n    }\n\n    /**\n     * @param {string} [color_arg=this.color] - Target color\n     * @param {boolean} [fineTuned=false] - Custom Color space is applied when true\n     * @return {boolean} - True if color has high luminance\n     */\n    isHighLuminance(color_arg = this.color, fineTuned = this.fineTuned) {\n        const { r, g, b } = this.rgba(1, this._colorType(color_arg).color);\n\n        let yiq =\n            fineTuned ?\n                ((r * (299 - 64)) + (g * (587 * 1.25)) + (b * 114)) / 1000 : // Fine tuned\n                ((r * 299) + (g * 587) + (b * 114)) / 1000; // Standard color space formula\n\n        // Web standard of color space threshold is 128\n        return (yiq >= (fineTuned ? 188 : 128));\n    }\n\n    _luminance(color_arg = this.color) {\n        let rgb = this.rgba(1, color_arg);\n        let a = [rgb.r, rgb.g, rgb.b].map(function (v) {\n            v /= 255;\n            return v <= 0.03928\n                ? v / 12.92\n                : Math.pow((v + 0.055) / 1.055, 2.4);\n        });\n\n        return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;\n    }\n\n    _toString(col) {\n        let numberOrNot = (n, def = 100) => {\n            return typeof n === 'number' ? n : def;\n        };\n        if (typeof col === 'string')\n            return col;\n\n        if (col.hasOwnProperty('h'))\n            return 'hsla(' + (col.h || 0) + ', ' + numberOrNot(col.s) + '%, ' + numberOrNot(col.l) + '%, ' + numberOrNot(col.a, 1) + ')';\n\n        if (col.hasOwnProperty('r'))\n            return 'rgba(' + numberOrNot(col.r) + ', ' + numberOrNot(col.g) + ', ' + numberOrNot(col.b) + ', ' + numberOrNot(col.a, 1) + ')';\n        throw col;\n    }\n\n    /**\n     * Returns contrast ratio between the given color.\n     * Useful to determine if the given color is suitable for text with the constructed color as a background.\n     * @param {string} color_arg1 - Color string you want to compare luminance ratio.\n     * @param {string} [color_arg2=this.color] - Color string you want to compare with color_arg1\n     * @return {number} - Contrast ratio\n     */\n    contrastRatio(color_arg1, color_arg2 = this.color) {\n        let lum1 = this._luminance(color_arg2) + 0.05;\n        let lum2 = this._luminance(color_arg1) + 0.05;\n\n        return lum1 > lum2 ? lum1 / lum2 : lum2 / lum1;\n    }\n\n    /**\n     * Returns suitable text color (Black / White).\n     * @param {(number | Object)} opacity - Can set returning color values opacity.\n     * @param {number} opacity.black - Set returning color values opacity when the result color is black.\n     * @param {number} opacity.white - Set returning color values opacity when the result color is white.\n     * @param {(string|Object)} [option=this.color] - Background color of text\n     * @param {(string|Object)} [option.color=this.color] - Background color of text\n     * @param {(string|Object)} [option.fineTuned=true] - Follows standard color space calculation when false\n     * @return {string | null} - HTML color string\n     */\n    textColor(opacity = 1, option = this.color) {\n\n        if (typeof option === 'string')\n            option = { color: option };\n\n        let { color = this.color, fineTuned = true } = option;\n\n        color = this._colorType(color).color;\n\n        // returns null if color opacity is below 0.5\n        if (this.getAlpha(color) < 0.5)\n            return \"\";\n\n        let blackOpacity, whiteOpacity;\n\n        if (typeof opacity === 'number' && opacity < 1) {\n            blackOpacity = opacity;\n            whiteOpacity = opacity;\n        } else if (opacity && typeof opacity === 'object') {\n            for (let k of ['black', 'white']) {\n                let opa = opacity[k];\n                if (typeof opa === 'number' && opa < 1) {\n                    if (k === 'black')\n                        blackOpacity = opa;\n                    else if (k === 'white')\n                        whiteOpacity = opa;\n                }\n            }\n        }\n\n        const opa = (v) => {\n            if (typeof v === 'number') {\n                if (v < 1 && v > 0) return v;\n                else if (v > 1) return 1;\n                else return 0;\n            } else return 1;\n        };\n\n        if (this.isHighLuminance(color, fineTuned))\n            return blackOpacity ? `rgba(0, 0, 0, ${opa(blackOpacity)})` : 'black';\n\n        return whiteOpacity ? `rgba(255, 255, 255, ${opa(whiteOpacity)})` : 'white';\n    }\n\n    /**\n     * Returns hsla color\n     * @param {number} [opacity] - Set opacity for returning color value.\n     * @param {string} [color_arg=this.color] - Color to convert to hsla string\n     * @return {Object} - { h: &lt;number&gt;, s: &lt;number&gt;, l: &lt;number&gt;, r: &lt;number&gt;, g: &lt;number&gt;, b: &lt;number&gt;, a: &lt;number&gt;, string: &lt;string | rgba color string&gt; }\n     */\n    hsla(opacity, color_arg = this.color) {\n        const { type = this.type, color = this.color } = this._colorType(color_arg);\n\n        const hsl = (r, g, b) => {\n            r /= 255;\n            g /= 255;\n            b /= 255;\n\n            let c_min = Math.min(r, g, b),\n                c_max = Math.max(r, g, b),\n                delta = c_max - c_min,\n                h = 0,\n                s = 0,\n                l = 0;\n\n            if (delta === 0)\n                h = 0;\n            else if (c_max === r)\n                h = ((g - b) / delta) % 6;\n            else if (c_max === g)\n                h = (b - r) / delta + 2;\n            else\n                h = (r - g) / delta + 4;\n\n            h = Math.round(h * 60);\n\n            if (h < 0) h += 360;\n\n            l = (c_max + c_min) / 2;\n            s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));\n            s = +(s * 100).toFixed(1);\n            l = +(l * 100).toFixed(1);\n            return { h, s, l };\n        };\n\n        if (type === 'hex') {\n            opacity = typeof opacity === 'number' ? opacity : 1;\n            const rgba = this.rgba(opacity, color);\n            const { r, g, b, a } = rgba;\n            const { h, s, l } = hsl(r, g, b);\n\n            return {\n                r, g, b, a,\n                h: h,\n                s: s,\n                l: l,\n                string: this._toString({ h, s, l, a: opacity })\n            };\n\n        } else {\n\n            const digit = this._extractDigit(color);\n            opacity = typeof opacity === 'number' ? opacity : digit[3] || 1;\n\n            if (type.includes('hsl')) {\n                const { r, g, b, a } = this.rgba(opacity, color);\n\n                return {\n                    r, g, b, a,\n                    h: digit[0],\n                    s: digit[1],\n                    l: digit[2],\n                    string: this._toString({\n                        h: digit[0],\n                        s: digit[1],\n                        l: digit[2],\n                        a\n                    })\n                };\n\n            } else if (type.includes('rgb')) {\n                const value = {\n                    r: digit[0],\n                    g: digit[1],\n                    b: digit[2],\n                    a: opacity\n                };\n                const { h, s, l } = hsl(value.r, value.g, value.b);\n\n                return Object.assign(value, {\n                    r: value.r,\n                    g: value.g,\n                    b: value.b,\n                    h: h,\n                    s: s,\n                    l: l,\n                    a: value.a,\n                    string: this._toString({ h, s, l, a: value.a })\n                });\n\n            }\n        }\n    }\n\n    /**\n     * Returns hex color string\n     * @param {string} [color_arg=this.color] - Color to convert to hex string\n     * @return {string} - HEX color string\n     */\n    hex(color_arg = this.color) {\n        const { type = this.type, color = this.color } = this._colorType(color_arg);\n\n        if (type.includes('rgb') || type.includes('hsl')) {\n            const rgba = this.rgba(1, color);\n            return '#' + ((1 << 24) + (rgba.r << 16) + (rgba.g << 8) + rgba.b).toString(16).slice(1);\n        }\n\n        return color;\n    }\n\n    /**\n     * Returns rgba color\n     * @param {number} [opacity] - Set opacity of returning color\n     * @param {string} [color_arg=this.color] - Color to convert to rgba string\n     * @return {Object} - { r: &lt;number&gt;, g: &lt;number&gt;, b: &lt;number&gt;, a: &lt;number&gt;, string: &lt;string | HTML color string&gt; }\n     */\n    rgba(opacity, color_arg = this.color) {\n        const { type = this.type, color = this.color } = this._colorType(color_arg);\n\n        if (type === 'hex') {\n            const hex = color;\n            let rgbObject = { r: null, g: null, b: null };\n            let hexValues = hex.match(/[a-fA-F0-9]{2}/g);\n\n            if (hex.length === 4) {\n                hexValues = hex.match(/[a-fA-F0-9]{1}/g);\n                hexValues = hexValues.map(hex => \"\" + hex + hex);\n            }\n            let count = 0;\n            for (const key in rgbObject) {\n                rgbObject[key] = parseInt(hexValues[count], 16);\n                count++;\n            }\n\n            const opacity_value = typeof opacity === 'number' ? opacity : 1;\n            let { r, g, b } = rgbObject;\n\n            return {\n                ...rgbObject,\n                a: opacity_value,\n                string: this._toString({\n                    r: +r, g: +g, b: +b, a: opacity_value\n                })\n            };\n\n        } else {\n            const digit = this._extractDigit(color);\n            const a = typeof opacity === 'number' ? opacity : digit[3] || 1;\n\n            if (type.includes('rgb')) {\n\n                let value = {\n                    r: digit[0],\n                    g: digit[1],\n                    b: digit[2],\n                    a\n                };\n\n                return Object.assign({\n                    string: this._toString(value)\n                }, value);\n\n            } else if (type.includes('hsl')) {\n\n                let h = digit[0];\n                let s = digit[1];\n                let l = digit[2];\n\n                s /= 100;\n                l /= 100;\n\n                let c = (1 - Math.abs(2 * l - 1)) * s,\n                    x = c * (1 - Math.abs((h / 60) % 2 - 1)),\n                    m = l - c / 2,\n                    r = 0,\n                    g = 0,\n                    b = 0;\n                if (0 <= h && h < 60) {\n                    r = c;\n                    g = x;\n                    b = 0;\n                } else if (60 <= h && h < 120) {\n                    r = x;\n                    g = c;\n                    b = 0;\n                } else if (120 <= h && h < 180) {\n                    r = 0;\n                    g = c;\n                    b = x;\n                } else if (180 <= h && h < 240) {\n                    r = 0;\n                    g = x;\n                    b = c;\n                } else if (240 <= h && h < 300) {\n                    r = x;\n                    g = 0;\n                    b = c;\n                } else if (300 <= h && h < 360) {\n                    r = c;\n                    g = 0;\n                    b = x;\n                }\n                r = Math.round((r + m) * 255);\n                g = Math.round((g + m) * 255);\n                b = Math.round((b + m) * 255);\n\n                return {\n                    r, g, b, a,\n                    string: this._toString({ r, g, b, a })\n                };\n\n            }\n        }\n    }\n\n    /**\n     * @param {number} value - Adjust value by percent. range: -100 ~ 100\n     * @param {(string|Object)} [option=this.color] - Color to adjust || additional option.\n     * @param {(string|Object)} [option.color_arg=this.color] - Color to adjust.\n     * @param {(string|Object)} [option.legacy=false] - Legacy adjust mode. Adjust brightness by saturation and luminance.\n     * @return {string} - Brightness adjusted HTML color string\n     */\n    adjustBrightness(value = 0, option = this.color) {\n        let color_arg, legacy = false;\n        if (typeof option === 'string')\n            color_arg = option || this.color;\n        else {\n            color_arg = option.color || this.color;\n            legacy = option.legacy || false;\n        }\n\n        if (legacy) {\n            let { color } = this._colorType(color_arg);\n            let col = this.hsla(this.getAlpha(color), color);\n\n            let limit = (v, limit = 100) => {\n                return v > limit ? limit : v < 0 ? 0 : v;\n            };\n\n            col.s += ((value > 0 ? (100 - col.s) : col.s) / 100) * value;\n            col.s = limit(col.s);\n            col.l += ((value > 0 ? (100 - col.l) : col.l) / 100) * value;\n            col.l = limit(col.l);\n\n            return this._toString(col);\n        }\n\n        let { type = this.type, color = this.color } = this._colorType(color_arg);\n\n        if (value === 0)\n            return color;\n\n        const opacity = type === 'hex' ? 1 : this._extractDigit(color)[3] || 1;\n        const rgb = this.rgba(opacity, color);\n\n        let rgbRange = {\n            r: 0 - rgb['r'],\n            g: 0 - rgb['g'],\n            b: 0 - rgb['b']\n        };\n\n        if (value > 0) {\n            Object.keys(rgbRange).map(function (key) {\n                rgbRange[key] = 255 - rgb[key];\n            });\n        }\n\n        ['r', 'g', 'b'].map(function (key) {\n            rgb[key] += parseInt(rgbRange[key] / 100 * Math.abs(value));\n        });\n\n        const result = 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')';\n\n        if (type === 'hex')\n            return this.hex(result);\n\n        else if (type.includes('rgb'))\n            return this.rgba(rgb.a, result).string;\n\n        else if (type.includes('hsl'))\n            return this.hsla(rgb.a, result).string;\n    }\n\n    /**\n     * @param {number} value - Adjust value by percent. range: -100 ~ 100\n     * @param {string} [color_arg=this.color] - Color to adjust.\n     * @return {string} - Luminance adjusted hsla color string\n     */\n    adjustLuminance(value = 0, color_arg = this.color) {\n        let { color } = this._colorType(color_arg);\n        let col = this.hsla(this.getAlpha(color), color);\n\n        let limit = (v, limit = 100) => {\n            return v > limit ? limit : v < 0 ? 0 : v;\n        };\n\n        col.l += ((value > 0 ? (100 - col.l) : col.l) / 100) * value;\n        col.l = limit(col.l);\n\n        return this._toString(col);\n    }\n\n    /**\n     * @param {number} value - Adjust value by percent. range: -100 ~ 100\n     * @param {string} [color_arg=this.color] - Color to adjust.\n     * @return {string} - Saturation adjusted hsla color string\n     */\n    adjustSaturation(value = 0, color_arg = this.color) {\n        let { color } = this._colorType(color_arg);\n        let col = this.hsla(this.getAlpha(color), color);\n\n        let limit = (v, limit = 100) => {\n            return v > limit ? limit : v < 0 ? 0 : v;\n        };\n\n        col.s += ((value > 0 ? (100 - col.s) : col.s) / 100) * value;\n        col.s = limit(col.s);\n\n        return this._toString(col);\n    }\n}\n\nexport { ColorMangle };","import { ColorMangle } from \"colormangle\";\n\nclass Wysiwyg4All {\n  /**\n   * Wysiwyg4All is a simple framework for building a text editor for your website.\n   * Focused on expandability and customizations.\n   * Additional library ColorMangle is required for text colors.\n   * @param {{}} option - Options\n   * @param {string} option.elementId - ID of target <DIV>.\n   * @param {boolean} [option.editable=true] - When set to false, Wysiwyg will not be editable. By doing this, it can be used as readonly.\n   * @param {string} [option.placeholder=''] - Add placeholder string.\n   * @param {boolean} [option.spellcheck=false] - Set spellcheck to true/false.\n   * @param {string | object} [option.highlightColor='teal'] - Sets the highlight color of the wysiwyg (web color name | hex | rgb | hsl). Or can provide custom color scheme object (more details in api doc).\n   * @param {string} [option.html=''] - HTML string to load on initialization.\n   * @param {function} [option.callback=(cb)=>{return cb}] - Setup callback function. Callback argument contains array of information such as current text style, added images, hashtags, urllinks, selected range... etc.\n   * @param {{} | number} [option.fontSize={desktop:18, tablet: 16, phone: 14}] - Set default font size of each screen size in px. If number is given all screen size will share the same give font size.\n   * @param {boolean} [option.lastLineBlank=false] - When set to true, Blank line will always be added on the last line of wysiwyg.\n   * @param {boolean} [option.hashtag=false] - When set to true, wysiwyg will auto detect hashtag strings.\n   * @param {boolean} [option.urllink=false] - When set to true, wysiwyg will auto detect url strings.\n   * @param {boolean} [option.logMutation=false] - When set to true, wysiwyg will output dom mutation data via callback function.\n   */\n  constructor(option) {\n    console.log(\"Wysiwyg4All 1.0.72\");\n    this.hashtag_regex =\n      /#[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC\\w-]+(?:\\+[\\w-]+)*/g;\n    this.hashtag_stopper_regex =\n      /[^\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC\\w-]/g;\n    this.urllink_regex =\n      /(https?:\\/\\/(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?:\\/\\/(?:www\\.|(?!www))[a-zA-Z0-9]+\\.[^\\s]{2,}|www\\.[a-zA-Z0-9]+\\.[^\\s]{2,})/gi;\n\n    let {\n      elementId = \"\",\n      editable = true,\n      placeholder = \"\",\n      spellcheck = false,\n      highlightColor = \"teal\",\n      html = \"\",\n      callback,\n      fontSize = {\n        desktop: \"18px\",\n        tablet: \"16px\",\n        phone: \"14px\",\n\n        h1: 4.2,\n        h2: 3.56,\n        h3: 2.92,\n        h4: 2.28,\n        h5: 1.64,\n        h6: 1.15,\n        small: 0.8,\n      },\n      lastLineBlank = false,\n      hashtag = false,\n      urllink = false,\n      logMutation = false,\n      logExecution = false,\n    } = option;\n\n    this.hashtag = hashtag;\n    this.urllink = urllink;\n    this.logMutation = logMutation;\n    this.logExecution = logExecution;\n    this.fontSizeCssVariable = {};\n\n    if (typeof fontSize === \"number\")\n      this.fontSizeCssVariable = {\n        \"--wysiwyg-font-desktop\": `${fontSize}`,\n        \"--wysiwyg-font-tablet\": `${fontSize}`,\n        \"--wysiwyg-font-phone\": `${fontSize}`,\n      };\n    else if (typeof fontSize === \"object\" && Object.keys(fontSize).length) {\n      let hold;\n      let keyArr = [\"desktop\", \"tablet\", \"phone\"];\n\n      for (let k of keyArr) {\n        if (fontSize[k]) {\n          hold = fontSize[k];\n          if (typeof hold === \"number\") hold = `${hold}px`;\n        }\n        this.fontSizeCssVariable[`--wysiwyg-font-${k}`] = `${hold}`;\n      }\n    }\n\n    if (!elementId || typeof elementId !== \"string\")\n      throw new Error(\"The wysiwyg element should have an ID\");\n    elementId = elementId[0] === \"#\" ? elementId.substring(1) : elementId;\n\n    this.html = html;\n    this.elementId = elementId[0] === \"#\" ? elementId.substring(1) : elementId;\n    this.placeholder = placeholder;\n    this.spellcheck = spellcheck;\n    this.lastLineBlank = lastLineBlank;\n\n    if (typeof highlightColor === \"string\")\n      highlightColor = new ColorMangle(highlightColor).color;\n\n    this.colorScheme = highlightColor;\n    this.callback = callback || null;\n\n    this.image_array = [];\n    this.hashtag_array = [];\n    this.urllink_array = [];\n    this.custom_array = [];\n\n    this.blockElement_queryArray = [\n      \"HR\",\n      \"BLOCKQUOTE\",\n      \"UL\",\n      \"OL\",\n      // \"LI\",\n      \"._media_\",\n      \"._custom_\",\n    ];\n    this.specialTextElement_queryArray = [\"._hashtag_\", \"._urllink_\"];\n    this.restrictedElement_queryArray = [\"._media_\"]; //, \"._custom_\"\n    this.textAreaElement_queryArray = [\n      \"BLOCKQUOTE\",\n      \"LI\",\n      // \"TD\", \n      // \"TH\"\n    ];\n    this.textBlockElement_queryArray = [\n      \"P\",\n      \"LI\",\n      \"TD\",\n      \"TH\",\n      \"TR\"\n    ]; //, \"TD\", \"TH\", '._color', '._small', '._h1`', '._h2', '._h3', '._h4', '._h5', '._h6', '._b', '._i', '._u', '._del'\n    this.ceilingElement_queryArray = [\n      \"UL\",\n      \"OL\",\n      \"LI\",\n      \"BLOCKQUOTE\",\n      // \"TD\",\n      // \"TH\",\n      // \"._media_\",\n      // \"._custom_\",\n      `#${elementId}`,\n    ];\n    this.unSelectable_queryArray = [\n      \"._media_\",\n      // \"._custom_\",\n      \"._hashtag_\",\n      \"._urllink_\",\n      \"HR\",\n    ];\n    this.needSafeGuard = [\n      \"._media_\",\n      \"._custom_\",\n      \"._hashtag_\",\n      \"._urllink_\",\n      \"HR\",\n      // \"LI\",\n      \"UL\",\n      \"OL\",\n      \"BLOCKQUOTE\",\n    ];\n    this.styleAllowedElement_queryArray = [\n      \"._backgroundColor\",\n      \"._color\",\n      \"._hashtag_\",\n      \"._urllink_\",\n      \"TD\",\n      \"TH\",\n      \"TR\",\n      `#${elementId}`,\n    ]; // ALLOWED ELEMENTS FOR STYLE ATTRIBUTE <... style=\"...\">\n    this.alignClass = [\"_alignCenter_\", \"_alignRight_\"];\n\n    this.hashtag_flag = false;\n    this.urllink_flag = false;\n    this.range_backup = null;\n\n    this.commandTracker = {};\n    this.range = null;\n    this.isRangeDirectionForward = true;\n    this.insertTabPending_tabString = \"\";\n    this.removeSandwichedLine_array = [];\n    this.lastKey = null;\n\n    //  setup div\n    this.element = document.getElementById(this.elementId);\n    if (!this.element) throw `element #${this.elementId} is null`;\n\n    this.element.innerHTML = \"\";\n\n    this.cssVariable = new ColorMangle().colorScheme(this.colorScheme);\n    Object.assign(this.cssVariable, this.fontSizeCssVariable);\n\n    for (const v in this.cssVariable)\n      this.element.style.setProperty(v, this.cssVariable[v]);\n\n    this.elementComputedStyle = window.getComputedStyle(this.element);\n    this.defaultFontColor = new ColorMangle(\n      this.cssVariable[\"--content-text\"]\n    ).hex();\n    this.defaultBackgroundColor = new ColorMangle(\n      this.cssVariable[\"--content\"]\n    ).hex();\n    this.highlightColor = new ColorMangle(\n      this.cssVariable[\"--content-focus\"]\n    ).hex();\n\n    if (!this.element.classList.contains(\"_wysiwyg4all\"))\n      this.element.classList.add(\"_wysiwyg4all\");\n\n    this.setPlaceholder(this.placeholder);\n    this.setSpellcheck(this.spellcheck);\n\n    //  re-adjust min-height depending on padding\n    let paddingB = this.elementComputedStyle.paddingBottom;\n    let paddingT = this.elementComputedStyle.paddingTop;\n    let borderT = this.elementComputedStyle.borderTopWidth;\n    let borderB = this.elementComputedStyle.borderBottomWidth;\n\n    this.element.style.minHeight = `calc(${paddingB} + ${paddingT} + ${borderT} + ${borderB} + 1.6em)`;\n\n    //  command style tag\n    const command = {\n      //  [<targetClassName>, <cssProperty>, [<string: counter tag | class name>]]\n      h1: [\"_h1\", \"fontSize\", [\"_small\", \"_h2\", \"_h3\", \"_h4\", \"_h5\", \"_h6\"]],\n      h2: [\"_h2\", \"fontSize\", [\"_small\", \"_h1\", \"_h3\", \"_h4\", \"_h5\", \"_h6\"]],\n      h3: [\"_h3\", \"fontSize\", [\"_small\", \"_h1\", \"_h2\", \"_h4\", \"_h5\", \"_h6\"]],\n      h4: [\"_h4\", \"fontSize\", [\"_small\", \"_h1\", \"_h2\", \"_h3\", \"_h5\", \"_h6\"]],\n      h5: [\"_h5\", \"fontSize\", [\"_small\", \"_h1\", \"_h2\", \"_h3\", \"_h4\", \"_h6\"]],\n      h6: [\"_h6\", \"fontSize\", [\"_small\", \"_h1\", \"_h2\", \"_h3\", \"_h4\", \"_h5\"]],\n      italic: [\"_i\", \"fontStyle\"],\n      small: [\n        \"_small\",\n        \"fontSize\",\n        [\"_h1\", \"_h2\", \"_h3\", \"_h4\", \"_h5\", \"_h6\", \"_b\"],\n      ],\n      bold: [\"_b\", \"fontWeight\", [\"_small\"]],\n      underline: [\"_u\", \"textDecoration\", [\"_del\"]],\n      strike: [\"_del\", \"textDecoration\", [\"_u\"]],\n      color: [\"_color\", \"color\"],\n      backgroundColor: [\"_backgroundColor\", \"backgroundColor\"],\n    };\n\n    const fontSizeRatio = {\n      //  should always be the same em value as css\n      // h1: 4.2,\n      // h2: 3.56,\n      // h3: 2.92,\n      // h4: 2.28,\n      // h5: 1.64,\n      // h6: 1.15,\n      // small: 0.8,\n      h1: fontSize.h1 || 4.2,\n      h2: fontSize.h2 || 3.56,\n      h3: fontSize.h3 || 2.92,\n      h4: fontSize.h4 || 2.28,\n      h5: fontSize.h5 || 1.64,\n      h6: fontSize.h6 || 1.15,\n      small: fontSize.small || 0.8,\n    };\n\n    // // font size variables\n    // --wysiwyg-h1: calc(var(--wysiwyg-font) * 4.2);\n    // --wysiwyg-h2: calc(var(--wysiwyg-font) * 3.56);\n    // --wysiwyg-h3: calc(var(--wysiwyg-font) * 2.92);\n    // --wysiwyg-h4: calc(var(--wysiwyg-font) * 2.28);\n    // --wysiwyg-h5: calc(var(--wysiwyg-font) * 1.64);\n    // --wysiwyg-h6: calc(var(--wysiwyg-font) * 1.15);\n    // --wysiwyg-small: calc(var(--wysiwyg-font) * 0.8);\n    for (const [tag, ratio] of Object.entries(fontSizeRatio)) {\n      if (typeof ratio === \"number\") {\n        this.element.style.setProperty(\n          `--wysiwyg-${tag}`,\n          `calc(var(--wysiwyg-font) * ${ratio})`\n        );\n      } else if (typeof ratio === \"string\") {\n        if (ratio.includes(\"px\")) {\n          this.element.style.setProperty(`--wysiwyg-${tag}`, ratio);\n        } else if (ratio.includes(\"em\") || ratio.includes(\"rem\")) {\n          let emSize = parseFloat(ratio);\n          if (emSize > 0) {\n            this.element.style.setProperty(\n              `--wysiwyg-${tag}`,\n              `calc(var(--wysiwyg-font) * ${emSize})`\n            );\n          }\n        }\n      }\n    }\n\n    this.styleTagOfCommand = {};\n    this.counterTagOf = {};\n    this.cssPropertyOf = {};\n    this.cssPropertyChecker = {\n      textDecoration: (v) => {\n        //  v = <string: value from computedStyle>\n        if (v.includes(\"underline\")) return \"underline\";\n        else if (v.includes(\"line-through\")) return \"strike\";\n\n        return false;\n      },\n      fontSize: (v) => {\n        //  v = <string: value from computedStyle>\n        let documentFontSize = parseFloat(this.elementComputedStyle.fontSize);\n        let nodeFontSize = parseFloat(v);\n        for (let tag in fontSizeRatio) {\n          let f_size = fontSizeRatio[tag];\n\n          if (typeof f_size === \"number\") {\n            //  precision\n            let compare_size = documentFontSize * f_size;\n            let f_size_high = compare_size + 0.01;\n            let f_size_low = compare_size - 0.01;\n            if (f_size_high > nodeFontSize && f_size_low < nodeFontSize)\n              return tag;\n          } else if (typeof f_size === \"string\") {\n            if (f_size.includes(\"px\")) {\n              if (v === f_size) return tag;\n            } else if (f_size.includes(\"em\") || f_size.includes(\"rem\")) {\n              let emSize = parseFloat(f_size);\n              if (emSize > 0) {\n                let compare_size = documentFontSize * emSize;\n                let f_size_high = compare_size + 0.01;\n                let f_size_low = compare_size - 0.01;\n                if (f_size_high > nodeFontSize && f_size_low < nodeFontSize)\n                  return tag;\n              }\n            }\n          }\n        }\n        return false;\n      },\n      fontStyle: (v) => {\n        //  v = <string: value from computedStyle>\n        if (v.includes(\"italic\")) return \"italic\";\n        return false;\n      },\n    };\n\n    for (let c in command) {\n      this.commandTracker[c] = false;\n      this.styleTagOfCommand[c] = command[c][0];\n      this.cssPropertyOf[command[c][0]] = command[c][1];\n      if (!this.cssPropertyChecker.hasOwnProperty(command[c][1]))\n        this.cssPropertyChecker[command[c][1]] = c;\n      if (command[c][2]) this.counterTagOf[command[c][0]] = command[c][2];\n    }\n\n    /**\n         this.styleTagOfCommand = {\n            [commandKey]: <targetClassName>\n         };\n\n         this.cssPropertyChecker = {\n            [cssPropertyKey]: <commandKey | function(<cssValue>)>\n         };\n\n         this.cssPropertyOf = {\n            [targetClassName]: <cssPropertyKey>\n         };\n\n         this.counterTagOf = {\n            [targetClassName]: [<counterClassName>]\n         };\n\n         this.commandTracker = {\n            [commandKey]: <boolean>\n         };\n\n         console.log({\n            styleTagOfCommand: this.styleTagOfCommand,\n            cssPropertyChecker: this.cssPropertyChecker,\n            cssPropertyOf: this.cssPropertyOf,\n            counterTagOf: this.counterTagOf,\n            commandTracker: this.commandTracker\n         });\n         */\n\n    this.loadHTML(this.html, editable).catch((err) => {\n      throw err;\n    });\n  }\n\n  _adjustSelection(\n    target,\n    ceilingElement_query = this.ceilingElement_queryArray\n  ) {\n    if (this.logExecution)\n      console.log(\"_adjustSelection()\", { target, ceilingElement_query });\n\n    let toArray = (v, allowObject = false) => {\n      if (Array.isArray(v)) return v;\n      else if (\n        (typeof v === \"string\" && v) ||\n        typeof v === \"number\" ||\n        typeof v === \"boolean\" ||\n        (allowObject && typeof v === \"object\")\n      )\n        return [v];\n      else return [];\n    };\n\n    let setRange = !!target;\n\n    let { node = null, position = true } = target || {};\n\n    let sel = window.getSelection();\n    if (!sel) return null;\n\n    let range;\n    try {\n      range = sel.getRangeAt(0);\n    } catch (err) {\n      if (setRange) range = document.createRange();\n    }\n\n    if (setRange) {\n      node = toArray(node, true);\n      position = toArray(position, true);\n\n      for (let p of position)\n        if (typeof p !== \"number\" && typeof p !== \"boolean\" && p !== null)\n          throw \"INVALID_POSITION\";\n\n      for (let n of node) {\n        if (!(n instanceof Node) && n !== null) {\n          if (n === false) return;\n          throw \"INVALID_NODE\";\n        }\n      }\n\n      const setTarget = (node, position) => {\n        if (node instanceof Node) {\n          if (node.nodeType === 1) {\n            if (typeof position === \"boolean\")\n              while (position === false ? node.lastChild : node.firstChild)\n                node = position === false ? node.lastChild : node.firstChild;\n            else if (typeof position === \"number\") {\n              let textLength = 0;\n              this._nodeCrawler(\n                (n) => {\n                  if (n.nodeType === 3 && n.textContent.length) {\n                    let length = n.textContent.length;\n                    if (\n                      n.parentNode.getAttribute(\"contenteditable\") === \"false\"\n                    ) {\n                      if (position - (textLength + length) >= 0)\n                        textLength += length;\n                      else {\n                        position = length;\n                        return \"BREAK\";\n                      }\n                      return n;\n                    } else {\n                      node = n;\n\n                      if (position - (textLength + length) >= 0) {\n                        textLength += length;\n                      } else {\n                        position -= textLength;\n                        return \"BREAK\";\n                      }\n                    }\n                  }\n                  return n;\n                },\n                {\n                  node,\n                }\n              );\n              if (node.nodeType === 1) {\n                let text = document.createTextNode(\"\\u200B\");\n                node.insertBefore(text, node.childNodes[0]);\n                node = text;\n                position = 0;\n              }\n            }\n\n            if (node.nodeName === \"BR\" && node.parentNode.childNodes.length > 1)\n              node = node.previousSibling || node;\n          }\n          if (typeof position === \"boolean\")\n            position = position ? 0 : node.textContent.length;\n          else\n            position =\n              position > node.textContent.length\n                ? node.textContent.length\n                : position;\n\n          return { node, position };\n        }\n      };\n\n      let doCollapse = false,\n        setEnd,\n        setStart = (() => {\n          node[0] = node[0] === null ? range.startContainer : node[0];\n          position[0] = position[0] === null ? range.startOffset : position[0];\n          return setTarget(node[0], position[0]);\n        })();\n      range.setStart(setStart.node, setStart.position);\n\n      if (position.length > 1)\n        setEnd = setTarget(\n          (node[1] === null ? range.endContainer : node[1]) || node[0],\n          position[1] === null ? range.endOffset : position[1]\n        );\n      else {\n        setEnd = setStart;\n        doCollapse = true;\n      }\n\n      range.setEnd(setEnd.node, setEnd.position);\n\n      if (doCollapse) range.collapse(true);\n\n      sel.removeAllRanges();\n      sel.addRange(range);\n    }\n\n    if (ceilingElement_query && range) {\n      let startLine, endLine;\n      for (let q of ceilingElement_query) {\n        if (startLine && endLine) break;\n\n        let e =\n          range.endContainer.nodeType === 3\n            ? range.endContainer.parentNode\n            : range.endContainer;\n        let s =\n          range.startContainer.nodeType === 3\n            ? range.startContainer.parentNode\n            : range.startContainer;\n\n        if (!startLine && s.closest(q))\n          startLine = this._climbUpToEldestParent(s, s.closest(q));\n        if (!endLine && e.closest(q))\n          endLine = this._climbUpToEldestParent(e, e.closest(q));\n      }\n\n      range.startLine = startLine;\n      range.endLine = endLine;\n    }\n\n    return range;\n  }\n\n  _generateId(option) {\n    if (this.logExecution) console.log(\"_generateId()\", { option });\n    let limit = 12;\n    let prefix = \"\";\n\n    if (typeof option === \"number\") limit = option;\n    else if (typeof option === \"string\") prefix = `${option}_`;\n\n    const possible = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\n    let text = \"\";\n    for (let i = 0; i < limit - 6; i++)\n      text += possible.charAt(\n        Math.floor(Math.random() * (possible.length - 1))\n      );\n\n    const numb = new Date().getTime().toString().substring(7, 13); // SECOND, MILLISECOND\n\n    // const shuffleArray = (array) => {\n    //     let currentIndex = array.length;\n    //     let temporaryValue, randomIndex;\n    //     while (0 !== currentIndex) {\n    //         randomIndex = Math.floor(Math.random() * currentIndex);\n    //         currentIndex -= 1;\n    //         temporaryValue = array[currentIndex];\n    //         array[currentIndex] = array[randomIndex];\n    //         array[randomIndex] = temporaryValue;\n    //     }\n    //     return array;\n    // };\n\n    // const letter_array = shuffleArray((text + numb).split(''));\n\n    // let output = '';\n    // for (let i = 0; i < limit; i++) output += letter_array[i];\n\n    return prefix + numb + text;\n  }\n\n  _nodeCrawler(run, option) {\n    if (this.logExecution) console.log(\"_nodeCrawler()\", { run, option });\n    const { parentNode, node, startFromEldestChild, startNode } = option;\n\n    if (startFromEldestChild && !parentNode)\n      throw new Error(\"Need parentNode to crawl up single child\");\n\n    if (!node || !(node instanceof Node || node?.commonAncestorContainer))\n      throw new Error(\"No node to crawl\");\n\n    let outputNodes = [],\n      nodeIsRange = !!node.commonAncestorContainer,\n      commonContainer = null,\n      parentAnchor;\n\n    if (parentNode && parentNode instanceof Node && parentNode?.nodeType === 1)\n      parentAnchor = parentNode;\n\n    if (nodeIsRange) {\n      commonContainer = node.commonAncestorContainer;\n      commonContainer =\n        commonContainer.nodeType === 3\n          ? commonContainer.parentNode || commonContainer\n          : commonContainer;\n    } else commonContainer = node;\n\n    if (startFromEldestChild)\n      commonContainer = this._climbUpToEldestParent(\n        commonContainer,\n        parentNode,\n        true\n      );\n\n    if (parentAnchor) {\n      while (\n        commonContainer.nodeType === 3 ||\n        (commonContainer !== parentAnchor &&\n          commonContainer.parentNode &&\n          commonContainer.parentNode !== parentAnchor)\n      )\n        commonContainer = commonContainer.parentNode;\n    }\n\n    /** crawl order below (outputs node on the way)\n     *  If 'BREAK' is returned, the node is not saved in outputNode\n     *\n     *  start   ->  [                   end\n     *                  |               ^ (finish)\n     *                  v               | (outputNode)\n     *              outputNode  ->  outputNode\n     *\n     *  NOTE: Will not crawl when node is textNode\n     */\n\n    if (commonContainer.nodeType === 3) {\n      outputNodes.push(run(commonContainer));\n\n      return { nodes: outputNodes, commonContainer };\n    }\n\n    let id, uniqueId;\n    if (commonContainer.nodeType === 1) {\n      uniqueId =\n        commonContainer.id ||\n        (() => {\n          id = this._generateId(\"crawl\");\n          commonContainer.id = id;\n          return id;\n        })();\n    }\n\n    let crawl =\n      (startNode instanceof Node ? startNode : null) ||\n      (nodeIsRange ? node.startContainer : commonContainer.childNodes[0]);\n    let endNode = nodeIsRange\n      ? node.endContainer\n      : commonContainer.childNodes[\n      commonContainer.childNodes.length\n        ? commonContainer.childNodes.length - 1\n        : 0\n      ];\n\n    let withInRange = (cwl) => {\n      if (!cwl || !(cwl instanceof Node)) return false;\n      if (cwl.nodeType === 1)\n        return cwl.id !== uniqueId && cwl.parentNode?.closest(\"#\" + uniqueId);\n      else return true;\n    };\n\n    while (withInRange(crawl)) {\n      if (crawl.nodeType === 1 && crawl.childNodes.length) {\n        // dive down to deepest child's first crawl\n        crawl = crawl.childNodes[0];\n      } else if (crawl) {\n        // entering the deepest elements first child.\n\n        if (typeof run === \"function\") crawl = run(crawl);\n        if (crawl === \"BREAK\" || !withInRange(crawl)) break;\n\n        outputNodes.push(crawl);\n\n        // break out if the crawl hits the end\n        if (crawl === endNode) break;\n\n        /**\n         * Climb up the node if the node doesn't have any next siblings\n         * Stop when it hits the commonContainer\n         */\n        let breakOut = false;\n        while (\n          !crawl.nextSibling &&\n          crawl.parentNode &&\n          withInRange(crawl.parentNode)\n        ) {\n          crawl = crawl.parentNode;\n          if (crawl) {\n            if (typeof run === \"function\") crawl = run(crawl);\n\n            if (crawl === \"BREAK\" || !withInRange(crawl)) {\n              breakOut = true;\n              break;\n            }\n\n            if (crawl) outputNodes.push(crawl);\n          }\n        }\n\n        if (breakOut) break;\n\n        // move on to next crawl\n        crawl = crawl.nextSibling;\n      }\n    }\n\n    // let withInRange = (cwl) => {\n    //     if (!cwl || !(cwl instanceof Node)) return false;\n    //     if (cwl.nodeType === 1)\n    //         return cwl.id !== uniqueId && cwl.parentNode?.closest(\"#\" + uniqueId);\n    //     else if (cwl.nodeType === 3)\n    //         return cwl.parentNode && cwl.parentNode?.closest(\"#\" + uniqueId);\n    //     // else if(nextnext) {\n    //     //   // crawl = nextnext;\n    //     //   return true;\n    //     // } \n    //     else return false;\n    // };\n    // let diving = false;\n    // // let nextnext = null;\n    // while (withInRange(crawl)) {\n    //     if (!diving && crawl.nodeType === 1 && crawl.childNodes.length) {\n    //         // dive down to deepest child's first crawl\n    //         crawl = crawl.childNodes[0];\n    //     } else if (crawl) {\n    //         diving = true;\n    //         // entering the deepest elements first child.\n\n    //         if (crawl.nodeType === 3) {\n    //             crawl = crawl.nextSibling || crawl.parentNode;\n    //             continue;\n    //         }\n\n    //         if (typeof run === \"function\") crawl = run.bind(this)(crawl);\n    //         if (crawl === \"BREAK\") break;\n\n    //         if (withInRange(crawl))\n    //             outputNodes.push(crawl);\n\n    //         // nextnext = crawl.nextSibling?.nextSibling || crawl.parentNode;\n    //         /**\n    //          * Climb up the node if the node doesn't have any next siblings\n    //          * Stop when it hits the commonContainer\n    //          */\n    //         if (\n    //             crawl.nextSibling\n    //         ) {\n    //             crawl = crawl.nextSibling;\n    //         } else if (crawl.parentNode) {\n    //             if (crawl.parentNode === commonContainer) {\n    //                 crawl = crawl.nextSibling;\n    //                 diving = false;\n    //             }\n    //             else {\n    //                 crawl = crawl.parentNode;\n    //             }\n    //         }\n    //         else {\n    //             break;\n    //         }\n    //     }\n    // }\n\n    if (id) commonContainer.removeAttribute(\"id\");\n\n    return { node: outputNodes, commonContainer };\n  }\n\n  _wrapNode(node, wrapper, appendWhole = false) {\n    if (this.logExecution)\n      console.log(\"_wrapNode()\", { node, wrapper, appendWhole });\n    if (!(node instanceof Node)) return;\n\n    if (!node.parentNode) throw new Error(\"can't unwrap document fragment\");\n\n    // save current range\n    let sel = window.getSelection();\n    let range = sel.getRangeAt(0);\n    let start = null;\n    let startOffset = range.startOffset;\n    let end = null;\n    let endOffset = range.endOffset;\n\n    const withinRange = (n) => {\n      if (range.startContainer === n) {\n        start = n;\n      }\n      if (range.endContainer === n) {\n        end = n;\n      }\n    };\n\n    if (node.nodeType === 1) {\n      this._nodeCrawler(\n        (n) => {\n          withinRange(n);\n          return n;\n        },\n        { node }\n      );\n    } else withinRange(node);\n\n    if (wrapper) {\n      // place the wrapper\n      node.parentNode.insertBefore(wrapper, node);\n    }\n\n    // append node\n    if (node.nodeType === 3) {\n      if (wrapper) wrapper.append(node);\n      else throw new Error(\"no wrapper for text content\");\n    } else if (appendWhole) wrapper.append(node);\n    else\n      while (node.childNodes[0]) {\n        let child = node.childNodes[0];\n        if (wrapper) wrapper.append(child);\n        else node.parentNode.insertBefore(child, node);\n      }\n\n    let stripped;\n    if (node.nodeType === 1 && !appendWhole) {\n      let n = wrapper || node;\n      let p = n.parentNode;\n      stripped = node.previousSibling;\n      p.removeChild(node);\n    }\n\n    // restore range\n    if ((stripped || node).textContent && (start || end)) {\n      if (start && start === end && startOffset === endOffset)\n        range = this._adjustSelection({\n          node: stripped || node,\n          position: startOffset,\n        });\n      else\n        range = this._adjustSelection({\n          node: [start, end],\n          position: [startOffset, endOffset],\n        });\n    }\n\n    this.range = range;\n    return { node: stripped || node, range };\n  }\n\n  _climbUpToEldestParent(node, wrapper, singleChildParent = false, callback) {\n    if (this.logExecution)\n      console.log(\"_climbUpToEldestParent()\", {\n        node,\n        wrapper,\n        singleChildParent,\n        callback,\n      });\n    callback =\n      callback ||\n      ((n) => {\n        return n;\n      });\n\n    if (!(wrapper instanceof Node) || wrapper?.nodeType === 3)\n      throw new Error(\"invalid wrapper node\");\n\n    let id;\n    let uniqueId =\n      wrapper.id ||\n      (() => {\n        id = this._generateId(\"eldest\");\n        wrapper.id = id;\n        return id;\n      })();\n    // on single parent mode climb up if parent has only 1 child or 2 child with zero space text\n    function _isSingleChildParent(n) {\n      if (!n || n.nodeType === 3) return false;\n\n      let childrenCount = n?.children?.length;\n      return (\n        childrenCount === 0 ||\n        (() => {\n          let sweep = n.childNodes.length;\n          let divCount = 0;\n          let iHaveText = false;\n\n          while (sweep--) {\n            let s = n.childNodes[sweep];\n\n            if (\n              s.nodeType === 3 &&\n              s.textContent.length > 0 &&\n              s.textContent !== \"\\u200B\"\n            )\n              iHaveText = true;\n            else if (s.nodeType === 1 && s.nodeName !== \"BR\") divCount++;\n\n            // if (divCount > 1 || divCount && iHaveText)\n            if ((divCount > 1 && !iHaveText) || (divCount && iHaveText))\n              return false;\n          }\n\n          return true;\n        })()\n      );\n    }\n    while (\n      node?.id !== uniqueId &&\n      node.parentNode &&\n      node.parentNode.closest(\"#\" + uniqueId) &&\n      node.parentNode.id !== uniqueId &&\n      (singleChildParent ? _isSingleChildParent(node?.parentNode) : true)\n    ) {\n      let cb = callback(node.parentNode);\n\n      if (!cb || cb === \"BREAK\") break;\n\n      node = cb;\n    }\n\n    if (id) wrapper.removeAttribute(\"id\");\n\n    return node;\n  }\n\n  _getStartEndLine(\n    range = this.range,\n    element = this.element,\n    getInbetween = false\n  ) {\n    if (this.logExecution)\n      console.log(\"_getStartEndLine()\", { range, element });\n    if (!range) return [null, null, null];\n\n    let startLine = this._climbUpToEldestParent(range.startContainer, element);\n    let endLine = this._climbUpToEldestParent(range.endContainer, element);\n\n    let inBetween = [];\n    if (getInbetween) {\n      // collect all the lines in between startLine and endLine. line is a block element\n      let currentLine = startLine.nextSibling;\n      while (currentLine && currentLine !== endLine) {\n        if (\n          currentLine.nodeType === 1 &&\n          this.blockElement_queryArray.some((q) =>\n            currentLine.matches(this._classNameToQuery(q))\n          )\n        ) {\n          inBetween.push(currentLine);\n        }\n        currentLine = currentLine.nextSibling;\n      }\n    }\n    if (this.logExecution)\n      console.log(\"startLine | endLine\", { startLine, endLine, inBetween });\n\n    return [startLine, endLine, inBetween];\n  }\n\n  _isThereContentEditableOverMyHead(node, element = this.element) {\n    if (node && node !== this.element) {\n      let flyup = node;\n      while (flyup && this.element !== flyup) {\n        if (flyup.getAttribute(\"contenteditable\") === \"true\") return true;\n        if (flyup.getAttribute(\"contenteditable\") === \"false\") return false;\n\n        flyup = flyup.parentNode;\n      }\n    }\n    return true;\n  }\n\n  _isSelectionWithinRestrictedRange(\n    range = this.range,\n    element = this.element\n  ) {\n    if (!range) {\n      if (this.logExecution)\n        console.log(\"_isSelectionWithinRestrictedRange():true\", {\n          range,\n          element,\n        });\n      return true;\n    }\n\n    let { commonAncestorContainer, startContainer, endContainer } = range;\n    let restrict = this.restrictedElement_queryArray;\n    // let startLine = this._climbUpToEldestParent(startContainer, element);\n    // let endLine = this._climbUpToEldestParent(endContainer, element);\n\n    // if (this.logExecution) console.log('startLine | endLine', {startLine, endLine});\n    let [startLine, endLine, inBetween] = this._getStartEndLine(\n      range,\n      element,\n      true\n    );\n    if (startLine === endLine) {\n      commonAncestorContainer =\n        commonAncestorContainer.nodeType === 3\n          ? commonAncestorContainer.parentNode\n          : commonAncestorContainer;\n      for (let r of restrict) {\n        let cl = commonAncestorContainer.closest(this._classNameToQuery(r));\n        if (cl) {\n          // if (cl.getAttribute('contenteditable') !== 'true') {\n          //     return r;\n          // }\n          let isThere = this._isThereContentEditableOverMyHead(\n            commonAncestorContainer,\n            element\n          );\n          if (!isThere) {\n            return true;\n          }\n        }\n        // let cl = commonAncestorContainer.closest(this._classNameToQuery(r));\n        // if (cl)\n        //     return r;\n      }\n    } else if (inBetween?.length) {\n      for (let i = 0; i < inBetween.length; i++) {\n        for (let r of restrict) {\n          if (inBetween[i].closest(this._classNameToQuery(r))) {\n            let isThere = this._isThereContentEditableOverMyHead(inBetween[i]);\n            if (!isThere) {\n              return true;\n            }\n          }\n        }\n      }\n      // while (startLine && startLine !== endLine) {\n      //     startLine = startLine.nextSibling;\n      //     if (startLine) {\n      //         if (startLine.nodeType === 1)\n      //             for (let r of restrict) {\n      //                 if (startLine.classList.contains(r)) {\n      //                     if (startLine.getAttribute('contenteditable') !== 'true') {\n      //                         return r;\n      //                     }\n      //                 }\n      //                 // if (startLine.classList.contains(r))\n      //                 //     return r;\n      //             }\n      //     } else\n      //         break;\n      // }\n    }\n\n    return false;\n  }\n\n  _classNameToQuery(q) {\n    if (this.logExecution) console.log(\"_classNameToQuery()\", { q });\n    if (q.includes(\"_stop\") && q[0] !== \".\") return \".\" + q;\n    return q[0] === \"_\" ? \".\" + q : q;\n  }\n\n  _createEmptyParagraph(append) {\n    if (this.logExecution) console.log(\"_createEmptyParagraph()\", { append });\n    let p = document.createElement(\"p\");\n\n    if (append && typeof append === \"string\")\n      append = document.createTextNode(append);\n\n    p.append(append || document.createTextNode(\"\"));\n\n    if (!append) p.append(document.createElement(\"br\"));\n\n    return p;\n  }\n\n  _trackStyle(n, cls) {\n    if (this.logExecution) console.log(\"_trackStyle()\", { n, cls });\n    let commandTracker = {};\n    let style = window.getComputedStyle(n);\n\n    for (let c of this.alignClass) {\n      if (n.closest(\".\" + c))\n        commandTracker[c.substring(1, c.length - 1)] = true;\n    }\n\n    let checker = (sp) => {\n      let key = this.cssPropertyChecker[sp];\n      if (typeof key === \"function\") {\n        key = key(style[sp]);\n        if (key) {\n          if (cls) return key;\n          commandTracker[key] = true;\n        }\n      } else if (sp === \"color\" && style[sp]) {\n        let col =\n          style[sp][0] === \"#\" ? style[sp] : new ColorMangle(style[sp]).hex();\n\n        if (col !== this.defaultFontColor) {\n          if (cls) return col;\n          commandTracker[key] = col;\n        }\n      } else if (sp === \"backgroundColor\" && style[sp]) {\n        let col = null;\n\n        if (style[sp][0] === \"#\")\n          col = style[sp]\n        else {\n          let colSplit = style[sp].split(',');\n          if (colSplit.length === 4) {\n            let last = colSplit[colSplit.length - 1].trim();\n            if (last === '0)') {\n              return false;\n            }\n          }\n          col = new ColorMangle(style[sp]).hex();\n        }\n\n        if (col && col !== this.defaultBackgroundColor) {\n          if (cls) return col;\n          commandTracker[key] = col;\n        }\n\n      } else if (\n        style[sp] !== this.elementComputedStyle[sp] &&\n        this._isTextElement(n)\n      ) {\n        if (cls) return true;\n        commandTracker[key] = true;\n      }\n      return false;\n    };\n\n    // if (cls) return checker(this.cssPropertyOf[cls.toLowerCase()]);\n    if (cls) return checker(this.cssPropertyOf[cls]);\n\n    for (let sp in this.cssPropertyChecker) {\n      checker(sp);\n    }\n\n    return commandTracker;\n  }\n\n  _lastLineBlank(force) {\n    if (this.logExecution) console.log(\"_lastLineBlank()\", { force });\n    if (this.lastLineBlank || force) {\n      let lastLine = this.element.lastChild;\n      if (\n        lastLine.nodeName !== \"P\" ||\n        (lastLine.nodeName === \"P\" &&\n          lastLine.textContent &&\n          lastLine.textContent !== \"\\u200B\")\n      ) {\n        // let br = document.createElement(\"br\");\n        // this.element.append(this._createEmptyParagraph(br));\n        this.element.append(this._createEmptyParagraph());\n      }\n    }\n  }\n\n  _setEventListener(listen) {\n    if (this.logExecution) console.log(\"_setEventListener()\", { listen });\n    /**\n     * keydown -> observer(dom change) -> selection change -> click | keyup\n     */\n\n    document.removeEventListener(\"selectionchange\", this._selectionchange);\n    this.imgInput = null;\n    // if (this.element) {\n    //   this.element.removeEventListener(\"keydown\", this._keydown);\n    //   this.element.removeEventListener(\"mousedown\", this._normalize);\n    //   window.removeEventListener(\"mousedown\", this._normalize);\n    //   this.element.removeEventListener(\"paste\", this._paste);\n    //   this.element.removeEventListener(\"keyup\", this._keyup);\n    // }\n\n    if (!listen) return;\n\n    //  image selector\n    let imgInput = document.createElement(\"input\");\n    for (const [key, value] of Object.entries({\n      id: this._generateId(\"imageInput\"),\n      type: \"file\",\n      accept: \"image/gif,image/png,image/jpeg,image/webp\",\n      hidden: true,\n      multiple: true,\n    })) {\n      imgInput.setAttribute(key, value);\n    }\n\n    this.imgInput = imgInput;\n    this.imgInput.addEventListener(\"change\", (e) => {\n      this._imageSelected(e).catch((err) => {\n        console.error(err);\n      });\n    });\n\n\n\n    this._keydown = function (e) {\n      if (this._isSelectionWithinRestrictedRange()) {\n        if (this.logExecution)\n          console.log(\"_keydown(): restricted range\", { e });\n        return;\n      }\n\n      this._modifySelection(() => {\n        if (!this.range) return;\n        let { startContainer, startOffset, collapsed, startLine, endLine } =\n          this.range;\n\n        let key = e.key.toUpperCase();\n        let shift = e.shiftKey;\n\n        this.lastKey = key;\n\n        if (key === \"ENTER\" && e.shiftKey) {\n          // prevent shift+enter\n          if (!this.range.endLine.closest(\"LI\")) e.preventDefault();\n          return;\n        }\n\n        // delete key\n        if ([\"BACKSPACE\", \"DELETE\"].includes(key)) {\n          this.isRangeDirectionForward = true;\n          if (this.logExecution) console.log(\"_keydown(): delete key\", { e });\n          // if (\n          //     this.element.childNodes.length === 1 &&\n          //     this._isTextBlockElement(this.element.childNodes[0]) &&\n          //     this.element.childNodes[0].textContent.length === 0\n          // ) {\n          //     if(this.logExecution) console.log('dead end');\n          //     e.preventDefault();\n          //     // Optionally, reset to a blank paragraph\n          //     // this.element.childNodes[0].innerHTML = '<br>';\n          //     // this.range = this._adjustSelection({ node: this.element.childNodes[0], position: 0 });\n          //     this._lastLineBlank(true);\n          // }\n\n          if (\n            !this.element.textContent &&\n            this.element.childNodes.length <= 1 &&\n            this._isTextElement(this.element.childNodes[0]) &&\n            this.element.childNodes[0] === startLine\n          ) {\n            if (this.logExecution) console.log(\"_keydown(): delete key\", \"nothing to delete\");\n            // there is nothing to delete\n            e.preventDefault();\n            return;\n          }\n\n          // Prevent potential quirk where the browser removes the whole element\n          if (\n            this.element.childNodes.length === 1 &&\n            this._isTextBlockElement(this.element.childNodes[0]) &&\n            this.element.childNodes[0].textContent.length === 0\n          ) {\n            if (this.logExecution) console.log(\"_keydown(): delete key\", \"dead end\");\n            e.preventDefault();\n            // Optionally, reset to a blank paragraph\n            this.element.childNodes[0].innerHTML = \"<p><br></p>\";\n            this.range = this._adjustSelection({\n              node: this.element.childNodes[0],\n              position: 0,\n            });\n            this._lastLineBlank(true);\n            return;\n          }\n\n          let stc = this.range.startContainer;\n          if (this.range.collapsed) {\n            let block = (stc.nodeType === 3 ? stc.parentNode : stc).closest(\n              \"blockquote\"\n            );\n            if (\n              block &&\n              block.childNodes[0] === this._climbUpToEldestParent(stc, block) &&\n              this.range.startOffset === 0\n            ) {\n              // if the block is empty and the cursor is on the first offset position within the blockquote\n              // cursor is on the first offset position within the blockquote\n\n              if (this.logExecution)\n                console.log(\"_keydown(): delete key\", \n                  \"block is empty and the cursor is on the first offset position within the blockquote\"\n                );\n              e.preventDefault();\n              this.command(\"quote\");\n              return;\n            }\n\n            if (this.range.startOffset === 0) {\n              if (this.logExecution)\n                console.log(\"_keydown(): delete key\", \n                  \"this.range.startOffset === 0\"\n                );\n\n              let ceil = this._climbUpToEldestParent(\n                stc,\n                this.element\n              )\n\n              let ceil_prev = ceil?.previousSibling;\n              if(ceil_prev) {\n                if (ceil_prev.getAttribute(\"contenteditable\") === \"false\") {\n                  ceil_prev.remove();\n                }\n              }\n              // for (let cl of this.restrictedElement_queryArray) {\n              //   if (ceil && ceil.closest(cl)) {\n              //     // remove the element\n              //     this.element.removeChild(ceil);\n\n              //     if (this.logExecution)\n              //       console.log(\"removing element\", { ceil });\n              //     e.preventDefault();\n              //     return;\n              //   }\n              // }\n            }\n            return;\n          }\n\n          // let commonAncestorContainer = this.range.commonAncestorContainer;\n          // check if commonAncestorContainer is the only element in this.element\n\n          // e.preventDefault();\n\n\n          // #[MARK]\n          // if (\n          //   !this.range.startOffset &&\n          //   ((this.element.childNodes.length === 1 &&\n          //     commonAncestorContainer === this.element.childNodes[0]) ||\n          //     (commonAncestorContainer === this.element &&\n          //       this.element.childNodes.length === 0))\n          // ) {\n          //   // if the element is empty and the cursor is on the first offset position within the block\n          //   // let t = document.createTextNode(\"\\u200B\");\n          //   // let stcEl = stc.nodeType === 3 ? stc.parentNode : stc;\n          //   // stcEl.insertBefore(t, stcEl[0]);\n          //   console.error('gawwsa!', this.range)\n          //   e.preventDefault();\n          //   return;\n          // }\n\n\n\n\n          // // Not sure what this is meant to do...\n          // if (stc.nodeType === 1 && this._isTextBlockElement(stc) && !this.range.startOffset) {\n          //     let t = document.createTextNode('\\u200B');\n          //     stc.insertBefore(t, stc.childNodes[0]);\n          //     this.range = this._adjustSelection({\n          //         node: t,\n          //         position: 0\n          //     });\n          // }\n\n          return;\n        }\n\n        //  hashtag flag\n        if (key === \"#\" && !this.hashtag_flag) {\n          this.hashtag_flag = true;\n          return;\n        }\n\n        //  url flag\n        if ([\":\", \"/\", \".\"].includes(key) && !this.urllink_flag) {\n          this.urllink_flag = true;\n          return;\n        }\n\n        // insert hashtag | urllink\n        if (\n          (this.hashtag_flag || this.urllink_flag) &&\n          ([\" \", \"ENTER\", \"TAB\"].includes(key) || key.includes(\"ARROW\"))\n        ) {\n          this._replaceText();\n          // return;\n        }\n\n        // when user press shift + arrows to expand the selection range,\n        // this.isRangeDirectionForward is responsible of setting direction to expand\n        // when set to true, the endOffset will change when using shift + arrow\n        if (shift) {\n          if (key === \"PAGEUP\" || key === \"HOME\") {\n            this.isRangeDirectionForward = false;\n            return;\n          }\n\n          if (key === \"PAGEDOWN\" || key === \"END\") {\n            this.isRangeDirectionForward = true;\n            return;\n          }\n        }\n\n        if (key.includes(\"ARROW\")) {\n          // this._setArrow(e);\n          return;\n        }\n\n        if (key === \"TAB\") {\n          this.isRangeDirectionForward = true;\n\n          e.preventDefault();\n          let sweep_array = [];\n\n          if (!collapsed) {\n            let sweep = startLine;\n            while (sweep && sweep !== endLine) {\n              sweep_array.push(sweep);\n              sweep = sweep.nextSibling;\n            }\n            sweep_array.push(endLine);\n          }\n\n          if (shift) {\n            // delete indent\n            let hasIndent = false;\n            let diveAndRemoveTab = (n) => {\n              while (n.childNodes[0]) {\n                n = n.childNodes[0];\n\n                while (n.nodeType === 3 && !n.textContent) n = n.nextSibling;\n\n                if (n.nodeType === 3 && n.textContent[0] === \"\\t\") {\n                  hasIndent = true;\n                  n.textContent = n.textContent.substring(1);\n                  break;\n                }\n              }\n            };\n            if (sweep_array.length) {\n              for (let n of sweep_array) {\n                if (n.textContent[0] === \"\\t\") diveAndRemoveTab(n);\n              }\n              if (hasIndent)\n                this._adjustSelection({\n                  node: [startLine, endLine],\n                  position: [true, false],\n                });\n            } else if (startLine.textContent[0] === \"\\t\") {\n              let lineOffset = (line, container, containerOffset) => {\n                if (line === container) return containerOffset;\n\n                this._nodeCrawler(\n                  (n) => {\n                    if (container === n) return \"BREAK\";\n\n                    if (n.nodeType === 3 && n.textContent.length)\n                      containerOffset += n.textContent.length;\n\n                    return n;\n                  },\n                  { node: line }\n                );\n                return containerOffset;\n              };\n\n              let offset =\n                lineOffset(startLine, startContainer, startOffset) - 1;\n              offset = offset < 0 ? 0 : offset;\n\n              diveAndRemoveTab(startLine);\n              if (hasIndent)\n                this._adjustSelection({ node: startLine, position: offset });\n            }\n          } else {\n            // indent\n            if (sweep_array.length) {\n              let hasIndent = false;\n              for (let n of sweep_array) {\n                hasIndent = true;\n                let tab = document.createTextNode(\"\\t\");\n                n.insertBefore(tab, n.childNodes[0]);\n              }\n              if (hasIndent)\n                this._adjustSelection({\n                  node: [startLine, endLine],\n                  position: [true, false],\n                });\n            } else {\n              let tab = document.createTextNode(\"\\t\");\n              this.range.insertNode(tab);\n              this._adjustSelection({ node: tab, position: false });\n            }\n          }\n          return;\n        }\n\n        if (key === \"ENTER\") {\n          // //  remove zero space\n          // if (\n          //   collapsed &&\n          //   (startContainer.textContent.includes(\"\\u200B\") ||\n          //     !startContainer.textContent)\n          // ) {\n          //   this._nodeCrawler(\n          //     (n) => {\n          //       if (\n          //         n.nodeType === 3 &&\n          //         (n.textContent === \"\\u200B\" || !n.textContent)\n          //       ) {\n          //         n.remove();\n          //       }\n\n          //       return n;\n          //     },\n          //     {\n          //       node:\n          //         startContainer.nodeType === 3\n          //           ? startContainer.parentNode\n          //           : startContainer,\n          //     }\n          //   );\n          // }\n\n          if (endLine.textContent[0] === \"\\t\") {\n            for (let s of endLine.textContent) {\n              if (s === \"\\t\") this.insertTabPending_tabString += \"\\t\";\n              else break;\n            }\n          }\n        }\n\n        this.isRangeDirectionForward = true;\n      });\n    }.bind(this);\n\n    this._normalize = function (e) {\n      // e.stopPropagation();\n      this._modifySelection(() => {\n        // if (this._isSelectionWithinRestrictedRange()) return;\n        this._normalizeDocument(true);\n        this.range_backup = this.range.cloneRange();\n        this._replaceText(true);\n      });\n    }.bind(this);\n    this._paste = function (e) {\n      e.preventDefault();\n      if (this._isSelectionWithinRestrictedRange()) return;\n      this._modifySelection(async () => {\n        if (this.range) {\n          if (this._isSelectionWithinRestrictedRange()) return;\n\n          let doc = await this._callback({ paste: e });\n          if (!doc) {\n            doc = document.createDocumentFragment();\n            doc.textContent = e.clipboardData\n              .getData(\"text/plain\")\n              .replace(/\\n\\n/g, \"\\n\");\n\n            if (doc.textContent.includes(\"#\")) {\n              this.hashtag_flag = true;\n            }\n\n            //  url flag\n            for (let u of [\":\", \"/\", \".\"]) {\n              doc.textContent.includes(u);\n              this.urllink_flag = true;\n            }\n          }\n\n          if (doc && !(doc instanceof DocumentFragment)) {\n            throw new Error(\"invalid document fragment\");\n          }\n\n          if (!this.range.collapsed) this.range.extractContents();\n          this.range.insertNode(doc);\n        }\n      });\n    }.bind(this);\n    // this._keyup = function () {\n    //   if (this.removeSandwichedLine_array.length)\n    //     while (this.removeSandwichedLine_array.length)\n    //       this.removeSandwichedLine_array.pop().remove();\n    // }.bind(this);\n    this._selectionchange = function () {\n      this._modifySelection(() => {\n        function isSelectionReversed() {\n          const selection = window.getSelection();\n\n          // Check if anchorNode comes after focusNode in the DOM\n          if (selection.anchorNode !== selection.focusNode) {\n            return selection.anchorNode.compareDocumentPosition(selection.focusNode) &\n              Node.DOCUMENT_POSITION_PRECEDING;\n          }\n\n          // If same node, compare offsets\n          return selection.anchorOffset > selection.focusOffset;\n        }\n\n        this.isRangeDirectionForward = isSelectionReversed();\n\n        let isForward =\n          !(this.lastKey === \"DELETE\" || this.lastKey === \"BACKSPACE\") ||\n          this.isRangeDirectionForward;\n\n        let rangeHeader = isForward\n          ? this.range.endContainer\n          : this.range.startContainer;\n        this.lastKey = null;\n\n        //  nudge range in-case carat is within non selectables\n        let unSel = this._isUnSelectableElement(rangeHeader);\n        if (unSel) {\n          let selNext = isForward ? unSel.nextSibling : unSel.previousSibling;\n\n          if (this.logExecution)\n            console.log(\"nudging range\", { unSel, selNext, isForward });\n\n          if (!selNext && !isForward) {\n            selNext = document.createTextNode(\"\\u200B\");\n            unSel.parentNode.insertBefore(\n              selNext,\n              isForward ? unSel.nextSibling : unSel\n            );\n          }\n          if (selNext)\n            this.range = this._adjustSelection({\n              node: this.range.collapsed\n                ? selNext\n                : isForward\n                  ? [null, selNext]\n                  : [selNext, null],\n              position: this.range.collapsed\n                ? isForward\n                  ? 0\n                  : selNext.textContent.length\n                : isForward\n                  ? [null, 0]\n                  : [0, null],\n            });\n        }\n\n        //  track commandTracker\n        let commandTracker = {};\n        for (let style in this.styleTagOfCommand) {\n          commandTracker[style] = false;\n        }\n\n        if (this._isSelectionWithinRestrictedRange()) {\n          this.commandTracker = commandTracker;\n          return;\n        }\n\n        let skipTrack = this.restrictedElement_queryArray.concat(\n          this.specialTextElement_queryArray\n        );\n        let crawlResult = this._nodeCrawler(\n          (node) => {\n            if (\n              (node.nodeType === 1 && node.closest(\"blockquote\")) ||\n              (node.nodeType === 3 && node.parentNode.closest(\"blockquote\"))\n            )\n              commandTracker.quote = true;\n\n            let styleRestrictedParents = (c) => {\n              return node.nodeType === 3\n                ? node.parentNode.closest(c)\n                : node.nodeType === 1\n                  ? node.closest(c)\n                  : !(node instanceof Node);\n            };\n\n            for (let p of skipTrack) {\n              let chk = styleRestrictedParents(p);\n              if (chk) return node;\n            }\n\n            if (\n              node.nodeType === 3 ||\n              node.nodeName === \"BR\" ||\n              (node.nodeType === 1 &&\n                node.childNodes.length === 1 &&\n                (node.childNodes[0].nodeName === \"BR\" ||\n                  node.childNodes[0].nodeType === 3))\n            ) {\n              let n =\n                node.nodeType === 3 || node.nodeName === \"BR\"\n                  ? node.parentNode\n                  : node;\n\n              let comm = this._trackStyle(n);\n              for (let c in comm) commandTracker[c] = comm[c];\n            }\n            return node;\n          },\n          { node: this.range, parentNode: this.element }\n        );\n\n        if (!crawlResult.node.length) {\n          let comm = this._trackStyle(this.range.startContainer);\n          for (let c in comm) commandTracker[c] = comm[c];\n        }\n\n        this.commandTracker = commandTracker;\n        let caratPosition;\n        let caratEl = this.isRangeDirectionForward\n          ? this.range.endContainer\n          : this.range.startContainer;\n\n        if (caratEl.nodeType === 3)\n          caratPosition = this.range.getBoundingClientRect();\n        else if (caratEl.nodeType === 1)\n          caratPosition = caratEl.getBoundingClientRect();\n\n        this._callback({\n          commandTracker,\n          range: this.range,\n          caratPosition,\n        }).catch((err) => console.error(err));\n        this._lastLineBlank();\n      });\n    }.bind(this);\n    document.addEventListener(\"selectionchange\", this._selectionchange);\n    this.element.addEventListener(\"keydown\", this._keydown);\n    // this.element.addEventListener(\"mousedown\", this._normalize);\n    // this.element.addEventListener('blur', this._normalize);\n    // fuck safari, firefox\n    window.addEventListener(\"mousedown\", this._normalize);\n    this.element.addEventListener(\"paste\", this._paste);\n    // this.element.addEventListener(\"keyup\", this._keyup);\n  }\n\n  _observeMutation(track) {\n    if (this.observer) this.observer.disconnect();\n\n    this.observer = null;\n\n    if (!track) return;\n\n    this.observer = new MutationObserver((mutation_array) => {\n      if (this.logMutation) {\n        let monitor = mutation_array.map((m) => {\n          return {\n            target: m.target.cloneNode(true),\n            type: m.type,\n            name: m.attributeName,\n            added: (() => {\n              let clones = [];\n              for (let a of m.addedNodes) {\n                if (a.nodeType === 3) clones.push(a.textContent);\n                else clones.push(a.cloneNode(true));\n              }\n              return clones;\n            })(),\n            removed: (() => {\n              let clones = [];\n              for (let r of m.removedNodes) {\n                if (r.nodeType === 3) clones.push(r.textContent);\n                else clones.push(r.cloneNode(true));\n              }\n              return clones;\n            })(),\n          };\n        });\n\n        let mutate = [];\n        for (let m of monitor) {\n          if (m.type === \"childList\" || m.attributeName === \"class\")\n            mutate.push(m);\n        }\n\n        if (mutate.length)\n          this._callback({ mutation: mutate }).catch((err) => err);\n      }\n\n      for (const mutation of mutation_array) {\n        /** changes in attributes */\n        if (mutation.type === \"attributes\") {\n          const { target, attributeName } = mutation;\n          if (attributeName === \"class\") {\n            if (\n              target.parentNode &&\n              !target.classList.length &&\n              !(\n                this._isTextBlockElement(target) ||\n                this._isBlockElement(target) ||\n                target.nodeName === \"P\"\n              )\n            ) {\n              // this._unwrapElement(target);\n              this._wrapNode(target);\n            }\n            if (!target.classList.length) target.removeAttribute(\"class\");\n          }\n          //  prevent style attributes\n          if (attributeName === \"style\" && !this._isStyleAllowedElement(target))\n            target.removeAttribute(\"style\");\n          continue;\n        }\n\n        /** changes in node */\n        if (mutation.type === \"childList\") {\n          let mutationTarget = mutation.target;\n\n          /** removed nodes */\n          if (mutation.removedNodes.length) {\n            for (let m of mutation.removedNodes) {\n              /**\n               *  CAUTION!\n               *  changing the order of if statements below can lead to critical flaw\n               *  _custom_ class should always be checked after _urllink_ and _hashtag_\n               */\n\n              let callbackRemoved = (what, m) => {\n                if (!m.id) return;\n\n                let arrIdx = this[`${what}_array`].length;\n                let removed;\n\n                while (arrIdx--) {\n                  let got = this[`${what}_array`][arrIdx];\n                  if (got.elementId === m.id) {\n                    removed = this[`${what}_array`].splice(arrIdx, 1);\n                    break;\n                  }\n                }\n\n                if (removed) {\n                  this._callback({ removed: { [what]: removed } });\n                }\n              };\n\n              if (m?.classList?.contains(\"_media_\")) {\n                let child = m.childNodes;\n                let childIdx = child.length;\n                while (childIdx--) {\n                  let c = child[childIdx];\n                  switch (c.nodeName) {\n                    case \"IMG\":\n                      callbackRemoved(\"image\", c);\n                      break;\n                  }\n                }\n                continue;\n              }\n\n              let toBreak = false;\n              for (let t of [\"hashtag\", \"urllink\", \"custom\"]) {\n                if (m?.id?.includes(t)) {\n                  callbackRemoved(t, m);\n                  toBreak = true;\n                  break;\n                }\n              }\n\n              toBreak = false;\n\n              if (\n                this._isCeilingElement(mutationTarget) &&\n                (() => {\n                  let idx = mutationTarget.childNodes.length;\n                  if (idx)\n                    while (idx--) {\n                      let node = mutationTarget.childNodes[idx];\n                      if (node.nodeType === 1 || node.textContent) {\n                        return false;\n                      }\n                    }\n                  return true;\n                })()\n              ) {\n                mutationTarget.remove();\n                continue;\n              }\n\n              if (\n                this._isTextBlockElement(mutationTarget) &&\n                mutationTarget.childNodes.length === 1 &&\n                this._isUnSelectableElement(mutationTarget.childNodes[0])\n              )\n                mutationTarget.append(document.createTextNode(\"\"));\n            }\n          }\n\n          /** added nodes */\n          if (mutation.addedNodes.length)\n            for (let i of mutation.addedNodes) {\n              let getBr = (n) => {\n                let idx = n?.childNodes?.length;\n                let br = [];\n                while (idx--) {\n                  let c = n.childNodes[idx];\n                  if (c.nodeName === \"BR\") br.push(c);\n                }\n                return br;\n              };\n\n              if (i.nodeType === 3) {\n                // wrap all eldest text node\n                if (this._isCeilingElement(mutationTarget))\n                  this._wrapNode(i, document.createElement(\"p\"));\n                // remove <br> when there is text\n                else if (i.textContent && i.textContent !== \"\\u200B\") {\n                  // prevent br added to line\n                  let br = getBr(mutationTarget);\n                  if (br.length) for (let b of br) b.remove();\n                }\n\n                continue;\n              }\n\n              if (i.nodeType === 1) {\n                let node = (() => {\n                  let isWysiwygChild =\n                    i.closest(`#${this.elementId}`) && i.id !== this.elementId;\n                  let isWysiwygEldestChild = (() => {\n                    if (!isWysiwygChild) return false;\n\n                    return this._isCeilingElement(mutationTarget);\n                  })();\n\n                  let ceiling = (() => {\n                    for (let c of this.ceilingElement_queryArray) {\n                      if (c === '#' + this.elementId) return this.element;\n                      let clo = i.closest(c);\n                      if (clo) return clo;\n                    }\n                    return null;\n                  })();\n\n                  let line = isWysiwygEldestChild\n                    ? i\n                    : isWysiwygChild &&\n                    (() => {\n                      let m = i;\n                      while (m && !this._isCeilingElement(m.parentNode)) {\n                        m = m.parentNode;\n                      }\n                      return m;\n                    })();\n\n                  return {\n                    isWysiwygChild,\n                    isWysiwygEldestChild,\n                    isMediaElement: i.closest(\"._media_\"),\n                    isBlockQuoteElement: i.closest(\"blockquote\"),\n                    isCustomElement: i.closest(\"._custom_\"),\n                    isHashtagElement: i.closest(\"._hashtag_\"),\n                    isUrlLinkElement: i.closest(\"._urllink_\"),\n                    ceiling,\n                    line,\n                  };\n                })();\n\n                if (!node.isWysiwygChild) continue; // bypass\n\n                if (\n                  // node.isCustomElement ||\n                  node.isMediaElement ||\n                  node.isHashtagElement ||\n                  node.isUrlLinkElement\n                ) {\n                  // make sure un-editable element is secure\n                  let el =\n                    // node.isCustomElement ||\n                    node.isMediaElement ||\n                    node.isHashtagElement ||\n                    node.isUrlLinkElement;\n\n                  // check if el has a value of contenteditable\n                  // if (el.getAttribute(\"contenteditable\") !== \"true\")\n                  //   el.setAttribute(\"contenteditable\", \"false\");\n\n                  continue;\n                }\n\n                if (\n                  !(\n                    (node.isWysiwygEldestChild || node.isCustomElement) &&\n                    (this._isBlockElement(i) || this._isTextBlockElement(i))\n                  ) &&\n                  i.nodeName !== \"BR\" &&\n                  !i.classList.length\n                ) {\n                  // unwrap anything that does not have class and is not block level text\n                  this._wrapNode(i);\n                  continue;\n                }\n\n                if (\n                  (() => {\n                    if (this._isStyleAllowedElement(i)) return false;\n\n                    for (let sa of this.restrictedElement_queryArray) {\n                      if (i.closest(sa)) return false;\n                    }\n\n                    return true;\n                  })()\n                )\n                  //  remove style attribute if not allowed\n                  i.removeAttribute(\"style\");\n\n                if (\n                  node.isWysiwygEldestChild &&\n                  !(this._isBlockElement(i) || this._isTextBlockElement(i))\n                ) {\n                  //  wrap eldest non text block element to p\n                  if (i.nodeName === \"BR\") i.remove();\n                  else this._wrapNode(i, document.createElement(\"p\"), true);\n                  continue;\n                }\n\n                if (\n                  mutationTarget.textContent &&\n                  mutationTarget.textContent !== \"\\u200B\"\n                ) {\n                  // prevent br added to line\n                  let br = getBr(mutationTarget);\n                  let doContinue = false;\n                  if (br.length)\n                    for (let b of br) {\n                      if (b === i) doContinue = true;\n                      // #[MARK]\n                      b.remove();\n                    }\n                  if (doContinue) continue;\n                }\n\n                if (node.isWysiwygEldestChild && !this._isCeilingElement(i)) {\n                  // add tab on new line created by pressing enter\n                  if (this.insertTabPending_tabString) {\n                    let tab = document.createTextNode(\n                      this.insertTabPending_tabString\n                    );\n                    node.line.insertBefore(tab, node.line.childNodes[0]);\n                    this.insertTabPending_tabString = \"\";\n                    this._adjustSelection({ node: tab, position: false });\n                  }\n\n                  // if empty text block is added add br\n                  if (\n                    !node.line.textContent ||\n                    node.line.textContent === \"\\u200B\"\n                  ) {\n                    let addBr = true;\n                    this._nodeCrawler(\n                      (n) => {\n                        if (n.nodeName === \"BR\") {\n                          addBr = false;\n                          return \"BREAK\";\n                        }\n                        return n;\n                      },\n                      { node: node.line }\n                    );\n\n                    if (addBr) node.line.append(document.createElement(\"br\"));\n                  }\n\n                  continue;\n                }\n\n                let classSet = (c) => {\n                  let counter = this.counterTagOf[c] || [];\n\n                  if (counter.length)\n                    counter = counter.concat(\n                      counter.map((m) => {\n                        return m + \"_stop\";\n                      })\n                    );\n\n                  return [\n                    c,\n                    c.includes(\"_stop\") ? c.replace(\"_stop\", \"\") : c + \"_stop\",\n                  ].concat(counter);\n                };\n\n                let toUnwrap = [];\n\n                if (i.classList.length) {\n                  this._climbUpToEldestParent(i, node.ceiling, true, (n) => {\n                    let cIdx = i.classList.length;\n                    while (cIdx--) {\n                      if (\n                        (() => {\n                          let set = classSet(i.classList[cIdx]);\n                          for (let s of set) {\n                            if (n.classList.contains(s)) return true;\n                          }\n                          return false;\n                        })()\n                      )\n                        toUnwrap.push(n);\n                    }\n\n                    return n;\n                  });\n                }\n\n                let idx = toUnwrap.length;\n\n                while (idx--) {\n                  // unwrap unnecessary counter parents\n                  this._wrapNode(toUnwrap[idx]);\n                }\n\n                let class_idx = i.classList.length;\n                while (class_idx--) {\n                  let className = i.classList[class_idx];\n                  let curSt = this._trackStyle(\n                    i,\n                    className.replace(\"_stop\", \"\")\n                  );\n                  let parSt = this._trackStyle(\n                    i.parentNode,\n                    className.replace(\"_stop\", \"\")\n                  );\n\n                  if (curSt === parSt)\n                    // remove style class if parent shares the same style\n                    i.classList.remove(className);\n                }\n\n                if (!i.classList.length) {\n                  // remove style attribute if there is no class\n                  i.removeAttribute(\"class\");\n                }\n\n                if (\n                  this._isTextBlockElement(mutationTarget) &&\n                  mutationTarget.childNodes.length === 1 &&\n                  this._isUnSelectableElement(mutationTarget.childNodes[0])\n                )\n                  // mutationTarget.append(document.createTextNode(\"\\u200B\"));\n                  mutationTarget.append(document.createTextNode(\"\"));\n              }\n            }\n        }\n      }\n    });\n    this.observer.observe(this.element, {\n      attributes: true,\n      childList: true,\n      subtree: true,\n    });\n  }\n\n  _setArrow(e) {\n    if (this.logExecution) console.log(\"_setArrow\", { e });\n    if (!this.range || !e?.key) return;\n\n    let endContainer,\n      endOffset,\n      startContainer,\n      startOffset,\n      collapsed,\n      startLine,\n      endLine,\n      isAllRangeOnSameLine,\n      currentLine,\n      caratElement,\n      arrowDirection;\n\n    let key = e.key.toUpperCase();\n    let shift = e?.shiftKey || false;\n    let metaKey = e?.ctrlKey || e?.metaKey || false;\n    let rangeSetup = () => {\n      endContainer = this.range?.endContainer;\n      endOffset = this.range?.endOffset;\n      startContainer = this.range?.startContainer;\n      startOffset = this.range?.startOffset;\n      collapsed = this.range?.collapsed;\n      startLine = this.range?.startLine;\n      endLine = this.range?.endLine;\n      isAllRangeOnSameLine = startLine === endLine;\n      currentLine = this.isRangeDirectionForward ? endLine : startLine;\n      caratElement = this.isRangeDirectionForward\n        ? endContainer\n        : startContainer;\n      caratElement =\n        caratElement?.nodeType === 3 ? caratElement?.parentNode : caratElement;\n    };\n\n    let preventDefault = () => {\n      try {\n        e.preventDefault();\n      } catch (err) { }\n    };\n\n    let removeZeroSpace = () => {\n      let targetContainer = this.isRangeDirectionForward\n        ? endContainer\n        : startContainer;\n      let nudged = false;\n\n      if (\n        collapsed &&\n        (targetContainer.textContent.includes(\"\\u200B\") ||\n          !targetContainer.textContent)\n      ) {\n        this._nodeCrawler(\n          (n) => {\n            if (\n              n.nodeType === 3 &&\n              (n.textContent === \"\\u200B\" || !n.textContent)\n            ) {\n              let r = n.nextSibling || n.parentNode;\n              let siblingDirection = this.isRangeDirectionForward\n                ? \"nextSibling\"\n                : \"previousSibling\";\n\n              if (\n                n === targetContainer ||\n                (() => {\n                  // fuck safari\n                  if (targetContainer.nodeType === 1) {\n                    let idx = targetContainer.childNodes.length;\n                    while (idx--) {\n                      if (targetContainer.childNodes[idx] === n) return true;\n                    }\n                    return false;\n                  }\n                })()\n              ) {\n                let run = r;\n                if (run.nodeType === 1 && n.parentNode === run) {\n                  if (run[siblingDirection]) nudged = run[siblingDirection];\n                } else nudged = r;\n\n                n.remove();\n\n                this.range = this._adjustSelection({\n                  node: !collapsed\n                    ? this.isRangeDirectionForward\n                      ? [null, nudged || r]\n                      : [nudged || r, null]\n                    : nudged,\n                  position: !collapsed\n                    ? this.isRangeDirectionForward\n                      ? [null, nudged]\n                      : [!nudged, null]\n                    : this.isRangeDirectionForward,\n                });\n\n                rangeSetup();\n                preventDefault();\n                return \"BREAK\";\n              }\n            }\n            return n;\n          },\n          { node: targetContainer }\n        );\n      }\n      return !!nudged;\n    };\n\n    let isCaratOnMultiLine = (el) => {\n      // check if carat is on the first / last line of multi wrapped line\n\n      let posTarget = arrowDirection === \"DOWN\" ? \"bottom\" : \"top\";\n      let caratViewPortPosition = this.range.getBoundingClientRect();\n      let elPosition = el.getBoundingClientRect()[posTarget];\n      let phoneTextSize = parseInt(\n        this.fontSizeCssVariable[\"--wysiwyg-font-phone\"]\n      );\n\n      if (caratViewPortPosition.height) {\n        let isLastLine =\n          (posTarget === \"bottom\"\n            ? elPosition - caratViewPortPosition[posTarget]\n            : caratViewPortPosition[posTarget] - elPosition) < phoneTextSize;\n        return !isLastLine;\n      }\n\n      return false;\n    };\n\n    let nudgeRangeToInlineElement = () => {\n      let rem = removeZeroSpace();\n\n      if (\n        !rem &&\n        window.getComputedStyle(caratElement).display === \"inline-block\"\n      ) {\n        let _caratElement =\n          caratElement.nodeType === 3 ? caratElement.parentNode : caratElement;\n        while (\n          window.getComputedStyle(_caratElement).display === \"inline-block\"\n        ) {\n          _caratElement = _caratElement.parentNode;\n        }\n\n        let siblingDirection =\n          arrowDirection === \"UP\" ? \"previousSibling\" : \"nextSibling\";\n        let nextEl = _caratElement[siblingDirection];\n\n        if (!nextEl) {\n          let t = document.createTextNode(\"\");\n          _caratElement.parentNode.insertBefore(\n            t,\n            siblingDirection === \"previousSibling\" ? _caratElement : nextEl\n          );\n        }\n\n        _caratElement = _caratElement[siblingDirection];\n\n        if (_caratElement) {\n          let setDirection = (() => {\n            return arrowDirection === \"DOWN\";\n          })();\n\n          this.range = this._adjustSelection({\n            node: shift\n              ? this.isRangeDirectionForward\n                ? [null, _caratElement]\n                : [_caratElement, null]\n              : _caratElement,\n            position: shift\n              ? this.isRangeDirectionForward\n                ? [null, setDirection]\n                : [setDirection, null]\n              : setDirection,\n          });\n\n          rangeSetup();\n\n          return true;\n        }\n      }\n      return false;\n    };\n\n    rangeSetup();\n\n    switch (key) {\n      case \"ARROWLEFT\":\n        arrowDirection = \"LEFT\";\n      case \"ARROWRIGHT\":\n        arrowDirection = arrowDirection || \"RIGHT\";\n\n        if (metaKey || (collapsed && shift)) {\n          this.isRangeDirectionForward = arrowDirection === \"RIGHT\";\n          rangeSetup();\n        }\n\n        let caratOnSingleLine = !isCaratOnMultiLine(caratElement);\n\n        let nudged;\n        if (caratOnSingleLine) {\n          if (metaKey && arrowDirection === \"RIGHT\")\n            nudged = nudgeRangeToInlineElement();\n        }\n\n        if (!nudged) removeZeroSpace();\n\n        break;\n\n      case \"ARROWUP\":\n        arrowDirection = \"UP\";\n      case \"ARROWDOWN\":\n        arrowDirection = arrowDirection || \"DOWN\";\n\n        if (!collapsed && !shift) {\n          preventDefault();\n          let adj =\n            arrowDirection === \"UP\"\n              ? [startContainer, startOffset]\n              : [endContainer, endOffset];\n          this.range = this._adjustSelection({\n            node: adj[0],\n            position: adj[1],\n          });\n          break;\n        }\n\n        if (collapsed || isAllRangeOnSameLine) {\n          this.isRangeDirectionForward = arrowDirection === \"DOWN\";\n          rangeSetup();\n        }\n\n        if (isCaratOnMultiLine(caratElement)) break;\n\n        let iNudged = nudgeRangeToInlineElement();\n\n        if (iNudged) break;\n        else removeZeroSpace();\n\n        let isMultiLine = isCaratOnMultiLine(currentLine);\n        if (isMultiLine) break;\n\n        let eldestParentOfCurrentLine = this._climbUpToEldestParent(\n          currentLine,\n          this.element\n        );\n\n        let isCurrentLineInsideSubCeiling =\n          eldestParentOfCurrentLine.id !== this.elementId &&\n          this._isCeilingElement(eldestParentOfCurrentLine);\n\n        // break out if current line is inside the sub ceiling and it's not on the last line\n        if (\n          isCurrentLineInsideSubCeiling &&\n          ((arrowDirection === \"UP\" &&\n            eldestParentOfCurrentLine.firstChild !== currentLine) ||\n            (arrowDirection === \"DOWN\" &&\n              eldestParentOfCurrentLine.lastChild !== currentLine))\n        )\n          break;\n\n        let siblingSet = [\n          isCurrentLineInsideSubCeiling\n            ? eldestParentOfCurrentLine.previousSibling\n            : currentLine.previousSibling,\n          isCurrentLineInsideSubCeiling\n            ? eldestParentOfCurrentLine.nextSibling\n            : currentLine.nextSibling,\n        ];\n\n        if (arrowDirection === \"UP\") siblingSet.reverse();\n\n        let [backwardNode, forwardNode] = siblingSet;\n\n        // if current line is on last line of sub ceiling set forward node to sub ceiling\n        let _forwardNode = isCurrentLineInsideSubCeiling\n          ? eldestParentOfCurrentLine\n          : forwardNode;\n        if (_forwardNode) {\n          if (this._isBlockElement(_forwardNode) && !shift) {\n            preventDefault();\n\n            let leap =\n              arrowDirection === \"UP\"\n                ? _forwardNode.previousSibling\n                : _forwardNode.nextSibling;\n\n            if (!leap || this._isBlockElement(leap)) {\n              let p = this._createEmptyParagraph();\n              _forwardNode.parentNode.insertBefore(\n                p,\n                arrowDirection === \"UP\" ? _forwardNode : leap\n              );\n              _forwardNode = p;\n            } else _forwardNode = leap;\n\n            this.range = this._adjustSelection({\n              node: _forwardNode,\n              position: arrowDirection === \"DOWN\",\n            });\n\n            if (\n              !shift &&\n              !currentLine.textContent &&\n              (this._isBlockElement(backwardNode) ||\n                (!backwardNode && currentLine === this.element.firstChild))\n            )\n              this.removeSandwichedLine_array.push(currentLine);\n          } else if (!isMultiLine && arrowDirection === \"DOWN\") {\n            preventDefault();\n            let collectOffset = 0;\n            let currentOffset = this.isRangeDirectionForward\n              ? endOffset\n              : startOffset;\n            this._nodeCrawler(\n              (n) => {\n                if (n === endContainer) return \"BREAK\";\n                else if (n.nodeType === 3 && n.textContent)\n                  collectOffset += n.textContent.length;\n                return n;\n              },\n              {\n                node: currentLine,\n              }\n            );\n            collectOffset += currentOffset;\n            this.range = this._adjustSelection({\n              node: collapsed\n                ? forwardNode\n                : this.isRangeDirectionForward\n                  ? [null, forwardNode]\n                  : [forwardNode, null],\n              position: collapsed\n                ? collectOffset\n                : this.isRangeDirectionForward\n                  ? [null, collectOffset]\n                  : [collectOffset, null],\n            });\n          }\n        } else preventDefault();\n    }\n  }\n\n  _append(i, insertAfter, wrap = false, focusElement) {\n    if (this.logExecution)\n      console.log(\"_append\", { i, insertAfter, wrap, focusElement });\n    let common = this._climbUpToEldestParent(\n      this.range.commonAncestorContainer,\n      this.element\n    );\n    let [startLine, endLine] = this._getStartEndLine();\n    // let startLine = this._climbUpToEldestParent(this.range.startContainer, this.element);\n    // let endLine = this._climbUpToEldestParent(this.range.endContainer, this.element);\n    let insertRestricted = [\"HR\", \"UL\", \"LI\", \"._media_\", \"._custom_\"];\n\n    let append = (node) => {\n      if (node === this.element)\n        node = this.element.childNodes[this.element.childNodes.length - 1];\n\n      let next = node.nextSibling;\n      if (insertAfter) node.parentNode.insertBefore(insertAfter, next);\n\n      node.parentNode.insertBefore(i, insertAfter || next);\n\n      if (\n        this._isTextElement(node) &&\n        !node.textContent &&\n        this.element.lastChild !== node\n      ) {\n        // #MARK\n        node.remove();\n      }\n    };\n\n    if (wrap) {\n      let nodeToUnwrap = {};\n      let restricted = false;\n\n      let checker = (tag, el) => {\n        // tag.replace(\"backgroundcolor\", \"backgroundColor\");\n        if (\n          el &&\n          (!nodeToUnwrap[tag] ||\n            (() => {\n              for (let u in nodeToUnwrap) {\n                if (nodeToUnwrap[u] === el) return false;\n              }\n              return true;\n            })())\n        )\n          nodeToUnwrap[tag] = el;\n      };\n\n      if (this.range.collapsed) {\n        checker(i.nodeName, startLine.closest(i.nodeName));\n\n        let idx = i.classList.length;\n        while (idx--) {\n          let className = i.classList[idx];\n          checker(className, startLine.closest(\".\" + className));\n        }\n      } else\n        this._nodeCrawler(\n          (n) => {\n            let chk = n.nodeType === 3 ? n.parentNode : n;\n            if (chk.nodeType !== 1) {\n              restricted = true;\n              return \"BREAK\";\n            }\n\n            if (n.nodeType === 1) {\n              for (let notAllowed of insertRestricted)\n                if (n.nodeName === notAllowed || n.closest(notAllowed)) {\n                  restricted = true;\n                  return \"BREAK\";\n                }\n            }\n\n            checker(i.nodeName, chk.closest(i.nodeName));\n\n            let idx = i.classList.length;\n            while (idx--) {\n              let className = i.classList[idx];\n              checker(className, chk.closest(\".\" + className));\n            }\n\n            if (n === this.range.endContainer) return \"BREAK\";\n\n            return n;\n          },\n          { node: common, startNode: this.range.startContainer }\n        );\n\n      if (restricted) return;\n\n      if (Object.keys(nodeToUnwrap).length) {\n        for (let u in nodeToUnwrap) this._wrapNode(nodeToUnwrap[u]);\n      } else {\n        append(endLine);\n\n        let extract = this.range.extractContents();\n\n        if (extract.childNodes[0]) {\n          while (extract.childNodes[0]) {\n            let t = extract.childNodes[0];\n            if (!t.textContent) {\n              // #[MARK]\n              t.remove();\n            }\n            else i.append(t);\n          }\n        } else i.append(this._createEmptyParagraph());\n\n        this.range = this._adjustSelection({\n          node: focusElement || i,\n          position: false,\n        });\n\n        //  remove garbage node\n        let fc = i.previousSibling;\n        // let lc = i.nextSibling;\n\n        if (fc) {\n          fc = fc.nodeType === 3 ? fc.parentNode : fc;\n\n          if (\n            this._isTextElement(fc) &&\n            (!fc.textContent || fc.textContent === \"\\u200B\")\n          ) {\n            // #[MARK]\n            fc.remove();\n          }\n        }\n      }\n\n      return;\n    }\n\n    for (let r of insertRestricted) {\n      if (endLine.closest(r)) endLine = endLine.closest(r);\n    }\n\n    append(endLine);\n\n    if (insertAfter)\n      this.range = this._adjustSelection({ node: focusElement || insertAfter });\n  }\n\n  async _callback(data) {\n    if (typeof this.callback === \"function\") {\n      let cb = this.callback(data) || data;\n      if (cb instanceof Promise) {\n        cb = await cb;\n      }\n      return cb || data;\n    }\n    return data;\n  }\n\n  async _imageSelected(e) {\n    if (this.logExecution) console.log(\"_imageSelected\", { e });\n    let files = e.target.files;\n\n    const prepareForCallback = { image: [] };\n    let readFile = new FileReader();\n\n    const load = (file) => {\n      return new Promise((res) => {\n        readFile.onload = (f) => {\n          const { lastModified, name, size, type } = file;\n          const source = f.target.result;\n\n          let img = new Image();\n          img.onload = () => {\n            res({\n              dimension: {\n                width: img.width,\n                height: img.height,\n              },\n              lastModified,\n              filename: name,\n              fileSize: size,\n              fileType: type,\n              source,\n              elementId: this._generateId(\"img\"),\n            });\n          };\n          img.src = source;\n        };\n        readFile.readAsDataURL(file);\n      });\n    };\n\n    this.callback({ loading: true });\n    for (let idx = 0; files.length > idx; idx++) {\n      prepareForCallback.image[idx] = await load(files[idx]);\n    }\n    this.callback({ loading: false });\n\n    //  reset image input\n    this.imgInput.value = \"\";\n\n    let feedback = await this._callback(prepareForCallback);\n\n    if (!this.range) {\n      this.restoreLastSelection();\n    }\n    if (\n      !this.range ||\n      (() => {\n        let c = this.range.commonAncestorContainer;\n        c = c.nodeType === 3 ? c.parentNode : c;\n        return !c.closest(\"#\" + this.elementId);\n      })()\n    )\n      this.element.focus();\n\n    this._modifySelection(() => {\n      for (let img of feedback.image) {\n        let media = this._loadImage(img, document.createElement(\"div\"));\n        this._append(media, this._createEmptyParagraph());\n      }\n    });\n  }\n\n  _loadImage(imageObject, wrapper) {\n    if (this.logExecution) console.log(\"_loadImage\", { imageObject, wrapper });\n    /**\n         elementId: \"img_uniqueId\"\n         element: HTML\n         fileSize: 0\n         fileType: \"image/jpeg\"\n         source: \"file.jpg | http://url.com/file.jpg | s3 filename | base 64 string\"\n         lastModified: 0000000000000\n         filename: \"selectedLocalFilename.jpg\"\n         */\n\n    if (wrapper instanceof Node) {\n      if (!wrapper.classList.contains(\"_media_\"))\n        wrapper.classList.add(\"_media_\");\n\n      if (wrapper.getAttribute(\"contenteditable\") !== \"false\")\n        wrapper.setAttribute(\"contenteditable\", \"false\");\n    } else throw \"image needs _media_ wrapper\";\n\n    let process = (i) => {\n      let image = i?.element instanceof Node ? i.element : null;\n\n      if (image) {\n        if (image.id) i.elementId = image.id;\n        else image.id = i.elementId;\n      }\n\n      if (!image) {\n        image = document.createElement(\"img\");\n        i.element = image;\n\n        let classname =\n          \"_img_\" +\n          i.source\n            .substring(i.source.length - 128)\n            .replace(/[/:.\"'\\\\@#$%\\?= \\{\\}\\|&*`!<>+]/g, \"\");\n        if (image.classList.contains(classname)) image.classList.add(classname);\n\n        if (Array.isArray(i.class)) {\n          for (let cl of i.class) image.classList.add(cl);\n        }\n\n        if (image.tagName === \"IMG\") image.setAttribute(\"src\", i.source);\n\n        if (typeof i.onclick === \"function\") {\n          image.addEventListener(\"click\", i.onclick);\n          image.classList.add(\"_hover_\");\n        }\n\n        if (\n          i.style &&\n          typeof i.style === \"object\" &&\n          Object.keys(i.style).length\n        ) {\n          for (let st in i.style) {\n            wrapper.style.setProperty(st, i.style[st]);\n          }\n        }\n      }\n\n      wrapper.setAttribute(\"contenteditable\", \"false\");\n      wrapper.append(image);\n\n      let pushArray = true;\n\n      for (let chk of this.image_array)\n        if (chk.elementId === i.elementId) {\n          pushArray = false;\n          break;\n        }\n\n      if (pushArray) this.image_array.push(i);\n    };\n\n    process(imageObject);\n\n    return wrapper;\n  }\n\n  _getAnchorOffsetFromLine(line) {\n    const sel = window.getSelection();\n    if (!sel || !sel.anchorNode) return 0;\n\n    let anchorNode = sel.anchorNode;\n    let anchorOffset = sel.anchorOffset;\n\n    // If anchorNode is not inside line, return 0\n    if (!line.contains(anchorNode) && line !== anchorNode) return 0;\n\n    let offset = 0;\n    let found = false;\n\n    function traverse(node) {\n      if (found) return;\n      if (node === anchorNode) {\n        offset += anchorOffset;\n        found = true;\n        return;\n      }\n      if (node.nodeType === 3) {\n        offset += node.textContent.length;\n      } else {\n        for (let child of node.childNodes) {\n          traverse(child);\n          if (found) break;\n        }\n      }\n    }\n\n    traverse(line);\n    return offset;\n  }\n  _getFocusOffsetFromLine(line) {\n    const sel = window.getSelection();\n    if (!sel || !sel.focusNode) return 0;\n\n    let focusNode = sel.focusNode;\n    let focusOffset = sel.focusOffset;\n\n    // If focusNode is not inside line, return 0\n    if (!line.contains(focusNode) && line !== focusNode) return 0;\n\n    let offset = 0;\n    let found = false;\n\n    function traverse(node) {\n      if (found) return;\n      if (node === focusNode) {\n        offset += focusOffset;\n        found = true;\n        return;\n      }\n      if (node.nodeType === 3) {\n        offset += node.textContent.length;\n      } else {\n        for (let child of node.childNodes) {\n          traverse(child);\n          if (found) break;\n        }\n      }\n    }\n\n    traverse(line);\n    return offset;\n  }\n  _modifySelection(run, lineByLine) {\n    if (this.logExecution) console.log(\"_modifySelection\", { run });\n    let sel = window.getSelection();\n    if (!sel) {\n\n      this.range = null;\n      this.commandTracker = {};\n      return;\n    }\n    let doSingleLine = (sel) => {\n      let anchorElement =\n        sel.anchorNode?.nodeType === 3\n          ? sel.anchorNode.parentNode\n          : sel.anchorNode;\n      if (anchorElement && anchorElement.closest(`#${this.elementId}`)) {\n        if (anchorElement.id === this.elementId) {\n          // In case selection is the wysiwyg element itself\n          let lastChild = this.element.lastChild;\n          if (!lastChild) {\n            // Wysiwyg is empty\n            lastChild = this._createEmptyParagraph();\n            this.element.appendChild(lastChild);\n\n            // Adjust selection\n            this.range = this._adjustSelection({\n              node: lastChild,\n              position: true,\n            });\n          }\n        } else this.range = this._adjustSelection(null);\n\n        if (typeof run === \"function\") run();\n        return;\n      }\n\n      this.range = null;\n      this.commandTracker = {};\n    };\n\n    return doSingleLine(sel);\n  }\n\n  _isFirstOrLastChild(node) {\n    let fc = this.element.firstChild;\n    let lc = this.element.lastChild;\n    if (!fc || !lc) return false;\n\n    if (this.logExecution) console.log(\"_isFirstOrLastChild\", { node });\n    if (!node || !node.parentNode) return false;\n\n    if (node.nodeType === 3) node = node.parentNode;\n    if (fc === node || lc === node) {\n      return node;\n    }\n\n    let eldestParent = this._climbUpToEldestParent(node, this.element);\n    if (eldestParent === fc || eldestParent === lc) {\n      return eldestParent;\n    }\n    return false;\n  }\n\n  _normalizeDocument(normalize) {\n    if (this.logExecution) console.log(\"_normalizeDocument\", { normalize });\n    if (!normalize) return;\n    let to_remove = [];\n    this._nodeCrawler(\n      (n) => {\n        let fol = this._isFirstOrLastChild(n);\n        if (fol && !fol.classList.contains(\"_media_\") && !fol.classList.contains(\"_custom_\")) {\n          if (n.nodeType === 3) {\n            let np = n.parentNode;\n            if (np === this.element.firstChild || np === this.element.lastChild) {\n              if (np.firstChild === n || np.lastChild === n) {\n                return n;\n              }\n            }\n          }\n          if (n.nodeType === 1) {\n            if (fol === n) {\n              n.normalize();\n              if (!n.textContent)\n                n.textContent = \"\\u200B\";\n              // n.appendChild(\n              //   document.createElement(\"br\")\n              // );\n              return n;\n            }\n          }\n        }\n\n        if (n.tagName !== \"BR\" && n.nodeType === 1 && !n.classList.contains(\"_media_\") && !n.classList.contains(\"_custom_\") && n.textContent.includes(\"\\u200B\")) {\n          n.textContent = n.textContent.replaceAll(\"\\u200B\", \"\");\n          n.normalize();\n        }\n\n        if (\n          n.nodeType === 1 &&\n          !n.classList.contains(\"_media_\") && !n.classList.contains(\"_custom_\") &&\n          !this._isCeilingElement(n) &&\n          !n.textContent &&\n          !n.childNodes.length &&\n          n.tagName !== \"BR\"\n          // && n.tagName !== \"P\"\n        ) {\n          to_remove.push(n);\n        }\n\n        return n;\n      },\n      { node: this.element }\n    );\n\n    to_remove.forEach((n) => {\n      // #[MARK]\n      n.remove();\n    });\n  }\n\n  _replaceText(wholeDocument = false) {\n    if (this.logExecution) console.log(\"_replaceText\", { wholeDocument });\n    const process = (typeName, setData) => {\n      if (!this[typeName]) return;\n\n      let regex = this[`${typeName}_regex`] || null;\n\n      if (regex === null) throw new Error(\"no regex to process\");\n\n      if (typeof setData !== \"function\")\n        throw new Error(\"setData should be returning function\");\n\n      let node = wholeDocument\n        ? this.element\n        : this.range?.commonAncestorContainer;\n\n      if (!node) return;\n\n      if (node.nodeType === 3) node = node.parentNode;\n\n      let res = (() => {\n        let className = `_${typeName}_`;\n        let element = [];\n        let collected = [];\n\n        let textNodes = [];\n        this._nodeCrawler(\n          (n) => {\n            if (n.nodeType === 3 && n.textContent) {\n              if (\n                n.nextSibling?.nodeType === 3 &&\n                n.nextSibling.textContent &&\n                n.nextSibling.textContent !== \"\\u200B\"\n              ) {\n                let par = n.parentNode;\n                par.normalize();\n                n = par;\n              } else if (\n                n.textContent !== \"\\u200B\" &&\n                !n.parentNode.closest(\".\" + className)\n              )\n                textNodes.push(n);\n            }\n\n            return n;\n          },\n          { node }\n        );\n\n        textNodes.forEach((node) => {\n          replaceTextNode(node, regex, function (matched) {\n            if (matched.length > 1) {\n              return {\n                name: \"span\",\n                attrs: { class: `${className} ${className}${matched}` },\n                content: matched,\n              };\n            }\n          });\n        });\n\n        function replaceTextNode(node, regex, handler) {\n          let par = node.parentNode,\n            nxt = node.nextSibling,\n            doc = node.ownerDocument,\n            hits;\n\n          if (regex.global) {\n            while (node && (hits = regex.exec(node.nodeValue))) {\n              regex.lastIndex = 0;\n              node = handleResult(node, hits, handler.apply(this, hits));\n            }\n          } else if ((hits = regex.exec(node.nodeValue)))\n            handleResult(node, hits, handler.apply(this, hits));\n\n          function handleResult(node, hits, results) {\n            let orig = node.nodeValue;\n            node.nodeValue = orig.slice(0, hits.index);\n            [].concat(create(par, results)).forEach(function (n) {\n              let res = par.insertBefore(n, nxt);\n              element.push(res);\n            });\n            let rest = orig.slice(hits.index + hits[0].length);\n            if (rest) {\n              let text = doc.createTextNode(rest);\n              return par.insertBefore(text, nxt);\n            }\n          }\n\n          function create(el, o) {\n            if (o.map)\n              return o.map(function (v) {\n                return create(el, v);\n              });\n            else if (typeof o === \"object\") {\n              let e = doc.createElementNS(\n                o.namespaceURI || el.namespaceURI,\n                o.name\n              );\n              if (o.attrs) for (let a in o.attrs) e.setAttribute(a, o.attrs[a]);\n              if (o.content)\n                [].concat(create(e, o.content)).forEach(e.appendChild, e);\n              if (typeof o.content === \"string\") collected.push(o.content);\n              e.contentEditable = \"false\";\n              return e;\n            } else return doc.createTextNode(o + \"\");\n          }\n        }\n\n        let anchorText;\n        if (element.length) {\n          for (let el of element) {\n            anchorText = node.ownerDocument.createTextNode(\"\");\n            el.parentNode.insertBefore(anchorText, el.nextSibling);\n          }\n        }\n        return { collected, element, anchorText };\n      })();\n\n      let textEl = res.element;\n\n      if (!wholeDocument) {\n        this.range = this._adjustSelection({\n          node: res.anchorText,\n          position: false,\n        });\n      }\n\n      let toCallback = [];\n      let collectId = [];\n\n      if (textEl[0])\n        for (let el of textEl) {\n          let elementId = this._generateId(typeName);\n          el.setAttribute(\"id\", elementId);\n          let tc = setData(el) || {};\n          tc.elementId = el.id;\n          tc.element = el;\n\n          el.removeAttribute(\"style\");\n          collectId.push(el.id);\n          toCallback.push(tc);\n        }\n\n      if (toCallback.length) {\n        this._callback({ [typeName]: toCallback })\n          .then((e) => {\n            for (let idx = 0; collectId.length > idx; idx++) {\n              //  elementId is read only\n              e[typeName][idx].elementId = collectId[idx];\n            }\n\n            if (Array.isArray(e[typeName]) && e[typeName].length)\n              for (let h of e[typeName]) {\n                let dom = document.getElementById(h.elementId);\n\n                dom.setAttribute(\"id\", h.elementId);\n                dom.setAttribute(\"contenteditable\", \"false\");\n\n                if (typeof h.onclick === \"function\") {\n                  dom.addEventListener(\"click\", h.onclick);\n                  dom.classList.add(\"_hover_\");\n                }\n\n                if (\n                  h.style &&\n                  typeof h.style === \"object\" &&\n                  Object.keys(h.style).length\n                ) {\n                  for (let s in h.style) dom.style.setProperty(s, h.style[s]);\n                }\n\n                this[`${typeName}_array`].push(h);\n              }\n          })\n          .catch((err) => {\n            console.error(err);\n          });\n      }\n    };\n\n    if (this.urllink_flag) {\n      process(\"urllink\", (url) => {\n        let u = url.textContent;\n        url.addEventListener(\"click\", function () {\n          if (!u.match(/^https?:\\/\\//i)) {\n            u = \"http://\" + u;\n          }\n          window.open(u, \"_blank\");\n        });\n\n        return { url: u };\n      });\n    }\n\n    if (this.hashtag_flag) {\n      process(\"hashtag\", (tag) => {\n        let t = tag.textContent;\n        return { tag: t[0] === \"#\" ? t.substring(1) : t };\n      });\n    }\n\n    this.hashtag_flag = false;\n    this.urllink_flag = false;\n  }\n\n  _checkElement(node, chkArr, closest, exp) {\n    /**\n     * parentNode when node is a text node\n     * chkArr is an array of class names or tag names\n     * closest is a boolean to check if the element is closest to the node\n     */\n    if (this.logExecution)\n      console.log(\"_checkElement\", { node, chkArr, closest, exp });\n    if (node && node.nodeType === 1)\n      for (let c of chkArr) {\n        if (closest) {\n          let clo = node.closest(c);\n          if (clo) {\n            if (exp && exp[c]) {\n              if (c === \"._custom_\") {\n                let flyup = node;\n                let gotTheMatch = false;\n                if (node !== this.element) {\n                  while (flyup && this.element !== flyup) {\n                    gotTheMatch =\n                      flyup.getAttribute(exp[c].attr) === exp[c].value;\n                    if (gotTheMatch) return false;\n\n                    flyup = flyup.parentNode;\n                  }\n                }\n              } else\n                return clo.getAttribute(exp[c].attr) === exp[c].value\n                  ? false\n                  : clo;\n            }\n\n            return clo;\n          }\n        } else if (\n          c[0] === \"#\"\n            ? node.id === c.substring(1)\n            : c[0] === \".\"\n              ? node.classList.contains(c.substring(1))\n              : node.nodeName === c\n        )\n          return true;\n      }\n    return false;\n  }\n\n  _isUnSelectableElement(node) {\n    if (this.logExecution) console.log(\"_isUnSelectableElement\", { node });\n    node = node?.nodeType === 3 ? node.parentNode : node;\n    // let exceptions = {\n    //   \"._custom_\": { attr: \"contenteditable\", value: \"true\" },\n    // };\n    return this._checkElement(\n      node,\n      this.unSelectable_queryArray,\n      true,\n      // exceptions\n    );\n  }\n\n  _isStyleAllowedElement(node) {\n    if (this.logExecution) console.log(\"_isStyleAllowedElement\", { node });\n    return this._checkElement(node, this.styleAllowedElement_queryArray);\n  }\n\n  _isCeilingElement(node) {\n    if (this.logExecution) console.log(\"_isCeilingElement\", { node });\n    return this._checkElement(node, this.ceilingElement_queryArray);\n  }\n\n  _isBlockElement(node) {\n    if (this.logExecution) console.log(\"_isBlockElement\", { node });\n    return this._checkElement(node, this.blockElement_queryArray);\n  }\n\n  _isTextAreaElement(node) {\n    if (this.logExecution) console.log(\"_isTextAreaElement\", { node });\n    return this._checkElement(node, this.textAreaElement_queryArray);\n  }\n\n  _isTextBlockElement(node) {\n    if (this.logExecution) console.log(\"_isTextBlockElement\", { node });\n    node = node?.nodeType === 3 ? node.parentNode : node;\n    return this._checkElement(node, this.textBlockElement_queryArray);\n  }\n\n  _isSpecialTextElement(node) {\n    if (this.logExecution) console.log(\"_isSpecialTextElement\", { node });\n    node = node?.nodeType === 3 ? node.parentNode : node;\n    return this._checkElement(node, this.specialTextElement_queryArray);\n  }\n\n  _isTextElement(node) {\n    if (this.logExecution) console.log(\"_isTextElement\", { node });\n    node = node?.nodeType === 3 ? node.parentNode : node;\n    return (\n      (this._isTextBlockElement(node) || node.nodeName === \"SPAN\") &&\n      !this._isSpecialTextElement(node)\n    );\n  }\n\n  /**\n   * List of command for editing wysiwyg text.\n   * @param {'quote'} action - Add blockquote below selected line.\n   * @also\n   * @param {'unorderedList'} action - Add unordered list below selected line.\n   * @also\n   * @param {'orderedList'} action - Add ordered list below selected line.\n   * @also\n   * @param {'divider'} action - Add HR below selected line.\n   * @also\n   * @param {'image'} action - Add image below selected line.\n   * @also\n   * @param {'alignLeft'} action - Align selected line to left.\n   * @also\n   * @param {'alignCenter'} action - Align selected line to center.\n   * @also\n   * @param {'alignRight'} action - Align selected line to right.\n   * @also\n   * @param {'color' | 'hex | rgb string | hsl string'} action - Apply color to selected text. If 'color' is given, the default focus color is applied to the text.\n   * @also\n   * @param {'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'small' | 'bold' | 'italic' | 'underline' | 'strike'} action - Apply style to selection.\n   * @also\n   * @param {object} action - Custom element object\n   * @param {object | string} action.element - Custom element can be node objects | html string | string\n   * @param {string} action.elementId - Set custom elements parent id. Otherwise auto generated\n   * @param {object} action.style - Set custom elements parent css style\n   * @param {boolean} action.insert - Set custom element insert mode. If true, inserts element at carat position, otherwise appends on next line\n   */\n  command(action) {\n    if (!action) return;\n\n    if (!this.range) this.restoreLastSelection();\n\n    switch (action) {\n      case \"quote\":\n        if (\n          !this.range ||\n          (() => {\n            let c = this.range.commonAncestorContainer;\n            c = c.nodeType === 3 ? c.parentNode : c;\n            return !c.closest(\"#\" + this.elementId);\n          })()\n        )\n          this.element.focus();\n\n        this._modifySelection(() => {\n          // let p = this._createEmptyParagraph(),\n          let bq = document.createElement(\"blockquote\");\n          this._append(bq, null, true);\n          this.setSafeLine();\n        });\n        return;\n      case \"unorderedList\":\n        if (\n          !this.range ||\n          (() => {\n            let c = this.range.commonAncestorContainer;\n            c = c.nodeType === 3 ? c.parentNode : c;\n            return !c.closest(\"#\" + this.elementId);\n          })()\n        )\n          this.element.focus();\n\n        this._modifySelection(() => {\n          // let p = this._createEmptyParagraph(),\n          let li = document.createElement(\"li\"),\n            ul = document.createElement(\"ul\");\n          ul.append(li);\n          // this._append(ul, p, false, li);\n          this._append(ul, null, false, li);\n          this.setSafeLine();\n        });\n\n        return;\n      case \"orderedList\":\n        if (\n          !this.range ||\n          (() => {\n            let c = this.range.commonAncestorContainer;\n            c = c.nodeType === 3 ? c.parentNode : c;\n            return !c.closest(\"#\" + this.elementId);\n          })()\n        )\n          this.element.focus();\n\n        this._modifySelection(() => {\n          // let p = this._createEmptyParagraph(),\n          let li = document.createElement(\"li\"),\n            ul = document.createElement(\"ol\");\n          ul.append(li);\n          // this._append(ul, p, false, li);\n          this._append(ul, null, false, li);\n          this.setSafeLine();\n        });\n\n        return;\n      case \"divider\":\n        if (\n          !this.range ||\n          (() => {\n            let c = this.range.commonAncestorContainer;\n            c = c.nodeType === 3 ? c.parentNode : c;\n            return !c.closest(\"#\" + this.elementId);\n          })()\n        )\n          this.element.focus();\n\n        this._modifySelection(() => {\n          // let p = this._createEmptyParagraph(),\n          let hr = document.createElement(\"hr\");\n          hr.setAttribute(\"contenteditable\", \"false\");\n          // this._append(hr, p, false);\n          this._append(hr, null, false);\n          this.setSafeLine();\n        });\n        return;\n      case \"image\":\n        this.imgInput.click();\n        return;\n      case \"alignLeft\":\n      case \"alignCenter\":\n      case \"alignRight\":\n        if (!this.range) return;\n\n        this._modifySelection(() => {\n          let startLine = this.range.startLine;\n          let endLine = this.range.endLine;\n\n          let collectLines = [];\n          collectLines.push(startLine);\n\n          while (collectLines[collectLines.length - 1] !== endLine) {\n            let nextLine = collectLines[collectLines.length - 1].nextSibling;\n\n            while (nextLine && !this._isTextBlockElement(nextLine)) {\n              if (\n                this._isCeilingElement(nextLine) &&\n                nextLine.firstChild &&\n                this._isTextBlockElement(nextLine.firstChild)\n              ) {\n                nextLine = nextLine.firstChild;\n                break;\n              }\n              nextLine = nextLine.nextSibling;\n            }\n\n            if (\n              !nextLine &&\n              this._isCeilingElement(\n                collectLines[collectLines.length - 1].parentNode\n              )\n            )\n              nextLine =\n                collectLines[collectLines.length - 1].parentNode.nextSibling;\n\n            if (nextLine) collectLines.push(nextLine);\n            else break;\n          }\n\n          let commandTracker = Object.assign({}, this.commandTracker);\n\n          for (let l of collectLines) {\n            for (let c of this.alignClass) {\n              if (l.classList.contains(c)) l.classList.remove(c);\n              commandTracker[c.substring(1, c.length - 1)] = false;\n            }\n\n            if (action !== \"alignLeft\" && !this.commandTracker[action]) {\n              for (let c of this.alignClass) {\n                if (c.includes(action)) l.classList.add(c);\n              }\n              commandTracker[action] = true;\n            }\n          }\n\n          this.commandTracker = commandTracker;\n\n          this._callback({\n            commandTracker,\n            range: this.range,\n          }).catch((err) => err);\n        });\n        return;\n\n      default:\n        break;\n    }\n\n    let isColor;\n    try {\n      isColor = new ColorMangle(action).hex();\n      action = \"color\";\n    } catch { }\n    let isBackgroundColor;\n    try {\n      if (action?.backgroundColor) {\n        isBackgroundColor = new ColorMangle(action?.backgroundColor).hex();\n        action = \"backgroundColor\";\n      }\n    } catch { }\n    //  style command\n    if (this.styleTagOfCommand[action]) {\n      this._modifySelection(() => {\n        let wrapper,\n          query = this.styleTagOfCommand[action],\n          stopperMode = false;\n\n        let counter = this.counterTagOf[query]\n          ? this.counterTagOf[query].map((c) => this._classNameToQuery(c))\n          : [];\n        if (counter.length)\n          counter = counter.concat(counter.map((c) => c + \"_stop\"));\n\n        //  setup query\n        query = this._classNameToQuery(query);\n\n        if (this.commandTracker[action]) {\n          let pass;\n\n          if (action === \"color\") {\n            pass =\n              isColor === this.commandTracker[action] ||\n              (isColor === undefined &&\n                this.commandTracker[action] ===\n                this.highlightColor);\n          } else if (action === \"backgroundColor\") {\n            pass =\n              isBackgroundColor === this.commandTracker[action] ||\n              (isBackgroundColor === undefined &&\n                this.commandTracker[action] ===\n                this.highlightColor);\n          } else pass = true;\n\n          if (pass) {\n            query = this._classNameToQuery(query + \"_stop\");\n            stopperMode = true;\n          }\n        }\n\n        //  setup wrapper element\n        if (query[0] === \".\") {\n          wrapper = document.createElement(\"SPAN\");\n          wrapper.classList.add(query.substring(1));\n        } else wrapper = document.createElement(query);\n\n        if (isColor && !stopperMode) wrapper.style.color = isColor;\n        if (isBackgroundColor && !stopperMode) wrapper.style.backgroundColor = isBackgroundColor;\n\n        let restrictedClass = this._isSelectionWithinRestrictedRange();\n        // console.log({ restrictedClass });\n        if (this.range.collapsed) {\n          if (restrictedClass) return;\n\n          // let text = document.createTextNode(\"\");\n          let text = document.createTextNode(\"\\u200B\");\n          wrapper.append(text);\n\n          if (this.range.startContainer.nodeName === \"BR\")\n            this.range.startContainer.parentNode.insertBefore(\n              wrapper,\n              this.range.startContainer\n            );\n          else this.range.insertNode(wrapper);\n\n          this.range = this._adjustSelection({ node: text, position: false });\n        } else {\n          if (restrictedClass) {\n            this.range = this._adjustSelection({\n              node: this.range.endContainer,\n              position: this.range.endOffset,\n            });\n            return;\n          }\n          //  selection has range\n          let extract = this.range.extractContents();\n          let span = document.createElement(\"span\");\n\n          while (extract.childNodes[0]) span.append(extract.childNodes[0]);\n\n          this._nodeCrawler(\n            (n) => {\n              let res = restrictedClass\n                ? this._classNameToQuery(restrictedClass)\n                : null;\n              let par = n.nodeType === 3 ? n.parentNode : n;\n              let restricted =\n                res && par.hasOwnProperty(\"closest\") ? par.closest(res) : false;\n\n              if (n.nodeType === 3 && !restricted)\n                n.textContent = n.textContent.replaceAll(\"\\t\", \"\");\n\n              return n;\n            },\n            { node: span, startFromEldestChild: true, parentNode: this.element }\n          );\n\n          while (span.childNodes[0]) extract.append(span.childNodes[0]);\n\n          //  unwrap duplicates and stopper | counter\n          let unwrapTarget = [query];\n\n          //  add countering | opposite tag to unwrap\n          if (stopperMode) {\n            let rev = query.replace(\"_stop\", \"\").substring(1);\n            rev = rev[0] === \"_\" ? \".\" + rev : rev;\n            unwrapTarget.push(rev);\n          } else {\n            let rev = query + \"_stop\";\n            rev = rev[0] === \".\" ? rev : \".\" + rev;\n            unwrapTarget.push(rev);\n          }\n\n          unwrapTarget = unwrapTarget.concat(counter);\n          let del = extract.querySelectorAll(unwrapTarget.join());\n          let idx = del.length;\n          if (idx) while (idx--) this._wrapNode(del[idx]);\n\n          //  split wrapper\n          let wrapperSplit = [wrapper.cloneNode(true)];\n\n          while (extract.childNodes[0]) {\n            let child = extract.childNodes[0];\n\n            if (child.nodeType === 1 && this._isBlockElement(child)) {\n              let nest = this._isTextAreaElement(child);\n\n              if (nest) {\n                for (let idx = 0; child.childNodes.length > idx; idx++) {\n                  let text = child.childNodes[idx];\n\n                  if (this._isTextElement(text)) {\n                    let nestedWrapper = wrapper.cloneNode(true);\n                    while (text.childNodes[0]) {\n                      if (text.childNodes[0].textContent)\n                        nestedWrapper.append(text.childNodes[0]);\n                      else {\n                        // #[MARK]\n                        text.childNodes[0].remove();\n                      }\n                    }\n                    text.append(nestedWrapper);\n                  }\n                }\n\n                if (!child.textContent) {\n                  // #[MARK]\n                  child.remove();\n                  continue;\n                }\n              }\n\n              let doc = document.createDocumentFragment();\n              doc.append(child);\n              wrapperSplit.push(doc);\n            } else {\n              if (child.nodeType === 1 && this._isTextBlockElement(child)) {\n                let nestedWrapper = wrapper.cloneNode(true);\n\n                while (child.childNodes[0])\n                  nestedWrapper.append(child.childNodes[0]);\n\n                if (\n                  nestedWrapper.childNodes.length === 1 &&\n                  nestedWrapper.childNodes[0].nodeName !== \"BR\" &&\n                  !nestedWrapper.textContent.length\n                ) {\n                  child.remove();\n                  continue;\n                }\n\n                child.append(nestedWrapper);\n                let doc = document.createDocumentFragment();\n                doc.append(child);\n                wrapperSplit.push(doc);\n              } else wrapperSplit[wrapperSplit.length - 1].append(child);\n            }\n          }\n\n          let output = document.createDocumentFragment();\n          for (let ws of wrapperSplit) output.append(ws);\n\n          let fc = output.firstChild;\n          let lc = output.lastChild;\n\n          if (this._isTextElement(fc) && !fc.textContent) {\n            let fn = fc.nextSibling;\n            fc.remove();\n            fc = fn;\n          }\n          if (this._isTextElement(lc) && !fc.textContent) {\n            let lp = lc.nextSibling;\n            lc.remove();\n            lc = lp;\n          }\n\n          this.range.insertNode(output);\n          this.range = this._adjustSelection({\n            node: [fc, lc],\n            position: [true, false],\n          });\n\n          //  remove garbage node\n          fc = fc.nodeType === 3 ? fc.parentNode : fc;\n          lc = lc.nodeType === 3 ? lc.parentNode : lc;\n\n          let next = lc.nextSibling;\n          if (\n            this._isTextElement(next) &&\n            (!next.textContent || next.textContent === \"\\u200B\")\n          )\n            next.remove();\n\n          let prev = fc.previousSibling;\n          if (\n            (this._isTextElement(prev) && !prev.textContent) ||\n            prev.textContent === \"\\u200B\"\n          )\n            prev.remove();\n        }\n      }, true);\n\n      return;\n    }\n\n    //  custom component\n    if (typeof action === \"object\") {\n      /**\n        action = {\n          elementId: <string: generated parent element id>,\n          element: <HTMLElement>,\n          style: {<css style object for parent element>},\n          insert: true | false,\n          contenteditable: false,\n        }\n      */\n\n      this._modifySelection(() => {\n        //  setup wrapper\n        // let custom = document.createElement(\"div\");\n        // custom.classList.add(\"_custom_\");\n        // custom.setAttribute(\n        //   \"contenteditable\",\n        //   (!!action?.contenteditable).toString()\n        // );\n\n        // if (action.style)\n        //   for (let s in action.style) custom.style[s] = action.style[s];\n\n        // action.elementId = action.elementId || this._generateId(\"custom\");\n        // custom.id = action.elementId;\n\n        // if (typeof action.element === \"string\")\n        //   custom.innerHTML = action.element;\n        // else if (action.element instanceof HTMLElement)\n        //   custom.append(action.element);\n\n        // if (!custom.children.length) action.insert = true; // insert if only text node\n\n        // if (!this.range) this.element.focus();\n\n        // this.custom_array.push(action);\n\n        // this._callback({ custom: action }).then((_) => {\n        //   if (action.insert) {\n        //     let txt = document.createTextNode(\"\");\n        //     this.range.insertNode(txt); // when inserted in range, it will push the next el back\n        //     this.range.insertNode(custom);\n        //     this.range = this._adjustSelection({\n        //       node: txt,\n        //       position: false,\n        //     });\n        //   } else this._append(custom, this._createEmptyParagraph(), false);\n        // });\n        let custom = null;\n\n        if (action.style)\n          for (let s in action.style) custom.style[s] = action.style[s];\n\n        action.elementId = action.elementId || this._generateId(\"custom\");\n\n        if (typeof action.element === \"string\") {\n          custom = document.createTextNode(action.element);\n          action.insert = true;\n        }\n        else if (action.element instanceof HTMLElement) {\n          custom = action.element;\n          custom.id = action.elementId;\n          custom.classList.add(\"_custom_\");\n        }\n        if (!this.range) this.element.focus();\n\n        this.custom_array.push(action);\n\n        this._callback({ custom: action }).then((_) => {\n\n          let txt = document.createTextNode(\"\");\n          if (action.insert) {\n            this.range.insertNode(txt); // when inserted in range, it will push the next el back\n            this.range.insertNode(custom);\n          } else {\n            this._append(custom, txt, false);\n          }\n          this.range = this._adjustSelection({\n            node: txt,\n            position: false,\n          });\n\n          this.setSafeLine();\n        });\n      });\n    }\n  }\n  setSafeLine() {\n    let firstChild = this.element.firstChild;\n    let lastChild = this.element.lastChild;\n    let txt = document.createElement(\"br\");\n    // let txt = document.createTextNode(\"\\u200B\");\n    this.needSafeGuard.forEach((cl) => {\n      if (cl[0] === \".\") {\n        cl = cl.substring(1);\n        if (firstChild && firstChild.nodeType === 1 && firstChild.classList.contains(cl))\n          this.element.insertBefore(\n            this._createEmptyParagraph(txt),\n            firstChild\n          );\n        if (lastChild && lastChild.nodeType === 1 && lastChild.classList.contains(cl))\n          this.element.appendChild(this._createEmptyParagraph(txt));\n      }\n      else {\n        if (firstChild && firstChild?.tagName === cl)\n          this.element.insertBefore(\n            this._createEmptyParagraph(txt),\n            firstChild\n          );\n        if (lastChild && lastChild?.tagName === cl)\n          this.element.appendChild(this._createEmptyParagraph(txt));\n      }\n    });\n  }\n  /**\n   * Restores the last selection range\n   */\n  restoreLastSelection() {\n    if (this.logExecution)\n      console.log(\"restoreLastSelection\", { range_backup: this.range_backup });\n    if (this.range_backup) {\n      this.range = this._adjustSelection({\n        node: [\n          this.range_backup.startContainer,\n          this.range_backup.endContainer,\n        ],\n        position: [this.range_backup.startOffset, this.range_backup.endOffset],\n      });\n      let sel = window.getSelection();\n      let range = document.createRange();\n      range.setStart(this.range.startContainer, this.range.startOffset);\n      range.setEnd(this.range.endContainer, this.range.endOffset);\n      sel.removeAllRanges();\n      sel.addRange(range);\n    }\n  }\n\n  /**\n   * Load html string to wysiwyg\n   * @param {string} html - HTML string to load.\n   * @param {boolean} [editable=false] - Set editable mode.\n   */\n  async loadHTML(html = this.html, editable = false) {\n    if (typeof html !== \"string\") {\n      throw new Error(\"html should be a string\");\n    }\n\n    this.setEditable(false);\n    this.html = html || \"\";\n    const div = document.createElement(\"div\");\n    div.innerHTML = html;\n\n    // image\n    const img = div.querySelectorAll(\"img\");\n    const imgCallback = [];\n    if (img.length)\n      for (let i of img) {\n        const imageParent = i.closest(\"._media_\");\n\n        if (imageParent) {\n          const source = i.getAttribute(\"src\");\n          let imgId = i.id || this._generateId(\"img\");\n          i.setAttribute(\"id\", imgId);\n\n          imgCallback.push({\n            source,\n            elementId: imgId,\n            element: i,\n          });\n        }\n\n        this.image_array = JSON.parse(JSON.stringify(imgCallback));\n      }\n\n    // hashtag\n    const hashtag = div.querySelectorAll(\"._hashtag_\");\n    const hashtagCallback = [];\n    if (hashtag.length)\n      for (let i of hashtag) {\n        let clIdx = i.classList.length;\n        let tag,\n          elementId = i.id || this._generateId(\"hashtag\");\n        while (clIdx--) {\n          let cls = i.classList[clIdx];\n          if (cls.replace(\"_hashtag_\", \"\")[0] === \"#\") {\n            tag = cls.replace(\"_hashtag_\", \"\");\n          }\n        }\n        tag = tag?.[0] === \"#\" ? tag.substring(1) : tag;\n        if (tag) hashtagCallback.push({ tag, elementId, element: i });\n      }\n\n    // urllink\n    const urllink = div.querySelectorAll(\"._urllink_\");\n    const urllinkCallback = [];\n    if (urllink.length)\n      for (let i of urllink) {\n        let elementId = i.id || this._generateId(\"urllink\");\n        let url;\n\n        let clIdx = i.classList.length;\n        while (clIdx--) {\n          let cls = i.classList[clIdx];\n          if (cls.includes(\"_urllink_\").length) {\n            url = cls.replace(\"_urllink_\", \"\");\n          }\n        }\n        if (url) urllinkCallback.push({ url, elementId, element: i });\n      }\n\n    const custom = div.querySelectorAll(\"._custom_\");\n    const customCallback = [];\n    if (custom.length)\n      for (let i of custom) {\n        let elementId = i.id || this._generateId(\"custom\");\n        customCallback.push({ elementId, element: i });\n      }\n\n    let fb = await this._callback({\n      image: imgCallback,\n      hashtag: hashtagCallback,\n      urllink: urllinkCallback,\n      custom: customCallback,\n    });\n\n    // callback\n    for (let f in fb) {\n      if (f === \"image\") {\n        let img = fb[f];\n        for (let i of img) {\n          let imgEl = div.querySelector(\"#\" + i.elementId);\n          const imageParent = imgEl.closest(\"._media_\");\n          this._loadImage(i, imageParent);\n        }\n      } else this[f + \"_array\"] = fb[f];\n    }\n\n    this.element.innerHTML = \"\";\n\n    while (div.childNodes[0]) this.element.append(div.childNodes[0]);\n\n    if (editable) this.setEditable(true);\n  }\n\n  /**\n   * Load html string to wysiwyg\n   * @param {function} [pre=(p)=>{return p}] - Pre processing callback before export.\n   * @return {object} - Exported wysiwyg data object\n   */\n  async export(pre) {\n    this._normalizeDocument(true);\n    const dom = this.element.cloneNode(true);\n\n    const { hashtag_array, image_array, urllink_array, custom_array } = this;\n    let title = \"\";\n    let text = \"\";\n\n    let setup = {\n      dom,\n      urllink: this.urllink ? urllink_array : undefined,\n      hashtag: this.hashtag ? hashtag_array : undefined,\n      image: image_array,\n      custom: custom_array,\n    };\n\n    if (typeof pre === \"function\") {\n      let promiseOrNot = pre(setup);\n\n      if (promiseOrNot instanceof Promise)\n        setup = (await promiseOrNot) || setup;\n      else setup = promiseOrNot || setup;\n\n      if (this.hashtag) this.hashtag_array = setup.hashtag;\n      if (this.urllink) this.urllink_array = setup.urllink;\n\n      this.image_array = setup.image;\n      this.custom_array = setup.custom;\n      title = setup.title || \"\";\n    }\n\n    const strip = setup.dom.querySelectorAll(\":scope > *\");\n\n    //  Loop through eldest child element in document\n    for (let sid = 0; sid < strip.length; sid++) {\n      let child = strip[sid];\n      if (child.textContent.length) {\n        //  set title and text information\n        let inputText = child.textContent;\n        if (!title) {\n          let titleSearchRegex = /([^\\s^.]{2,}[^\\s]+[.][^\\s^.]{2,})/g;\n          let urlArray = inputText.match(titleSearchRegex);\n\n          // We are replacing the urls with a special text here.\n          // Then we split the sentences by the dots.\n          // Then we replace the url with the special text and identify the title and body text\n\n          let split;\n          if (urlArray) {\n            for (let i = 0; i < urlArray.length; i++) {\n              inputText = inputText.replace(\n                urlArray[i].replace(/\\.+$/, \"\"),\n                \"[§url§]\" + i + \"[/§url§]\"\n              );\n            }\n\n            split = inputText.split(\".\");\n\n            for (let i = 0; i < split.length; i++) {\n              for (let j = 0; j < urlArray.length; j++) {\n                split[i] = split[i].replace(\n                  \"[§url§]\" + j + \"[/§url§]\",\n                  urlArray[j].replace(/\\.+$/, \"\")\n                );\n              }\n            }\n          } else split = inputText.split(\".\");\n\n          title = split[0];\n          if (title.length > 200) {\n            text += title.substring(200) + \".\";\n            title = title.substring(0, 200);\n          }\n\n          split.shift();\n          inputText = split.join(\".\").replace(/\\s\\s+/g, \" \");\n          text += inputText + \" \";\n        } else text += `${inputText}\\n`;\n      }\n\n      if (child.classList.contains(\"_media_\")) {\n        let idx = child.childNodes.length;\n        while (idx--) {\n          let c = child.childNodes[idx];\n          if (c.nodeName === \"IMG\") {\n            for (const f of this.image_array) {\n              if (f.elementId === c.id && f.source !== c.getAttribute(\"src\")) {\n                c.setAttribute(\"src\", f.source);\n                let cIdx = c.classList.length;\n                while (cIdx--) {\n                  if (\n                    c.classList[cIdx].includes(\"_img_\") &&\n                    c.classList[cIdx].length > 5\n                  ) {\n                    c.classList.remove(c.classList[cIdx]);\n                    let splitUrl = f.source.split(\"/\");\n                    let splitTail = splitUrl[splitUrl.length - 1];\n                    let splitTail_length = splitTail.length - 64;\n                    const sourceClip = splitUrl[splitUrl.length - 1].substring(\n                      splitTail_length > 0 ? splitTail : 0\n                    );\n                    c.classList.add(\"_img_\" + sourceClip);\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n\n    return {\n      html: setup.dom.innerHTML,\n      title: title.trim(),\n      text: text.trim(),\n      urllink: this.urllink ? this.urllink_array : undefined,\n      hashtag: this.hashtag ? this.hashtag_array : undefined,\n      image: this.image_array,\n      custom: this.custom_array,\n    };\n  }\n\n  /**\n   * Set placeholder string\n   * @param {string} p - Set placeholder string.\n   */\n  setPlaceholder(p) {\n    if (this.logExecution) console.log(\"setPlaceholder\", { p });\n    if (this.element) {\n      if (p && typeof p === \"string\")\n        this.element.setAttribute(\"placeholder\", p);\n      else this.element.removeAttribute(\"placeholder\");\n    }\n  }\n\n  /**\n   * Set spellcheck mode\n   * @param {boolean} bool - Set spellcheck mode.\n   */\n  setSpellcheck(bool) {\n    if (this.logExecution) console.log(\"setSpellcheck\", { bool });\n    if (this.element)\n      this.element.setAttribute(\"spellcheck\", bool ? \"on\" : \"off\");\n  }\n\n  /**\n   * Set edit mode\n   * @param {boolean} bool - Set wysiwyg to editable when true.\n   */\n  setEditable(bool) {\n    if (this.logExecution) console.log(\"setEditable\", { bool });\n    bool = this.element ? bool : false;\n\n    if (this.element)\n      this.element.setAttribute(\"contenteditable\", bool ? \"true\" : \"false\");\n\n    this._setEventListener(bool);\n    this._observeMutation(bool);\n  }\n}\n\nexport { Wysiwyg4All };\n"],"names":["__webpack_require__","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","colorNames","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","goldenrod","gold","gray","green","greenyellow","grey","honeydew","hotpink","indianred","indigo","ivory","khaki","lavenderblush","lavender","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","ColorMangle","constructor","color","fineTuned","this","format","_colorType","type","throwErr","chkType","string","toLowerCase","match","Array","isArray","length","exec","err","_extractDigit","color_arg","rgba","i","push","parseFloat","getAlpha","extract","colorScheme","darkMode","focusOriginal","focusSat","opacity","template","content_isHighLuminance","isHighLuminance","focus","includes","matchLuminance","compDir","analogous","focusHSL","hsla","h","an1HSL","an2HSL","Math","abs","complementary","fixedValue","darkModeAnalogous","analogousNude","k","textColor","assign","contrastRatio","unordered","keys","sort","reduce","target_color","target_ratio","direction","method","target","adj","m","dir","count","adj_set","adjustBrightness","adjustLuminance","legacy","hex","main_lum","_luminance","lum","currDir","lum_pre","deg","spin","v","val","hsl","plus","s","l","a","minus","add","_toString","r","g","b","rgb","map","pow","col","numberOrNot","n","def","color_arg1","color_arg2","lum1","lum2","option","blackOpacity","whiteOpacity","opa","c_min","min","c_max","max","delta","round","toFixed","digit","toString","slice","rgbObject","hexValues","parseInt","opacity_value","c","x","limit","rgbRange","result","adjustSaturation","Wysiwyg4All","console","log","hashtag_regex","hashtag_stopper_regex","urllink_regex","elementId","editable","placeholder","spellcheck","highlightColor","html","callback","fontSize","desktop","tablet","phone","h1","h2","h3","h4","h5","h6","small","lastLineBlank","hashtag","urllink","logMutation","logExecution","fontSizeCssVariable","hold","keyArr","Error","substring","image_array","hashtag_array","urllink_array","custom_array","blockElement_queryArray","specialTextElement_queryArray","restrictedElement_queryArray","textAreaElement_queryArray","textBlockElement_queryArray","ceilingElement_queryArray","unSelectable_queryArray","needSafeGuard","styleAllowedElement_queryArray","alignClass","hashtag_flag","urllink_flag","range_backup","commandTracker","range","isRangeDirectionForward","insertTabPending_tabString","removeSandwichedLine_array","lastKey","element","document","getElementById","innerHTML","cssVariable","style","setProperty","elementComputedStyle","window","getComputedStyle","defaultFontColor","defaultBackgroundColor","classList","contains","setPlaceholder","setSpellcheck","paddingB","paddingBottom","paddingT","paddingTop","borderT","borderTopWidth","borderB","borderBottomWidth","minHeight","command","italic","bold","underline","strike","backgroundColor","fontSizeRatio","tag","ratio","entries","emSize","styleTagOfCommand","counterTagOf","cssPropertyOf","cssPropertyChecker","textDecoration","documentFontSize","nodeFontSize","f_size","compare_size","fontStyle","loadHTML","catch","_adjustSelection","ceilingElement_query","toArray","allowObject","setRange","node","position","sel","getSelection","getRangeAt","createRange","p","Node","setTarget","nodeType","lastChild","firstChild","textLength","_nodeCrawler","textContent","parentNode","getAttribute","text","createTextNode","insertBefore","childNodes","nodeName","previousSibling","setEnd","doCollapse","setStart","startContainer","startOffset","endContainer","endOffset","collapse","removeAllRanges","addRange","startLine","endLine","q","e","closest","_climbUpToEldestParent","_generateId","prefix","charAt","floor","random","Date","getTime","run","startFromEldestChild","startNode","commonAncestorContainer","parentAnchor","id","uniqueId","outputNodes","nodeIsRange","commonContainer","nodes","crawl","endNode","withInRange","cwl","breakOut","nextSibling","removeAttribute","_wrapNode","wrapper","appendWhole","start","end","withinRange","append","child","stripped","removeChild","singleChildParent","_isSingleChildParent","childrenCount","children","sweep","divCount","iHaveText","cb","_getStartEndLine","getInbetween","inBetween","currentLine","some","matches","_classNameToQuery","_isThereContentEditableOverMyHead","flyup","_isSelectionWithinRestrictedRange","restrict","_createEmptyParagraph","createElement","_trackStyle","cls","checker","sp","colSplit","split","trim","_isTextElement","_lastLineBlank","force","lastLine","_setEventListener","listen","removeEventListener","_selectionchange","imgInput","accept","hidden","multiple","setAttribute","addEventListener","_imageSelected","error","_keydown","_modifySelection","collapsed","toUpperCase","shift","shiftKey","preventDefault","_isTextBlockElement","stc","block","ceil","ceil_prev","remove","_replaceText","sweep_array","hasIndent","diveAndRemoveTab","offset","line","container","containerOffset","lineOffset","tab","insertNode","bind","_normalize","_normalizeDocument","cloneRange","_paste","async","doc","_callback","paste","createDocumentFragment","clipboardData","getData","replace","u","DocumentFragment","extractContents","selection","anchorNode","focusNode","compareDocumentPosition","DOCUMENT_POSITION_PRECEDING","anchorOffset","focusOffset","isSelectionReversed","isForward","rangeHeader","unSel","_isUnSelectableElement","selNext","caratPosition","skipTrack","concat","quote","comm","caratEl","getBoundingClientRect","_observeMutation","track","observer","disconnect","MutationObserver","mutation_array","monitor","cloneNode","name","attributeName","added","clones","addedNodes","removed","removedNodes","mutate","mutation","mutationTarget","callbackRemoved","what","arrIdx","splice","childIdx","toBreak","t","_isCeilingElement","idx","getBr","br","isWysiwygChild","isWysiwygEldestChild","ceiling","clo","isMediaElement","isBlockQuoteElement","isCustomElement","isHashtagElement","isUrlLinkElement","_isBlockElement","_isStyleAllowedElement","sa","doContinue","addBr","classSet","counter","toUnwrap","cIdx","set","class_idx","className","observe","attributes","childList","subtree","_setArrow","isAllRangeOnSameLine","caratElement","arrowDirection","metaKey","ctrlKey","rangeSetup","removeZeroSpace","targetContainer","nudged","siblingDirection","isCaratOnMultiLine","el","posTarget","caratViewPortPosition","elPosition","phoneTextSize","height","nudgeRangeToInlineElement","display","_caratElement","nextEl","setDirection","isMultiLine","eldestParentOfCurrentLine","isCurrentLineInsideSubCeiling","siblingSet","reverse","backwardNode","forwardNode","_forwardNode","leap","collectOffset","currentOffset","_append","insertAfter","wrap","focusElement","common","insertRestricted","next","nodeToUnwrap","restricted","chk","notAllowed","fc","data","Promise","files","prepareForCallback","image","readFile","FileReader","load","file","res","onload","f","lastModified","size","source","img","Image","dimension","width","filename","fileSize","fileType","src","readAsDataURL","loading","feedback","restoreLastSelection","media","_loadImage","imageObject","classname","class","cl","tagName","onclick","st","pushArray","process","_getAnchorOffsetFromLine","found","traverse","_getFocusOffsetFromLine","lineByLine","anchorElement","appendChild","doSingleLine","_isFirstOrLastChild","lc","eldestParent","normalize","to_remove","fol","np","replaceAll","forEach","wholeDocument","typeName","setData","regex","anchorText","collected","textNodes","par","handler","hits","nxt","ownerDocument","global","nodeValue","lastIndex","handleResult","apply","results","orig","index","create","rest","createElementNS","namespaceURI","attrs","content","contentEditable","replaceTextNode","matched","textEl","toCallback","collectId","tc","then","dom","url","open","_checkElement","chkArr","exp","attr","gotTheMatch","_isTextAreaElement","_isSpecialTextElement","action","bq","setSafeLine","li","ul","hr","click","collectLines","nextLine","isColor","isBackgroundColor","query","stopperMode","pass","undefined","restrictedClass","span","unwrapTarget","rev","del","querySelectorAll","join","wrapperSplit","nestedWrapper","output","ws","fn","lp","prev","custom","insert","HTMLElement","_","txt","setEditable","div","imgCallback","imgId","JSON","parse","stringify","hashtagCallback","clIdx","urllinkCallback","customCallback","fb","imageParent","querySelector","pre","title","setup","promiseOrNot","strip","sid","inputText","titleSearchRegex","urlArray","j","splitUrl","splitTail","splitTail_length","sourceClip","bool"],"sourceRoot":""}