var roosterjs = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "./packages/roosterjs/lib/index.ts"); /******/ }) /************************************************************************/ /******/ ({ /***/ "./node_modules/color-convert/conversions.js": /*!***************************************************!*\ !*** ./node_modules/color-convert/conversions.js ***! \***************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ var cssKeywords = __webpack_require__(/*! color-name */ "./node_modules/color-name/index.js"); // NOTE: conversions should only return primitive values (i.e. arrays, or // values that give correct `typeof` results). // do not use box values types (i.e. Number(), String(), etc.) var reverseKeywords = {}; for (var key in cssKeywords) { if (cssKeywords.hasOwnProperty(key)) { reverseKeywords[cssKeywords[key]] = key; } } var convert = module.exports = { rgb: {channels: 3, labels: 'rgb'}, hsl: {channels: 3, labels: 'hsl'}, hsv: {channels: 3, labels: 'hsv'}, hwb: {channels: 3, labels: 'hwb'}, cmyk: {channels: 4, labels: 'cmyk'}, xyz: {channels: 3, labels: 'xyz'}, lab: {channels: 3, labels: 'lab'}, lch: {channels: 3, labels: 'lch'}, hex: {channels: 1, labels: ['hex']}, keyword: {channels: 1, labels: ['keyword']}, ansi16: {channels: 1, labels: ['ansi16']}, ansi256: {channels: 1, labels: ['ansi256']}, hcg: {channels: 3, labels: ['h', 'c', 'g']}, apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, gray: {channels: 1, labels: ['gray']} }; // hide .channels and .labels properties for (var model in convert) { if (convert.hasOwnProperty(model)) { if (!('channels' in convert[model])) { throw new Error('missing channels property: ' + model); } if (!('labels' in convert[model])) { throw new Error('missing channel labels property: ' + model); } if (convert[model].labels.length !== convert[model].channels) { throw new Error('channel and label counts mismatch: ' + model); } var channels = convert[model].channels; var labels = convert[model].labels; delete convert[model].channels; delete convert[model].labels; Object.defineProperty(convert[model], 'channels', {value: channels}); Object.defineProperty(convert[model], 'labels', {value: labels}); } } convert.rgb.hsl = function (rgb) { var r = rgb[0] / 255; var g = rgb[1] / 255; var b = rgb[2] / 255; var min = Math.min(r, g, b); var max = Math.max(r, g, b); var delta = max - min; var h; var s; var l; if (max === min) { h = 0; } else if (r === max) { h = (g - b) / delta; } else if (g === max) { h = 2 + (b - r) / delta; } else if (b === max) { h = 4 + (r - g) / delta; } h = Math.min(h * 60, 360); if (h < 0) { h += 360; } l = (min + max) / 2; if (max === min) { s = 0; } else if (l <= 0.5) { s = delta / (max + min); } else { s = delta / (2 - max - min); } return [h, s * 100, l * 100]; }; convert.rgb.hsv = function (rgb) { var rdif; var gdif; var bdif; var h; var s; var r = rgb[0] / 255; var g = rgb[1] / 255; var b = rgb[2] / 255; var v = Math.max(r, g, b); var diff = v - Math.min(r, g, b); var diffc = function (c) { return (v - c) / 6 / diff + 1 / 2; }; if (diff === 0) { h = s = 0; } else { s = diff / v; rdif = diffc(r); gdif = diffc(g); bdif = diffc(b); if (r === v) { h = bdif - gdif; } else if (g === v) { h = (1 / 3) + rdif - bdif; } else if (b === v) { h = (2 / 3) + gdif - rdif; } if (h < 0) { h += 1; } else if (h > 1) { h -= 1; } } return [ h * 360, s * 100, v * 100 ]; }; convert.rgb.hwb = function (rgb) { var r = rgb[0]; var g = rgb[1]; var b = rgb[2]; var h = convert.rgb.hsl(rgb)[0]; var w = 1 / 255 * Math.min(r, Math.min(g, b)); b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); return [h, w * 100, b * 100]; }; convert.rgb.cmyk = function (rgb) { var r = rgb[0] / 255; var g = rgb[1] / 255; var b = rgb[2] / 255; var c; var m; var y; var k; k = Math.min(1 - r, 1 - g, 1 - b); c = (1 - r - k) / (1 - k) || 0; m = (1 - g - k) / (1 - k) || 0; y = (1 - b - k) / (1 - k) || 0; return [c * 100, m * 100, y * 100, k * 100]; }; /** * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance * */ function comparativeDistance(x, y) { return ( Math.pow(x[0] - y[0], 2) + Math.pow(x[1] - y[1], 2) + Math.pow(x[2] - y[2], 2) ); } convert.rgb.keyword = function (rgb) { var reversed = reverseKeywords[rgb]; if (reversed) { return reversed; } var currentClosestDistance = Infinity; var currentClosestKeyword; for (var keyword in cssKeywords) { if (cssKeywords.hasOwnProperty(keyword)) { var value = cssKeywords[keyword]; // Compute comparative distance var distance = comparativeDistance(rgb, value); // Check if its less, if so set as closest if (distance < currentClosestDistance) { currentClosestDistance = distance; currentClosestKeyword = keyword; } } } return currentClosestKeyword; }; convert.keyword.rgb = function (keyword) { return cssKeywords[keyword]; }; convert.rgb.xyz = function (rgb) { var r = rgb[0] / 255; var g = rgb[1] / 255; var b = rgb[2] / 255; // assume sRGB r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); return [x * 100, y * 100, z * 100]; }; convert.rgb.lab = function (rgb) { var xyz = convert.rgb.xyz(rgb); var x = xyz[0]; var y = xyz[1]; var z = xyz[2]; var l; var a; var b; x /= 95.047; y /= 100; z /= 108.883; x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); l = (116 * y) - 16; a = 500 * (x - y); b = 200 * (y - z); return [l, a, b]; }; convert.hsl.rgb = function (hsl) { var h = hsl[0] / 360; var s = hsl[1] / 100; var l = hsl[2] / 100; var t1; var t2; var t3; var rgb; var val; if (s === 0) { val = l * 255; return [val, val, val]; } if (l < 0.5) { t2 = l * (1 + s); } else { t2 = l + s - l * s; } t1 = 2 * l - t2; rgb = [0, 0, 0]; for (var i = 0; i < 3; i++) { t3 = h + 1 / 3 * -(i - 1); if (t3 < 0) { t3++; } if (t3 > 1) { t3--; } if (6 * t3 < 1) { val = t1 + (t2 - t1) * 6 * t3; } else if (2 * t3 < 1) { val = t2; } else if (3 * t3 < 2) { val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; } else { val = t1; } rgb[i] = val * 255; } return rgb; }; convert.hsl.hsv = function (hsl) { var h = hsl[0]; var s = hsl[1] / 100; var l = hsl[2] / 100; var smin = s; var lmin = Math.max(l, 0.01); var sv; var v; l *= 2; s *= (l <= 1) ? l : 2 - l; smin *= lmin <= 1 ? lmin : 2 - lmin; v = (l + s) / 2; sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); return [h, sv * 100, v * 100]; }; convert.hsv.rgb = function (hsv) { var h = hsv[0] / 60; var s = hsv[1] / 100; var v = hsv[2] / 100; var hi = Math.floor(h) % 6; var f = h - Math.floor(h); var p = 255 * v * (1 - s); var q = 255 * v * (1 - (s * f)); var t = 255 * v * (1 - (s * (1 - f))); v *= 255; switch (hi) { case 0: return [v, t, p]; case 1: return [q, v, p]; case 2: return [p, v, t]; case 3: return [p, q, v]; case 4: return [t, p, v]; case 5: return [v, p, q]; } }; convert.hsv.hsl = function (hsv) { var h = hsv[0]; var s = hsv[1] / 100; var v = hsv[2] / 100; var vmin = Math.max(v, 0.01); var lmin; var sl; var l; l = (2 - s) * v; lmin = (2 - s) * vmin; sl = s * vmin; sl /= (lmin <= 1) ? lmin : 2 - lmin; sl = sl || 0; l /= 2; return [h, sl * 100, l * 100]; }; // http://dev.w3.org/csswg/css-color/#hwb-to-rgb convert.hwb.rgb = function (hwb) { var h = hwb[0] / 360; var wh = hwb[1] / 100; var bl = hwb[2] / 100; var ratio = wh + bl; var i; var v; var f; var n; // wh + bl cant be > 1 if (ratio > 1) { wh /= ratio; bl /= ratio; } i = Math.floor(6 * h); v = 1 - bl; f = 6 * h - i; if ((i & 0x01) !== 0) { f = 1 - f; } n = wh + f * (v - wh); // linear interpolation var r; var g; var b; switch (i) { default: case 6: case 0: r = v; g = n; b = wh; break; case 1: r = n; g = v; b = wh; break; case 2: r = wh; g = v; b = n; break; case 3: r = wh; g = n; b = v; break; case 4: r = n; g = wh; b = v; break; case 5: r = v; g = wh; b = n; break; } return [r * 255, g * 255, b * 255]; }; convert.cmyk.rgb = function (cmyk) { var c = cmyk[0] / 100; var m = cmyk[1] / 100; var y = cmyk[2] / 100; var k = cmyk[3] / 100; var r; var g; var b; r = 1 - Math.min(1, c * (1 - k) + k); g = 1 - Math.min(1, m * (1 - k) + k); b = 1 - Math.min(1, y * (1 - k) + k); return [r * 255, g * 255, b * 255]; }; convert.xyz.rgb = function (xyz) { var x = xyz[0] / 100; var y = xyz[1] / 100; var z = xyz[2] / 100; var r; var g; var b; r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); // assume sRGB r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) : r * 12.92; g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) : g * 12.92; b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) : b * 12.92; r = Math.min(Math.max(0, r), 1); g = Math.min(Math.max(0, g), 1); b = Math.min(Math.max(0, b), 1); return [r * 255, g * 255, b * 255]; }; convert.xyz.lab = function (xyz) { var x = xyz[0]; var y = xyz[1]; var z = xyz[2]; var l; var a; var b; x /= 95.047; y /= 100; z /= 108.883; x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); l = (116 * y) - 16; a = 500 * (x - y); b = 200 * (y - z); return [l, a, b]; }; convert.lab.xyz = function (lab) { var l = lab[0]; var a = lab[1]; var b = lab[2]; var x; var y; var z; y = (l + 16) / 116; x = a / 500 + y; z = y - b / 200; var y2 = Math.pow(y, 3); var x2 = Math.pow(x, 3); var z2 = Math.pow(z, 3); y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; x *= 95.047; y *= 100; z *= 108.883; return [x, y, z]; }; convert.lab.lch = function (lab) { var l = lab[0]; var a = lab[1]; var b = lab[2]; var hr; var h; var c; hr = Math.atan2(b, a); h = hr * 360 / 2 / Math.PI; if (h < 0) { h += 360; } c = Math.sqrt(a * a + b * b); return [l, c, h]; }; convert.lch.lab = function (lch) { var l = lch[0]; var c = lch[1]; var h = lch[2]; var a; var b; var hr; hr = h / 360 * 2 * Math.PI; a = c * Math.cos(hr); b = c * Math.sin(hr); return [l, a, b]; }; convert.rgb.ansi16 = function (args) { var r = args[0]; var g = args[1]; var b = args[2]; var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization value = Math.round(value / 50); if (value === 0) { return 30; } var ansi = 30 + ((Math.round(b / 255) << 2) | (Math.round(g / 255) << 1) | Math.round(r / 255)); if (value === 2) { ansi += 60; } return ansi; }; convert.hsv.ansi16 = function (args) { // optimization here; we already know the value and don't need to get // it converted for us. return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); }; convert.rgb.ansi256 = function (args) { var r = args[0]; var g = args[1]; var b = args[2]; // we use the extended greyscale palette here, with the exception of // black and white. normal palette only has 4 greyscale shades. if (r === g && g === b) { if (r < 8) { return 16; } if (r > 248) { return 231; } return Math.round(((r - 8) / 247) * 24) + 232; } var ansi = 16 + (36 * Math.round(r / 255 * 5)) + (6 * Math.round(g / 255 * 5)) + Math.round(b / 255 * 5); return ansi; }; convert.ansi16.rgb = function (args) { var color = args % 10; // handle greyscale if (color === 0 || color === 7) { if (args > 50) { color += 3.5; } color = color / 10.5 * 255; return [color, color, color]; } var mult = (~~(args > 50) + 1) * 0.5; var r = ((color & 1) * mult) * 255; var g = (((color >> 1) & 1) * mult) * 255; var b = (((color >> 2) & 1) * mult) * 255; return [r, g, b]; }; convert.ansi256.rgb = function (args) { // handle greyscale if (args >= 232) { var c = (args - 232) * 10 + 8; return [c, c, c]; } args -= 16; var rem; var r = Math.floor(args / 36) / 5 * 255; var g = Math.floor((rem = args % 36) / 6) / 5 * 255; var b = (rem % 6) / 5 * 255; return [r, g, b]; }; convert.rgb.hex = function (args) { var integer = ((Math.round(args[0]) & 0xFF) << 16) + ((Math.round(args[1]) & 0xFF) << 8) + (Math.round(args[2]) & 0xFF); var string = integer.toString(16).toUpperCase(); return '000000'.substring(string.length) + string; }; convert.hex.rgb = function (args) { var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); if (!match) { return [0, 0, 0]; } var colorString = match[0]; if (match[0].length === 3) { colorString = colorString.split('').map(function (char) { return char + char; }).join(''); } var integer = parseInt(colorString, 16); var r = (integer >> 16) & 0xFF; var g = (integer >> 8) & 0xFF; var b = integer & 0xFF; return [r, g, b]; }; convert.rgb.hcg = function (rgb) { var r = rgb[0] / 255; var g = rgb[1] / 255; var b = rgb[2] / 255; var max = Math.max(Math.max(r, g), b); var min = Math.min(Math.min(r, g), b); var chroma = (max - min); var grayscale; var hue; if (chroma < 1) { grayscale = min / (1 - chroma); } else { grayscale = 0; } if (chroma <= 0) { hue = 0; } else if (max === r) { hue = ((g - b) / chroma) % 6; } else if (max === g) { hue = 2 + (b - r) / chroma; } else { hue = 4 + (r - g) / chroma + 4; } hue /= 6; hue %= 1; return [hue * 360, chroma * 100, grayscale * 100]; }; convert.hsl.hcg = function (hsl) { var s = hsl[1] / 100; var l = hsl[2] / 100; var c = 1; var f = 0; if (l < 0.5) { c = 2.0 * s * l; } else { c = 2.0 * s * (1.0 - l); } if (c < 1.0) { f = (l - 0.5 * c) / (1.0 - c); } return [hsl[0], c * 100, f * 100]; }; convert.hsv.hcg = function (hsv) { var s = hsv[1] / 100; var v = hsv[2] / 100; var c = s * v; var f = 0; if (c < 1.0) { f = (v - c) / (1 - c); } return [hsv[0], c * 100, f * 100]; }; convert.hcg.rgb = function (hcg) { var h = hcg[0] / 360; var c = hcg[1] / 100; var g = hcg[2] / 100; if (c === 0.0) { return [g * 255, g * 255, g * 255]; } var pure = [0, 0, 0]; var hi = (h % 1) * 6; var v = hi % 1; var w = 1 - v; var mg = 0; switch (Math.floor(hi)) { case 0: pure[0] = 1; pure[1] = v; pure[2] = 0; break; case 1: pure[0] = w; pure[1] = 1; pure[2] = 0; break; case 2: pure[0] = 0; pure[1] = 1; pure[2] = v; break; case 3: pure[0] = 0; pure[1] = w; pure[2] = 1; break; case 4: pure[0] = v; pure[1] = 0; pure[2] = 1; break; default: pure[0] = 1; pure[1] = 0; pure[2] = w; } mg = (1.0 - c) * g; return [ (c * pure[0] + mg) * 255, (c * pure[1] + mg) * 255, (c * pure[2] + mg) * 255 ]; }; convert.hcg.hsv = function (hcg) { var c = hcg[1] / 100; var g = hcg[2] / 100; var v = c + g * (1.0 - c); var f = 0; if (v > 0.0) { f = c / v; } return [hcg[0], f * 100, v * 100]; }; convert.hcg.hsl = function (hcg) { var c = hcg[1] / 100; var g = hcg[2] / 100; var l = g * (1.0 - c) + 0.5 * c; var s = 0; if (l > 0.0 && l < 0.5) { s = c / (2 * l); } else if (l >= 0.5 && l < 1.0) { s = c / (2 * (1 - l)); } return [hcg[0], s * 100, l * 100]; }; convert.hcg.hwb = function (hcg) { var c = hcg[1] / 100; var g = hcg[2] / 100; var v = c + g * (1.0 - c); return [hcg[0], (v - c) * 100, (1 - v) * 100]; }; convert.hwb.hcg = function (hwb) { var w = hwb[1] / 100; var b = hwb[2] / 100; var v = 1 - b; var c = v - w; var g = 0; if (c < 1) { g = (v - c) / (1 - c); } return [hwb[0], c * 100, g * 100]; }; convert.apple.rgb = function (apple) { return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; }; convert.rgb.apple = function (rgb) { return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; }; convert.gray.rgb = function (args) { return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; }; convert.gray.hsl = convert.gray.hsv = function (args) { return [0, 0, args[0]]; }; convert.gray.hwb = function (gray) { return [0, 100, gray[0]]; }; convert.gray.cmyk = function (gray) { return [0, 0, 0, gray[0]]; }; convert.gray.lab = function (gray) { return [gray[0], 0, 0]; }; convert.gray.hex = function (gray) { var val = Math.round(gray[0] / 100 * 255) & 0xFF; var integer = (val << 16) + (val << 8) + val; var string = integer.toString(16).toUpperCase(); return '000000'.substring(string.length) + string; }; convert.rgb.gray = function (rgb) { var val = (rgb[0] + rgb[1] + rgb[2]) / 3; return [val / 255 * 100]; }; /***/ }), /***/ "./node_modules/color-convert/index.js": /*!*********************************************!*\ !*** ./node_modules/color-convert/index.js ***! \*********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { var conversions = __webpack_require__(/*! ./conversions */ "./node_modules/color-convert/conversions.js"); var route = __webpack_require__(/*! ./route */ "./node_modules/color-convert/route.js"); var convert = {}; var models = Object.keys(conversions); function wrapRaw(fn) { var wrappedFn = function (args) { if (args === undefined || args === null) { return args; } if (arguments.length > 1) { args = Array.prototype.slice.call(arguments); } return fn(args); }; // preserve .conversion property if there is one if ('conversion' in fn) { wrappedFn.conversion = fn.conversion; } return wrappedFn; } function wrapRounded(fn) { var wrappedFn = function (args) { if (args === undefined || args === null) { return args; } if (arguments.length > 1) { args = Array.prototype.slice.call(arguments); } var result = fn(args); // we're assuming the result is an array here. // see notice in conversions.js; don't use box types // in conversion functions. if (typeof result === 'object') { for (var len = result.length, i = 0; i < len; i++) { result[i] = Math.round(result[i]); } } return result; }; // preserve .conversion property if there is one if ('conversion' in fn) { wrappedFn.conversion = fn.conversion; } return wrappedFn; } models.forEach(function (fromModel) { convert[fromModel] = {}; Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); var routes = route(fromModel); var routeModels = Object.keys(routes); routeModels.forEach(function (toModel) { var fn = routes[toModel]; convert[fromModel][toModel] = wrapRounded(fn); convert[fromModel][toModel].raw = wrapRaw(fn); }); }); module.exports = convert; /***/ }), /***/ "./node_modules/color-convert/route.js": /*!*********************************************!*\ !*** ./node_modules/color-convert/route.js ***! \*********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { var conversions = __webpack_require__(/*! ./conversions */ "./node_modules/color-convert/conversions.js"); /* this function routes a model to all other models. all functions that are routed have a property `.conversion` attached to the returned synthetic function. This property is an array of strings, each with the steps in between the 'from' and 'to' color models (inclusive). conversions that are not possible simply are not included. */ function buildGraph() { var graph = {}; // https://jsperf.com/object-keys-vs-for-in-with-closure/3 var models = Object.keys(conversions); for (var len = models.length, i = 0; i < len; i++) { graph[models[i]] = { // http://jsperf.com/1-vs-infinity // micro-opt, but this is simple. distance: -1, parent: null }; } return graph; } // https://en.wikipedia.org/wiki/Breadth-first_search function deriveBFS(fromModel) { var graph = buildGraph(); var queue = [fromModel]; // unshift -> queue -> pop graph[fromModel].distance = 0; while (queue.length) { var current = queue.pop(); var adjacents = Object.keys(conversions[current]); for (var len = adjacents.length, i = 0; i < len; i++) { var adjacent = adjacents[i]; var node = graph[adjacent]; if (node.distance === -1) { node.distance = graph[current].distance + 1; node.parent = current; queue.unshift(adjacent); } } } return graph; } function link(from, to) { return function (args) { return to(from(args)); }; } function wrapConversion(toModel, graph) { var path = [graph[toModel].parent, toModel]; var fn = conversions[graph[toModel].parent][toModel]; var cur = graph[toModel].parent; while (graph[cur].parent) { path.unshift(graph[cur].parent); fn = link(conversions[graph[cur].parent][cur], fn); cur = graph[cur].parent; } fn.conversion = path; return fn; } module.exports = function (fromModel) { var graph = deriveBFS(fromModel); var conversion = {}; var models = Object.keys(graph); for (var len = models.length, i = 0; i < len; i++) { var toModel = models[i]; var node = graph[toModel]; if (node.parent === null) { // no possible conversion, or this node is the source model. continue; } conversion[toModel] = wrapConversion(toModel, graph); } return conversion; }; /***/ }), /***/ "./node_modules/color-name/index.js": /*!******************************************!*\ !*** ./node_modules/color-name/index.js ***! \******************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; module.exports = { "aliceblue": [240, 248, 255], "antiquewhite": [250, 235, 215], "aqua": [0, 255, 255], "aquamarine": [127, 255, 212], "azure": [240, 255, 255], "beige": [245, 245, 220], "bisque": [255, 228, 196], "black": [0, 0, 0], "blanchedalmond": [255, 235, 205], "blue": [0, 0, 255], "blueviolet": [138, 43, 226], "brown": [165, 42, 42], "burlywood": [222, 184, 135], "cadetblue": [95, 158, 160], "chartreuse": [127, 255, 0], "chocolate": [210, 105, 30], "coral": [255, 127, 80], "cornflowerblue": [100, 149, 237], "cornsilk": [255, 248, 220], "crimson": [220, 20, 60], "cyan": [0, 255, 255], "darkblue": [0, 0, 139], "darkcyan": [0, 139, 139], "darkgoldenrod": [184, 134, 11], "darkgray": [169, 169, 169], "darkgreen": [0, 100, 0], "darkgrey": [169, 169, 169], "darkkhaki": [189, 183, 107], "darkmagenta": [139, 0, 139], "darkolivegreen": [85, 107, 47], "darkorange": [255, 140, 0], "darkorchid": [153, 50, 204], "darkred": [139, 0, 0], "darksalmon": [233, 150, 122], "darkseagreen": [143, 188, 143], "darkslateblue": [72, 61, 139], "darkslategray": [47, 79, 79], "darkslategrey": [47, 79, 79], "darkturquoise": [0, 206, 209], "darkviolet": [148, 0, 211], "deeppink": [255, 20, 147], "deepskyblue": [0, 191, 255], "dimgray": [105, 105, 105], "dimgrey": [105, 105, 105], "dodgerblue": [30, 144, 255], "firebrick": [178, 34, 34], "floralwhite": [255, 250, 240], "forestgreen": [34, 139, 34], "fuchsia": [255, 0, 255], "gainsboro": [220, 220, 220], "ghostwhite": [248, 248, 255], "gold": [255, 215, 0], "goldenrod": [218, 165, 32], "gray": [128, 128, 128], "green": [0, 128, 0], "greenyellow": [173, 255, 47], "grey": [128, 128, 128], "honeydew": [240, 255, 240], "hotpink": [255, 105, 180], "indianred": [205, 92, 92], "indigo": [75, 0, 130], "ivory": [255, 255, 240], "khaki": [240, 230, 140], "lavender": [230, 230, 250], "lavenderblush": [255, 240, 245], "lawngreen": [124, 252, 0], "lemonchiffon": [255, 250, 205], "lightblue": [173, 216, 230], "lightcoral": [240, 128, 128], "lightcyan": [224, 255, 255], "lightgoldenrodyellow": [250, 250, 210], "lightgray": [211, 211, 211], "lightgreen": [144, 238, 144], "lightgrey": [211, 211, 211], "lightpink": [255, 182, 193], "lightsalmon": [255, 160, 122], "lightseagreen": [32, 178, 170], "lightskyblue": [135, 206, 250], "lightslategray": [119, 136, 153], "lightslategrey": [119, 136, 153], "lightsteelblue": [176, 196, 222], "lightyellow": [255, 255, 224], "lime": [0, 255, 0], "limegreen": [50, 205, 50], "linen": [250, 240, 230], "magenta": [255, 0, 255], "maroon": [128, 0, 0], "mediumaquamarine": [102, 205, 170], "mediumblue": [0, 0, 205], "mediumorchid": [186, 85, 211], "mediumpurple": [147, 112, 219], "mediumseagreen": [60, 179, 113], "mediumslateblue": [123, 104, 238], "mediumspringgreen": [0, 250, 154], "mediumturquoise": [72, 209, 204], "mediumvioletred": [199, 21, 133], "midnightblue": [25, 25, 112], "mintcream": [245, 255, 250], "mistyrose": [255, 228, 225], "moccasin": [255, 228, 181], "navajowhite": [255, 222, 173], "navy": [0, 0, 128], "oldlace": [253, 245, 230], "olive": [128, 128, 0], "olivedrab": [107, 142, 35], "orange": [255, 165, 0], "orangered": [255, 69, 0], "orchid": [218, 112, 214], "palegoldenrod": [238, 232, 170], "palegreen": [152, 251, 152], "paleturquoise": [175, 238, 238], "palevioletred": [219, 112, 147], "papayawhip": [255, 239, 213], "peachpuff": [255, 218, 185], "peru": [205, 133, 63], "pink": [255, 192, 203], "plum": [221, 160, 221], "powderblue": [176, 224, 230], "purple": [128, 0, 128], "rebeccapurple": [102, 51, 153], "red": [255, 0, 0], "rosybrown": [188, 143, 143], "royalblue": [65, 105, 225], "saddlebrown": [139, 69, 19], "salmon": [250, 128, 114], "sandybrown": [244, 164, 96], "seagreen": [46, 139, 87], "seashell": [255, 245, 238], "sienna": [160, 82, 45], "silver": [192, 192, 192], "skyblue": [135, 206, 235], "slateblue": [106, 90, 205], "slategray": [112, 128, 144], "slategrey": [112, 128, 144], "snow": [255, 250, 250], "springgreen": [0, 255, 127], "steelblue": [70, 130, 180], "tan": [210, 180, 140], "teal": [0, 128, 128], "thistle": [216, 191, 216], "tomato": [255, 99, 71], "turquoise": [64, 224, 208], "violet": [238, 130, 238], "wheat": [245, 222, 179], "white": [255, 255, 255], "whitesmoke": [245, 245, 245], "yellow": [255, 255, 0], "yellowgreen": [154, 205, 50] }; /***/ }), /***/ "./node_modules/color-string/index.js": /*!********************************************!*\ !*** ./node_modules/color-string/index.js ***! \********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ var colorNames = __webpack_require__(/*! color-name */ "./node_modules/color-name/index.js"); var swizzle = __webpack_require__(/*! simple-swizzle */ "./node_modules/simple-swizzle/index.js"); var reverseNames = {}; // create a list of reverse color names for (var name in colorNames) { if (colorNames.hasOwnProperty(name)) { reverseNames[colorNames[name]] = name; } } var cs = module.exports = { to: {}, get: {} }; cs.get = function (string) { var prefix = string.substring(0, 3).toLowerCase(); var val; var model; switch (prefix) { case 'hsl': val = cs.get.hsl(string); model = 'hsl'; break; case 'hwb': val = cs.get.hwb(string); model = 'hwb'; break; default: val = cs.get.rgb(string); model = 'rgb'; break; } if (!val) { return null; } return {model: model, value: val}; }; cs.get.rgb = function (string) { if (!string) { return null; } var abbr = /^#([a-f0-9]{3,4})$/i; var hex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i; var rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; var per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; var keyword = /(\D+)/; var rgb = [0, 0, 0, 1]; var match; var i; var hexAlpha; if (match = string.match(hex)) { hexAlpha = match[2]; match = match[1]; for (i = 0; i < 3; i++) { // https://jsperf.com/slice-vs-substr-vs-substring-methods-long-string/19 var i2 = i * 2; rgb[i] = parseInt(match.slice(i2, i2 + 2), 16); } if (hexAlpha) { rgb[3] = parseInt(hexAlpha, 16) / 255; } } else if (match = string.match(abbr)) { match = match[1]; hexAlpha = match[3]; for (i = 0; i < 3; i++) { rgb[i] = parseInt(match[i] + match[i], 16); } if (hexAlpha) { rgb[3] = parseInt(hexAlpha + hexAlpha, 16) / 255; } } else if (match = string.match(rgba)) { for (i = 0; i < 3; i++) { rgb[i] = parseInt(match[i + 1], 0); } if (match[4]) { rgb[3] = parseFloat(match[4]); } } else if (match = string.match(per)) { for (i = 0; i < 3; i++) { rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); } if (match[4]) { rgb[3] = parseFloat(match[4]); } } else if (match = string.match(keyword)) { if (match[1] === 'transparent') { return [0, 0, 0, 0]; } rgb = colorNames[match[1]]; if (!rgb) { return null; } rgb[3] = 1; return rgb; } else { return null; } for (i = 0; i < 3; i++) { rgb[i] = clamp(rgb[i], 0, 255); } rgb[3] = clamp(rgb[3], 0, 1); return rgb; }; cs.get.hsl = function (string) { if (!string) { return null; } var hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; var match = string.match(hsl); if (match) { var alpha = parseFloat(match[4]); var h = (parseFloat(match[1]) + 360) % 360; var s = clamp(parseFloat(match[2]), 0, 100); var l = clamp(parseFloat(match[3]), 0, 100); var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); return [h, s, l, a]; } return null; }; cs.get.hwb = function (string) { if (!string) { return null; } var hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/; var match = string.match(hwb); if (match) { var alpha = parseFloat(match[4]); var h = ((parseFloat(match[1]) % 360) + 360) % 360; var w = clamp(parseFloat(match[2]), 0, 100); var b = clamp(parseFloat(match[3]), 0, 100); var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); return [h, w, b, a]; } return null; }; cs.to.hex = function () { var rgba = swizzle(arguments); return ( '#' + hexDouble(rgba[0]) + hexDouble(rgba[1]) + hexDouble(rgba[2]) + (rgba[3] < 1 ? (hexDouble(Math.round(rgba[3] * 255))) : '') ); }; cs.to.rgb = function () { var rgba = swizzle(arguments); return rgba.length < 4 || rgba[3] === 1 ? 'rgb(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ')' : 'rgba(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ', ' + rgba[3] + ')'; }; cs.to.rgb.percent = function () { var rgba = swizzle(arguments); var r = Math.round(rgba[0] / 255 * 100); var g = Math.round(rgba[1] / 255 * 100); var b = Math.round(rgba[2] / 255 * 100); return rgba.length < 4 || rgba[3] === 1 ? 'rgb(' + r + '%, ' + g + '%, ' + b + '%)' : 'rgba(' + r + '%, ' + g + '%, ' + b + '%, ' + rgba[3] + ')'; }; cs.to.hsl = function () { var hsla = swizzle(arguments); return hsla.length < 4 || hsla[3] === 1 ? 'hsl(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%)' : 'hsla(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%, ' + hsla[3] + ')'; }; // hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax // (hwb have alpha optional & 1 is default value) cs.to.hwb = function () { var hwba = swizzle(arguments); var a = ''; if (hwba.length >= 4 && hwba[3] !== 1) { a = ', ' + hwba[3]; } return 'hwb(' + hwba[0] + ', ' + hwba[1] + '%, ' + hwba[2] + '%' + a + ')'; }; cs.to.keyword = function (rgb) { return reverseNames[rgb.slice(0, 3)]; }; // helpers function clamp(num, min, max) { return Math.min(Math.max(min, num), max); } function hexDouble(num) { var str = num.toString(16).toUpperCase(); return (str.length < 2) ? '0' + str : str; } /***/ }), /***/ "./node_modules/color/index.js": /*!*************************************!*\ !*** ./node_modules/color/index.js ***! \*************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var colorString = __webpack_require__(/*! color-string */ "./node_modules/color-string/index.js"); var convert = __webpack_require__(/*! color-convert */ "./node_modules/color-convert/index.js"); var _slice = [].slice; var skippedModels = [ // to be honest, I don't really feel like keyword belongs in color convert, but eh. 'keyword', // gray conflicts with some method names, and has its own method defined. 'gray', // shouldn't really be in color-convert either... 'hex' ]; var hashedModelKeys = {}; Object.keys(convert).forEach(function (model) { hashedModelKeys[_slice.call(convert[model].labels).sort().join('')] = model; }); var limiters = {}; function Color(obj, model) { if (!(this instanceof Color)) { return new Color(obj, model); } if (model && model in skippedModels) { model = null; } if (model && !(model in convert)) { throw new Error('Unknown model: ' + model); } var i; var channels; if (obj == null) { // eslint-disable-line no-eq-null,eqeqeq this.model = 'rgb'; this.color = [0, 0, 0]; this.valpha = 1; } else if (obj instanceof Color) { this.model = obj.model; this.color = obj.color.slice(); this.valpha = obj.valpha; } else if (typeof obj === 'string') { var result = colorString.get(obj); if (result === null) { throw new Error('Unable to parse color from string: ' + obj); } this.model = result.model; channels = convert[this.model].channels; this.color = result.value.slice(0, channels); this.valpha = typeof result.value[channels] === 'number' ? result.value[channels] : 1; } else if (obj.length) { this.model = model || 'rgb'; channels = convert[this.model].channels; var newArr = _slice.call(obj, 0, channels); this.color = zeroArray(newArr, channels); this.valpha = typeof obj[channels] === 'number' ? obj[channels] : 1; } else if (typeof obj === 'number') { // this is always RGB - can be converted later on. obj &= 0xFFFFFF; this.model = 'rgb'; this.color = [ (obj >> 16) & 0xFF, (obj >> 8) & 0xFF, obj & 0xFF ]; this.valpha = 1; } else { this.valpha = 1; var keys = Object.keys(obj); if ('alpha' in obj) { keys.splice(keys.indexOf('alpha'), 1); this.valpha = typeof obj.alpha === 'number' ? obj.alpha : 0; } var hashedKeys = keys.sort().join(''); if (!(hashedKeys in hashedModelKeys)) { throw new Error('Unable to parse color from object: ' + JSON.stringify(obj)); } this.model = hashedModelKeys[hashedKeys]; var labels = convert[this.model].labels; var color = []; for (i = 0; i < labels.length; i++) { color.push(obj[labels[i]]); } this.color = zeroArray(color); } // perform limitations (clamping, etc.) if (limiters[this.model]) { channels = convert[this.model].channels; for (i = 0; i < channels; i++) { var limit = limiters[this.model][i]; if (limit) { this.color[i] = limit(this.color[i]); } } } this.valpha = Math.max(0, Math.min(1, this.valpha)); if (Object.freeze) { Object.freeze(this); } } Color.prototype = { toString: function () { return this.string(); }, toJSON: function () { return this[this.model](); }, string: function (places) { var self = this.model in colorString.to ? this : this.rgb(); self = self.round(typeof places === 'number' ? places : 1); var args = self.valpha === 1 ? self.color : self.color.concat(this.valpha); return colorString.to[self.model](args); }, percentString: function (places) { var self = this.rgb().round(typeof places === 'number' ? places : 1); var args = self.valpha === 1 ? self.color : self.color.concat(this.valpha); return colorString.to.rgb.percent(args); }, array: function () { return this.valpha === 1 ? this.color.slice() : this.color.concat(this.valpha); }, object: function () { var result = {}; var channels = convert[this.model].channels; var labels = convert[this.model].labels; for (var i = 0; i < channels; i++) { result[labels[i]] = this.color[i]; } if (this.valpha !== 1) { result.alpha = this.valpha; } return result; }, unitArray: function () { var rgb = this.rgb().color; rgb[0] /= 255; rgb[1] /= 255; rgb[2] /= 255; if (this.valpha !== 1) { rgb.push(this.valpha); } return rgb; }, unitObject: function () { var rgb = this.rgb().object(); rgb.r /= 255; rgb.g /= 255; rgb.b /= 255; if (this.valpha !== 1) { rgb.alpha = this.valpha; } return rgb; }, round: function (places) { places = Math.max(places || 0, 0); return new Color(this.color.map(roundToPlace(places)).concat(this.valpha), this.model); }, alpha: function (val) { if (arguments.length) { return new Color(this.color.concat(Math.max(0, Math.min(1, val))), this.model); } return this.valpha; }, // rgb red: getset('rgb', 0, maxfn(255)), green: getset('rgb', 1, maxfn(255)), blue: getset('rgb', 2, maxfn(255)), hue: getset(['hsl', 'hsv', 'hsl', 'hwb', 'hcg'], 0, function (val) { return ((val % 360) + 360) % 360; }), // eslint-disable-line brace-style saturationl: getset('hsl', 1, maxfn(100)), lightness: getset('hsl', 2, maxfn(100)), saturationv: getset('hsv', 1, maxfn(100)), value: getset('hsv', 2, maxfn(100)), chroma: getset('hcg', 1, maxfn(100)), gray: getset('hcg', 2, maxfn(100)), white: getset('hwb', 1, maxfn(100)), wblack: getset('hwb', 2, maxfn(100)), cyan: getset('cmyk', 0, maxfn(100)), magenta: getset('cmyk', 1, maxfn(100)), yellow: getset('cmyk', 2, maxfn(100)), black: getset('cmyk', 3, maxfn(100)), x: getset('xyz', 0, maxfn(100)), y: getset('xyz', 1, maxfn(100)), z: getset('xyz', 2, maxfn(100)), l: getset('lab', 0, maxfn(100)), a: getset('lab', 1), b: getset('lab', 2), keyword: function (val) { if (arguments.length) { return new Color(val); } return convert[this.model].keyword(this.color); }, hex: function (val) { if (arguments.length) { return new Color(val); } return colorString.to.hex(this.rgb().round().color); }, rgbNumber: function () { var rgb = this.rgb().color; return ((rgb[0] & 0xFF) << 16) | ((rgb[1] & 0xFF) << 8) | (rgb[2] & 0xFF); }, luminosity: function () { // http://www.w3.org/TR/WCAG20/#relativeluminancedef var rgb = this.rgb().color; var lum = []; for (var i = 0; i < rgb.length; i++) { var chan = rgb[i] / 255; lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); } return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; }, contrast: function (color2) { // http://www.w3.org/TR/WCAG20/#contrast-ratiodef var lum1 = this.luminosity(); var lum2 = color2.luminosity(); if (lum1 > lum2) { return (lum1 + 0.05) / (lum2 + 0.05); } return (lum2 + 0.05) / (lum1 + 0.05); }, level: function (color2) { var contrastRatio = this.contrast(color2); if (contrastRatio >= 7.1) { return 'AAA'; } return (contrastRatio >= 4.5) ? 'AA' : ''; }, isDark: function () { // YIQ equation from http://24ways.org/2010/calculating-color-contrast var rgb = this.rgb().color; var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; return yiq < 128; }, isLight: function () { return !this.isDark(); }, negate: function () { var rgb = this.rgb(); for (var i = 0; i < 3; i++) { rgb.color[i] = 255 - rgb.color[i]; } return rgb; }, lighten: function (ratio) { var hsl = this.hsl(); hsl.color[2] += hsl.color[2] * ratio; return hsl; }, darken: function (ratio) { var hsl = this.hsl(); hsl.color[2] -= hsl.color[2] * ratio; return hsl; }, saturate: function (ratio) { var hsl = this.hsl(); hsl.color[1] += hsl.color[1] * ratio; return hsl; }, desaturate: function (ratio) { var hsl = this.hsl(); hsl.color[1] -= hsl.color[1] * ratio; return hsl; }, whiten: function (ratio) { var hwb = this.hwb(); hwb.color[1] += hwb.color[1] * ratio; return hwb; }, blacken: function (ratio) { var hwb = this.hwb(); hwb.color[2] += hwb.color[2] * ratio; return hwb; }, grayscale: function () { // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale var rgb = this.rgb().color; var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; return Color.rgb(val, val, val); }, fade: function (ratio) { return this.alpha(this.valpha - (this.valpha * ratio)); }, opaquer: function (ratio) { return this.alpha(this.valpha + (this.valpha * ratio)); }, rotate: function (degrees) { var hsl = this.hsl(); var hue = hsl.color[0]; hue = (hue + degrees) % 360; hue = hue < 0 ? 360 + hue : hue; hsl.color[0] = hue; return hsl; }, mix: function (mixinColor, weight) { // ported from sass implementation in C // https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 if (!mixinColor || !mixinColor.rgb) { throw new Error('Argument to "mix" was not a Color instance, but rather an instance of ' + typeof mixinColor); } var color1 = mixinColor.rgb(); var color2 = this.rgb(); var p = weight === undefined ? 0.5 : weight; var w = 2 * p - 1; var a = color1.alpha() - color2.alpha(); var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; var w2 = 1 - w1; return Color.rgb( w1 * color1.red() + w2 * color2.red(), w1 * color1.green() + w2 * color2.green(), w1 * color1.blue() + w2 * color2.blue(), color1.alpha() * p + color2.alpha() * (1 - p)); } }; // model conversion methods and static constructors Object.keys(convert).forEach(function (model) { if (skippedModels.indexOf(model) !== -1) { return; } var channels = convert[model].channels; // conversion methods Color.prototype[model] = function () { if (this.model === model) { return new Color(this); } if (arguments.length) { return new Color(arguments, model); } var newAlpha = typeof arguments[channels] === 'number' ? channels : this.valpha; return new Color(assertArray(convert[this.model][model].raw(this.color)).concat(newAlpha), model); }; // 'static' construction methods Color[model] = function (color) { if (typeof color === 'number') { color = zeroArray(_slice.call(arguments), channels); } return new Color(color, model); }; }); function roundTo(num, places) { return Number(num.toFixed(places)); } function roundToPlace(places) { return function (num) { return roundTo(num, places); }; } function getset(model, channel, modifier) { model = Array.isArray(model) ? model : [model]; model.forEach(function (m) { (limiters[m] || (limiters[m] = []))[channel] = modifier; }); model = model[0]; return function (val) { var result; if (arguments.length) { if (modifier) { val = modifier(val); } result = this[model](); result.color[channel] = val; return result; } result = this[model]().color[channel]; if (modifier) { result = modifier(result); } return result; }; } function maxfn(max) { return function (v) { return Math.max(0, Math.min(max, v)); }; } function assertArray(val) { return Array.isArray(val) ? val : [val]; } function zeroArray(arr, length) { for (var i = 0; i < length; i++) { if (typeof arr[i] !== 'number') { arr[i] = 0; } } return arr; } module.exports = Color; /***/ }), /***/ "./node_modules/is-arrayish/index.js": /*!*******************************************!*\ !*** ./node_modules/is-arrayish/index.js ***! \*******************************************/ /*! no static exports found */ /***/ (function(module, exports) { module.exports = function isArrayish(obj) { if (!obj || typeof obj === 'string') { return false; } return obj instanceof Array || Array.isArray(obj) || (obj.length >= 0 && (obj.splice instanceof Function || (Object.getOwnPropertyDescriptor(obj, (obj.length - 1)) && obj.constructor.name !== 'String'))); }; /***/ }), /***/ "./node_modules/simple-swizzle/index.js": /*!**********************************************!*\ !*** ./node_modules/simple-swizzle/index.js ***! \**********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var isArrayish = __webpack_require__(/*! is-arrayish */ "./node_modules/is-arrayish/index.js"); var concat = Array.prototype.concat; var slice = Array.prototype.slice; var swizzle = module.exports = function swizzle(args) { var results = []; for (var i = 0, len = args.length; i < len; i++) { var arg = args[i]; if (isArrayish(arg)) { // http://jsperf.com/javascript-array-concat-vs-push/98 results = concat.call(results, slice.call(arg)); } else { results.push(arg); } } return results; }; swizzle.wrap = function (fn) { return function () { return fn(swizzle(arguments)); }; }; /***/ }), /***/ "./packages/roosterjs-color-utils/lib/index.ts": /*!*****************************************************!*\ !*** ./packages/roosterjs-color-utils/lib/index.ts ***! \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getDarkColor = void 0; var getDarkColor_1 = __webpack_require__(/*! ./utils/getDarkColor */ "./packages/roosterjs-color-utils/lib/utils/getDarkColor.ts"); Object.defineProperty(exports, "getDarkColor", { enumerable: true, get: function () { return getDarkColor_1.default; } }); /***/ }), /***/ "./packages/roosterjs-color-utils/lib/utils/getDarkColor.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-color-utils/lib/utils/getDarkColor.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Color = __webpack_require__(/*! color */ "./node_modules/color/index.js"); var DefaultBaseLValue = 21.247; // L-value of #333333 /** * Get dark mode color for a given color * @param color The color to calculate from * @param baseLValue The Light value for base dark color in LAB format. @default the Light value for #333333 */ function getDarkColor(color, baseLValue) { if (baseLValue === void 0) { baseLValue = DefaultBaseLValue; } try { var computedColor = Color(color || undefined); var colorLab = computedColor.lab().array(); var newLValue = (100 - colorLab[0]) * ((100 - baseLValue) / 100) + baseLValue; color = Color.lab(newLValue, colorLab[1], colorLab[2]) .rgb() .alpha(computedColor.alpha()) .toString(); } catch (_a) { } return color; } exports.default = getDarkColor; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/changeCapitalization.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/changeCapitalization.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Change the capitalization of text in the selection * @param editor The editor instance * @param capitalization The case option * @param language Optional parameter for language string that should comply to "IETF BCP 47 Tags for * Identifying Languages". For example: 'en' or 'en-US' for English, 'tr' for Turkish. * Default is the host environment’s current locale. */ function changeCapitalization(editor, capitalization, language) { (0, applyInlineStyle_1.default)(editor, function (element) { for (var node = (0, roosterjs_editor_dom_1.getFirstLeafNode)(element); node; node = (0, roosterjs_editor_dom_1.getNextLeafSibling)(element, node)) { if (node.nodeType == 3 /* Text */) { try { node.textContent = getCapitalizedText(node.textContent, language); } catch (_a) { node.textContent = getCapitalizedText(node.textContent, undefined); } } } }, 'changeCapitalization'); function getCapitalizedText(originalText, language) { switch (capitalization) { case "lowercase" /* Lowercase */: return originalText.toLocaleLowerCase(language); case "uppercase" /* Uppercase */: return originalText.toLocaleUpperCase(language); case "capitalize" /* CapitalizeEachWord */: var wordArray = originalText.toLocaleLowerCase(language).split(' '); for (var i = 0; i < wordArray.length; i++) { wordArray[i] = wordArray[i].charAt(0).toLocaleUpperCase(language) + wordArray[i].slice(1); } return wordArray.join(' '); case "sentence" /* Sentence */: // TODO: Add rules on punctuation for internationalization - TASK 104769 var punctuationMarks = '[\\.\\!\\?]'; // Find a match of a word character either: // - At the beginning of a string with or without preceding whitespace, for // example: ' hello world' and 'hello world' strings would both match 'h'. // - Or preceded by a punctuation mark and at least one whitespace, for // example 'yes. hello world' would match 'y' and 'h'. var regex = new RegExp('^\\s*\\w|' + punctuationMarks + '\\s+\\w', 'g'); return originalText.toLocaleLowerCase(language).replace(regex, function (match) { return match.toLocaleUpperCase(language); }); } } } exports.default = changeCapitalization; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/changeFontSize.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/changeFontSize.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getNewFontSize = exports.FONT_SIZES = void 0; var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Default font size sequence, in pt. Suggest editor UI use this sequence as your font size list, * So that when increase/decrease font size, the font size can match the sequence of your font size picker */ exports.FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72]; var MIN_FONT_SIZE = 1; var MAX_FONT_SIZE = 1000; /** * Increase or decrease font size in selection * @param editor The editor instance * @param change Whether increase or decrease font size * @param fontSizes A sorted font size array, in pt. Default value is FONT_SIZES */ function changeFontSize(editor, change, fontSizes) { if (fontSizes === void 0) { fontSizes = exports.FONT_SIZES; } var changeBase = change == 0 /* Increase */ ? 1 : -1; (0, applyInlineStyle_1.default)(editor, function (element) { var pt = parseFloat((0, roosterjs_editor_dom_1.getComputedStyle)(element, 'font-size') || element.style.fontSize); element.style.fontSize = getNewFontSize(pt, changeBase, fontSizes) + 'pt'; var lineHeight = (0, roosterjs_editor_dom_1.getComputedStyle)(element, 'line-height'); if (lineHeight && lineHeight != 'normal') { element.style.lineHeight = 'normal'; } }, 'changeFontSize'); } exports.default = changeFontSize; /** * @internal * Get new font size after increase/decrease. This is exported for test only * @param pt Original font size, in Point * @param changeBase Changed value, 1 means increase, -1 means decrease * @param fontSizes Known font size array */ function getNewFontSize(pt, changeBase, fontSizes) { pt = changeBase == 1 ? Math.floor(pt) : Math.ceil(pt); var last = fontSizes[fontSizes.length - 1]; if (pt <= fontSizes[0]) { pt = Math.max(pt + changeBase, MIN_FONT_SIZE); } else if (pt > last || (pt == last && changeBase == 1)) { pt = pt / 10; pt = changeBase == 1 ? Math.floor(pt) : Math.ceil(pt); pt = Math.min(Math.max((pt + changeBase) * 10, last), MAX_FONT_SIZE); } else if (changeBase == 1) { for (var i = 0; i < fontSizes.length; i++) { if (pt < fontSizes[i]) { pt = fontSizes[i]; break; } } } else { for (var i = fontSizes.length - 1; i >= 0; i--) { if (pt > fontSizes[i]) { pt = fontSizes[i]; break; } } } return pt; } exports.getNewFontSize = getNewFontSize; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/clearBlockFormat.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/clearBlockFormat.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var clearFormat_1 = __webpack_require__(/*! ./clearFormat */ "./packages/roosterjs-editor-api/lib/format/clearFormat.ts"); /** * @deprecated Use clearFormat instead and pass the ClearFormatMode.Block as parameter * @param editor The editor instance */ function clearBlockFormat(editor) { (0, clearFormat_1.default)(editor, 1 /* Block */); } exports.default = clearBlockFormat; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/clearFormat.ts": /*!*****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/clearFormat.ts ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var applyListItemWrap_1 = __webpack_require__(/*! ../utils/applyListItemWrap */ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts"); var blockFormat_1 = __webpack_require__(/*! ../utils/blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts"); var execCommand_1 = __webpack_require__(/*! ../utils/execCommand */ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts"); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var setBackgroundColor_1 = __webpack_require__(/*! ./setBackgroundColor */ "./packages/roosterjs-editor-api/lib/format/setBackgroundColor.ts"); var setFontName_1 = __webpack_require__(/*! ./setFontName */ "./packages/roosterjs-editor-api/lib/format/setFontName.ts"); var setFontSize_1 = __webpack_require__(/*! ./setFontSize */ "./packages/roosterjs-editor-api/lib/format/setFontSize.ts"); var setTextColor_1 = __webpack_require__(/*! ./setTextColor */ "./packages/roosterjs-editor-api/lib/format/setTextColor.ts"); var toggleBold_1 = __webpack_require__(/*! ./toggleBold */ "./packages/roosterjs-editor-api/lib/format/toggleBold.ts"); var toggleItalic_1 = __webpack_require__(/*! ./toggleItalic */ "./packages/roosterjs-editor-api/lib/format/toggleItalic.ts"); var toggleUnderline_1 = __webpack_require__(/*! ./toggleUnderline */ "./packages/roosterjs-editor-api/lib/format/toggleUnderline.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var STYLES_TO_REMOVE = ['font', 'text-decoration', 'color', 'background']; var TAGS_TO_UNWRAP = 'B,I,U,STRONG,EM,SUB,SUP,STRIKE,FONT,CENTER,H1,H2,H3,H4,H5,H6,UL,OL,LI,SPAN,P,BLOCKQUOTE,CODE,S,PRE'.split(','); var ATTRIBUTES_TO_PRESERVE = ['href', 'src', 'cellpadding', 'cellspacing']; var TAGS_TO_STOP_UNWRAP = ['TD', 'TH', 'TR', 'TABLE', 'TBODY', 'THEAD']; /** * @param editor The editor instance * @returns if the current selection is composed of two or more block elements */ function isMultiBlockSelection(editor) { var transverser = editor.getSelectionTraverser(); var blockElement = transverser.currentBlockElement; if (!blockElement) { return false; } var nextBlockElement = transverser.getNextBlockElement(); //At least two blocks are selected return !!nextBlockElement; } function clearNodeFormat(node) { // 1. Recursively clear format of all its child nodes var areBlockElements = (0, roosterjs_editor_dom_1.toArray)(node.childNodes).map(clearNodeFormat); var areAllChildrenBlock = areBlockElements.every(function (b) { return b; }); var returnBlockElement = (0, roosterjs_editor_dom_1.isBlockElement)(node); // 2. Unwrap the tag if necessary var tag = (0, roosterjs_editor_dom_1.getTagOfNode)(node); if (tag) { if (TAGS_TO_UNWRAP.indexOf(tag) >= 0 || (areAllChildrenBlock && !(0, roosterjs_editor_dom_1.isVoidHtmlElement)(node) && TAGS_TO_STOP_UNWRAP.indexOf(tag) < 0)) { if (returnBlockElement && !areAllChildrenBlock) { (0, roosterjs_editor_dom_1.wrap)(node); } (0, roosterjs_editor_dom_1.unwrap)(node); } else { // 3. Otherwise, remove all attributes clearAttribute(node); } } return returnBlockElement; } function clearAttribute(element) { var isTableCell = (0, roosterjs_editor_dom_1.safeInstanceOf)(element, 'HTMLTableCellElement'); var isTable = (0, roosterjs_editor_dom_1.safeInstanceOf)(element, 'HTMLTableElement'); for (var _i = 0, _a = (0, roosterjs_editor_dom_1.toArray)(element.attributes); _i < _a.length; _i++) { var attr = _a[_i]; if (isTableCell && attr.name == 'style') { removeNonBorderStyles(element); } else if (isTable && attr.name == 'style') { removeNotTableDefaultStyles(element); } else if (ATTRIBUTES_TO_PRESERVE.indexOf(attr.name.toLowerCase()) < 0 && attr.name.indexOf('data-') != 0) { element.removeAttribute(attr.name); } } } function updateStyles(element, callbackfn) { var styles = (0, roosterjs_editor_dom_1.getStyles)(element); var result = {}; (0, roosterjs_editor_dom_1.getObjectKeys)(styles).forEach(function (style) { return callbackfn(style, styles, result); }); (0, roosterjs_editor_dom_1.setStyles)(element, styles); return result; } function removeNonBorderStyles(element) { return updateStyles(element, function (name, styles, result) { if (name.indexOf('border') < 0) { result[name] = styles[name]; delete styles[name]; } }); } function removeNotTableDefaultStyles(element) { return updateStyles(element, function (name, styles, result) { if (name != 'border-collapse') { result[name] = styles[name]; delete styles[name]; } }); } /** * Verifies recursively if a node and its parents have any siblings with text content * Ignoring the children of contentDiv and returning true if any node is LI * @returns `true` if this node, and its parents (minus the children of the contentDiv) have no siblings with text content */ function isNodeWholeBlock(node, editor) { var _a; var currentNode = node; var _loop_1 = function () { if (currentNode.nextSibling || currentNode.previousSibling) { if ((0, roosterjs_editor_dom_1.safeInstanceOf)(currentNode, 'HTMLLIElement')) { return { value: true }; } var isOnlySiblingWithContent_1 = true; (_a = currentNode.parentNode) === null || _a === void 0 ? void 0 : _a.childNodes.forEach(function (node) { if (node != currentNode && node.textContent.length) { isOnlySiblingWithContent_1 = false; } }); return { value: isOnlySiblingWithContent_1 }; } currentNode = currentNode.parentNode; }; while (currentNode && editor.contains(currentNode.parentNode)) { var state_1 = _loop_1(); if (typeof state_1 === "object") return state_1.value; } return true; } /** * Clear the format of the selected text or list of blocks * If the current selection is compose of multiple block elements then remove the text and struture format for all the selected blocks * If the current selection is compose of a partial inline element then only the text format is removed from the current selection * @param editor The editor instance */ function clearAutoDetectFormat(editor) { var isMultiBlock = isMultiBlockSelection(editor); if (!isMultiBlock) { var transverser = editor.getSelectionTraverser(); var inlineElement = transverser.currentInlineElement; var isPartial = inlineElement instanceof roosterjs_editor_dom_1.PartialInlineElement || (inlineElement instanceof roosterjs_editor_dom_1.NodeInlineElement && !isNodeWholeBlock(inlineElement.getContainerNode(), editor)); if (isPartial) { clearFormat(editor); return; } } clearBlockFormat(editor); } /** * Clear all formats of selected blocks. * When selection is collapsed, only clear format of current block. * @param editor The editor instance */ function clearBlockFormat(editor) { (0, formatUndoSnapshot_1.default)(editor, function () { (0, blockFormat_1.default)(editor, function (region) { var blocks = (0, roosterjs_editor_dom_1.getSelectedBlockElementsInRegion)(region, undefined /* createBlockIfEmpty */, editor.isFeatureEnabled("DefaultFormatInSpan" /* DefaultFormatInSpan */)); var nodes = (0, roosterjs_editor_dom_1.collapseNodesInRegion)(region, blocks); if (editor.contains(region.rootNode)) { // If there are styles on table cell, wrap all its children and move down all non-border styles. // So that we can preserve styles for unselected blocks as well as border styles for table var nonborderStyles = removeNonBorderStyles(region.rootNode); if ((0, roosterjs_editor_dom_1.getObjectKeys)(nonborderStyles).length > 0) { var wrapper = (0, roosterjs_editor_dom_1.wrap)((0, roosterjs_editor_dom_1.toArray)(region.rootNode.childNodes)); (0, roosterjs_editor_dom_1.setStyles)(wrapper, nonborderStyles); } } while (nodes.length > 0 && (0, roosterjs_editor_dom_1.isNodeInRegion)(region, nodes[0].parentNode)) { nodes = [(0, roosterjs_editor_dom_1.splitBalancedNodeRange)(nodes)]; } nodes.forEach(clearNodeFormat); }); setDefaultFormat(editor); }, 'clearBlockFormat'); } function clearInlineFormat(editor) { editor.focus(); editor.addUndoSnapshot(function () { (0, execCommand_1.default)(editor, "removeFormat" /* RemoveFormat */); editor.queryElements('[class]', 1 /* OnSelection */, function (node) { return node.removeAttribute('class'); }); setDefaultFormat(editor); return 'clearInlineFormat'; }, "Format" /* Format */); } function setDefaultFontWeight(editor, fontWeight) { if (fontWeight === void 0) { fontWeight = '400'; } (0, applyListItemWrap_1.default)(editor, 'font-weight', function (element) { return (element.style.fontWeight = fontWeight); }, 'setDefaultFontWeight'); } function setDefaultFormat(editor) { var defaultFormat = editor.getDefaultFormat(); var isDefaultFormatEmpty = (0, roosterjs_editor_dom_1.getObjectKeys)(defaultFormat).length === 0; editor.queryElements('[style]', 2 /* InSelection */, function (node) { var tag = (0, roosterjs_editor_dom_1.getTagOfNode)(node); if (TAGS_TO_STOP_UNWRAP.indexOf(tag) == -1) { removeStyles(tag, node, isDefaultFormatEmpty); } else { node.childNodes.forEach(function (node) { node.childNodes.forEach(function (cNode) { var tag = (0, roosterjs_editor_dom_1.getTagOfNode)(cNode); if ((0, roosterjs_editor_dom_1.safeInstanceOf)(cNode, 'HTMLElement')) { removeStyles(tag, cNode, isDefaultFormatEmpty); } }); }); } }); if (!isDefaultFormatEmpty) { if (defaultFormat.fontFamily) { (0, setFontName_1.default)(editor, defaultFormat.fontFamily); } if (defaultFormat.fontSize) { (0, setFontSize_1.default)(editor, defaultFormat.fontSize); } if (defaultFormat.textColor) { var setColorIgnoredElements_1 = editor.queryElements('a *, a', 1 /* OnSelection */); var shouldApplyInlineStyle = setColorIgnoredElements_1.length > 0 ? function (element) { return setColorIgnoredElements_1.indexOf(element) == -1; } : null; if (defaultFormat.textColors) { (0, setTextColor_1.default)(editor, defaultFormat.textColors, shouldApplyInlineStyle); } else { (0, setTextColor_1.default)(editor, defaultFormat.textColor, shouldApplyInlineStyle); } } if (defaultFormat.backgroundColor) { if (defaultFormat.backgroundColors) { (0, setBackgroundColor_1.default)(editor, defaultFormat.backgroundColors); } else { (0, setBackgroundColor_1.default)(editor, defaultFormat.backgroundColor); } } if (defaultFormat.bold) { (0, toggleBold_1.default)(editor); } else { setDefaultFontWeight(editor); } if (defaultFormat.italic) { (0, toggleItalic_1.default)(editor); } if (defaultFormat.underline) { (0, toggleUnderline_1.default)(editor); } } } function removeStyles(tag, node, isDefaultFormatEmpty) { if (TAGS_TO_STOP_UNWRAP.indexOf(tag) == -1) { STYLES_TO_REMOVE.forEach(function (style) { return node.style.removeProperty(style); }); // when default format is empty, keep the HTML minimum by removing style attribute if there's no style // (note: because default format is empty, we're not adding style back in) if (isDefaultFormatEmpty && node.getAttribute('style') === '') { node.removeAttribute('style'); } } } /** * Clear the format in current selection, after cleaning, the format will be * changed to default format. The format that get cleaned include B/I/U/font name/ * font size/text color/background color/align left/align right/align center/superscript/subscript * @param editor The editor instance * @param formatType type of format to apply */ function clearFormat(editor, formatType) { if (formatType === void 0) { formatType = 0 /* Inline */; } switch (formatType) { case 0 /* Inline */: clearInlineFormat(editor); break; case 1 /* Block */: clearBlockFormat(editor); break; default: clearAutoDetectFormat(editor); } } exports.default = clearFormat; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/createLink.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/createLink.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); // Regex matching Uri scheme var URI_REGEX = /^[a-zA-Z]+:/i; // Regex matching begin of email address var MAILTO_REGEX = /^[\w.%+-]+@/i; // Regex matching begin of ftp, i.e. ftp.microsoft.com var FTP_REGEX = /^ftp\./i; function applyLinkPrefix(url) { if (!url) { return url; } // Add link prefix per rule: // (a) if the url always starts with a URI scheme, leave it as it is // (b) if the url is an email address, xxx@... add mailto: prefix // (c) if the url starts with ftp., add ftp:// prefix // (d) rest, add http:// prefix var prefix = ''; if (url.search(URI_REGEX) < 0) { if (url.search(MAILTO_REGEX) == 0) { prefix = 'mailto:'; } else if (url.search(FTP_REGEX) == 0) { prefix = 'ftp://'; } else { // fallback to http:// prefix = 'http://'; } } return prefix + url; } /** * Insert a hyperlink at cursor. * When there is a selection, hyperlink will be applied to the selection, * otherwise a hyperlink will be inserted to the cursor position. * @param editor Editor object * @param link Link address, can be http(s), mailto, notes, file, unc, ftp, news, telnet, gopher, wais. * When protocol is not specified, a best matched protocol will be predicted. * @param altText Optional alt text of the link, will be shown when hover on the link * @param displayText Optional display text for the link. * @param target Optional display target for the link ("_blank"|"_self"|"_parent"|"_top"|"{framename}") * If specified, the display text of link will be replaced with this text. * If not specified and there wasn't a link, the link url will be used as display text. */ function createLink(editor, link, altText, displayText, target) { editor.focus(); var url = (checkXss(link) || '').trim(); if (url) { var linkData = (0, roosterjs_editor_dom_1.matchLink)(url); // matchLink can match most links, but not all, i.e. if you pass link a link as "abc", it won't match // we know in that case, users will want to insert a link like http://abc // so we have separate logic in applyLinkPrefix to add link prefix depending on the format of the link // i.e. if the link starts with something like abc@xxx, we will add mailto: prefix // if the link starts with ftp.xxx, we will add ftp:// link. For more, see applyLinkPrefix var normalizedUrl_1 = linkData ? linkData.normalizedUrl : applyLinkPrefix(url); var originalUrl_1 = linkData ? linkData.originalUrl : url; editor.addUndoSnapshot(function () { var selection = editor.getSelectionRangeEx(); var anchor = null; if (selection.type === 0 /* Normal */) { var range = selection.ranges[0]; if (range && range.collapsed) { anchor = getAnchorNodeAtCursor(editor); // If there is already a link, just change its href if (anchor) { anchor.href = normalizedUrl_1; // Change text content if it is specified updateAnchorDisplayText(anchor, displayText); } else { anchor = editor.getDocument().createElement('A'); anchor.textContent = displayText || originalUrl_1; anchor.href = normalizedUrl_1; editor.insertNode(anchor); } } else { // the selection is not collapsed, use browser execCommand editor .getDocument() .execCommand("createLink" /* CreateLink */, false, normalizedUrl_1); var traverser = editor.getSelectionTraverser(); var currentInline = traverser.getNextInlineElement(); // list for removing unwanted lines var deletionInlineList = []; while (currentInline) { deletionInlineList.push(currentInline.getContainerNode()); currentInline = traverser.getNextInlineElement(); } deletionInlineList.forEach(function (node) { return editor.deleteNode(node); }); anchor = getAnchorNodeAtCursor(editor); updateAnchorDisplayText(anchor, displayText); } } else if (selection.type === 2 /* ImageSelection */) { anchor = (0, roosterjs_editor_dom_1.wrap)(selection.image, 'A'); anchor.href = normalizedUrl_1; } if (altText && anchor) { anchor.title = altText; } if (anchor) { updateAnchorTarget(anchor, target); } return anchor; }, "CreateLink" /* CreateLink */); } } exports.default = createLink; function getAnchorNodeAtCursor(editor) { return editor.queryElements('a[href]', 1 /* OnSelection */)[0]; } function updateAnchorDisplayText(anchor, displayText) { if (displayText && anchor.textContent != displayText) { anchor.textContent = displayText; } } function updateAnchorTarget(anchor, target) { if (target) { anchor.target = target; } else if (!target && anchor.getAttribute('target')) { anchor.removeAttribute('target'); } } function checkXss(link) { var sanitizer = new roosterjs_editor_dom_1.HtmlSanitizer(); var a = document.createElement('a'); a.href = link || ''; sanitizer.sanitize(a); // We use getAttribute because some browsers will try to make the href property a valid link. // This has unintended side effects when the link lacks a protocol. return a.getAttribute('href'); } /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/getFormatState.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/getFormatState.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getElementBasedFormatState = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Get element based Format State at cursor * @param editor The editor instance * @param event (Optional) The plugin event, it stores the event cached data for looking up. * In this function the event cache is used to get list state and header level. If not passed, * it will query the node within selection to get the info * @returns An ElementBasedFormatState object */ function getElementBasedFormatState(editor, event) { var listTag = (0, roosterjs_editor_dom_1.getTagOfNode)(editor.getElementAtCursor('OL,UL', null /*startFrom*/, event)); // Check if selection is multiline, spans more than one block var range = editor.getSelectionRange(); var multiline = false; if (range && !range.collapsed) { var startingBlock = editor.getBlockElementAtNode(range.startContainer); var endingBlock = editor.getBlockElementAtNode(range.endContainer); multiline = endingBlock && startingBlock ? !endingBlock.equals(startingBlock) : false; } var headerTag = (0, roosterjs_editor_dom_1.getTagOfNode)(editor.getElementAtCursor('H1,H2,H3,H4,H5,H6', null /*startFrom*/, event)); var table = editor.queryElements('table', 1 /* OnSelection */)[0]; var tableFormat = table ? (0, roosterjs_editor_dom_1.getTableFormatInfo)(table) : undefined; var hasHeader = (table === null || table === void 0 ? void 0 : table.rows[0]) ? (0, roosterjs_editor_dom_1.toArray)(table.rows[0].cells).every(function (cell) { return (0, roosterjs_editor_dom_1.getTagOfNode)(cell) == 'TH'; }) : undefined; return { isBullet: listTag == 'UL', isNumbering: listTag == 'OL', isMultilineSelection: multiline, headerLevel: (headerTag && parseInt(headerTag[1])) || 0, canUnlink: !!editor.queryElements('a[href]', 1 /* OnSelection */)[0], canAddImageAltText: !!editor.queryElements('img', 1 /* OnSelection */)[0], isBlockQuote: !!editor.queryElements('blockquote', 1 /* OnSelection */)[0], isCodeBlock: !!editor.queryElements('pre>code', 1 /* OnSelection */)[0], isInTable: !!table, tableFormat: tableFormat, tableHasHeader: hasHeader, canMergeTableCell: canMergeTableCell(editor), }; } exports.getElementBasedFormatState = getElementBasedFormatState; /** * Get format state at cursor * A format state is a collection of all format related states, e.g., * bold, italic, underline, font name, font size, etc. * @param editor The editor instance * @param event (Optional) The plugin event, it stores the event cached data for looking up. * In this function the event cache is used to get list state and header level. If not passed, * it will query the node within selection to get the info * @returns The format state at cursor */ function getFormatState(editor, event) { return __assign(__assign(__assign(__assign(__assign({}, editor.getPendableFormatState(false /* forceGetStateFromDom */)), getElementBasedFormatState(editor, event)), editor.getStyleBasedFormatState()), editor.getUndoState()), { isDarkMode: editor.isDarkMode(), zoomScale: editor.getZoomScale() }); } exports.default = getFormatState; /** * Checks whether the editor selection range is starting and ending at a table element. * @param editor Editor Instance * @returns */ var canMergeTableCell = function (editor) { var selection = editor.getSelectionRangeEx(); var isATable = selection && selection.type === 1 /* TableSelection */; if (isATable && selection.coordinates) { var _a = selection.coordinates, firstCell = _a.firstCell, lastCell = _a.lastCell; if (firstCell.x !== lastCell.x || firstCell.y !== lastCell.y) { return true; } return false; } return false; }; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/insertEntity.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/insertEntity.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var commitListChains_1 = __webpack_require__(/*! ../utils/commitListChains */ "./packages/roosterjs-editor-api/lib/utils/commitListChains.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Insert an entity into editor. * @param editor The editor to insert entity into. * @param type Type of the entity * @param contentNode Root element of the entity * @param isBlock Whether the entity will be shown as a block * @param isReadonly Whether the entity will be a readonly entity * @param position @optional The position to insert into. If not specified, current position will be used. * If isBlock is true, entity will be insert below this position * @param insertToRegionRoot @optional When pass true, insert the entity at the root level of current region. * Parent nodes will be split if need */ function insertEntity(editor, type, contentNode, isBlock, isReadonly, position, insertToRegionRoot) { var wrapper = (0, roosterjs_editor_dom_1.wrap)(contentNode, isBlock ? 'DIV' : 'SPAN'); // For inline & readonly entity, we need to set display to "inline-block" otherwise // there will be some weird behavior when move cursor around the entity node. // And we should only do this for readonly entity since "inline-block" has some side effect // in IE that there will be a resize border around the inline-block element. We made some // workaround for readonly entity for this issue but for editable entity, keep it as "inline" // will just work fine. if (!isBlock && isReadonly) { wrapper.style.display = 'inline-block'; } (0, roosterjs_editor_dom_1.commitEntity)(wrapper, type, isReadonly); if (!editor.contains(wrapper)) { var currentRange = void 0; var contentPosition = void 0; if (typeof position == 'number') { contentPosition = position; } else if (position) { currentRange = editor.getSelectionRange(); var node = position.normalize().node; var existingEntity = node && editor.getElementAtCursor((0, roosterjs_editor_dom_1.getEntitySelector)(), node); // Do not insert entity into another entity if (existingEntity) { position = new roosterjs_editor_dom_1.Position(existingEntity, -3 /* After */); } editor.select(position); contentPosition = 3 /* SelectionStart */; } else { editor.focus(); contentPosition = 3 /* SelectionStart */; } var regions = insertToRegionRoot && editor.getSelectedRegions(); var chains = regions && roosterjs_editor_dom_1.VListChain.createListChains(regions); editor.insertNode(wrapper, { updateCursor: false, insertOnNewLine: isBlock, replaceSelection: true, position: contentPosition, insertToRegionRoot: insertToRegionRoot, }); if (chains) { (0, commitListChains_1.default)(editor, chains); } if (contentPosition == 3 /* SelectionStart */) { if (currentRange) { editor.select(currentRange); } else if (!isBlock) { editor.select(wrapper, -3 /* After */); } } } if (isBlock) { // Insert an extra empty line for block entity to make sure // user can still put cursor below the entity. var br = editor.getDocument().createElement('BR'); wrapper.parentNode.insertBefore(br, wrapper.nextSibling); } var entity = (0, roosterjs_editor_dom_1.getEntityFromElement)(wrapper); editor.triggerContentChangedEvent("InsertEntity" /* InsertEntity */, entity); return entity; } exports.default = insertEntity; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/insertImage.ts": /*!*****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/insertImage.ts ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); function insertImage(editor, imageFile, attributes) { if (typeof imageFile == 'string') { insertImageWithSrc(editor, imageFile, attributes); } else { (0, roosterjs_editor_dom_1.readFile)(imageFile, function (dataUrl) { if (dataUrl && !editor.isDisposed()) { insertImageWithSrc(editor, dataUrl, attributes); } }); } } exports.default = insertImage; function insertImageWithSrc(editor, src, attributes) { (0, formatUndoSnapshot_1.default)(editor, function () { var image = editor.getDocument().createElement('img'); image.src = src; if (attributes) { (0, roosterjs_editor_dom_1.getObjectKeys)(attributes).forEach(function (attribute) { return image.setAttribute(attribute, attributes[attribute]); }); } image.style.maxWidth = '100%'; editor.insertNode(image); }, 'insertImage'); } /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/removeLink.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/removeLink.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Remove link at selection. If no links at selection, do nothing. * If selection contains multiple links, all of the link styles will be removed. * If only part of a link is selected, the whole link style will be removed. * @param editor The editor instance */ function removeLink(editor) { editor.focus(); (0, formatUndoSnapshot_1.default)(editor, function (start, end) { editor.queryElements('a[href]', 1 /* OnSelection */, roosterjs_editor_dom_1.unwrap); editor.select(start, end); }, 'removeLink'); } exports.default = removeLink; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/replaceWithNode.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/replaceWithNode.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function replaceWithNode(editor, textOrRange, node, exactMatch, searcher) { // Make sure the text and node is valid if (!textOrRange || !node) { return false; } var range; if (typeof textOrRange == 'string') { searcher = searcher || editor.getContentSearcherOfCursor(); range = searcher && searcher.getRangeFromText(textOrRange, exactMatch); } else { range = textOrRange; } if (range) { var backupRange = editor.getSelectionRange(); // If the range to replace is right before current cursor, it is actually an exact match if (backupRange.collapsed && range.endContainer == backupRange.startContainer && range.endOffset == backupRange.startOffset) { exactMatch = true; } editor.insertNode(node, { position: 5 /* Range */, updateCursor: exactMatch, replaceSelection: true, insertOnNewLine: false, range: range, }); return true; } return false; } exports.default = replaceWithNode; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/rotateElement.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/rotateElement.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); /** * Rotate an element visually * @param editor The editor instance * @param element The element that should be rotated * @param angle The degree at which to rotate the element from it's center */ function rotateElement(editor, element, angle) { if (element) { (0, formatUndoSnapshot_1.default)(editor, function () { element.style.transform = "rotate(" + angle + "deg)"; }, 'rotateElement'); } } exports.default = rotateElement; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/setAlignment.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/setAlignment.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var blockFormat_1 = __webpack_require__(/*! ../utils/blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts"); var execCommand_1 = __webpack_require__(/*! ../utils/execCommand */ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts"); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var normalizeBlockquote_1 = __webpack_require__(/*! ../utils/normalizeBlockquote */ "./packages/roosterjs-editor-api/lib/utils/normalizeBlockquote.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Set content alignment * @param editor The editor instance * @param alignment The alignment option: * Alignment.Center, Alignment.Left, Alignment.Right */ function setAlignment(editor, alignment) { (0, formatUndoSnapshot_1.default)(editor, function () { var selection = editor.getSelectionRangeEx(); var isATable = selection && selection.type === 1 /* TableSelection */; var elementAtCursor = editor.getElementAtCursor(); if (isATable && (0, roosterjs_editor_dom_1.isWholeTableSelected)(new roosterjs_editor_dom_1.VTable(selection.table), selection.coordinates)) { alignTable(selection, alignment); } else if (isList(elementAtCursor) && editor.isFeatureEnabled("ListItemAlignment" /* ListItemAlignment */)) { alignList(editor, alignment); } else { alignText(editor, alignment); } }, 'setAlignment'); } exports.default = setAlignment; /** * Align text using the margins * @param editor * @param element * @param alignment * @param addUndoSnapshot * @returns */ function alignTable(selection, alignment) { var table = selection.table; if (alignment == 1 /* Center */) { table.style.marginLeft = 'auto'; table.style.marginRight = 'auto'; } else if (alignment == 2 /* Right */) { table.style.marginLeft = 'auto'; table.style.marginRight = ''; } else { table.style.marginLeft = ''; table.style.marginRight = 'auto'; } } /** * Align text using the text-align * @param editor * @param alignment * @returns */ function alignText(editor, alignment) { var align = 'left'; var command = "justifyLeft" /* JustifyLeft */; if (alignment == 1 /* Center */) { command = "justifyCenter" /* JustifyCenter */; align = 'center'; } else if (alignment == 2 /* Right */) { command = "justifyRight" /* JustifyRight */; align = 'right'; } (0, execCommand_1.default)(editor, command); var elements = editor.queryElements('[align]', 1 /* OnSelection */, function (node) { node.style.textAlign = align; (0, normalizeBlockquote_1.default)(node); }); if (elements.length == 0) { var node = editor.getElementAtCursor(); (0, normalizeBlockquote_1.default)(node); } } function isList(element) { return (0, roosterjs_editor_dom_1.findClosestElementAncestor)(element, undefined /** root */, 'LI'); } function alignList(editor, alignment) { (0, blockFormat_1.default)(editor, function (region, start, end) { var blocks = (0, roosterjs_editor_dom_1.getSelectedBlockElementsInRegion)(region, undefined /* createBlockIfEmpty */, editor.isFeatureEnabled("DefaultFormatInSpan" /* DefaultFormatInSpan */)); var startNode = blocks[0].getStartNode(); var vList = (0, roosterjs_editor_dom_1.createVListFromRegion)(region, true /*includeSiblingLists*/, startNode); vList.setAlignment(start, end, alignment); }, undefined /* beforeRunCallback */, 'alignList'); } /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/setBackgroundColor.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/setBackgroundColor.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Set background color at current selection * @param editor The editor instance * @param color One of two options: * The color string, can be any of the predefined color names (e.g, 'red') * or hexadecimal color string (e.g, '#FF0000') or rgb value (e.g, 'rgb(255, 0, 0)') supported by browser. * Currently there's no validation to the string, if the passed string is invalid, it won't take effect * Alternatively, you can pass a @typedef ModeIndependentColor. If in light mode, the lightModeColor property will be used. * If in dark mode, the darkModeColor will be used and the lightModeColor will be used when converting back to light mode. **/ function setBackgroundColor(editor, color) { (0, applyInlineStyle_1.default)(editor, function (element, isInnerNode) { (0, roosterjs_editor_dom_1.setColor)(element, isInnerNode ? '' : color, true /*isBackground*/, editor.isDarkMode(), false /*shouldAdaptFontColor*/, editor.getDarkColorHandler()); }, 'setBackgroundColor'); } exports.default = setBackgroundColor; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/setDirection.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/setDirection.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var collapseSelectedBlocks_1 = __webpack_require__(/*! ../utils/collapseSelectedBlocks */ "./packages/roosterjs-editor-api/lib/utils/collapseSelectedBlocks.ts"); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); /** * Change direction for the blocks/paragraph at selection * @param editor The editor instance * @param direction The direction option: * Direction.LeftToRight refers to 'ltr', Direction.RightToLeft refers to 'rtl' */ function setDirection(editor, direction) { editor.focus(); (0, formatUndoSnapshot_1.default)(editor, function (start, end) { (0, collapseSelectedBlocks_1.default)(editor, function (element) { element.setAttribute('dir', direction == 0 /* LeftToRight */ ? 'ltr' : 'rtl'); element.style.textAlign = direction == 0 /* LeftToRight */ ? 'left' : 'right'; }); editor.select(start, end); }, 'setDirection'); } exports.default = setDirection; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/setFontName.ts": /*!*****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/setFontName.ts ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var applyListItemWrap_1 = __webpack_require__(/*! ../utils/applyListItemWrap */ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts"); /** * Set font name at selection * @param editor The editor instance * @param fontName The fontName string, should be a valid CSS font-family style. * Currently there's no validation to the string, if the passed string is invalid, it won't take affect */ function setFontName(editor, fontName) { // The browser provided execCommand creates a HTML tag with face attribute. is not HTML5 standard // (http://www.w3schools.com/tags/tag_font.asp). (0, applyListItemWrap_1.default)(editor, 'font-family', function (element, isInnerNode) { element.style.fontFamily = isInnerNode ? '' : fontName; }, 'setFontName'); } exports.default = setFontName; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/setFontSize.ts": /*!*****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/setFontSize.ts ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var applyListItemWrap_1 = __webpack_require__(/*! ../utils/applyListItemWrap */ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Set font size at selection * @param editor The editor instance * @param fontSize The fontSize string, should be a valid CSS font-size style. * Currently there's no validation to the string, if the passed string is invalid, it won't take affect */ function setFontSize(editor, fontSize) { // The browser provided execCommand only accepts 1-7 point value. In addition, it uses HTML tag with size attribute. // is not HTML5 standard (http://www.w3schools.com/tags/tag_font.asp). (0, applyListItemWrap_1.default)(editor, 'font-size', function (element, isInnerNode) { element.style.fontSize = isInnerNode ? '' : fontSize; var lineHeight = (0, roosterjs_editor_dom_1.getComputedStyle)(element, 'line-height'); if (lineHeight && lineHeight != 'normal') { element.style.lineHeight = 'normal'; } }, 'setFontSize'); } exports.default = setFontSize; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/setImageAltText.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/setImageAltText.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); /** * Set image alt text for all selected images at selection. If no images is contained * in selection, do nothing. * The alt attribute provides alternative information for an image if a user for some reason * cannot view it (because of slow connection, an error in the src attribute, or if the user * uses a screen reader). See https://www.w3schools.com/tags/att_img_alt.asp * @param editor The editor instance * @param altText The image alt text */ function setImageAltText(editor, altText) { editor.focus(); (0, formatUndoSnapshot_1.default)(editor, function () { editor.queryElements('img', 1 /* OnSelection */, function (node) { return node.setAttribute('alt', altText); }); }, 'setImageAltText'); } exports.default = setImageAltText; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/setIndentation.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/setIndentation.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var blockFormat_1 = __webpack_require__(/*! ../utils/blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts"); var normalizeBlockquote_1 = __webpack_require__(/*! ../utils/normalizeBlockquote */ "./packages/roosterjs-editor-api/lib/utils/normalizeBlockquote.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Set indentation at selection * If selection contains bullet/numbering list, increase/decrease indentation will * increase/decrease the list level by one. * @param editor The editor instance * @param indentation The indentation option: * Indentation.Increase to increase indentation or Indentation.Decrease to decrease indentation */ function setIndentation(editor, indentation) { var handler = indentation == 0 /* Increase */ ? indent : outdent; (0, blockFormat_1.default)(editor, function (region, start, end) { var blocks = (0, roosterjs_editor_dom_1.getSelectedBlockElementsInRegion)(region, true /*createBlockIfEmpty*/, editor.isFeatureEnabled("DefaultFormatInSpan" /* DefaultFormatInSpan */)); var blockGroups = [[]]; for (var i = 0; i < blocks.length; i++) { var startNode = blocks[i].getStartNode(); var vList = (0, roosterjs_editor_dom_1.createVListFromRegion)(region, true /*includeSiblingLists*/, startNode); if (vList) { while (blocks[i + 1] && vList.contains(blocks[i + 1].getStartNode())) { i++; } var isTabKeyTextFeaturesEnabled = editor.isFeatureEnabled("TabKeyTextFeatures" /* TabKeyTextFeatures */); if (isTabKeyTextFeaturesEnabled && isFirstItem(vList, startNode) && shouldHandleWithBlockquotes(indentation, editor, startNode)) { var block = editor.getBlockElementAtNode(vList.rootList); blockGroups.push([block]); } else { indentation == 1 /* Decrease */ ? vList.setIndentation(start, end, indentation, false /* softOutdent */, isTabKeyTextFeaturesEnabled /* preventItemRemoval */) : vList.setIndentation(start, end, indentation); vList.writeBack(editor.isFeatureEnabled("ReuseAllAncestorListElements" /* ReuseAllAncestorListElements */)); blockGroups.push([]); } } else { blockGroups[blockGroups.length - 1].push(blocks[i]); } } blockGroups.forEach(function (group) { return handler(region, group); }); }, function () { var selection = editor.getSelectionRangeEx(); if (selection.type == 1 /* TableSelection */ && (0, roosterjs_editor_dom_1.isWholeTableSelected)(new roosterjs_editor_dom_1.VTable(selection.table), selection.coordinates)) { if (indentation == 1 /* Decrease */) { var quote = editor.getElementAtCursor('blockquote', selection.table); (0, roosterjs_editor_dom_1.unwrap)(quote); } else if (indentation == 0 /* Increase */) { (0, roosterjs_editor_dom_1.wrap)(selection.table, 2 /* BlockquoteWrapper */); } return false; } return true; }, 'setIndentation'); function indent(region, blocks) { var nodes = (0, roosterjs_editor_dom_1.collapseNodesInRegion)(region, blocks); (0, roosterjs_editor_dom_1.wrap)(nodes, 2 /* BlockquoteWrapper */); var quotesHandled = []; nodes.forEach(function (node) { return (0, normalizeBlockquote_1.default)(node, quotesHandled); }); } } exports.default = setIndentation; function outdent(region, blocks) { blocks.forEach(function (blockElement) { var node = blockElement.collapseToSingleElement(); var quote = (0, roosterjs_editor_dom_1.findClosestElementAncestor)(node, region.rootNode, 'blockquote'); if (quote) { if (node == quote) { node = (0, roosterjs_editor_dom_1.wrap)((0, roosterjs_editor_dom_1.toArray)(node.childNodes)); } while (node && (0, roosterjs_editor_dom_1.isNodeInRegion)(region, node) && (0, roosterjs_editor_dom_1.getTagOfNode)(node) != 'BLOCKQUOTE') { node = (0, roosterjs_editor_dom_1.splitBalancedNodeRange)(node); } if (node && (0, roosterjs_editor_dom_1.isNodeInRegion)(region, node)) { (0, roosterjs_editor_dom_1.unwrap)(node); } } }); } function isFirstItem(vList, startNode) { var _a; return (((_a = vList.items[0]) === null || _a === void 0 ? void 0 : _a.getNode()) == startNode && vList.getListItemIndex(startNode) == (vList.getStart() || 1)); } function shouldHandleWithBlockquotes(indentation, editor, startNode) { return (indentation == 0 /* Increase */ || editor.getElementAtCursor('blockquote', startNode)); } /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/setOrderedListNumbering.ts": /*!*****************************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/setOrderedListNumbering.ts ***! \*****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Resets Ordered List Numbering back to the value of the parameter startNumber * @param editor The editor instance * @param separator The HTML element that indicates when to split the VList * @param startNumber The number of that the splitted list should start */ function setOrderedListNumbering(editor, separator, startNumber) { if (startNumber === void 0) { startNumber = 1; } (0, formatUndoSnapshot_1.default)(editor, function () { editor.focus(); var regions = editor.getSelectedRegions(); if (regions[0]) { var vList = (0, roosterjs_editor_dom_1.createVListFromRegion)(regions[0], false /*includeSiblingLists*/, separator); if (vList) { vList.split(separator, startNumber); vList.writeBack(editor.isFeatureEnabled("ReuseAllAncestorListElements" /* ReuseAllAncestorListElements */)); } } }, 'setOrderedListNumbering'); } exports.default = setOrderedListNumbering; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/setTextColor.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/setTextColor.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var applyListItemWrap_1 = __webpack_require__(/*! ../utils/applyListItemWrap */ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Set text color at selection * @param editor The editor instance * @param color One of two options: * The color string, can be any of the predefined color names (e.g, 'red') * or hexadecimal color string (e.g, '#FF0000') or rgb value (e.g, 'rgb(255, 0, 0)') supported by browser. * Currently there's no validation to the string, if the passed string is invalid, it won't take affect * Alternatively, you can pass a @typedef ModeIndependentColor. If in light mode, the lightModeColor property will be used. * If in dark mode, the darkModeColor will be used and the lightModeColor will be used when converting back to light mode. * @param shouldApplyInlineStyle Optional callback function to be invoked to verify if the current element should have the inline Style applied */ function setTextColor(editor, color, shouldApplyInlineStyle) { (0, applyListItemWrap_1.default)(editor, 'color', function (element, isInnerNode) { if (!shouldApplyInlineStyle || shouldApplyInlineStyle(element)) { (0, roosterjs_editor_dom_1.setColor)(element, isInnerNode ? '' : color, false /*isBackground*/, editor.isDarkMode(), false /*shouldAdaptFontColor*/, editor.getDarkColorHandler()); } }, 'setTextColor'); } exports.default = setTextColor; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleBlockQuote.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleBlockQuote.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var blockWrap_1 = __webpack_require__(/*! ../utils/blockWrap */ "./packages/roosterjs-editor-api/lib/utils/blockWrap.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var BLOCKQUOTE_TAG = 'blockquote'; var DEFAULT_STYLER = function (element) { element.style.borderLeft = '3px solid'; element.style.borderColor = '#C8C8C8'; element.style.paddingLeft = '10px'; element.style.color = '#666666'; }; /** * Toggle blockquote at selection, if selection already contains any blockquote elements, * the blockquote elements will be unquote and other elements will take no effect * @param editor The editor instance * @param styler (Optional) The custom styler for setting the style for the blockquote element */ function toggleBlockQuote(editor, styler) { (0, blockWrap_1.default)(editor, function (nodes) { var wrapper = (0, roosterjs_editor_dom_1.wrap)(nodes, BLOCKQUOTE_TAG); (styler || DEFAULT_STYLER)(wrapper); }, function () { return editor.queryElements('blockquote', 1 /* OnSelection */, roosterjs_editor_dom_1.unwrap).length == 0; }, 'toggleBlockQuote'); } exports.default = toggleBlockQuote; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleBold.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleBold.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var execCommand_1 = __webpack_require__(/*! ../utils/execCommand */ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts"); /** * Toggle bold at selection * If selection is collapsed, it will only affect the following input after caret * If selection contains only bold text, the bold style will be removed * If selection contains only normal text, bold style will be added to the whole selected text * If selection contains both bold and normal text, bold style will be added to the whole selected text * @param editor The editor instance */ function toggleBold(editor) { (0, execCommand_1.default)(editor, "bold" /* Bold */, 'toggleBold'); } exports.default = toggleBold; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleBullet.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleBullet.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var toggleListType_1 = __webpack_require__(/*! ../utils/toggleListType */ "./packages/roosterjs-editor-api/lib/utils/toggleListType.ts"); /** * Toggle bullet at selection * If selection contains bullet in deep level, toggle bullet will decrease the bullet level by one * If selection contains number list, toggle bullet will convert the number list into bullet list * If selection contains both bullet/numbering and normal text, the behavior is decided by corresponding * browser execCommand API * @param editor The editor instance * @param listStyle (Optional) the style of the bullet list. If not defined, the style will be set to disc. * @param apiNameOverride (Optional) Set a new api name, if empty the api name will be 'toggleListType'. */ function toggleBullet(editor, listStyle, apiNameOverride) { (0, toggleListType_1.default)(editor, 2 /* Unordered */, undefined /* startNumber */, false /* includeSiblingLists */, undefined /** orderedStyle */, listStyle, apiNameOverride); } exports.default = toggleBullet; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleCodeBlock.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleCodeBlock.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var blockWrap_1 = __webpack_require__(/*! ../utils/blockWrap */ "./packages/roosterjs-editor-api/lib/utils/blockWrap.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var PRE_TAG = 'pre'; var CODE_TAG = 'code'; var SELECTOR = PRE_TAG + ">" + CODE_TAG; /** * Toggle code block at selection, if selection already contains any code blocked elements, * the code block elements will be no longer be code blocked and other elements will take no affect * @param editor The editor instance * @param styler (Optional) The custom styler for setting the style for the code block element */ function toggleCodeBlock(editor, styler) { (0, blockWrap_1.default)(editor, function (nodes) { var code = (0, roosterjs_editor_dom_1.wrap)(nodes, CODE_TAG); var pre = (0, roosterjs_editor_dom_1.wrap)(code, PRE_TAG); styler === null || styler === void 0 ? void 0 : styler(pre); }, function () { return editor.queryElements(SELECTOR, 1 /* OnSelection */, function (code) { if (!code.previousSibling && !code.nextSibling) { var parent_1 = code.parentNode; (0, roosterjs_editor_dom_1.unwrap)(code); (0, roosterjs_editor_dom_1.unwrap)(parent_1); } }).length == 0; }, 'toggleCodeBlock'); } exports.default = toggleCodeBlock; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleHeader.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleHeader.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Toggle header at selection * @param editor The editor instance * @param level The header level, can be a number from 0 to 6, in which 1 ~ 6 refers to * the HTML header element <H1> to <H6>, 0 means no header * if passed in param is outside the range, will be rounded to nearest number in the range */ function toggleHeader(editor, level) { level = Math.min(Math.max(Math.round(level), 0), 6); (0, formatUndoSnapshot_1.default)(editor, function () { editor.focus(); var wrapped = false; editor.queryElements('H1,H2,H3,H4,H5,H6', 1 /* OnSelection */, function (header) { if (!wrapped) { editor.getDocument().execCommand("formatBlock" /* FormatBlock */, false, '
'); wrapped = true; } var div = editor.getDocument().createElement('div'); (0, roosterjs_editor_dom_1.moveChildNodes)(div, header); editor.replaceNode(header, div); }); if (level > 0) { var traverser = editor.getSelectionTraverser(); var blockElement = traverser ? traverser.currentBlockElement : null; var sanitizer = new roosterjs_editor_dom_1.HtmlSanitizer({ cssStyleCallbacks: { 'font-size': function () { return false; }, }, }); while (blockElement) { var element = blockElement.collapseToSingleElement(); sanitizer.sanitize(element); blockElement = traverser.getNextBlockElement(); } editor.getDocument().execCommand("formatBlock" /* FormatBlock */, false, ""); } }, 'toggleHeader'); } exports.default = toggleHeader; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleItalic.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleItalic.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var execCommand_1 = __webpack_require__(/*! ../utils/execCommand */ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts"); /** * Toggle italic at selection * If selection is collapsed, it will only affect the input after caret * If selection contains only italic text, the italic style will be removed * If selection contains only normal text, italic style will be added to the whole selected text * If selection contains both italic and normal text, italic style will be added to the whole selected text * @param editor The editor instance */ function toggleItalic(editor) { (0, execCommand_1.default)(editor, "italic" /* Italic */, 'toggleItalic'); } exports.default = toggleItalic; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleNumbering.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleNumbering.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var toggleListType_1 = __webpack_require__(/*! ../utils/toggleListType */ "./packages/roosterjs-editor-api/lib/utils/toggleListType.ts"); /** * Toggle numbering at selection * If selection contains numbering in deep level, toggle numbering will decrease the numbering level by one * If selection contains bullet list, toggle numbering will convert the bullet list into number list * If selection contains both bullet/numbering and normal text, the behavior is decided by corresponding * realization of browser execCommand API * @param editor The editor instance * @param startNumber (Optional) Start number of the list * @param listStyle (Optional) The style of the numbering list. If not defined, the style will be set to decimal. * @param apiNameOverride (Optional) Set a new api name, if empty the api name will be 'toggleListType'. */ function toggleNumbering(editor, startNumber, listStyle, apiNameOverride) { (0, toggleListType_1.default)(editor, 1 /* Ordered */, startNumber, undefined /* includeSiblingLists */, listStyle, undefined /* unorderedStyle */, apiNameOverride); } exports.default = toggleNumbering; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleStrikethrough.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleStrikethrough.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var execCommand_1 = __webpack_require__(/*! ../utils/execCommand */ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts"); /** * Toggle strikethrough at selection * If selection is collapsed, it will only affect the input after caret * If selection contains only strikethrough text, the strikethrough style will be removed * If selection contains only normal text, strikethrough style will be added to the whole selected text * If selection contains both strikethrough and normal text, strikethrough style will be added to the whole selected text * @param editor The editor instance */ function toggleStrikethrough(editor) { (0, execCommand_1.default)(editor, "strikeThrough" /* StrikeThrough */, 'toggleStrikethrough'); } exports.default = toggleStrikethrough; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleSubscript.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleSubscript.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var execCommand_1 = __webpack_require__(/*! ../utils/execCommand */ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts"); /** * Toggle subscript at selection * If selection is collapsed, it will only affect the input after caret * If selection contains only subscript text, the subscript style will be removed * If selection contains only normal text, subscript style will be added to the whole selected text * If selection contains both subscript and normal text, the subscript style will be removed from whole selected text * If selection contains any superscript text, the behavior is determined by corresponding realization of browser * execCommand API * @param editor The editor instance */ function toggleSubscript(editor) { (0, execCommand_1.default)(editor, "subscript" /* Subscript */, 'toggleSubscript'); } exports.default = toggleSubscript; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleSuperscript.ts": /*!***********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleSuperscript.ts ***! \***********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var execCommand_1 = __webpack_require__(/*! ../utils/execCommand */ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts"); /** * Toggle superscript at selection * If selection is collapsed, it will only affect the input after caret * If selection contains only superscript text, the superscript style will be removed * If selection contains only normal text, superscript style will be added to the whole selected text * If selection contains both superscript and normal text, the superscript style will be removed from whole selected text * If selection contains any subscript text, the behavior is determined by corresponding realization of browser * execCommand API * @param editor The editor instance */ function toggleSuperscript(editor) { (0, execCommand_1.default)(editor, "superscript" /* Superscript */, 'toggleSuperscript'); } exports.default = toggleSuperscript; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/format/toggleUnderline.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/format/toggleUnderline.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var execCommand_1 = __webpack_require__(/*! ../utils/execCommand */ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts"); /** * Toggle underline at selection * If selection is collapsed, it will only affect the input after caret * If selection contains only underlined text, the underline style will be removed * If selection contains only normal text, underline style will be added to the whole selected text * If selection contains both underlined and normal text, the underline style will be added to the whole selected text * @param editor The editor instance */ function toggleUnderline(editor) { (0, execCommand_1.default)(editor, "underline" /* Underline */, 'toggleUnderline'); } exports.default = toggleUnderline; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/index.ts": /*!****************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/index.ts ***! \****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.experimentCommitListChains = exports.commitListChains = exports.blockFormat = exports.toggleListType = exports.applyCellShading = exports.toggleHeader = exports.toggleUnderline = exports.toggleSuperscript = exports.toggleSubscript = exports.toggleStrikethrough = exports.toggleCodeBlock = exports.toggleBlockQuote = exports.setOrderedListNumbering = exports.toggleNumbering = exports.toggleItalic = exports.toggleBullet = exports.toggleBold = exports.changeCapitalization = exports.setIndentation = exports.setImageAltText = exports.setFontSize = exports.setFontName = exports.setDirection = exports.setTextColor = exports.setBackgroundColor = exports.setAlignment = exports.rotateElement = exports.replaceWithNode = exports.removeLink = exports.formatTable = exports.editTable = exports.insertTable = exports.insertImage = exports.insertEntity = exports.getElementBasedFormatState = exports.getFormatState = exports.createLink = exports.clearFormat = exports.clearBlockFormat = exports.FONT_SIZES = exports.changeFontSize = void 0; var changeFontSize_1 = __webpack_require__(/*! ./format/changeFontSize */ "./packages/roosterjs-editor-api/lib/format/changeFontSize.ts"); Object.defineProperty(exports, "changeFontSize", { enumerable: true, get: function () { return changeFontSize_1.default; } }); Object.defineProperty(exports, "FONT_SIZES", { enumerable: true, get: function () { return changeFontSize_1.FONT_SIZES; } }); var clearBlockFormat_1 = __webpack_require__(/*! ./format/clearBlockFormat */ "./packages/roosterjs-editor-api/lib/format/clearBlockFormat.ts"); Object.defineProperty(exports, "clearBlockFormat", { enumerable: true, get: function () { return clearBlockFormat_1.default; } }); var clearFormat_1 = __webpack_require__(/*! ./format/clearFormat */ "./packages/roosterjs-editor-api/lib/format/clearFormat.ts"); Object.defineProperty(exports, "clearFormat", { enumerable: true, get: function () { return clearFormat_1.default; } }); var createLink_1 = __webpack_require__(/*! ./format/createLink */ "./packages/roosterjs-editor-api/lib/format/createLink.ts"); Object.defineProperty(exports, "createLink", { enumerable: true, get: function () { return createLink_1.default; } }); var getFormatState_1 = __webpack_require__(/*! ./format/getFormatState */ "./packages/roosterjs-editor-api/lib/format/getFormatState.ts"); Object.defineProperty(exports, "getFormatState", { enumerable: true, get: function () { return getFormatState_1.default; } }); Object.defineProperty(exports, "getElementBasedFormatState", { enumerable: true, get: function () { return getFormatState_1.getElementBasedFormatState; } }); var insertEntity_1 = __webpack_require__(/*! ./format/insertEntity */ "./packages/roosterjs-editor-api/lib/format/insertEntity.ts"); Object.defineProperty(exports, "insertEntity", { enumerable: true, get: function () { return insertEntity_1.default; } }); var insertImage_1 = __webpack_require__(/*! ./format/insertImage */ "./packages/roosterjs-editor-api/lib/format/insertImage.ts"); Object.defineProperty(exports, "insertImage", { enumerable: true, get: function () { return insertImage_1.default; } }); var insertTable_1 = __webpack_require__(/*! ./table/insertTable */ "./packages/roosterjs-editor-api/lib/table/insertTable.ts"); Object.defineProperty(exports, "insertTable", { enumerable: true, get: function () { return insertTable_1.default; } }); var editTable_1 = __webpack_require__(/*! ./table/editTable */ "./packages/roosterjs-editor-api/lib/table/editTable.ts"); Object.defineProperty(exports, "editTable", { enumerable: true, get: function () { return editTable_1.default; } }); var formatTable_1 = __webpack_require__(/*! ./table/formatTable */ "./packages/roosterjs-editor-api/lib/table/formatTable.ts"); Object.defineProperty(exports, "formatTable", { enumerable: true, get: function () { return formatTable_1.default; } }); var removeLink_1 = __webpack_require__(/*! ./format/removeLink */ "./packages/roosterjs-editor-api/lib/format/removeLink.ts"); Object.defineProperty(exports, "removeLink", { enumerable: true, get: function () { return removeLink_1.default; } }); var replaceWithNode_1 = __webpack_require__(/*! ./format/replaceWithNode */ "./packages/roosterjs-editor-api/lib/format/replaceWithNode.ts"); Object.defineProperty(exports, "replaceWithNode", { enumerable: true, get: function () { return replaceWithNode_1.default; } }); var rotateElement_1 = __webpack_require__(/*! ./format/rotateElement */ "./packages/roosterjs-editor-api/lib/format/rotateElement.ts"); Object.defineProperty(exports, "rotateElement", { enumerable: true, get: function () { return rotateElement_1.default; } }); var setAlignment_1 = __webpack_require__(/*! ./format/setAlignment */ "./packages/roosterjs-editor-api/lib/format/setAlignment.ts"); Object.defineProperty(exports, "setAlignment", { enumerable: true, get: function () { return setAlignment_1.default; } }); var setBackgroundColor_1 = __webpack_require__(/*! ./format/setBackgroundColor */ "./packages/roosterjs-editor-api/lib/format/setBackgroundColor.ts"); Object.defineProperty(exports, "setBackgroundColor", { enumerable: true, get: function () { return setBackgroundColor_1.default; } }); var setTextColor_1 = __webpack_require__(/*! ./format/setTextColor */ "./packages/roosterjs-editor-api/lib/format/setTextColor.ts"); Object.defineProperty(exports, "setTextColor", { enumerable: true, get: function () { return setTextColor_1.default; } }); var setDirection_1 = __webpack_require__(/*! ./format/setDirection */ "./packages/roosterjs-editor-api/lib/format/setDirection.ts"); Object.defineProperty(exports, "setDirection", { enumerable: true, get: function () { return setDirection_1.default; } }); var setFontName_1 = __webpack_require__(/*! ./format/setFontName */ "./packages/roosterjs-editor-api/lib/format/setFontName.ts"); Object.defineProperty(exports, "setFontName", { enumerable: true, get: function () { return setFontName_1.default; } }); var setFontSize_1 = __webpack_require__(/*! ./format/setFontSize */ "./packages/roosterjs-editor-api/lib/format/setFontSize.ts"); Object.defineProperty(exports, "setFontSize", { enumerable: true, get: function () { return setFontSize_1.default; } }); var setImageAltText_1 = __webpack_require__(/*! ./format/setImageAltText */ "./packages/roosterjs-editor-api/lib/format/setImageAltText.ts"); Object.defineProperty(exports, "setImageAltText", { enumerable: true, get: function () { return setImageAltText_1.default; } }); var setIndentation_1 = __webpack_require__(/*! ./format/setIndentation */ "./packages/roosterjs-editor-api/lib/format/setIndentation.ts"); Object.defineProperty(exports, "setIndentation", { enumerable: true, get: function () { return setIndentation_1.default; } }); var changeCapitalization_1 = __webpack_require__(/*! ./format/changeCapitalization */ "./packages/roosterjs-editor-api/lib/format/changeCapitalization.ts"); Object.defineProperty(exports, "changeCapitalization", { enumerable: true, get: function () { return changeCapitalization_1.default; } }); var toggleBold_1 = __webpack_require__(/*! ./format/toggleBold */ "./packages/roosterjs-editor-api/lib/format/toggleBold.ts"); Object.defineProperty(exports, "toggleBold", { enumerable: true, get: function () { return toggleBold_1.default; } }); var toggleBullet_1 = __webpack_require__(/*! ./format/toggleBullet */ "./packages/roosterjs-editor-api/lib/format/toggleBullet.ts"); Object.defineProperty(exports, "toggleBullet", { enumerable: true, get: function () { return toggleBullet_1.default; } }); var toggleItalic_1 = __webpack_require__(/*! ./format/toggleItalic */ "./packages/roosterjs-editor-api/lib/format/toggleItalic.ts"); Object.defineProperty(exports, "toggleItalic", { enumerable: true, get: function () { return toggleItalic_1.default; } }); var toggleNumbering_1 = __webpack_require__(/*! ./format/toggleNumbering */ "./packages/roosterjs-editor-api/lib/format/toggleNumbering.ts"); Object.defineProperty(exports, "toggleNumbering", { enumerable: true, get: function () { return toggleNumbering_1.default; } }); var setOrderedListNumbering_1 = __webpack_require__(/*! ./format/setOrderedListNumbering */ "./packages/roosterjs-editor-api/lib/format/setOrderedListNumbering.ts"); Object.defineProperty(exports, "setOrderedListNumbering", { enumerable: true, get: function () { return setOrderedListNumbering_1.default; } }); var toggleBlockQuote_1 = __webpack_require__(/*! ./format/toggleBlockQuote */ "./packages/roosterjs-editor-api/lib/format/toggleBlockQuote.ts"); Object.defineProperty(exports, "toggleBlockQuote", { enumerable: true, get: function () { return toggleBlockQuote_1.default; } }); var toggleCodeBlock_1 = __webpack_require__(/*! ./format/toggleCodeBlock */ "./packages/roosterjs-editor-api/lib/format/toggleCodeBlock.ts"); Object.defineProperty(exports, "toggleCodeBlock", { enumerable: true, get: function () { return toggleCodeBlock_1.default; } }); var toggleStrikethrough_1 = __webpack_require__(/*! ./format/toggleStrikethrough */ "./packages/roosterjs-editor-api/lib/format/toggleStrikethrough.ts"); Object.defineProperty(exports, "toggleStrikethrough", { enumerable: true, get: function () { return toggleStrikethrough_1.default; } }); var toggleSubscript_1 = __webpack_require__(/*! ./format/toggleSubscript */ "./packages/roosterjs-editor-api/lib/format/toggleSubscript.ts"); Object.defineProperty(exports, "toggleSubscript", { enumerable: true, get: function () { return toggleSubscript_1.default; } }); var toggleSuperscript_1 = __webpack_require__(/*! ./format/toggleSuperscript */ "./packages/roosterjs-editor-api/lib/format/toggleSuperscript.ts"); Object.defineProperty(exports, "toggleSuperscript", { enumerable: true, get: function () { return toggleSuperscript_1.default; } }); var toggleUnderline_1 = __webpack_require__(/*! ./format/toggleUnderline */ "./packages/roosterjs-editor-api/lib/format/toggleUnderline.ts"); Object.defineProperty(exports, "toggleUnderline", { enumerable: true, get: function () { return toggleUnderline_1.default; } }); var toggleHeader_1 = __webpack_require__(/*! ./format/toggleHeader */ "./packages/roosterjs-editor-api/lib/format/toggleHeader.ts"); Object.defineProperty(exports, "toggleHeader", { enumerable: true, get: function () { return toggleHeader_1.default; } }); var applyCellShading_1 = __webpack_require__(/*! ./table/applyCellShading */ "./packages/roosterjs-editor-api/lib/table/applyCellShading.ts"); Object.defineProperty(exports, "applyCellShading", { enumerable: true, get: function () { return applyCellShading_1.default; } }); var toggleListType_1 = __webpack_require__(/*! ./utils/toggleListType */ "./packages/roosterjs-editor-api/lib/utils/toggleListType.ts"); Object.defineProperty(exports, "toggleListType", { enumerable: true, get: function () { return toggleListType_1.default; } }); var blockFormat_1 = __webpack_require__(/*! ./utils/blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts"); Object.defineProperty(exports, "blockFormat", { enumerable: true, get: function () { return blockFormat_1.default; } }); var commitListChains_1 = __webpack_require__(/*! ./utils/commitListChains */ "./packages/roosterjs-editor-api/lib/utils/commitListChains.ts"); Object.defineProperty(exports, "commitListChains", { enumerable: true, get: function () { return commitListChains_1.default; } }); Object.defineProperty(exports, "experimentCommitListChains", { enumerable: true, get: function () { return commitListChains_1.experimentCommitListChains; } }); /***/ }), /***/ "./packages/roosterjs-editor-api/lib/table/applyCellShading.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/table/applyCellShading.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Set background color of cells. * @param editor The editor instance * @param color One of two options: **/ function applyCellShading(editor, color) { editor.focus(); (0, formatUndoSnapshot_1.default)(editor, function () { var regions = editor.getSelectedRegions(); regions.forEach(function (region) { if ((0, roosterjs_editor_dom_1.safeInstanceOf)(region.rootNode, 'HTMLTableCellElement')) { (0, roosterjs_editor_dom_1.setColor)(region.rootNode, color, true /* isBackgroundColor */, editor.isDarkMode(), true /** shouldAdaptFontColor */, editor.getDarkColorHandler()); (0, roosterjs_editor_dom_1.saveTableCellMetadata)(region.rootNode, { bgColorOverride: true }); } }); }, 'applyCellShading'); } exports.default = applyCellShading; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/table/editTable.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/table/editTable.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Edit table with given operation. If there is no table at cursor then no op. * @param editor The editor instance * @param operation Table operation */ function editTable(editor, operation) { var td = editor.getElementAtCursor('TD,TH'); if (td) { (0, formatUndoSnapshot_1.default)(editor, function () { var vtable = new roosterjs_editor_dom_1.VTable(td); saveTableSelection(editor, vtable); vtable.edit(operation); vtable.writeBack(); editor.transformToDarkColor(vtable.table); editor.focus(); var cellToSelect = calculateCellToSelect(operation, vtable.row, vtable.col); editor.select(vtable.getCell(cellToSelect.newRow, cellToSelect.newCol).td, 0 /* Begin */); }, 'editTable'); } } exports.default = editTable; function calculateCellToSelect(operation, currentRow, currentCol) { var newRow = currentRow; var newCol = currentCol; switch (operation) { case 0 /* InsertAbove */: newCol = 0; break; case 1 /* InsertBelow */: newRow += 1; newCol = 0; break; case 2 /* InsertLeft */: newRow = 0; break; case 3 /* InsertRight */: newRow = 0; newCol += 1; break; } return { newRow: newRow, newCol: newCol, }; } function saveTableSelection(editor, vtable) { var selection = editor.getSelectionRangeEx(); if (selection && selection.type === 1 /* TableSelection */) { vtable.selection = selection.coordinates; } } /***/ }), /***/ "./packages/roosterjs-editor-api/lib/table/formatTable.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/table/formatTable.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Format table * @param editor The editor which contains the table to format * @param format A TableFormat object contains format information we want to apply to the table * @param table The table to format. This is optional. When not passed, the current table (if any) will be formatted */ function formatTable(editor, format, table) { table = table || editor.getElementAtCursor('TABLE'); if (table) { (0, formatUndoSnapshot_1.default)(editor, function (start, end) { var vtable = new roosterjs_editor_dom_1.VTable(table); vtable.applyFormat(format); vtable.writeBack(); editor.transformToDarkColor(vtable.table); editor.focus(); editor.select(start, end); }, 'formatTable'); } } exports.default = formatTable; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/table/insertTable.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/table/insertTable.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ../utils/formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var setBackgroundColor_1 = __webpack_require__(/*! ../format/setBackgroundColor */ "./packages/roosterjs-editor-api/lib/format/setBackgroundColor.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Insert table into editor at current selection * @param editor The editor instance * @param columns Number of columns in table, it also controls the default table cell width: * if columns <= 4, width = 120px; if columns <= 6, width = 100px; else width = 70px * @param rows Number of rows in table * @param format (Optional) The table format. If not passed, the default format will be applied: * background color: #FFF; border color: #ABABAB */ function insertTable(editor, columns, rows, format) { var document = editor.getDocument(); var table = document.createElement('table'); table.cellSpacing = '0'; table.cellPadding = '1'; for (var i = 0; i < rows; i++) { var tr = document.createElement('tr'); table.appendChild(tr); for (var j = 0; j < columns; j++) { var td = document.createElement('td'); tr.appendChild(td); td.appendChild(document.createElement('br')); td.style.width = getTableCellWidth(columns); } } editor.focus(); (0, formatUndoSnapshot_1.default)(editor, function () { var element = editor.getElementAtCursor(); if (element === null || element === void 0 ? void 0 : element.style.backgroundColor) { (0, setBackgroundColor_1.default)(editor, 'transparent'); } var vtable = new roosterjs_editor_dom_1.VTable(table); vtable.applyFormat(format); vtable.writeBack(); editor.insertNode(table); editor.runAsync(function (editor) { return editor.select(new roosterjs_editor_dom_1.Position(table, 0 /* Begin */).normalize()); }); }, 'insertTable'); } exports.default = insertTable; function getTableCellWidth(columns) { if (columns <= 4) { return '120px'; } else if (columns <= 6) { return '100px'; } else { return '70px'; } } /***/ }), /***/ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ./formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Apply inline style to current selection * @param editor The editor instance * @param callback The callback function to apply style */ function applyInlineStyle(editor, callback, apiName) { editor.focus(); var selection = editor.getSelectionRangeEx(); var safeCallback = function (element, isInnerNode) { return element.isContentEditable && callback(element, isInnerNode); }; if (selection && selection.areAllCollapsed) { var range = selection.ranges[0]; var node = range.startContainer; var isEmptySpan = (0, roosterjs_editor_dom_1.getTagOfNode)(node) == 'SPAN' && (!node.firstChild || ((0, roosterjs_editor_dom_1.getTagOfNode)(node.firstChild) == 'BR' && !node.firstChild.nextSibling)); if (isEmptySpan) { editor.addUndoSnapshot(); safeCallback(node); } else { editor.triggerPluginEvent(13 /* PendingFormatStateChanged */, { formatState: {}, // Here we use callback instead of safeCallback because we know it's contentEditable. // In addition, for elements that are not added to the DOM tree, isContentEditable always returns false on Safari. formatCallback: callback, }); editor.triggerContentChangedEvent("Format" /* Format */); } } else { // This is start and end node that get the style. The start and end needs to be recorded so that selection // can be re-applied post-applying style (0, formatUndoSnapshot_1.default)(editor, function () { var firstNode; var lastNode; selection.ranges.forEach(function (range) { var contentTraverser = editor.getSelectionTraverser(range); var inlineElement = contentTraverser && contentTraverser.currentInlineElement; while (inlineElement) { var nextInlineElement = contentTraverser.getNextInlineElement(); inlineElement.applyStyle(function (element, isInnerNode) { safeCallback(element, isInnerNode); firstNode = firstNode || element; lastNode = element; }); inlineElement = nextInlineElement; } }); if (firstNode && lastNode && selection.type == 0 /* Normal */) { editor.select(firstNode, -2 /* Before */, lastNode, -3 /* After */); } }, apiName); } } exports.default = applyInlineStyle; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Set the List Item Style when all inner inline element have the same style * @param editor The editor instance * @param styleName Name of the style to apply to the list item * @param formatCallback callback to apply the style to each element */ function applyListItemStyleWrap(editor, styleName, formatCallback, apiName) { var parentNodes = []; (0, applyInlineStyle_1.default)(editor, function (element, isInnerNode) { formatCallback(element, isInnerNode); var parent = editor.getElementAtCursor('LI', element); if (parent && parentNodes.indexOf(parent) === -1) { parentNodes.push(parent); } }, apiName); applyStyleToListItems(parentNodes, [styleName]); } exports.default = applyListItemStyleWrap; /** * @internal * Checks if the parent element is a List Item, if it is, apply the style elements to the list item * @param parentNodes parentNodes to apply the style * @param styles styles to apply to the List Item Element */ function applyStyleToListItems(parentNodes, styles) { parentNodes.forEach(function (node) { if ((0, roosterjs_editor_dom_1.safeInstanceOf)(node, 'HTMLLIElement')) { (0, roosterjs_editor_dom_1.setListItemStyle)(node, styles); } }); } /***/ }), /***/ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/utils/blockFormat.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var commitListChains_1 = __webpack_require__(/*! ../utils/commitListChains */ "./packages/roosterjs-editor-api/lib/utils/commitListChains.ts"); var formatUndoSnapshot_1 = __webpack_require__(/*! ./formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Split selection into regions, and perform a block-wise formatting action for each region. */ function blockFormat(editor, callback, beforeRunCallback, apiName) { editor.focus(); var selection = editor.getSelectionRangeEx(); (0, formatUndoSnapshot_1.default)(editor, function (start, end) { if (!beforeRunCallback || beforeRunCallback()) { var regions = editor.getSelectedRegions(); var chains_1 = roosterjs_editor_dom_1.VListChain.createListChains(regions, start === null || start === void 0 ? void 0 : start.node); regions.forEach(function (region) { return callback(region, start, end, chains_1); }); (0, commitListChains_1.default)(editor, chains_1); } if (selection.type == 0 /* Normal */) { editor.select(start, end); } else { editor.select(selection); } }, apiName); } exports.default = blockFormat; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/utils/blockWrap.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/utils/blockWrap.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var blockFormat_1 = __webpack_require__(/*! ./blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Toggle a tag at selection, if selection already contains elements of such tag, * the elements will be untagged and other elements will take no effect * @param editor The editor instance * @param wrapFunction The wrap function * @param beforeRunCallback A callback function to run before looping all regions. If it returns false, * the loop for regions will be skipped */ function blockWrap(editor, wrapFunction, beforeRunCallback, apiName) { (0, blockFormat_1.default)(editor, function (region) { var blocks = (0, roosterjs_editor_dom_1.getSelectedBlockElementsInRegion)(region, true /*createBlockIfEmpty*/, editor.isFeatureEnabled("DefaultFormatInSpan" /* DefaultFormatInSpan */)); var nodes = (0, roosterjs_editor_dom_1.collapseNodesInRegion)(region, blocks); if (nodes.length > 0) { if (nodes.length == 1) { var NodeTag = (0, roosterjs_editor_dom_1.getTagOfNode)(nodes[0]); if (NodeTag == 'BR') { nodes = [(0, roosterjs_editor_dom_1.wrap)(nodes[0])]; } else if (NodeTag == 'LI' || NodeTag == 'TD') { nodes = (0, roosterjs_editor_dom_1.toArray)(nodes[0].childNodes); } } while (nodes[0] && (0, roosterjs_editor_dom_1.isNodeInRegion)(region, nodes[0].parentNode) && nodes.some(function (node) { return (0, roosterjs_editor_dom_1.getTagOfNode)(node) == 'LI'; })) { nodes = [(0, roosterjs_editor_dom_1.splitBalancedNodeRange)(nodes)]; } wrapFunction(nodes); } }, beforeRunCallback, apiName); } exports.default = blockWrap; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/utils/collapseSelectedBlocks.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/utils/collapseSelectedBlocks.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Collapse all selected blocks, return single HTML elements for each block * @param editor The editor instance * @param forEachCallback A callback function to invoke for each of the collapsed element */ function collapseSelectedBlocks(editor, forEachCallback) { var traverser = editor.getSelectionTraverser(); var block = traverser && traverser.currentBlockElement; var blocks = []; while (block) { if (!isEmptyBlockUnderTR(block)) { blocks.push(block); } block = traverser.getNextBlockElement(); } blocks.forEach(function (block) { var element = block.collapseToSingleElement(); forEachCallback(element); }); } exports.default = collapseSelectedBlocks; function isEmptyBlockUnderTR(block) { var startNode = block.getStartNode(); return (startNode == block.getEndNode() && startNode.nodeType == 3 /* Text */ && ['TR', 'TABLE'].indexOf((0, roosterjs_editor_dom_1.getTagOfNode)(startNode.parentNode)) >= 0); } /***/ }), /***/ "./packages/roosterjs-editor-api/lib/utils/commitListChains.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/utils/commitListChains.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.experimentCommitListChains = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Commit changes of all list changes when experiment features are allowed * @param editor The Editor object * @param chains List chains to commit */ function commitListChains(editor, chains) { if ((chains === null || chains === void 0 ? void 0 : chains.length) > 0) { var range = editor.getSelectionRange(); var start = range && roosterjs_editor_dom_1.Position.getStart(range); var end = range && roosterjs_editor_dom_1.Position.getEnd(range); var shouldReuseAllAncestorListElements_1 = editor.isFeatureEnabled("ReuseAllAncestorListElements" /* ReuseAllAncestorListElements */); chains.forEach(function (chain) { return chain.commit(shouldReuseAllAncestorListElements_1); }); editor.select(start, end); } } exports.default = commitListChains; /** * @deprecated * Same with commitListChains, keep this export just for backward compatibility */ exports.experimentCommitListChains = commitListChains; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/utils/execCommand.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var formatUndoSnapshot_1 = __webpack_require__(/*! ./formatUndoSnapshot */ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Execute a document command * @param editor The editor instance * @param command The command to execute * @param addUndoSnapshotWhenCollapsed Optional, set to true to always add undo snapshot even current selection is collapsed. * Default value is false. * @param doWorkaroundForList Optional, set to true to do workaround for list in order to keep current format. * Default value is false. */ function execCommand(editor, command, apiName) { editor.focus(); var formatter = function () { return editor.getDocument().execCommand(command, false, null); }; var selection = editor.getSelectionRangeEx(); if (selection && selection.areAllCollapsed) { editor.addUndoSnapshot(); var formatState = editor.getPendableFormatState(false /* forceGetStateFromDom */); formatter(); var formatName = (0, roosterjs_editor_dom_1.getObjectKeys)(roosterjs_editor_dom_1.PendableFormatCommandMap).filter(function (x) { return roosterjs_editor_dom_1.PendableFormatCommandMap[x] == command; })[0]; if (formatName) { formatState[formatName] = !formatState[formatName]; editor.triggerPluginEvent(13 /* PendingFormatStateChanged */, { formatState: formatState, }); } } else { (0, formatUndoSnapshot_1.default)(editor, function () { var needToSwitchSelection = selection.type != 0 /* Normal */; selection.ranges.forEach(function (range) { if (needToSwitchSelection) { editor.select(range); } formatter(); }); if (needToSwitchSelection) { editor.select(selection); } }, apiName); } } exports.default = execCommand; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts": /*!***********************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/utils/formatUndoSnapshot.ts ***! \***********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * @internal * Execute add undo snapshot for the Format APIs * @param editor The editor instance * @param command Optional, The callback function to perform formatting, returns a data object which will be used as the data field in ContentChangedEvent if changeSource is not null. * @param apiName Optional, name of the API that was is going to be executed. * Default value is false. */ function formatUndoSnapshot(editor, callback, apiName) { editor.addUndoSnapshot(callback, "Format" /* Format */, undefined /* canUndoByBackspace */, apiName && { formatApiName: apiName, }); } exports.default = formatUndoSnapshot; /***/ }), /***/ "./packages/roosterjs-editor-api/lib/utils/normalizeBlockquote.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/utils/normalizeBlockquote.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * @param node start node to normalize * @param quotesHandled Optional parameter to prevent already modified quotes to be rechecked. * @returns */ function normalizeBlockquote(node, quotesHandled) { if ((0, roosterjs_editor_dom_1.safeInstanceOf)(node, 'HTMLElement')) { var alignment = node.style.textAlign; var quote = (0, roosterjs_editor_dom_1.findClosestElementAncestor)(node, undefined /* root */, 'blockquote'); var isNodeRTL = isRTL(node); if (quotesHandled) { if (quotesHandled.indexOf(quote) > -1) { return; } quotesHandled.push(quote); } while (quote) { if (alignment == 'center') { if (isNodeRTL) { delete quote.style.marginInlineEnd; quote.style.marginInlineStart = 'auto'; } else { delete quote.style.marginInlineStart; quote.style.marginInlineEnd = 'auto'; } } else { delete quote.style.marginInlineStart; delete quote.style.marginInlineEnd; } quote = (0, roosterjs_editor_dom_1.findClosestElementAncestor)(quote.parentElement, undefined /* root */, 'blockquote'); } } } exports.default = normalizeBlockquote; function isRTL(el) { return (0, roosterjs_editor_dom_1.getComputedStyle)(el, 'direction') == 'rtl' || el.getAttribute('dir') == 'rtl'; } /***/ }), /***/ "./packages/roosterjs-editor-api/lib/utils/toggleListType.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-api/lib/utils/toggleListType.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var blockFormat_1 = __webpack_require__(/*! ../utils/blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Toggle List Type at selection * If ListType Provided is Ordered: * If selection contains numbering in deep level, toggle numbering will decrease the numbering level by one * If selection contains bullet list, toggle numbering will convert the bullet list into number list * If selection contains both bullet/numbering and normal text, the behavior is decided by corresponding * realization of browser execCommand API * If ListType Provided is Unordered: * If selection contains bullet in deep level, toggle bullet will decrease the bullet level by one * If selection contains number list, toggle bullet will convert the number list into bullet list * If selection contains both bullet/numbering and normal text, the behavior is decided by corresponding * browser execCommand API * @param editor The editor instance * @param listType The list type to toggle * @param startNumber (Optional) Start number of the list * @param includeSiblingLists Sets wether the operation should include Sibling Lists, by default true * @param orderedStyle (Optional) the style of an ordered. If not defined, the style will be set to decimal. * @param unorderedStyle (Optional) the style of an unordered list. If not defined, the style will be set to disc. * @param apiNameOverride (Optional) Set a new api name, if empty the api name will be 'toggleListType'. */ function toggleListType(editor, listType, startNumber, includeSiblingLists, orderedStyle, unorderedStyle, apiNameOverride) { if (includeSiblingLists === void 0) { includeSiblingLists = true; } (0, blockFormat_1.default)(editor, function (region, start, end, chains) { var _a; var chain = startNumber > 0 && chains.filter(function (chain) { return chain.canAppendAtCursor(startNumber); })[0]; var vList = chain && start.equalTo(end) ? chain.createVListAtBlock((_a = (0, roosterjs_editor_dom_1.getBlockElementAtNode)(region.rootNode, start.node)) === null || _a === void 0 ? void 0 : _a.collapseToSingleElement(), startNumber) : (0, roosterjs_editor_dom_1.createVListFromRegion)(region, startNumber === 1 ? false : includeSiblingLists); if (vList) { vList.changeListType(start, end, listType); if (editor.isFeatureEnabled("AutoFormatList" /* AutoFormatList */)) { vList.setListStyleType(orderedStyle, unorderedStyle); } vList.writeBack(editor.isFeatureEnabled("ReuseAllAncestorListElements" /* ReuseAllAncestorListElements */)); } }, undefined /* beforeRunCallback */, apiNameOverride || 'toggleListType'); } exports.default = toggleListType; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/addUndoSnapshot.ts": /*!***********************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/addUndoSnapshot.ts ***! \***********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.addUndoSnapshot = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Call an editing callback with adding undo snapshots around, and trigger a ContentChanged event if change source is specified. * Undo snapshot will not be added if this call is nested inside another addUndoSnapshot() call. * @param core The EditorCore object * @param callback The editing callback, accepting current selection start and end position, returns an optional object used as the data field of ContentChangedEvent. * @param changeSource The ChangeSource string of ContentChangedEvent. @default ChangeSource.Format. Set to null to avoid triggering ContentChangedEvent * @param canUndoByBackspace True if this action can be undone when user press Backspace key (aka Auto Complete). * @param formatApiName Optional parameter to provide the ContentChangeEvent which FormatApi was invoked. */ var addUndoSnapshot = function (core, callback, changeSource, canUndoByBackspace, additionalData) { var undoState = core.undo; var isNested = undoState.isNested; var data; if (!isNested) { undoState.isNested = true; addUndoSnapshotInternal(core, canUndoByBackspace); } try { if (callback) { var range = core.api.getSelectionRange(core, true /*tryGetFromCache*/); data = callback(range && roosterjs_editor_dom_1.Position.getStart(range).normalize(), range && roosterjs_editor_dom_1.Position.getEnd(range).normalize()); if (!isNested) { addUndoSnapshotInternal(core, false /*isAutoCompleteSnapshot*/); } } } finally { if (!isNested) { undoState.isNested = false; } } if (callback && changeSource) { var event_1 = { eventType: 7 /* ContentChanged */, source: changeSource, data: data, additionalData: additionalData, }; core.api.triggerEvent(core, event_1, true /*broadcast*/); } if (canUndoByBackspace) { var range = core.api.getSelectionRange(core, false /*tryGetFromCache*/); if (range) { core.undo.hasNewContent = false; core.undo.autoCompletePosition = roosterjs_editor_dom_1.Position.getStart(range); } } }; exports.addUndoSnapshot = addUndoSnapshot; function addUndoSnapshotInternal(core, canUndoByBackspace) { if (!core.lifecycle.shadowEditFragment) { var rangeEx = core.api.getSelectionRangeEx(core); var isDarkMode = core.lifecycle.isDarkMode; var metadata = createContentMetadata(core.contentDiv, rangeEx, isDarkMode) || null; core.undo.snapshotsService.addSnapshot({ html: core.contentDiv.innerHTML, metadata: metadata, }, canUndoByBackspace); core.undo.hasNewContent = false; } } function createContentMetadata(root, rangeEx, isDarkMode) { switch (rangeEx === null || rangeEx === void 0 ? void 0 : rangeEx.type) { case 1 /* TableSelection */: return __assign({ type: 1 /* TableSelection */, tableId: rangeEx.table.id, isDarkMode: !!isDarkMode }, rangeEx.coordinates); case 2 /* ImageSelection */: return { type: 2 /* ImageSelection */, imageId: rangeEx.image.id, isDarkMode: !!isDarkMode, }; case 0 /* Normal */: return __assign({ type: 0 /* Normal */, isDarkMode: !!isDarkMode, start: [], end: [] }, ((0, roosterjs_editor_dom_1.getSelectionPath)(root, rangeEx.ranges[0]) || {})); } } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/attachDomEvent.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/attachDomEvent.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.attachDomEvent = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Attach a DOM event to the editor content DIV * @param core The EditorCore object * @param eventName The DOM event name * @param pluginEventType Optional event type. When specified, editor will trigger a plugin event with this name when the DOM event is triggered * @param beforeDispatch Optional callback function to be invoked when the DOM event is triggered before trigger plugin event */ var attachDomEvent = function (core, eventMap) { var disposers = (0, roosterjs_editor_dom_1.getObjectKeys)(eventMap || {}).map(function (key) { var _a = extractHandler(eventMap[key]), pluginEventType = _a.pluginEventType, beforeDispatch = _a.beforeDispatch; var eventName = key; var onEvent = function (event) { if (beforeDispatch) { beforeDispatch(event); } if (pluginEventType != null) { core.api.triggerEvent(core, { eventType: pluginEventType, rawEvent: event, }, false /*broadcast*/); } }; core.contentDiv.addEventListener(eventName, onEvent); return function () { core.contentDiv.removeEventListener(eventName, onEvent); }; }); return function () { return disposers.forEach(function (disposers) { return disposers(); }); }; }; exports.attachDomEvent = attachDomEvent; function extractHandler(handlerObj) { var result = { pluginEventType: null, beforeDispatch: null, }; if (typeof handlerObj === 'number') { result.pluginEventType = handlerObj; } else if (typeof handlerObj === 'function') { result.beforeDispatch = handlerObj; } else if (typeof handlerObj === 'object') { result = handlerObj; } return result; } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/coreApiMap.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/coreApiMap.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.coreApiMap = void 0; var addUndoSnapshot_1 = __webpack_require__(/*! ./addUndoSnapshot */ "./packages/roosterjs-editor-core/lib/coreApi/addUndoSnapshot.ts"); var attachDomEvent_1 = __webpack_require__(/*! ./attachDomEvent */ "./packages/roosterjs-editor-core/lib/coreApi/attachDomEvent.ts"); var createPasteFragment_1 = __webpack_require__(/*! ./createPasteFragment */ "./packages/roosterjs-editor-core/lib/coreApi/createPasteFragment.ts"); var ensureTypeInContainer_1 = __webpack_require__(/*! ./ensureTypeInContainer */ "./packages/roosterjs-editor-core/lib/coreApi/ensureTypeInContainer.ts"); var focus_1 = __webpack_require__(/*! ./focus */ "./packages/roosterjs-editor-core/lib/coreApi/focus.ts"); var getContent_1 = __webpack_require__(/*! ./getContent */ "./packages/roosterjs-editor-core/lib/coreApi/getContent.ts"); var getPendableFormatState_1 = __webpack_require__(/*! ./getPendableFormatState */ "./packages/roosterjs-editor-core/lib/coreApi/getPendableFormatState.ts"); var getSelectionRange_1 = __webpack_require__(/*! ./getSelectionRange */ "./packages/roosterjs-editor-core/lib/coreApi/getSelectionRange.ts"); var getSelectionRangeEx_1 = __webpack_require__(/*! ./getSelectionRangeEx */ "./packages/roosterjs-editor-core/lib/coreApi/getSelectionRangeEx.ts"); var getStyleBasedFormatState_1 = __webpack_require__(/*! ./getStyleBasedFormatState */ "./packages/roosterjs-editor-core/lib/coreApi/getStyleBasedFormatState.ts"); var hasFocus_1 = __webpack_require__(/*! ./hasFocus */ "./packages/roosterjs-editor-core/lib/coreApi/hasFocus.ts"); var insertNode_1 = __webpack_require__(/*! ./insertNode */ "./packages/roosterjs-editor-core/lib/coreApi/insertNode.ts"); var restoreUndoSnapshot_1 = __webpack_require__(/*! ./restoreUndoSnapshot */ "./packages/roosterjs-editor-core/lib/coreApi/restoreUndoSnapshot.ts"); var selectImage_1 = __webpack_require__(/*! ./selectImage */ "./packages/roosterjs-editor-core/lib/coreApi/selectImage.ts"); var selectRange_1 = __webpack_require__(/*! ./selectRange */ "./packages/roosterjs-editor-core/lib/coreApi/selectRange.ts"); var selectTable_1 = __webpack_require__(/*! ./selectTable */ "./packages/roosterjs-editor-core/lib/coreApi/selectTable.ts"); var setContent_1 = __webpack_require__(/*! ./setContent */ "./packages/roosterjs-editor-core/lib/coreApi/setContent.ts"); var switchShadowEdit_1 = __webpack_require__(/*! ./switchShadowEdit */ "./packages/roosterjs-editor-core/lib/coreApi/switchShadowEdit.ts"); var transformColor_1 = __webpack_require__(/*! ./transformColor */ "./packages/roosterjs-editor-core/lib/coreApi/transformColor.ts"); var triggerEvent_1 = __webpack_require__(/*! ./triggerEvent */ "./packages/roosterjs-editor-core/lib/coreApi/triggerEvent.ts"); /** * @internal */ exports.coreApiMap = { attachDomEvent: attachDomEvent_1.attachDomEvent, addUndoSnapshot: addUndoSnapshot_1.addUndoSnapshot, createPasteFragment: createPasteFragment_1.createPasteFragment, ensureTypeInContainer: ensureTypeInContainer_1.ensureTypeInContainer, focus: focus_1.focus, getContent: getContent_1.getContent, getSelectionRange: getSelectionRange_1.getSelectionRange, getSelectionRangeEx: getSelectionRangeEx_1.getSelectionRangeEx, getStyleBasedFormatState: getStyleBasedFormatState_1.getStyleBasedFormatState, getPendableFormatState: getPendableFormatState_1.getPendableFormatState, hasFocus: hasFocus_1.hasFocus, insertNode: insertNode_1.insertNode, restoreUndoSnapshot: restoreUndoSnapshot_1.restoreUndoSnapshot, selectRange: selectRange_1.selectRange, setContent: setContent_1.setContent, switchShadowEdit: switchShadowEdit_1.switchShadowEdit, transformColor: transformColor_1.transformColor, triggerEvent: triggerEvent_1.triggerEvent, selectTable: selectTable_1.selectTable, selectImage: selectImage_1.selectImage, }; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/createPasteFragment.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/createPasteFragment.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformTabCharacters = exports.createPasteFragment = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var START_FRAGMENT = ''; var END_FRAGMENT = ''; var NBSP_HTML = '\u00A0'; var ENSP_HTML = '\u2002'; var TAB_SPACES = 6; /** * @internal * Create a DocumentFragment for paste from a ClipboardData * @param core The EditorCore object. * @param clipboardData Clipboard data retrieved from clipboard * @param position The position to paste to * @param pasteAsText True to force use plain text as the content to paste, false to choose HTML or Image if any * @param applyCurrentStyle True if apply format of current selection to the pasted content, * false to keep original format */ var createPasteFragment = function (core, clipboardData, position, pasteAsText, applyCurrentStyle) { var _a, _b; if (!clipboardData) { return null; } // Step 1: Prepare BeforePasteEvent object var event = createBeforePasteEvent(core, clipboardData); var fragment = event.fragment, sanitizingOption = event.sanitizingOption; var rawHtml = clipboardData.rawHtml, text = clipboardData.text, imageDataUri = clipboardData.imageDataUri; var document = core.contentDiv.ownerDocument; var doc = rawHtml ? new DOMParser().parseFromString(core.trustedHTMLHandler(rawHtml), 'text/html') : undefined; // Step 2: Retrieve Metadata from Html and the Html that was copied. if (rawHtml && (doc === null || doc === void 0 ? void 0 : doc.body)) { var attributes = (_a = doc.querySelector('html')) === null || _a === void 0 ? void 0 : _a.attributes; (attributes ? (0, roosterjs_editor_dom_1.toArray)(attributes) : []).reduce(function (attrs, attr) { attrs[attr.name] = attr.value; return attrs; }, event.htmlAttributes); (0, roosterjs_editor_dom_1.toArray)(doc.querySelectorAll('meta')).reduce(function (attrs, meta) { attrs[meta.name] = meta.content; return attrs; }, event.htmlAttributes); clipboardData.htmlFirstLevelChildTags = []; doc === null || doc === void 0 ? void 0 : doc.body.normalize(); for (var i = 0; i < (doc === null || doc === void 0 ? void 0 : doc.body.childNodes.length); i++) { var node = doc === null || doc === void 0 ? void 0 : doc.body.childNodes.item(i); if (node.nodeType == Node.TEXT_NODE) { var trimmedString = (_b = node.nodeValue) === null || _b === void 0 ? void 0 : _b.replace(/(\r\n|\r|\n)/gm, '').trim(); if (!trimmedString) { continue; } } var nodeTag = (0, roosterjs_editor_dom_1.getTagOfNode)(node); if (node.nodeType != Node.COMMENT_NODE) { clipboardData.htmlFirstLevelChildTags.push(nodeTag); } } // Move all STYLE nodes into header, and save them into sanitizing options. // Because if we directly move them into a fragment, all sheets under STYLE will be lost. processStyles(doc, function (style) { doc === null || doc === void 0 ? void 0 : doc.head.appendChild(style); sanitizingOption.additionalGlobalStyleNodes.push(style); }); var startIndex = rawHtml.indexOf(START_FRAGMENT); var endIndex = rawHtml.lastIndexOf(END_FRAGMENT); if (startIndex >= 0 && endIndex >= startIndex + START_FRAGMENT.length) { event.htmlBefore = rawHtml.substr(0, startIndex); event.htmlAfter = rawHtml.substr(endIndex + END_FRAGMENT.length); clipboardData.html = rawHtml.substring(startIndex + START_FRAGMENT.length, endIndex); doc.body.innerHTML = core.trustedHTMLHandler(clipboardData.html); // Remove style nodes just added by setting innerHTML of body since we already have all // style nodes in header. // Here we use doc.body instead of doc because we only want to remove STYLE nodes under BODY // and the nodes under HEAD are still used when convert global CSS to inline processStyles(doc.body, function (style) { var _a; return (_a = style.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(style); }); } } // Step 3: Fill the BeforePasteEvent object, especially the fragment for paste if (!pasteAsText && !text && imageDataUri) { // Paste image var img = document.createElement('img'); img.style.maxWidth = '100%'; img.src = imageDataUri; fragment.appendChild(img); } else if (!pasteAsText && rawHtml && doc ? doc.body : false) { (0, roosterjs_editor_dom_1.moveChildNodes)(fragment, doc === null || doc === void 0 ? void 0 : doc.body); if (applyCurrentStyle && position) { var format_1 = getCurrentFormat(core, position.node); (0, roosterjs_editor_dom_1.applyTextStyle)(fragment, function (node) { return (0, roosterjs_editor_dom_1.applyFormat)(node, format_1); }); } } else if (text) { // Paste text text.split('\n').forEach(function (line, index, lines) { line = line .replace(/^ /g, NBSP_HTML) .replace(/\r/g, '') .replace(/ {2}/g, ' ' + NBSP_HTML); if (line.includes('\t')) { line = transformTabCharacters(line, index === 0 ? position === null || position === void 0 ? void 0 : position.offset : 0); } var textNode = document.createTextNode(line); // There are 3 scenarios: // 1. Single line: Paste as it is // 2. Two lines: Add
between the lines // 3. 3 or More lines, For first and last line, paste as it is. For middle lines, wrap with DIV, and add BR if it is empty line if (lines.length == 2 && index == 0) { // 1 of 2 lines scenario, add BR fragment.appendChild(textNode); fragment.appendChild(document.createElement('br')); } else if (index > 0 && index < lines.length - 1) { // Middle line of >=3 lines scenario, wrap with DIV fragment.appendChild((0, roosterjs_editor_dom_1.wrap)(line == '' ? document.createElement('br') : textNode)); } else { // All others, paste as it is fragment.appendChild(textNode); } }); } // Step 4: Trigger BeforePasteEvent so that plugins can do proper change before paste core.api.triggerEvent(core, event, true /*broadcast*/); // Step 5. Sanitize the fragment before paste to make sure the content is safe var sanitizer = new roosterjs_editor_dom_1.HtmlSanitizer(event.sanitizingOption); sanitizer.convertGlobalCssToInlineCss(fragment); sanitizer.sanitize(fragment, position ? (0, roosterjs_editor_dom_1.getInheritableStyles)(position.element) : undefined); return fragment; }; exports.createPasteFragment = createPasteFragment; /** * @internal * Transform \t characters into EN SPACE characters * @param input string NOT containing \n characters * @example t("\thello", 2) => "    hello" */ function transformTabCharacters(input, initialOffset) { if (initialOffset === void 0) { initialOffset = 0; } var line = input; var tIndex; while ((tIndex = line.indexOf('\t')) != -1) { var lineBefore = line.slice(0, tIndex); var lineAfter = line.slice(tIndex + 1); var tabCount = TAB_SPACES - ((lineBefore.length + initialOffset) % TAB_SPACES); var tabStr = Array(tabCount).fill(ENSP_HTML).join(''); line = lineBefore + tabStr + lineAfter; } return line; } exports.transformTabCharacters = transformTabCharacters; function getCurrentFormat(core, node) { var pendableFormat = core.api.getPendableFormatState(core, true /** forceGetStateFromDOM*/); var styleBasedFormat = core.api.getStyleBasedFormatState(core, node); return { fontFamily: styleBasedFormat.fontName, fontSize: styleBasedFormat.fontSize, textColor: styleBasedFormat.textColor, backgroundColor: styleBasedFormat.backgroundColor, textColors: styleBasedFormat.textColors, backgroundColors: styleBasedFormat.backgroundColors, bold: pendableFormat.isBold, italic: pendableFormat.isItalic, underline: pendableFormat.isUnderline, }; } function createBeforePasteEvent(core, clipboardData) { var options = (0, roosterjs_editor_dom_1.createDefaultHtmlSanitizerOptions)(); // Remove "caret-color" style generated by Safari to make sure caret shows in right color after paste options.cssStyleCallbacks['caret-color'] = function () { return false; }; return { eventType: 10 /* BeforePaste */, clipboardData: clipboardData, fragment: core.contentDiv.ownerDocument.createDocumentFragment(), sanitizingOption: options, htmlBefore: '', htmlAfter: '', htmlAttributes: {}, }; } function processStyles(node, callback) { (0, roosterjs_editor_dom_1.toArray)(node.querySelectorAll('style')).forEach(callback); } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/ensureTypeInContainer.ts": /*!*****************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/ensureTypeInContainer.ts ***! \*****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ensureTypeInContainer = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * When typing goes directly under content div, many things can go wrong * We fix it by wrapping it with a div and reposition cursor within the div */ var ensureTypeInContainer = function (core, position, keyboardEvent, applyFormatToSpan) { var table = (0, roosterjs_editor_dom_1.findClosestElementAncestor)(position.node, core.contentDiv, 'table'); var td; if (table && (td = table.querySelector('td,th'))) { position = new roosterjs_editor_dom_1.Position(td, 0 /* Begin */); } position = position.normalize(); var block = (0, roosterjs_editor_dom_1.getBlockElementAtNode)(core.contentDiv, position.node); var formatNode; if (block) { formatNode = block.collapseToSingleElement(); if ((0, roosterjs_editor_dom_1.isNodeEmpty)(formatNode, false /* trimContent */, true /* shouldCountBrAsVisible */)) { var brEl = formatNode.ownerDocument.createElement('br'); formatNode.append(brEl); } // if the block is empty, apply default format // Otherwise, leave it as it is as we don't want to change the style for existing data // unless the block was just created by the keyboard event (e.g. ctrl+a & start typing) var shouldSetNodeStyles = (0, roosterjs_editor_dom_1.isNodeEmpty)(formatNode) || (keyboardEvent && wasNodeJustCreatedByKeyboardEvent(keyboardEvent, formatNode)); formatNode = formatNode && shouldSetNodeStyles ? formatNode : null; if (formatNode && core.lifecycle.defaultFormat && applyFormatToSpan) { var firstChild = formatNode.firstChild; formatNode = (0, roosterjs_editor_dom_1.safeInstanceOf)(firstChild, 'HTMLSpanElement') ? firstChild : (0, roosterjs_editor_dom_1.wrap)((0, roosterjs_editor_dom_1.toArray)(formatNode.childNodes), 'span'); } } else { // Only reason we don't get the selection block is that we have an empty content div // which can happen when users removes everything (i.e. select all and DEL, or backspace from very end to begin) // The fix is to add a DIV wrapping, apply default format and move cursor over formatNode = (0, roosterjs_editor_dom_1.createElement)(applyFormatToSpan ? 12 /* EmptyLineFormatInSpan */ : 1 /* EmptyLine */, core.contentDiv.ownerDocument); core.api.insertNode(core, formatNode, { position: 1 /* End */, updateCursor: false, replaceSelection: false, insertOnNewLine: false, }); formatNode = applyFormatToSpan ? formatNode.firstChild : formatNode; // element points to a wrapping node we added "

". We should move the selection left to
position = new roosterjs_editor_dom_1.Position(formatNode, 0 /* Begin */); } if (formatNode && core.lifecycle.defaultFormat) { (0, roosterjs_editor_dom_1.applyFormat)(formatNode, core.lifecycle.defaultFormat, core.lifecycle.isDarkMode, core.darkColorHandler); } // If this is triggered by a keyboard event, let's select the new position if (keyboardEvent) { core.api.selectRange(core, (0, roosterjs_editor_dom_1.createRange)(new roosterjs_editor_dom_1.Position(position))); } }; exports.ensureTypeInContainer = ensureTypeInContainer; function wasNodeJustCreatedByKeyboardEvent(event, formatNode) { return ((0, roosterjs_editor_dom_1.safeInstanceOf)(event.target, 'Node') && event.target.contains(formatNode) && event.key === formatNode.innerText); } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/focus.ts": /*!*************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/focus.ts ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.focus = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Focus to editor. If there is a cached selection range, use it as current selection * @param core The EditorCore object */ var focus = function (core) { if (!core.lifecycle.shadowEditFragment) { if (!core.api.hasFocus(core) || !core.api.getSelectionRange(core, false /*tryGetFromCache*/)) { // Focus (document.activeElement indicates) and selection are mostly in sync, but could be out of sync in some extreme cases. // i.e. if you programmatically change window selection to point to a non-focusable DOM element (i.e. tabindex=-1 etc.). // On Chrome/Firefox, it does not change document.activeElement. On Edge/IE, it change document.activeElement to be body // Although on Chrome/Firefox, document.activeElement points to editor, you cannot really type which we don't want (no cursor). // So here we always do a live selection pull on DOM and make it point in Editor. The pitfall is, the cursor could be reset // to very begin to of editor since we don't really have last saved selection (created on blur which does not fire in this case). // It should be better than the case you cannot type if (!core.domEvent.selectionRange || !core.api.selectRange(core, core.domEvent.selectionRange, true /*skipSameRange*/)) { var node = (0, roosterjs_editor_dom_1.getFirstLeafNode)(core.contentDiv) || core.contentDiv; core.api.selectRange(core, (0, roosterjs_editor_dom_1.createRange)(node, 0 /* Begin */), true /*skipSameRange*/); } } // remember to clear cached selection range core.domEvent.selectionRange = null; // This is more a fallback to ensure editor gets focus if it didn't manage to move focus to editor if (!core.api.hasFocus(core)) { core.contentDiv.focus(); } } }; exports.focus = focus; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/getContent.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/getContent.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getContent = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Get current editor content as HTML string * @param core The EditorCore object * @param mode specify what kind of HTML content to retrieve * @returns HTML string representing current editor content */ var getContent = function (core, mode) { var content = ''; var triggerExtractContentEvent = mode == 0 /* CleanHTML */; var includeSelectionMarker = mode == 2 /* RawHTMLWithSelection */; // When there is fragment for shadow edit, always use the cached fragment as document since HTML node in editor // has been changed by uncommitted shadow edit which should be ignored. var root = core.lifecycle.shadowEditFragment || core.contentDiv; if (mode == 4 /* PlainTextFast */) { content = root.textContent; } else if (mode == 3 /* PlainText */) { content = (0, roosterjs_editor_dom_1.getTextContent)(root); } else if (triggerExtractContentEvent || core.lifecycle.isDarkMode || core.darkColorHandler) { var clonedRoot = cloneNode(root); clonedRoot.normalize(); var originalRange = core.api.getSelectionRange(core, true /*tryGetFromCache*/); var path = !includeSelectionMarker ? null : core.lifecycle.shadowEditFragment ? core.lifecycle.shadowEditSelectionPath : originalRange ? (0, roosterjs_editor_dom_1.getSelectionPath)(core.contentDiv, originalRange) : null; var range = path && (0, roosterjs_editor_dom_1.createRange)(clonedRoot, path.start, path.end); if (core.lifecycle.isDarkMode || core.darkColorHandler) { core.api.transformColor(core, clonedRoot, false /*includeSelf*/, null /*callback*/, 1 /* DarkToLight */, !!core.darkColorHandler); } if (triggerExtractContentEvent) { core.api.triggerEvent(core, { eventType: 8 /* ExtractContentWithDom */, clonedRoot: clonedRoot, }, true /*broadcast*/); content = clonedRoot.innerHTML; } else if (range) { // range is not null, which means we want to include a selection path in the content content = (0, roosterjs_editor_dom_1.getHtmlWithSelectionPath)(clonedRoot, range); } else { content = clonedRoot.innerHTML; } } else { content = (0, roosterjs_editor_dom_1.getHtmlWithSelectionPath)(root, includeSelectionMarker ? core.api.getSelectionRange(core, true /*tryGetFromCache*/) : null); } return content !== null && content !== void 0 ? content : ''; }; exports.getContent = getContent; function cloneNode(node) { var clonedNode; if ((0, roosterjs_editor_dom_1.safeInstanceOf)(node, 'DocumentFragment')) { clonedNode = node.ownerDocument.createElement('div'); clonedNode.appendChild(node.cloneNode(true /*deep*/)); } else { clonedNode = node.cloneNode(true /*deep*/); } return clonedNode; } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/getPendableFormatState.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/getPendableFormatState.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getPendableFormatState = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * @param core The EditorCore object * @param forceGetStateFromDOM If set to true, will force get the format state from DOM tree. * @returns The cached format state if it exists. If the cached position do not exist, search for pendable elements in the DOM tree and return the pendable format state. */ var getPendableFormatState = function (core, forceGetStateFromDOM) { var _a; var range = core.api.getSelectionRange(core, true /* tryGetFromCache*/); var cachedPendableFormatState = core.pendingFormatState.pendableFormatState; var cachedPosition = (_a = core.pendingFormatState.pendableFormatPosition) === null || _a === void 0 ? void 0 : _a.normalize(); var currentPosition = range && roosterjs_editor_dom_1.Position.getStart(range).normalize(); var isSamePosition = currentPosition && cachedPosition && range.collapsed && currentPosition.equalTo(cachedPosition); if (range && cachedPendableFormatState && isSamePosition && !forceGetStateFromDOM) { return cachedPendableFormatState; } else { return currentPosition ? queryCommandStateFromDOM(core, currentPosition) : {}; } }; exports.getPendableFormatState = getPendableFormatState; var PendableStyleCheckers = { isBold: function (tag, style) { return tag == 'B' || tag == 'STRONG' || tag == 'H1' || tag == 'H2' || tag == 'H3' || tag == 'H4' || tag == 'H5' || tag == 'H6' || parseInt(style.fontWeight) >= 700 || ['bold', 'bolder'].indexOf(style.fontWeight) >= 0; }, isUnderline: function (tag, style) { return tag == 'U' || style.textDecoration.indexOf('underline') >= 0; }, isItalic: function (tag, style) { return tag == 'I' || tag == 'EM' || style.fontStyle === 'italic'; }, isSubscript: function (tag, style) { return tag == 'SUB' || style.verticalAlign === 'sub'; }, isSuperscript: function (tag, style) { return tag == 'SUP' || style.verticalAlign === 'super'; }, isStrikeThrough: function (tag, style) { return tag == 'S' || tag == 'STRIKE' || style.textDecoration.indexOf('line-through') >= 0; }, }; /** * CssFalsyCheckers checks for non pendable format that might overlay a pendable format, then it can prevent getPendableFormatState return falsy pendable format states. */ var CssFalsyCheckers = { isBold: function (style) { return (style.fontWeight !== '' && parseInt(style.fontWeight) < 700) || style.fontWeight === 'normal'; }, isUnderline: function (style) { return style.textDecoration !== '' && style.textDecoration.indexOf('underline') < 0; }, isItalic: function (style) { return style.fontStyle !== '' && style.fontStyle !== 'italic'; }, isSubscript: function (style) { return style.verticalAlign !== '' && style.verticalAlign !== 'sub'; }, isSuperscript: function (style) { return style.verticalAlign !== '' && style.verticalAlign !== 'super'; }, isStrikeThrough: function (style) { return style.textDecoration !== '' && style.textDecoration.indexOf('line-through') < 0; }, }; function queryCommandStateFromDOM(core, currentPosition) { var node = currentPosition.node; var formatState = {}; var pendableKeys = []; var _loop_1 = function () { var tag = (0, roosterjs_editor_dom_1.getTagOfNode)(node); var style = node.nodeType == 1 /* Element */ && node.style; if (tag && style) { (0, roosterjs_editor_dom_1.getObjectKeys)(PendableStyleCheckers).forEach(function (key) { if (!(pendableKeys.indexOf(key) >= 0)) { formatState[key] = formatState[key] || PendableStyleCheckers[key](tag, style); if (CssFalsyCheckers[key](style)) { pendableKeys.push(key); } } }); } node = node.parentNode; }; while (node && (0, roosterjs_editor_dom_1.contains)(core.contentDiv, node)) { _loop_1(); } return formatState; } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/getSelectionRange.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/getSelectionRange.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSelectionRange = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Get current or cached selection range * @param core The EditorCore object * @param tryGetFromCache Set to true to retrieve the selection range from cache if editor doesn't own the focus now * @returns A Range object of the selection range */ var getSelectionRange = function (core, tryGetFromCache) { var _a; var result = null; if (core.lifecycle.shadowEditFragment) { result = core.lifecycle.shadowEditSelectionPath && (0, roosterjs_editor_dom_1.createRange)(core.contentDiv, core.lifecycle.shadowEditSelectionPath.start, core.lifecycle.shadowEditSelectionPath.end); return result; } else { if (!tryGetFromCache || core.api.hasFocus(core)) { var selection = (_a = core.contentDiv.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection(); if (selection && selection.rangeCount > 0) { var range = selection.getRangeAt(0); if ((0, roosterjs_editor_dom_1.contains)(core.contentDiv, range)) { result = range; } } } if (!result && tryGetFromCache) { result = core.domEvent.selectionRange; } return result; } }; exports.getSelectionRange = getSelectionRange; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/getSelectionRangeEx.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/getSelectionRangeEx.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSelectionRangeEx = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Get current or cached selection range * @param core The EditorCore object * @returns A Range object of the selection range */ var getSelectionRangeEx = function (core) { var _a, _b, _c; var result = null; if (core.lifecycle.shadowEditFragment) { var _d = core.lifecycle, shadowEditTableSelectionPath = _d.shadowEditTableSelectionPath, shadowEditSelectionPath = _d.shadowEditSelectionPath, shadowEditImageSelectionPath = _d.shadowEditImageSelectionPath; if (((shadowEditTableSelectionPath === null || shadowEditTableSelectionPath === void 0 ? void 0 : shadowEditTableSelectionPath.length) || 0) > 0) { var ranges = core.lifecycle.shadowEditTableSelectionPath.map(function (path) { return (0, roosterjs_editor_dom_1.createRange)(core.contentDiv, path.start, path.end); }); return { type: 1 /* TableSelection */, ranges: ranges, areAllCollapsed: checkAllCollapsed(ranges), table: (0, roosterjs_editor_dom_1.findClosestElementAncestor)(ranges[0].startContainer, core.contentDiv, 'table'), coordinates: undefined, }; } else if (((shadowEditImageSelectionPath === null || shadowEditImageSelectionPath === void 0 ? void 0 : shadowEditImageSelectionPath.length) || 0) > 0) { var ranges = core.lifecycle.shadowEditImageSelectionPath.map(function (path) { return (0, roosterjs_editor_dom_1.createRange)(core.contentDiv, path.start, path.end); }); return { type: 2 /* ImageSelection */, ranges: ranges, areAllCollapsed: checkAllCollapsed(ranges), image: (0, roosterjs_editor_dom_1.findClosestElementAncestor)(ranges[0].startContainer, core.contentDiv, 'img'), imageId: undefined, }; } else { var shadowRange = shadowEditSelectionPath && (0, roosterjs_editor_dom_1.createRange)(core.contentDiv, shadowEditSelectionPath.start, shadowEditSelectionPath.end); return createNormalSelectionEx(shadowRange ? [shadowRange] : []); } } else { if (core.api.hasFocus(core)) { if (core.domEvent.tableSelectionRange) { return core.domEvent.tableSelectionRange; } if (core.domEvent.imageSelectionRange) { return core.domEvent.imageSelectionRange; } var selection = (_a = core.contentDiv.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection(); if (!result && selection && selection.rangeCount > 0) { var range = selection.getRangeAt(0); if ((0, roosterjs_editor_dom_1.contains)(core.contentDiv, range)) { return createNormalSelectionEx([range]); } } } return ((_c = (_b = core.domEvent.tableSelectionRange) !== null && _b !== void 0 ? _b : core.domEvent.imageSelectionRange) !== null && _c !== void 0 ? _c : createNormalSelectionEx(core.domEvent.selectionRange ? [core.domEvent.selectionRange] : [])); } }; exports.getSelectionRangeEx = getSelectionRangeEx; function createNormalSelectionEx(ranges) { return { type: 0 /* Normal */, ranges: ranges, areAllCollapsed: checkAllCollapsed(ranges), }; } function checkAllCollapsed(ranges) { return ranges.filter(function (range) { return range === null || range === void 0 ? void 0 : range.collapsed; }).length == ranges.length; } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/getStyleBasedFormatState.ts": /*!********************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/getStyleBasedFormatState.ts ***! \********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getStyleBasedFormatState = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var ORIGINAL_STYLE_COLOR_SELECTOR = "[data-" + "ogsc" /* OriginalStyleColor */ + "],[data-" + "ogac" /* OriginalAttributeColor */ + "]"; var ORIGINAL_STYLE_BACK_COLOR_SELECTOR = "[data-" + "ogsb" /* OriginalStyleBackgroundColor */ + "],[data-" + "ogab" /* OriginalAttributeBackgroundColor */ + "]"; /** * @internal * Get style based format state from current selection, including font name/size and colors * @param core The EditorCore objects * @param node The node to get style from */ var getStyleBasedFormatState = function (core, node) { if (!node) { return {}; } var override = []; var pendableFormatSpan = core.pendingFormatState.pendableFormatSpan; if (pendableFormatSpan) { override = [ pendableFormatSpan.style.fontFamily, pendableFormatSpan.style.fontSize, pendableFormatSpan.style.color, pendableFormatSpan.style.backgroundColor, ]; } var styles = node ? (0, roosterjs_editor_dom_1.getComputedStyles)(node) : []; var contentDiv = core.contentDiv, darkColorHandler = core.darkColorHandler, isDarkMode = core.lifecycle.isDarkMode; if (darkColorHandler) { var styleTextColor = void 0; var styleBackColor = void 0; while (node && (0, roosterjs_editor_dom_1.contains)(contentDiv, node, true /*treatSameNodeAsContain*/) && !(styleTextColor && styleBackColor)) { if (node.nodeType == 1 /* Element */) { var element = node; styleTextColor = styleTextColor || element.style.getPropertyValue('color'); styleBackColor = styleBackColor || element.style.getPropertyValue('background-color'); } node = node.parentNode; } if (!core.lifecycle.isDarkMode && node == core.contentDiv) { styleTextColor = styleTextColor || styles[2]; styleBackColor = styleBackColor || styles[3]; } var textColor = darkColorHandler.parseColorValue(override[2] || styleTextColor); var backColor = darkColorHandler.parseColorValue(override[3] || styleBackColor); return { fontName: override[0] || styles[0], fontSize: override[1] || styles[1], textColor: textColor.lightModeColor, backgroundColor: backColor.lightModeColor, textColors: textColor.darkModeColor ? { lightModeColor: textColor.lightModeColor, darkModeColor: textColor.darkModeColor, } : undefined, backgroundColors: backColor.darkModeColor ? { lightModeColor: backColor.lightModeColor, darkModeColor: backColor.darkModeColor, } : undefined, }; } else { var ogTextColorNode = isDarkMode && (override[2] ? pendableFormatSpan : (0, roosterjs_editor_dom_1.findClosestElementAncestor)(node, contentDiv, ORIGINAL_STYLE_COLOR_SELECTOR)); var ogBackgroundColorNode = isDarkMode && (override[3] ? pendableFormatSpan : (0, roosterjs_editor_dom_1.findClosestElementAncestor)(node, contentDiv, ORIGINAL_STYLE_BACK_COLOR_SELECTOR)); return { fontName: override[0] || styles[0], fontSize: override[1] || styles[1], textColor: override[2] || styles[2], backgroundColor: override[3] || styles[3], textColors: ogTextColorNode ? { darkModeColor: override[2] || styles[2], lightModeColor: ogTextColorNode.dataset["ogsc" /* OriginalStyleColor */] || ogTextColorNode.dataset["ogac" /* OriginalAttributeColor */] || styles[2], } : undefined, backgroundColors: ogBackgroundColorNode ? { darkModeColor: override[3] || styles[3], lightModeColor: ogBackgroundColorNode.dataset["ogsb" /* OriginalStyleBackgroundColor */] || ogBackgroundColorNode.dataset["ogab" /* OriginalAttributeBackgroundColor */] || styles[3], } : undefined, }; } }; exports.getStyleBasedFormatState = getStyleBasedFormatState; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/hasFocus.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/hasFocus.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.hasFocus = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Check if the editor has focus now * @param core The EditorCore object * @returns True if the editor has focus, otherwise false */ var hasFocus = function (core) { var activeElement = core.contentDiv.ownerDocument.activeElement; return !!(activeElement && (0, roosterjs_editor_dom_1.contains)(core.contentDiv, activeElement, true /*treatSameNodeAsContain*/)); }; exports.hasFocus = hasFocus; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/insertNode.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/insertNode.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.insertNode = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); function getInitialRange(core, option) { // Selection start replaces based on the current selection. // Range inserts based on a provided range. // Both have the potential to use the current selection to restore cursor position // So in both cases we need to store the selection state. var range = core.api.getSelectionRange(core, true /*tryGetFromCache*/); var rangeToRestore = null; if (option.position == 5 /* Range */) { rangeToRestore = range; range = option.range; } else if (range) { rangeToRestore = range.cloneRange(); } return { range: range, rangeToRestore: rangeToRestore }; } /** * @internal * Insert a DOM node into editor content * @param core The EditorCore object. No op if null. * @param option An insert option object to specify how to insert the node */ var insertNode = function (core, node, option) { var _a; option = option || { position: 3 /* SelectionStart */, insertOnNewLine: false, updateCursor: true, replaceSelection: true, insertToRegionRoot: false, }; var contentDiv = core.contentDiv; if (option.updateCursor) { core.api.focus(core); } if (option.position == 4 /* Outside */) { (_a = contentDiv.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(node, contentDiv.nextSibling); return true; } core.api.transformColor(core, node, true /*includeSelf*/, function () { var _a, _b; if (!option) { return; } switch (option.position) { case 0 /* Begin */: case 1 /* End */: { var isBegin = option.position == 0 /* Begin */; var block = (0, roosterjs_editor_dom_1.getFirstLastBlockElement)(contentDiv, isBegin); var insertedNode_1; if (block) { var refNode = isBegin ? block.getStartNode() : block.getEndNode(); if (option.insertOnNewLine || refNode.nodeType == 3 /* Text */ || (0, roosterjs_editor_dom_1.isVoidHtmlElement)(refNode)) { // For insert on new line, or refNode is text or void html element (HR, BR etc.) // which cannot have children, i.e.
hello
world
. 'hello', 'world' are the // first and last node. Insert before 'hello' or after 'world', but still inside DIV if ((0, roosterjs_editor_dom_1.safeInstanceOf)(node, 'DocumentFragment')) { // if the node to be inserted is DocumentFragment, use its childNodes as insertedNode // because insertBefore() returns an empty DocumentFragment insertedNode_1 = (0, roosterjs_editor_dom_1.toArray)(node.childNodes); (_a = refNode.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(node, isBegin ? refNode : refNode.nextSibling); } else { insertedNode_1 = (_b = refNode.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(node, isBegin ? refNode : refNode.nextSibling); } } else { // if the refNode can have child, use appendChild (which is like to insert as first/last child) // i.e.
hello
, the content will be inserted before/after hello insertedNode_1 = refNode.insertBefore(node, isBegin ? refNode.firstChild : null); } } else { // No first block, this can happen when editor is empty. Use appendChild to insert the content in contentDiv insertedNode_1 = contentDiv.appendChild(node); } // Final check to see if the inserted node is a block. If not block and the ask is to insert on new line, // add a DIV wrapping if (insertedNode_1 && option.insertOnNewLine) { var nodes = Array.isArray(insertedNode_1) ? insertedNode_1 : [insertedNode_1]; if (!(0, roosterjs_editor_dom_1.isBlockElement)(nodes[0]) || !(0, roosterjs_editor_dom_1.isBlockElement)(nodes[nodes.length - 1])) { (0, roosterjs_editor_dom_1.wrap)(nodes); } } break; } case 2 /* DomEnd */: // Use appendChild to insert the node at the end of the content div. var insertedNode = contentDiv.appendChild(node); // Final check to see if the inserted node is a block. If not block and the ask is to insert on new line, // add a DIV wrapping if (insertedNode && option.insertOnNewLine && !(0, roosterjs_editor_dom_1.isBlockElement)(insertedNode)) { (0, roosterjs_editor_dom_1.wrap)(insertedNode); } break; case 5 /* Range */: case 3 /* SelectionStart */: var _c = getInitialRange(core, option), range = _c.range, rangeToRestore = _c.rangeToRestore; if (!range) { return; } // if to replace the selection and the selection is not collapsed, remove the the content at selection first if (option.replaceSelection && !range.collapsed) { range.deleteContents(); } var pos = roosterjs_editor_dom_1.Position.getStart(range); var blockElement = void 0; if (option.insertOnNewLine && option.insertToRegionRoot) { pos = adjustInsertPositionRegionRoot(core, range, pos); } else if (option.insertOnNewLine && (blockElement = (0, roosterjs_editor_dom_1.getBlockElementAtNode)(contentDiv, pos.normalize().node))) { pos = adjustInsertPositionNewLine(blockElement, core, pos); } else { pos = (0, roosterjs_editor_dom_1.adjustInsertPosition)(contentDiv, node, pos, range); } var nodeForCursor = node.nodeType == 11 /* DocumentFragment */ ? node.lastChild : node; range = (0, roosterjs_editor_dom_1.createRange)(pos); range.insertNode(node); if (option.updateCursor && nodeForCursor) { rangeToRestore = (0, roosterjs_editor_dom_1.createRange)(new roosterjs_editor_dom_1.Position(nodeForCursor, -3 /* After */).normalize()); } if (rangeToRestore) { core.api.selectRange(core, rangeToRestore); } break; } }, 0 /* LightToDark */); return true; }; exports.insertNode = insertNode; function adjustInsertPositionRegionRoot(core, range, position) { var region = (0, roosterjs_editor_dom_1.getRegionsFromRange)(core.contentDiv, range, 0 /* Table */)[0]; var node = position.node; if (region) { if (node.nodeType == 3 /* Text */ && !position.isAtEnd) { node = (0, roosterjs_editor_dom_1.splitTextNode)(node, position.offset, true /*returnFirstPart*/); } if (node != region.rootNode) { while (node && node.parentNode != region.rootNode) { (0, roosterjs_editor_dom_1.splitParentNode)(node, false /*splitBefore*/); node = node.parentNode; } } if (node) { position = new roosterjs_editor_dom_1.Position(node, -3 /* After */); } } return position; } function adjustInsertPositionNewLine(blockElement, core, pos) { var tempPos = new roosterjs_editor_dom_1.Position(blockElement.getEndNode(), -3 /* After */); if ((0, roosterjs_editor_dom_1.safeInstanceOf)(tempPos.node, 'HTMLTableRowElement')) { var div = core.contentDiv.ownerDocument.createElement('div'); var range = (0, roosterjs_editor_dom_1.createRange)(pos); range.insertNode(div); tempPos = new roosterjs_editor_dom_1.Position(div, 0 /* Begin */); } return tempPos; } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/restoreUndoSnapshot.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/restoreUndoSnapshot.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.restoreUndoSnapshot = void 0; /** * @internal * Restore an undo snapshot into editor * @param core The editor core object * @param step Steps to move, can be 0, positive or negative */ var restoreUndoSnapshot = function (core, step) { var _a; if (core.undo.hasNewContent && step < 0) { core.api.addUndoSnapshot(core, null /*callback*/, null /*changeSource*/, false /*canUndoByBackspace*/); } var snapshot = core.undo.snapshotsService.move(step); if (snapshot && snapshot.html != null) { try { core.undo.isRestoring = true; core.api.setContent(core, snapshot.html, true /*triggerContentChangedEvent*/, (_a = snapshot.metadata) !== null && _a !== void 0 ? _a : undefined); } finally { core.undo.isRestoring = false; } } }; exports.restoreUndoSnapshot = restoreUndoSnapshot; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/selectImage.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/selectImage.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.selectImage = void 0; var addUniqueId_1 = __webpack_require__(/*! ./utils/addUniqueId */ "./packages/roosterjs-editor-core/lib/coreApi/utils/addUniqueId.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var IMAGE_ID = 'imageSelected'; var CONTENT_DIV_ID = 'contentDiv_'; var STYLE_ID = 'imageStyle'; var DEFAULT_SELECTION_BORDER_COLOR = '#DB626C'; /** * @internal * Select a image and save data of the selected range * @param image Image to select * @returns Selected image information */ var selectImage = function (core, image) { unselect(core); var selection = null; if (image) { var range = (0, roosterjs_editor_dom_1.createRange)(image); (0, addUniqueId_1.default)(image, IMAGE_ID); (0, addUniqueId_1.default)(core.contentDiv, CONTENT_DIV_ID); core.api.selectRange(core, (0, roosterjs_editor_dom_1.createRange)(new roosterjs_editor_dom_1.Position(image, -3 /* After */))); select(core, image); selection = { type: 2 /* ImageSelection */, ranges: [range], image: image, areAllCollapsed: range.collapsed, }; } return selection; }; exports.selectImage = selectImage; var select = function (core, image) { (0, roosterjs_editor_dom_1.removeImportantStyleRule)(image, ['border', 'margin']); var borderCSS = buildBorderCSS(core, image.id); (0, roosterjs_editor_dom_1.setGlobalCssStyles)(core.contentDiv.ownerDocument, borderCSS, STYLE_ID + core.contentDiv.id); }; var buildBorderCSS = function (core, imageId) { var divId = core.contentDiv.id; var color = core.imageSelectionBorderColor || DEFAULT_SELECTION_BORDER_COLOR; return "#" + divId + " #" + imageId + " {outline-style: auto!important;outline-color: " + color + "!important;caret-color: transparent!important;}"; }; var unselect = function (core) { var doc = core.contentDiv.ownerDocument; (0, roosterjs_editor_dom_1.removeGlobalCssStyle)(doc, STYLE_ID + core.contentDiv.id); }; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/selectRange.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/selectRange.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.selectRange = void 0; var hasFocus_1 = __webpack_require__(/*! ./hasFocus */ "./packages/roosterjs-editor-core/lib/coreApi/hasFocus.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Change the editor selection to the given range * @param core The EditorCore object * @param range The range to select * @param skipSameRange When set to true, do nothing if the given range is the same with current selection * in editor, otherwise it will always remove current selection range and set to the given one. * This parameter is always treat as true in Edge to avoid some weird runtime exception. */ var selectRange = function (core, range, skipSameRange) { if (!core.lifecycle.shadowEditSelectionPath && (0, roosterjs_editor_dom_1.contains)(core.contentDiv, range)) { (0, roosterjs_editor_dom_1.addRangeToSelection)(range, skipSameRange); if (!(0, hasFocus_1.hasFocus)(core)) { core.domEvent.selectionRange = range; } if (range.collapsed) { // If selected, and current selection is collapsed, // need to restore pending format state if exists. restorePendingFormatState(core); } return true; } else { return false; } }; exports.selectRange = selectRange; /** * Restore cached pending format state (if exist) to current selection */ function restorePendingFormatState(core) { var contentDiv = core.contentDiv, pendingFormatState = core.pendingFormatState, getSelectionRange = core.api.getSelectionRange; if (pendingFormatState.pendableFormatState) { var document_1 = contentDiv.ownerDocument; var formatState_1 = (0, roosterjs_editor_dom_1.getPendableFormatState)(document_1); (0, roosterjs_editor_dom_1.getObjectKeys)(roosterjs_editor_dom_1.PendableFormatCommandMap).forEach(function (key) { var _a; if (!!((_a = pendingFormatState.pendableFormatState) === null || _a === void 0 ? void 0 : _a[key]) != formatState_1[key]) { document_1.execCommand(roosterjs_editor_dom_1.PendableFormatCommandMap[key], false /* showUI */, undefined /* value */); } }); var range = getSelectionRange(core, true /*tryGetFromCache*/); var position = range && roosterjs_editor_dom_1.Position.getStart(range); if (position) { pendingFormatState.pendableFormatPosition = position; } } } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/selectTable.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/selectTable.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.selectTable = void 0; var addUniqueId_1 = __webpack_require__(/*! ./utils/addUniqueId */ "./packages/roosterjs-editor-core/lib/coreApi/utils/addUniqueId.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var TABLE_ID = 'tableSelected'; var CONTENT_DIV_ID = 'contentDiv_'; var STYLE_ID = 'tableStyle'; /** * @internal * Select a table and save data of the selected range * @param core The EditorCore object * @param table table to select * @param coordinates first and last cell of the selection, if this parameter is null, instead of * selecting, will unselect the table. * @returns true if successful */ var selectTable = function (core, table, coordinates) { var _a; unselect(core); if (areValidCoordinates(coordinates) && table) { (0, addUniqueId_1.default)(table, TABLE_ID); (0, addUniqueId_1.default)(core.contentDiv, CONTENT_DIV_ID); var ranges = select(core, table, coordinates); if (!isMergedCell(table, coordinates)) { var cellToSelect = (_a = table.rows .item(coordinates.firstCell.y)) === null || _a === void 0 ? void 0 : _a.cells.item(coordinates.firstCell.x); if (cellToSelect) { core.api.selectRange(core, (0, roosterjs_editor_dom_1.createRange)(new roosterjs_editor_dom_1.Position(cellToSelect, 0 /* Begin */))); } } return { type: 1 /* TableSelection */, ranges: ranges, table: table, areAllCollapsed: ranges.filter(function (range) { return range === null || range === void 0 ? void 0 : range.collapsed; }).length == ranges.length, coordinates: coordinates, }; } return null; }; exports.selectTable = selectTable; function buildCss(table, coordinates, contentDivSelector) { var _a; var tr1 = coordinates.firstCell.y; var td1 = coordinates.firstCell.x; var tr2 = coordinates.lastCell.y; var td2 = coordinates.lastCell.x; var ranges = []; var firstSelected = null; var lastSelected = null; var selectors = []; var vTable = new roosterjs_editor_dom_1.VTable(table); // Get whether table has thead, tbody or tfoot. var tableChildren = (0, roosterjs_editor_dom_1.toArray)(table.childNodes).filter(function (node) { return ['THEAD', 'TBODY', 'TFOOT'].indexOf((0, roosterjs_editor_dom_1.getTagOfNode)(node)) > -1; }); // Set the start and end of each of the table children, so we can build the selector according the element between the table and the row. var cont = 0; var indexes = tableChildren.map(function (node) { var result = { el: (0, roosterjs_editor_dom_1.getTagOfNode)(node), start: cont, end: node.childNodes.length + cont, }; cont = result.end; return result; }); (_a = vTable.cells) === null || _a === void 0 ? void 0 : _a.forEach(function (row, rowIndex) { var tdCount = 0; firstSelected = null; lastSelected = null; //Get current TBODY/THEAD/TFOOT var midElement = indexes.filter(function (ind) { return ind.start <= rowIndex && ind.end > rowIndex; })[0]; var middleElSelector = midElement ? '>' + midElement.el + '>' : '>'; var currentRow = midElement && rowIndex + 1 >= midElement.start ? rowIndex + 1 - midElement.start : rowIndex + 1; for (var cellIndex = 0; cellIndex < row.length; cellIndex++) { var cell = row[cellIndex].td; if (cell) { var tag = (0, roosterjs_editor_dom_1.getTagOfNode)(cell); tdCount++; if (rowIndex >= tr1 && rowIndex <= tr2 && cellIndex >= td1 && cellIndex <= td2) { removeImportant(cell); var selector = generateCssFromCell(contentDivSelector, table.id, middleElSelector, currentRow, tag, tdCount); var elementsSelector = selector + ' *'; selectors.push(selector); selectors.push(elementsSelector); firstSelected = firstSelected || table.querySelector(selector); lastSelected = table.querySelector(selector); } } } if (firstSelected && lastSelected) { var rowRange = new Range(); rowRange.setStartBefore(firstSelected); rowRange.setEndAfter(lastSelected); ranges.push(rowRange); } }); var css = selectors.join(',') + " {background-color: rgba(198,198,198,0.7) !important; caret-color: transparent}"; return { css: css, ranges: ranges }; } function select(core, table, coordinates) { var contentDivSelector = '#' + core.contentDiv.id; var _a = buildCss(table, coordinates, contentDivSelector), css = _a.css, ranges = _a.ranges; (0, roosterjs_editor_dom_1.setGlobalCssStyles)(core.contentDiv.ownerDocument, css, STYLE_ID + core.contentDiv.id); return ranges; } var unselect = function (core) { var doc = core.contentDiv.ownerDocument; (0, roosterjs_editor_dom_1.removeGlobalCssStyle)(doc, STYLE_ID + core.contentDiv.id); }; function generateCssFromCell(contentDivSelector, tableId, middleElSelector, rowIndex, cellTag, index) { return (contentDivSelector + ' #' + tableId + middleElSelector + ' tr:nth-child(' + rowIndex + ')>' + cellTag + ':nth-child(' + index + ')'); } function removeImportant(cell) { if (cell) { (0, roosterjs_editor_dom_1.removeImportantStyleRule)(cell, ['background-color', 'background']); } } function areValidCoordinates(input) { if (input) { var _a = input || {}, firstCell = _a.firstCell, lastCell = _a.lastCell; if (firstCell && lastCell) { var handler = function (coordinate) { return isValidCoordinate(coordinate.x) && isValidCoordinate(coordinate.y); }; return handler(firstCell) && handler(lastCell); } } return false; } function isValidCoordinate(input) { return (!!input || input == 0) && input > -1; } function isMergedCell(table, coordinates) { var _a; var firstCell = coordinates.firstCell; return !(table.rows.item(firstCell.y) && ((_a = table.rows.item(firstCell.y)) === null || _a === void 0 ? void 0 : _a.cells.item(firstCell.x))); } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/setContent.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/setContent.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setContent = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var roosterjs_editor_dom_2 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Set HTML content to this editor. All existing content will be replaced. A ContentChanged event will be triggered * if triggerContentChangedEvent is set to true * @param core The EditorCore object * @param content HTML content to set in * @param triggerContentChangedEvent True to trigger a ContentChanged event. Default value is true */ var setContent = function (core, content, triggerContentChangedEvent, metadata) { var contentChanged = false; if (core.contentDiv.innerHTML != content) { core.api.triggerEvent(core, { eventType: 20 /* BeforeSetContent */, newContent: content, }, true /*broadcast*/); var metadataFromContent = (0, roosterjs_editor_dom_2.setHtmlWithMetadata)(core.contentDiv, content, core.trustedHTMLHandler); metadata = metadata || metadataFromContent; selectContentMetadata(core, metadata); contentChanged = true; } var isDarkMode = core.lifecycle.isDarkMode; if ((!metadata && isDarkMode) || (metadata && !!metadata.isDarkMode != !!isDarkMode)) { core.api.transformColor(core, core.contentDiv, false /*includeSelf*/, null /*callback*/, isDarkMode ? 0 /* LightToDark */ : 1 /* DarkToLight */, true /*forceTransform*/); contentChanged = true; } if (triggerContentChangedEvent && contentChanged) { core.api.triggerEvent(core, { eventType: 7 /* ContentChanged */, source: "SetContent" /* SetContent */, }, false /*broadcast*/); } }; exports.setContent = setContent; function selectContentMetadata(core, metadata) { if (!core.lifecycle.shadowEditSelectionPath && metadata) { core.domEvent.tableSelectionRange = null; core.domEvent.imageSelectionRange = null; core.domEvent.selectionRange = null; switch (metadata.type) { case 0 /* Normal */: core.api.selectTable(core, null); core.api.selectImage(core, null); var range = (0, roosterjs_editor_dom_1.createRange)(core.contentDiv, metadata.start, metadata.end); core.api.selectRange(core, range); break; case 1 /* TableSelection */: var table = (0, roosterjs_editor_dom_1.queryElements)(core.contentDiv, '#' + metadata.tableId)[0]; if (table) { core.domEvent.tableSelectionRange = core.api.selectTable(core, table, metadata); } break; case 2 /* ImageSelection */: var image = (0, roosterjs_editor_dom_1.queryElements)(core.contentDiv, '#' + metadata.imageId)[0]; if (image) { core.domEvent.imageSelectionRange = core.api.selectImage(core, image); } break; } } } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/switchShadowEdit.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/switchShadowEdit.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.switchShadowEdit = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal */ var switchShadowEdit = function (core, isOn) { var lifecycle = core.lifecycle, contentDiv = core.contentDiv; var shadowEditEntities = lifecycle.shadowEditEntities, shadowEditFragment = lifecycle.shadowEditFragment, shadowEditSelectionPath = lifecycle.shadowEditSelectionPath, shadowEditTableSelectionPath = lifecycle.shadowEditTableSelectionPath, shadowEditImageSelectionPath = lifecycle.shadowEditImageSelectionPath; var wasInShadowEdit = !!shadowEditFragment; var getShadowEditSelectionPath = function (selectionType, shadowEditSelection) { return (((shadowEditSelection === null || shadowEditSelection === void 0 ? void 0 : shadowEditSelection.type) == selectionType && shadowEditSelection.ranges .map(function (range) { return (0, roosterjs_editor_dom_1.getSelectionPath)(contentDiv, range); }) .map(function (w) { return w; })) || null); }; if (isOn) { if (!wasInShadowEdit) { var selection = core.api.getSelectionRangeEx(core); var range = core.api.getSelectionRange(core, true /*tryGetFromCache*/); shadowEditSelectionPath = range && (0, roosterjs_editor_dom_1.getSelectionPath)(contentDiv, range); shadowEditTableSelectionPath = getShadowEditSelectionPath(1 /* TableSelection */, selection); shadowEditImageSelectionPath = getShadowEditSelectionPath(2 /* ImageSelection */, selection); shadowEditEntities = {}; shadowEditFragment = (0, roosterjs_editor_dom_1.moveContentWithEntityPlaceholders)(contentDiv, shadowEditEntities); core.api.triggerEvent(core, { eventType: 17 /* EnteredShadowEdit */, fragment: shadowEditFragment, selectionPath: shadowEditSelectionPath, }, false /*broadcast*/); lifecycle.shadowEditFragment = shadowEditFragment; lifecycle.shadowEditSelectionPath = shadowEditSelectionPath; lifecycle.shadowEditTableSelectionPath = shadowEditTableSelectionPath; lifecycle.shadowEditImageSelectionPath = shadowEditImageSelectionPath; lifecycle.shadowEditEntities = shadowEditEntities; } if (lifecycle.shadowEditFragment) { (0, roosterjs_editor_dom_1.restoreContentWithEntityPlaceholder)(lifecycle.shadowEditFragment, contentDiv, lifecycle.shadowEditEntities, true /*insertClonedNode*/); } } else { lifecycle.shadowEditFragment = null; lifecycle.shadowEditSelectionPath = null; lifecycle.shadowEditEntities = null; if (wasInShadowEdit) { core.api.triggerEvent(core, { eventType: 18 /* LeavingShadowEdit */, }, false /*broadcast*/); if (shadowEditFragment) { (0, roosterjs_editor_dom_1.restoreContentWithEntityPlaceholder)(shadowEditFragment, contentDiv, shadowEditEntities); } core.api.focus(core); if (shadowEditSelectionPath) { core.api.selectRange(core, (0, roosterjs_editor_dom_1.createRange)(contentDiv, shadowEditSelectionPath.start, shadowEditSelectionPath.end)); } if (core.domEvent.imageSelectionRange) { var image = core.domEvent.imageSelectionRange.image; var imageElement = core.contentDiv.querySelector('#' + image.id); if (imageElement) { core.api.selectImage(core, image); } } if (core.domEvent.tableSelectionRange) { var _a = core.domEvent.tableSelectionRange, table = _a.table, coordinates = _a.coordinates; var tableId = table.id; var tableElement = core.contentDiv.querySelector('#' + tableId); if (table) { core.domEvent.tableSelectionRange = core.api.selectTable(core, tableElement, coordinates); } } } } }; exports.switchShadowEdit = switchShadowEdit; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/transformColor.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/transformColor.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformColor = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var ColorAttributeName = [ (_a = {}, _a[0 /* CssColor */] = 'color', _a[1 /* HtmlColor */] = 'color', _a[2 /* CssDataSet */] = "ogsc" /* OriginalStyleColor */, _a[3 /* HtmlDataSet */] = "ogac" /* OriginalAttributeColor */, _a), (_b = {}, _b[0 /* CssColor */] = 'background-color', _b[1 /* HtmlColor */] = 'bgcolor', _b[2 /* CssDataSet */] = "ogsb" /* OriginalStyleBackgroundColor */, _b[3 /* HtmlDataSet */] = "ogab" /* OriginalAttributeBackgroundColor */, _b), ]; /** * @internal * Edit and transform color of elements between light mode and dark mode * @param core The EditorCore object * @param rootNode The root HTML elements to transform * @param includeSelf True to transform the root node as well, otherwise false * @param callback The callback function to invoke before do color transformation * @param direction To specify the transform direction, light to dark, or dark to light * @param forceTransform By default this function will only work when editor core is in dark mode. * Pass true to this value to force do color transformation even editor core is in light mode */ var transformColor = function (core, rootNode, includeSelf, callback, direction, forceTransform) { var darkColorHandler = core.darkColorHandler; var elements = rootNode && (forceTransform || core.lifecycle.isDarkMode) ? getAll(rootNode, includeSelf) : []; callback === null || callback === void 0 ? void 0 : callback(); if (darkColorHandler) { transformV2(elements, darkColorHandler, direction == 0 /* LightToDark */); } else { if (direction == 1 /* DarkToLight */) { transformToLightMode(elements); } else if (core.lifecycle.onExternalContentTransform) { elements.forEach(function (element) { return core.lifecycle.onExternalContentTransform(element); }); } else { transformToDarkMode(elements, core.lifecycle.getDarkColor); } } }; exports.transformColor = transformColor; function transformV2(elements, darkColorHandler, toDark) { elements.forEach(function (element) { ColorAttributeName.forEach(function (names, i) { var color = darkColorHandler.parseColorValue(element.style.getPropertyValue(names[0 /* CssColor */]) || element.getAttribute(names[1 /* HtmlColor */])).lightModeColor; if (color && color != 'inherit') { (0, roosterjs_editor_dom_1.setColor)(element, color, i != 0, toDark, false /*shouldAdaptFontColor*/, darkColorHandler); } }); }); } function transformToLightMode(elements) { elements.forEach(function (element) { ColorAttributeName.forEach(function (names) { // Reset color styles based on the content of the ogsc/ogsb data element. // If those data properties are empty or do not exist, set them anyway to clear the content. element.style.setProperty(names[0 /* CssColor */], getValueOrDefault(element.dataset[names[2 /* CssDataSet */]], '')); delete element.dataset[names[2 /* CssDataSet */]]; // Some elements might have set attribute colors. We need to reset these as well. var value = getValueOrDefault(element.dataset[names[3 /* HtmlDataSet */]], null); if (value) { element.setAttribute(names[1 /* HtmlColor */], value); } else { element.removeAttribute(names[1 /* HtmlColor */]); } delete element.dataset[names[3 /* HtmlDataSet */]]; }); }); } function transformToDarkMode(elements, getDarkColor) { ColorAttributeName.forEach(function (names) { elements .map(function (element) { var styleColor = element.style.getPropertyValue(names[0 /* CssColor */]); var attrColor = element.getAttribute(names[1 /* HtmlColor */]); var existingDataSetCssValue = element.dataset[names[2 /* CssDataSet */]]; var existingDataSetHtmlValue = element.dataset[names[3 /* HtmlDataSet */]]; var needProcess = (!existingDataSetCssValue || existingDataSetCssValue == styleColor) && (!existingDataSetHtmlValue || existingDataSetHtmlValue == attrColor) && (styleColor || attrColor) && styleColor != 'inherit'; // For inherit style, no need to change it and let it keep inherit from parent element return needProcess ? { element: element, styleColor: styleColor, attrColor: attrColor, newColor: styleColor || attrColor ? getDarkColor((styleColor || attrColor)) : null, } : null; }) .filter(function (x) { return !!x; }) .forEach(function (entry) { if (!entry) { return; } var element = entry.element, styleColor = entry.styleColor, attrColor = entry.attrColor, newColor = entry.newColor; element.style.setProperty(names[0 /* CssColor */], newColor, 'important'); element.dataset[names[2 /* CssDataSet */]] = styleColor || ''; if (attrColor && newColor) { element.setAttribute(names[1 /* HtmlColor */], newColor); element.dataset[names[3 /* HtmlDataSet */]] = attrColor; } }); }); } function getValueOrDefault(value, defaultValue) { return value && value != 'undefined' && value != 'null' ? value : defaultValue; } function getAll(rootNode, includeSelf) { var result = []; if ((0, roosterjs_editor_dom_1.safeInstanceOf)(rootNode, 'HTMLElement')) { if (includeSelf) { result.push(rootNode); } var allChildren = rootNode.getElementsByTagName('*'); (0, roosterjs_editor_dom_1.arrayPush)(result, (0, roosterjs_editor_dom_1.toArray)(allChildren)); } else if ((0, roosterjs_editor_dom_1.safeInstanceOf)(rootNode, 'DocumentFragment')) { var allChildren = rootNode.querySelectorAll('*'); (0, roosterjs_editor_dom_1.arrayPush)(result, (0, roosterjs_editor_dom_1.toArray)(allChildren)); } return result.filter(isHTMLElement); } // This is not a strict check, we just need to make sure this element has style so that we can set style to it // We don't use safeInstanceOf() here since this function will be called very frequently when extract html content // in dark mode, so we need to make sure this check is fast enough function isHTMLElement(element) { var htmlElement = element; return !!htmlElement.style && !!htmlElement.dataset; } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/triggerEvent.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/triggerEvent.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.triggerEvent = void 0; var allowedEventsInShadowEdit = [ 11 /* EditorReady */, 12 /* BeforeDispose */, 8 /* ExtractContentWithDom */, 21 /* ZoomChanged */, ]; /** * @internal * Trigger a plugin event * @param core The EditorCore object * @param pluginEvent The event object to trigger * @param broadcast Set to true to skip the shouldHandleEventExclusively check */ var triggerEvent = function (core, pluginEvent, broadcast) { if ((!core.lifecycle.shadowEditFragment || allowedEventsInShadowEdit.indexOf(pluginEvent.eventType) >= 0) && (broadcast || !core.plugins.some(function (plugin) { return handledExclusively(pluginEvent, plugin); }))) { core.plugins.forEach(function (plugin) { if (plugin.onPluginEvent) { plugin.onPluginEvent(pluginEvent); } }); } }; exports.triggerEvent = triggerEvent; function handledExclusively(event, plugin) { var _a; if (plugin.onPluginEvent && ((_a = plugin.willHandleEventExclusively) === null || _a === void 0 ? void 0 : _a.call(plugin, event))) { plugin.onPluginEvent(event); return true; } return false; } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/coreApi/utils/addUniqueId.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/coreApi/utils/addUniqueId.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Add an unique id to element and ensure that is unique * @param el The HTMLElement that will receive the id * @param idPrefix The prefix that will antecede the id (Ex: tableSelected01) */ function addUniqueId(el, idPrefix) { var doc = el.ownerDocument; if (!el.id) { applyId(el, idPrefix, doc); } else { var elements = doc.querySelectorAll("#" + el.id); if (elements.length > 1) { el.removeAttribute('id'); applyId(el, idPrefix, doc); } } } exports.default = addUniqueId; function applyId(el, idPrefix, doc) { var cont = 0; var getElement = function () { return doc.getElementById(idPrefix + cont); }; //Ensure that there are no elements with the same ID var element = getElement(); while (element) { cont++; element = getElement(); } el.id = idPrefix + cont; } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/CopyPastePlugin.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/CopyPastePlugin.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var forEachSelectedCell_1 = __webpack_require__(/*! ./utils/forEachSelectedCell */ "./packages/roosterjs-editor-core/lib/corePlugins/utils/forEachSelectedCell.ts"); var removeCellsOutsideSelection_1 = __webpack_require__(/*! ./utils/removeCellsOutsideSelection */ "./packages/roosterjs-editor-core/lib/corePlugins/utils/removeCellsOutsideSelection.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Copy and paste plugin for handling onCopy and onPaste event */ var CopyPastePlugin = /** @class */ (function () { /** * Construct a new instance of CopyPastePlugin * @param options The editor options */ function CopyPastePlugin(options) { var _this = this; this.editor = null; this.disposer = null; this.onPaste = function (event) { var _a; var range = null; if (_this.editor) { var editor_1 = _this.editor; (0, roosterjs_editor_dom_1.extractClipboardEvent)(event, function (clipboardData) { if (editor_1 && !editor_1.isDisposed()) { editor_1.paste(clipboardData); } }, { allowedCustomPasteType: _this.state.allowedCustomPasteType, getTempDiv: function () { var _a; range = (_a = editor_1.getSelectionRange()) !== null && _a !== void 0 ? _a : null; return _this.getTempDiv(editor_1); }, removeTempDiv: function (div) { if (range) { _this.cleanUpAndRestoreSelection(div, range, false /* isCopy */); } }, }, (_a = _this.editor.getSelectionRange()) !== null && _a !== void 0 ? _a : undefined); } }; this.state = { allowedCustomPasteType: options.allowedCustomPasteType || [], }; } /** * Get a friendly name of this plugin */ CopyPastePlugin.prototype.getName = function () { return 'CopyPaste'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ CopyPastePlugin.prototype.initialize = function (editor) { var _this = this; this.editor = editor; this.disposer = this.editor.addDomEventHandler({ paste: function (e) { return _this.onPaste(e); }, copy: function (e) { return _this.onCutCopy(e, false /*isCut*/); }, cut: function (e) { return _this.onCutCopy(e, true /*isCut*/); }, }); }; /** * Dispose this plugin */ CopyPastePlugin.prototype.dispose = function () { if (this.disposer) { this.disposer(); } this.disposer = null; this.editor = null; }; /** * Get plugin state object */ CopyPastePlugin.prototype.getState = function () { return this.state; }; CopyPastePlugin.prototype.onCutCopy = function (event, isCut) { var _this = this; if (this.editor) { var selection_1 = this.editor.getSelectionRangeEx(); if (selection_1 && !selection_1.areAllCollapsed) { var html = this.editor.getContent(2 /* RawHTMLWithSelection */); var tempDiv_1 = this.getTempDiv(this.editor, true /*forceInLightMode*/); var metadata = (0, roosterjs_editor_dom_1.setHtmlWithMetadata)(tempDiv_1, html, this.editor.getTrustedHTMLHandler()); var newRange = null; if (selection_1.type === 1 /* TableSelection */ && selection_1.coordinates) { var table = tempDiv_1.querySelector("#" + selection_1.table.id); newRange = this.createTableRange(table, selection_1.coordinates); if (isCut) { this.deleteTableContent(this.editor, selection_1.table, selection_1.coordinates); } } else if (selection_1.type === 2 /* ImageSelection */) { var image = tempDiv_1.querySelector('#' + selection_1.image.id); if (image) { newRange = (0, roosterjs_editor_dom_1.createRange)(image); if (isCut) { this.deleteImage(this.editor, selection_1.image.id); } } } else { newRange = (metadata === null || metadata === void 0 ? void 0 : metadata.type) === 0 /* Normal */ ? (0, roosterjs_editor_dom_1.createRange)(tempDiv_1, metadata.start, metadata.end) : null; } if (newRange) { var cutCopyEvent = this.editor.triggerPluginEvent(9 /* BeforeCutCopy */, { clonedRoot: tempDiv_1, range: newRange, rawEvent: event, isCut: isCut, }); if (cutCopyEvent.range) { (0, roosterjs_editor_dom_1.addRangeToSelection)(newRange); } this.editor.runAsync(function (editor) { _this.cleanUpAndRestoreSelection(tempDiv_1, selection_1, !isCut /* isCopy */); if (isCut) { editor.addUndoSnapshot(function () { var position = editor.deleteSelectedContent(); editor.focus(); editor.select(position); }, "Cut" /* Cut */); } }); } } } }; CopyPastePlugin.prototype.getTempDiv = function (editor, forceInLightMode) { var div = editor.getCustomData('CopyPasteTempDiv', function () { var tempDiv = (0, roosterjs_editor_dom_1.createElement)(3 /* CopyPasteTempDiv */, editor.getDocument()); editor.getDocument().body.appendChild(tempDiv); return tempDiv; }, function (tempDiv) { var _a; return (_a = tempDiv.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(tempDiv); }); if (forceInLightMode) { div.style.backgroundColor = 'white'; div.style.color = 'black'; } div.style.display = ''; div.focus(); return div; }; CopyPastePlugin.prototype.cleanUpAndRestoreSelection = function (tempDiv, range, isCopy) { var _a, _b, _c; if (!!((_a = range) === null || _a === void 0 ? void 0 : _a.type) || range.type == 0) { var selection = range; switch (selection.type) { case 1 /* TableSelection */: case 2 /* ImageSelection */: (_b = this.editor) === null || _b === void 0 ? void 0 : _b.select(selection); break; case 0 /* Normal */: var range_1 = (_c = selection.ranges) === null || _c === void 0 ? void 0 : _c[0]; this.restoreRange(range_1, isCopy); break; } } else { this.restoreRange(range, isCopy); } tempDiv.style.backgroundColor = ''; tempDiv.style.color = ''; tempDiv.style.display = 'none'; (0, roosterjs_editor_dom_1.moveChildNodes)(tempDiv); }; CopyPastePlugin.prototype.restoreRange = function (range, isCopy) { if (range && this.editor) { if (isCopy && roosterjs_editor_dom_1.Browser.isAndroid) { range.collapse(); } this.editor.select(range); } }; CopyPastePlugin.prototype.createTableRange = function (table, selection) { var clonedVTable = new roosterjs_editor_dom_1.VTable(table); clonedVTable.selection = selection; (0, removeCellsOutsideSelection_1.removeCellsOutsideSelection)(clonedVTable); clonedVTable.writeBack(); return (0, roosterjs_editor_dom_1.createRange)(clonedVTable.table); }; CopyPastePlugin.prototype.deleteTableContent = function (editor, table, selection) { var selectedVTable = new roosterjs_editor_dom_1.VTable(table); selectedVTable.selection = selection; (0, forEachSelectedCell_1.forEachSelectedCell)(selectedVTable, function (cell) { if (cell === null || cell === void 0 ? void 0 : cell.td) { cell.td.innerHTML = editor.getTrustedHTMLHandler()('
'); } }); var wholeTableSelected = (0, roosterjs_editor_dom_1.isWholeTableSelected)(selectedVTable, selection); var isWholeColumnSelected = table.rows.length - 1 === selection.lastCell.y && selection.firstCell.y === 0; if (wholeTableSelected) { selectedVTable.edit(4 /* DeleteTable */); selectedVTable.writeBack(); } else if (isWholeColumnSelected) { selectedVTable.edit(5 /* DeleteColumn */); selectedVTable.writeBack(); } if (wholeTableSelected || isWholeColumnSelected) { table.style.removeProperty('width'); table.style.removeProperty('height'); } }; CopyPastePlugin.prototype.deleteImage = function (editor, imageId) { editor.queryElements('#' + imageId, function (node) { editor.deleteNode(node); }); }; return CopyPastePlugin; }()); exports.default = CopyPastePlugin; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/DOMEventPlugin.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/DOMEventPlugin.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * DOMEventPlugin handles customized DOM events, including: * 1. Keyboard event * 2. Mouse event * 3. IME state * 4. Drop event * 5. Focus and blur event * 6. Input event * 7. Scroll event * It contains special handling for Safari since Safari cannot get correct selection when onBlur event is triggered in editor. */ var DOMEventPlugin = /** @class */ (function () { /** * Construct a new instance of DOMEventPlugin * @param options The editor options * @param contentDiv The editor content DIV */ function DOMEventPlugin(options, contentDiv) { var _this = this; var _a; this.editor = null; this.disposer = null; this.onDrop = function () { var _a; (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.runAsync(function (editor) { editor.addUndoSnapshot(function () { }, "Drop" /* Drop */); }); }; this.onFocus = function () { var _a, _b, _c; var _d = _this.state.tableSelectionRange || {}, table = _d.table, coordinates = _d.coordinates; var image = (_this.state.imageSelectionRange || {}).image; if (table && coordinates) { (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.select(table, coordinates); } else if (image) { (_b = _this.editor) === null || _b === void 0 ? void 0 : _b.select(image); } else if (_this.state.selectionRange) { (_c = _this.editor) === null || _c === void 0 ? void 0 : _c.select(_this.state.selectionRange); } _this.state.selectionRange = null; }; this.onKeyDownDocument = function (event) { if (event.which == 9 /* TAB */ && !event.defaultPrevented) { _this.cacheSelection(); } }; this.onMouseDownDocument = function (event) { if (_this.editor && !_this.state.selectionRange && !_this.editor.contains(event.target)) { _this.cacheSelection(); } }; this.cacheSelection = function () { if (!_this.state.selectionRange && _this.editor) { _this.state.selectionRange = _this.editor.getSelectionRange(false /*tryGetFromCache*/); } }; this.onScroll = function (e) { var _a; (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.triggerPluginEvent(14 /* Scroll */, { rawEvent: e, scrollContainer: _this.state.scrollContainer, }); }; this.onKeyboardEvent = function (event) { if ((0, roosterjs_editor_dom_1.isCharacterValue)(event) || (event.which >= 33 /* PAGEUP */ && event.which <= 40 /* DOWN */)) { // Stop propagation for Character keys and Up/Down/Left/Right/Home/End/PageUp/PageDown // since editor already handles these keys and no need to propagate to parents event.stopPropagation(); } }; this.onInputEvent = function (event) { event.stopPropagation(); }; this.onContextMenuEvent = function (event) { var _a, _b; var allItems = []; var searcher = (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.getContentSearcherOfCursor(); var elementBeforeCursor = searcher === null || searcher === void 0 ? void 0 : searcher.getInlineElementBefore(); var eventTargetNode = event.target; if (event.button != 2 && elementBeforeCursor) { eventTargetNode = elementBeforeCursor.getContainerNode(); } _this.state.contextMenuProviders.forEach(function (provider) { var _a; var items = (_a = provider.getContextMenuItems(eventTargetNode)) !== null && _a !== void 0 ? _a : []; if ((items === null || items === void 0 ? void 0 : items.length) > 0) { if (allItems.length > 0) { allItems.push(null); } (0, roosterjs_editor_dom_1.arrayPush)(allItems, items); } }); (_b = _this.editor) === null || _b === void 0 ? void 0 : _b.triggerPluginEvent(16 /* ContextMenu */, { rawEvent: event, items: allItems, }); }; this.state = { isInIME: false, scrollContainer: options.scrollContainer || contentDiv, selectionRange: null, stopPrintableKeyboardEventPropagation: !options.allowKeyboardEventPropagation, contextMenuProviders: ((_a = options.plugins) === null || _a === void 0 ? void 0 : _a.filter(isContextMenuProvider)) || [], tableSelectionRange: null, imageSelectionRange: null, }; } /** * Get a friendly name of this plugin */ DOMEventPlugin.prototype.getName = function () { return 'DOMEvent'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ DOMEventPlugin.prototype.initialize = function (editor) { var _a; var _this = this; var _b, _c, _d; this.editor = editor; var document = this.editor.getDocument(); //Record var eventHandlers = (_a = { // 1. Keyboard event keypress: this.getEventHandler(1 /* KeyPress */), keydown: this.getEventHandler(0 /* KeyDown */), keyup: this.getEventHandler(2 /* KeyUp */), // 2. Mouse event mousedown: 5 /* MouseDown */, contextmenu: this.onContextMenuEvent, // 3. IME state management compositionstart: function () { return (_this.state.isInIME = true); }, compositionend: function (rawEvent) { _this.state.isInIME = false; editor.triggerPluginEvent(4 /* CompositionEnd */, { rawEvent: rawEvent, }); }, // 4. Drop event drop: this.onDrop, // 5. Focus management focus: this.onFocus }, // 6. Input event _a[roosterjs_editor_dom_1.Browser.isIE ? 'textinput' : 'input'] = this.getEventHandler(3 /* Input */), _a); // 7. onBlur handlers if (roosterjs_editor_dom_1.Browser.isSafari) { document.addEventListener('mousedown', this.onMouseDownDocument, true /*useCapture*/); document.addEventListener('keydown', this.onKeyDownDocument); (_b = document.defaultView) === null || _b === void 0 ? void 0 : _b.addEventListener('blur', this.cacheSelection); } else if (roosterjs_editor_dom_1.Browser.isIEOrEdge) { eventHandlers.beforedeactivate = this.cacheSelection; } else { eventHandlers.blur = this.cacheSelection; } this.disposer = editor.addDomEventHandler(eventHandlers); // 8. Scroll event this.state.scrollContainer.addEventListener('scroll', this.onScroll); (_c = document.defaultView) === null || _c === void 0 ? void 0 : _c.addEventListener('scroll', this.onScroll); (_d = document.defaultView) === null || _d === void 0 ? void 0 : _d.addEventListener('resize', this.onScroll); }; /** * Dispose this plugin */ DOMEventPlugin.prototype.dispose = function () { var _a, _b, _c, _d, _e; var document = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDocument(); if (document && roosterjs_editor_dom_1.Browser.isSafari) { document.removeEventListener('mousedown', this.onMouseDownDocument, true /*useCapture*/); document.removeEventListener('keydown', this.onKeyDownDocument); (_b = document.defaultView) === null || _b === void 0 ? void 0 : _b.removeEventListener('blur', this.cacheSelection); } (_c = document === null || document === void 0 ? void 0 : document.defaultView) === null || _c === void 0 ? void 0 : _c.removeEventListener('resize', this.onScroll); (_d = document === null || document === void 0 ? void 0 : document.defaultView) === null || _d === void 0 ? void 0 : _d.removeEventListener('scroll', this.onScroll); this.state.scrollContainer.removeEventListener('scroll', this.onScroll); (_e = this.disposer) === null || _e === void 0 ? void 0 : _e.call(this); this.disposer = null; this.editor = null; }; /** * Get plugin state object */ DOMEventPlugin.prototype.getState = function () { return this.state; }; DOMEventPlugin.prototype.getEventHandler = function (eventType) { var _this = this; var beforeDispatch = function (event) { return eventType == 3 /* Input */ ? _this.onInputEvent(event) : _this.onKeyboardEvent(event); }; return this.state.stopPrintableKeyboardEventPropagation ? { pluginEventType: eventType, beforeDispatch: beforeDispatch, } : eventType; }; return DOMEventPlugin; }()); exports.default = DOMEventPlugin; function isContextMenuProvider(source) { var _a; return !!((_a = source) === null || _a === void 0 ? void 0 : _a.getContextMenuItems); } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/EditPlugin.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/EditPlugin.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Edit Component helps handle Content edit features */ var EditPlugin = /** @class */ (function () { /** * Construct a new instance of EditPlugin * @param options The editor options */ function EditPlugin() { this.editor = null; this.state = { features: {}, }; } /** * Get a friendly name of this plugin */ EditPlugin.prototype.getName = function () { return 'Edit'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ EditPlugin.prototype.initialize = function (editor) { this.editor = editor; }; /** * Dispose this plugin */ EditPlugin.prototype.dispose = function () { this.editor = null; }; /** * Get plugin state object */ EditPlugin.prototype.getState = function () { return this.state; }; /** * Handle events triggered from editor * @param event PluginEvent object */ EditPlugin.prototype.onPluginEvent = function (event) { var _a; var hasFunctionKey = false; var features = null; var ctrlOrMeta = false; if (event.eventType == 0 /* KeyDown */) { var rawEvent = event.rawEvent; var range = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getSelectionRange(); ctrlOrMeta = (0, roosterjs_editor_dom_1.isCtrlOrMetaPressed)(rawEvent); hasFunctionKey = ctrlOrMeta || rawEvent.altKey; features = this.state.features[rawEvent.which] || (range && !range.collapsed && this.state.features[258 /* RANGE */]); } else if (event.eventType == 7 /* ContentChanged */) { features = this.state.features[257 /* CONTENTCHANGED */]; } for (var i = 0; features && i < (features === null || features === void 0 ? void 0 : features.length); i++) { var feature = features[i]; if ((feature.allowFunctionKeys || !hasFunctionKey) && this.editor && feature.shouldHandleEvent(event, this.editor, ctrlOrMeta)) { feature.handleEvent(event, this.editor); break; } } }; return EditPlugin; }()); exports.default = EditPlugin; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/EntityPlugin.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/EntityPlugin.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var ENTITY_ID_REGEX = /_(\d{1,8})$/; var ENTITY_CSS_REGEX = '^' + "_Entity" /* ENTITY_INFO_NAME */ + '$'; var ENTITY_ID_CSS_REGEX = '^' + "_EId_" /* ENTITY_ID_PREFIX */; var ENTITY_TYPE_CSS_REGEX = '^' + "_EType_" /* ENTITY_TYPE_PREFIX */; var ENTITY_READONLY_CSS_REGEX = '^' + "_EReadonly_" /* ENTITY_READONLY_PREFIX */; var ALLOWED_CSS_CLASSES = [ ENTITY_CSS_REGEX, ENTITY_ID_CSS_REGEX, ENTITY_TYPE_CSS_REGEX, ENTITY_READONLY_CSS_REGEX, ]; var REMOVE_ENTITY_OPERATIONS = [ 6 /* Overwrite */, 7 /* PartialOverwrite */, 4 /* RemoveFromStart */, 5 /* RemoveFromEnd */, ]; /** * @internal * Entity Plugin helps handle all operations related to an entity and generate entity specified events */ var EntityPlugin = /** @class */ (function () { /** * Construct a new instance of EntityPlugin */ function EntityPlugin() { var _this = this; this.editor = null; this.cancelAsyncRun = null; this.handleCutEvent = function (event) { var _a; var range = (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.getSelectionRange(); if (range && !range.collapsed) { _this.checkRemoveEntityForRange(event); } }; this.state = { knownEntityElements: [], shadowEntityCache: {}, }; } /** * Get a friendly name of this plugin */ EntityPlugin.prototype.getName = function () { return 'Entity'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ EntityPlugin.prototype.initialize = function (editor) { this.editor = editor; }; /** * Check if the plugin should handle the given event exclusively. * Handle an event exclusively means other plugin will not receive this event in * onPluginEvent method. * If two plugins will return true in willHandleEventExclusively() for the same event, * the final result depends on the order of the plugins are added into editor * @param event The event to check */ EntityPlugin.prototype.willHandleEventExclusively = function (event) { var _a; return (event.eventType == 1 /* KeyPress */ && !!((_a = event.rawEvent.target) === null || _a === void 0 ? void 0 : _a.shadowRoot)); }; /** * Dispose this plugin */ EntityPlugin.prototype.dispose = function () { this.editor = null; this.state.knownEntityElements = []; }; /** * Get plugin state object */ EntityPlugin.prototype.getState = function () { return this.state; }; /** * Handle events triggered from editor * @param event PluginEvent object */ EntityPlugin.prototype.onPluginEvent = function (event) { switch (event.eventType) { case 6 /* MouseUp */: this.handleMouseUpEvent(event); break; case 0 /* KeyDown */: this.handleKeyDownEvent(event.rawEvent); break; case 9 /* BeforeCutCopy */: if (event.isCut) { this.handleCutEvent(event.rawEvent); } break; case 10 /* BeforePaste */: this.handleBeforePasteEvent(event.sanitizingOption); break; case 7 /* ContentChanged */: this.handleContentChangedEvent(event); break; case 11 /* EditorReady */: this.handleContentChangedEvent(); break; case 8 /* ExtractContentWithDom */: this.handleExtractContentWithDomEvent(event.clonedRoot); break; case 16 /* ContextMenu */: this.handleContextMenuEvent(event.rawEvent); break; case 20 /* BeforeSetContent */: this.handleBeforeSetContentEvent(); break; case 15 /* EntityOperation */: this.handleEntityOperationEvent(event); break; } }; EntityPlugin.prototype.handleContextMenuEvent = function (event) { var _a; var node = event.target; var entityElement = node && ((_a = this.editor) === null || _a === void 0 ? void 0 : _a.getElementAtCursor((0, roosterjs_editor_dom_1.getEntitySelector)(), node)); if (entityElement) { event.preventDefault(); this.triggerEvent(entityElement, 2 /* ContextMenu */, event); } }; EntityPlugin.prototype.handleMouseUpEvent = function (event) { var rawEvent = event.rawEvent, isClicking = event.isClicking; var node = rawEvent.target; var entityElement; if (this.editor && isClicking && node && !!(entityElement = this.editor.getElementAtCursor((0, roosterjs_editor_dom_1.getEntitySelector)(), node))) { this.triggerEvent(entityElement, 1 /* Click */, rawEvent); workaroundSelectionIssueForIE(this.editor); } }; EntityPlugin.prototype.handleKeyDownEvent = function (event) { var _a; if ((0, roosterjs_editor_dom_1.isCharacterValue)(event) || event.which == 8 /* BACKSPACE */ || event.which == 46 /* DELETE */ || event.which == 13 /* ENTER */) { var range = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getSelectionRange(); if (range && !range.collapsed) { this.checkRemoveEntityForRange(event); } } }; EntityPlugin.prototype.handleBeforePasteEvent = function (sanitizingOption) { var _a; var range = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getSelectionRange(); if (range && !range.collapsed) { this.checkRemoveEntityForRange(null /*rawEvent*/); } if (sanitizingOption.additionalAllowedCssClasses) { (0, roosterjs_editor_dom_1.arrayPush)(sanitizingOption.additionalAllowedCssClasses, ALLOWED_CSS_CLASSES); } }; EntityPlugin.prototype.handleBeforeSetContentEvent = function () { this.cacheShadowEntities(this.state.shadowEntityCache); }; EntityPlugin.prototype.handleContentChangedEvent = function (event) { var _this = this; // 1. find removed entities for (var i = this.state.knownEntityElements.length - 1; i >= 0; i--) { var element = this.state.knownEntityElements[i]; if (this.editor && !this.editor.contains(element)) { this.setIsEntityKnown(element, false /*isKnown*/); if (element.shadowRoot) { this.triggerEvent(element, 10 /* RemoveShadowRoot */); } } } // 2. collect all new entities var knownIds = this.state.knownEntityElements .map(function (e) { var _a; return (_a = (0, roosterjs_editor_dom_1.getEntityFromElement)(e)) === null || _a === void 0 ? void 0 : _a.id; }) .filter(function (x) { return !!x; }); var newEntities = (event === null || event === void 0 ? void 0 : event.source) == "InsertEntity" /* InsertEntity */ && event.data ? [event.data] : this.getExistingEntities().filter(function (_a) { var wrapper = _a.wrapper; return !_this.isEntityKnown(wrapper); }); // 3. Add new entities to known entity list, and hydrate newEntities.forEach(function (entity) { var wrapper = entity.wrapper, type = entity.type, id = entity.id, isReadonly = entity.isReadonly; entity.id = _this.ensureUniqueId(type, id, knownIds); (0, roosterjs_editor_dom_1.commitEntity)(wrapper, type, isReadonly, entity.id); // Use entity.id here because it is newly updated _this.handleNewEntity(entity); }); (0, roosterjs_editor_dom_1.getObjectKeys)(this.state.shadowEntityCache).forEach(function (id) { _this.triggerEvent(_this.state.shadowEntityCache[id], 6 /* Overwrite */); delete _this.state.shadowEntityCache[id]; }); }; EntityPlugin.prototype.handleEntityOperationEvent = function (event) { var _this = this; var _a; if (this.editor && REMOVE_ENTITY_OPERATIONS.indexOf(event.operation) >= 0) { (_a = this.cancelAsyncRun) === null || _a === void 0 ? void 0 : _a.call(this); this.cancelAsyncRun = this.editor.runAsync(function () { _this.cancelAsyncRun = null; _this.handleContentChangedEvent(); }); } }; EntityPlugin.prototype.handleExtractContentWithDomEvent = function (root) { var _this = this; (0, roosterjs_editor_dom_1.toArray)(root.querySelectorAll((0, roosterjs_editor_dom_1.getEntitySelector)())).forEach(function (element) { element.removeAttribute('contentEditable'); _this.triggerEvent(element, 8 /* ReplaceTemporaryContent */); }); }; EntityPlugin.prototype.checkRemoveEntityForRange = function (event) { var _this = this; var _a; var editableEntityElements = []; var selector = (0, roosterjs_editor_dom_1.getEntitySelector)(); (_a = this.editor) === null || _a === void 0 ? void 0 : _a.queryElements(selector, 1 /* OnSelection */, function (element) { if (element.isContentEditable) { editableEntityElements.push(element); } else { _this.triggerEvent(element, 6 /* Overwrite */, event); } }); // For editable entities, we need to check if it is fully or partially covered by current selection, // and trigger different events; if (this.editor && editableEntityElements.length > 0) { var inSelectionEntityElements_1 = this.editor.queryElements(selector, 2 /* InSelection */); editableEntityElements.forEach(function (element) { var isFullyCovered = inSelectionEntityElements_1.indexOf(element) >= 0; _this.triggerEvent(element, isFullyCovered ? 6 /* Overwrite */ : 7 /* PartialOverwrite */, event); }); } }; EntityPlugin.prototype.triggerEvent = function (element, operation, rawEvent, contentForShadowEntity) { var _a; var entity = element && (0, roosterjs_editor_dom_1.getEntityFromElement)(element); if (entity) { (_a = this.editor) === null || _a === void 0 ? void 0 : _a.triggerPluginEvent(15 /* EntityOperation */, { operation: operation, rawEvent: rawEvent, entity: entity, contentForShadowEntity: contentForShadowEntity, }); } }; EntityPlugin.prototype.handleNewEntity = function (entity) { var _a, _b; var wrapper = entity.wrapper; var fragment = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDocument().createDocumentFragment(); var cache = this.state.shadowEntityCache[entity.id]; delete this.state.shadowEntityCache[entity.id]; if (fragment && (cache === null || cache === void 0 ? void 0 : cache.shadowRoot)) { (0, roosterjs_editor_dom_1.moveChildNodes)(fragment, cache.shadowRoot); } this.triggerEvent(wrapper, 0 /* NewEntity */, undefined /*rawEvent*/, fragment); // If there is element to hydrate for shadow entity, create shadow root and mount these elements to shadow root // Then trigger AddShadowRoot so that plugins can do further actions if (fragment === null || fragment === void 0 ? void 0 : fragment.firstChild) { if (wrapper.shadowRoot) { (0, roosterjs_editor_dom_1.moveChildNodes)(wrapper.shadowRoot, fragment); } else { this.createShadowRoot(wrapper, fragment); } } else if (wrapper.shadowRoot) { // If no elements to hydrate, remove existing shadow root by cloning a new node this.triggerEvent(wrapper, 10 /* RemoveShadowRoot */); var newWrapper = wrapper.cloneNode(); (0, roosterjs_editor_dom_1.moveChildNodes)(newWrapper, wrapper); (_b = this.editor) === null || _b === void 0 ? void 0 : _b.replaceNode(wrapper, newWrapper); entity.wrapper = newWrapper; } this.setIsEntityKnown(entity.wrapper, true /*isKnown*/); }; EntityPlugin.prototype.getExistingEntities = function (shadowEntityOnly) { var _a, _b; return ((_b = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.queryElements((0, roosterjs_editor_dom_1.getEntitySelector)()).map(roosterjs_editor_dom_1.getEntityFromElement).filter(function (x) { return !!x && (!shadowEntityOnly || !!x.wrapper.shadowRoot); })) !== null && _b !== void 0 ? _b : []); }; EntityPlugin.prototype.createShadowRoot = function (wrapper, shadowContentContainer) { if (wrapper.attachShadow) { var shadowRoot = wrapper.attachShadow({ mode: 'open', delegatesFocus: true, }); wrapper.contentEditable = 'false'; this.triggerEvent(wrapper, 9 /* AddShadowRoot */); (0, roosterjs_editor_dom_1.moveChildNodes)(shadowRoot, shadowContentContainer); return shadowRoot; } }; EntityPlugin.prototype.cacheShadowEntities = function (cache) { this.getExistingEntities(true /*shadowEntityOnly*/).forEach(function (_a) { var wrapper = _a.wrapper, id = _a.id; cache[id] = wrapper; }); }; EntityPlugin.prototype.ensureUniqueId = function (type, id, knownIds) { var match = ENTITY_ID_REGEX.exec(id); var baseId = (match ? id.substr(0, id.length - match[0].length) : id) || type; // Make sure entity id is unique var newId = ''; for (var num = (match && parseInt(match[1])) || 0;; num++) { newId = num > 0 ? baseId + "_" + num : baseId; if (knownIds.indexOf(newId) < 0) { knownIds.push(newId); break; } } return newId; }; EntityPlugin.prototype.setIsEntityKnown = function (wrapper, isKnown) { var index = this.state.knownEntityElements.indexOf(wrapper); if (isKnown && index < 0) { this.state.knownEntityElements.push(wrapper); } else if (!isKnown && index >= 0) { this.state.knownEntityElements.splice(index, 1); } }; EntityPlugin.prototype.isEntityKnown = function (wrapper) { return this.state.knownEntityElements.indexOf(wrapper) >= 0; }; return EntityPlugin; }()); exports.default = EntityPlugin; /** * IE will show a resize border around the readonly content within content editable DIV * This is a workaround to remove it by temporarily move focus out of editor */ var workaroundSelectionIssueForIE = roosterjs_editor_dom_1.Browser.isIE ? function (editor) { editor.runAsync(function (editor) { var workaroundButton = editor.getCustomData('ENTITY_IE_FOCUS_BUTTON', function () { var button = (0, roosterjs_editor_dom_1.createElement)({ tag: 'button', style: 'overflow:hidden;position:fixed;width:0;height:0;top:-1000px', }, editor.getDocument()); button.onblur = function () { button.style.display = 'none'; }; editor.insertNode(button, { position: 4 /* Outside */, }); return button; }); workaroundButton.style.display = ''; (0, roosterjs_editor_dom_1.addRangeToSelection)((0, roosterjs_editor_dom_1.createRange)(workaroundButton, 0)); }); } : function () { }; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/ImageSelection.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/ImageSelection.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var Escape = 'Escape'; var mouseRightButton = 2; var mouseLeftButton = 0; /** * Detect image selection and help highlight the image */ var ImageSelection = /** @class */ (function () { function ImageSelection() { this.editor = null; } /** * Get a friendly name of this plugin */ ImageSelection.prototype.getName = function () { return 'ImageSelection'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ ImageSelection.prototype.initialize = function (editor) { this.editor = editor; }; /** * Dispose this plugin */ ImageSelection.prototype.dispose = function () { var _a; (_a = this.editor) === null || _a === void 0 ? void 0 : _a.select(null); this.editor = null; }; ImageSelection.prototype.onPluginEvent = function (event) { var _a; if (this.editor) { switch (event.eventType) { case 17 /* EnteredShadowEdit */: case 18 /* LeavingShadowEdit */: var selection = this.editor.getSelectionRangeEx(); if (selection.type == 2 /* ImageSelection */) { this.editor.select(selection.image); } break; case 6 /* MouseUp */: var target = event.rawEvent.target; if ((0, roosterjs_editor_dom_1.safeInstanceOf)(target, 'HTMLImageElement')) { if (event.rawEvent.button === mouseRightButton) { var imageRange = (0, roosterjs_editor_dom_1.createRange)(target); this.editor.select(imageRange); } else if (event.rawEvent.button === mouseLeftButton) { this.editor.select(target); } } break; case 5 /* MouseDown */: var mouseTarget = event.rawEvent.target; var mouseSelection = this.editor.getSelectionRangeEx(); if (mouseSelection && mouseSelection.type === 2 /* ImageSelection */ && mouseSelection.image !== mouseTarget) { this.editor.select(null); } break; case 2 /* KeyUp */: var key = event.rawEvent.key; var keyDownSelection = this.editor.getSelectionRangeEx(); if (keyDownSelection.type === 2 /* ImageSelection */) { if (key === Escape) { this.editor.select(keyDownSelection.image, -2 /* Before */); (_a = this.editor.getSelectionRange()) === null || _a === void 0 ? void 0 : _a.collapse(); event.rawEvent.stopPropagation(); } else { this.editor.select(keyDownSelection.ranges[0]); } } break; } } }; return ImageSelection; }()); exports.default = ImageSelection; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/LifecyclePlugin.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/LifecyclePlugin.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var CONTENT_EDITABLE_ATTRIBUTE_NAME = 'contenteditable'; var COMMANDS = roosterjs_editor_dom_1.Browser.isFirefox ? (_a = {}, /** * Disable these object resizing for firefox since other browsers don't have these behaviors */ _a["enableObjectResizing" /* EnableObjectResizing */] = false, _a["enableInlineTableEditing" /* EnableInlineTableEditing */] = false, _a) : roosterjs_editor_dom_1.Browser.isIE ? (_b = {}, /** * Change the default paragraph separator to DIV. This is mainly for IE since its default setting is P */ _b["defaultParagraphSeparator" /* DefaultParagraphSeparator */] = 'div', /** * Disable auto link feature in IE since we have our own implementation */ _b["AutoUrlDetect" /* AutoUrlDetect */] = false, _b) : {}; var DARK_MODE_DEFAULT_FORMAT = { backgroundColors: { darkModeColor: 'rgb(51,51,51)', lightModeColor: 'rgb(255,255,255)', }, textColors: { darkModeColor: 'rgb(255,255,255)', lightModeColor: 'rgb(0,0,0)', }, }; /** * @internal * Lifecycle plugin handles editor initialization and disposing */ var LifecyclePlugin = /** @class */ (function () { /** * Construct a new instance of LifecyclePlugin * @param options The editor options * @param contentDiv The editor content DIV */ function LifecyclePlugin(options, contentDiv) { var _this = this; var _a, _b, _c; this.editor = null; this.initializer = null; this.disposer = null; this.initialContent = options.initialContent || contentDiv.innerHTML || ''; this.contentDivFormat = (0, roosterjs_editor_dom_1.getComputedStyles)(contentDiv); // Make the container editable and set its selection styles if (contentDiv.getAttribute(CONTENT_EDITABLE_ATTRIBUTE_NAME) === null) { this.initializer = function () { contentDiv.contentEditable = 'true'; contentDiv.style.userSelect = 'text'; contentDiv.style.webkitUserSelect = 'text'; }; this.disposer = function () { contentDiv.style.userSelect = ''; contentDiv.style.webkitUserSelect = ''; contentDiv.removeAttribute(CONTENT_EDITABLE_ATTRIBUTE_NAME); }; } this.adjustColor = options.doNotAdjustEditorColor ? function () { } : function () { var _a; var textColors = DARK_MODE_DEFAULT_FORMAT.textColors, backgroundColors = DARK_MODE_DEFAULT_FORMAT.backgroundColors; var isDarkMode = _this.state.isDarkMode; var darkColorHandler = (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.getDarkColorHandler(); (0, roosterjs_editor_dom_1.setColor)(contentDiv, textColors, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler); (0, roosterjs_editor_dom_1.setColor)(contentDiv, backgroundColors, true /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler); }; this.state = { customData: {}, defaultFormat: (_a = options.defaultFormat) !== null && _a !== void 0 ? _a : null, isDarkMode: !!options.inDarkMode, getDarkColor: (_b = options.getDarkColor) !== null && _b !== void 0 ? _b : (function (color) { return color; }), onExternalContentTransform: (_c = options.onExternalContentTransform) !== null && _c !== void 0 ? _c : null, experimentalFeatures: options.experimentalFeatures || [], shadowEditFragment: null, shadowEditEntities: null, shadowEditSelectionPath: null, shadowEditTableSelectionPath: null, shadowEditImageSelectionPath: null, }; } /** * Get a friendly name of this plugin */ LifecyclePlugin.prototype.getName = function () { return 'Lifecycle'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ LifecyclePlugin.prototype.initialize = function (editor) { var _a; this.editor = editor; // Calculate default format this.recalculateDefaultFormat(); // Ensure initial content and its format this.editor.setContent(this.initialContent, false /*triggerContentChangedEvent*/); // Set content DIV to be editable (_a = this.initializer) === null || _a === void 0 ? void 0 : _a.call(this); // Set editor background color for dark mode this.adjustColor(); // Do proper change for browsers to disable some browser-specified behaviors. this.adjustBrowserBehavior(); // Let other plugins know that we are ready this.editor.triggerPluginEvent(11 /* EditorReady */, {}, true /*broadcast*/); }; /** * Dispose this plugin */ LifecyclePlugin.prototype.dispose = function () { var _this = this; var _a; (_a = this.editor) === null || _a === void 0 ? void 0 : _a.triggerPluginEvent(12 /* BeforeDispose */, {}, true /*broadcast*/); (0, roosterjs_editor_dom_1.getObjectKeys)(this.state.customData).forEach(function (key) { var data = _this.state.customData[key]; if (data && data.disposer) { data.disposer(data.value); } delete _this.state.customData[key]; }); if (this.disposer) { this.disposer(); this.disposer = null; this.initializer = null; } this.editor = null; }; /** * Get plugin state object */ LifecyclePlugin.prototype.getState = function () { return this.state; }; /** * Handle events triggered from editor * @param event PluginEvent object */ LifecyclePlugin.prototype.onPluginEvent = function (event) { if (event.eventType == 7 /* ContentChanged */ && (event.source == "SwitchToDarkMode" /* SwitchToDarkMode */ || event.source == "SwitchToLightMode" /* SwitchToLightMode */)) { this.state.isDarkMode = event.source == "SwitchToDarkMode" /* SwitchToDarkMode */; this.recalculateDefaultFormat(); this.adjustColor(); } }; LifecyclePlugin.prototype.adjustBrowserBehavior = function () { var _this = this; (0, roosterjs_editor_dom_1.getObjectKeys)(COMMANDS).forEach(function (command) { var _a; // Catch any possible exception since this should not block the initialization of editor try { (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.getDocument().execCommand(command, false, COMMANDS[command]); } catch (_b) { } }); }; LifecyclePlugin.prototype.recalculateDefaultFormat = function () { var _a = this.state, baseFormat = _a.defaultFormat, isDarkMode = _a.isDarkMode; if (isDarkMode && baseFormat) { if (!baseFormat.backgroundColors) { baseFormat.backgroundColors = DARK_MODE_DEFAULT_FORMAT.backgroundColors; } if (!baseFormat.textColors) { baseFormat.textColors = DARK_MODE_DEFAULT_FORMAT.textColors; } } if (baseFormat && (0, roosterjs_editor_dom_1.getObjectKeys)(baseFormat).length === 0) { return; } var _b = baseFormat || {}, fontFamily = _b.fontFamily, fontSize = _b.fontSize, textColor = _b.textColor, textColors = _b.textColors, backgroundColor = _b.backgroundColor, backgroundColors = _b.backgroundColors, bold = _b.bold, italic = _b.italic, underline = _b.underline; var defaultFormat = this.contentDivFormat; this.state.defaultFormat = { fontFamily: fontFamily || defaultFormat[0], fontSize: fontSize || defaultFormat[1], get textColor() { return textColors ? isDarkMode ? textColors.darkModeColor : textColors.lightModeColor : textColor || defaultFormat[2]; }, textColors: textColors, get backgroundColor() { return backgroundColors ? isDarkMode ? backgroundColors.darkModeColor : backgroundColors.lightModeColor : backgroundColor || ''; }, backgroundColors: backgroundColors, bold: bold, italic: italic, underline: underline, }; }; return LifecyclePlugin; }()); exports.default = LifecyclePlugin; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/MouseUpPlugin.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/MouseUpPlugin.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * @internal * MouseUpPlugin help trigger MouseUp event even when mouse up happens outside editor * as long as the mouse was pressed within Editor before */ var MouseUpPlugin = /** @class */ (function () { function MouseUpPlugin() { var _this = this; this.editor = null; this.mouseUpEventListerAdded = false; this.mouseDownX = null; this.mouseDownY = null; this.onMouseUp = function (rawEvent) { if (_this.editor) { _this.removeMouseUpEventListener(); _this.editor.triggerPluginEvent(6 /* MouseUp */, { rawEvent: rawEvent, isClicking: _this.mouseDownX == rawEvent.pageX && _this.mouseDownY == rawEvent.pageY, }); } }; } /** * Get a friendly name of this plugin */ MouseUpPlugin.prototype.getName = function () { return 'MouseUp'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ MouseUpPlugin.prototype.initialize = function (editor) { this.editor = editor; }; /** * Dispose this plugin */ MouseUpPlugin.prototype.dispose = function () { this.removeMouseUpEventListener(); this.editor = null; }; /** * Handle events triggered from editor * @param event PluginEvent object */ MouseUpPlugin.prototype.onPluginEvent = function (event) { if (this.editor && event.eventType == 5 /* MouseDown */ && !this.mouseUpEventListerAdded) { this.editor .getDocument() .addEventListener('mouseup', this.onMouseUp, true /*setCapture*/); this.mouseUpEventListerAdded = true; this.mouseDownX = event.rawEvent.pageX; this.mouseDownY = event.rawEvent.pageY; } }; MouseUpPlugin.prototype.removeMouseUpEventListener = function () { if (this.editor && this.mouseUpEventListerAdded) { this.mouseUpEventListerAdded = false; this.editor.getDocument().removeEventListener('mouseup', this.onMouseUp, true); } }; return MouseUpPlugin; }()); exports.default = MouseUpPlugin; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/NormalizeTablePlugin.ts": /*!********************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/NormalizeTablePlugin.ts ***! \********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * TODO: Rename this plugin since it is not only for table now * * NormalizeTable plugin makes sure each table in editor has TBODY/THEAD/TFOOT tag around TR tags * * When we retrieve HTML content using innerHTML, browser will always add TBODY around TR nodes if there is not. * This causes some issue when we restore the HTML content with selection path since the selection path is * deeply coupled with DOM structure. So we need to always make sure there is already TBODY tag whenever * new table is inserted, to make sure the selection path we created is correct. */ var NormalizeTablePlugin = /** @class */ (function () { function NormalizeTablePlugin() { this.editor = null; } /** * Get a friendly name of this plugin */ NormalizeTablePlugin.prototype.getName = function () { return 'NormalizeTable'; }; /** * The first method that editor will call to a plugin when editor is initializing. * It will pass in the editor instance, plugin should take this chance to save the * editor reference so that it can call to any editor method or format API later. * @param editor The editor object */ NormalizeTablePlugin.prototype.initialize = function (editor) { this.editor = editor; }; /** * The last method that editor will call to a plugin before it is disposed. * Plugin can take this chance to clear the reference to editor. After this method is * called, plugin should not call to any editor method since it will result in error. */ NormalizeTablePlugin.prototype.dispose = function () { this.editor = null; }; /** * Core method for a plugin. Once an event happens in editor, editor will call this * method of each plugin to handle the event as long as the event is not handled * exclusively by another plugin. * @param event The event to handle: */ NormalizeTablePlugin.prototype.onPluginEvent = function (event) { switch (event.eventType) { case 11 /* EditorReady */: case 7 /* ContentChanged */: if (this.editor) { this.normalizeTables(this.editor.queryElements('table')); } break; case 10 /* BeforePaste */: this.normalizeTables((0, roosterjs_editor_dom_1.toArray)(event.fragment.querySelectorAll('table'))); break; case 5 /* MouseDown */: this.normalizeTableFromEvent(event.rawEvent); break; case 0 /* KeyDown */: if (event.rawEvent.shiftKey) { this.normalizeTableFromEvent(event.rawEvent); } break; case 8 /* ExtractContentWithDom */: normalizeListsForExport(event.clonedRoot); break; } }; NormalizeTablePlugin.prototype.normalizeTableFromEvent = function (event) { var _a; var table = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getElementAtCursor('table', event.target); if (table) { this.normalizeTables([table]); } }; NormalizeTablePlugin.prototype.normalizeTables = function (tables) { if (this.editor && tables.length > 0) { var rangeEx = this.editor.getSelectionRangeEx(); var _a = ((rangeEx === null || rangeEx === void 0 ? void 0 : rangeEx.type) == 0 /* Normal */ && rangeEx.ranges[0]) || {}, startContainer = _a.startContainer, endContainer = _a.endContainer, startOffset = _a.startOffset, endOffset = _a.endOffset; var isChanged = normalizeTables(tables); if (isChanged) { if (startContainer && endContainer && typeof startOffset === 'number' && typeof endOffset === 'number') { this.editor.select(startContainer, startOffset, endContainer, endOffset); } else if ((rangeEx === null || rangeEx === void 0 ? void 0 : rangeEx.type) == 1 /* TableSelection */ && rangeEx.coordinates) { this.editor.select(rangeEx.table, rangeEx.coordinates); } } } }; return NormalizeTablePlugin; }()); exports.default = NormalizeTablePlugin; function normalizeTables(tables) { var isDOMChanged = false; tables.forEach(function (table) { var _a; var tbody = null; for (var child = table.firstChild; child; child = child.nextSibling) { var tag = (0, roosterjs_editor_dom_1.getTagOfNode)(child); switch (tag) { case 'TR': if (!tbody) { tbody = table.ownerDocument.createElement('tbody'); table.insertBefore(tbody, child); } tbody.appendChild(child); child = tbody; isDOMChanged = true; break; case 'TBODY': if (tbody) { (0, roosterjs_editor_dom_1.moveChildNodes)(tbody, child, true /*keepExistingChildren*/); (_a = child.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(child); child = tbody; isDOMChanged = true; } else { tbody = child; } break; default: tbody = null; break; } } var colgroups = table.querySelectorAll('colgroup'); var thead = table.querySelector('thead'); if (thead) { colgroups.forEach(function (colgroup) { if (!thead.contains(colgroup)) { thead.appendChild(colgroup); } }); } }); return isDOMChanged; } function normalizeListsForExport(root) { (0, roosterjs_editor_dom_1.toArray)(root.querySelectorAll('li')).forEach(function (li) { var prevElement = li.previousSibling; if (li.style.display == 'block' && (0, roosterjs_editor_dom_1.safeInstanceOf)(prevElement, 'HTMLLIElement')) { li.style.removeProperty('display'); prevElement.appendChild((0, roosterjs_editor_dom_1.changeElementTag)(li, 'div')); } }); } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/PendingFormatStatePlugin.ts": /*!************************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/PendingFormatStatePlugin.ts ***! \************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var ZERO_WIDTH_SPACE = '\u200B'; /** * @internal * PendingFormatStatePlugin handles pending format state management */ var PendingFormatStatePlugin = /** @class */ (function () { /** * Construct a new instance of PendingFormatStatePlugin * @param options The editor options * @param contentDiv The editor content DIV */ function PendingFormatStatePlugin() { this.editor = null; this.state = { pendableFormatPosition: null, pendableFormatState: null, pendableFormatSpan: null, }; } /** * Get a friendly name of this plugin */ PendingFormatStatePlugin.prototype.getName = function () { return 'PendingFormatState'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ PendingFormatStatePlugin.prototype.initialize = function (editor) { this.editor = editor; }; /** * Dispose this plugin */ PendingFormatStatePlugin.prototype.dispose = function () { this.editor = null; this.clear(); }; /** * Get plugin state object */ PendingFormatStatePlugin.prototype.getState = function () { return this.state; }; /** * Handle events triggered from editor * @param event PluginEvent object */ PendingFormatStatePlugin.prototype.onPluginEvent = function (event) { switch (event.eventType) { case 13 /* PendingFormatStateChanged */: // Got PendingFormatStateChanged event, cache current position and pending format if a format is passed in // otherwise clear existing pending format. if (event.formatState) { this.state.pendableFormatPosition = this.getCurrentPosition(); this.state.pendableFormatState = event.formatState; this.state.pendableFormatSpan = event.formatCallback ? this.createPendingFormatSpan(event.formatCallback) : null; } else { this.clear(); } break; case 0 /* KeyDown */: case 5 /* MouseDown */: case 7 /* ContentChanged */: var currentPosition = null; if (this.editor && event.eventType == 0 /* KeyDown */ && (0, roosterjs_editor_dom_1.isCharacterValue)(event.rawEvent) && this.state.pendableFormatSpan) { this.state.pendableFormatSpan.removeAttribute('contentEditable'); this.editor.insertNode(this.state.pendableFormatSpan); this.editor.select(this.state.pendableFormatSpan, -2 /* Before */, this.state.pendableFormatSpan, -1 /* End */); this.clear(); } else if ((event.eventType == 0 /* KeyDown */ && event.rawEvent.which >= 33 /* PAGEUP */ && event.rawEvent.which <= 40 /* DOWN */) || (this.state.pendableFormatPosition && (currentPosition = this.getCurrentPosition()) && !this.state.pendableFormatPosition.equalTo(currentPosition)) || (event.eventType == 7 /* ContentChanged */ && (event.source == "SwitchToDarkMode" /* SwitchToDarkMode */ || event.source == "SwitchToLightMode" /* SwitchToLightMode */))) { // If content or position is changed (by keyboard, mouse, or code), // check if current position is still the same with the cached one (if exist), // and clear cached format if position is changed since it is out-of-date now this.clear(); } break; } }; PendingFormatStatePlugin.prototype.clear = function () { this.state.pendableFormatPosition = null; this.state.pendableFormatState = null; this.state.pendableFormatSpan = null; }; PendingFormatStatePlugin.prototype.getCurrentPosition = function () { var _a, _b; var range = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getSelectionRange(); return (_b = (range && roosterjs_editor_dom_1.Position.getStart(range).normalize())) !== null && _b !== void 0 ? _b : null; }; PendingFormatStatePlugin.prototype.createPendingFormatSpan = function (callback) { var _a, _b; var span = this.state.pendableFormatSpan; if (!span && this.editor) { var currentStyle = this.editor.getStyleBasedFormatState(); var doc = this.editor.getDocument(); var isDarkMode = this.editor.isDarkMode(); span = doc.createElement('span'); span.contentEditable = 'true'; span.appendChild(doc.createTextNode(ZERO_WIDTH_SPACE)); span.style.setProperty('font-family', (_a = currentStyle.fontName) !== null && _a !== void 0 ? _a : null); span.style.setProperty('font-size', (_b = currentStyle.fontSize) !== null && _b !== void 0 ? _b : null); var darkColorHandler = this.editor.getDarkColorHandler(); if (currentStyle.textColors || currentStyle.textColor) { (0, roosterjs_editor_dom_1.setColor)(span, (currentStyle.textColors || currentStyle.textColor), false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler); } if (currentStyle.backgroundColors || currentStyle.backgroundColor) { (0, roosterjs_editor_dom_1.setColor)(span, (currentStyle.backgroundColors || currentStyle.backgroundColor), true /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler); } } if (span) { callback(span); } return span; }; return PendingFormatStatePlugin; }()); exports.default = PendingFormatStatePlugin; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/TypeInContainerPlugin.ts": /*!*********************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/TypeInContainerPlugin.ts ***! \*********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Typing Component helps to ensure typing is always happening under a DOM container */ var TypeInContainerPlugin = /** @class */ (function () { function TypeInContainerPlugin() { this.editor = null; } /** * Get a friendly name of this plugin */ TypeInContainerPlugin.prototype.getName = function () { return 'TypeInContainer'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ TypeInContainerPlugin.prototype.initialize = function (editor) { this.editor = editor; }; /** * Dispose this plugin */ TypeInContainerPlugin.prototype.dispose = function () { this.editor = null; }; TypeInContainerPlugin.prototype.isRangeEmpty = function (range) { if (range.collapsed && range.startContainer.nodeType === Node.ELEMENT_NODE && (0, roosterjs_editor_dom_1.getTagOfNode)(range.startContainer) == 'DIV' && !range.startContainer.firstChild) { return true; } return false; }; /** * Handle events triggered from editor * @param event PluginEvent object */ TypeInContainerPlugin.prototype.onPluginEvent = function (event) { var _this = this; var _a, _b, _c, _d, _e, _f; // We need to check if the ctrl key or the meta key is pressed, // browsers like Safari fire the "keypress" event when the meta key is pressed. if (event.eventType == 1 /* KeyPress */ && this.editor && !(event.rawEvent && (0, roosterjs_editor_dom_1.isCtrlOrMetaPressed)(event.rawEvent))) { // If normalization was not possible before the keypress, // check again after the keyboard event has been processed by browser native behavior. // // This handles the case where the keyboard event that first inserts content happens when // there is already content under the selection (e.g. Ctrl+a -> type new content). // // Only schedule when the range is not collapsed to catch this edge case. var range = this.editor.getSelectionRange(); var styledAncestor = range && (0, roosterjs_editor_dom_1.findClosestElementAncestor)(range.startContainer, undefined /* root */, '[style]'); if (!range || (!this.isRangeEmpty(range) && this.editor.contains(styledAncestor))) { return; } if (range.collapsed) { this.editor.ensureTypeInContainer(roosterjs_editor_dom_1.Position.getStart(range), event.rawEvent); } else { var callback = function () { var _a, _b; var focusedPosition = (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.getFocusedPosition(); if (focusedPosition) { (_b = _this.editor) === null || _b === void 0 ? void 0 : _b.ensureTypeInContainer(focusedPosition, event.rawEvent); } }; if (roosterjs_editor_dom_1.Browser.isMobileOrTablet) { (_a = this.editor.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.setTimeout(callback, 100); } else { this.editor.runAsync(callback); } } } /** * Add a Span with default format to the previous element when pressing backspace */ if (event.eventType == 0 /* KeyDown */ && event.rawEvent.which == 8 /* BACKSPACE */ && ((_b = this.editor) === null || _b === void 0 ? void 0 : _b.isFeatureEnabled("DefaultFormatInSpan" /* DefaultFormatInSpan */))) { var element = (_c = this.editor) === null || _c === void 0 ? void 0 : _c.getElementAtCursor(); var block_1 = element && ((_e = (_d = this.editor) === null || _d === void 0 ? void 0 : _d.getBlockElementAtNode(element)) === null || _e === void 0 ? void 0 : _e.getStartNode().previousSibling); if (block_1) { (_f = this.editor) === null || _f === void 0 ? void 0 : _f.runAsync(function (editor) { var position = editor.getFocusedPosition(); if (position && block_1 == position.element) { editor.ensureTypeInContainer(position, event.rawEvent); } }); } } }; return TypeInContainerPlugin; }()); exports.default = TypeInContainerPlugin; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/UndoPlugin.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/UndoPlugin.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); // Max stack size that cannot be exceeded. When exceeded, old undo history will be dropped // to keep size under limit. This is kept at 10MB var MAX_SIZE_LIMIT = 1e7; /** * @internal * Provides snapshot based undo service for Editor */ var UndoPlugin = /** @class */ (function () { /** * Construct a new instance of UndoPlugin * @param options The wrapper of the state object */ function UndoPlugin(options) { this.editor = null; this.lastKeyPress = null; this.state = { snapshotsService: options.undoMetadataSnapshotService || createUndoSnapshotServiceBridge(options.undoSnapshotService) || createUndoSnapshots(), isRestoring: false, hasNewContent: false, isNested: false, autoCompletePosition: null, }; } /** * Get a friendly name of this plugin */ UndoPlugin.prototype.getName = function () { return 'Undo'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ UndoPlugin.prototype.initialize = function (editor) { this.editor = editor; }; /** * Dispose this plugin */ UndoPlugin.prototype.dispose = function () { this.editor = null; }; /** * Get plugin state object */ UndoPlugin.prototype.getState = function () { return this.state; }; /** * Check if the plugin should handle the given event exclusively. * @param event The event to check */ UndoPlugin.prototype.willHandleEventExclusively = function (event) { return (event.eventType == 0 /* KeyDown */ && event.rawEvent.which == 8 /* BACKSPACE */ && this.canUndoAutoComplete()); }; /** * Handle events triggered from editor * @param event PluginEvent object */ UndoPlugin.prototype.onPluginEvent = function (event) { // if editor is in IME, don't do anything if (!this.editor || this.editor.isInIME()) { return; } switch (event.eventType) { case 11 /* EditorReady */: var undoState = this.editor.getUndoState(); if (!undoState.canUndo && !undoState.canRedo) { // Only add initial snapshot when there is no existing snapshot // Otherwise preserved undo/redo state may be ruined this.addUndoSnapshot(); } break; case 0 /* KeyDown */: this.onKeyDown(event.rawEvent); break; case 1 /* KeyPress */: this.onKeyPress(event.rawEvent); break; case 4 /* CompositionEnd */: this.clearRedoForInput(); this.addUndoSnapshot(); break; case 7 /* ContentChanged */: if (!(this.state.isRestoring || event.source == "SwitchToDarkMode" /* SwitchToDarkMode */ || event.source == "SwitchToLightMode" /* SwitchToLightMode */)) { this.clearRedoForInput(); } break; } }; UndoPlugin.prototype.onKeyDown = function (evt) { var _a, _b; // Handle backspace/delete when there is a selection to take a snapshot // since we want the state prior to deletion restorable // Ignore if keycombo is ALT+BACKSPACE if ((evt.which == 8 /* BACKSPACE */ && !evt.altKey) || evt.which == 46 /* DELETE */) { if (evt.which == 8 /* BACKSPACE */ && this.canUndoAutoComplete()) { evt.preventDefault(); (_a = this.editor) === null || _a === void 0 ? void 0 : _a.undo(); this.state.autoCompletePosition = null; this.lastKeyPress = evt.which; } else { var selectionRange = (_b = this.editor) === null || _b === void 0 ? void 0 : _b.getSelectionRange(); // Add snapshot when // 1. Something has been selected (not collapsed), or // 2. It has a different key code from the last keyDown event (to prevent adding too many snapshot when keeping press the same key), or // 3. Ctrl/Meta key is pressed so that a whole word will be deleted if (selectionRange && (!selectionRange.collapsed || this.lastKeyPress != evt.which || (0, roosterjs_editor_dom_1.isCtrlOrMetaPressed)(evt))) { this.addUndoSnapshot(); } // Since some content is deleted, always set hasNewContent to true so that we will take undo snapshot next time this.state.hasNewContent = true; this.lastKeyPress = evt.which; } } else if (evt.which >= 33 /* PAGEUP */ && evt.which <= 40 /* DOWN */) { // PageUp, PageDown, Home, End, Left, Right, Up, Down if (this.state.hasNewContent) { this.addUndoSnapshot(); } this.lastKeyPress = 0; } }; UndoPlugin.prototype.onKeyPress = function (evt) { var _a; if (evt.metaKey) { // if metaKey is pressed, simply return since no actual effect will be taken on the editor. // this is to prevent changing hasNewContent to true when meta + v to paste on Safari. return; } var range = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getSelectionRange(); if ((range && !range.collapsed) || (evt.which == 32 /* SPACE */ && this.lastKeyPress != 32 /* SPACE */) || evt.which == 13 /* ENTER */) { this.addUndoSnapshot(); if (evt.which == 13 /* ENTER */) { // Treat ENTER as new content so if there is no input after ENTER and undo, // we restore the snapshot before ENTER this.state.hasNewContent = true; } } else { this.clearRedoForInput(); } this.lastKeyPress = evt.which; }; UndoPlugin.prototype.clearRedoForInput = function () { this.state.snapshotsService.clearRedo(); this.lastKeyPress = 0; this.state.hasNewContent = true; }; UndoPlugin.prototype.canUndoAutoComplete = function () { var _a, _b; var focusedPosition = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getFocusedPosition(); return (this.state.snapshotsService.canUndoAutoComplete() && !!focusedPosition && !!((_b = this.state.autoCompletePosition) === null || _b === void 0 ? void 0 : _b.equalTo(focusedPosition))); }; UndoPlugin.prototype.addUndoSnapshot = function () { var _a; (_a = this.editor) === null || _a === void 0 ? void 0 : _a.addUndoSnapshot(); this.state.autoCompletePosition = null; }; return UndoPlugin; }()); exports.default = UndoPlugin; function createUndoSnapshots() { var snapshots = (0, roosterjs_editor_dom_1.createSnapshots)(MAX_SIZE_LIMIT); return { canMove: function (delta) { return (0, roosterjs_editor_dom_1.canMoveCurrentSnapshot)(snapshots, delta); }, move: function (delta) { return (0, roosterjs_editor_dom_1.moveCurrentSnapshot)(snapshots, delta); }, addSnapshot: function (snapshot, isAutoCompleteSnapshot) { return (0, roosterjs_editor_dom_1.addSnapshotV2)(snapshots, snapshot, isAutoCompleteSnapshot); }, clearRedo: function () { return (0, roosterjs_editor_dom_1.clearProceedingSnapshotsV2)(snapshots); }, canUndoAutoComplete: function () { return (0, roosterjs_editor_dom_1.canUndoAutoComplete)(snapshots); }, }; } function createUndoSnapshotServiceBridge(service) { var html; return service ? { canMove: function (delta) { return service.canMove(delta); }, move: function (delta) { return (html = service.move(delta)) ? { html: html, metadata: null } : null; }, addSnapshot: function (snapshot, isAutoCompleteSnapshot) { return service.addSnapshot(snapshot.html + (snapshot.metadata ? "" : ''), isAutoCompleteSnapshot); }, clearRedo: function () { return service.clearRedo(); }, canUndoAutoComplete: function () { return service.canUndoAutoComplete(); }, } : undefined; } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/createCorePlugins.ts": /*!*****************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/createCorePlugins.ts ***! \*****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getPluginState = void 0; var CopyPastePlugin_1 = __webpack_require__(/*! ./CopyPastePlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/CopyPastePlugin.ts"); var DOMEventPlugin_1 = __webpack_require__(/*! ./DOMEventPlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/DOMEventPlugin.ts"); var EditPlugin_1 = __webpack_require__(/*! ./EditPlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/EditPlugin.ts"); var EntityPlugin_1 = __webpack_require__(/*! ./EntityPlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/EntityPlugin.ts"); var ImageSelection_1 = __webpack_require__(/*! ./ImageSelection */ "./packages/roosterjs-editor-core/lib/corePlugins/ImageSelection.ts"); var LifecyclePlugin_1 = __webpack_require__(/*! ./LifecyclePlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/LifecyclePlugin.ts"); var MouseUpPlugin_1 = __webpack_require__(/*! ./MouseUpPlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/MouseUpPlugin.ts"); var NormalizeTablePlugin_1 = __webpack_require__(/*! ./NormalizeTablePlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/NormalizeTablePlugin.ts"); var PendingFormatStatePlugin_1 = __webpack_require__(/*! ./PendingFormatStatePlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/PendingFormatStatePlugin.ts"); var TypeInContainerPlugin_1 = __webpack_require__(/*! ./TypeInContainerPlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/TypeInContainerPlugin.ts"); var UndoPlugin_1 = __webpack_require__(/*! ./UndoPlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/UndoPlugin.ts"); /** * @internal * Create Core Plugins * @param contentDiv Content DIV of editor * @param options Editor options */ function createCorePlugins(contentDiv, options) { var map = options.corePluginOverride || {}; // The order matters, some plugin needs to be put before/after others to make sure event // can be handled in right order return { typeInContainer: map.typeInContainer || new TypeInContainerPlugin_1.default(), edit: map.edit || new EditPlugin_1.default(), pendingFormatState: map.pendingFormatState || new PendingFormatStatePlugin_1.default(), _placeholder: null, typeAfterLink: null, undo: map.undo || new UndoPlugin_1.default(options), domEvent: map.domEvent || new DOMEventPlugin_1.default(options, contentDiv), mouseUp: map.mouseUp || new MouseUpPlugin_1.default(), copyPaste: map.copyPaste || new CopyPastePlugin_1.default(options), entity: map.entity || new EntityPlugin_1.default(), imageSelection: map.imageSelection || new ImageSelection_1.default(), normalizeTable: map.normalizeTable || new NormalizeTablePlugin_1.default(), lifecycle: map.lifecycle || new LifecyclePlugin_1.default(options, contentDiv), }; } exports.default = createCorePlugins; /** * @internal * Get plugin state of core plugins * @param corePlugins CorePlugins object */ function getPluginState(corePlugins) { return { domEvent: corePlugins.domEvent.getState(), pendingFormatState: corePlugins.pendingFormatState.getState(), edit: corePlugins.edit.getState(), lifecycle: corePlugins.lifecycle.getState(), undo: corePlugins.undo.getState(), entity: corePlugins.entity.getState(), copyPaste: corePlugins.copyPaste.getState(), }; } exports.getPluginState = getPluginState; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/utils/forEachSelectedCell.ts": /*!*************************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/utils/forEachSelectedCell.ts ***! \*************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.forEachSelectedCell = void 0; /** * @internal * Executes an action to all the cells within the selection range. * @param callback action to apply on each selected cell * @returns the amount of cells modified */ var forEachSelectedCell = function (vTable, callback) { var _a; if (vTable.selection) { var _b = vTable.selection, lastCell = _b.lastCell, firstCell = _b.firstCell; for (var y = firstCell.y; y <= lastCell.y; y++) { for (var x = firstCell.x; x <= lastCell.x; x++) { if (vTable.cells && ((_a = vTable.cells[y][x]) === null || _a === void 0 ? void 0 : _a.td)) { callback(vTable.cells[y][x]); } } } } }; exports.forEachSelectedCell = forEachSelectedCell; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/corePlugins/utils/removeCellsOutsideSelection.ts": /*!*********************************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/corePlugins/utils/removeCellsOutsideSelection.ts ***! \*********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.removeCellsOutsideSelection = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Remove the cells outside of the selection. * @param vTable VTable to remove selection */ var removeCellsOutsideSelection = function (vTable) { if (vTable.selection) { if ((0, roosterjs_editor_dom_1.isWholeTableSelected)(vTable, vTable.selection)) { return; } vTable.table.style.removeProperty('width'); vTable.table.style.removeProperty('height'); var _a = vTable.selection, firstCell = _a.firstCell, lastCell = _a.lastCell; var resultCells_1 = []; var firstX_1 = firstCell.x; var firstY_1 = firstCell.y; var lastX_1 = lastCell.x; var lastY_1 = lastCell.y; if (vTable.cells) { vTable.cells.forEach(function (row, y) { row = row.filter(function (_, x) { return y >= firstY_1 && y <= lastY_1 && x >= firstX_1 && x <= lastX_1; }); if (row.length > 0) { resultCells_1.push(row); } }); vTable.cells = resultCells_1; } } }; exports.removeCellsOutsideSelection = removeCellsOutsideSelection; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/editor/DarkColorHandlerImpl.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/editor/DarkColorHandlerImpl.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var VARIABLE_REGEX = /^\s*var\(\s*(\-\-[a-zA-Z0-9\-_]+)\s*(?:,\s*(.*))?\)\s*$/; var VARIABLE_PREFIX = 'var('; var COLOR_VAR_PREFIX = 'darkColor'; /** * @internal */ var DarkColorHandlerImpl = /** @class */ (function () { function DarkColorHandlerImpl(contentDiv, getDarkColor) { this.contentDiv = contentDiv; this.getDarkColor = getDarkColor; this.knownColors = {}; } /** * Given a light mode color value and an optional dark mode color value, register this color * so that editor can handle it, then return the CSS color value for current color mode. * @param lightModeColor Light mode color value * @param isDarkMode Whether current color mode is dark mode * @param darkModeColor Optional dark mode color value. If not passed, we will calculate one. */ DarkColorHandlerImpl.prototype.registerColor = function (lightModeColor, isDarkMode, darkModeColor) { var parsedColor = this.parseColorValue(lightModeColor); var colorKey; if (parsedColor) { lightModeColor = parsedColor.lightModeColor; darkModeColor = parsedColor.darkModeColor || darkModeColor; colorKey = parsedColor.key; } if (isDarkMode && lightModeColor) { colorKey = colorKey || "--" + COLOR_VAR_PREFIX + "_" + lightModeColor.replace(/[^\d\w]/g, '_'); if (!this.knownColors[colorKey]) { darkModeColor = darkModeColor || this.getDarkColor(lightModeColor); this.knownColors[colorKey] = { lightModeColor: lightModeColor, darkModeColor: darkModeColor }; this.contentDiv.style.setProperty(colorKey, darkModeColor); } return "var(" + colorKey + ", " + lightModeColor + ")"; } else { return lightModeColor; } }; /** * Reset known color record, clean up registered color variables. */ DarkColorHandlerImpl.prototype.reset = function () { var _this = this; (0, roosterjs_editor_dom_1.getObjectKeys)(this.knownColors).forEach(function (key) { return _this.contentDiv.style.removeProperty(key); }); this.knownColors = {}; }; /** * Parse an existing color value, if it is in variable-based color format, extract color key, * light color and query related dark color if any * @param color The color string to parse */ DarkColorHandlerImpl.prototype.parseColorValue = function (color) { var _a; var key; var lightModeColor = color || ''; var darkModeColor; if (color) { var match = color.startsWith(VARIABLE_PREFIX) ? VARIABLE_REGEX.exec(color) : null; if (match) { if (match[2]) { key = match[1]; lightModeColor = match[2]; darkModeColor = (_a = this.knownColors[key]) === null || _a === void 0 ? void 0 : _a.darkModeColor; } else { lightModeColor = ''; } } } return { key: key, lightModeColor: lightModeColor, darkModeColor: darkModeColor }; }; return DarkColorHandlerImpl; }()); exports.default = DarkColorHandlerImpl; /***/ }), /***/ "./packages/roosterjs-editor-core/lib/editor/Editor.ts": /*!*************************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/editor/Editor.ts ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); var createCorePlugins_1 = __webpack_require__(/*! ../corePlugins/createCorePlugins */ "./packages/roosterjs-editor-core/lib/corePlugins/createCorePlugins.ts"); var DarkColorHandlerImpl_1 = __webpack_require__(/*! ./DarkColorHandlerImpl */ "./packages/roosterjs-editor-core/lib/editor/DarkColorHandlerImpl.ts"); var coreApiMap_1 = __webpack_require__(/*! ../coreApi/coreApiMap */ "./packages/roosterjs-editor-core/lib/coreApi/coreApiMap.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * RoosterJs core editor class */ var Editor = /** @class */ (function () { //#region Lifecycle /** * Creates an instance of Editor * @param contentDiv The DIV HTML element which will be the container element of editor * @param options An optional options object to customize the editor */ function Editor(contentDiv, options) { var _this = this; if (options === void 0) { options = {}; } var _a; this.core = null; // 1. Make sure all parameters are valid if ((0, roosterjs_editor_dom_1.getTagOfNode)(contentDiv) != 'DIV') { throw new Error('contentDiv must be an HTML DIV element'); } // 2. Store options values to local variables var corePlugins = (0, createCorePlugins_1.default)(contentDiv, options); var plugins = []; (0, roosterjs_editor_dom_1.getObjectKeys)(corePlugins).forEach(function (name) { if (name == '_placeholder') { if (options.plugins) { (0, roosterjs_editor_dom_1.arrayPush)(plugins, options.plugins); } } else { plugins.push(corePlugins[name]); } }); var zoomScale = ((_a = options.zoomScale) !== null && _a !== void 0 ? _a : -1) > 0 ? options.zoomScale : 1; this.core = __assign(__assign({ contentDiv: contentDiv, api: __assign(__assign({}, coreApiMap_1.coreApiMap), (options.coreApiOverride || {})), originalApi: coreApiMap_1.coreApiMap, plugins: plugins.filter(function (x) { return !!x; }) }, (0, createCorePlugins_1.getPluginState)(corePlugins)), { trustedHTMLHandler: options.trustedHTMLHandler || (function (html) { return html; }), zoomScale: zoomScale, sizeTransformer: options.sizeTransformer || (function (size) { return size / zoomScale; }), getVisibleViewport: options.getVisibleViewport || (function () { var scrollContainer = _this.getScrollContainer(); return (0, roosterjs_editor_dom_1.getIntersectedRect)(scrollContainer == contentDiv ? [scrollContainer] : [scrollContainer, contentDiv]); }), imageSelectionBorderColor: options.imageSelectionBorderColor }); if (this.isFeatureEnabled("VariableBasedDarkColor" /* VariableBasedDarkColor */)) { this.core.darkColorHandler = new DarkColorHandlerImpl_1.default(contentDiv, this.core.lifecycle.getDarkColor); } // 3. Initialize plugins this.core.plugins.forEach(function (plugin) { return plugin.initialize(_this); }); // 4. Ensure user will type in a container node, not the editor content DIV this.ensureTypeInContainer(new roosterjs_editor_dom_1.Position(this.core.contentDiv, 0 /* Begin */).normalize()); } /** * Dispose this editor, dispose all plugins and custom data */ Editor.prototype.dispose = function () { var _a; var core = this.getCore(); for (var i = core.plugins.length - 1; i >= 0; i--) { core.plugins[i].dispose(); } (_a = core.darkColorHandler) === null || _a === void 0 ? void 0 : _a.reset(); this.core = null; }; /** * Get whether this editor is disposed * @returns True if editor is disposed, otherwise false */ Editor.prototype.isDisposed = function () { return !this.core; }; //#endregion //#region Node API /** * Insert node into editor * @param node The node to insert * @param option Insert options. Default value is: * position: ContentPosition.SelectionStart * updateCursor: true * replaceSelection: true * insertOnNewLine: false * @returns true if node is inserted. Otherwise false */ Editor.prototype.insertNode = function (node, option) { var core = this.getCore(); return node ? core.api.insertNode(core, node, option !== null && option !== void 0 ? option : null) : false; }; /** * Delete a node from editor content * @param node The node to delete * @returns true if node is deleted. Otherwise false */ Editor.prototype.deleteNode = function (node) { // Only remove the node when it falls within editor if (node && this.contains(node) && node.parentNode) { node.parentNode.removeChild(node); return true; } return false; }; /** * Replace a node in editor content with another node * @param existingNode The existing node to be replaced * @param toNode node to replace to * @param transformColorForDarkMode (optional) Whether to transform new node to dark mode. Default is false * @returns true if node is replaced. Otherwise false */ Editor.prototype.replaceNode = function (existingNode, toNode, transformColorForDarkMode) { var core = this.getCore(); // Only replace the node when it falls within editor if (this.contains(existingNode) && toNode) { core.api.transformColor(core, transformColorForDarkMode ? toNode : null, true /*includeSelf*/, function () { var _a; return (_a = existingNode.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(toNode, existingNode); }, 0 /* LightToDark */); return true; } return false; }; /** * Get BlockElement at given node * @param node The node to create InlineElement * @returns The BlockElement result */ Editor.prototype.getBlockElementAtNode = function (node) { return (0, roosterjs_editor_dom_1.getBlockElementAtNode)(this.getCore().contentDiv, node); }; Editor.prototype.contains = function (arg) { if (!arg) { return false; } return (0, roosterjs_editor_dom_1.contains)(this.getCore().contentDiv, arg); }; Editor.prototype.queryElements = function (selector, scopeOrCallback, callback) { if (scopeOrCallback === void 0) { scopeOrCallback = 0 /* Body */; } var core = this.getCore(); var result = []; var scope = scopeOrCallback instanceof Function ? 0 /* Body */ : scopeOrCallback; callback = scopeOrCallback instanceof Function ? scopeOrCallback : callback; var selectionEx = scope == 0 /* Body */ ? null : this.getSelectionRangeEx(); if (selectionEx) { selectionEx.ranges.forEach(function (range) { result.push.apply(result, (0, roosterjs_editor_dom_1.queryElements)(core.contentDiv, selector, callback, scope, range)); }); } else { return (0, roosterjs_editor_dom_1.queryElements)(core.contentDiv, selector, callback, scope, undefined /* range */); } return result; }; /** * Collapse nodes within the given start and end nodes to their common ancestor node, * split parent nodes if necessary * @param start The start node * @param end The end node * @param canSplitParent True to allow split parent node there are nodes before start or after end under the same parent * and the returned nodes will be all nodes from start through end after splitting * False to disallow split parent * @returns When canSplitParent is true, returns all node from start through end after splitting, * otherwise just return start and end */ Editor.prototype.collapseNodes = function (start, end, canSplitParent) { return (0, roosterjs_editor_dom_1.collapseNodes)(this.getCore().contentDiv, start, end, canSplitParent); }; //#endregion //#region Content API /** * Check whether the editor contains any visible content * @param trim Whether trim the content string before check. Default is false * @returns True if there's no visible content, otherwise false */ Editor.prototype.isEmpty = function (trim) { return (0, roosterjs_editor_dom_1.isNodeEmpty)(this.getCore().contentDiv, trim); }; /** * Get current editor content as HTML string * @param mode specify what kind of HTML content to retrieve * @returns HTML string representing current editor content */ Editor.prototype.getContent = function (mode) { if (mode === void 0) { mode = 0 /* CleanHTML */; } var core = this.getCore(); return core.api.getContent(core, mode); }; /** * Set HTML content to this editor. All existing content will be replaced. A ContentChanged event will be triggered * @param content HTML content to set in * @param triggerContentChangedEvent True to trigger a ContentChanged event. Default value is true */ Editor.prototype.setContent = function (content, triggerContentChangedEvent) { if (triggerContentChangedEvent === void 0) { triggerContentChangedEvent = true; } var core = this.getCore(); core.api.setContent(core, content, triggerContentChangedEvent); }; /** * Insert HTML content into editor * @param HTML content to insert * @param option Insert options. Default value is: * position: ContentPosition.SelectionStart * updateCursor: true * replaceSelection: true * insertOnNewLine: false */ Editor.prototype.insertContent = function (content, option) { var _a; if (content) { var doc = this.getDocument(); var body = (_a = new DOMParser().parseFromString(this.getCore().trustedHTMLHandler(content), 'text/html')) === null || _a === void 0 ? void 0 : _a.body; var allNodes = (body === null || body === void 0 ? void 0 : body.childNodes) ? (0, roosterjs_editor_dom_1.toArray)(body.childNodes) : []; // If it is to insert on new line, and there are more than one node in the collection, wrap all nodes with // a parent DIV before calling insertNode on each top level sub node. Otherwise, every sub node may get wrapped // separately to show up on its own line if (option && option.insertOnNewLine && allNodes.length > 1) { allNodes = [(0, roosterjs_editor_dom_1.wrap)(allNodes)]; } var fragment_1 = doc.createDocumentFragment(); allNodes.forEach(function (node) { return fragment_1.appendChild(node); }); this.insertNode(fragment_1, option); } }; /** * Delete selected content */ Editor.prototype.deleteSelectedContent = function () { var range = this.getSelectionRange(); if (range && !range.collapsed) { return (0, roosterjs_editor_dom_1.deleteSelectedContent)(this.getCore().contentDiv, range); } return null; }; /** * Paste into editor using a clipboardData object * @param clipboardData Clipboard data retrieved from clipboard * @param pasteAsText Force pasting as plain text. Default value is false * @param applyCurrentStyle True if apply format of current selection to the pasted content, * false to keep original format. Default value is false. When pasteAsText is true, this parameter is ignored */ Editor.prototype.paste = function (clipboardData, pasteAsText, applyCurrentFormat) { var _this = this; if (pasteAsText === void 0) { pasteAsText = false; } if (applyCurrentFormat === void 0) { applyCurrentFormat = false; } var core = this.getCore(); if (!clipboardData) { return; } if (clipboardData.snapshotBeforePaste) { // Restore original content before paste a new one this.setContent(clipboardData.snapshotBeforePaste); } else { clipboardData.snapshotBeforePaste = this.getContent(2 /* RawHTMLWithSelection */); } var range = this.getSelectionRange(); var pos = range && roosterjs_editor_dom_1.Position.getStart(range); var fragment = core.api.createPasteFragment(core, clipboardData, pos, pasteAsText, applyCurrentFormat); if (fragment) { this.addUndoSnapshot(function () { _this.insertNode(fragment); return clipboardData; }, "Paste" /* Paste */); } }; //#endregion //#region Focus and Selection /** * Get current selection range from Editor. * It does a live pull on the selection, if nothing retrieved, return whatever we have in cache. * @param tryGetFromCache Set to true to retrieve the selection range from cache if editor doesn't own the focus now. * Default value is true * @returns current selection range, or null if editor never got focus before */ Editor.prototype.getSelectionRange = function (tryGetFromCache) { if (tryGetFromCache === void 0) { tryGetFromCache = true; } var core = this.getCore(); return core.api.getSelectionRange(core, tryGetFromCache); }; /** * Get current selection range from Editor. * It does a live pull on the selection, if nothing retrieved, return whatever we have in cache. * @param tryGetFromCache Set to true to retrieve the selection range from cache if editor doesn't own the focus now. * Default value is true * @returns current selection range, or null if editor never got focus before */ Editor.prototype.getSelectionRangeEx = function () { var core = this.getCore(); return core.api.getSelectionRangeEx(core); }; /** * Get current selection in a serializable format * It does a live pull on the selection, if nothing retrieved, return whatever we have in cache. * @returns current selection path, or null if editor never got focus before */ Editor.prototype.getSelectionPath = function () { var range = this.getSelectionRange(); return range && (0, roosterjs_editor_dom_1.getSelectionPath)(this.getCore().contentDiv, range); }; /** * Check if focus is in editor now * @returns true if focus is in editor, otherwise false */ Editor.prototype.hasFocus = function () { var core = this.getCore(); return core.api.hasFocus(core); }; /** * Focus to this editor, the selection was restored to where it was before, no unexpected scroll. */ Editor.prototype.focus = function () { var core = this.getCore(); core.api.focus(core); }; Editor.prototype.select = function (arg1, arg2, arg3, arg4) { var core = this.getCore(); var rangeEx = null; if (isSelectionRangeEx(arg1)) { rangeEx = arg1; } else if ((0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'HTMLTableElement') && isTableSelection(arg2)) { rangeEx = { type: 1 /* TableSelection */, ranges: [], areAllCollapsed: false, table: arg1, coordinates: arg2, }; } else if ((0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'HTMLImageElement') && typeof arg2 == 'undefined') { rangeEx = { type: 2 /* ImageSelection */, ranges: [], areAllCollapsed: false, image: arg1, }; } else { var range = !arg1 ? null : (0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'Range') ? arg1 : isSelectionPath(arg1) ? (0, roosterjs_editor_dom_1.createRange)(core.contentDiv, arg1.start, arg1.end) : isNodePosition(arg1) || (0, roosterjs_editor_dom_1.safeInstanceOf)(arg1, 'Node') ? (0, roosterjs_editor_dom_1.createRange)(arg1, arg2, arg3, arg4) : null; rangeEx = range ? { type: 0 /* Normal */, ranges: [range], areAllCollapsed: range.collapsed, } : null; } if (rangeEx) { switch (rangeEx.type) { case 1 /* TableSelection */: if (this.contains(rangeEx.table)) { core.domEvent.imageSelectionRange = core.api.selectImage(core, null); core.domEvent.tableSelectionRange = core.api.selectTable(core, rangeEx.table, rangeEx.coordinates); rangeEx = core.domEvent.tableSelectionRange; } break; case 2 /* ImageSelection */: if (this.contains(rangeEx.image)) { core.domEvent.tableSelectionRange = core.api.selectTable(core, null); core.domEvent.imageSelectionRange = core.api.selectImage(core, rangeEx.image); rangeEx = core.domEvent.imageSelectionRange; } break; case 0 /* Normal */: core.domEvent.tableSelectionRange = core.api.selectTable(core, null); core.domEvent.imageSelectionRange = core.api.selectImage(core, null); if (this.contains(rangeEx.ranges[0])) { core.api.selectRange(core, rangeEx.ranges[0]); } else { rangeEx = null; } break; } this.triggerPluginEvent(22 /* SelectionChanged */, { selectionRangeEx: rangeEx, }, true /** broadcast **/); } else { core.domEvent.tableSelectionRange = core.api.selectTable(core, null); core.domEvent.imageSelectionRange = core.api.selectImage(core, null); } return !!rangeEx; }; /** * Get current focused position. Return null if editor doesn't have focus at this time. */ Editor.prototype.getFocusedPosition = function () { var _a; var sel = (_a = this.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.getSelection(); if ((sel === null || sel === void 0 ? void 0 : sel.focusNode) && this.contains(sel.focusNode)) { return new roosterjs_editor_dom_1.Position(sel.focusNode, sel.focusOffset); } var range = this.getSelectionRange(); if (range) { return roosterjs_editor_dom_1.Position.getStart(range); } return null; }; /** * Get an HTML element from current cursor position. * When expectedTags is not specified, return value is the current node (if it is HTML element) * or its parent node (if current node is a Text node). * When expectedTags is specified, return value is the first ancestor of current node which has * one of the expected tags. * If no element found within editor by the given tag, return null. * @param selector Optional, an HTML selector to find HTML element with. * @param startFrom Start search from this node. If not specified, start from current focused position * @param event Optional, if specified, editor will try to get cached result from the event object first. * If it is not cached before, query from DOM and cache the result into the event object */ Editor.prototype.getElementAtCursor = function (selector, startFrom, event) { var _this = this; var _a; event = startFrom ? undefined : event; // Only use cache when startFrom is not specified, for different start position can have different result return ((_a = (0, roosterjs_editor_dom_1.cacheGetEventData)(event !== null && event !== void 0 ? event : null, 'GET_ELEMENT_AT_CURSOR_' + selector, function () { if (!startFrom) { var position = _this.getFocusedPosition(); startFrom = position === null || position === void 0 ? void 0 : position.node; } return (startFrom && (0, roosterjs_editor_dom_1.findClosestElementAncestor)(startFrom, _this.getCore().contentDiv, selector)); })) !== null && _a !== void 0 ? _a : null); }; /** * Check if this position is at beginning of the editor. * This will return true if all nodes between the beginning of target node and the position are empty. * @param position The position to check * @returns True if position is at beginning of the editor, otherwise false */ Editor.prototype.isPositionAtBeginning = function (position) { return (0, roosterjs_editor_dom_1.isPositionAtBeginningOf)(position, this.getCore().contentDiv); }; /** * Get impacted regions from selection */ Editor.prototype.getSelectedRegions = function (type) { if (type === void 0) { type = 0 /* Table */; } var selection = this.getSelectionRangeEx(); var result = []; var contentDiv = this.getCore().contentDiv; selection.ranges.forEach(function (range) { result.push.apply(result, (range ? (0, roosterjs_editor_dom_1.getRegionsFromRange)(contentDiv, range, type) : [])); }); return result.filter(function (value, index, self) { return self.indexOf(value) === index; }); }; //#endregion //#region EVENT API Editor.prototype.addDomEventHandler = function (nameOrMap, handler) { var _a; var eventsToMap = typeof nameOrMap == 'string' ? (_a = {}, _a[nameOrMap] = handler, _a) : nameOrMap; var core = this.getCore(); return core.api.attachDomEvent(core, eventsToMap); }; /** * Trigger an event to be dispatched to all plugins * @param eventType Type of the event * @param data data of the event with given type, this is the rest part of PluginEvent with the given type * @param broadcast indicates if the event needs to be dispatched to all plugins * True means to all, false means to allow exclusive handling from one plugin unless no one wants that * @returns the event object which is really passed into plugins. Some plugin may modify the event object so * the result of this function provides a chance to read the modified result */ Editor.prototype.triggerPluginEvent = function (eventType, data, broadcast) { if (broadcast === void 0) { broadcast = false; } var core = this.getCore(); var event = __assign({ eventType: eventType }, data); core.api.triggerEvent(core, event, broadcast); return event; }; /** * Trigger a ContentChangedEvent * @param source Source of this event, by default is 'SetContent' * @param data additional data for this event */ Editor.prototype.triggerContentChangedEvent = function (source, data) { if (source === void 0) { source = "SetContent" /* SetContent */; } this.triggerPluginEvent(7 /* ContentChanged */, { source: source, data: data, }); }; //#endregion //#region Undo API /** * Undo last edit operation */ Editor.prototype.undo = function () { this.focus(); var core = this.getCore(); core.api.restoreUndoSnapshot(core, -1 /*step*/); }; /** * Redo next edit operation */ Editor.prototype.redo = function () { this.focus(); var core = this.getCore(); core.api.restoreUndoSnapshot(core, 1 /*step*/); }; /** * Add undo snapshot, and execute a format callback function, then add another undo snapshot, then trigger * ContentChangedEvent with given change source. * If this function is called nested, undo snapshot will only be added in the outside one * @param callback The callback function to perform formatting, returns a data object which will be used as * the data field in ContentChangedEvent if changeSource is not null. * @param changeSource The change source to use when fire ContentChangedEvent. When the value is not null, * a ContentChangedEvent will be fired with change source equal to this value * @param canUndoByBackspace True if this action can be undone when user press Backspace key (aka Auto Complete). */ Editor.prototype.addUndoSnapshot = function (callback, changeSource, canUndoByBackspace, additionalData) { var core = this.getCore(); core.api.addUndoSnapshot(core, callback !== null && callback !== void 0 ? callback : null, changeSource !== null && changeSource !== void 0 ? changeSource : null, canUndoByBackspace !== null && canUndoByBackspace !== void 0 ? canUndoByBackspace : false, additionalData); }; /** * Whether there is an available undo/redo snapshot */ Editor.prototype.getUndoState = function () { var _a = this.getCore().undo, hasNewContent = _a.hasNewContent, snapshotsService = _a.snapshotsService; return { canUndo: hasNewContent || snapshotsService.canMove(-1 /*previousSnapshot*/), canRedo: snapshotsService.canMove(1 /*nextSnapshot*/), }; }; //#endregion //#region Misc /** * Get document which contains this editor * @returns The HTML document which contains this editor */ Editor.prototype.getDocument = function () { return this.getCore().contentDiv.ownerDocument; }; /** * Get the scroll container of the editor */ Editor.prototype.getScrollContainer = function () { return this.getCore().domEvent.scrollContainer; }; /** * Get custom data related to this editor * @param key Key of the custom data * @param getter Getter function. If custom data for the given key doesn't exist, * call this function to get one and store it if it is specified. Otherwise return undefined * @param disposer An optional disposer function to dispose this custom data when * dispose editor. */ Editor.prototype.getCustomData = function (key, getter, disposer) { var core = this.getCore(); return (core.lifecycle.customData[key] = core.lifecycle.customData[key] || { value: getter ? getter() : undefined, disposer: disposer, }).value; }; /** * Check if editor is in IME input sequence * @returns True if editor is in IME input sequence, otherwise false */ Editor.prototype.isInIME = function () { return this.getCore().domEvent.isInIME; }; /** * Get default format of this editor * @returns Default format object of this editor */ Editor.prototype.getDefaultFormat = function () { var _a; return (_a = this.getCore().lifecycle.defaultFormat) !== null && _a !== void 0 ? _a : {}; }; /** * Get a content traverser for the whole editor * @param startNode The node to start from. If not passed, it will start from the beginning of the body */ Editor.prototype.getBodyTraverser = function (startNode) { return roosterjs_editor_dom_1.ContentTraverser.createBodyTraverser(this.getCore().contentDiv, startNode); }; /** * Get a content traverser for current selection * @returns A content traverser, or null if editor never got focus before */ Editor.prototype.getSelectionTraverser = function (range) { var _a; range = (_a = range !== null && range !== void 0 ? range : this.getSelectionRange()) !== null && _a !== void 0 ? _a : undefined; return range ? roosterjs_editor_dom_1.ContentTraverser.createSelectionTraverser(this.getCore().contentDiv, range) : null; }; /** * Get a content traverser for current block element start from specified position * @param startFrom Start position of the traverser. Default value is ContentPosition.SelectionStart * @returns A content traverser, or null if editor never got focus before */ Editor.prototype.getBlockTraverser = function (startFrom) { if (startFrom === void 0) { startFrom = 3 /* SelectionStart */; } var range = this.getSelectionRange(); return range ? roosterjs_editor_dom_1.ContentTraverser.createBlockTraverser(this.getCore().contentDiv, range, startFrom) : null; }; /** * Get a text traverser of current selection * @param event Optional, if specified, editor will try to get cached result from the event object first. * If it is not cached before, query from DOM and cache the result into the event object * @returns A content traverser, or null if editor never got focus before */ Editor.prototype.getContentSearcherOfCursor = function (event) { var _this = this; return (0, roosterjs_editor_dom_1.cacheGetEventData)(event !== null && event !== void 0 ? event : null, 'ContentSearcher', function () { var range = _this.getSelectionRange(); return (range && new roosterjs_editor_dom_1.PositionContentSearcher(_this.getCore().contentDiv, roosterjs_editor_dom_1.Position.getStart(range))); }); }; /** * Run a callback function asynchronously * @param callback The callback function to run * @returns a function to cancel this async run */ Editor.prototype.runAsync = function (callback) { var _this = this; var win = this.getCore().contentDiv.ownerDocument.defaultView || window; var handle = win.requestAnimationFrame(function () { if (!_this.isDisposed() && callback) { callback(_this); } }); return function () { win.cancelAnimationFrame(handle); }; }; /** * Set DOM attribute of editor content DIV * @param name Name of the attribute * @param value Value of the attribute */ Editor.prototype.setEditorDomAttribute = function (name, value) { if (value === null) { this.getCore().contentDiv.removeAttribute(name); } else { this.getCore().contentDiv.setAttribute(name, value); } }; /** * Get DOM attribute of editor content DIV, null if there is no such attribute. * @param name Name of the attribute */ Editor.prototype.getEditorDomAttribute = function (name) { return this.getCore().contentDiv.getAttribute(name); }; /** * @deprecated Use getVisibleViewport() instead. * * Get current relative distance from top-left corner of the given element to top-left corner of editor content DIV. * @param element The element to calculate from. If the given element is not in editor, return value will be null * @param addScroll When pass true, The return value will also add scrollLeft and scrollTop if any. So the value * may be different than what user is seeing from the view. When pass false, scroll position will be ignored. * @returns An [x, y] array which contains the left and top distances, or null if the given element is not in editor. */ Editor.prototype.getRelativeDistanceToEditor = function (element, addScroll) { if (this.contains(element)) { var contentDiv = this.getCore().contentDiv; var editorRect = contentDiv.getBoundingClientRect(); var elementRect = element.getBoundingClientRect(); if (editorRect && elementRect) { var x = elementRect.left - (editorRect === null || editorRect === void 0 ? void 0 : editorRect.left); var y = elementRect.top - (editorRect === null || editorRect === void 0 ? void 0 : editorRect.top); if (addScroll) { x += contentDiv.scrollLeft; y += contentDiv.scrollTop; } return [x, y]; } } return null; }; /** * Add a Content Edit feature. * @param feature The feature to add */ Editor.prototype.addContentEditFeature = function (feature) { var core = this.getCore(); feature === null || feature === void 0 ? void 0 : feature.keys.forEach(function (key) { var array = core.edit.features[key] || []; array.push(feature); core.edit.features[key] = array; }); }; /** * Remove a Content Edit feature. * @param feature The feature to remove */ Editor.prototype.removeContentEditFeature = function (feature) { var core = this.getCore(); feature === null || feature === void 0 ? void 0 : feature.keys.forEach(function (key) { var _a; var featureSet = core.edit.features[key]; var index = (_a = featureSet === null || featureSet === void 0 ? void 0 : featureSet.indexOf(feature)) !== null && _a !== void 0 ? _a : -1; if (index >= 0) { core.edit.features[key].splice(index, 1); if (core.edit.features[key].length < 1) { delete core.edit.features[key]; } } }); }; /** * Get style based format state from current selection, including font name/size and colors */ Editor.prototype.getStyleBasedFormatState = function (node) { var _a; if (!node) { var range = this.getSelectionRange(); node = (_a = (range && roosterjs_editor_dom_1.Position.getStart(range).normalize().node)) !== null && _a !== void 0 ? _a : undefined; } var core = this.getCore(); return core.api.getStyleBasedFormatState(core, node !== null && node !== void 0 ? node : null); }; /** * Get the pendable format such as underline and bold * @param forceGetStateFromDOM If set to true, will force get the format state from DOM tree. * @returns The pending format state */ Editor.prototype.getPendableFormatState = function (forceGetStateFromDOM) { if (forceGetStateFromDOM === void 0) { forceGetStateFromDOM = false; } var core = this.getCore(); return core.api.getPendableFormatState(core, forceGetStateFromDOM); }; /** * Ensure user will type into a container element rather than into the editor content DIV directly * @param position The position that user is about to type to * @param keyboardEvent Optional keyboard event object */ Editor.prototype.ensureTypeInContainer = function (position, keyboardEvent) { var core = this.getCore(); core.api.ensureTypeInContainer(core, position, keyboardEvent, this.isFeatureEnabled("DefaultFormatInSpan" /* DefaultFormatInSpan */)); }; //#endregion //#region Dark mode APIs /** * Set the dark mode state and transforms the content to match the new state. * @param nextDarkMode The next status of dark mode. True if the editor should be in dark mode, false if not. */ Editor.prototype.setDarkModeState = function (nextDarkMode) { if (this.isDarkMode() == !!nextDarkMode) { return; } var core = this.getCore(); core.api.transformColor(core, core.contentDiv, false /*includeSelf*/, null /*callback*/, nextDarkMode ? 0 /* LightToDark */ : 1 /* DarkToLight */, true /*forceTransform*/); this.triggerContentChangedEvent(nextDarkMode ? "SwitchToDarkMode" /* SwitchToDarkMode */ : "SwitchToLightMode" /* SwitchToLightMode */); }; /** * Check if the editor is in dark mode * @returns True if the editor is in dark mode, otherwise false */ Editor.prototype.isDarkMode = function () { return this.getCore().lifecycle.isDarkMode; }; /** * Transform the given node and all its child nodes to dark mode color if editor is in dark mode * @param node The node to transform */ Editor.prototype.transformToDarkColor = function (node) { var core = this.getCore(); core.api.transformColor(core, node, true /*includeSelf*/, null /*callback*/, 0 /* LightToDark */); }; /** * Get a darkColorHandler object for this editor. It will return null if experimental feature "VariableBasedDarkColor" is not enabled */ Editor.prototype.getDarkColorHandler = function () { return this.getCore().darkColorHandler || null; }; /** * Make the editor in "Shadow Edit" mode. * In Shadow Edit mode, all format change will finally be ignored. * This can be used for building a live preview feature for format button, to allow user * see format result without really apply it. * This function can be called repeated. If editor is already in shadow edit mode, we can still * use this function to do more shadow edit operation. */ Editor.prototype.startShadowEdit = function () { var core = this.getCore(); core.api.switchShadowEdit(core, true /*isOn*/); }; /** * Leave "Shadow Edit" mode, all changes made during shadow edit will be discarded */ Editor.prototype.stopShadowEdit = function () { var core = this.getCore(); core.api.switchShadowEdit(core, false /*isOn*/); }; /** * Check if editor is in Shadow Edit mode */ Editor.prototype.isInShadowEdit = function () { return !!this.getCore().lifecycle.shadowEditFragment; }; /** * Check if the given experimental feature is enabled * @param feature The feature to check */ Editor.prototype.isFeatureEnabled = function (feature) { return this.getCore().lifecycle.experimentalFeatures.indexOf(feature) >= 0; }; /** * Get a function to convert HTML string to trusted HTML string. * By default it will just return the input HTML directly. To override this behavior, * pass your own trusted HTML handler to EditorOptions.trustedHTMLHandler * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types */ Editor.prototype.getTrustedHTMLHandler = function () { return this.getCore().trustedHTMLHandler; }; /** * @deprecated Use getZoomScale() instead */ Editor.prototype.getSizeTransformer = function () { return this.getCore().sizeTransformer; }; /** * Get current zoom scale, default value is 1 * When editor is put under a zoomed container, need to pass the zoom scale number using EditorOptions.zoomScale * to let editor behave correctly especially for those mouse drag/drop behaviors * @returns current zoom scale number */ Editor.prototype.getZoomScale = function () { return this.getCore().zoomScale; }; /** * Set current zoom scale, default value is 1 * When editor is put under a zoomed container, need to pass the zoom scale number using EditorOptions.zoomScale * to let editor behave correctly especially for those mouse drag/drop behaviors * @param scale The new scale number to set. It should be positive number and no greater than 10, otherwise it will be ignored. */ Editor.prototype.setZoomScale = function (scale) { var core = this.getCore(); if (scale > 0 && scale <= 10) { var oldValue = core.zoomScale; core.zoomScale = scale; if (oldValue != scale) { this.triggerPluginEvent(21 /* ZoomChanged */, { oldZoomScale: oldValue, newZoomScale: scale, }, true /*broadcast*/); } } }; /** * Retrieves the rect of the visible viewport of the editor. */ Editor.prototype.getVisibleViewport = function () { return this.getCore().getVisibleViewport(); }; /** * @returns the current EditorCore object * @throws a standard Error if there's no core object */ Editor.prototype.getCore = function () { if (!this.core) { throw new Error('Editor is already disposed'); } return this.core; }; return Editor; }()); exports.default = Editor; function isSelectionRangeEx(obj) { var rangeEx = obj; return (rangeEx && typeof rangeEx == 'object' && typeof rangeEx.type == 'number' && Array.isArray(rangeEx.ranges)); } function isTableSelection(obj) { var selection = obj; return (selection && typeof selection == 'object' && typeof selection.firstCell == 'object' && typeof selection.lastCell == 'object'); } function isSelectionPath(obj) { var path = obj; return path && typeof path == 'object' && Array.isArray(path.start) && Array.isArray(path.end); } function isNodePosition(obj) { var pos = obj; return (pos && typeof pos == 'object' && typeof pos.node == 'object' && typeof pos.offset == 'number'); } /***/ }), /***/ "./packages/roosterjs-editor-core/lib/index.ts": /*!*****************************************************!*\ !*** ./packages/roosterjs-editor-core/lib/index.ts ***! \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Editor = void 0; // Classes var Editor_1 = __webpack_require__(/*! ./editor/Editor */ "./packages/roosterjs-editor-core/lib/editor/Editor.ts"); Object.defineProperty(exports, "Editor", { enumerable: true, get: function () { return Editor_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts": /*!*****************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts ***! \*****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var isNodeAfter_1 = __webpack_require__(/*! ../utils/isNodeAfter */ "./packages/roosterjs-editor-dom/lib/utils/isNodeAfter.ts"); /** * @internal * This presents a content block that can be represented by a single html block type element. * In most cases, it corresponds to an HTML block level element, i.e. P, DIV, LI, TD etc. */ var NodeBlockElement = /** @class */ (function () { function NodeBlockElement(element) { this.element = element; } /** * Collapse this element to a single DOM element. * If the content nodes are separated in different root nodes, wrap them to a single node * If the content nodes are included in root node with other nodes, split root node */ NodeBlockElement.prototype.collapseToSingleElement = function () { return this.element; }; /** * Get the start node of the block * For NodeBlockElement, start and end essentially refers to same node */ NodeBlockElement.prototype.getStartNode = function () { return this.element; }; /** * Get the end node of the block * For NodeBlockElement, start and end essentially refers to same node */ NodeBlockElement.prototype.getEndNode = function () { return this.element; }; /** * Checks if it refers to same block */ NodeBlockElement.prototype.equals = function (blockElement) { // Ideally there is only one unique way to generate a block so we only need to compare the startNode return this.element == blockElement.getStartNode(); }; /** * Checks if a block is after the current block */ NodeBlockElement.prototype.isAfter = function (blockElement) { // if the block's startNode is after current node endEnd, we say it is after return (0, isNodeAfter_1.default)(this.element, blockElement.getEndNode()); }; /** * Checks if a certain html node is within the block */ NodeBlockElement.prototype.contains = function (node) { return (0, contains_1.default)(this.element, node, true /*treatSameNodeAsContain*/); }; /** * Get the text content of this block element */ NodeBlockElement.prototype.getTextContent = function () { var _a; return ((_a = this.element) === null || _a === void 0 ? void 0 : _a.textContent) || ''; }; return NodeBlockElement; }()); exports.default = NodeBlockElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/blockElements/StartEndBlockElement.ts": /*!*********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/blockElements/StartEndBlockElement.ts ***! \*********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var collapseNodes_1 = __webpack_require__(/*! ../utils/collapseNodes */ "./packages/roosterjs-editor-dom/lib/utils/collapseNodes.ts"); var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var createRange_1 = __webpack_require__(/*! ../selection/createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts"); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var isBlockElement_1 = __webpack_require__(/*! ../utils/isBlockElement */ "./packages/roosterjs-editor-dom/lib/utils/isBlockElement.ts"); var isNodeAfter_1 = __webpack_require__(/*! ../utils/isNodeAfter */ "./packages/roosterjs-editor-dom/lib/utils/isNodeAfter.ts"); var wrap_1 = __webpack_require__(/*! ../utils/wrap */ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts"); var splitParentNode_1 = __webpack_require__(/*! ../utils/splitParentNode */ "./packages/roosterjs-editor-dom/lib/utils/splitParentNode.ts"); var STRUCTURE_NODE_TAGS = ['TD', 'TH', 'LI', 'BLOCKQUOTE']; /** * @internal * This represents a block that is identified by a start and end node * This is for cases like <root>Hello<BR>World</root> * in that case, Hello<BR> is a block, World is another block * Such block cannot be represented by a NodeBlockElement since they don't chained up * to a single parent node, instead they have a start and end * This start and end must be in same sibling level and have same parent in DOM tree */ var StartEndBlockElement = /** @class */ (function () { function StartEndBlockElement(rootNode, startNode, endNode) { this.rootNode = rootNode; this.startNode = startNode; this.endNode = endNode; } StartEndBlockElement.getBlockContext = function (node) { var currentNode = node; while (currentNode && !(0, isBlockElement_1.default)(currentNode)) { currentNode = currentNode.parentNode; } return currentNode; }; /** * Collapse this element to a single DOM element. * If the content nodes are separated in different root nodes, wrap them to a single node * If the content nodes are included in root node with other nodes, split root node */ StartEndBlockElement.prototype.collapseToSingleElement = function () { var nodeContext = StartEndBlockElement.getBlockContext(this.startNode); var nodes = nodeContext ? (0, collapseNodes_1.default)(nodeContext, this.startNode, this.endNode, true /*canSplitParent*/) : []; var blockContext = StartEndBlockElement.getBlockContext(this.startNode); while (nodes[0] && nodes[0] != blockContext && nodes[0].parentNode != this.rootNode && STRUCTURE_NODE_TAGS.indexOf((0, getTagOfNode_1.default)(nodes[0].parentNode)) < 0) { var newNode = (0, splitParentNode_1.splitBalancedNodeRange)(nodes); if (newNode) { nodes = [newNode]; } else { break; } } return nodes.length == 1 && (0, isBlockElement_1.default)(nodes[0]) ? nodes[0] : (0, wrap_1.default)(nodes); }; /** * Gets the start node */ StartEndBlockElement.prototype.getStartNode = function () { return this.startNode; }; /** * Gets the end node */ StartEndBlockElement.prototype.getEndNode = function () { return this.endNode; }; /** * Checks equals of two blocks */ StartEndBlockElement.prototype.equals = function (blockElement) { return (this.startNode == blockElement.getStartNode() && this.endNode == blockElement.getEndNode()); }; /** * Checks if another block is after this current */ StartEndBlockElement.prototype.isAfter = function (blockElement) { return (0, isNodeAfter_1.default)(this.getStartNode(), blockElement.getEndNode()); }; /** * Checks if an Html node is contained within the block */ StartEndBlockElement.prototype.contains = function (node) { return ((0, contains_1.default)(this.startNode, node, true /*treatSameNodeAsContain*/) || (0, contains_1.default)(this.endNode, node, true /*treatSameNodeAsContain*/) || ((0, isNodeAfter_1.default)(node, this.startNode) && (0, isNodeAfter_1.default)(this.endNode, node))); }; /** * Get the text content of this block element */ StartEndBlockElement.prototype.getTextContent = function () { var range = (0, createRange_1.default)(this.getStartNode(), this.getEndNode()); return range ? range.toString() : ''; }; return StartEndBlockElement; }()); exports.default = StartEndBlockElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts": /*!**********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts ***! \**********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var collapseNodes_1 = __webpack_require__(/*! ../utils/collapseNodes */ "./packages/roosterjs-editor-dom/lib/utils/collapseNodes.ts"); var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var isBlockElement_1 = __webpack_require__(/*! ../utils/isBlockElement */ "./packages/roosterjs-editor-dom/lib/utils/isBlockElement.ts"); var NodeBlockElement_1 = __webpack_require__(/*! ./NodeBlockElement */ "./packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts"); var StartEndBlockElement_1 = __webpack_require__(/*! ./StartEndBlockElement */ "./packages/roosterjs-editor-dom/lib/blockElements/StartEndBlockElement.ts"); /** * This produces a block element from a a node * It needs to account for various HTML structure. Examples: * 1) <root><div>abc</div></root> * This is most common the case, user passes in a node pointing to abc, and get back a block representing <div>abc</div> * 2) <root><p><br></p></root> * Common content for empty block, user passes node pointing to <br>, and get back a block representing <p><br></p> * 3) <root>abc</root> * Not common, but does happen. It is still a block in user's view. User passes in abc, and get back a start-end block representing abc * NOTE: abc could be just one node. However, since it is not a html block, it is more appropriate to use start-end block although they point to same node * 4) <root><div>abc<br>123</div></root> * A bit tricky, but can happen when user use Ctrl+Enter which simply inserts a <BR> to create a link break. There're two blocks: * block1: 1) abc<br> block2: 123 * 5) <root><div>abc<div>123</div></div></root> * Nesting div and there is text node in same level as a DIV. Two blocks: 1) abc 2) <div>123</div> * 6) <root><div>abc<span>123<br>456</span></div></root> * This is really tricky. Essentially there is a <BR> in middle of a span breaking the span into two blocks; * block1: abc<span>123<br> block2: 456 * In summary, given any arbitrary node (leaf), to identify the head and tail of the block, following rules need to be followed: * 1) to identify the head, it needs to crawl DOM tre left/up till a block node or BR is encountered * 2) same for identifying tail * 3) should also apply a block ceiling, meaning as it crawls up, it should stop at a block node * @param rootNode Root node of the scope, the block element will be inside of this node * @param node The node to get BlockElement start from */ function getBlockElementAtNode(rootNode, node) { if (!(0, contains_1.default)(rootNode, node)) { return null; } // Identify the containing block. This serves as ceiling for traversing down below // NOTE: this container block could be just the rootNode, // which cannot be used to create block element. We will special case handle it later on var containerBlockNode = StartEndBlockElement_1.default.getBlockContext(node); if (!containerBlockNode) { return null; } else if (containerBlockNode == node) { return new NodeBlockElement_1.default(containerBlockNode); } // Find the head and leaf node in the block var headNode = findHeadTailLeafNode(node, containerBlockNode, false /*isTail*/); var tailNode = findHeadTailLeafNode(node, containerBlockNode, true /*isTail*/); // At this point, we have the head and tail of a block, here are some examples and where head and tail point to // 1) <root><div>hello<br></div></root>, head: hello, tail: <br> // 2) <root><div>hello<span style="font-family: Arial">world</span></div></root>, head: hello, tail: world // Both are actually completely and exclusively wrapped in a parent div, and can be represented with a Node block // So we shall try to collapse as much as we can to the nearest common ancestor var nodes = (0, collapseNodes_1.default)(rootNode, headNode, tailNode, false /*canSplitParent*/); headNode = nodes[0]; tailNode = nodes[nodes.length - 1]; if (headNode.parentNode != tailNode.parentNode) { // Un-Balanced start and end, create a start-end block return new StartEndBlockElement_1.default(rootNode, headNode, tailNode); } else { // Balanced start and end (point to same parent), need to see if further collapsing can be done while (!headNode.previousSibling && !tailNode.nextSibling) { var parentNode = headNode.parentNode; if (parentNode == containerBlockNode) { // Has reached the container block if (containerBlockNode != rootNode) { // If the container block is not the root, use the container block headNode = tailNode = parentNode; } break; } else if (parentNode && parentNode != rootNode) { // Continue collapsing to parent headNode = tailNode = parentNode; } else { break; } } // If head and tail are same and it is a block element, create NodeBlock, otherwise start-end block return headNode == tailNode && (0, isBlockElement_1.default)(headNode) ? new NodeBlockElement_1.default(headNode) : new StartEndBlockElement_1.default(rootNode, headNode, tailNode); } } exports.default = getBlockElementAtNode; /** * Given a node and container block, identify the first/last leaf node * A leaf node is defined as deepest first/last node in a block * i.e. <div><span style="font-family: Arial">abc</span></div>, abc is the head leaf of the block * Often <br> or a child <div> is used to create a block. In that case, the leaf after the sibling div or br should be the head leaf * i.e. <div>123<br>abc</div>, abc is the head of a block because of a previous sibling <br> * i.e. <div><div>123</div>abc</div>, abc is also the head of a block because of a previous sibling <div> */ function findHeadTailLeafNode(node, containerBlockNode, isTail) { var result = node; if ((0, getTagOfNode_1.default)(result) == 'BR' && isTail) { return result; } while (result) { var sibling = node; while (node.parentNode && !(sibling = isTail ? node.nextSibling : node.previousSibling)) { node = node.parentNode; if (node == containerBlockNode) { return result; } } while (sibling) { if ((0, isBlockElement_1.default)(sibling)) { return result; } else if ((0, getTagOfNode_1.default)(sibling) == 'BR') { return isTail ? sibling : result; } node = sibling; sibling = isTail ? node.firstChild : node.lastChild; } result = node; } return result; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/blockElements/getFirstLastBlockElement.ts": /*!*************************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/blockElements/getFirstLastBlockElement.ts ***! \*************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getBlockElementAtNode_1 = __webpack_require__(/*! ./getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts"); /** * Get the first/last BlockElement of under the root node. * If no suitable BlockElement found, returns null * @param rootNode The root node to get BlockElement from * @param isFirst True to get first BlockElement, false to get last BlockElement */ function getFirstLastBlockElement(rootNode, isFirst) { var node = rootNode; do { node = node && (isFirst ? node.firstChild : node.lastChild); } while (node && node.firstChild); return (node && (0, getBlockElementAtNode_1.default)(rootNode, node)) || null; } exports.default = getFirstLastBlockElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardEvent.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardEvent.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var extractClipboardItems_1 = __webpack_require__(/*! ./extractClipboardItems */ "./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardItems.ts"); var extractClipboardItemsForIE_1 = __webpack_require__(/*! ./extractClipboardItemsForIE */ "./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardItemsForIE.ts"); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); var Browser_1 = __webpack_require__(/*! ../utils/Browser */ "./packages/roosterjs-editor-dom/lib/utils/Browser.ts"); /** * @deprecated Use extractClipboardItems and extractClipboardItemsForIE instead * Extract a Clipboard event * @param event The paste event * @param callback Callback function when data is ready * @param options Options to retrieve more items from the event, including HTML string and other customized items * @param rangeBeforePaste Optional range to be removed when pasting in Android * @returns An object with the following properties: * types: Available types from the clipboard event * text: Plain text from the clipboard event * image: Image file from the clipboard event * html: Html string from the clipboard event. When set to null, it means there's no HTML found from the event. * When set to undefined, it means can't retrieve HTML string, there may be HTML string but direct retrieving is * not supported by browser. */ function extractClipboardEvent(event, callback, options, rangeBeforePaste) { var _a; var dataTransfer = event.clipboardData || ((_a = event.target.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView).clipboardData; if (dataTransfer.items) { event.preventDefault(); (0, extractClipboardItems_1.default)((0, toArray_1.default)(dataTransfer.items), options).then(function (clipboardData) { removeContents(rangeBeforePaste); callback(clipboardData); }); } else { (0, extractClipboardItemsForIE_1.default)(dataTransfer, callback, options); } } exports.default = extractClipboardEvent; function removeContents(range) { if (Browser_1.Browser.isAndroid && range) { range.deleteContents(); } } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardItems.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardItems.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); var readFile_1 = __webpack_require__(/*! ../utils/readFile */ "./packages/roosterjs-editor-dom/lib/utils/readFile.ts"); var Browser_1 = __webpack_require__(/*! ../utils/Browser */ "./packages/roosterjs-editor-dom/lib/utils/Browser.ts"); // HTML header to indicate where is the HTML content started from. // Sample header: // Version:0.9 // StartHTML:71 // EndHTML:170 // StartFragment:140 // EndFragment:160 // StartSelection:140 // EndSelection:160 var CLIPBOARD_HTML_HEADER_REGEX = /^Version:[0-9\.]+\s+StartHTML:\s*([0-9]+)\s+EndHTML:\s*([0-9]+)\s+/i; var OTHER_TEXT_TYPE = "text/" /* Text */ + '*'; var EDGE_LINK_PREVIEW = 'link-preview'; var ContentHandlers = (_a = {}, _a["text/html" /* HTML */] = function (data, value) { return (data.rawHtml = Browser_1.Browser.isEdge ? workaroundForEdge(value) : value); }, _a["text/plain" /* PlainText */] = function (data, value) { return (data.text = value); }, _a[OTHER_TEXT_TYPE] = function (data, value, type) { return !!type && (data.customValues[type] = value); }, _a["text/" /* Text */ + EDGE_LINK_PREVIEW] = tryParseLinkPreview, _a); /** * Extract clipboard items to be a ClipboardData object for IE * @param items The clipboard items retrieve from a DataTransfer object * @param callback Callback function when data is ready * @returns An object with the following properties: * types: Available types from the clipboard event * text: Plain text from the clipboard event * image: Image file from the clipboard event * html: Html string from the clipboard event. When set to null, it means there's no HTML found from the event. * When set to undefined, it means can't retrieve HTML string, there may be HTML string but direct retrieving is * not supported by browser. */ function extractClipboardItems(items, options) { var data = { types: [], text: '', image: null, files: [], rawHtml: null, customValues: {}, }; return Promise.all((items || []).map(function (item) { var type = item.type; if (type.indexOf("image/" /* Image */) == 0 && !data.image && item.kind == 'file') { data.types.push(type); data.image = item.getAsFile(); return new Promise(function (resolve) { if (data.image) { (0, readFile_1.default)(data.image, function (dataUrl) { data.imageDataUri = dataUrl; resolve(); }); } else { resolve(); } }); } else if (item.kind == 'file') { return new Promise(function (resolve) { var file = item.getAsFile(); if (!!file) { data.types.push(type); data.files.push(file); } resolve(); }); } else { var customType_1 = getAllowedCustomType(type, options === null || options === void 0 ? void 0 : options.allowedCustomPasteType); var handler_1 = ContentHandlers[type] || (customType_1 ? ContentHandlers[OTHER_TEXT_TYPE] : null); return new Promise(function (resolve) { return handler_1 ? item.getAsString(function (value) { data.types.push(type); handler_1(data, value, customType_1); resolve(); }) : resolve(); }); } })).then(function () { return data; }); } exports.default = extractClipboardItems; /** * Edge sometimes doesn't remove the headers, which cause we paste more things then expected. * So we need to remove it in our code * @param html The HTML string got from clipboard */ function workaroundForEdge(html) { var headerValues = CLIPBOARD_HTML_HEADER_REGEX.exec(html); if ((headerValues === null || headerValues === void 0 ? void 0 : headerValues.length) == 3) { var start = parseInt(headerValues[1]); var end = parseInt(headerValues[2]); if (start > 0 && end > start) { html = html.substring(start, end); } } return html; } function tryParseLinkPreview(data, value) { try { data.customValues[EDGE_LINK_PREVIEW] = value; data.linkPreview = JSON.parse(value); } catch (_a) { } } function getAllowedCustomType(type, allowedCustomPasteType) { var textType = type.indexOf("text/" /* Text */) == 0 ? type.substring("text/" /* Text */.length) : null; var index = allowedCustomPasteType && textType ? allowedCustomPasteType.indexOf(textType) : -1; return textType && index >= 0 ? textType : undefined; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardItemsForIE.ts": /*!***********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardItemsForIE.ts ***! \***********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var readFile_1 = __webpack_require__(/*! ../utils/readFile */ "./packages/roosterjs-editor-dom/lib/utils/readFile.ts"); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); /** * Extract clipboard items to be a ClipboardData object for IE * @param dataTransfer The clipboard items retrieve from a DataTransfer object * @param callback Callback function when data is ready * @returns An object with the following properties: * types: Available types from the clipboard event * text: Plain text from the clipboard event * image: Image file from the clipboard event * html: Html string from the clipboard event. When set to null, it means there's no HTML found from the event. * When set to undefined, it means can't retrieve HTML string, there may be HTML string but direct retrieving is * not supported by browser. */ function extractClipboardItemsForIE(dataTransfer, callback, options) { var _a, _b, _c; var clipboardData = { types: dataTransfer.types ? (0, toArray_1.default)(dataTransfer.types) : [], text: dataTransfer.getData('text'), image: null, files: [], rawHtml: null, customValues: {}, }; for (var i = 0; i < (dataTransfer.files ? dataTransfer.files.length : 0); i++) { var file = dataTransfer.files.item(i); if (((_a = file === null || file === void 0 ? void 0 : file.type) === null || _a === void 0 ? void 0 : _a.indexOf("image/" /* Image */)) == 0) { clipboardData.image = file; break; } } var nextStep = function () { if (clipboardData.image) { (0, readFile_1.default)(clipboardData.image, function (dataUrl) { clipboardData.imageDataUri = dataUrl; callback(clipboardData); }); } else { callback(clipboardData); } }; if ((options === null || options === void 0 ? void 0 : options.getTempDiv) && (options === null || options === void 0 ? void 0 : options.removeTempDiv)) { var div_1 = options.getTempDiv(); div_1.contentEditable = 'true'; div_1.innerHTML = ''; div_1.focus(); (_c = (_b = div_1.ownerDocument) === null || _b === void 0 ? void 0 : _b.defaultView) === null || _c === void 0 ? void 0 : _c.setTimeout(function () { var _a; clipboardData.rawHtml = div_1.innerHTML; (_a = options.removeTempDiv) === null || _a === void 0 ? void 0 : _a.call(options, div_1); nextStep(); }, 0); } else { clipboardData.rawHtml = undefined; nextStep(); } } exports.default = extractClipboardItemsForIE; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/contentTraverser/BodyScoper.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/contentTraverser/BodyScoper.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts"); var getFirstLastBlockElement_1 = __webpack_require__(/*! ../blockElements/getFirstLastBlockElement */ "./packages/roosterjs-editor-dom/lib/blockElements/getFirstLastBlockElement.ts"); var getInlineElementAtNode_1 = __webpack_require__(/*! ../inlineElements/getInlineElementAtNode */ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementAtNode.ts"); var getFirstLastInlineElement_1 = __webpack_require__(/*! ../inlineElements/getFirstLastInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/getFirstLastInlineElement.ts"); /** * @internal * provides a scope object for traversing the entire editor body starting from the beginning */ var BodyScoper = /** @class */ (function () { /** * Construct a new instance of BodyScoper class * @param rootNode Root node of the body * @param startNode The node to start from. If not passed, it will start from the beginning of the body */ function BodyScoper(rootNode, startNode) { this.rootNode = rootNode; this.startNode = (0, contains_1.default)(rootNode, startNode) ? startNode : null; } /** * Get the start block element */ BodyScoper.prototype.getStartBlockElement = function () { return this.startNode ? (0, getBlockElementAtNode_1.default)(this.rootNode, this.startNode) : (0, getFirstLastBlockElement_1.default)(this.rootNode, true /*isFirst*/); }; /** * Get the start inline element */ BodyScoper.prototype.getStartInlineElement = function () { return this.startNode ? (0, getInlineElementAtNode_1.default)(this.rootNode, this.startNode) : (0, getFirstLastInlineElement_1.getFirstInlineElement)(this.rootNode); }; /** * Since the scope is global, all blocks under the root node are in scope */ BodyScoper.prototype.isBlockInScope = function (blockElement) { return (0, contains_1.default)(this.rootNode, blockElement.getStartNode()); }; /** * Since we're at body scope, inline elements never need to be trimmed */ BodyScoper.prototype.trimInlineElement = function (inlineElement) { return inlineElement; }; return BodyScoper; }()); exports.default = BodyScoper; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts": /*!********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts ***! \********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var BodyScoper_1 = __webpack_require__(/*! ./BodyScoper */ "./packages/roosterjs-editor-dom/lib/contentTraverser/BodyScoper.ts"); var EmptyInlineElement_1 = __webpack_require__(/*! ../inlineElements/EmptyInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/EmptyInlineElement.ts"); var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts"); var getInlineElementAtNode_1 = __webpack_require__(/*! ../inlineElements/getInlineElementAtNode */ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementAtNode.ts"); var PartialInlineElement_1 = __webpack_require__(/*! ../inlineElements/PartialInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/PartialInlineElement.ts"); var SelectionBlockScoper_1 = __webpack_require__(/*! ./SelectionBlockScoper */ "./packages/roosterjs-editor-dom/lib/contentTraverser/SelectionBlockScoper.ts"); var SelectionScoper_1 = __webpack_require__(/*! ./SelectionScoper */ "./packages/roosterjs-editor-dom/lib/contentTraverser/SelectionScoper.ts"); var getInlineElementBeforeAfter_1 = __webpack_require__(/*! ../inlineElements/getInlineElementBeforeAfter */ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementBeforeAfter.ts"); var getLeafSibling_1 = __webpack_require__(/*! ../utils/getLeafSibling */ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts"); /** * The provides traversing of content inside editor. * There are two ways to traverse, block by block, or inline element by inline element * Block and inline traversing is independent from each other, meaning if you traverse block by block, it does not change * the current inline element position */ var ContentTraverser = /** @class */ (function () { /** * Create a content traverser for the whole body of given root node * @param scoper Traversing scoper object to help scope the traversing * @param skipTags (Optional) tags that child elements will be skipped */ function ContentTraverser(scoper, skipTags) { this.scoper = scoper; this.skipTags = skipTags; this.currentInline = null; this.currentBlock = null; } /** * Create a content traverser for the whole body of given root node * @param rootNode The root node to traverse in * @param startNode The node to start from. If not passed, it will start from the beginning of the body * @param skipTags (Optional) tags that child elements will be skipped */ ContentTraverser.createBodyTraverser = function (rootNode, startNode, skipTags) { return new ContentTraverser(new BodyScoper_1.default(rootNode, startNode)); }; /** * Create a content traverser for the given selection * @param rootNode The root node to traverse in * @param range The selection range to scope the traversing * @param skipTags (Optional) tags that child elements will be skipped */ ContentTraverser.createSelectionTraverser = function (rootNode, range, skipTags) { return new ContentTraverser(new SelectionScoper_1.default(rootNode, range), skipTags); }; /** * Create a content traverser for a block element which contains the given position * @param rootNode The root node to traverse in * @param position A position inside a block, traversing will be scoped within this block. * If passing a range, the start position of this range will be used * @param startFrom Start position of traversing. The value can be Begin, End, SelectionStart * @param skipTags (Optional) tags that child elements will be skipped */ ContentTraverser.createBlockTraverser = function (rootNode, position, start, skipTags) { if (start === void 0) { start = 3 /* SelectionStart */; } return new ContentTraverser(new SelectionBlockScoper_1.default(rootNode, position, start)); }; Object.defineProperty(ContentTraverser.prototype, "currentBlockElement", { /** * Get current block */ get: function () { // Prepare currentBlock from the scoper if (!this.currentBlock) { this.currentBlock = this.scoper.getStartBlockElement(); } return this.currentBlock; }, enumerable: false, configurable: true }); /** * Get next block element */ ContentTraverser.prototype.getNextBlockElement = function () { return this.getPreviousNextBlockElement(true /*isNext*/); }; /** * Get previous block element */ ContentTraverser.prototype.getPreviousBlockElement = function () { return this.getPreviousNextBlockElement(false /*isNext*/); }; ContentTraverser.prototype.getPreviousNextBlockElement = function (isNext) { var current = this.currentBlockElement; if (!current) { return null; } var leaf = (0, getLeafSibling_1.getLeafSibling)(this.scoper.rootNode, isNext ? current.getEndNode() : current.getStartNode(), isNext, this.skipTags); var newBlock = leaf ? (0, getBlockElementAtNode_1.default)(this.scoper.rootNode, leaf) : null; // Make sure this is right block: // 1) the block is in scope per scoper // 2) the block is after (for next) or before (for previous) the current block // Then: // 1) Re-position current block to newly found block if (newBlock && this.scoper.isBlockInScope(newBlock) && ((isNext && newBlock.isAfter(current)) || (!isNext && current.isAfter(newBlock)))) { this.currentBlock = newBlock; return this.currentBlock; } return null; }; Object.defineProperty(ContentTraverser.prototype, "currentInlineElement", { /** * Current inline element getter */ get: function () { // Retrieve a start inline from scoper if (!this.currentInline) { this.currentInline = this.scoper.getStartInlineElement(); } return this.currentInline instanceof EmptyInlineElement_1.default ? null : this.currentInline; }, enumerable: false, configurable: true }); /** * Get next inline element */ ContentTraverser.prototype.getNextInlineElement = function () { return this.getPreviousNextInlineElement(true /*isNext*/); }; /** * Get previous inline element */ ContentTraverser.prototype.getPreviousInlineElement = function () { return this.getPreviousNextInlineElement(false /*isNext*/); }; ContentTraverser.prototype.getPreviousNextInlineElement = function (isNext) { var current = this.currentInlineElement || this.currentInline; var newInline; if (!current) { return null; } if (current instanceof EmptyInlineElement_1.default) { newInline = (0, getInlineElementBeforeAfter_1.getInlineElementBeforeAfter)(this.scoper.rootNode, current.getStartPosition(), isNext); if (newInline && !current.getParentBlock().contains(newInline.getContainerNode())) { newInline = null; } } else { newInline = getNextPreviousInlineElement(this.scoper.rootNode, current, isNext); newInline = newInline && current && ((isNext && newInline.isAfter(current)) || (!isNext && current.isAfter(newInline))) ? newInline : null; } // For inline, we need to make sure: // 1) it is really next/previous to current // 2) pass on the new inline to this.scoper to do the trimming and we still get back an inline // Then // 1) re-position current inline if (newInline && (newInline = this.scoper.trimInlineElement(newInline))) { this.currentInline = newInline; return this.currentInline; } return null; }; return ContentTraverser; }()); exports.default = ContentTraverser; function getNextPreviousInlineElement(rootNode, current, isNext) { if (!current) { return null; } if (current instanceof PartialInlineElement_1.default) { // if current is partial, get the other half of the inline unless it is no more var result = isNext ? current.nextInlineElement : current.previousInlineElement; if (result) { return result; } } // Get a leaf node after startNode and use that base to find next inline var startNode = current.getContainerNode(); startNode = (0, getLeafSibling_1.getLeafSibling)(rootNode, startNode, isNext); return (0, getInlineElementAtNode_1.default)(rootNode, startNode); } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/contentTraverser/PositionContentSearcher.ts": /*!***************************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/contentTraverser/PositionContentSearcher.ts ***! \***************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var ContentTraverser_1 = __webpack_require__(/*! ./ContentTraverser */ "./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts"); var createRange_1 = __webpack_require__(/*! ../selection/createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts"); // White space matching regex. It matches following chars: // \s: white space // \u00A0: no-breaking white space // \u200B: zero width space // \u3000: full width space (which can come from JPN IME) var WHITESPACE_REGEX = /[\s\u00A0\u200B\u3000]+([^\s\u00A0\u200B\u3000]*)$/i; /** * The class that helps search content around a position */ var PositionContentSearcher = /** @class */ (function () { /** * Create a new CursorData instance * @param rootNode Root node of the whole scope * @param position Start position */ function PositionContentSearcher(rootNode, position) { this.rootNode = rootNode; this.position = position; // The cached text before position that has been read so far this.text = ''; // The cached word before position this.word = ''; // The inline element before position this.inlineBefore = null; // The inline element after position this.inlineAfter = null; // The content traverser used to traverse backwards this.traverser = null; // Backward parsing has completed this.traversingComplete = false; // All inline elements before position that have been read so far this.inlineElements = []; // First non-text inline before position this.nearestNonTextInlineElement = null; } /** * Get the word before position. The word is determined by scanning backwards till the first white space, the portion * between position and the white space is the word before position * @returns The word before position */ PositionContentSearcher.prototype.getWordBefore = function () { var _this = this; if (!this.word) { this.traverse(function () { return _this.word; }); } return this.word || ''; }; /** * Get the inline element before position * @returns The inlineElement before position */ PositionContentSearcher.prototype.getInlineElementBefore = function () { if (!this.inlineBefore) { this.traverse(null); } return this.inlineBefore; }; /** * Get the inline element after position * @returns The inline element after position */ PositionContentSearcher.prototype.getInlineElementAfter = function () { if (!this.inlineAfter) { this.inlineAfter = ContentTraverser_1.default.createBlockTraverser(this.rootNode, this.position).currentInlineElement; } return this.inlineAfter; }; /** * Get X number of chars before position * The actual returned chars may be less than what is requested. * @param length The length of string user want to get, the string always ends at the position, * so this length determines the start position of the string * @returns The actual string we get as a sub string, or the whole string before position when * there is not enough chars in the string */ PositionContentSearcher.prototype.getSubStringBefore = function (length) { var _this = this; if (this.text.length < length) { this.traverse(function () { return _this.text.length >= length; }); } return this.text.substr(Math.max(0, this.text.length - length)); }; /** * Try to get a range matches the given text before the position * @param text The text to match against * @param exactMatch Whether it is an exact match * @returns The range for the matched text, null if unable to find a match */ PositionContentSearcher.prototype.getRangeFromText = function (text, exactMatch) { if (!text) { return null; } var startPosition = null; var endPosition = null; var textIndex = text.length - 1; this.forEachTextInlineElement(function (textInline) { var nodeContent = textInline.getTextContent() || ''; var nodeIndex = nodeContent.length - 1; for (; nodeIndex >= 0 && textIndex >= 0; nodeIndex--) { if (text.charCodeAt(textIndex) == nodeContent.charCodeAt(nodeIndex)) { textIndex--; // on first time when end is matched, set the end of range if (!endPosition) { endPosition = textInline.getStartPosition().move(nodeIndex + 1); } } else if (exactMatch || endPosition) { // Mismatch found when exact match or end already match, so return since matching failed return true; } } // when textIndex == -1, we have a successful complete match if (textIndex == -1) { startPosition = textInline.getStartPosition().move(nodeIndex + 1); return true; } return false; }); return startPosition && endPosition && (0, createRange_1.default)(startPosition, endPosition); }; /** * Get text section before position till stop condition is met. * This offers consumers to retrieve text section by section * The section essentially is just an inline element which has Container element * so that the consumer can remember it for anchoring popup or verification purpose * when position moves out of context etc. * @param stopFunc The callback stop function */ PositionContentSearcher.prototype.forEachTextInlineElement = function (callback) { // We cache all text sections read so far // Every time when you ask for textSection, we start with the cached first // and resort to further reading once we exhausted with the cache if (!this.inlineElements.some(callback)) { this.traverse(callback); } }; /** * Get first non textual inline element before position * @returns First non textual inline element before position or null if no such element exists */ PositionContentSearcher.prototype.getNearestNonTextInlineElement = function () { var _this = this; if (!this.nearestNonTextInlineElement) { this.traverse(function () { return _this.nearestNonTextInlineElement; }); } return this.nearestNonTextInlineElement; }; /** * Continue traversing backward till stop condition is met or begin of block is reached */ PositionContentSearcher.prototype.traverse = function (callback) { this.traverser = this.traverser || ContentTraverser_1.default.createBlockTraverser(this.rootNode, this.position); if (!this.traverser || this.traversingComplete) { return; } var previousInline = this.traverser.getPreviousInlineElement(); while (!this.traversingComplete) { this.inlineBefore = this.inlineBefore || previousInline; if (previousInline && previousInline.isTextualInlineElement()) { var textContent = previousInline.getTextContent(); // build the word before position if it is not built yet if (!this.word) { // Match on the white space, the portion after space is on the index of 1 of the matched result // (index at 0 is whole match result, index at 1 is the word) var matches = WHITESPACE_REGEX.exec(textContent); if (matches && matches.length == 2) { this.word = matches[1] + this.text; } } this.text = textContent + this.text; this.inlineElements.push(previousInline); // Check if stop condition is met if (callback && callback(previousInline)) { break; } } else { this.nearestNonTextInlineElement = previousInline; this.traversingComplete = true; if (!this.word) { // if parsing is done, whatever we get so far in this.cachedText should also be in this.cachedWordBeforeCursor this.word = this.text; } // When a non-textual inline element, or null is seen, we consider parsing complete // TODO: we may need to change this if there is a future need to parse beyond text, i.e. // we have aaa @someone bbb, and we want to read the text before @someone break; } previousInline = this.traverser.getPreviousInlineElement(); } }; return PositionContentSearcher; }()); exports.default = PositionContentSearcher; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/contentTraverser/SelectionBlockScoper.ts": /*!************************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/contentTraverser/SelectionBlockScoper.ts ***! \************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var EmptyInlineElement_1 = __webpack_require__(/*! ../inlineElements/EmptyInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/EmptyInlineElement.ts"); var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts"); var getInlineElementAtNode_1 = __webpack_require__(/*! ../inlineElements/getInlineElementAtNode */ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementAtNode.ts"); var NodeBlockElement_1 = __webpack_require__(/*! ../blockElements/NodeBlockElement */ "./packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var getInlineElementBeforeAfter_1 = __webpack_require__(/*! ../inlineElements/getInlineElementBeforeAfter */ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementBeforeAfter.ts"); var getFirstLastInlineElement_1 = __webpack_require__(/*! ../inlineElements/getFirstLastInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/getFirstLastInlineElement.ts"); /** * @internal * This provides traversing content in a selection start block * This is commonly used for those cursor context sensitive plugin, * they want to know text being typed at cursor * This provides a scope for parsing from cursor position up to begin of the selection block */ var SelectionBlockScoper = /** @class */ (function () { /** * Create a new instance of SelectionBlockScoper class * @param rootNode The root node of the whole scope * @param position Position of the selection start * @param startFrom Where to start, can be Begin, End, SelectionStart */ function SelectionBlockScoper(rootNode, position, startFrom) { this.rootNode = rootNode; this.startFrom = startFrom; if ((0, safeInstanceOf_1.default)(position, 'Range')) { position = Position_1.default.getStart(position); } this.position = position.normalize(); this.block = (0, getBlockElementAtNode_1.default)(this.rootNode, this.position.node); } /** * Get the start block element */ SelectionBlockScoper.prototype.getStartBlockElement = function () { return this.block; }; /** * Get the start inline element * The start inline refers to inline before the selection start * The reason why we choose the one before rather after is, when cursor is at the end of a paragraph, * the one after likely will point to inline in next paragraph which may be null if the cursor is at bottom of editor */ SelectionBlockScoper.prototype.getStartInlineElement = function () { if (this.block) { switch (this.startFrom) { case 0 /* Begin */: case 1 /* End */: case 2 /* DomEnd */: return getFirstLastInlineElementFromBlockElement(this.block, this.startFrom == 0 /* Begin */); case 3 /* SelectionStart */: // Get the inline before selection start point, and ensure it falls in the selection block var startInline = (0, getInlineElementBeforeAfter_1.getInlineElementAfter)(this.rootNode, this.position); return startInline && this.block.contains(startInline.getContainerNode()) ? startInline : new EmptyInlineElement_1.default(this.position, this.block); } } return null; }; /** * Check if the given block element is in current scope * @param blockElement The block element to check */ SelectionBlockScoper.prototype.isBlockInScope = function (blockElement) { return this.block && blockElement ? this.block.equals(blockElement) : false; }; /** * Trim the incoming inline element, and return an inline element * This just tests and return the inline element if it is in block * This is a block scoper, which is not like selection scoper where it may cut an inline element in half * A block scoper does not cut an inline in half */ SelectionBlockScoper.prototype.trimInlineElement = function (inlineElement) { return this.block && inlineElement && this.block.contains(inlineElement.getContainerNode()) ? inlineElement : null; }; return SelectionBlockScoper; }()); exports.default = SelectionBlockScoper; /** * Get first/last InlineElement of the given BlockElement * @param block The BlockElement to get InlineElement from * @param isFirst True to get first InlineElement, false to get last InlineElement */ function getFirstLastInlineElementFromBlockElement(block, isFirst) { if (block instanceof NodeBlockElement_1.default) { var blockNode = block.getStartNode(); return isFirst ? (0, getFirstLastInlineElement_1.getFirstInlineElement)(blockNode) : (0, getFirstLastInlineElement_1.getLastInlineElement)(blockNode); } else { return (0, getInlineElementAtNode_1.default)(block, isFirst ? block.getStartNode() : block.getEndNode()); } } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/contentTraverser/SelectionScoper.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/contentTraverser/SelectionScoper.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts"); var PartialInlineElement_1 = __webpack_require__(/*! ../inlineElements/PartialInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/PartialInlineElement.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var getInlineElementBeforeAfter_1 = __webpack_require__(/*! ../inlineElements/getInlineElementBeforeAfter */ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementBeforeAfter.ts"); /** * @internal * This is selection scoper that provide a start inline as the start of the selection * and checks if a block falls in the selection (isBlockInScope) * last trimInlineElement to trim any inline element to return a partial that falls in the selection */ var SelectionScoper = /** @class */ (function () { /** * Create a new instance of SelectionScoper class * @param rootNode The root node of the content * @param range The selection range to scope to */ function SelectionScoper(rootNode, range) { this.rootNode = rootNode; this.startBlock = null; this.startInline = null; this.start = Position_1.default.getStart(range).normalize(); this.end = Position_1.default.getEnd(range).normalize(); } /** * Provide a start block as the first block after the cursor */ SelectionScoper.prototype.getStartBlockElement = function () { if (!this.startBlock) { this.startBlock = (0, getBlockElementAtNode_1.default)(this.rootNode, this.start.node); } return this.startBlock; }; /** * Provide a start inline as the first inline after the cursor */ SelectionScoper.prototype.getStartInlineElement = function () { if (!this.startInline) { this.startInline = this.trimInlineElement((0, getInlineElementBeforeAfter_1.getInlineElementAfter)(this.rootNode, this.start)); } return this.startInline; }; /** * Checks if a block completely falls in the selection * @param block The BlockElement to check */ SelectionScoper.prototype.isBlockInScope = function (block) { if (!block) { return false; } var inScope = false; var selStartBlock = this.getStartBlockElement(); if (this.start.equalTo(this.end)) { inScope = !!selStartBlock && selStartBlock.equals(block); } else { var selEndBlock = (0, getBlockElementAtNode_1.default)(this.rootNode, this.end.node); // There are three cases that are considered as "block in scope" // 1) The start of selection falls on the block // 2) The end of selection falls on the block // 3) the block falls in-between selection start and end inScope = !!selStartBlock && !!selEndBlock && (block.equals(selStartBlock) || block.equals(selEndBlock) || (block.isAfter(selStartBlock) && selEndBlock.isAfter(block))); } return inScope; }; /** * Trim an incoming inline. If it falls completely outside selection, return null * otherwise return a partial that represents the portion that falls in the selection * @param inline The InlineElement to check */ SelectionScoper.prototype.trimInlineElement = function (inline) { if (!inline || this.start.equalTo(this.end)) { return null; } // Temp code. Will be changed to using InlineElement.getStart/EndPosition() soon var start = inline.getStartPosition(); var end = inline.getEndPosition(); if (start.isAfter(this.end) || this.start.isAfter(end)) { return null; } var startPartial = false; var endPartial = false; if (this.start.isAfter(start)) { start = this.start; startPartial = true; } if (end.isAfter(this.end)) { end = this.end; endPartial = true; } return start.isAfter(end) || start.equalTo(end) ? null : startPartial || endPartial ? new PartialInlineElement_1.default(inline, startPartial ? start : undefined, endPartial ? end : undefined) : inline; }; return SelectionScoper; }()); exports.default = SelectionScoper; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/edit/adjustInsertPosition.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/edit/adjustInsertPosition.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var changeElementTag_1 = __webpack_require__(/*! ../utils/changeElementTag */ "./packages/roosterjs-editor-dom/lib/utils/changeElementTag.ts"); var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var ContentTraverser_1 = __webpack_require__(/*! ../contentTraverser/ContentTraverser */ "./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts"); var createRange_1 = __webpack_require__(/*! ../selection/createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts"); var findClosestElementAncestor_1 = __webpack_require__(/*! ../utils/findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts"); var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts"); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var isNodeEmpty_1 = __webpack_require__(/*! ../utils/isNodeEmpty */ "./packages/roosterjs-editor-dom/lib/utils/isNodeEmpty.ts"); var isPositionAtBeginningOf_1 = __webpack_require__(/*! ../selection/isPositionAtBeginningOf */ "./packages/roosterjs-editor-dom/lib/selection/isPositionAtBeginningOf.ts"); var isVoidHtmlElement_1 = __webpack_require__(/*! ../utils/isVoidHtmlElement */ "./packages/roosterjs-editor-dom/lib/utils/isVoidHtmlElement.ts"); var LinkInlineElement_1 = __webpack_require__(/*! ../inlineElements/LinkInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/LinkInlineElement.ts"); var moveChildNodes_1 = __webpack_require__(/*! ../utils/moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts"); var pasteTable_1 = __webpack_require__(/*! ../table/pasteTable */ "./packages/roosterjs-editor-dom/lib/table/pasteTable.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var PositionContentSearcher_1 = __webpack_require__(/*! ../contentTraverser/PositionContentSearcher */ "./packages/roosterjs-editor-dom/lib/contentTraverser/PositionContentSearcher.ts"); var queryElements_1 = __webpack_require__(/*! ../utils/queryElements */ "./packages/roosterjs-editor-dom/lib/utils/queryElements.ts"); var splitTextNode_1 = __webpack_require__(/*! ../utils/splitTextNode */ "./packages/roosterjs-editor-dom/lib/utils/splitTextNode.ts"); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); var unwrap_1 = __webpack_require__(/*! ../utils/unwrap */ "./packages/roosterjs-editor-dom/lib/utils/unwrap.ts"); var wrap_1 = __webpack_require__(/*! ../utils/wrap */ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts"); var splitParentNode_1 = __webpack_require__(/*! ../utils/splitParentNode */ "./packages/roosterjs-editor-dom/lib/utils/splitParentNode.ts"); var NOT_EDITABLE_SELECTOR = '[contenteditable=false]'; var adjustSteps = [ adjustInsertPositionForHyperLink, adjustInsertPositionForStructuredNode, adjustInsertPositionForParagraph, adjustInsertPositionForVoidElement, adjustInsertPositionForMoveCursorOutOfALink, adjustInsertPositionForNotEditableNode, adjustInsertPositionForTable, ]; /** * Adjust position for A tag don't be nested inside another A tag. */ function adjustInsertPositionForHyperLink(root, nodeToInsert, position, range) { var _a, _b; var blockElement = (0, getBlockElementAtNode_1.default)(root, position.node); if (blockElement) { // Find the first tag within current block which covers current selection // If there are more than one nested, let's handle the first one only since that is not a common scenario. var anchor = (0, queryElements_1.default)(root, 'a[href]', null /*forEachCallback*/, 1 /* OnSelection */, (0, createRange_1.default)(position)).filter(function (a) { return blockElement.contains(a); })[0]; // If this is about to insert node to an empty A tag, clear the A tag and reset position if (anchor && (0, isNodeEmpty_1.default)(anchor)) { position = new Position_1.default(anchor, -2 /* Before */); safeRemove(anchor); anchor = null; } // If this is about to insert nodes which contains A tag into another A tag, need to break current A tag // otherwise we will have nested A tags which is a wrong HTML structure if (anchor && ((_a = nodeToInsert) === null || _a === void 0 ? void 0 : _a.querySelector) && ((_b = nodeToInsert) === null || _b === void 0 ? void 0 : _b.querySelector('a[href]'))) { var normalizedPosition = position.normalize(); var parentNode = normalizedPosition.node.parentNode; var nextNode = normalizedPosition.node.nodeType == 3 /* Text */ ? (0, splitTextNode_1.default)(normalizedPosition.node, normalizedPosition.offset, false /*returnFirstPart*/) : normalizedPosition.isAtEnd ? normalizedPosition.node.nextSibling : normalizedPosition.node; var splitter = root.ownerDocument.createTextNode(''); parentNode.insertBefore(splitter, nextNode); while (splitter && (0, contains_1.default)(anchor, splitter)) { splitter = (0, splitParentNode_1.splitBalancedNodeRange)(splitter); } if (splitter) { position = new Position_1.default(splitter, -2 /* Before */); safeRemove(splitter); } } } return position; } /** * Adjust position for a node don't be nested inside tags like BR, LI, TD. */ function adjustInsertPositionForStructuredNode(root, nodeToInsert, position, range) { var rootNodeToInsert = nodeToInsert; var isFragment = false; if (rootNodeToInsert.nodeType == 11 /* DocumentFragment */) { isFragment = true; var rootNodes = (0, toArray_1.default)(rootNodeToInsert.childNodes).filter(function (n) { return (0, getTagOfNode_1.default)(n) != 'BR'; }); rootNodeToInsert = rootNodes.length == 1 ? rootNodes[0] : null; } var tag = (0, getTagOfNode_1.default)(rootNodeToInsert); var hasBrNextToRoot = tag && rootNodeToInsert && (0, getTagOfNode_1.default)(rootNodeToInsert.nextSibling) == 'BR'; var listItem = (0, findClosestElementAncestor_1.default)(position.node, root, 'LI'); var listNode = listItem && (0, findClosestElementAncestor_1.default)(listItem, root, 'OL,UL'); var tdNode = (0, findClosestElementAncestor_1.default)(position.node, root, 'TD,TH'); if (tag == 'LI') { tag = listNode ? (0, getTagOfNode_1.default)(listNode) : 'UL'; rootNodeToInsert = (0, wrap_1.default)(rootNodeToInsert, tag); } if ((tag == 'OL' || tag == 'UL') && rootNodeToInsert && (0, getTagOfNode_1.default)(rootNodeToInsert.firstChild) == 'LI') { var shouldInsertListAsText = !rootNodeToInsert.firstChild.nextSibling && !hasBrNextToRoot; if (hasBrNextToRoot && rootNodeToInsert.parentNode) { safeRemove(rootNodeToInsert.nextSibling); } if (shouldInsertListAsText) { (0, unwrap_1.default)(rootNodeToInsert.firstChild); (0, unwrap_1.default)(rootNodeToInsert); } else if ((0, getTagOfNode_1.default)(listNode) == tag) { (0, unwrap_1.default)(rootNodeToInsert); position = new Position_1.default(listItem, (0, isPositionAtBeginningOf_1.default)(position, listItem) ? -2 /* Before */ : -3 /* After */); } } if (isFragment && tag == 'TABLE' && tdNode) { (0, pasteTable_1.default)(tdNode, rootNodeToInsert, position, range); position = new Position_1.default(rootNodeToInsert, 0); (0, moveChildNodes_1.default)(nodeToInsert); } return position; } /** * Change P tag to DIV, when a new node when insert node. */ function adjustInsertPositionForParagraph(root, nodeToInsert, position, range) { if ((0, getTagOfNode_1.default)(position.node) == 'P') { // Insert into a P tag may cause issues when the inserted content contains any block element. // Change P tag to DIV to make sure it works well var pos = position.normalize(); var div = (0, changeElementTag_1.default)(position.node, 'div'); if (pos.node != div) { position = pos; } } return position; } /** * Adjust position for a node that can have children. */ function adjustInsertPositionForVoidElement(root, nodeToInsert, position, range) { if ((0, isVoidHtmlElement_1.default)(position.node)) { position = new Position_1.default(position.node, position.isAtEnd ? -3 /* After */ : -2 /* Before */); } return position; } /** * Adjust the position cursor out of link when a new node is inserted. */ function adjustInsertPositionForMoveCursorOutOfALink(root, nodeToInsert, position, range) { if (range && range.collapsed) { var searcher = new PositionContentSearcher_1.default(root, Position_1.default.getStart(range)); var inlineElementBefore = searcher.getInlineElementBefore(); var inlineElementAfter = searcher.getInlineElementAfter(); if (inlineElementBefore instanceof LinkInlineElement_1.default) { position = new Position_1.default(inlineElementBefore.getContainerNode(), -3 /* After */); } else if (inlineElementAfter instanceof LinkInlineElement_1.default) { position = new Position_1.default(inlineElementAfter.getContainerNode(), -2 /* Before */); } } return position; } /** * Adjust the position cursor out of a not contenteditable element. */ function adjustInsertPositionForNotEditableNode(root, nodeToInsert, position, range) { var _a; if (!((_a = position.element) === null || _a === void 0 ? void 0 : _a.isContentEditable)) { var nonEditableElement = void 0; var lastNonEditableElement = (0, findClosestElementAncestor_1.default)(position.node, root, NOT_EDITABLE_SELECTOR); while (lastNonEditableElement) { nonEditableElement = lastNonEditableElement; lastNonEditableElement = (nonEditableElement === null || nonEditableElement === void 0 ? void 0 : nonEditableElement.parentElement) ? (0, findClosestElementAncestor_1.default)(nonEditableElement.parentElement, root, NOT_EDITABLE_SELECTOR) : null; } if (nonEditableElement) { position = new Position_1.default(nonEditableElement, -3 /* After */); return adjustInsertPositionForNotEditableNode(root, nodeToInsert, position, range); } } return position; } /** * Adjust the position of a table to be one line after another table. */ function adjustInsertPositionForTable(root, nodeToInsert, position, range) { if ((nodeToInsert.childNodes.length == 1 && (0, getTagOfNode_1.default)(nodeToInsert.childNodes[0]) == 'TABLE') || (0, getTagOfNode_1.default)(nodeToInsert) == 'TABLE') { var element = position.element; var posBefore = new Position_1.default(element, -2 /* Before */); var rangeToTraverse = (0, createRange_1.default)(posBefore, position); var contentTraverser = ContentTraverser_1.default.createSelectionTraverser(root, rangeToTraverse); var blockElement = contentTraverser && contentTraverser.currentBlockElement; if (blockElement) { var nextBlockElement = blockElement; while (!nextBlockElement) { nextBlockElement = contentTraverser.getNextBlockElement(); if (nextBlockElement) { blockElement = nextBlockElement; } } var prevElement = blockElement === null || blockElement === void 0 ? void 0 : blockElement.getEndNode(); if (prevElement && (0, findClosestElementAncestor_1.default)(prevElement, root, 'TABLE')) { var tempRange = (0, createRange_1.default)(position); tempRange.collapse(false /* toStart */); var br = root.ownerDocument.createElement('br'); tempRange.insertNode(br); tempRange = (0, createRange_1.default)(br); position = Position_1.default.getEnd(tempRange); } } } return position; } /** * * @param root the contentDiv of the ditor * @param nodeToInsert the node to be inserted * @param position the position of the node to be inserted * @param range the range current or cached range of the editor * @returns the adjusted position of the inserted node */ function adjustInsertPositionBySteps(root, nodeToInsert, position, range) { adjustSteps.forEach(function (handler) { position = handler(root, nodeToInsert, position, range); }); return position; } exports.default = adjustInsertPositionBySteps; function safeRemove(node) { var _a; (_a = node === null || node === void 0 ? void 0 : node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node); } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/edit/deleteSelectedContent.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/edit/deleteSelectedContent.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var arrayPush_1 = __webpack_require__(/*! ../jsUtils/arrayPush */ "./packages/roosterjs-editor-dom/lib/jsUtils/arrayPush.ts"); var collapseNodesInRegion_1 = __webpack_require__(/*! ../region/collapseNodesInRegion */ "./packages/roosterjs-editor-dom/lib/region/collapseNodesInRegion.ts"); var getRegionsFromRange_1 = __webpack_require__(/*! ../region/getRegionsFromRange */ "./packages/roosterjs-editor-dom/lib/region/getRegionsFromRange.ts"); var getSelectionRangeInRegion_1 = __webpack_require__(/*! ../region/getSelectionRangeInRegion */ "./packages/roosterjs-editor-dom/lib/region/getSelectionRangeInRegion.ts"); var mergeBlocksInRegion_1 = __webpack_require__(/*! ../region/mergeBlocksInRegion */ "./packages/roosterjs-editor-dom/lib/region/mergeBlocksInRegion.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var queryElements_1 = __webpack_require__(/*! ../utils/queryElements */ "./packages/roosterjs-editor-dom/lib/utils/queryElements.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var splitTextNode_1 = __webpack_require__(/*! ../utils/splitTextNode */ "./packages/roosterjs-editor-dom/lib/utils/splitTextNode.ts"); /** * Delete selected content, and return the new position to select * @param core The EditorCore object. * @param range The range to delete */ function deleteSelectedContent(root, range) { var nodeBefore = null; // 1. TABLE and TR node in selected should be deleted. It is possible we don't detect them from step 2 // since table cells will fall in to different regions var nodesToDelete = (0, queryElements_1.default)(root, 'table,tr', null /*callback*/, 2 /* InSelection */, range); // 2. Loop all selected regions, find out those nodes need to be deleted and merged. // We don't delete them directly here because delete node from one region may cause selection range // another region becomes invalid. So we delay the process of deletion. var regions = (0, getRegionsFromRange_1.default)(root, range, 0 /* Table */); var nodesPairToMerge = regions .map(function (region) { var regionRange = (0, getSelectionRangeInRegion_1.default)(region); if (!regionRange) { return null; } var startContainer = regionRange.startContainer, endContainer = regionRange.endContainer, startOffset = regionRange.startOffset, endOffset = regionRange.endOffset, commonAncestorContainer = regionRange.commonAncestorContainer; // Disallow merging of readonly elements if ((0, safeInstanceOf_1.default)(commonAncestorContainer, 'HTMLElement') && !commonAncestorContainer.isContentEditable) { return null; } // Make sure there are node before and after the merging point. // This is required by mergeBlocksInRegion API. // This may create some empty text node as anchor var _a = ensureBeforeAndAfter(endContainer, endOffset, false /*isStart*/), beforeEnd = _a[0], afterEnd = _a[1]; var _b = ensureBeforeAndAfter(startContainer, startOffset, true /*isStart*/), beforeStart = _b[0], afterStart = _b[1]; nodeBefore = nodeBefore || beforeStart; // Find out all nodes to be deleted var nodes = (0, collapseNodesInRegion_1.default)(region, [afterStart, beforeEnd]); (0, arrayPush_1.default)(nodesToDelete, nodes); return { region: region, beforeStart: beforeStart, afterEnd: afterEnd }; }) .filter(function (x) { return !!x; }); // 3. Delete all nodes that we found, whose parent is editable nodesToDelete.forEach(function (node) { var _a; return ((_a = node.parentElement) === null || _a === void 0 ? void 0 : _a.isContentEditable) && node.parentElement.removeChild(node); }); // 4. Merge lines for each region, so that after we don't see extra line breaks nodesPairToMerge.forEach(function (nodes) { if (nodes) { (0, mergeBlocksInRegion_1.default)(nodes.region, nodes.beforeStart, nodes.afterEnd); } }); return nodeBefore && new Position_1.default(nodeBefore, -1 /* End */); } exports.default = deleteSelectedContent; function ensureBeforeAndAfter(node, offset, isStart) { var _a, _b; if ((0, safeInstanceOf_1.default)(node, 'Text')) { var newNode = (0, splitTextNode_1.default)(node, offset, isStart); return isStart ? [newNode, node] : [node, newNode]; } else { var nodeBefore = node.childNodes[offset - 1]; var nodeAfter = node.childNodes[offset]; // Condition 1: node child nodes // ("I" means cursor; "o" means a DOM node, "[ ]" means a parent node) // [ I ] // need to use parent node instead to convert to condition 2 if (!nodeBefore && !nodeAfter) { if (isStart) { nodeAfter = node; nodeBefore = nodeAfter.previousSibling; } else { nodeBefore = node; nodeAfter = nodeBefore.nextSibling; } } // Condition 2: Either nodeBefore or nodeAfter is null (XOR case) // [ o I ] or [ I o] // need to add empty text node to convert to condition 3 if ((nodeBefore || nodeAfter) && (!nodeBefore || !nodeAfter)) { var emptyNode = node.ownerDocument.createTextNode(''); (_b = (_a = (nodeBefore || nodeAfter)) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(emptyNode, nodeAfter); if (nodeBefore) { nodeAfter = emptyNode; } else { nodeBefore = emptyNode; } } // Condition 3: Both nodeBefore and nodeAfter are not null // [o I o] // return the nodes return [nodeBefore, nodeAfter]; } } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/edit/getTextContent.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/edit/getTextContent.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var ContentTraverser_1 = __webpack_require__(/*! ../contentTraverser/ContentTraverser */ "./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts"); /** * get block element's text content. * @param rootNode Root node that the get the textContent of. * @returns text content of given text content. */ function getTextContent(rootNode) { var traverser = ContentTraverser_1.default.createBodyTraverser(rootNode); var block = traverser && traverser.currentBlockElement; var textContent = []; while (block) { textContent.push(block.getTextContent()); block = traverser.getNextBlockElement(); } return textContent.join('\n'); } exports.default = getTextContent; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/entity/commitEntity.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/entity/commitEntity.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var CONTENT_EDITABLE = 'contenteditable'; /** * Commit information of an entity (type, isReadonly, id) into the wrapper node as CSS Classes * @param wrapper The entity wrapper element * @param type Entity type * @param isReadonly Whether this is a readonly entity * @param id Optional Id of the entity */ function commitEntity(wrapper, type, isReadonly, id) { if (wrapper) { wrapper.className = "_Entity" /* ENTITY_INFO_NAME */ + " " + "_EType_" /* ENTITY_TYPE_PREFIX */ + type + " " + (id ? "" + "_EId_" /* ENTITY_ID_PREFIX */ + id + " " : '') + "_EReadonly_" /* ENTITY_READONLY_PREFIX */ + (isReadonly ? '1' : '0'); if (isReadonly) { wrapper.contentEditable = 'false'; } else if (wrapper.getAttribute(CONTENT_EDITABLE)) { wrapper.removeAttribute(CONTENT_EDITABLE); } } } exports.default = commitEntity; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/entity/entityPlaceholderUtils.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/entity/entityPlaceholderUtils.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.restoreContentWithEntityPlaceholder = exports.moveContentWithEntityPlaceholders = exports.createEntityPlaceholder = void 0; var getEntityFromElement_1 = __webpack_require__(/*! ./getEntityFromElement */ "./packages/roosterjs-editor-dom/lib/entity/getEntityFromElement.ts"); var getEntitySelector_1 = __webpack_require__(/*! ./getEntitySelector */ "./packages/roosterjs-editor-dom/lib/entity/getEntitySelector.ts"); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var EntityPlaceHolderTagName = 'ENTITY-PLACEHOLDER'; /** * Create a placeholder comment node for entity * @param entity The entity to create placeholder from * @returns A placeholder comment node as */ function createEntityPlaceholder(entity) { var placeholder = entity.wrapper.ownerDocument.createElement(EntityPlaceHolderTagName); placeholder.id = entity.id; return placeholder; } exports.createEntityPlaceholder = createEntityPlaceholder; /** * Move content from a container into a new Document fragment, and try keep entities to be reusable by creating placeholder * for them in the document fragment. * If an entity is directly under root container, the whole entity can be reused and no need to move it at all. * If an entity is not directly under root container, it is still reusable, but it may need some movement. * In any case, entities will be replaced with a placeholder in the target document fragment. * We will use an entity map (the "entities" parameter) to save the map from entity id to its wrapper element. * @param root The root element * @param entities A map from entity id to entity wrapper element * @returns A new document fragment contains all the content and entity placeholders */ function moveContentWithEntityPlaceholders(root, entities) { var entitySelector = (0, getEntitySelector_1.default)(); var fragment = root.ownerDocument.createDocumentFragment(); var next = null; var _loop_1 = function (child) { var entity; var nodeToAppend = child; next = child.nextSibling; if ((0, safeInstanceOf_1.default)(child, 'HTMLElement')) { if ((entity = (0, getEntityFromElement_1.default)(child))) { nodeToAppend = getPlaceholder(entity, entities); } else { child.querySelectorAll(entitySelector).forEach(function (wrapper) { var _a; if ((entity = (0, getEntityFromElement_1.default)(wrapper))) { var placeholder = getPlaceholder(entity, entities); (_a = wrapper.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(placeholder, wrapper); } }); } } fragment.appendChild(nodeToAppend); }; for (var child = root.firstChild; child; child = next) { _loop_1(child); } fragment.normalize(); return fragment; } exports.moveContentWithEntityPlaceholders = moveContentWithEntityPlaceholders; /** * Restore HTML content from a document fragment that may contain entity placeholders. * @param source Source document fragment that contains HTML content and entity placeholders * @param target Target container, usually to be editor root container * @param entities A map from entity id to entity wrapper, used for reusing existing DOM structure for entity * @param insertClonedNode When pass true, merge with a cloned copy of the nodes from source fragment rather than the nodes themselves @default false */ function restoreContentWithEntityPlaceholder(source, target, entities, insertClonedNode) { var anchor = target.firstChild; entities = entities || {}; var _loop_2 = function (current) { var wrapper = null; var next = current.nextSibling; var id = tryGetIdFromEntityPlaceholder(current); if (id && (wrapper = entities[current.id])) { anchor = removeUntil(anchor, wrapper); if (anchor) { anchor = anchor.nextSibling; } else { target.appendChild(wrapper); } } else { var nodeToInsert = insertClonedNode ? current.cloneNode(true /*deep*/) : current; target.insertBefore(nodeToInsert, anchor); if ((0, safeInstanceOf_1.default)(nodeToInsert, 'HTMLElement')) { nodeToInsert.querySelectorAll(EntityPlaceHolderTagName).forEach(function (placeholder) { var _a; wrapper = entities[placeholder.id]; if (wrapper) { (_a = placeholder.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(wrapper, placeholder); } }); } } current = next; out_current_1 = current; }; var out_current_1; for (var current = source.firstChild; current;) { _loop_2(current); current = out_current_1; } removeUntil(anchor); } exports.restoreContentWithEntityPlaceholder = restoreContentWithEntityPlaceholder; function removeUntil(anchor, nodeToStop) { var _a; while (anchor && (!nodeToStop || anchor != nodeToStop)) { var nodeToRemove = anchor; anchor = anchor.nextSibling; (_a = nodeToRemove.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(nodeToRemove); } return anchor; } function tryGetIdFromEntityPlaceholder(node) { return (0, getTagOfNode_1.default)(node) == EntityPlaceHolderTagName ? node.id : null; } function getPlaceholder(entity, entities) { var placeholder = createEntityPlaceholder(entity); entities[entity.id] = entity.wrapper; return placeholder; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/entity/getEntityFromElement.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/entity/getEntityFromElement.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Get Entity object from an entity root element * @param element The entity root element. If this element is not an entity root element, * it will return null */ function getEntityFromElement(element) { var _a; var isEntity = false; var type = ''; var id = ''; var isReadonly = false; (_a = element === null || element === void 0 ? void 0 : element.className) === null || _a === void 0 ? void 0 : _a.split(' ').forEach(function (name) { if (name == "_Entity" /* ENTITY_INFO_NAME */) { isEntity = true; } else if (name.indexOf("_EType_" /* ENTITY_TYPE_PREFIX */) == 0) { type = name.substr("_EType_" /* ENTITY_TYPE_PREFIX */.length); } else if (name.indexOf("_EId_" /* ENTITY_ID_PREFIX */) == 0) { id = name.substr("_EId_" /* ENTITY_ID_PREFIX */.length); } else if (name.indexOf("_EReadonly_" /* ENTITY_READONLY_PREFIX */) == 0) { isReadonly = name.substr("_EReadonly_" /* ENTITY_READONLY_PREFIX */.length) == '1'; } }); return isEntity ? { wrapper: element, id: id, type: type, isReadonly: isReadonly, } : null; } exports.default = getEntityFromElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/entity/getEntitySelector.ts": /*!***********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/entity/getEntitySelector.ts ***! \***********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Get a selector string for specified entity type and id * @param type (Optional) Type of entity * @param id (Optional) Id of entity */ function getEntitySelector(type, id) { var typeSelector = type ? "." + "_EType_" /* ENTITY_TYPE_PREFIX */ + type : ''; var idSelector = id ? "." + "_EId_" /* ENTITY_ID_PREFIX */ + id : ''; return '.' + "_Entity" /* ENTITY_INFO_NAME */ + typeSelector + idSelector; } exports.default = getEntitySelector; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/event/cacheGetEventData.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/event/cacheGetEventData.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Gets the cached event data by cache key from event object if there is already one. * Otherwise, call getter function to create one, and cache it. * @param event The event object * @param key Cache key string, need to be unique * @param getter Getter function to get the object when it is not in cache yet */ function cacheGetEventData(event, key, getter) { var result = event && event.eventDataCache && event.eventDataCache.hasOwnProperty(key) ? event.eventDataCache[key] : getter(); if (event) { event.eventDataCache = event.eventDataCache || {}; event.eventDataCache[key] = result; } return result; } exports.default = cacheGetEventData; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/event/clearEventDataCache.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/event/clearEventDataCache.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Clear a cached object by its key from an event object * @param event The event object * @param key The cache key */ function clearEventDataCache(event, key) { if (event && event.eventDataCache) { if (key && event.eventDataCache.hasOwnProperty(key)) { delete event.eventDataCache[key]; } else if (!key) { event.eventDataCache = {}; } } } exports.default = clearEventDataCache; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/event/isCharacterValue.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/event/isCharacterValue.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var isModifierKey_1 = __webpack_require__(/*! ./isModifierKey */ "./packages/roosterjs-editor-dom/lib/event/isModifierKey.ts"); /** * Returns true when the event was fired from a key that produces a character value, otherwise false * This detection is not 100% accurate. event.key is not fully supported by all browsers, and in some browsers (e.g. IE), * event.key is longer than 1 for num pad input. But here we just want to improve performance as much as possible. * So if we missed some case here it is still acceptable. * @param event The keyboard event object */ function isCharacterValue(event) { return !(0, isModifierKey_1.default)(event) && !!event.key && event.key.length == 1; } exports.default = isCharacterValue; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/event/isCtrlOrMetaPressed.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/event/isCtrlOrMetaPressed.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Browser_1 = __webpack_require__(/*! ../utils/Browser */ "./packages/roosterjs-editor-dom/lib/utils/Browser.ts"); var isCtrlOrMetaPressedImpl = Browser_1.Browser.isMac ? function (event) { return event.metaKey; } : function (event) { return event.ctrlKey; }; /** * Check if Ctrl key (Windows) or Meta key (Mac) is pressed for the given Event * @param event A Keyboard event or Mouse event object * @returns True if Ctrl key is pressed on Windows or Meta key is pressed on Mac */ function isCtrlOrMetaPressed(event) { return isCtrlOrMetaPressedImpl(event); } exports.default = isCtrlOrMetaPressed; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/event/isModifierKey.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/event/isModifierKey.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var CTRL_CHAR_CODE = 'Control'; var ALT_CHAR_CODE = 'Alt'; var META_CHAR_CODE = 'Meta'; /** * Returns true when the event was fired from a modifier key, otherwise false * @param event The keyboard event object */ function isModifierKey(event) { var isCtrlKey = event.ctrlKey || event.key === CTRL_CHAR_CODE; var isAltKey = event.altKey || event.key === ALT_CHAR_CODE; var isMetaKey = event.metaKey || event.key === META_CHAR_CODE; return isCtrlKey || isAltKey || isMetaKey; } exports.default = isModifierKey; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/HtmlSanitizer.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/htmlSanitizer/HtmlSanitizer.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var changeElementTag_1 = __webpack_require__(/*! ../utils/changeElementTag */ "./packages/roosterjs-editor-dom/lib/utils/changeElementTag.ts"); var getInheritableStyles_1 = __webpack_require__(/*! ./getInheritableStyles */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/getInheritableStyles.ts"); var getObjectKeys_1 = __webpack_require__(/*! ../jsUtils/getObjectKeys */ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts"); var getPredefinedCssForElement_1 = __webpack_require__(/*! ./getPredefinedCssForElement */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/getPredefinedCssForElement.ts"); var getStyles_1 = __webpack_require__(/*! ../style/getStyles */ "./packages/roosterjs-editor-dom/lib/style/getStyles.ts"); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var setStyles_1 = __webpack_require__(/*! ../style/setStyles */ "./packages/roosterjs-editor-dom/lib/style/setStyles.ts"); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); var cloneObject_1 = __webpack_require__(/*! ./cloneObject */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/cloneObject.ts"); var processCssVariable_1 = __webpack_require__(/*! ./processCssVariable */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/processCssVariable.ts"); var getAllowedValues_1 = __webpack_require__(/*! ./getAllowedValues */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/getAllowedValues.ts"); /** * HTML sanitizer class provides two features: * 1. Convert global CSS to inline CSS * 2. Sanitize an HTML document, remove unnecessary/dangerous attribute/nodes */ var HtmlSanitizer = /** @class */ (function () { /** * Construct a new instance of HtmlSanitizer * @param options Options for HtmlSanitizer */ function HtmlSanitizer(options) { options = options || {}; this.elementCallbacks = (0, cloneObject_1.cloneObject)(options.elementCallbacks); this.styleCallbacks = (0, getAllowedValues_1.getStyleCallbacks)(options.cssStyleCallbacks); this.attributeCallbacks = (0, cloneObject_1.cloneObject)(options.attributeCallbacks); this.tagReplacements = (0, getAllowedValues_1.getTagReplacement)(options.additionalTagReplacements); this.allowedAttributes = (0, getAllowedValues_1.getAllowedAttributes)(options.additionalAllowedAttributes); this.allowedCssClassesRegex = (0, getAllowedValues_1.getAllowedCssClassesRegex)(options.additionalAllowedCssClasses); this.defaultStyleValues = (0, getAllowedValues_1.getDefaultStyleValues)(options.additionalDefaultStyleValues); this.additionalPredefinedCssForElement = options.additionalPredefinedCssForElement || null; this.additionalGlobalStyleNodes = options.additionalGlobalStyleNodes || []; this.preserveHtmlComments = options.preserveHtmlComments || false; this.unknownTagReplacement = options.unknownTagReplacement || null; } /** * @deprecated Use new HtmlSanitizer().convertGlobalCssToInlineCss() instead * Convert global CSS to inline CSS if any * @param html HTML source * @param additionalStyleNodes (Optional) additional HTML STYLE elements used as global CSS */ HtmlSanitizer.convertInlineCss = function (html, additionalStyleNodes) { var sanitizer = new HtmlSanitizer({ additionalGlobalStyleNodes: additionalStyleNodes, }); return sanitizer.exec(html, true /*convertCssOnly*/); }; /** * @deprecated Use new HtmlSanitizer().sanitize() instead * Sanitize HTML string, remove any unused HTML node/attribute/CSS. * @param html HTML source string * @param options Options used for this sanitizing process */ HtmlSanitizer.sanitizeHtml = function (html, options) { options = options || {}; var sanitizer = new HtmlSanitizer(options); var currentStyles = (0, safeInstanceOf_1.default)(options.currentElementOrStyle, 'HTMLElement') ? (0, getInheritableStyles_1.default)(options.currentElementOrStyle) : options.currentElementOrStyle; return sanitizer.exec(html, options.convertCssOnly, currentStyles); }; /** * @deprecated Use HtmlSanitizer.convertGlobalCssToInlineCss() and HtmlSanitizer.sanitize() instead * Sanitize HTML string * This function will do the following work: * 1. Convert global CSS into inline CSS * 2. Remove dangerous HTML tags and attributes * 3. Remove useless CSS properties * @param html The input HTML * @param convertInlineCssOnly Whether only convert inline css and skip html content sanitizing * @param currentStyles Current inheritable CSS styles */ HtmlSanitizer.prototype.exec = function (html, convertCssOnly, currentStyles) { var parser = new DOMParser(); var doc = parser.parseFromString(html || '', 'text/html'); if (doc && doc.body && doc.body.firstChild) { this.convertGlobalCssToInlineCss(doc); if (!convertCssOnly) { this.sanitize(doc.body, currentStyles); } } return (doc && doc.body && doc.body.innerHTML) || ''; }; /** * Sanitize an HTML element, remove unnecessary or dangerous elements/attribute/CSS rules * @param rootNode Root node to sanitize * @param currentStyles Current CSS styles. Inheritable styles in the given node which has * the same value with current styles will be ignored. */ HtmlSanitizer.prototype.sanitize = function (rootNode, currentStyles) { if (!rootNode) { return ''; } currentStyles = (0, cloneObject_1.cloneObject)(currentStyles, (0, getInheritableStyles_1.default)(null)); this.processNode(rootNode, currentStyles, {}); }; /** * Convert global CSS into inline CSS * @param rootNode The HTML Document */ HtmlSanitizer.prototype.convertGlobalCssToInlineCss = function (rootNode) { var styleNodes = (0, toArray_1.default)(rootNode.querySelectorAll('style')); var styleSheets = this.additionalGlobalStyleNodes .reverse() .map(function (node) { return node.sheet; }) .concat(styleNodes.map(function (node) { return node.sheet; }).reverse()) .filter(function (sheet) { return sheet; }); for (var _i = 0, styleSheets_1 = styleSheets; _i < styleSheets_1.length; _i++) { var styleSheet = styleSheets_1[_i]; var _loop_1 = function (j) { // Skip any none-style rule, i.e. @page var styleRule = styleSheet.cssRules[j]; var text = styleRule && styleRule.style ? styleRule.style.cssText : null; if (styleRule.type != CSSRule.STYLE_RULE || !text || !styleRule.selectorText) { return "continue"; } // Make sure the selector is not empty for (var _a = 0, _b = styleRule.selectorText.split(','); _a < _b.length; _a++) { var selector = _b[_a]; if (!selector || !selector.trim() || selector.indexOf(':') >= 0) { continue; } var nodes = (0, toArray_1.default)(rootNode.querySelectorAll(selector)); // Always put existing styles after so that they have higher priority // Which means if both global style and inline style apply to the same element, // inline style will have higher priority nodes.forEach(function (node) { return node.setAttribute('style', text + (node.getAttribute('style') || '')); }); } }; for (var j = styleSheet.cssRules.length - 1; j >= 0; j--) { _loop_1(j); } } styleNodes.forEach(function (node) { if (node.parentNode) { node.parentNode.removeChild(node); } }); }; HtmlSanitizer.prototype.processNode = function (node, currentStyle, context) { var _a; var nodeType = node.nodeType; var isElement = nodeType == 1 /* Element */; var isText = nodeType == 3 /* Text */; var isFragment = nodeType == 11 /* DocumentFragment */; var isComment = nodeType == 8 /* Comment */; var shouldKeep = false; if (isElement) { var tag = (0, getTagOfNode_1.default)(node); var callback = this.elementCallbacks[tag]; var replacement = this.tagReplacements[tag.toLowerCase()]; if (replacement === undefined) { replacement = this.unknownTagReplacement; } if (callback) { shouldKeep = callback(node, context); } else if (tag.indexOf(':') > 0) { shouldKeep = true; } else if (tag == replacement || replacement == '*') { shouldKeep = true; } else if (replacement && /^[a-zA-Z][\w\-]*$/.test(replacement)) { node = (0, changeElementTag_1.default)(node, replacement); shouldKeep = true; } } else if (isText) { var whiteSpace = currentStyle['white-space']; shouldKeep = whiteSpace == 'pre' || whiteSpace == 'pre-line' || whiteSpace == 'pre-wrap' || !/^[\r\n]*$/g.test(node.nodeValue || ''); } else if (isFragment) { shouldKeep = true; } else if (isComment) { shouldKeep = this.preserveHtmlComments; } else { shouldKeep = false; } if (!shouldKeep) { (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node); } else if (isText && (currentStyle['white-space'] == 'pre' || currentStyle['white-space'] == 'pre-wrap')) { node.nodeValue = (node.nodeValue || '') .replace(/^ /gm, '\u00A0') .replace(/ {2}/g, ' \u00A0'); } else if (isElement || isFragment) { var thisStyle = (0, cloneObject_1.cloneObject)(currentStyle); var element = node; if (isElement) { this.processAttributes(element, context); this.preprocessCss(element, thisStyle); this.processCss(element, thisStyle, context); } var child = element.firstChild; var next = void 0; for (; child; child = next) { next = child.nextSibling; this.processNode(child, thisStyle, context); } } }; HtmlSanitizer.prototype.preprocessCss = function (element, thisStyle) { var predefinedStyles = (0, getPredefinedCssForElement_1.default)(element, this.additionalPredefinedCssForElement); if (predefinedStyles) { (0, getObjectKeys_1.default)(predefinedStyles).forEach(function (name) { thisStyle[name] = predefinedStyles[name]; }); } }; HtmlSanitizer.prototype.processCss = function (element, thisStyle, context) { var _this = this; var styles = (0, getStyles_1.default)(element); (0, getObjectKeys_1.default)(styles).forEach(function (name) { var value = styles[name]; var callback = _this.styleCallbacks[name]; var isInheritable = thisStyle[name] != undefined; var keep = true; if (keep && !!callback) { keep = callback(value, element, thisStyle, context); } if (keep && (0, processCssVariable_1.isCssVariable)(value)) { value = (0, processCssVariable_1.processCssVariable)(value); keep = !!value; } keep = keep && value != 'inherit' && value.indexOf('expression') < 0 && name.substr(0, 1) != '-' && _this.defaultStyleValues[name] != value && ((isInheritable && value != thisStyle[name]) || (!isInheritable && value != 'initial' && value != 'normal')); if (keep && isInheritable) { thisStyle[name] = value; } if (keep) { styles[name] = value; } else { delete styles[name]; } }); (0, setStyles_1.default)(element, styles); }; HtmlSanitizer.prototype.processAttributes = function (element, context) { for (var i = element.attributes.length - 1; i >= 0; i--) { var attribute = element.attributes[i]; var name_1 = attribute.name.toLowerCase().trim(); var value = attribute.value; var callback = this.attributeCallbacks[name_1]; var newValue = callback ? callback(value, element, context) : this.allowedAttributes.indexOf(name_1) >= 0 || name_1.indexOf('data-') == 0 ? value : null; if (name_1 == 'class' && this.allowedCssClassesRegex) { newValue = this.processCssClass(value, newValue); } if (newValue === null || newValue === undefined || newValue.match(/s\n*c\n*r\n*i\n*p\n*t\n*:/i) // match script: with any NewLine inside. Browser will ignore those NewLine char and still treat it as script prefix ) { element.removeAttribute(name_1); } else { attribute.value = newValue; } } }; HtmlSanitizer.prototype.processCssClass = function (originalValue, calculatedValue) { var _this = this; var originalClasses = originalValue ? originalValue.split(' ') : []; var calculatedClasses = calculatedValue ? calculatedValue.split(' ') : []; originalClasses.forEach(function (className) { var _a; if (((_a = _this.allowedCssClassesRegex) === null || _a === void 0 ? void 0 : _a.test(className)) && calculatedClasses.indexOf(className) < 0) { calculatedClasses.push(className); } }); return (calculatedClasses === null || calculatedClasses === void 0 ? void 0 : calculatedClasses.length) > 0 ? calculatedClasses.join(' ') : null; }; return HtmlSanitizer; }()); exports.default = HtmlSanitizer; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/chainSanitizerCallback.ts": /*!***********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/htmlSanitizer/chainSanitizerCallback.ts ***! \***********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Chain all callback for an attribute together * @param map The source callback map * @param name Name of the property to chain * @param newCallback A new callback to process the given name on the given map. * If the same property got multiple callbacks, the final return value will be the return * value of the latest callback */ function chainSanitizerCallback(map, name, newCallback) { if (!map[name]) { map[name] = newCallback; } else { var originalCallback_1 = map[name]; map[name] = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } originalCallback_1.apply(void 0, args); return newCallback.apply(void 0, args); }; } } exports.default = chainSanitizerCallback; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/cloneObject.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/htmlSanitizer/cloneObject.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.cloneObject = void 0; var getObjectKeys_1 = __webpack_require__(/*! ../jsUtils/getObjectKeys */ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts"); function nativeClone(source, existingObj) { return Object.assign(existingObj || {}, source); } function customClone(source, existingObj) { var result = existingObj || {}; if (source) { for (var _i = 0, _a = (0, getObjectKeys_1.default)(source); _i < _a.length; _i++) { var key = _a[_i]; result[key] = source[key]; } } return result; } // @ts-ignore Ignore this error for IE compatibility var cloneObjectImpl = Object.assign ? nativeClone : customClone; /** * @internal */ function cloneObject(source, existingObj) { return cloneObjectImpl(source, existingObj); } exports.cloneObject = cloneObject; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/createDefaultHtmlSanitizerOptions.ts": /*!**********************************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/htmlSanitizer/createDefaultHtmlSanitizerOptions.ts ***! \**********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Create default value of HtmlSanitizerOptions with every property set */ function createDefaultHtmlSanitizerOptions() { return { elementCallbacks: {}, attributeCallbacks: {}, cssStyleCallbacks: {}, additionalTagReplacements: {}, additionalAllowedAttributes: [], additionalAllowedCssClasses: [], additionalDefaultStyleValues: {}, additionalGlobalStyleNodes: [], additionalPredefinedCssForElement: {}, preserveHtmlComments: false, unknownTagReplacement: null, }; } exports.default = createDefaultHtmlSanitizerOptions; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/getAllowedValues.ts": /*!*****************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/htmlSanitizer/getAllowedValues.ts ***! \*****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getStyleCallbacks = exports.getDefaultStyleValues = exports.getAllowedCssClassesRegex = exports.getAllowedAttributes = exports.getTagReplacement = void 0; var getObjectKeys_1 = __webpack_require__(/*! ../jsUtils/getObjectKeys */ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts"); var cloneObject_1 = __webpack_require__(/*! ./cloneObject */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/cloneObject.ts"); var HTML_TAG_REPLACEMENT = { // Allowed tags a: '*', abbr: '*', address: '*', area: '*', article: '*', aside: '*', b: '*', bdi: '*', bdo: '*', blockquote: '*', body: '*', br: '*', button: '*', canvas: '*', caption: '*', center: '*', cite: '*', code: '*', col: '*', colgroup: '*', data: '*', datalist: '*', dd: '*', del: '*', details: '*', dfn: '*', dialog: '*', dir: '*', div: '*', dl: '*', dt: '*', em: '*', fieldset: '*', figcaption: '*', figure: '*', font: '*', footer: '*', h1: '*', h2: '*', h3: '*', h4: '*', h5: '*', h6: '*', head: '*', header: '*', hgroup: '*', hr: '*', html: '*', i: '*', img: '*', input: '*', ins: '*', kbd: '*', label: '*', legend: '*', li: '*', main: '*', map: '*', mark: '*', menu: '*', menuitem: '*', meter: '*', nav: '*', ol: '*', optgroup: '*', option: '*', output: '*', p: '*', picture: '*', pre: '*', progress: '*', q: '*', rp: '*', rt: '*', ruby: '*', s: '*', samp: '*', section: '*', select: '*', small: '*', span: '*', strike: '*', strong: '*', sub: '*', summary: '*', sup: '*', table: '*', tbody: '*', td: '*', textarea: '*', tfoot: '*', th: '*', thead: '*', time: '*', tr: '*', tt: '*', u: '*', ul: '*', var: '*', wbr: '*', xmp: '*', // Replaced tags: form: 'SPAN', // Disallowed tags applet: null, audio: null, base: null, basefont: null, embed: null, frame: null, frameset: null, iframe: null, link: null, meta: null, noscript: null, object: null, param: null, script: null, slot: null, source: null, style: null, template: null, title: null, track: null, video: null, }; var ALLOWED_HTML_ATTRIBUTES = ('accept,align,alt,checked,cite,color,cols,colspan,contextmenu,' + 'coords,datetime,default,dir,dirname,disabled,download,face,headers,height,hidden,high,href,' + 'hreflang,ismap,kind,label,lang,list,low,max,maxlength,media,min,multiple,open,optimum,pattern,' + 'placeholder,readonly,rel,required,reversed,rows,rowspan,scope,selected,shape,size,sizes,span,' + 'spellcheck,src,srclang,srcset,start,step,style,tabindex,target,title,translate,type,usemap,valign,value,' + 'width,wrap').split(','); var DEFAULT_STYLE_VALUES = { 'background-color': 'transparent', 'border-bottom-color': 'rgb(0, 0, 0)', 'border-bottom-style': 'none', 'border-bottom-width': '0px', 'border-image-outset': '0', 'border-image-repeat': 'stretch', 'border-image-slice': '100%', 'border-image-source': 'none', 'border-image-width': '1', 'border-left-color': 'rgb(0, 0, 0)', 'border-left-style': 'none', 'border-left-width': '0px', 'border-right-color': 'rgb(0, 0, 0)', 'border-right-style': 'none', 'border-right-width': '0px', 'border-top-color': 'rgb(0, 0, 0)', 'border-top-style': 'none', 'border-top-width': '0px', 'outline-color': 'transparent', 'outline-style': 'none', 'outline-width': '0px', overflow: 'visible', 'text-decoration': 'none', '-webkit-text-stroke-width': '0px', 'word-wrap': 'break-word', 'margin-left': '0px', 'margin-right': '0px', padding: '0px', 'padding-top': '0px', 'padding-left': '0px', 'padding-right': '0px', 'padding-bottom': '0px', border: '0px', 'border-top': '0px', 'border-left': '0px', 'border-right': '0px', 'border-bottom': '0px', 'vertical-align': 'baseline', float: 'none', }; // This is to preserve entity related CSS classes when paste. var ALLOWED_CSS_CLASSES = []; /** * @internal */ function getTagReplacement(additionalReplacements) { var result = __assign({}, HTML_TAG_REPLACEMENT); var replacements = additionalReplacements || {}; (0, getObjectKeys_1.default)(replacements).forEach(function (key) { if (key) { result[key.toLowerCase()] = replacements[key]; } }); return result; } exports.getTagReplacement = getTagReplacement; /** * @internal */ function getAllowedAttributes(additionalAttributes) { return unique(ALLOWED_HTML_ATTRIBUTES.concat(additionalAttributes || [])).map(function (attr) { return attr.toLocaleLowerCase(); }); } exports.getAllowedAttributes = getAllowedAttributes; /** * @internal */ function getAllowedCssClassesRegex(additionalCssClasses) { var patterns = ALLOWED_CSS_CLASSES.concat(additionalCssClasses || []); return patterns.length > 0 ? new RegExp(patterns.join('|')) : null; } exports.getAllowedCssClassesRegex = getAllowedCssClassesRegex; /** * @internal */ function getDefaultStyleValues(additionalDefaultStyles) { var result = (0, cloneObject_1.cloneObject)(DEFAULT_STYLE_VALUES); if (additionalDefaultStyles) { Object.keys(additionalDefaultStyles).forEach(function (name) { var value = additionalDefaultStyles[name]; if (value !== null && value !== undefined) { result[name] = value; } else { delete result[name]; } }); } return result; } exports.getDefaultStyleValues = getDefaultStyleValues; /** * @internal */ function getStyleCallbacks(callbacks) { var result = (0, cloneObject_1.cloneObject)(callbacks); result.position = result.position || removeValue; result.width = result.width || removeWidthForLiAndDiv; return result; } exports.getStyleCallbacks = getStyleCallbacks; function removeValue() { return null; } function removeWidthForLiAndDiv(value, element) { var tag = element.tagName; return !(tag == 'LI' || tag == 'DIV'); } function unique(array) { return array.filter(function (value, index, self) { return self.indexOf(value) == index; }); } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/getInheritableStyles.ts": /*!*********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/htmlSanitizer/getInheritableStyles.ts ***! \*********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // Inheritable CSS properties // Ref: https://www.w3.org/TR/CSS21/propidx.html var INHERITABLE_PROPERTIES = ('border-spacing,caption-side,color,' + 'cursor,direction,empty-cells,font-family,font-size,font-style,font-variant,font-weight,' + 'font,letter-spacing,line-height,list-style-image,list-style-position,list-style-type,' + 'list-style,orphans,quotes,text-align,text-indent,text-transform,visibility,white-space,' + 'widows,word-spacing').split(','); /** * Get inheritable CSS style values from the given element * @param element The element to get style from */ function getInheritableStyles(element) { var win = element && element.ownerDocument && element.ownerDocument.defaultView; var styles = win && element && win.getComputedStyle(element); var result = {}; INHERITABLE_PROPERTIES.forEach(function (name) { return (result[name] = (styles && styles.getPropertyValue(name)) || ''); }); return result; } exports.default = getInheritableStyles; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/getPredefinedCssForElement.ts": /*!***************************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/htmlSanitizer/getPredefinedCssForElement.ts ***! \***************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var PREDEFINED_CSS_FOR_ELEMENT = { B: { 'font-weight': 'bold', }, EM: { 'font-style': 'italic', }, I: { 'font-style': 'italic', }, U: { 'text-decoration': 'underline', }, P: { 'margin-top': '1em', 'margin-bottom': '1em', }, PRE: { 'white-space': 'pre', }, S: { 'text-decoration': 'line-through', }, STRIKE: { 'text-decoration': 'line-through', }, SUB: { 'vertical-align': 'sub', 'font-size': 'smaller', }, SUP: { 'vertical-align': 'super', 'font-size': 'smaller', }, }; /** * @internal * Get a map for browser built-in CSS definitions of elements */ function getPredefinedCssForElement(element, additionalPredefinedCssForElement) { var tag = (0, getTagOfNode_1.default)(element); return PREDEFINED_CSS_FOR_ELEMENT[tag] || (additionalPredefinedCssForElement || {})[tag]; } exports.default = getPredefinedCssForElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/processCssVariable.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/htmlSanitizer/processCssVariable.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isCssVariable = exports.processCssVariable = void 0; var VARIABLE_REGEX = /^\s*var\(\s*[a-zA-Z0-9-_]+\s*(,\s*(.*))?\)\s*$/; var VARIABLE_PREFIX = 'var('; /** * @internal * Handle CSS variable format. e.g.: var(--name, fallbackValue) */ function processCssVariable(value) { var match = VARIABLE_REGEX.exec(value); return (match === null || match === void 0 ? void 0 : match[2]) || ''; // Without fallback value, we don't know what does the original value mean, so ignore it } exports.processCssVariable = processCssVariable; /** * @internal */ function isCssVariable(value) { return value.indexOf(VARIABLE_PREFIX) == 0; } exports.isCssVariable = isCssVariable; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/index.ts": /*!****************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/index.ts ***! \****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getIntersectedRect = exports.moveChildNodes = exports.KnownCreateElementData = exports.createElement = exports.matchesSelector = exports.setColor = exports.getInnerHTML = exports.readFile = exports.safeInstanceOf = exports.normalizeRect = exports.splitTextNode = exports.getLastLeafNode = exports.getFirstLeafNode = exports.getPreviousLeafSibling = exports.getNextLeafSibling = exports.wrap = exports.unwrap = exports.splitBalancedNodeRange = exports.splitParentNode = exports.queryElements = exports.matchLink = exports.isVoidHtmlElement = exports.isNodeEmpty = exports.isBlockElement = exports.getTagOfNode = exports.PendableFormatCommandMap = exports.getPendableFormatState = exports.getComputedStyle = exports.getComputedStyles = exports.fromHtml = exports.findClosestElementAncestor = exports.contains = exports.collapseNodes = exports.changeElementTag = exports.applyFormat = exports.getBrowserInfo = exports.Browser = exports.extractClipboardItemsForIE = exports.extractClipboardItems = exports.extractClipboardEvent = exports.applyTextStyle = exports.PartialInlineElement = exports.NodeInlineElement = exports.LinkInlineElement = exports.ImageInlineElement = exports.getInlineElementAtNode = exports.PositionContentSearcher = exports.ContentTraverser = exports.getFirstLastBlockElement = exports.getBlockElementAtNode = void 0; exports.getStyles = exports.isCtrlOrMetaPressed = exports.isCharacterValue = exports.isModifierKey = exports.clearEventDataCache = exports.cacheGetEventData = exports.restoreContentWithEntityPlaceholder = exports.moveContentWithEntityPlaceholders = exports.createEntityPlaceholder = exports.getEntitySelector = exports.getEntityFromElement = exports.commitEntity = exports.chainSanitizerCallback = exports.createDefaultHtmlSanitizerOptions = exports.getInheritableStyles = exports.HtmlSanitizer = exports.canUndoAutoComplete = exports.createSnapshots = exports.moveCurrentSnapsnot = exports.moveCurrentSnapshot = exports.clearProceedingSnapshotsV2 = exports.clearProceedingSnapshots = exports.canMoveCurrentSnapshot = exports.addSnapshotV2 = exports.addSnapshot = exports.addRangeToSelection = exports.setHtmlWithMetadata = exports.setHtmlWithSelectionPath = exports.getHtmlWithSelectionPath = exports.getSelectionPath = exports.isPositionAtBeginningOf = exports.getPositionRect = exports.createRange = exports.Position = exports.mergeBlocksInRegion = exports.getSelectionRangeInRegion = exports.isNodeInRegion = exports.collapseNodesInRegion = exports.getSelectedBlockElementsInRegion = exports.getRegionsFromRange = exports.saveTableCellMetadata = exports.getTableFormatInfo = exports.setListItemStyle = exports.VListChain = exports.createVListFromRegion = exports.VListItem = exports.VList = exports.isWholeTableSelected = exports.VTable = exports.isNodeAfter = void 0; exports.toArray = exports.getObjectKeys = exports.arrayPush = exports.removeMetadata = exports.setMetadata = exports.getMetadata = exports.createObjectDefinition = exports.createArrayDefinition = exports.createStringDefinition = exports.createBooleanDefinition = exports.createNumberDefinition = exports.validate = exports.getTextContent = exports.deleteSelectedContent = exports.adjustInsertPosition = exports.removeGlobalCssStyle = exports.setGlobalCssStyles = exports.removeImportantStyleRule = exports.setStyles = void 0; var getBlockElementAtNode_1 = __webpack_require__(/*! ./blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts"); Object.defineProperty(exports, "getBlockElementAtNode", { enumerable: true, get: function () { return getBlockElementAtNode_1.default; } }); var getFirstLastBlockElement_1 = __webpack_require__(/*! ./blockElements/getFirstLastBlockElement */ "./packages/roosterjs-editor-dom/lib/blockElements/getFirstLastBlockElement.ts"); Object.defineProperty(exports, "getFirstLastBlockElement", { enumerable: true, get: function () { return getFirstLastBlockElement_1.default; } }); var ContentTraverser_1 = __webpack_require__(/*! ./contentTraverser/ContentTraverser */ "./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts"); Object.defineProperty(exports, "ContentTraverser", { enumerable: true, get: function () { return ContentTraverser_1.default; } }); var PositionContentSearcher_1 = __webpack_require__(/*! ./contentTraverser/PositionContentSearcher */ "./packages/roosterjs-editor-dom/lib/contentTraverser/PositionContentSearcher.ts"); Object.defineProperty(exports, "PositionContentSearcher", { enumerable: true, get: function () { return PositionContentSearcher_1.default; } }); var getInlineElementAtNode_1 = __webpack_require__(/*! ./inlineElements/getInlineElementAtNode */ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementAtNode.ts"); Object.defineProperty(exports, "getInlineElementAtNode", { enumerable: true, get: function () { return getInlineElementAtNode_1.default; } }); var ImageInlineElement_1 = __webpack_require__(/*! ./inlineElements/ImageInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/ImageInlineElement.ts"); Object.defineProperty(exports, "ImageInlineElement", { enumerable: true, get: function () { return ImageInlineElement_1.default; } }); var LinkInlineElement_1 = __webpack_require__(/*! ./inlineElements/LinkInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/LinkInlineElement.ts"); Object.defineProperty(exports, "LinkInlineElement", { enumerable: true, get: function () { return LinkInlineElement_1.default; } }); var NodeInlineElement_1 = __webpack_require__(/*! ./inlineElements/NodeInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/NodeInlineElement.ts"); Object.defineProperty(exports, "NodeInlineElement", { enumerable: true, get: function () { return NodeInlineElement_1.default; } }); var PartialInlineElement_1 = __webpack_require__(/*! ./inlineElements/PartialInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/PartialInlineElement.ts"); Object.defineProperty(exports, "PartialInlineElement", { enumerable: true, get: function () { return PartialInlineElement_1.default; } }); var applyTextStyle_1 = __webpack_require__(/*! ./inlineElements/applyTextStyle */ "./packages/roosterjs-editor-dom/lib/inlineElements/applyTextStyle.ts"); Object.defineProperty(exports, "applyTextStyle", { enumerable: true, get: function () { return applyTextStyle_1.default; } }); var extractClipboardEvent_1 = __webpack_require__(/*! ./clipboard/extractClipboardEvent */ "./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardEvent.ts"); Object.defineProperty(exports, "extractClipboardEvent", { enumerable: true, get: function () { return extractClipboardEvent_1.default; } }); var extractClipboardItems_1 = __webpack_require__(/*! ./clipboard/extractClipboardItems */ "./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardItems.ts"); Object.defineProperty(exports, "extractClipboardItems", { enumerable: true, get: function () { return extractClipboardItems_1.default; } }); var extractClipboardItemsForIE_1 = __webpack_require__(/*! ./clipboard/extractClipboardItemsForIE */ "./packages/roosterjs-editor-dom/lib/clipboard/extractClipboardItemsForIE.ts"); Object.defineProperty(exports, "extractClipboardItemsForIE", { enumerable: true, get: function () { return extractClipboardItemsForIE_1.default; } }); var Browser_1 = __webpack_require__(/*! ./utils/Browser */ "./packages/roosterjs-editor-dom/lib/utils/Browser.ts"); Object.defineProperty(exports, "Browser", { enumerable: true, get: function () { return Browser_1.Browser; } }); Object.defineProperty(exports, "getBrowserInfo", { enumerable: true, get: function () { return Browser_1.getBrowserInfo; } }); var applyFormat_1 = __webpack_require__(/*! ./utils/applyFormat */ "./packages/roosterjs-editor-dom/lib/utils/applyFormat.ts"); Object.defineProperty(exports, "applyFormat", { enumerable: true, get: function () { return applyFormat_1.default; } }); var changeElementTag_1 = __webpack_require__(/*! ./utils/changeElementTag */ "./packages/roosterjs-editor-dom/lib/utils/changeElementTag.ts"); Object.defineProperty(exports, "changeElementTag", { enumerable: true, get: function () { return changeElementTag_1.default; } }); var collapseNodes_1 = __webpack_require__(/*! ./utils/collapseNodes */ "./packages/roosterjs-editor-dom/lib/utils/collapseNodes.ts"); Object.defineProperty(exports, "collapseNodes", { enumerable: true, get: function () { return collapseNodes_1.default; } }); var contains_1 = __webpack_require__(/*! ./utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); Object.defineProperty(exports, "contains", { enumerable: true, get: function () { return contains_1.default; } }); var findClosestElementAncestor_1 = __webpack_require__(/*! ./utils/findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts"); Object.defineProperty(exports, "findClosestElementAncestor", { enumerable: true, get: function () { return findClosestElementAncestor_1.default; } }); var fromHtml_1 = __webpack_require__(/*! ./utils/fromHtml */ "./packages/roosterjs-editor-dom/lib/utils/fromHtml.ts"); Object.defineProperty(exports, "fromHtml", { enumerable: true, get: function () { return fromHtml_1.default; } }); var getComputedStyles_1 = __webpack_require__(/*! ./utils/getComputedStyles */ "./packages/roosterjs-editor-dom/lib/utils/getComputedStyles.ts"); Object.defineProperty(exports, "getComputedStyles", { enumerable: true, get: function () { return getComputedStyles_1.default; } }); Object.defineProperty(exports, "getComputedStyle", { enumerable: true, get: function () { return getComputedStyles_1.getComputedStyle; } }); var getPendableFormatState_1 = __webpack_require__(/*! ./utils/getPendableFormatState */ "./packages/roosterjs-editor-dom/lib/utils/getPendableFormatState.ts"); Object.defineProperty(exports, "getPendableFormatState", { enumerable: true, get: function () { return getPendableFormatState_1.default; } }); Object.defineProperty(exports, "PendableFormatCommandMap", { enumerable: true, get: function () { return getPendableFormatState_1.PendableFormatCommandMap; } }); var getTagOfNode_1 = __webpack_require__(/*! ./utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); Object.defineProperty(exports, "getTagOfNode", { enumerable: true, get: function () { return getTagOfNode_1.default; } }); var isBlockElement_1 = __webpack_require__(/*! ./utils/isBlockElement */ "./packages/roosterjs-editor-dom/lib/utils/isBlockElement.ts"); Object.defineProperty(exports, "isBlockElement", { enumerable: true, get: function () { return isBlockElement_1.default; } }); var isNodeEmpty_1 = __webpack_require__(/*! ./utils/isNodeEmpty */ "./packages/roosterjs-editor-dom/lib/utils/isNodeEmpty.ts"); Object.defineProperty(exports, "isNodeEmpty", { enumerable: true, get: function () { return isNodeEmpty_1.default; } }); var isVoidHtmlElement_1 = __webpack_require__(/*! ./utils/isVoidHtmlElement */ "./packages/roosterjs-editor-dom/lib/utils/isVoidHtmlElement.ts"); Object.defineProperty(exports, "isVoidHtmlElement", { enumerable: true, get: function () { return isVoidHtmlElement_1.default; } }); var matchLink_1 = __webpack_require__(/*! ./utils/matchLink */ "./packages/roosterjs-editor-dom/lib/utils/matchLink.ts"); Object.defineProperty(exports, "matchLink", { enumerable: true, get: function () { return matchLink_1.default; } }); var queryElements_1 = __webpack_require__(/*! ./utils/queryElements */ "./packages/roosterjs-editor-dom/lib/utils/queryElements.ts"); Object.defineProperty(exports, "queryElements", { enumerable: true, get: function () { return queryElements_1.default; } }); var splitParentNode_1 = __webpack_require__(/*! ./utils/splitParentNode */ "./packages/roosterjs-editor-dom/lib/utils/splitParentNode.ts"); Object.defineProperty(exports, "splitParentNode", { enumerable: true, get: function () { return splitParentNode_1.default; } }); Object.defineProperty(exports, "splitBalancedNodeRange", { enumerable: true, get: function () { return splitParentNode_1.splitBalancedNodeRange; } }); var unwrap_1 = __webpack_require__(/*! ./utils/unwrap */ "./packages/roosterjs-editor-dom/lib/utils/unwrap.ts"); Object.defineProperty(exports, "unwrap", { enumerable: true, get: function () { return unwrap_1.default; } }); var wrap_1 = __webpack_require__(/*! ./utils/wrap */ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts"); Object.defineProperty(exports, "wrap", { enumerable: true, get: function () { return wrap_1.default; } }); var getLeafSibling_1 = __webpack_require__(/*! ./utils/getLeafSibling */ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts"); Object.defineProperty(exports, "getNextLeafSibling", { enumerable: true, get: function () { return getLeafSibling_1.getNextLeafSibling; } }); Object.defineProperty(exports, "getPreviousLeafSibling", { enumerable: true, get: function () { return getLeafSibling_1.getPreviousLeafSibling; } }); var getLeafNode_1 = __webpack_require__(/*! ./utils/getLeafNode */ "./packages/roosterjs-editor-dom/lib/utils/getLeafNode.ts"); Object.defineProperty(exports, "getFirstLeafNode", { enumerable: true, get: function () { return getLeafNode_1.getFirstLeafNode; } }); Object.defineProperty(exports, "getLastLeafNode", { enumerable: true, get: function () { return getLeafNode_1.getLastLeafNode; } }); var splitTextNode_1 = __webpack_require__(/*! ./utils/splitTextNode */ "./packages/roosterjs-editor-dom/lib/utils/splitTextNode.ts"); Object.defineProperty(exports, "splitTextNode", { enumerable: true, get: function () { return splitTextNode_1.default; } }); var normalizeRect_1 = __webpack_require__(/*! ./utils/normalizeRect */ "./packages/roosterjs-editor-dom/lib/utils/normalizeRect.ts"); Object.defineProperty(exports, "normalizeRect", { enumerable: true, get: function () { return normalizeRect_1.default; } }); var safeInstanceOf_1 = __webpack_require__(/*! ./utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); Object.defineProperty(exports, "safeInstanceOf", { enumerable: true, get: function () { return safeInstanceOf_1.default; } }); var readFile_1 = __webpack_require__(/*! ./utils/readFile */ "./packages/roosterjs-editor-dom/lib/utils/readFile.ts"); Object.defineProperty(exports, "readFile", { enumerable: true, get: function () { return readFile_1.default; } }); var getInnerHTML_1 = __webpack_require__(/*! ./utils/getInnerHTML */ "./packages/roosterjs-editor-dom/lib/utils/getInnerHTML.ts"); Object.defineProperty(exports, "getInnerHTML", { enumerable: true, get: function () { return getInnerHTML_1.default; } }); var setColor_1 = __webpack_require__(/*! ./utils/setColor */ "./packages/roosterjs-editor-dom/lib/utils/setColor.ts"); Object.defineProperty(exports, "setColor", { enumerable: true, get: function () { return setColor_1.default; } }); var matchesSelector_1 = __webpack_require__(/*! ./utils/matchesSelector */ "./packages/roosterjs-editor-dom/lib/utils/matchesSelector.ts"); Object.defineProperty(exports, "matchesSelector", { enumerable: true, get: function () { return matchesSelector_1.default; } }); var createElement_1 = __webpack_require__(/*! ./utils/createElement */ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts"); Object.defineProperty(exports, "createElement", { enumerable: true, get: function () { return createElement_1.default; } }); Object.defineProperty(exports, "KnownCreateElementData", { enumerable: true, get: function () { return createElement_1.KnownCreateElementData; } }); var moveChildNodes_1 = __webpack_require__(/*! ./utils/moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts"); Object.defineProperty(exports, "moveChildNodes", { enumerable: true, get: function () { return moveChildNodes_1.default; } }); var getIntersectedRect_1 = __webpack_require__(/*! ./utils/getIntersectedRect */ "./packages/roosterjs-editor-dom/lib/utils/getIntersectedRect.ts"); Object.defineProperty(exports, "getIntersectedRect", { enumerable: true, get: function () { return getIntersectedRect_1.default; } }); var isNodeAfter_1 = __webpack_require__(/*! ./utils/isNodeAfter */ "./packages/roosterjs-editor-dom/lib/utils/isNodeAfter.ts"); Object.defineProperty(exports, "isNodeAfter", { enumerable: true, get: function () { return isNodeAfter_1.default; } }); var VTable_1 = __webpack_require__(/*! ./table/VTable */ "./packages/roosterjs-editor-dom/lib/table/VTable.ts"); Object.defineProperty(exports, "VTable", { enumerable: true, get: function () { return VTable_1.default; } }); var isWholeTableSelected_1 = __webpack_require__(/*! ./table/isWholeTableSelected */ "./packages/roosterjs-editor-dom/lib/table/isWholeTableSelected.ts"); Object.defineProperty(exports, "isWholeTableSelected", { enumerable: true, get: function () { return isWholeTableSelected_1.default; } }); var VList_1 = __webpack_require__(/*! ./list/VList */ "./packages/roosterjs-editor-dom/lib/list/VList.ts"); Object.defineProperty(exports, "VList", { enumerable: true, get: function () { return VList_1.default; } }); var VListItem_1 = __webpack_require__(/*! ./list/VListItem */ "./packages/roosterjs-editor-dom/lib/list/VListItem.ts"); Object.defineProperty(exports, "VListItem", { enumerable: true, get: function () { return VListItem_1.default; } }); var createVListFromRegion_1 = __webpack_require__(/*! ./list/createVListFromRegion */ "./packages/roosterjs-editor-dom/lib/list/createVListFromRegion.ts"); Object.defineProperty(exports, "createVListFromRegion", { enumerable: true, get: function () { return createVListFromRegion_1.default; } }); var VListChain_1 = __webpack_require__(/*! ./list/VListChain */ "./packages/roosterjs-editor-dom/lib/list/VListChain.ts"); Object.defineProperty(exports, "VListChain", { enumerable: true, get: function () { return VListChain_1.default; } }); var setListItemStyle_1 = __webpack_require__(/*! ./list/setListItemStyle */ "./packages/roosterjs-editor-dom/lib/list/setListItemStyle.ts"); Object.defineProperty(exports, "setListItemStyle", { enumerable: true, get: function () { return setListItemStyle_1.default; } }); var tableFormatInfo_1 = __webpack_require__(/*! ./table/tableFormatInfo */ "./packages/roosterjs-editor-dom/lib/table/tableFormatInfo.ts"); Object.defineProperty(exports, "getTableFormatInfo", { enumerable: true, get: function () { return tableFormatInfo_1.getTableFormatInfo; } }); var tableCellInfo_1 = __webpack_require__(/*! ./table/tableCellInfo */ "./packages/roosterjs-editor-dom/lib/table/tableCellInfo.ts"); Object.defineProperty(exports, "saveTableCellMetadata", { enumerable: true, get: function () { return tableCellInfo_1.saveTableCellMetadata; } }); var getRegionsFromRange_1 = __webpack_require__(/*! ./region/getRegionsFromRange */ "./packages/roosterjs-editor-dom/lib/region/getRegionsFromRange.ts"); Object.defineProperty(exports, "getRegionsFromRange", { enumerable: true, get: function () { return getRegionsFromRange_1.default; } }); var getSelectedBlockElementsInRegion_1 = __webpack_require__(/*! ./region/getSelectedBlockElementsInRegion */ "./packages/roosterjs-editor-dom/lib/region/getSelectedBlockElementsInRegion.ts"); Object.defineProperty(exports, "getSelectedBlockElementsInRegion", { enumerable: true, get: function () { return getSelectedBlockElementsInRegion_1.default; } }); var collapseNodesInRegion_1 = __webpack_require__(/*! ./region/collapseNodesInRegion */ "./packages/roosterjs-editor-dom/lib/region/collapseNodesInRegion.ts"); Object.defineProperty(exports, "collapseNodesInRegion", { enumerable: true, get: function () { return collapseNodesInRegion_1.default; } }); var isNodeInRegion_1 = __webpack_require__(/*! ./region/isNodeInRegion */ "./packages/roosterjs-editor-dom/lib/region/isNodeInRegion.ts"); Object.defineProperty(exports, "isNodeInRegion", { enumerable: true, get: function () { return isNodeInRegion_1.default; } }); var getSelectionRangeInRegion_1 = __webpack_require__(/*! ./region/getSelectionRangeInRegion */ "./packages/roosterjs-editor-dom/lib/region/getSelectionRangeInRegion.ts"); Object.defineProperty(exports, "getSelectionRangeInRegion", { enumerable: true, get: function () { return getSelectionRangeInRegion_1.default; } }); var mergeBlocksInRegion_1 = __webpack_require__(/*! ./region/mergeBlocksInRegion */ "./packages/roosterjs-editor-dom/lib/region/mergeBlocksInRegion.ts"); Object.defineProperty(exports, "mergeBlocksInRegion", { enumerable: true, get: function () { return mergeBlocksInRegion_1.default; } }); var Position_1 = __webpack_require__(/*! ./selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); Object.defineProperty(exports, "Position", { enumerable: true, get: function () { return Position_1.default; } }); var createRange_1 = __webpack_require__(/*! ./selection/createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts"); Object.defineProperty(exports, "createRange", { enumerable: true, get: function () { return createRange_1.default; } }); var getPositionRect_1 = __webpack_require__(/*! ./selection/getPositionRect */ "./packages/roosterjs-editor-dom/lib/selection/getPositionRect.ts"); Object.defineProperty(exports, "getPositionRect", { enumerable: true, get: function () { return getPositionRect_1.default; } }); var isPositionAtBeginningOf_1 = __webpack_require__(/*! ./selection/isPositionAtBeginningOf */ "./packages/roosterjs-editor-dom/lib/selection/isPositionAtBeginningOf.ts"); Object.defineProperty(exports, "isPositionAtBeginningOf", { enumerable: true, get: function () { return isPositionAtBeginningOf_1.default; } }); var getSelectionPath_1 = __webpack_require__(/*! ./selection/getSelectionPath */ "./packages/roosterjs-editor-dom/lib/selection/getSelectionPath.ts"); Object.defineProperty(exports, "getSelectionPath", { enumerable: true, get: function () { return getSelectionPath_1.default; } }); var getHtmlWithSelectionPath_1 = __webpack_require__(/*! ./selection/getHtmlWithSelectionPath */ "./packages/roosterjs-editor-dom/lib/selection/getHtmlWithSelectionPath.ts"); Object.defineProperty(exports, "getHtmlWithSelectionPath", { enumerable: true, get: function () { return getHtmlWithSelectionPath_1.default; } }); var setHtmlWithSelectionPath_1 = __webpack_require__(/*! ./selection/setHtmlWithSelectionPath */ "./packages/roosterjs-editor-dom/lib/selection/setHtmlWithSelectionPath.ts"); Object.defineProperty(exports, "setHtmlWithSelectionPath", { enumerable: true, get: function () { return setHtmlWithSelectionPath_1.default; } }); Object.defineProperty(exports, "setHtmlWithMetadata", { enumerable: true, get: function () { return setHtmlWithSelectionPath_1.setHtmlWithMetadata; } }); var addRangeToSelection_1 = __webpack_require__(/*! ./selection/addRangeToSelection */ "./packages/roosterjs-editor-dom/lib/selection/addRangeToSelection.ts"); Object.defineProperty(exports, "addRangeToSelection", { enumerable: true, get: function () { return addRangeToSelection_1.default; } }); var addSnapshot_1 = __webpack_require__(/*! ./snapshots/addSnapshot */ "./packages/roosterjs-editor-dom/lib/snapshots/addSnapshot.ts"); Object.defineProperty(exports, "addSnapshot", { enumerable: true, get: function () { return addSnapshot_1.default; } }); Object.defineProperty(exports, "addSnapshotV2", { enumerable: true, get: function () { return addSnapshot_1.addSnapshotV2; } }); var canMoveCurrentSnapshot_1 = __webpack_require__(/*! ./snapshots/canMoveCurrentSnapshot */ "./packages/roosterjs-editor-dom/lib/snapshots/canMoveCurrentSnapshot.ts"); Object.defineProperty(exports, "canMoveCurrentSnapshot", { enumerable: true, get: function () { return canMoveCurrentSnapshot_1.default; } }); var clearProceedingSnapshots_1 = __webpack_require__(/*! ./snapshots/clearProceedingSnapshots */ "./packages/roosterjs-editor-dom/lib/snapshots/clearProceedingSnapshots.ts"); Object.defineProperty(exports, "clearProceedingSnapshots", { enumerable: true, get: function () { return clearProceedingSnapshots_1.default; } }); Object.defineProperty(exports, "clearProceedingSnapshotsV2", { enumerable: true, get: function () { return clearProceedingSnapshots_1.clearProceedingSnapshotsV2; } }); var moveCurrentSnapshot_1 = __webpack_require__(/*! ./snapshots/moveCurrentSnapshot */ "./packages/roosterjs-editor-dom/lib/snapshots/moveCurrentSnapshot.ts"); Object.defineProperty(exports, "moveCurrentSnapshot", { enumerable: true, get: function () { return moveCurrentSnapshot_1.default; } }); Object.defineProperty(exports, "moveCurrentSnapsnot", { enumerable: true, get: function () { return moveCurrentSnapshot_1.moveCurrentSnapsnot; } }); var createSnapshots_1 = __webpack_require__(/*! ./snapshots/createSnapshots */ "./packages/roosterjs-editor-dom/lib/snapshots/createSnapshots.ts"); Object.defineProperty(exports, "createSnapshots", { enumerable: true, get: function () { return createSnapshots_1.default; } }); var canUndoAutoComplete_1 = __webpack_require__(/*! ./snapshots/canUndoAutoComplete */ "./packages/roosterjs-editor-dom/lib/snapshots/canUndoAutoComplete.ts"); Object.defineProperty(exports, "canUndoAutoComplete", { enumerable: true, get: function () { return canUndoAutoComplete_1.default; } }); var HtmlSanitizer_1 = __webpack_require__(/*! ./htmlSanitizer/HtmlSanitizer */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/HtmlSanitizer.ts"); Object.defineProperty(exports, "HtmlSanitizer", { enumerable: true, get: function () { return HtmlSanitizer_1.default; } }); var getInheritableStyles_1 = __webpack_require__(/*! ./htmlSanitizer/getInheritableStyles */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/getInheritableStyles.ts"); Object.defineProperty(exports, "getInheritableStyles", { enumerable: true, get: function () { return getInheritableStyles_1.default; } }); var createDefaultHtmlSanitizerOptions_1 = __webpack_require__(/*! ./htmlSanitizer/createDefaultHtmlSanitizerOptions */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/createDefaultHtmlSanitizerOptions.ts"); Object.defineProperty(exports, "createDefaultHtmlSanitizerOptions", { enumerable: true, get: function () { return createDefaultHtmlSanitizerOptions_1.default; } }); var chainSanitizerCallback_1 = __webpack_require__(/*! ./htmlSanitizer/chainSanitizerCallback */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/chainSanitizerCallback.ts"); Object.defineProperty(exports, "chainSanitizerCallback", { enumerable: true, get: function () { return chainSanitizerCallback_1.default; } }); var commitEntity_1 = __webpack_require__(/*! ./entity/commitEntity */ "./packages/roosterjs-editor-dom/lib/entity/commitEntity.ts"); Object.defineProperty(exports, "commitEntity", { enumerable: true, get: function () { return commitEntity_1.default; } }); var getEntityFromElement_1 = __webpack_require__(/*! ./entity/getEntityFromElement */ "./packages/roosterjs-editor-dom/lib/entity/getEntityFromElement.ts"); Object.defineProperty(exports, "getEntityFromElement", { enumerable: true, get: function () { return getEntityFromElement_1.default; } }); var getEntitySelector_1 = __webpack_require__(/*! ./entity/getEntitySelector */ "./packages/roosterjs-editor-dom/lib/entity/getEntitySelector.ts"); Object.defineProperty(exports, "getEntitySelector", { enumerable: true, get: function () { return getEntitySelector_1.default; } }); var entityPlaceholderUtils_1 = __webpack_require__(/*! ./entity/entityPlaceholderUtils */ "./packages/roosterjs-editor-dom/lib/entity/entityPlaceholderUtils.ts"); Object.defineProperty(exports, "createEntityPlaceholder", { enumerable: true, get: function () { return entityPlaceholderUtils_1.createEntityPlaceholder; } }); Object.defineProperty(exports, "moveContentWithEntityPlaceholders", { enumerable: true, get: function () { return entityPlaceholderUtils_1.moveContentWithEntityPlaceholders; } }); Object.defineProperty(exports, "restoreContentWithEntityPlaceholder", { enumerable: true, get: function () { return entityPlaceholderUtils_1.restoreContentWithEntityPlaceholder; } }); var cacheGetEventData_1 = __webpack_require__(/*! ./event/cacheGetEventData */ "./packages/roosterjs-editor-dom/lib/event/cacheGetEventData.ts"); Object.defineProperty(exports, "cacheGetEventData", { enumerable: true, get: function () { return cacheGetEventData_1.default; } }); var clearEventDataCache_1 = __webpack_require__(/*! ./event/clearEventDataCache */ "./packages/roosterjs-editor-dom/lib/event/clearEventDataCache.ts"); Object.defineProperty(exports, "clearEventDataCache", { enumerable: true, get: function () { return clearEventDataCache_1.default; } }); var isModifierKey_1 = __webpack_require__(/*! ./event/isModifierKey */ "./packages/roosterjs-editor-dom/lib/event/isModifierKey.ts"); Object.defineProperty(exports, "isModifierKey", { enumerable: true, get: function () { return isModifierKey_1.default; } }); var isCharacterValue_1 = __webpack_require__(/*! ./event/isCharacterValue */ "./packages/roosterjs-editor-dom/lib/event/isCharacterValue.ts"); Object.defineProperty(exports, "isCharacterValue", { enumerable: true, get: function () { return isCharacterValue_1.default; } }); var isCtrlOrMetaPressed_1 = __webpack_require__(/*! ./event/isCtrlOrMetaPressed */ "./packages/roosterjs-editor-dom/lib/event/isCtrlOrMetaPressed.ts"); Object.defineProperty(exports, "isCtrlOrMetaPressed", { enumerable: true, get: function () { return isCtrlOrMetaPressed_1.default; } }); var getStyles_1 = __webpack_require__(/*! ./style/getStyles */ "./packages/roosterjs-editor-dom/lib/style/getStyles.ts"); Object.defineProperty(exports, "getStyles", { enumerable: true, get: function () { return getStyles_1.default; } }); var setStyles_1 = __webpack_require__(/*! ./style/setStyles */ "./packages/roosterjs-editor-dom/lib/style/setStyles.ts"); Object.defineProperty(exports, "setStyles", { enumerable: true, get: function () { return setStyles_1.default; } }); var removeImportantStyleRule_1 = __webpack_require__(/*! ./style/removeImportantStyleRule */ "./packages/roosterjs-editor-dom/lib/style/removeImportantStyleRule.ts"); Object.defineProperty(exports, "removeImportantStyleRule", { enumerable: true, get: function () { return removeImportantStyleRule_1.default; } }); var setGlobalCssStyles_1 = __webpack_require__(/*! ./style/setGlobalCssStyles */ "./packages/roosterjs-editor-dom/lib/style/setGlobalCssStyles.ts"); Object.defineProperty(exports, "setGlobalCssStyles", { enumerable: true, get: function () { return setGlobalCssStyles_1.default; } }); var removeGlobalCssStyle_1 = __webpack_require__(/*! ./style/removeGlobalCssStyle */ "./packages/roosterjs-editor-dom/lib/style/removeGlobalCssStyle.ts"); Object.defineProperty(exports, "removeGlobalCssStyle", { enumerable: true, get: function () { return removeGlobalCssStyle_1.default; } }); var adjustInsertPosition_1 = __webpack_require__(/*! ./edit/adjustInsertPosition */ "./packages/roosterjs-editor-dom/lib/edit/adjustInsertPosition.ts"); Object.defineProperty(exports, "adjustInsertPosition", { enumerable: true, get: function () { return adjustInsertPosition_1.default; } }); var deleteSelectedContent_1 = __webpack_require__(/*! ./edit/deleteSelectedContent */ "./packages/roosterjs-editor-dom/lib/edit/deleteSelectedContent.ts"); Object.defineProperty(exports, "deleteSelectedContent", { enumerable: true, get: function () { return deleteSelectedContent_1.default; } }); var getTextContent_1 = __webpack_require__(/*! ./edit/getTextContent */ "./packages/roosterjs-editor-dom/lib/edit/getTextContent.ts"); Object.defineProperty(exports, "getTextContent", { enumerable: true, get: function () { return getTextContent_1.default; } }); var validate_1 = __webpack_require__(/*! ./metadata/validate */ "./packages/roosterjs-editor-dom/lib/metadata/validate.ts"); Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return validate_1.default; } }); var definitionCreators_1 = __webpack_require__(/*! ./metadata/definitionCreators */ "./packages/roosterjs-editor-dom/lib/metadata/definitionCreators.ts"); Object.defineProperty(exports, "createNumberDefinition", { enumerable: true, get: function () { return definitionCreators_1.createNumberDefinition; } }); Object.defineProperty(exports, "createBooleanDefinition", { enumerable: true, get: function () { return definitionCreators_1.createBooleanDefinition; } }); Object.defineProperty(exports, "createStringDefinition", { enumerable: true, get: function () { return definitionCreators_1.createStringDefinition; } }); Object.defineProperty(exports, "createArrayDefinition", { enumerable: true, get: function () { return definitionCreators_1.createArrayDefinition; } }); Object.defineProperty(exports, "createObjectDefinition", { enumerable: true, get: function () { return definitionCreators_1.createObjectDefinition; } }); var metadata_1 = __webpack_require__(/*! ./metadata/metadata */ "./packages/roosterjs-editor-dom/lib/metadata/metadata.ts"); Object.defineProperty(exports, "getMetadata", { enumerable: true, get: function () { return metadata_1.getMetadata; } }); Object.defineProperty(exports, "setMetadata", { enumerable: true, get: function () { return metadata_1.setMetadata; } }); Object.defineProperty(exports, "removeMetadata", { enumerable: true, get: function () { return metadata_1.removeMetadata; } }); var arrayPush_1 = __webpack_require__(/*! ./jsUtils/arrayPush */ "./packages/roosterjs-editor-dom/lib/jsUtils/arrayPush.ts"); Object.defineProperty(exports, "arrayPush", { enumerable: true, get: function () { return arrayPush_1.default; } }); var getObjectKeys_1 = __webpack_require__(/*! ./jsUtils/getObjectKeys */ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts"); Object.defineProperty(exports, "getObjectKeys", { enumerable: true, get: function () { return getObjectKeys_1.default; } }); var toArray_1 = __webpack_require__(/*! ./jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); Object.defineProperty(exports, "toArray", { enumerable: true, get: function () { return toArray_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/inlineElements/EmptyInlineElement.ts": /*!********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/inlineElements/EmptyInlineElement.ts ***! \********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * @internal * Represents an empty InlineElement. * This is used for ContentTraverser internally only. * An empty InlineElement means current position is at the end of a tag so nothing is included inside this element */ var EmptyInlineElement = /** @class */ (function () { function EmptyInlineElement(position, parentBlock) { this.position = position; this.parentBlock = parentBlock; } /** * Get the text content of this inline element */ EmptyInlineElement.prototype.getTextContent = function () { return ''; }; /** * Get the container node of this inline element */ EmptyInlineElement.prototype.getContainerNode = function () { return this.position.node; }; /** * Get the parent block element of this inline element */ EmptyInlineElement.prototype.getParentBlock = function () { return this.parentBlock; }; /** * Get the start position of this inline element */ EmptyInlineElement.prototype.getStartPosition = function () { return this.position; }; /** * Get the end position of this inline element */ EmptyInlineElement.prototype.getEndPosition = function () { return this.position; }; /** * Checks if the given inline element is after this inline element */ EmptyInlineElement.prototype.isAfter = function (inlineElement) { return inlineElement && this.position.isAfter(inlineElement.getEndPosition()); }; /** * Checks if this inline element is a textual inline element */ EmptyInlineElement.prototype.isTextualInlineElement = function () { return false; }; /** * Checks if the given editor position is contained in this inline element */ EmptyInlineElement.prototype.contains = function (position) { return false; }; /** * Apply inline style to a region of an inline element. */ EmptyInlineElement.prototype.applyStyle = function (styler) { }; return EmptyInlineElement; }()); exports.default = EmptyInlineElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/inlineElements/ImageInlineElement.ts": /*!********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/inlineElements/ImageInlineElement.ts ***! \********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var NodeInlineElement_1 = __webpack_require__(/*! ./NodeInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/NodeInlineElement.ts"); /** * This is an inline element representing an Html image */ var ImageInlineElement = /** @class */ (function (_super) { __extends(ImageInlineElement, _super); function ImageInlineElement(containerNode, parentBlock) { return _super.call(this, containerNode, parentBlock) || this; } return ImageInlineElement; }(NodeInlineElement_1.default)); exports.default = ImageInlineElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/inlineElements/LinkInlineElement.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/inlineElements/LinkInlineElement.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var NodeInlineElement_1 = __webpack_require__(/*! ./NodeInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/NodeInlineElement.ts"); /** * This is inline element presenting an html hyperlink */ var LinkInlineElement = /** @class */ (function (_super) { __extends(LinkInlineElement, _super); function LinkInlineElement(containerNode, parentBlock) { return _super.call(this, containerNode, parentBlock) || this; } return LinkInlineElement; }(NodeInlineElement_1.default)); exports.default = LinkInlineElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/inlineElements/NodeInlineElement.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/inlineElements/NodeInlineElement.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var applyTextStyle_1 = __webpack_require__(/*! ./applyTextStyle */ "./packages/roosterjs-editor-dom/lib/inlineElements/applyTextStyle.ts"); var isNodeAfter_1 = __webpack_require__(/*! ../utils/isNodeAfter */ "./packages/roosterjs-editor-dom/lib/utils/isNodeAfter.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); /** * This presents an inline element that can be represented by a single html node. * This serves as base for most inline element as it contains most implementation * of all operations that can happen on an inline element. Other sub inline elements mostly * just identify themselves for a certain type */ var NodeInlineElement = /** @class */ (function () { function NodeInlineElement(containerNode, parentBlock) { this.containerNode = containerNode; this.parentBlock = parentBlock; } /** * The text content for this inline element */ NodeInlineElement.prototype.getTextContent = function () { // nodeValue is better way to retrieve content for a text. Others, just use textContent return ((this.containerNode.nodeType == 3 /* Text */ ? this.containerNode.nodeValue : this.containerNode.textContent) || ''); }; /** * Get the container node */ NodeInlineElement.prototype.getContainerNode = function () { return this.containerNode; }; // Get the parent block NodeInlineElement.prototype.getParentBlock = function () { return this.parentBlock; }; /** * Get the start position of the inline element */ NodeInlineElement.prototype.getStartPosition = function () { // For a position, we always want it to point to a leaf node // We should try to go get the lowest first child node from the container return new Position_1.default(this.containerNode, 0).normalize(); }; /** * Get the end position of the inline element */ NodeInlineElement.prototype.getEndPosition = function () { // For a position, we always want it to point to a leaf node // We should try to go get the lowest last child node from the container return new Position_1.default(this.containerNode, -1 /* End */).normalize(); }; /** * Checks if this inline element is a textual inline element */ NodeInlineElement.prototype.isTextualInlineElement = function () { return this.containerNode && this.containerNode.nodeType == 3 /* Text */; }; /** * Checks if an inline element is after the current inline element */ NodeInlineElement.prototype.isAfter = function (inlineElement) { return inlineElement && (0, isNodeAfter_1.default)(this.containerNode, inlineElement.getContainerNode()); }; /** * Checks if the given position is contained in the inline element */ NodeInlineElement.prototype.contains = function (pos) { var start = this.getStartPosition(); var end = this.getEndPosition(); return pos && pos.isAfter(start) && end.isAfter(pos); }; /** * Apply inline style to an inline element */ NodeInlineElement.prototype.applyStyle = function (styler) { (0, applyTextStyle_1.default)(this.containerNode, styler); }; return NodeInlineElement; }()); exports.default = NodeInlineElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/inlineElements/PartialInlineElement.ts": /*!**********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/inlineElements/PartialInlineElement.ts ***! \**********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var applyTextStyle_1 = __webpack_require__(/*! ./applyTextStyle */ "./packages/roosterjs-editor-dom/lib/inlineElements/applyTextStyle.ts"); var createRange_1 = __webpack_require__(/*! ../selection/createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var getLeafSibling_1 = __webpack_require__(/*! ../utils/getLeafSibling */ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts"); /** * This is a special version of inline element that identifies a section of an inline element * We often have the need to cut an inline element in half and perform some operation only on half of an inline element * i.e. users select only some text of a text node and apply format, in that case, format has to happen on partial of an inline element * PartialInlineElement is implemented in a way that decorate another full inline element with its own override on methods like isAfter * It also offers some special methods that others don't have, i.e. nextInlineElement etc. */ var PartialInlineElement = /** @class */ (function () { function PartialInlineElement(inlineElement, start, end) { if (start === void 0) { start = null; } if (end === void 0) { end = null; } this.inlineElement = inlineElement; this.start = start; this.end = end; } /** * Get the full inline element that this partial inline decorates */ PartialInlineElement.prototype.getDecoratedInline = function () { return this.inlineElement; }; /** * Gets the container node */ PartialInlineElement.prototype.getContainerNode = function () { return this.inlineElement.getContainerNode(); }; /** * Gets the parent block */ PartialInlineElement.prototype.getParentBlock = function () { return this.inlineElement.getParentBlock(); }; /** * Gets the text content */ PartialInlineElement.prototype.getTextContent = function () { var range = (0, createRange_1.default)(this.getStartPosition(), this.getEndPosition()); return range.toString(); }; /** * Get start position of this inline element. */ PartialInlineElement.prototype.getStartPosition = function () { return this.start || this.inlineElement.getStartPosition(); }; /** * Get end position of this inline element. */ PartialInlineElement.prototype.getEndPosition = function () { return this.end || this.inlineElement.getEndPosition(); }; Object.defineProperty(PartialInlineElement.prototype, "nextInlineElement", { /** * Get next partial inline element if it is not at the end boundary yet */ get: function () { return this.end ? new PartialInlineElement(this.inlineElement, this.end) : null; }, enumerable: false, configurable: true }); Object.defineProperty(PartialInlineElement.prototype, "previousInlineElement", { /** * Get previous partial inline element if it is not at the begin boundary yet */ get: function () { return this.start ? new PartialInlineElement(this.inlineElement, undefined, this.start) : null; }, enumerable: false, configurable: true }); /** * Checks if it contains a position */ PartialInlineElement.prototype.contains = function (pos) { return pos && pos.isAfter(this.getStartPosition()) && this.getEndPosition().isAfter(pos); }; /** * Checks if this inline element is a textual inline element */ PartialInlineElement.prototype.isTextualInlineElement = function () { return this.inlineElement && this.inlineElement.isTextualInlineElement(); }; /** * Check if this inline element is after the other inline element */ PartialInlineElement.prototype.isAfter = function (inlineElement) { var thisStart = this.getStartPosition(); var otherEnd = inlineElement && inlineElement.getEndPosition(); return otherEnd && (thisStart.isAfter(otherEnd) || thisStart.equalTo(otherEnd)); }; /** * apply style */ PartialInlineElement.prototype.applyStyle = function (styler) { var from = this.getStartPosition().normalize(); var to = this.getEndPosition().normalize(); var container = this.getContainerNode(); if (from.isAtEnd) { var nextNode = (0, getLeafSibling_1.getNextLeafSibling)(container, from.node); from = nextNode ? new Position_1.default(nextNode, 0 /* Begin */) : null; } if (to.offset == 0) { var previousNode = (0, getLeafSibling_1.getPreviousLeafSibling)(container, to.node); to = previousNode ? new Position_1.default(previousNode, -1 /* End */) : null; } (0, applyTextStyle_1.default)(container, styler, from || undefined, to || undefined); }; return PartialInlineElement; }()); exports.default = PartialInlineElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/inlineElements/applyTextStyle.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/inlineElements/applyTextStyle.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var splitTextNode_1 = __webpack_require__(/*! ../utils/splitTextNode */ "./packages/roosterjs-editor-dom/lib/utils/splitTextNode.ts"); var wrap_1 = __webpack_require__(/*! ../utils/wrap */ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts"); var getLeafSibling_1 = __webpack_require__(/*! ../utils/getLeafSibling */ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts"); var splitParentNode_1 = __webpack_require__(/*! ../utils/splitParentNode */ "./packages/roosterjs-editor-dom/lib/utils/splitParentNode.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var STYLET_AGS = 'SPAN,B,I,U,EM,STRONG,STRIKE,S,SMALL,SUP,SUB'.split(','); /** * Apply style using a styler function to the given container node in the given range * @param container The container node to apply style to * @param styler The styler function * @param fromPosition From position * @param toPosition To position */ function applyTextStyle(container, styler, from, to) { if (from === void 0) { from = new Position_1.default(container, 0 /* Begin */).normalize(); } if (to === void 0) { to = new Position_1.default(container, -1 /* End */).normalize(); } var formatNodes = []; var fromPosition = from; var toPosition = to; while (fromPosition && toPosition && toPosition.isAfter(fromPosition)) { var formatNode = fromPosition.node; var parentTag = (0, getTagOfNode_1.default)(formatNode.parentNode); // The code below modifies DOM. Need to get the next sibling first otherwise you won't be able to reliably get a good next sibling node var nextNode = (0, getLeafSibling_1.getNextLeafSibling)(container, formatNode); if (formatNode.nodeType == 3 /* Text */ && ['TR', 'TABLE'].indexOf(parentTag) < 0) { if (formatNode == toPosition.node && !toPosition.isAtEnd) { formatNode = (0, splitTextNode_1.default)(formatNode, toPosition.offset, true /*returnFirstPart*/); } if (fromPosition.offset > 0) { formatNode = (0, splitTextNode_1.default)(formatNode, fromPosition.offset, false /*returnFirstPart*/); } formatNodes.push(formatNode); } fromPosition = nextNode && new Position_1.default(nextNode, 0 /* Begin */); } if (formatNodes.length > 0) { if (formatNodes.every(function (node) { return node.parentNode == formatNodes[0].parentNode; })) { var newNode_1 = formatNodes.shift(); formatNodes.forEach(function (node) { var _a; var newNodeValue = (newNode_1.nodeValue || '') + (node.nodeValue || ''); newNode_1.nodeValue = newNodeValue; (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node); }); formatNodes = [newNode_1]; } formatNodes.forEach(function (startingNode) { // When apply style within style tags like B/I/U/..., we split the tag and apply outside them // So that the inner style tag such as U, STRIKE can inherit the style we added var node = startingNode; while (node && (0, getTagOfNode_1.default)(node) != 'SPAN' && STYLET_AGS.indexOf((0, getTagOfNode_1.default)(node.parentNode)) >= 0) { callStylerWithInnerNode(node, styler); node = (0, splitParentNode_1.splitBalancedNodeRange)(node); } if (node && (0, getTagOfNode_1.default)(node) != 'SPAN') { callStylerWithInnerNode(node, styler); node = (0, wrap_1.default)(node, 'SPAN'); } if ((0, safeInstanceOf_1.default)(node, 'HTMLElement')) { styler(node); } }); } } exports.default = applyTextStyle; function callStylerWithInnerNode(node, styler) { if (node && node.nodeType == 1 /* Element */) { styler(node, true /*isInnerNode*/); } } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/inlineElements/getFirstLastInlineElement.ts": /*!***************************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/inlineElements/getFirstLastInlineElement.ts ***! \***************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getLastInlineElement = exports.getFirstInlineElement = void 0; var getInlineElementAtNode_1 = __webpack_require__(/*! ./getInlineElementAtNode */ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementAtNode.ts"); var getLeafNode_1 = __webpack_require__(/*! ../utils/getLeafNode */ "./packages/roosterjs-editor-dom/lib/utils/getLeafNode.ts"); /** * @internal * Get the first inline element inside the given node */ function getFirstInlineElement(rootNode) { // getFirstLeafNode can return null for empty container // do check null before passing on to get inline from the node var node = (0, getLeafNode_1.getFirstLeafNode)(rootNode); return node ? (0, getInlineElementAtNode_1.default)(rootNode, node) : null; } exports.getFirstInlineElement = getFirstInlineElement; /** * @internal * Get the last inline element inside the given node */ function getLastInlineElement(rootNode) { // getLastLeafNode can return null for empty container // do check null before passing on to get inline from the node var node = (0, getLeafNode_1.getLastLeafNode)(rootNode); return node ? (0, getInlineElementAtNode_1.default)(rootNode, node) : null; } exports.getLastInlineElement = getLastInlineElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementAtNode.ts": /*!************************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementAtNode.ts ***! \************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts"); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var ImageInlineElement_1 = __webpack_require__(/*! ./ImageInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/ImageInlineElement.ts"); var LinkInlineElement_1 = __webpack_require__(/*! ./LinkInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/LinkInlineElement.ts"); var NodeInlineElement_1 = __webpack_require__(/*! ./NodeInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/NodeInlineElement.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); function getInlineElementAtNode(parent, node) { // An inline element has to be in a block element, get the block first and then resolve through the factory var parentBlock = (0, safeInstanceOf_1.default)(parent, 'Node') ? (0, getBlockElementAtNode_1.default)(parent, node) : parent; return node && parentBlock && resolveInlineElement(node, parentBlock); } exports.default = getInlineElementAtNode; /** * Resolve an inline element by a leaf node * @param node The node to resolve from * @param parentBlock The parent block element */ function resolveInlineElement(node, parentBlock) { var nodeChain = [node]; for (var parent_1 = node.parentNode; parent_1 && parentBlock.contains(parent_1); parent_1 = parent_1.parentNode) { nodeChain.push(parent_1); } var inlineElement; for (var i = nodeChain.length - 1; i >= 0 && !inlineElement; i--) { var currentNode = nodeChain[i]; var tag = (0, getTagOfNode_1.default)(currentNode); if (tag == 'A') { inlineElement = new LinkInlineElement_1.default(currentNode, parentBlock); } else if (tag == 'IMG') { inlineElement = new ImageInlineElement_1.default(currentNode, parentBlock); } } return inlineElement || new NodeInlineElement_1.default(node, parentBlock); } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementBeforeAfter.ts": /*!*****************************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementBeforeAfter.ts ***! \*****************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getInlineElementBeforeAfter = exports.getInlineElementAfter = exports.getInlineElementBefore = void 0; var getInlineElementAtNode_1 = __webpack_require__(/*! ./getInlineElementAtNode */ "./packages/roosterjs-editor-dom/lib/inlineElements/getInlineElementAtNode.ts"); var PartialInlineElement_1 = __webpack_require__(/*! ./PartialInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/PartialInlineElement.ts"); var shouldSkipNode_1 = __webpack_require__(/*! ../utils/shouldSkipNode */ "./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts"); var getLeafSibling_1 = __webpack_require__(/*! ../utils/getLeafSibling */ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts"); /** * @internal * Get inline element before a position * This is mostly used when we want to get the inline element before selection/cursor * There is a possible that the cursor is in middle of an inline element (i.e. mid of a text node) * in this case, we only want to return what is before cursor (a partial of an inline) to indicate * that we're in middle. * @param root Root node of current scope, use for create InlineElement * @param position The position to get InlineElement before */ function getInlineElementBefore(root, position) { return getInlineElementBeforeAfter(root, position, false /*isAfter*/); } exports.getInlineElementBefore = getInlineElementBefore; /** * @internal * Get inline element after a position * This is mostly used when we want to get the inline element after selection/cursor * There is a possible that the cursor is in middle of an inline element (i.e. mid of a text node) * in this case, we only want to return what is before cursor (a partial of an inline) to indicate * that we're in middle. * @param root Root node of current scope, use for create InlineElement * @param position The position to get InlineElement after */ function getInlineElementAfter(root, position) { return getInlineElementBeforeAfter(root, position, true /*isAfter*/); } exports.getInlineElementAfter = getInlineElementAfter; /** * @internal */ function getInlineElementBeforeAfter(root, position, isAfter) { if (!root || !position || !position.node) { return null; } position = position.normalize(); var offset = position.offset, isAtEnd = position.isAtEnd; var node = position.node; var isPartial = false; if ((!isAfter && offset == 0 && !isAtEnd) || (isAfter && isAtEnd)) { node = (0, getLeafSibling_1.getLeafSibling)(root, node, isAfter); } else if (node.nodeType == 3 /* Text */ && ((!isAfter && !isAtEnd) || (isAfter && offset > 0))) { isPartial = true; } if (node && (0, shouldSkipNode_1.default)(node)) { node = (0, getLeafSibling_1.getLeafSibling)(root, node, isAfter); } var inlineElement = (0, getInlineElementAtNode_1.default)(root, node); if (inlineElement && (isPartial || inlineElement.contains(position))) { inlineElement = isAfter ? new PartialInlineElement_1.default(inlineElement, position, undefined) : new PartialInlineElement_1.default(inlineElement, undefined, position); } return inlineElement; } exports.getInlineElementBeforeAfter = getInlineElementBeforeAfter; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/jsUtils/arrayPush.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/jsUtils/arrayPush.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * A type-safe wrapper for Array.prototype.push.apply() * @param mainArray The main array to push items into * @param itemsArray The items to push to main array */ function arrayPush(mainArray, itemsArray) { Array.prototype.push.apply(mainArray, itemsArray); } exports.default = arrayPush; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Provide a strong-typed version of Object.keys() * @param obj The source object * @returns Array of keys */ function getObjectKeys(obj) { return Object.keys(obj); } exports.default = getObjectKeys; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function toArray(collection) { return [].slice.call(collection); } exports.default = toArray; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/VList.ts": /*!*********************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/VList.ts ***! \*********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); var changeElementTag_1 = __webpack_require__(/*! ../utils/changeElementTag */ "./packages/roosterjs-editor-dom/lib/utils/changeElementTag.ts"); var getListTypeFromNode_1 = __webpack_require__(/*! ./getListTypeFromNode */ "./packages/roosterjs-editor-dom/lib/list/getListTypeFromNode.ts"); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var isBlockElement_1 = __webpack_require__(/*! ../utils/isBlockElement */ "./packages/roosterjs-editor-dom/lib/utils/isBlockElement.ts"); var isNodeEmpty_1 = __webpack_require__(/*! ../utils/isNodeEmpty */ "./packages/roosterjs-editor-dom/lib/utils/isNodeEmpty.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var queryElements_1 = __webpack_require__(/*! ../utils/queryElements */ "./packages/roosterjs-editor-dom/lib/utils/queryElements.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var splitParentNode_1 = __webpack_require__(/*! ../utils/splitParentNode */ "./packages/roosterjs-editor-dom/lib/utils/splitParentNode.ts"); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); var unwrap_1 = __webpack_require__(/*! ../utils/unwrap */ "./packages/roosterjs-editor-dom/lib/utils/unwrap.ts"); var VListItem_1 = __webpack_require__(/*! ./VListItem */ "./packages/roosterjs-editor-dom/lib/list/VListItem.ts"); var wrap_1 = __webpack_require__(/*! ../utils/wrap */ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts"); var metadata_1 = __webpack_require__(/*! ../metadata/metadata */ "./packages/roosterjs-editor-dom/lib/metadata/metadata.ts"); /** * Represent a bullet or a numbering list * * @example * A VList is a logical representation of list items, it contains an item array with node and list type stack. * e.g. We have a list like this * ```html *
    *
  1. item 1
  2. *
  3. item 2
  4. *
      *
    • item 2.1
    • *
    • item 2.2
    • *
        *
* ``` * * A VList of this list will be like this: * ```javascript * { * rootList: (OL node), * items: [{ * node: (LI node with 'item 1'), * listTypes: [null, OL], * }, { * node: (LI node with 'item 2'), * listTypes: [null, OL], * }, { * node: (LI node with 'item 2.1), * listTypes: [null, OL, UL], * }, { * node: (LI node with 'item 2.2'), * listTypes: [null, OL, UL], * } * ] * } * ``` * * When we want to outdent item 2.1, we just need to remove the last "UL" from listTypes of item 2.1, then * the writeBack() function will handle everything related to DOM change */ var VList = /** @class */ (function () { /** * Create a new instance of VList class * @param rootList The root list element, can be either OL or UL tag */ function VList(rootList) { this.rootList = rootList; this.items = []; if (!rootList) { throw new Error('rootList must not be null'); } // Before populate items, we need to normalize the list to make sure it is in a correct format // otherwise further action may mass thing up. // // There are two kinds of normalization to perform. // 1. Move nodes directly under OL/UL into a LI node, unless it is an orphan node // Please see comment for VListItem.isOrphanItem() for more information about orphan node // e.g.: // ```HTML //
    //
  1. item 1
  2. //
    item 2
    //
// ``` // After this step, it should become: // ```html //
    //
  1. item 1 //
    item 2
    //
  2. //
// ``` moveChildNodesToLi(this.rootList); (0, queryElements_1.default)(this.rootList, 'ol,ul', moveChildNodesToLi); // 2. Move LI node embedded into another LI node out to directly under OL/UL node // Ideally browser we do this for us automatically when out the HTML into DOM. However after // step 1, it is possible that we move some LI node into another one. e.g: // ```HTML //
    //
  1. item 1
  2. //
    // item 1.1 //
  3. item 3
  4. //
    //
// ``` // See that the second LI tag is not directly under OL, so after step 1, this will become: // ```html //
    //
  1. item 1 //
    // item 1.1 //
  2. item 2
  3. //
//
  • // // ``` // Now we have a LI tag embedded into another LI tag. So we need step 2 to move the inner LI tag out to be: // ```html //
      //
    1. item1 //
      item 1.1
      //
    2. //
    3. item2
    4. //
    // ``` (0, queryElements_1.default)(this.rootList, 'li', moveLiToList); this.populateItems(this.rootList); } /** * Check if this list contains the given node * @param node The node to check */ VList.prototype.contains = function (node) { // We don't check if the node is contained by this.rootList here, because after some operation, // it is possible a node is logically contained by this list but the container list item hasn't // been put under this.rootList in DOM tree yet. return this.items.some(function (item) { return item.contains(node); }); }; /** * Get list number of the last item in this VList. * If there is no order list item, result will be undefined */ VList.prototype.getLastItemNumber = function () { var start = this.getStart(); return start === undefined ? start : start - 1 + this.items.filter(function (item) { return item.getListType() == 1 /* Ordered */ && item.getLevel() == 1 && !item.isDummy(); }).length; }; /** * Write the result back into DOM tree * After that, this VList becomes unavailable because we set this.rootList to null * * @param shouldReuseAllAncestorListElements Optional - defaults to false. */ VList.prototype.writeBack = function (shouldReuseAllAncestorListElements) { var _this = this; if (!this.rootList) { throw new Error('rootList must not be null'); } var doc = this.rootList.ownerDocument; var listStack = [doc.createDocumentFragment()]; var placeholder = doc.createTextNode(''); var start = this.getStart() || 1; var lastList; // Use a placeholder to hold the position since the root list may be moved into document fragment later this.rootList.parentNode.replaceChild(placeholder, this.rootList); this.items.forEach(function (item) { var newListStart = item.getNewListStart(); if (newListStart && newListStart != start) { listStack.splice(1, listStack.length - 1); start = newListStart; } item.writeBack(listStack, _this.rootList, shouldReuseAllAncestorListElements); var topList = listStack[1]; if ((0, safeInstanceOf_1.default)(topList, 'HTMLOListElement')) { if (lastList != topList) { if (start == 1) { topList.removeAttribute('start'); } else { topList.start = start; } } if (item.getLevel() == 1) { start++; } } var itemIndex = _this.getListItemIndex(item.getNode()); item.applyListStyle(_this.rootList, itemIndex); lastList = topList; }); // Restore the content to the position of placeholder placeholder.parentNode.replaceChild(listStack[0], placeholder); }; /** * Sets the New List Start Property, that is going to be used to create a new List in the WriteBack function * @param separator The HTML element that indicates when to split the VList * @param startNumber The start number of the new List */ VList.prototype.split = function (separator, startNumber) { if (!this.rootList) { throw new Error('rootList must not be null'); } //Traverse the items of the VList, when the separator is found, set the New List Start Property for (var index = 0; index < this.items.length; index++) { if (this.items[index].getNode() == separator) { this.items[index].setNewListStart(startNumber); return; } } }; VList.prototype.setIndentation = function (start, end, indentation, softOutdent, preventItemRemoval) { var _this = this; if (preventItemRemoval === void 0) { preventItemRemoval = false; } var shouldAddMargin = false; this.findListItems(start, end, function (item) { shouldAddMargin = shouldAddMargin || _this.items.indexOf(item) == 0; indentation == 1 /* Decrease */ ? softOutdent && !item.isDummy() ? item.setIsDummy(true /*isDummy*/) : item.outdent(preventItemRemoval) : item.indent(); }); if (shouldAddMargin && preventItemRemoval) { for (var index = 0; index < this.items.length; index++) { this.items[index].addNegativeMargins(); } } }; /** * Set alignment of the given range of this list * @param start Start position to operate from * @param end End position to operate to * @param alignment Align items left, center or right */ VList.prototype.setAlignment = function (start, end, alignment) { this.rootList.style.display = 'flex'; this.rootList.style.flexDirection = 'column'; this.findListItems(start, end, function (item) { var align = 'start'; if (alignment == 1 /* Center */) { align = 'center'; } else if (alignment == 2 /* Right */) { align = 'end'; } item.getNode().style.alignSelf = align; }); }; /** * Change list type of the given range of this list. * If some of the items are not real list item yet, this will make them to be list item with given type * If all items in the given range are already in the type to change to, this becomes an outdent operation * @param start Start position to operate from * @param end End position to operate to * @param targetType Target list type */ VList.prototype.changeListType = function (start, end, targetType) { var needChangeType = false; this.findListItems(start, end, function (item) { needChangeType = needChangeType || item.getListType() != targetType; }); this.findListItems(start, end, function (item) { return needChangeType ? item.changeListType(targetType) : item.outdent(); }); }; /** * Change list style of the given range of this list. * If some of the items are not real list item yet, this will make them to be list item with given style * @param orderedStyle The style of ordered list * @param unorderedStyle The style of unordered list */ VList.prototype.setListStyleType = function (orderedStyle, unorderedStyle) { var style = (0, metadata_1.getMetadata)(this.rootList, VListItem_1.ListStyleDefinitionMetadata); var styleMetadata = createListStyleMetadata(style, orderedStyle, unorderedStyle); (0, metadata_1.setMetadata)(this.rootList, styleMetadata, VListItem_1.ListStyleDefinitionMetadata); }; /** * Append a new item to this VList * @param node node of the item to append. If it is not wrapped with LI tag, it will be wrapped * @param type Type of this list item, can be ListType.None */ VList.prototype.appendItem = function (node, type) { var nodeTag = (0, getTagOfNode_1.default)(node); // Change DIV tag to SPAN. Otherwise we cannot create new list item by Enter key in Safari if (nodeTag == 'DIV') { node = (0, changeElementTag_1.default)(node, 'LI'); } else if (nodeTag != 'LI') { node = (0, wrap_1.default)(node, 'LI'); } this.items.push(type == 0 /* None */ ? new VListItem_1.default(node) : new VListItem_1.default(node, type)); }; /** * Merge the given VList into current VList. * - All list items will be removed from the given VList and added into this list. * - The root node of the given VList will be removed from DOM tree * - If there are orphan items in the given VList, they will be merged into the last item * of this list if any. * @param list The vList to merge from */ VList.prototype.mergeVList = function (list) { var _this = this; var _a; if (list && list != this) { list.items.forEach(function (item) { return _this.items.push(item); }); list.items.splice(0, list.items.length); (_a = list.rootList.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(list.rootList); } }; /** * Get the index of the List Item in the current List * If the root list is: * Ordered list, the listIndex start count is going to be the start property of the OL - 1, * @example For example if we want to find the index of Item 2 in the list below, the returned index is going to be 6 * * ```html *
      *
    1. item 1
    2. *
    3. item 2
    4. *
    5. item 3
    6. *
    * ``` * Unordered list, the listIndex start count starts from 0 * @example For example if we want to find the index of Item 2 in the list below, the returned index is going to be 2 * ```html *
      *
    • item 1
    • *
    • item 2
    • *
    • item 3
    • *
    * ``` * @param input List item to find in the root list */ VList.prototype.getListItemIndex = function (input) { if (this.items) { var listIndex = (this.getStart() || 1) - 1; for (var index = 0; index < this.items.length; index++) { var child = this.items[index]; if (child.getLevel() == 1 && !child.isDummy()) { listIndex++; } if (child.getNode() == input) { return listIndex; } } } return -1; }; /** * Get the Start property of the root list of this VList * @returns Start number of the list */ VList.prototype.getStart = function () { return (0, safeInstanceOf_1.default)(this.rootList, 'HTMLOListElement') ? this.rootList.start : undefined; }; VList.prototype.findListItems = function (start, end, callback) { if (this.items.length == 0) { return []; } var listStartPos = new Position_1.default(this.items[0].getNode(), 0 /* Begin */); var listEndPos = new Position_1.default(this.items[this.items.length - 1].getNode(), -1 /* End */); var startIndex = listStartPos.isAfter(start) ? 0 : -1; var endIndex = this.items.length - (end.isAfter(listEndPos) ? 1 : 0); this.items.forEach(function (item, index) { startIndex = item.contains(start.node) ? index : startIndex; endIndex = item.contains(end.node) ? index : endIndex; }); startIndex = endIndex < this.items.length ? Math.max(0, startIndex) : startIndex; endIndex = startIndex >= 0 ? Math.min(this.items.length - 1, endIndex) : endIndex; var result = startIndex <= endIndex ? this.items.slice(startIndex, endIndex + 1) : []; if (callback) { result.forEach(callback); } return result; }; VList.prototype.populateItems = function (list, listTypes) { var _this = this; if (listTypes === void 0) { listTypes = []; } var type = (0, getListTypeFromNode_1.default)(list); var items = (0, toArray_1.default)(list.childNodes); items.forEach(function (item) { var newListTypes = __spreadArray(__spreadArray([], listTypes, true), [type], false); if ((0, getListTypeFromNode_1.isListElement)(item)) { _this.populateItems(item, newListTypes); } else if (item.nodeType != 3 /* Text */ || (item.nodeValue || '').trim() != '') { _this.items.push(new (VListItem_1.default.bind.apply(VListItem_1.default, __spreadArray([void 0, item], newListTypes, false)))()); } }); }; return VList; }()); exports.default = VList; //Normalization // Step 1: Move all non-LI direct children under list into LI // e.g. // From:
    • line 1
    • line 2
    // To:
    • line 1
      line 2
    function moveChildNodesToLi(list) { var currentItem = null; (0, toArray_1.default)(list.childNodes).forEach(function (child) { if ((0, getTagOfNode_1.default)(child) == 'LI') { currentItem = child; } else if ((0, getListTypeFromNode_1.isListElement)(child)) { currentItem = null; } else if (currentItem && !(0, isNodeEmpty_1.default)(child, true /*trimContent*/)) { currentItem.appendChild((0, isBlockElement_1.default)(child) ? child : (0, wrap_1.default)(child)); } }); } // Step 2: Move nested LI up to under list directly // e.g. // From:
    • line 1
    • line 2
    • line 3
    // To:
    • line 1
    • line 2
      line 3
    function moveLiToList(li) { while (!(0, getListTypeFromNode_1.isListElement)(li.parentNode)) { (0, splitParentNode_1.default)(li, true /*splitBefore*/); var furtherNodes = (0, toArray_1.default)(li.parentNode.childNodes).slice(1); if (furtherNodes.length > 0) { if (!(0, isBlockElement_1.default)(furtherNodes[0])) { furtherNodes = [(0, wrap_1.default)(furtherNodes)]; } furtherNodes.forEach(function (node) { return li.appendChild(node); }); } (0, unwrap_1.default)(li.parentNode); } } function getValidValue() { var values = []; for (var _i = 0; _i < arguments.length; _i++) { values[_i] = arguments[_i]; } return values.filter(function (x) { return x !== undefined; })[0]; } function createListStyleMetadata(style, orderedStyle, unorderedStyle) { return { orderedStyleType: getValidValue(orderedStyle, style === null || style === void 0 ? void 0 : style.orderedStyleType, 1 /* Decimal */), unorderedStyleType: getValidValue(unorderedStyle, style === null || style === void 0 ? void 0 : style.unorderedStyleType, 1 /* Disc */), }; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/VListChain.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/VListChain.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var arrayPush_1 = __webpack_require__(/*! ../jsUtils/arrayPush */ "./packages/roosterjs-editor-dom/lib/jsUtils/arrayPush.ts"); var getRootListNode_1 = __webpack_require__(/*! ./getRootListNode */ "./packages/roosterjs-editor-dom/lib/list/getRootListNode.ts"); var isNodeAfter_1 = __webpack_require__(/*! ../utils/isNodeAfter */ "./packages/roosterjs-editor-dom/lib/utils/isNodeAfter.ts"); var isNodeInRegion_1 = __webpack_require__(/*! ../region/isNodeInRegion */ "./packages/roosterjs-editor-dom/lib/region/isNodeInRegion.ts"); var queryElements_1 = __webpack_require__(/*! ../utils/queryElements */ "./packages/roosterjs-editor-dom/lib/utils/queryElements.ts"); var VList_1 = __webpack_require__(/*! ./VList */ "./packages/roosterjs-editor-dom/lib/list/VList.ts"); var CHAIN_NAME_PREFIX = '__List_Chain_'; var CHAIN_DATASET_NAME = 'listchain'; var AFTER_CURSOR_DATASET_NAME = 'listchainafter'; var lastChainIndex = 0; /** * Represent a chain of list nodes. * A chain of lists is a virtual link of lists that have continuous numbers, when editor one of them, * all others should also be updated in order to main the list number to be continuous. */ var VListChain = /** @class */ (function () { /** * Construct a new instance of VListChain class * @param editor Editor object */ function VListChain(region, name) { this.region = region; this.name = name; this.lastNumber = 0; this.lastNumberBeforeCursor = 0; } /** * Create an array of VListChain from current region in editor * @param region The region to create VListChain from * @param currentNode Optional current node, used for mark lists that are after this node * @param nameGenerator Used by test code only */ VListChain.createListChains = function (region, currentNode, nameGenerator) { var regions = Array.isArray(region) ? region : region ? [region] : []; var result = []; regions.forEach(function (region) { var chains = []; var lastList; (0, queryElements_1.default)(region.rootNode, 'ol', function (ol) { var list = (0, getRootListNode_1.default)(region, 'ol', ol); if (lastList != list) { var chain = chains.filter(function (c) { return c.canAppendToTail(list); })[0] || new VListChain(region, (nameGenerator || createListChainName)()); var index = chains.indexOf(chain); var afterCurrentNode = !!currentNode && (0, isNodeAfter_1.default)(list, currentNode); if (!afterCurrentNode) { // Make sure current one is at the front if current block has not been met, so that // the first chain is always the nearest one from current node if (index >= 0) { chains.splice(index, 1); } chains.unshift(chain); } else if (index < 0) { chains.push(chain); } chain.append(list, afterCurrentNode); lastList = list; } }); (0, arrayPush_1.default)(result, chains); }); return result; }; /** * Check if a list with the given start number can be appended next to the last list before cursor * @param startNumber The start number of the new list */ VListChain.prototype.canAppendAtCursor = function (startNumber) { return startNumber > 1 && this.lastNumberBeforeCursor + 1 == startNumber; }; /** * Create a VList to wrap the block of the given node, and append to current chain * @param container The container node to create list at * @param startNumber Start number of the new list */ VListChain.prototype.createVListAtBlock = function (container, startNumber) { if (container && container.parentNode) { var list = container.ownerDocument.createElement('ol'); list.start = startNumber; this.applyChainName(list); container.parentNode.insertBefore(list, container); var vList = new VList_1.default(list); vList.appendItem(container, 0 /* None */); return vList; } else { return null; } }; /** * After change the lists, commit the change to all lists in this chain to update the list number, * and clear the temporary dataset values added to list node */ VListChain.prototype.commit = function (shouldReuseAllAncestorListElements) { var lists = this.getLists(); var lastNumber = 0; for (var i = 0; i < lists.length; i++) { var list = lists[i]; list.start = list.start > 1 ? list.start : lastNumber + 1; var vlist = new VList_1.default(list); lastNumber = vlist.getLastItemNumber() || 0; delete list.dataset[CHAIN_DATASET_NAME]; delete list.dataset[AFTER_CURSOR_DATASET_NAME]; vlist.writeBack(shouldReuseAllAncestorListElements); } }; /** * Check if the given list node is can be appended into current list chain * @param list The list node to check */ VListChain.prototype.canAppendToTail = function (list) { return this.lastNumber + 1 == list.start; }; /** * Append the given list node into this VListChain * @param list The list node to append * @param isAfterCurrentNode Whether this list is after current node */ VListChain.prototype.append = function (list, isAfterCurrentNode) { this.applyChainName(list); this.lastNumber = new VList_1.default(list).getLastItemNumber() || 0; if (isAfterCurrentNode) { list.dataset[AFTER_CURSOR_DATASET_NAME] = 'true'; } else { this.lastNumberBeforeCursor = this.lastNumber; } }; VListChain.prototype.applyChainName = function (list) { list.dataset[CHAIN_DATASET_NAME] = this.name; }; VListChain.prototype.getLists = function () { var _this = this; return (0, queryElements_1.default)(this.region.rootNode, "ol[data-" + CHAIN_DATASET_NAME + "=" + this.name + "]").filter(function (node) { return (0, isNodeInRegion_1.default)(_this.region, node); }); }; return VListChain; }()); exports.default = VListChain; function createListChainName() { return CHAIN_NAME_PREFIX + lastChainIndex++; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/VListItem.ts": /*!*************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/VListItem.ts ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ListStyleDefinitionMetadata = void 0; var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var getListTypeFromNode_1 = __webpack_require__(/*! ./getListTypeFromNode */ "./packages/roosterjs-editor-dom/lib/list/getListTypeFromNode.ts"); var getStyles_1 = __webpack_require__(/*! ../style/getStyles */ "./packages/roosterjs-editor-dom/lib/style/getStyles.ts"); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var isBlockElement_1 = __webpack_require__(/*! ../utils/isBlockElement */ "./packages/roosterjs-editor-dom/lib/utils/isBlockElement.ts"); var moveChildNodes_1 = __webpack_require__(/*! ../utils/moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var setBulletListMarkers_1 = __webpack_require__(/*! ./setBulletListMarkers */ "./packages/roosterjs-editor-dom/lib/list/setBulletListMarkers.ts"); var setListItemStyle_1 = __webpack_require__(/*! ./setListItemStyle */ "./packages/roosterjs-editor-dom/lib/list/setListItemStyle.ts"); var setNumberingListMarkers_1 = __webpack_require__(/*! ./setNumberingListMarkers */ "./packages/roosterjs-editor-dom/lib/list/setNumberingListMarkers.ts"); var setStyles_1 = __webpack_require__(/*! ../style/setStyles */ "./packages/roosterjs-editor-dom/lib/style/setStyles.ts"); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); var unwrap_1 = __webpack_require__(/*! ../utils/unwrap */ "./packages/roosterjs-editor-dom/lib/utils/unwrap.ts"); var wrap_1 = __webpack_require__(/*! ../utils/wrap */ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts"); var definitionCreators_1 = __webpack_require__(/*! ../metadata/definitionCreators */ "./packages/roosterjs-editor-dom/lib/metadata/definitionCreators.ts"); var metadata_1 = __webpack_require__(/*! ../metadata/metadata */ "./packages/roosterjs-editor-dom/lib/metadata/metadata.ts"); var orderListStyles = [null, 'lower-alpha', 'lower-roman']; var unorderedListStyles = ['disc', 'circle', 'square']; var MARGIN_BASE = '0in 0in 0in 0.5in'; var NEGATIVE_MARGIN = '-.25in'; var stylesToInherit = ['font-size', 'font-family', 'color']; var attrsToInherit = ['data-ogsc', 'data-ogsb', 'data-ogac', 'data-ogab']; /** * @internal * The definition for the number of BulletListType or NumberingListType */ exports.ListStyleDefinitionMetadata = (0, definitionCreators_1.createObjectDefinition)({ orderedStyleType: (0, definitionCreators_1.createNumberDefinition)(true /** isOptional */, undefined /** value **/, 1 /* Min */, 20 /* Max */), unorderedStyleType: (0, definitionCreators_1.createNumberDefinition)(true /** isOptional */, undefined /** value **/, 1 /* Min */, 9 /* Max */), }, true /** isOptional */, true /** allowNull */); /** * !!! Never directly create instance of this class. It should be created within VList class !!! * * Represent a list item. * * A list item is normally wrapped using a LI tag. But this class is only a logical item, * it can be a LI tag, or another other type of node which means it is actually not a list item. * That can happen after we do "outdent" on a 1-level list item, then it becomes not a list item. */ var VListItem = /** @class */ (function () { /** * Construct a new instance of VListItem class * @param node The DOM node for this item * @param listTypes An array represents list types of all parent and current level. * Skip this parameter for a non-list item. */ function VListItem(node) { var listTypes = []; for (var _i = 1; _i < arguments.length; _i++) { listTypes[_i - 1] = arguments[_i]; } this.newListStart = undefined; if (!node) { throw new Error('node must not be null'); } this.node = (0, safeInstanceOf_1.default)(node, 'HTMLLIElement') ? node : (0, wrap_1.default)(node, 4 /* BlockListItem */); var display = this.node.style.display; this.dummy = display != 'list-item' && display != ''; // Always add a None list type in front of all other types to represent non-list scenario. this.listTypes = __spreadArray([0 /* None */], listTypes, true); } /** * Get type of current list item */ VListItem.prototype.getListType = function () { return this.listTypes[this.listTypes.length - 1]; }; /** * Get the levels of this list item. */ VListItem.prototype.getLevel = function () { return this.listTypes.length - 1; }; /** * Get DOM node of this list item */ VListItem.prototype.getNode = function () { return this.node; }; /** * Get the Start Number of the new List */ VListItem.prototype.getNewListStart = function () { return this.newListStart; }; /** * Check if a given node is contained by this list item * @param node The node to check */ VListItem.prototype.contains = function (node) { return (0, contains_1.default)(this.node, node, true /*treatSameNodeAsContain*/); }; /** * Check if this item is a dummy item. * A dummy item is also represented by LI tag, but it won't render a bullet (for Unordered list) or a number (for Ordered list) * normally it has CSS style display set to a value other than "list-item" */ VListItem.prototype.isDummy = function () { return this.dummy; }; /** * @deprecated Always return false */ VListItem.prototype.isOrphanItem = function () { return false; }; /** * @deprecated */ VListItem.prototype.canMerge = function (item) { if (!(item === null || item === void 0 ? void 0 : item.isOrphanItem()) || this.listTypes.length != item.listTypes.length) { return false; } return this.listTypes.every(function (type, index) { return item.listTypes[index] == type; }); }; /** * @deprecated */ VListItem.prototype.mergeItems = function (items) { var _this = this; var nodesToWrap = (items === null || items === void 0 ? void 0 : items.map(function (item) { return item.node; })) || []; var targetNodes = wrapIfNotBlockNode(nodesToWrap, true /*checkFirst*/, false /*checkLast*/); targetNodes.forEach(function (node) { return _this.node.appendChild(node); }); }; /** * Indent this item * If this is not an list item, it will be no op */ VListItem.prototype.indent = function () { if (this.node.style.marginLeft == NEGATIVE_MARGIN) { this.node.style.margin = ''; this.node.style.marginLeft = ''; return; } var listType = this.getListType(); if (listType != 0 /* None */) { this.listTypes.push(listType); } }; /** * Outdent this item * If this item is already not an list item, it will be no op * @param preventItemRemoval Whether prevent the list item to be removed for the listItem by default false */ VListItem.prototype.outdent = function (preventItemRemoval) { if (preventItemRemoval === void 0) { preventItemRemoval = false; } var expectedLength = preventItemRemoval ? 2 : 1; if (this.listTypes.length > expectedLength) { this.listTypes.pop(); } }; /** * Add negative margin to the List item */ VListItem.prototype.addNegativeMargins = function () { this.node.style.margin = MARGIN_BASE; this.node.style.marginLeft = NEGATIVE_MARGIN; }; /** * Change list type of this item * @param targetType The target list type to change to */ VListItem.prototype.changeListType = function (targetType) { if (targetType == 0 /* None */) { this.listTypes = [targetType]; } else { this.outdent(); this.listTypes.push(targetType); } }; /** * Set whether the item is a dummy item * @param isDummy Whether the item is a dummy item */ VListItem.prototype.setIsDummy = function (isDummy) { this.dummy = isDummy; }; /** * Set the start Number of the new list * @param isDummy Whether the item is a dummy item */ VListItem.prototype.setNewListStart = function (startNumber) { this.newListStart = startNumber; }; /** * Apply the list style type * @param rootList the vList that receives the style * @param index the list item index */ VListItem.prototype.applyListStyle = function (rootList, index) { var style = (0, metadata_1.getMetadata)(rootList, exports.ListStyleDefinitionMetadata); // The list just need to be styled if it is at top level, so the listType length for this Vlist must be 2. var isFirstLevel = this.listTypes.length < 3; if (style) { if (isFirstLevel && this.listTypes[1] === 2 /* Unordered */ && style.unorderedStyleType) { (0, setBulletListMarkers_1.default)(this.node, style.unorderedStyleType); } else if (isFirstLevel && this.listTypes[1] === 1 /* Ordered */ && style.orderedStyleType) { (0, setNumberingListMarkers_1.default)(this.node, style.orderedStyleType, index); } else { this.node.style.removeProperty('list-style-type'); } } }; /** * Write the change result back into DOM * @param listStack current stack of list elements * @param originalRoot Original list root element. It will be reused when write back if possible * @param shouldReuseAllAncestorListElements Optional - defaults to false. If true, only make * sure the direct parent of this list matches the list types when writing back. */ VListItem.prototype.writeBack = function (listStack, originalRoot, shouldReuseAllAncestorListElements) { var _this = this; var _a; if (shouldReuseAllAncestorListElements === void 0) { shouldReuseAllAncestorListElements = false; } var nextLevel = 1; if (shouldReuseAllAncestorListElements) { // Remove any un-needed lists from the stack. if (listStack.length > this.listTypes.length) { listStack.splice(this.listTypes.length); } // 1. If the listStack is the same length as the listTypes for this item, check // if the last item needs to change, and remove it if needed. We can always re-use // the other lists even if the type doesn't match - since the display is the same // as long as the list immediately surrounding the item is correct. var listStackEndIndex = listStack.length - 1; if (listStackEndIndex === this.listTypes.length - 1 && // they are the same length (0, getListTypeFromNode_1.default)(listStack[listStackEndIndex]) !== this.listTypes[listStackEndIndex]) { listStack.splice(listStackEndIndex); } nextLevel = listStack.length; } else { // 1. Determine list elements that we can reuse // e.g.: // passed in listStack: Fragment > OL > UL > OL // local listTypes: null > OL > UL > UL > OL // then Fragment > OL > UL can be reused for (; nextLevel < listStack.length; nextLevel++) { if ((0, getListTypeFromNode_1.default)(listStack[nextLevel]) !== this.listTypes[nextLevel]) { listStack.splice(nextLevel); break; } } } // 2. Add new list elements // e.g.: // passed in listStack: Fragment > OL > UL // local listTypes: null > OL > UL > UL > OL // then we need to create a UL and a OL tag for (; nextLevel < this.listTypes.length; nextLevel++) { var stackLength = listStack.length - 1; var newList = createListElement(listStack[0], this.listTypes[nextLevel], nextLevel, originalRoot); listStack[stackLength].appendChild(newList); listStack.push(newList); //If the current node parent is in the same deep child index, //apply the styles of the current parent list to the new list if (this.getDeepChildIndex(originalRoot) == stackLength) { var listStyleType = (_a = this.node.parentElement) === null || _a === void 0 ? void 0 : _a.style.listStyleType; if (listStyleType && (0, getTagOfNode_1.default)(this.node.parentElement) === (0, getTagOfNode_1.default)(newList)) { newList.style.listStyleType = listStyleType; } } } // 3. Add current node into deepest list element listStack[listStack.length - 1].appendChild(this.node); this.node.style.setProperty('display', this.dummy ? 'block' : null); // 4. Inherit styles of the child element to the li, so we are able to apply the styles to the ::marker if (this.listTypes.length > 1) { (0, setListItemStyle_1.default)(this.node, stylesToInherit, true /*isCssStyle*/); (0, setListItemStyle_1.default)(this.node, attrsToInherit, false /*isCssStyle*/); } // 5. If this is not a list item now, need to unwrap the LI node and do proper handling if (this.listTypes.length <= 1) { // If original
  • node has styles for font and color, we need to apply it to new parent var isLi = (0, getTagOfNode_1.default)(this.node) == 'LI'; var stylesToApply = isLi ? { 'font-family': this.node.style.fontFamily, 'font-size': this.node.style.fontSize, color: this.node.style.color, } : undefined; var childNodes = isLi ? getChildrenAndUnwrap(this.node) : [this.node]; if (stylesToApply) { var _loop_1 = function (i) { if ((0, safeInstanceOf_1.default)(childNodes[i], 'Text')) { childNodes[i] = (0, wrap_1.default)(childNodes[i], 'span'); } var node = childNodes[i]; if ((0, safeInstanceOf_1.default)(node, 'HTMLElement')) { var styles = __assign(__assign({}, stylesToApply), (0, getStyles_1.default)(node)); (0, setStyles_1.default)(node, styles); attrsToInherit.forEach(function (attr) { var attrValue = _this.node.getAttribute(attr); if (attrValue) { node.setAttribute(attr, attrValue); } }); } }; for (var i = 0; i < childNodes.length; i++) { _loop_1(i); } } wrapIfNotBlockNode(childNodes, true /*checkFirst*/, true /*checkLast*/); } }; /** * Get the index of how deep is the current node parent list inside of the original root list. * @example In the following structure this function would return 2 * ```html *
      *
        *
          *
        1. *
        *
      *
    * ``` * @param originalRoot The root list * @returns -1 if the node does not have parent element or if original root was not provided, * else, how deep is the parent element inside of the original root. */ VListItem.prototype.getDeepChildIndex = function (originalRoot) { var parentElement = this.node.parentElement; if (originalRoot && parentElement) { var deepIndex = 0; while (parentElement && parentElement != originalRoot) { deepIndex++; parentElement = (parentElement === null || parentElement === void 0 ? void 0 : parentElement.parentElement) || null; } return deepIndex; } return -1; }; return VListItem; }()); exports.default = VListItem; function createListElement(newRoot, listType, nextLevel, originalRoot) { var doc = newRoot.ownerDocument; var result; // Try to reuse the existing root element // It can be reused when // 1. Current list item is level 1 (top level), AND // 2. Original root exists, AND // 3. They have the same list type AND // 4. The original root is not used yet if (nextLevel == 1 && originalRoot && listType == (0, getListTypeFromNode_1.default)(originalRoot)) { if ((0, contains_1.default)(newRoot, originalRoot)) { // If it is already used, let's clone one and remove ID to avoid duplicating ID result = originalRoot.cloneNode(false /*deep*/); result.removeAttribute('id'); } else { // Remove all child nodes, they will be added back later when write back other items (0, moveChildNodes_1.default)(originalRoot); result = originalRoot; } } else { // Can't be reused, can't clone, let's create a new one result = doc.createElement(listType == 1 /* Ordered */ ? 'ol' : 'ul'); } // Always maintain the metadata saved in the list if (originalRoot && nextLevel == 1 && listType != (0, getListTypeFromNode_1.default)(originalRoot)) { var style = (0, metadata_1.getMetadata)(originalRoot, exports.ListStyleDefinitionMetadata); if (style) { (0, metadata_1.setMetadata)(result, style, exports.ListStyleDefinitionMetadata); } } if (listType == 1 /* Ordered */ && nextLevel > 1) { result.style.setProperty('list-style-type', orderListStyles[(nextLevel - 1) % orderListStyles.length]); } if (listType == 2 /* Unordered */ && nextLevel > 1) { result.style.setProperty('list-style-type', unorderedListStyles[(nextLevel - 1) % unorderedListStyles.length]); } return result; } function wrapIfNotBlockNode(nodes, checkFirst, checkLast) { if (nodes.length > 0 && (!checkFirst || !(0, isBlockElement_1.default)(nodes[0])) && (!checkLast || !(0, isBlockElement_1.default)(nodes[nodes.length]))) { nodes = [(0, wrap_1.default)(nodes)]; } return nodes; } function getChildrenAndUnwrap(node) { var result = (0, toArray_1.default)(node.childNodes); (0, unwrap_1.default)(node); return result; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/convertDecimalsToAlpha.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/convertDecimalsToAlpha.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var ALPHABET = { 0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G', 7: 'H', 8: 'I', 9: 'J', 10: 'K', 11: 'L', 12: 'M', 13: 'N', 14: 'O', 15: 'P', 16: 'Q', 17: 'R', 18: 'S', 19: 'T', 20: 'U', 21: 'V', 22: 'W', 23: 'X', 24: 'Y', 25: 'Z', }; /** * @internal * Convert decimal numbers into english alphabet letters * @param decimal The decimal number that needs to be converted * @param isLowerCase if true the roman value will appear in lower case * @returns */ function convertDecimalsToAlpha(decimal, isLowerCase) { var alpha = ''; while (decimal >= 0) { alpha = ALPHABET[decimal % 26] + alpha; decimal = Math.floor(decimal / 26) - 1; } return isLowerCase ? alpha.toLowerCase() : alpha; } exports.default = convertDecimalsToAlpha; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/convertDecimalsToRomans.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/convertDecimalsToRomans.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getObjectKeys_1 = __webpack_require__(/*! ../jsUtils/getObjectKeys */ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts"); var RomanValues = { M: 1000, CM: 900, D: 500, CD: 400, C: 100, XC: 90, L: 50, XL: 40, X: 10, IX: 9, V: 5, IV: 4, I: 1, }; /** * @internal * Convert decimal numbers into roman numbers * @param decimal The decimal number that needs to be converted * @param isLowerCase if true the roman value will appear in lower case * @returns */ function convertDecimalsToRoman(decimal, isLowerCase) { var romanValue = ''; for (var _i = 0, _a = (0, getObjectKeys_1.default)(RomanValues); _i < _a.length; _i++) { var i = _a[_i]; var timesRomanCharAppear = Math.floor(decimal / RomanValues[i]); decimal = decimal - timesRomanCharAppear * RomanValues[i]; romanValue = romanValue + i.repeat(timesRomanCharAppear); } return isLowerCase ? romanValue.toLocaleLowerCase() : romanValue; } exports.default = convertDecimalsToRoman; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/createVListFromRegion.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/createVListFromRegion.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var createElement_1 = __webpack_require__(/*! ../utils/createElement */ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts"); var getRootListNode_1 = __webpack_require__(/*! ./getRootListNode */ "./packages/roosterjs-editor-dom/lib/list/getRootListNode.ts"); var getSelectedBlockElementsInRegion_1 = __webpack_require__(/*! ../region/getSelectedBlockElementsInRegion */ "./packages/roosterjs-editor-dom/lib/region/getSelectedBlockElementsInRegion.ts"); var isNodeInRegion_1 = __webpack_require__(/*! ../region/isNodeInRegion */ "./packages/roosterjs-editor-dom/lib/region/isNodeInRegion.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var shouldSkipNode_1 = __webpack_require__(/*! ../utils/shouldSkipNode */ "./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts"); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); var VList_1 = __webpack_require__(/*! ./VList */ "./packages/roosterjs-editor-dom/lib/list/VList.ts"); var wrap_1 = __webpack_require__(/*! ../utils/wrap */ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts"); var getLeafSibling_1 = __webpack_require__(/*! ../utils/getLeafSibling */ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts"); var getListTypeFromNode_1 = __webpack_require__(/*! ./getListTypeFromNode */ "./packages/roosterjs-editor-dom/lib/list/getListTypeFromNode.ts"); var ListSelector = 'ol,ul'; /** * Create a VList object from the given region. * @param region The region to get VList from * @param includeSiblingLists True to also try get lists before and after the selection and merge them together, * false to only include the list for the selected blocks * @param startNode (Optional) When specified, try get VList which will contain this node. * If not specified, get VList from selection of this region */ function createVListFromRegion(region, includeSiblingLists, startNode) { if (!region) { return null; } var nodes = []; if (startNode) { var list = (0, getRootListNode_1.default)(region, ListSelector, startNode); if (list) { nodes.push(list); } } else { var blocks = (0, getSelectedBlockElementsInRegion_1.default)(region, undefined, true /* shouldApplyFormatToSpan */); blocks.forEach(function (block) { var list = (0, getRootListNode_1.default)(region, ListSelector, block.getStartNode()); if (list) { if (nodes[nodes.length - 1] != list) { nodes.push(list); } if (nodes.length == 1 && (0, safeInstanceOf_1.default)(list, 'HTMLOListElement') && list.start > 1) { // Do not include sibling lists if this list is not start from 1 includeSiblingLists = false; } } else { nodes.push(block.collapseToSingleElement()); } }); if (nodes.length == 0 && !region.rootNode.firstChild) { var newNode = (0, createElement_1.default)(12 /* EmptyLineFormatInSpan */, region.rootNode.ownerDocument); region.rootNode.appendChild(newNode); nodes.push(newNode); region.fullSelectionStart = new Position_1.default(newNode, 0 /* Begin */); region.fullSelectionEnd = new Position_1.default(newNode, -1 /* End */); } if (includeSiblingLists) { tryIncludeSiblingNode(region, nodes, false /*isNext*/); tryIncludeSiblingNode(region, nodes, true /*isNext*/); } nodes = nodes.filter(function (node) { return !(0, shouldSkipNode_1.default)(node, true /*ignoreSpace*/); }); } var vList = null; if (nodes.length > 0) { var firstNode = nodes.shift() || null; vList = (0, getListTypeFromNode_1.isListElement)(firstNode) ? new VList_1.default(firstNode) : firstNode ? createVListFromItemNode(firstNode) : null; if (vList) { nodes.forEach(function (node) { if ((0, getListTypeFromNode_1.isListElement)(node)) { vList.mergeVList(new VList_1.default(node)); } else { vList.appendItem(node, 0 /* None */); } }); } } return vList; } exports.default = createVListFromRegion; function tryIncludeSiblingNode(region, nodes, isNext) { var node = nodes[isNext ? nodes.length - 1 : 0]; node = (0, getLeafSibling_1.getLeafSibling)(region.rootNode, node, isNext, region.skipTags, true /*ignoreSpace*/); node = (0, getRootListNode_1.default)(region, ListSelector, node); if ((0, isNodeInRegion_1.default)(region, node) && (0, getListTypeFromNode_1.isListElement)(node)) { if (isNext) { if (!(0, safeInstanceOf_1.default)(node, 'HTMLOListElement') || node.start == 1) { // Only include sibling list when // 1. This is a unordered list, OR // 2. This list starts from 1 nodes.push(node); } } else { nodes.unshift(node); } } } function createVListFromItemNode(node) { // Wrap all child nodes under a single one, and put the new list under original root node // so that the list can carry over styles under the root node. var childNodes = (0, toArray_1.default)(node.childNodes); var nodeForItem = childNodes.length == 1 ? childNodes[0] : (0, wrap_1.default)(childNodes, 'SPAN'); // Create a temporary OL root element for this list. var listNode = node.ownerDocument.createElement('ol'); // Either OL or UL is ok here node.appendChild(listNode); // Create the VList and append items var vList = new VList_1.default(listNode); vList.appendItem(nodeForItem, 0 /* None */); return vList; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/getListTypeFromNode.ts": /*!***********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/getListTypeFromNode.ts ***! \***********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isListElement = void 0; var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); function getListTypeFromNode(node) { switch ((0, getTagOfNode_1.default)(node)) { case 'OL': return 1 /* Ordered */; case 'UL': return 2 /* Unordered */; default: return 0 /* None */; } } exports.default = getListTypeFromNode; /** * @internal * Check if the given DOM node is a list element (OL or UL) * @param node The node to check */ function isListElement(node) { return getListTypeFromNode(node) != 0 /* None */; } exports.isListElement = isListElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/getRootListNode.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/getRootListNode.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var findClosestElementAncestor_1 = __webpack_require__(/*! ../utils/findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts"); /** * @internal * Get Root list node from the given node within the given region * @param region Region to scope the search into * @param selector The selector to search * @param node The start node */ function getRootListNode(region, selector, node) { var list = region && (0, findClosestElementAncestor_1.default)(node, region.rootNode, selector); if (list) { var ancestor = void 0; while ((ancestor = (0, findClosestElementAncestor_1.default)(list.parentNode, region.rootNode, selector))) { list = ancestor; } } return list; } exports.default = getRootListNode; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/setBulletListMarkers.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/setBulletListMarkers.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); /** * @internal * Set the marker of a bullet list * @param li * @param listStyleType */ function setBulletListMarkers(li, listStyleType) { var marker = bulletListStyle[listStyleType]; var isDisc = listStyleType === 1 /* Disc */; li.style.listStyleType = isDisc ? marker : "\"" + marker + "\""; } exports.default = setBulletListMarkers; var bulletListStyle = (_a = {}, _a[1 /* Disc */] = 'disc', _a[3 /* Square */] = '∎ ', _a[2 /* Dash */] = '- ', _a[5 /* LongArrow */] = '➔ ', _a[8 /* DoubleLongArrow */] = '➔ ', _a[4 /* ShortArrow */] = '➢ ', _a[6 /* UnfilledArrow */] = '➪ ', _a[7 /* Hyphen */] = '— ', _a); /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/setListItemStyle.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/setListItemStyle.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var ContentTraverser_1 = __webpack_require__(/*! ../contentTraverser/ContentTraverser */ "./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts"); var findClosestElementAncestor_1 = __webpack_require__(/*! ../utils/findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); /** * Set the Style of a List Item provided, with the styles that the inline child elements have * If the child inline elements have different styles, it will not modify the styles of the list item * @param element the LI Element to set the styles * @param styles The styles that should be applied to the element. * @param isCssStyle True means the given styles are CSS style names, false means they are HTML attributes @default true */ function setListItemStyle(element, styles, isCssStyle) { if (isCssStyle === void 0) { isCssStyle = true; } var elementsStyles = getInlineChildElementsStyle(element, styles, isCssStyle); styles.forEach(function (styleName) { var styleValues = elementsStyles.map(function (style) { return style[styleName] !== undefined ? style[styleName] : ''; }); if (styleValues && (styleValues.length == 1 || new Set(styleValues).size == 1) && styleValues[0]) { if (isCssStyle) { element.style.setProperty(styleName, styleValues[0]); } else { element.setAttribute(styleName, styleValues[0]); } } }); } exports.default = setListItemStyle; function getInlineChildElementsStyle(element, styles, isCssStyle) { var _a, _b; var result = []; var contentTraverser = ContentTraverser_1.default.createBodyTraverser(element); var currentInlineElement = null; var _loop_1 = function () { currentInlineElement = contentTraverser.currentInlineElement; var currentNode = (currentInlineElement === null || currentInlineElement === void 0 ? void 0 : currentInlineElement.getContainerNode()) || null; var currentStyle = null; currentNode = currentNode ? (0, findClosestElementAncestor_1.default)(currentNode) : null; var _loop_2 = function () { var element_1 = currentNode; styles.forEach(function (styleName) { var styleValue = isCssStyle ? element_1.style.getPropertyValue(styleName) : element_1.getAttribute(styleName); if (!currentStyle) { currentStyle = {}; } if (styleValue && !currentStyle[styleName]) { currentStyle[styleName] = styleValue; } }); if (((_b = currentNode === null || currentNode === void 0 ? void 0 : currentNode.parentNode) === null || _b === void 0 ? void 0 : _b.childNodes.length) === 1) { currentNode = currentNode.parentNode; } else { currentNode = null; } }; // we should consider of when it is the single child node of element, the parentNode's style should add // such as the "i", "b", "span" node in
  • aa
  • while (currentNode && currentNode !== element && (0, safeInstanceOf_1.default)(currentNode, 'HTMLElement') && (result.length == 0 || (((_a = currentNode.textContent) === null || _a === void 0 ? void 0 : _a.trim().length) || 0) > 0)) { _loop_2(); } if (currentStyle) { result.push(currentStyle); } contentTraverser.getNextInlineElement(); }; while (contentTraverser.currentInlineElement != currentInlineElement) { _loop_1(); } return result; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/list/setNumberingListMarkers.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/list/setNumberingListMarkers.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); var convertDecimalsToAlpha_1 = __webpack_require__(/*! ./convertDecimalsToAlpha */ "./packages/roosterjs-editor-dom/lib/list/convertDecimalsToAlpha.ts"); var convertDecimalsToRomans_1 = __webpack_require__(/*! ./convertDecimalsToRomans */ "./packages/roosterjs-editor-dom/lib/list/convertDecimalsToRomans.ts"); var MarkerTypes; (function (MarkerTypes) { MarkerTypes[MarkerTypes["Decimal"] = 0] = "Decimal"; MarkerTypes[MarkerTypes["Roman"] = 1] = "Roman"; MarkerTypes[MarkerTypes["Alpha"] = 2] = "Alpha"; })(MarkerTypes || (MarkerTypes = {})); /** * @internal * Set marker style of a numbering list * @param listStyleType * @param li */ function setNumberingListMarkers(li, listStyleType, level) { var _a = numberingListStyle[listStyleType], markerSeparator = _a.markerSeparator, markerSecondSeparator = _a.markerSecondSeparator, markerType = _a.markerType, lowerCase = _a.lowerCase; var markerNumber = level.toString(); if (markerType === MarkerTypes.Roman) { markerNumber = (0, convertDecimalsToRomans_1.default)(level, lowerCase); } else if (markerType === MarkerTypes.Alpha) { markerNumber = (0, convertDecimalsToAlpha_1.default)(level - 1, lowerCase); } var marker = markerSecondSeparator ? markerSecondSeparator + markerNumber + markerSeparator : markerNumber + markerSeparator; li.style.listStyleType = "\"" + marker + "\""; } exports.default = setNumberingListMarkers; var numberingListStyle = (_a = {}, _a[1 /* Decimal */] = { markerType: MarkerTypes.Decimal, markerSeparator: '. ', }, _a[2 /* DecimalDash */] = { markerType: MarkerTypes.Decimal, markerSeparator: '- ', }, _a[3 /* DecimalParenthesis */] = { markerType: MarkerTypes.Decimal, markerSeparator: ') ', }, _a[4 /* DecimalDoubleParenthesis */] = { markerType: MarkerTypes.Decimal, markerSeparator: ') ', markerSecondSeparator: '(', }, _a[5 /* LowerAlpha */] = { markerType: MarkerTypes.Alpha, markerSeparator: '. ', lowerCase: true, }, _a[8 /* LowerAlphaDash */] = { markerType: MarkerTypes.Alpha, markerSeparator: '- ', lowerCase: true, }, _a[6 /* LowerAlphaParenthesis */] = { markerType: MarkerTypes.Alpha, markerSeparator: ') ', lowerCase: true, }, _a[7 /* LowerAlphaDoubleParenthesis */] = { markerType: MarkerTypes.Alpha, markerSeparator: ') ', markerSecondSeparator: '(', lowerCase: true, }, _a[9 /* UpperAlpha */] = { markerType: MarkerTypes.Alpha, markerSeparator: '. ', }, _a[12 /* UpperAlphaDash */] = { markerType: MarkerTypes.Alpha, markerSeparator: '- ', }, _a[10 /* UpperAlphaParenthesis */] = { markerType: MarkerTypes.Alpha, markerSeparator: ') ', }, _a[11 /* UpperAlphaDoubleParenthesis */] = { markerType: MarkerTypes.Alpha, markerSeparator: ') ', markerSecondSeparator: '(', }, _a[13 /* LowerRoman */] = { markerType: MarkerTypes.Roman, markerSeparator: '. ', lowerCase: true, }, _a[16 /* LowerRomanDash */] = { markerType: MarkerTypes.Roman, markerSeparator: '- ', lowerCase: true, }, _a[14 /* LowerRomanParenthesis */] = { markerType: MarkerTypes.Roman, markerSeparator: ') ', lowerCase: true, }, _a[15 /* LowerRomanDoubleParenthesis */] = { markerType: MarkerTypes.Roman, markerSeparator: ') ', markerSecondSeparator: '(', lowerCase: true, }, _a[17 /* UpperRoman */] = { markerType: MarkerTypes.Roman, markerSeparator: '. ', }, _a[20 /* UpperRomanDash */] = { markerType: MarkerTypes.Roman, markerSeparator: '- ', }, _a[18 /* UpperRomanParenthesis */] = { markerType: MarkerTypes.Roman, markerSeparator: ') ', }, _a[19 /* UpperRomanDoubleParenthesis */] = { markerType: MarkerTypes.Roman, markerSeparator: ') ', markerSecondSeparator: '(', }, _a); /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/metadata/definitionCreators.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/metadata/definitionCreators.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createObjectDefinition = exports.createArrayDefinition = exports.createStringDefinition = exports.createBooleanDefinition = exports.createNumberDefinition = void 0; /** * Create a number definition * @param isOptional Whether this property is optional * @param value Optional value of the number * @param minValue Optional minimum value * @param maxValue Optional maximum value * @param allowNull Allow the property to be null * @returns The number definition object */ function createNumberDefinition(isOptional, value, minValue, maxValue, allowNull) { return { type: 1 /* Number */, isOptional: isOptional, value: value, maxValue: maxValue, minValue: minValue, allowNull: allowNull, }; } exports.createNumberDefinition = createNumberDefinition; /** * Create a boolean definition * @param isOptional Whether this property is optional * @param value Optional expected boolean value * @param allowNull Allow the property to be null * @returns The boolean definition object */ function createBooleanDefinition(isOptional, value, allowNull) { return { type: 0 /* Boolean */, isOptional: isOptional, value: value, allowNull: allowNull, }; } exports.createBooleanDefinition = createBooleanDefinition; /** * Create a string definition * @param isOptional Whether this property is optional * @param value Optional expected string value * @param allowNull Allow the property to be null * @returns The string definition object */ function createStringDefinition(isOptional, value, allowNull) { return { type: 2 /* String */, isOptional: isOptional, value: value, allowNull: allowNull, }; } exports.createStringDefinition = createStringDefinition; /** * Create an array definition * @param itemDef Definition of each item of the related array * @param isOptional Whether this property is optional * @param allowNull Allow the property to be null * @returns The array definition object */ function createArrayDefinition(itemDef, isOptional, minLength, maxLength, allowNull) { return { type: 3 /* Array */, isOptional: isOptional, itemDef: itemDef, minLength: minLength, maxLength: maxLength, allowNull: allowNull, }; } exports.createArrayDefinition = createArrayDefinition; /** * Create an object definition * @param propertyDef Definition of each property of the related object * @param isOptional Whether this property is optional * @param allowNull Allow the property to be null * @returns The object definition object */ function createObjectDefinition(propertyDef, isOptional, allowNull) { return { type: 4 /* Object */, isOptional: isOptional, propertyDef: propertyDef, allowNull: allowNull, }; } exports.createObjectDefinition = createObjectDefinition; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/metadata/metadata.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/metadata/metadata.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.removeMetadata = exports.setMetadata = exports.getMetadata = void 0; var validate_1 = __webpack_require__(/*! ./validate */ "./packages/roosterjs-editor-dom/lib/metadata/validate.ts"); var MetadataDataSetName = 'editingInfo'; /** * Get metadata object from an HTML element * @param element The HTML element to get metadata object from * @param definition The type definition of this metadata used for validate this metadata object. * If not specified, no validation will be performed and always return whatever we get from the element * @param defaultValue The default value to return if the retrieved object cannot pass the validation, * or there is no metadata object at all * @returns The strong-type metadata object if it can be validated, or null */ function getMetadata(element, definition, defaultValue) { var str = element.dataset[MetadataDataSetName]; var obj; try { obj = str ? JSON.parse(str) : null; } catch (_a) { } if (typeof obj !== 'undefined') { if (!definition) { return obj; } else if ((0, validate_1.default)(obj, definition)) { return obj; } } if (defaultValue) { return defaultValue; } else { return null; } } exports.getMetadata = getMetadata; /** * Set metadata object into an HTML element * @param element The HTML element to set metadata object to * @param metadata The metadata object to set * @param def An optional type definition object used for validate this metadata object. * If not specified, metadata will be set without validation * @returns True if metadata is set, otherwise false */ function setMetadata(element, metadata, def) { if (!def || (0, validate_1.default)(metadata, def)) { element.dataset[MetadataDataSetName] = JSON.stringify(metadata); return true; } else { return false; } } exports.setMetadata = setMetadata; /** * Remove metadata from the given element if any * @param element The element to remove metadata from */ function removeMetadata(element) { delete element.dataset[MetadataDataSetName]; } exports.removeMetadata = removeMetadata; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/metadata/validate.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/metadata/validate.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getObjectKeys_1 = __webpack_require__(/*! ../jsUtils/getObjectKeys */ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts"); /** * Validate the given object with a type definition object * @param input The object to validate * @param def The type definition object used for validation * @returns True if the object passed the validation, otherwise false */ function validate(input, def) { var result = false; if ((def.isOptional && typeof input === 'undefined') || (def.allowNull && input === null)) { result = true; } else if ((!def.isOptional && typeof input === 'undefined') || (!def.allowNull && input === null)) { return false; } else { switch (def.type) { case 2 /* String */: result = typeof input === 'string' && (typeof def.value === 'undefined' || input === def.value); break; case 1 /* Number */: result = typeof input === 'number' && (typeof def.value === 'undefined' || areSameNumbers(def.value, input)) && (typeof def.minValue === 'undefined' || input >= def.minValue) && (typeof def.maxValue === 'undefined' || input <= def.maxValue); break; case 0 /* Boolean */: result = typeof input === 'boolean' && (typeof def.value === 'undefined' || input === def.value); break; case 3 /* Array */: result = Array.isArray(input) && (typeof def.minLength === 'undefined' || input.length >= def.minLength) && (typeof def.maxLength === 'undefined' || input.length <= def.maxLength) && input.every(function (x) { return validate(x, def.itemDef); }); break; case 4 /* Object */: result = typeof input === 'object' && (0, getObjectKeys_1.default)(def.propertyDef).every(function (x) { return validate(input[x], def.propertyDef[x]); }); break; case 5 /* Customize */: result = def.validator(input); break; } } return result; } exports.default = validate; function areSameNumbers(n1, n2) { return Math.abs(n1 - n2) < 1e-3; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/region/collapseNodesInRegion.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/region/collapseNodesInRegion.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var collapseNodes_1 = __webpack_require__(/*! ../utils/collapseNodes */ "./packages/roosterjs-editor-dom/lib/utils/collapseNodes.ts"); var isNodeInRegion_1 = __webpack_require__(/*! ./isNodeInRegion */ "./packages/roosterjs-editor-dom/lib/region/isNodeInRegion.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); /** * Collapse nodes within this region to their common ancestor node under this region * @param region The region to collapse nodes in. * @param nodesOrBlockElements Nodes or block elements to collapse. When take BlockElement[] as input, * start node of the first BlockElement and end node of the last BlockElement will be used as the nodes. * All nodes not contained by the given region will be ignored. */ function collapseNodesInRegion(region, nodesOrBlockElements) { if (!nodesOrBlockElements || nodesOrBlockElements.length == 0) { return []; } var nodes = (0, safeInstanceOf_1.default)(nodesOrBlockElements[0], 'Node') ? nodesOrBlockElements : [ nodesOrBlockElements[0].getStartNode(), nodesOrBlockElements[nodesOrBlockElements.length - 1].getEndNode(), ]; nodes = nodes && nodes.filter(function (node) { return (0, isNodeInRegion_1.default)(region, node); }); var firstNode = nodes[0]; var lastNode = nodes[nodes.length - 1]; if ((0, isNodeInRegion_1.default)(region, firstNode) && (0, isNodeInRegion_1.default)(region, lastNode)) { return (0, collapseNodes_1.default)(region.rootNode, firstNode, lastNode, true /*canSplitParent*/); } else { return []; } } exports.default = collapseNodesInRegion; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/region/getRegionsFromRange.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/region/getRegionsFromRange.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.getRegionCreator = void 0; var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var findClosestElementAncestor_1 = __webpack_require__(/*! ../utils/findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var queryElements_1 = __webpack_require__(/*! ../utils/queryElements */ "./packages/roosterjs-editor-dom/lib/utils/queryElements.ts"); var getLeafSibling_1 = __webpack_require__(/*! ../utils/getLeafSibling */ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts"); var regionTypeData = (_a = {}, _a[0 /* Table */] = { skipTags: ['TABLE'], outerSelector: 'table', innerSelector: 'td,th', }, _a); /** * Get regions impacted by the given range under the root node * @param root Root node to get regions from * @param range A selection range. Regions will be created according to this range. Each region will be * fully or partially covered by this range. * @param type Type of region. Currently we only support TABLE region. */ function getRegionsFromRange(root, range, type) { var regions = []; if (root && range) { var _a = regionTypeData[type], innerSelector = _a.innerSelector, skipTags = _a.skipTags; var boundaryTree = buildBoundaryTree(root, range, type); var start = (0, findClosestElementAncestor_1.default)(range.startContainer, root, innerSelector) || root; var end = (0, findClosestElementAncestor_1.default)(range.endContainer, root, innerSelector) || root; var creator = getRegionCreator(range, skipTags); regions = iterateNodes(creator, boundaryTree, start, end)[0]; } return regions.filter(function (r) { return !!r; }); } exports.default = getRegionsFromRange; /** * @internal export for test only */ function getRegionCreator(fullRange, skipTags) { var fullSelectionStart = Position_1.default.getStart(fullRange).normalize(); var fullSelectionEnd = Position_1.default.getEnd(fullRange).normalize(); return function (rootNode, nodeBefore, nodeAfter) { return areNodesValid(rootNode, nodeBefore, nodeAfter, skipTags) ? { rootNode: rootNode, nodeBefore: nodeBefore, nodeAfter: nodeAfter, skipTags: skipTags, fullSelectionStart: fullSelectionStart, fullSelectionEnd: fullSelectionEnd, } : null; }; } exports.getRegionCreator = getRegionCreator; /** * Step 1: Build boundary tree * @param root Root node of the whole scope, normally this will be the root of editable scope * @param range Existing selected full range * @param type Type of region to create */ function buildBoundaryTree(root, range, type) { var allBoundaries = [{ innerNode: root, children: [] }]; var _a = regionTypeData[type], outerSelector = _a.outerSelector, innerSelector = _a.innerSelector; var inSelectionOuterNode = (0, queryElements_1.default)(root, outerSelector, null /*callback*/, 2 /* InSelection */, range); // According to https://www.w3.org/TR/selectors-api/#queryselectorall, the result of querySelectorAll // is in document order, which is what we expect. So we don't need to sort the result here. (0, queryElements_1.default)(root, innerSelector, function (thisInnerNode) { var thisOuterNode = (0, findClosestElementAncestor_1.default)(thisInnerNode, root, outerSelector); if (thisOuterNode && inSelectionOuterNode.indexOf(thisOuterNode) < 0) { var boundary = { innerNode: thisInnerNode, children: [] }; for (var i = allBoundaries.length - 1; i >= 0; i--) { var _a = allBoundaries[i], innerNode = _a.innerNode, children = _a.children; if ((0, contains_1.default)(innerNode, thisOuterNode)) { var child = children.filter(function (c) { return c.outerNode == thisOuterNode; })[0]; if (!child) { child = { outerNode: thisOuterNode, boundaries: [] }; children.push(child); } child.boundaries.push(boundary); break; } } allBoundaries.push(boundary); } }, 1 /* OnSelection */, range); return allBoundaries[0]; } /** * Step 2: Recursively iterate all boundaries and create regions * @param creator A region creator function to help create region * @param boundary Current root boundary * @param start A node where full range start from. This may not be the direct node container of range.startContainer. * It is the nearest ancestor which satisfies the InnerSelector of the given region type * @param end A node where full range end from. This may not be the direct node container of range.endContainer. * It is the nearest ancestor which satisfies the InnerSelector of the given region type * @param started Whether we have already hit the start node */ function iterateNodes(creator, boundary, start, end, started) { var _a; started = started || boundary.innerNode == start; var ended = false; var children = boundary.children, innerNode = boundary.innerNode; var regions = []; if (children.length == 0) { var region = creator(innerNode); if (region) { regions.push(region); } } else { // Need to run one more time to add region after all children for (var i = 0; i <= children.length && !ended; i++) { var _b = children[i] || {}, outerNode = _b.outerNode, boundaries = _b.boundaries; var previousOuterNode = (_a = children[i - 1]) === null || _a === void 0 ? void 0 : _a.outerNode; if (started) { var region = creator(innerNode, previousOuterNode, outerNode); if (region) { regions.push(region); } } boundaries === null || boundaries === void 0 ? void 0 : boundaries.forEach(function (child) { var _a; var newRegions; _a = iterateNodes(creator, child, start, end, started), newRegions = _a[0], started = _a[1], ended = _a[2]; regions = regions.concat(newRegions); }); } } return [regions, started, ended || innerNode == end]; } /** * Check if the given nodes combination is valid to create a region. * A combination is valid when: * 1. Root node is not null and is not empty. And * 2. For nodeBefore and nodeAfter, each of them should be either null or contained by root node. And * 3. If none of nodeBefore and nodeAfter is null, the should not contain each other, and there should be * node between them. * @param root Root node of region * @param nodeBefore The boundary node before the region under root * @param nodeAfter The boundary node after the region under root * @param skipTags Tags to skip */ function areNodesValid(root, nodeBefore, nodeAfter, skipTags) { if (!root) { return false; } else { var firstNodeOfRegion = nodeBefore && (0, getLeafSibling_1.getNextLeafSibling)(root, nodeBefore, skipTags); var lastNodeOfRegion = nodeAfter && (0, getLeafSibling_1.getPreviousLeafSibling)(root, nodeAfter, skipTags); var firstNodeValid = !nodeBefore || ((0, contains_1.default)(root, nodeBefore) && (0, contains_1.default)(root, firstNodeOfRegion)); var lastNodeValid = !nodeAfter || ((0, contains_1.default)(root, nodeAfter) && (0, contains_1.default)(root, lastNodeOfRegion)); var bothValid = !nodeBefore || !nodeAfter || (!(0, contains_1.default)(nodeBefore, nodeAfter, true /*treatSameAsContain*/) && !(0, contains_1.default)(nodeBefore, lastNodeOfRegion, true /*treatSameAsContain*/) && !(0, contains_1.default)(nodeAfter, nodeBefore, true /*treatSameAsContain*/) && !(0, contains_1.default)(nodeAfter, firstNodeOfRegion, true /*treatSameAsContain*/)); return firstNodeValid && lastNodeValid && bothValid; } } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/region/getSelectedBlockElementsInRegion.ts": /*!**************************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/region/getSelectedBlockElementsInRegion.ts ***! \**************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var ContentTraverser_1 = __webpack_require__(/*! ../contentTraverser/ContentTraverser */ "./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts"); var createElement_1 = __webpack_require__(/*! ../utils/createElement */ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts"); var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts"); var getSelectionRangeInRegion_1 = __webpack_require__(/*! ./getSelectionRangeInRegion */ "./packages/roosterjs-editor-dom/lib/region/getSelectionRangeInRegion.ts"); var shouldSkipNode_1 = __webpack_require__(/*! ../utils/shouldSkipNode */ "./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts"); /** * Get all block elements covered by the selection under this region * @param regionBase The region to get block elements from * @param createBlockIfEmpty When set to true, a new empty block element will be created if there is not * any blocks in the region. Default value is false */ function getSelectedBlockElementsInRegion(regionBase, createBlockIfEmpty, shouldApplyFormatToSpan) { var range = (0, getSelectionRangeInRegion_1.default)(regionBase); var blocks = []; if (range) { var rootNode = regionBase.rootNode, skipTags = regionBase.skipTags; var traverser = ContentTraverser_1.default.createSelectionTraverser(rootNode, range, skipTags); for (var block = traverser === null || traverser === void 0 ? void 0 : traverser.currentBlockElement; !!block; block = traverser.getNextBlockElement()) { blocks.push(block); } // Remove meaningless nodes blocks = blocks.filter(function (block) { var _a; var startNode = block.getStartNode(); var endNode = block.getEndNode(); if (startNode == endNode && (0, shouldSkipNode_1.default)(startNode, true /*ignoreSpace*/)) { (_a = startNode.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(startNode); return false; } else { return true; } }); } if (blocks.length == 0 && regionBase && !regionBase.rootNode.firstChild && createBlockIfEmpty) { var newNode = (0, createElement_1.default)(shouldApplyFormatToSpan ? 12 /* EmptyLineFormatInSpan */ : 1 /* EmptyLine */, regionBase.rootNode.ownerDocument); regionBase.rootNode.appendChild(newNode); var block = (0, getBlockElementAtNode_1.default)(regionBase.rootNode, newNode); if (block) { blocks.push(block); } } return blocks; } exports.default = getSelectedBlockElementsInRegion; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/region/getSelectionRangeInRegion.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/region/getSelectionRangeInRegion.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var createRange_1 = __webpack_require__(/*! ../selection/createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts"); var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var getLeafSibling_1 = __webpack_require__(/*! ../utils/getLeafSibling */ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts"); /** * Get the selection range in the given region. * The original range can cover multiple regions, this function will narrow the original selection * of a region into current region * @param regionBase The region to get range from */ function getSelectionRangeInRegion(regionBase) { if (!regionBase) { return null; } var nodeBefore = regionBase.nodeBefore, nodeAfter = regionBase.nodeAfter, rootNode = regionBase.rootNode, skipTags = regionBase.skipTags; var startNode = nodeBefore ? (0, getLeafSibling_1.getNextLeafSibling)(regionBase.rootNode, nodeBefore, regionBase.skipTags) : rootNode.firstChild; var endNode = nodeAfter ? (0, getLeafSibling_1.getPreviousLeafSibling)(rootNode, nodeAfter, skipTags) : rootNode.lastChild; var regionRange = startNode && endNode && (0, createRange_1.default)(startNode, endNode); if (!isRegion(regionBase)) { return regionRange; } else if (regionRange) { var regionStart = Position_1.default.getStart(regionRange).normalize(); var regionEnd = Position_1.default.getEnd(regionRange).normalize(); var fullSelectionEnd = regionBase.fullSelectionEnd, fullSelectionStart = regionBase.fullSelectionStart; if (!fullSelectionStart.isAfter(regionEnd) && !regionStart.isAfter(fullSelectionEnd)) { var start = fullSelectionStart.isAfter(regionStart) ? fullSelectionStart : regionStart; var end = fullSelectionEnd.isAfter(regionEnd) ? regionEnd : fullSelectionEnd; return (0, createRange_1.default)(start, end); } } return null; } exports.default = getSelectionRangeInRegion; function isRegion(regionBase) { var region = regionBase; return !!region.fullSelectionEnd && !!region.fullSelectionStart; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/region/isNodeInRegion.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/region/isNodeInRegion.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); /** * Check if a given node is contained by the given region * @param region The region to check from * @param node The node or block element to check */ function isNodeInRegion(region, node) { return !!(region && (0, contains_1.default)(region.rootNode, node) && (!region.nodeBefore || region.nodeBefore.compareDocumentPosition(node) == 4 /* Following */) && (!region.nodeAfter || region.nodeAfter.compareDocumentPosition(node) == 2 /* Preceding */)); } exports.default = isNodeInRegion; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/region/mergeBlocksInRegion.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/region/mergeBlocksInRegion.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); var changeElementTag_1 = __webpack_require__(/*! ../utils/changeElementTag */ "./packages/roosterjs-editor-dom/lib/utils/changeElementTag.ts"); var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts"); var getPredefinedCssForElement_1 = __webpack_require__(/*! ../htmlSanitizer/getPredefinedCssForElement */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/getPredefinedCssForElement.ts"); var getStyles_1 = __webpack_require__(/*! ../style/getStyles */ "./packages/roosterjs-editor-dom/lib/style/getStyles.ts"); var isNodeInRegion_1 = __webpack_require__(/*! ./isNodeInRegion */ "./packages/roosterjs-editor-dom/lib/region/isNodeInRegion.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var setStyles_1 = __webpack_require__(/*! ../style/setStyles */ "./packages/roosterjs-editor-dom/lib/style/setStyles.ts"); var collapseNodes_1 = __webpack_require__(/*! ../utils/collapseNodes */ "./packages/roosterjs-editor-dom/lib/utils/collapseNodes.ts"); /** * Merge a BlockElement of given node after another node * @param region Region to operate in * @param refNode The node to merge after * @param targetNode The node of target block element */ function mergeBlocksInRegion(region, refNode, targetNode) { var _a, _b, _c; var block; if (!(0, isNodeInRegion_1.default)(region, refNode) || !(0, isNodeInRegion_1.default)(region, targetNode) || !(block = (0, getBlockElementAtNode_1.default)(region.rootNode, targetNode)) || block.contains(refNode)) { return; } var blockRoot = block.collapseToSingleElement(); var commonContainer = (0, collapseNodes_1.collapse)(region.rootNode, blockRoot, refNode, false /*isStart*/, true /*canSplitParent*/); // Copy styles of parent nodes into blockRoot for (var node = blockRoot; (0, contains_1.default)(commonContainer, node);) { var parent_1 = node.parentNode; if ((0, safeInstanceOf_1.default)(parent_1, 'HTMLElement')) { var styles = __assign(__assign(__assign({}, ((0, getPredefinedCssForElement_1.default)(parent_1) || {})), (0, getStyles_1.default)(parent_1)), (0, getStyles_1.default)(blockRoot)); (0, setStyles_1.default)(blockRoot, styles); } node = parent_1; } var nodeToRemove = null; var nodeToMerge = blockRoot.childNodes.length == 1 && blockRoot.attributes.length == 0 ? blockRoot.firstChild : (0, changeElementTag_1.default)(blockRoot, 'SPAN'); // Remove empty node for (var node = nodeToMerge; (0, contains_1.default)(commonContainer, node) && ((_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.childNodes.length) == 1; node = node.parentNode) { // If the only child is the one which is about to be removed, this node should also be removed nodeToRemove = node.parentNode; } // Finally, merge blocks, and remove empty nodes (_b = refNode.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(nodeToMerge, refNode.nextSibling); (_c = nodeToRemove === null || nodeToRemove === void 0 ? void 0 : nodeToRemove.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(nodeToRemove); } exports.default = mergeBlocksInRegion; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/selection/Position.ts": /*!*****************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/selection/Position.ts ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var findClosestElementAncestor_1 = __webpack_require__(/*! ../utils/findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts"); var isNodeAfter_1 = __webpack_require__(/*! ../utils/isNodeAfter */ "./packages/roosterjs-editor-dom/lib/utils/isNodeAfter.ts"); /** * Represent a position in DOM tree by the node and its offset index */ var Position = /** @class */ (function () { function Position(nodeOrPosition, offsetOrPosType, isFromEndOfRange) { if (offsetOrPosType === void 0) { offsetOrPosType = 0; } this.isFromEndOfRange = isFromEndOfRange; if (nodeOrPosition.node) { this.node = nodeOrPosition.node; offsetOrPosType = nodeOrPosition.offset; } else { this.node = nodeOrPosition; } switch (offsetOrPosType) { case -2 /* Before */: this.offset = getIndexOfNode(this.node); this.node = this.node.parentNode; // TODO: how to handle parentNode is null? this.isAtEnd = false; break; case -3 /* After */: this.offset = getIndexOfNode(this.node) + 1; this.isAtEnd = !this.node.nextSibling; this.node = this.node.parentNode; // TODO: how to handle parentNode is null? break; case -1 /* End */: this.offset = getEndOffset(this.node); this.isAtEnd = true; break; default: var endOffset = getEndOffset(this.node); this.offset = Math.max(0, Math.min(offsetOrPosType, endOffset)); this.isAtEnd = offsetOrPosType > 0 && offsetOrPosType >= endOffset; break; } this.element = (0, findClosestElementAncestor_1.default)(this.node); // TODO: how to handle parent element is null? } /** * Normalize this position to the leaf node, return the normalize result. * If current position is already using leaf node, return this position object itself */ Position.prototype.normalize = function () { if (this.node.nodeType == 3 /* Text */ || !this.node.firstChild) { return this; } var node = this.node; var newOffset = this.isAtEnd ? -1 /* End */ : this.offset; while (node.nodeType == 1 /* Element */ || node.nodeType == 11 /* DocumentFragment */) { var nextNode = this.isFromEndOfRange ? newOffset == -1 /* End */ ? node.lastChild : node.childNodes[newOffset - 1] : newOffset == 0 /* Begin */ ? node.firstChild : newOffset == -1 /* End */ ? node.lastChild : node.childNodes[newOffset]; if (nextNode) { node = nextNode; newOffset = this.isAtEnd || this.isFromEndOfRange ? -1 /* End */ : 0 /* Begin */; } else { break; } } return new Position(node, newOffset, this.isFromEndOfRange); }; /** * Check if this position is equal to the given position * @param position The position to check */ Position.prototype.equalTo = function (position) { return (position && (this == position || (this.node == position.node && this.offset == position.offset && this.isAtEnd == position.isAtEnd))); }; /** * Checks if this position is after the given position */ Position.prototype.isAfter = function (position) { return this.node == position.node ? (this.isAtEnd && !position.isAtEnd) || this.offset > position.offset : (0, isNodeAfter_1.default)(this.node, position.node); }; /** * Move this position with offset, returns a new position with a valid offset in the same node * @param offset Offset to move with */ Position.prototype.move = function (offset) { return new Position(this.node, Math.max(this.offset + offset, 0)); }; /** * Get start position of the given Range * @param range The range to get position from */ Position.getStart = function (range) { return new Position(range.startContainer, range.startOffset); }; /** * Get end position of the given Range * @param range The range to get position from */ Position.getEnd = function (range) { // For collapsed range, always return the same value of start container to make sure // end position is not before start position return range.collapsed ? Position.getStart(range) : new Position(range.endContainer, range.endOffset, true /*isFromEndOfRange*/); }; return Position; }()); exports.default = Position; function getIndexOfNode(node) { var i = 0; while ((node = (node === null || node === void 0 ? void 0 : node.previousSibling) || null)) { i++; } return i; } function getEndOffset(node) { var _a; if (node.nodeType == 3 /* Text */) { return ((_a = node.nodeValue) === null || _a === void 0 ? void 0 : _a.length) || 0; } else if (node.nodeType == 1 /* Element */ || node.nodeType == 11 /* DocumentFragment */) { return node.childNodes.length; } else { return 1; } } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/selection/addRangeToSelection.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/selection/addRangeToSelection.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Browser_1 = __webpack_require__(/*! ../utils/Browser */ "./packages/roosterjs-editor-dom/lib/utils/Browser.ts"); /** * Add the given range into selection of the given document * @param range The range to select * @param skipSameRange When set to true, do nothing if the given range is the same with current selection, * otherwise it will always remove current selection range and set to the given one. * This parameter is always treat as true in Edge to avoid some weird runtime exception. */ function addRangeToSelection(range, skipSameRange) { var _a, _b, _c; var selection = (_c = (_b = (_a = range === null || range === void 0 ? void 0 : range.commonAncestorContainer) === null || _a === void 0 ? void 0 : _a.ownerDocument) === null || _b === void 0 ? void 0 : _b.defaultView) === null || _c === void 0 ? void 0 : _c.getSelection(); if (selection) { var needAddRange = true; if (selection.rangeCount > 0) { // Workaround IE exception 800a025e try { var currentRange = null; // Do not remove/add range if current selection is the same with target range // Without this check, execCommand() may fail in Edge since we changed the selection if ((skipSameRange || Browser_1.Browser.isEdge) && (currentRange = selection.rangeCount == 1 ? selection.getRangeAt(0) : null) && currentRange.startContainer == range.startContainer && currentRange.startOffset == range.startOffset && currentRange.endContainer == range.endContainer && currentRange.endOffset == range.endOffset) { needAddRange = false; } else { selection.removeAllRanges(); } } catch (e) { } } if (needAddRange) { selection.addRange(range); } } } exports.default = addRangeToSelection; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/selection/createRange.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var isVoidHtmlElement_1 = __webpack_require__(/*! ../utils/isVoidHtmlElement */ "./packages/roosterjs-editor-dom/lib/utils/isVoidHtmlElement.ts"); var Position_1 = __webpack_require__(/*! ./Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); function createRange(arg1, arg2, arg3, arg4) { var _a; var start = null; var end = null; if (isNodePosition(arg1)) { // function createRange(startPosition: NodePosition, endPosition?: NodePosition): Range; start = arg1; end = isNodePosition(arg2) ? arg2 : null; } else if ((0, safeInstanceOf_1.default)(arg1, 'Node')) { if (Array.isArray(arg2)) { // function createRange(rootNode: Node, startPath: number[], endPath?: number[]): Range; start = getPositionFromPath(arg1, arg2); end = Array.isArray(arg3) ? getPositionFromPath(arg1, arg3) : null; } else if (typeof arg2 == 'number') { // function createRange(node: Node, offset: number | PositionType): Range; // function createRange(startNode: Node, startOffset: number | PositionType, endNode: Node, endOffset: number | PositionType): Range; start = new Position_1.default(arg1, arg2); end = (0, safeInstanceOf_1.default)(arg3, 'Node') ? new Position_1.default(arg3, arg4) : null; } else if ((0, safeInstanceOf_1.default)(arg2, 'Node') || !arg2) { // function createRange(startNode: Node, endNode?: Node): Range; start = new Position_1.default(arg1, -2 /* Before */); end = new Position_1.default(arg2 || arg1, -3 /* After */); } } if ((_a = start === null || start === void 0 ? void 0 : start.node) === null || _a === void 0 ? void 0 : _a.ownerDocument) { var range = start.node.ownerDocument.createRange(); start = getFocusablePosition(start); end = getFocusablePosition(end || start); range.setStart(start.node, start.offset); range.setEnd(end.node, end.offset); return range; } else { return null; } } exports.default = createRange; /** * Convert to focusable position * If current node is a void element, we need to move up one level to put cursor outside void element */ function getFocusablePosition(position) { return position.node.nodeType == 1 /* Element */ && (0, isVoidHtmlElement_1.default)(position.node) ? new Position_1.default(position.node, position.isAtEnd ? -3 /* After */ : -2 /* Before */) : position; } function isNodePosition(arg) { return arg && arg.node; } function getPositionFromPath(node, path) { if (!node || !path) { return null; } // Iterate with a for loop to avoid mutating the passed in element path stack // or needing to copy it. var offset = 0; for (var i = 0; i < path.length; i++) { offset = path[i]; if (i < path.length - 1 && node && node.nodeType == 1 /* Element */ && node.childNodes.length > offset) { node = node.childNodes[offset]; } else { break; } } return new Position_1.default(node, offset); } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/selection/getHtmlWithSelectionPath.ts": /*!*********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/selection/getHtmlWithSelectionPath.ts ***! \*********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getInnerHTML_1 = __webpack_require__(/*! ../utils/getInnerHTML */ "./packages/roosterjs-editor-dom/lib/utils/getInnerHTML.ts"); var getSelectionPath_1 = __webpack_require__(/*! ./getSelectionPath */ "./packages/roosterjs-editor-dom/lib/selection/getSelectionPath.ts"); /** * Get inner Html of a root node with a selection path which can be used for restore selection. * The result string can be used by setHtmlWithSelectionPath() to restore the HTML and selection. * @param rootNode Root node to get inner Html from * @param range The range of selection. If pass null, no selection path will be added * @returns Inner HTML of the root node, followed by HTML comment contains selection path if the given range is valid */ function getHtmlWithSelectionPath(rootNode, range) { if (!rootNode) { return ''; } var content = (0, getInnerHTML_1.default)(rootNode); var selectionPath = range && (0, getSelectionPath_1.default)(rootNode, range); return selectionPath ? content + "" : content; } exports.default = getHtmlWithSelectionPath; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/selection/getPositionRect.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/selection/getPositionRect.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var createElement_1 = __webpack_require__(/*! ../utils/createElement */ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts"); var createRange_1 = __webpack_require__(/*! ./createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts"); var normalizeRect_1 = __webpack_require__(/*! ../utils/normalizeRect */ "./packages/roosterjs-editor-dom/lib/utils/normalizeRect.ts"); /** * Get bounding rect of this position * @param position The position to get rect from */ function getPositionRect(position) { var _a; if (!position) { return null; } var range = (0, createRange_1.default)(position); // 1) try to get rect using range.getBoundingClientRect() var rect = range.getBoundingClientRect && (0, normalizeRect_1.default)(range.getBoundingClientRect()); if (rect) { return rect; } // 2) try to get rect using range.getClientRects position = position.normalize(); var rects = range.getClientRects && range.getClientRects(); rect = rects && rects.length == 1 ? (0, normalizeRect_1.default)(rects[0]) : null; if (rect) { return rect; } // 3) if node is text node, try inserting a SPAN and get the rect of SPAN for others if (position.node.nodeType == 3 /* Text */ && position.node.ownerDocument) { var span = (0, createElement_1.default)({ tag: 'span', children: ['\u200b'] }, position.node.ownerDocument); range = (0, createRange_1.default)(position); range.insertNode(span); rect = span.getBoundingClientRect && (0, normalizeRect_1.default)(span.getBoundingClientRect()); (_a = span.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(span); if (rect) { return rect; } } // 4) try getBoundingClientRect on element var element = position.element; if (element && element.getBoundingClientRect) { rect = (0, normalizeRect_1.default)(element.getBoundingClientRect()); if (rect) { return rect; } } return null; } exports.default = getPositionRect; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/selection/getSelectionPath.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/selection/getSelectionPath.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var Position_1 = __webpack_require__(/*! ./Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts"); /** * Get path of the given selection range related to the given rootNode * @param rootNode The root node where the path start from * @param range The range of selection */ function getSelectionPath(rootNode, range) { if (!range) { return null; } var selectionPath = { start: getPositionPath(Position_1.default.getStart(range), rootNode), end: getPositionPath(Position_1.default.getEnd(range), rootNode), }; return selectionPath; } exports.default = getSelectionPath; /** * Get the path of the node relative to rootNode. * The path of the node is an array of integer indices into the childNodes of the given node. * * The node path will be what the node path will be on a _normalized_ dom * (e.g. empty text nodes will be ignored and adjacent text nodes will be concatenated) * * @param rootNode the node the path will be relative to * @param position the position to get indexes from. Follows the same semantics * as selectionRange (if node is of type Text, it is an offset into the text of that node. * If node is of type Element, it is the index of a child in that Element node.) */ function getPositionPath(position, rootNode) { var _a, _b; if (!position || !rootNode) { return []; } var node = position.node; var offset = position.offset; var result = []; var parent; if (!(0, contains_1.default)(rootNode, node, true)) { return []; } if (node.nodeType == 3 /* Text */) { parent = node.parentNode; while (node.previousSibling && node.previousSibling.nodeType == 3 /* Text */) { offset += ((_a = node.previousSibling.nodeValue) === null || _a === void 0 ? void 0 : _a.length) || 0; node = node.previousSibling; } result.unshift(offset); } else { parent = node; node = node.childNodes[offset]; } do { offset = 0; var isPreviousText = false; for (var c = (parent === null || parent === void 0 ? void 0 : parent.firstChild) || null; c && c != node; c = c.nextSibling) { if (c.nodeType == 3 /* Text */) { if (((_b = c.nodeValue) === null || _b === void 0 ? void 0 : _b.length) === 0 || isPreviousText) { continue; } isPreviousText = true; } else { isPreviousText = false; } offset++; } result.unshift(offset); node = parent; parent = (parent === null || parent === void 0 ? void 0 : parent.parentNode) || null; } while (node && node != rootNode); return result; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/selection/isPositionAtBeginningOf.ts": /*!********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/selection/isPositionAtBeginningOf.ts ***! \********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var isNodeEmpty_1 = __webpack_require__(/*! ../utils/isNodeEmpty */ "./packages/roosterjs-editor-dom/lib/utils/isNodeEmpty.ts"); /** * Check if this position is at beginning of the given node. * This will return true if all nodes between the beginning of target node and the position are empty. * @param position The position to check * @param targetNode The node to check * @returns True if position is at beginning of the node, otherwise false */ function isPositionAtBeginningOf(position, targetNode) { if (position) { position = position.normalize(); var node = position.node; var offset = position.offset; if (offset == 0) { while (node && (0, contains_1.default)(targetNode, node) && areAllPreviousNodesEmpty(node)) { node = (node === null || node === void 0 ? void 0 : node.parentNode) || null; } return node == targetNode; } } return false; } exports.default = isPositionAtBeginningOf; function areAllPreviousNodesEmpty(node) { while (node.previousSibling) { node = node.previousSibling; if ((0, getTagOfNode_1.default)(node) == 'BR' || !(0, isNodeEmpty_1.default)(node)) { return false; } } return true; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/selection/setHtmlWithSelectionPath.ts": /*!*********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/selection/setHtmlWithSelectionPath.ts ***! \*********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setHtmlWithMetadata = void 0; var createRange_1 = __webpack_require__(/*! ./createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var validate_1 = __webpack_require__(/*! ../metadata/validate */ "./packages/roosterjs-editor-dom/lib/metadata/validate.ts"); var definitionCreators_1 = __webpack_require__(/*! ../metadata/definitionCreators */ "./packages/roosterjs-editor-dom/lib/metadata/definitionCreators.ts"); var NumberArrayDefinition = (0, definitionCreators_1.createArrayDefinition)((0, definitionCreators_1.createNumberDefinition)()); var CoordinatesDefinition = (0, definitionCreators_1.createObjectDefinition)({ x: (0, definitionCreators_1.createNumberDefinition)(), y: (0, definitionCreators_1.createNumberDefinition)(), }); var IsDarkModeDefinition = (0, definitionCreators_1.createBooleanDefinition)(true /*isOptional*/); var NormalContentMetadataDefinition = (0, definitionCreators_1.createObjectDefinition)({ type: (0, definitionCreators_1.createNumberDefinition)(true /*isOptional*/, 0 /* Normal */), isDarkMode: IsDarkModeDefinition, start: NumberArrayDefinition, end: NumberArrayDefinition, }); var TableContentMetadataDefinition = (0, definitionCreators_1.createObjectDefinition)({ type: (0, definitionCreators_1.createNumberDefinition)(false /*isOptional*/, 1 /* TableSelection */), isDarkMode: IsDarkModeDefinition, tableId: (0, definitionCreators_1.createStringDefinition)(), firstCell: CoordinatesDefinition, lastCell: CoordinatesDefinition, }); var ImageContentMetadataDefinition = (0, definitionCreators_1.createObjectDefinition)({ type: (0, definitionCreators_1.createNumberDefinition)(false /*isOptional*/, 2 /* ImageSelection */), isDarkMode: IsDarkModeDefinition, imageId: (0, definitionCreators_1.createStringDefinition)(), }); /** * @deprecated Use setHtmlWithMetadata instead * Restore inner HTML of a root element from given html string. If the string contains selection path, * remove the selection path and return a range represented by the path * @param root The root element * @param html The HTML to restore * @param trustedHTMLHandler An optional trusted HTML handler to convert HTML string to security string * @returns A selection range if the html contains a valid selection path, otherwise null */ function setHtmlWithSelectionPath(rootNode, html, trustedHTMLHandler) { var metadata = setHtmlWithMetadata(rootNode, html, trustedHTMLHandler); return (metadata === null || metadata === void 0 ? void 0 : metadata.type) == 0 /* Normal */ ? (0, createRange_1.default)(rootNode, metadata.start, metadata.end) : null; } exports.default = setHtmlWithSelectionPath; /** * Restore inner HTML of a root element from given html string. If the string contains metadata, * remove it from DOM tree and return the metadata * @param root The root element * @param html The HTML to restore * @param trustedHTMLHandler An optional trusted HTML handler to convert HTML string to security string * @returns Content metadata if any, or undefined */ function setHtmlWithMetadata(rootNode, html, trustedHTMLHandler) { if (!rootNode) { return undefined; } html = html || ''; rootNode.innerHTML = (trustedHTMLHandler === null || trustedHTMLHandler === void 0 ? void 0 : trustedHTMLHandler(html)) || html; var potentialMetadataComment = rootNode.lastChild; if ((0, safeInstanceOf_1.default)(potentialMetadataComment, 'Comment')) { try { var obj = JSON.parse(potentialMetadataComment.nodeValue || ''); if ((0, validate_1.default)(obj, NormalContentMetadataDefinition) || (0, validate_1.default)(obj, TableContentMetadataDefinition) || (0, validate_1.default)(obj, ImageContentMetadataDefinition)) { rootNode.removeChild(potentialMetadataComment); obj.type = typeof obj.type === 'undefined' ? 0 /* Normal */ : obj.type; obj.isDarkMode = obj.isDarkMode || false; return obj; } } catch (_a) { } } return undefined; } exports.setHtmlWithMetadata = setHtmlWithMetadata; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/snapshots/addSnapshot.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/snapshots/addSnapshot.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.addSnapshotV2 = void 0; var clearProceedingSnapshots_1 = __webpack_require__(/*! ./clearProceedingSnapshots */ "./packages/roosterjs-editor-dom/lib/snapshots/clearProceedingSnapshots.ts"); function addSnapshot(snapshots, snapshot, isAutoCompleteSnapshot, getLength, compare) { getLength = getLength || (function (str) { var _a; return ((_a = str) === null || _a === void 0 ? void 0 : _a.length) || 0; }); compare = compare || defaultCompare; var currentSnapshot = snapshots.snapshots[snapshots.currentIndex]; if (snapshots.currentIndex < 0 || !currentSnapshot || !compare(snapshot, currentSnapshot)) { (0, clearProceedingSnapshots_1.default)(snapshots, getLength); snapshots.snapshots.push(snapshot); snapshots.currentIndex++; snapshots.totalSize += getLength(snapshot); var removeCount = 0; while (removeCount < snapshots.snapshots.length && snapshots.totalSize > snapshots.maxSize) { snapshots.totalSize -= getLength(snapshots.snapshots[removeCount]); removeCount++; } if (removeCount > 0) { snapshots.snapshots.splice(0, removeCount); snapshots.currentIndex -= removeCount; snapshots.autoCompleteIndex -= removeCount; } if (isAutoCompleteSnapshot) { snapshots.autoCompleteIndex = snapshots.currentIndex; } } else if (currentSnapshot && compare(snapshot, currentSnapshot)) { // replace the currentSnapshot, to update other data such as metadata snapshots.snapshots.splice(snapshots.currentIndex, 1, snapshot); } } exports.default = addSnapshot; /** * Add a new snapshot to the given snapshots data structure * @param snapshots The snapshots data structure to add new snapshot into * @param snapshot The snapshot object to add * @param isAutoCompleteSnapshot Whether this is a snapshot before auto complete action */ function addSnapshotV2(snapshots, snapshot, isAutoCompleteSnapshot) { addSnapshot(snapshots, snapshot, isAutoCompleteSnapshot, function (s) { var _a; return ((_a = s.html) === null || _a === void 0 ? void 0 : _a.length) || 0; }, compareSnapshots); } exports.addSnapshotV2 = addSnapshotV2; function compareSnapshots(s1, s2) { return s1.html == s2.html; } function defaultCompare(s1, s2) { return s1 == s2; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/snapshots/canMoveCurrentSnapshot.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/snapshots/canMoveCurrentSnapshot.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Check whether can move current snapshot with the given step * @param snapshots The snapshots data structure to check * @param step The step to check, can be positive, negative or 0 * @returns True if can move current snapshot with the given step, otherwise false */ function canMoveCurrentSnapshot(snapshots, step) { var newIndex = snapshots.currentIndex + step; return newIndex >= 0 && newIndex < snapshots.snapshots.length; } exports.default = canMoveCurrentSnapshot; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/snapshots/canUndoAutoComplete.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/snapshots/canUndoAutoComplete.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Whether there is a snapshot added before auto complete and it can be undone now */ function canUndoAutoComplete(snapshots) { return (snapshots.autoCompleteIndex >= 0 && snapshots.currentIndex - snapshots.autoCompleteIndex == 1); } exports.default = canUndoAutoComplete; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/snapshots/clearProceedingSnapshots.ts": /*!*********************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/snapshots/clearProceedingSnapshots.ts ***! \*********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clearProceedingSnapshotsV2 = void 0; var canMoveCurrentSnapshot_1 = __webpack_require__(/*! ./canMoveCurrentSnapshot */ "./packages/roosterjs-editor-dom/lib/snapshots/canMoveCurrentSnapshot.ts"); /** * Clear all snapshots after the current one * @param snapshots The snapshots data structure to clear */ function clearProceedingSnapshots(snapshots, getLength) { getLength = getLength || (function (str) { var _a; return ((_a = str) === null || _a === void 0 ? void 0 : _a.length) || 0; }); if ((0, canMoveCurrentSnapshot_1.default)(snapshots, 1)) { var removedSize = 0; for (var i = snapshots.currentIndex + 1; i < snapshots.snapshots.length; i++) { removedSize += getLength(snapshots.snapshots[i]); } snapshots.snapshots.splice(snapshots.currentIndex + 1); snapshots.totalSize -= removedSize; snapshots.autoCompleteIndex = -1; } } exports.default = clearProceedingSnapshots; /** * Clear all snapshots after the current one * @param snapshots The snapshots data structure to clear */ function clearProceedingSnapshotsV2(snapshots) { clearProceedingSnapshots(snapshots, function (s) { var _a; return ((_a = s.html) === null || _a === void 0 ? void 0 : _a.length) || 0; }); } exports.clearProceedingSnapshotsV2 = clearProceedingSnapshotsV2; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/snapshots/createSnapshots.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/snapshots/createSnapshots.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Create initial snapshots * @param maxSize max size of all snapshots */ function createSnapshots(maxSize) { return { snapshots: [], totalSize: 0, currentIndex: -1, autoCompleteIndex: -1, maxSize: maxSize, }; } exports.default = createSnapshots; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/snapshots/moveCurrentSnapshot.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/snapshots/moveCurrentSnapshot.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.moveCurrentSnapsnot = void 0; var canMoveCurrentSnapshot_1 = __webpack_require__(/*! ./canMoveCurrentSnapshot */ "./packages/roosterjs-editor-dom/lib/snapshots/canMoveCurrentSnapshot.ts"); /** * Move current snapshot with the given step if can move this step. Otherwise no action and return null * @param snapshots The snapshots data structure to move * @param step The step to move * @returns If can move with the given step, returns the snapshot after move, otherwise null */ function moveCurrentSnapshot(snapshots, step) { if ((0, canMoveCurrentSnapshot_1.default)(snapshots, step)) { snapshots.currentIndex += step; snapshots.autoCompleteIndex = -1; return snapshots.snapshots[snapshots.currentIndex]; } else { return null; } } exports.default = moveCurrentSnapshot; /** * @deprecated * For backward compatibility only */ exports.moveCurrentSnapsnot = moveCurrentSnapshot; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/style/getStyles.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/style/getStyles.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Get CSS styles of a given element in name-value pair format * @param element The element to get styles from */ function getStyles(element) { var result = {}; var style = (element === null || element === void 0 ? void 0 : element.getAttribute('style')) || ''; style.split(';').forEach(function (pair) { var valueIndex = pair.indexOf(':'); var name = pair.slice(0, valueIndex); var value = pair.slice(valueIndex + 1); if (name && value) { result[name.trim()] = value.trim(); } }); return result; } exports.default = getStyles; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/style/removeGlobalCssStyle.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/style/removeGlobalCssStyle.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * Remove a css rule style from a style sheet * @param doc The document object * @param styleId the ID of the style tag */ Object.defineProperty(exports, "__esModule", { value: true }); function removeGlobalCssStyle(doc, styleId) { var _a; var styleTag = doc.getElementById(styleId); if (styleTag) { (_a = styleTag.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(styleTag); } } exports.default = removeGlobalCssStyle; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/style/removeImportantStyleRule.ts": /*!*****************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/style/removeImportantStyleRule.ts ***! \*****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getStyles_1 = __webpack_require__(/*! ./getStyles */ "./packages/roosterjs-editor-dom/lib/style/getStyles.ts"); var setStyles_1 = __webpack_require__(/*! ./setStyles */ "./packages/roosterjs-editor-dom/lib/style/setStyles.ts"); /** * Removes the css important rule from some css properties * @param element The HTMLElement * @param styleProperties The css properties that important must be removed. Ex: ['background-color', 'background'] */ function removeImportantStyleRule(element, styleProperties) { var styles = (0, getStyles_1.default)(element); var modifiedStyles = 0; styleProperties.forEach(function (style) { var _a; if (((_a = styles[style]) === null || _a === void 0 ? void 0 : _a.indexOf('!important')) > -1) { var index = styles[style].indexOf('!'); styles[style] = styles[style].substring(0, index); modifiedStyles++; } }); if (modifiedStyles > 0) { (0, setStyles_1.default)(element, styles); } } exports.default = removeImportantStyleRule; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/style/setGlobalCssStyles.ts": /*!***********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/style/setGlobalCssStyles.ts ***! \***********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * Add global css styles * @param doc The document object * @param cssRule The css rule that must added to the selection * @param editorId Te id of the editor * @param styleId the ID of the style tag */ Object.defineProperty(exports, "__esModule", { value: true }); function setGlobalCssStyles(doc, cssRule, styleId) { var _a; var styleTag = doc.getElementById(styleId); if (!styleTag) { styleTag = doc.createElement('style'); styleTag.id = styleId; doc.head.appendChild(styleTag); } (_a = styleTag.sheet) === null || _a === void 0 ? void 0 : _a.insertRule(cssRule); } exports.default = setGlobalCssStyles; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/style/setStyles.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/style/setStyles.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getObjectKeys_1 = __webpack_require__(/*! ../jsUtils/getObjectKeys */ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts"); /** * Set styles to an HTML element. If styles are empty, remove 'style' attribute * @param element The element to set styles * @param styles The styles to set, in name-value pair format */ function setStyles(element, styles) { if (element) { var style = (0, getObjectKeys_1.default)(styles || {}) .map(function (name) { var value = styles[name]; var trimmedName = name ? name.trim() : null; var trimmedValue = value ? value.trim() : null; return trimmedName && trimmedValue ? trimmedName + ":" + trimmedValue : null; }) .filter(function (x) { return x; }) .join(';'); if (style) { element.setAttribute('style', style); } else { element.removeAttribute('style'); } } } exports.default = setStyles; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/table/VTable.ts": /*!***********************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/table/VTable.ts ***! \***********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); var applyTableFormat_1 = __webpack_require__(/*! ./applyTableFormat */ "./packages/roosterjs-editor-dom/lib/table/applyTableFormat.ts"); var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var moveChildNodes_1 = __webpack_require__(/*! ../utils/moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts"); var normalizeRect_1 = __webpack_require__(/*! ../utils/normalizeRect */ "./packages/roosterjs-editor-dom/lib/utils/normalizeRect.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); var tableFormatInfo_1 = __webpack_require__(/*! ./tableFormatInfo */ "./packages/roosterjs-editor-dom/lib/table/tableFormatInfo.ts"); var metadata_1 = __webpack_require__(/*! ../metadata/metadata */ "./packages/roosterjs-editor-dom/lib/metadata/metadata.ts"); var DEFAULT_FORMAT = { topBorderColor: '#ABABAB', bottomBorderColor: '#ABABAB', verticalBorderColor: '#ABABAB', hasHeaderRow: false, hasFirstColumn: false, hasBandedRows: false, hasBandedColumns: false, bgColorEven: null, bgColorOdd: '#ABABAB20', headerRowColor: '#ABABAB', tableBorderFormat: 0 /* DEFAULT */, keepCellShade: false, }; /** * A virtual table class, represent an HTML table, by expand all merged cells to each separated cells */ var VTable = /** @class */ (function () { /** * Create a new instance of VTable object using HTML TABLE or TD node * @param node The HTML Table or TD node * @param normalizeSize Whether table size needs to be normalized * @param zoomScale When the table is under a zoomed container, pass in the zoom scale here */ function VTable(node, normalizeSize, zoomScale) { var _this = this; /** * Virtual cells */ this.cells = null; /** * Current format of the table */ this.formatInfo = null; this.trs = []; this.tableSelection = null; this.table = (0, safeInstanceOf_1.default)(node, 'HTMLTableElement') ? node : getTableFromTd(node); if (this.table) { var currentTd_1 = (0, safeInstanceOf_1.default)(node, 'HTMLTableElement') ? null : node; var trs = (0, toArray_1.default)(this.table.rows); this.cells = trs.map(function (row) { return []; }); trs.forEach(function (tr, rowIndex) { var _a; _this.trs[rowIndex % 2] = tr; for (var sourceCol = 0, targetCol = 0; sourceCol < tr.cells.length; sourceCol++) { // Skip the cells which already initialized for (; _this.cells[rowIndex][targetCol]; targetCol++) { } var td = tr.cells[sourceCol]; if (td == currentTd_1) { _this.col = targetCol; _this.row = rowIndex; } for (var colSpan = 0; colSpan < td.colSpan; colSpan++, targetCol++) { for (var rowSpan = 0; rowSpan < td.rowSpan; rowSpan++) { var hasTd = colSpan + rowSpan == 0; var rect = td.getBoundingClientRect(); if ((_a = _this.cells) === null || _a === void 0 ? void 0 : _a[rowIndex + rowSpan]) { _this.cells[rowIndex + rowSpan][targetCol] = { td: hasTd ? td : null, spanLeft: colSpan > 0, spanAbove: rowSpan > 0, width: hasTd ? rect.width : undefined, height: hasTd ? rect.height : undefined, }; } } } } }); this.formatInfo = (0, tableFormatInfo_1.getTableFormatInfo)(this.table); if (normalizeSize) { this.normalizeSize(typeof zoomScale == 'number' ? function (n) { return n / zoomScale; } : zoomScale); } } } Object.defineProperty(VTable.prototype, "selection", { /** * Selected range of cells with the coordinates of the first and last cell selected. */ get: function () { return this.tableSelection || null; }, set: function (value) { if (value) { var firstCell = value.firstCell; this.row = firstCell === null || firstCell === void 0 ? void 0 : firstCell.y; this.col = firstCell === null || firstCell === void 0 ? void 0 : firstCell.x; } this.tableSelection = value; }, enumerable: false, configurable: true }); /** * Write the virtual table back to DOM tree to represent the change of VTable * @param skipApplyFormat Do not reapply table format when write back. * Only use this parameter when you are pretty sure there is no format or table structure change during the process. */ VTable.prototype.writeBack = function (skipApplyFormat) { var _this = this; var _a; if (this.cells) { (0, moveChildNodes_1.default)(this.table); this.cells.forEach(function (row, r) { var tr = cloneNode(_this.trs[r % 2] || _this.trs[0]); if (tr) { _this.table.appendChild(tr); row.forEach(function (cell, c) { if (cell.td) { _this.recalculateSpans(r, c); _this.recalculateCellHeight(cell.td); tr.appendChild(cell.td); } }); } }); if (this.formatInfo && !skipApplyFormat) { (0, tableFormatInfo_1.saveTableInfo)(this.table, this.formatInfo); (0, applyTableFormat_1.default)(this.table, this.cells, this.formatInfo); } } else if (this.table) { (_a = this.table.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this.table); } }; VTable.prototype.recalculateCellHeight = function (td) { if (this.isEmptyCell(td) && td.rowSpan > 1) { for (var i = 1; i < td.rowSpan; i++) { var br = document.createElement('br'); td.appendChild(br); } } }; /** * Apply the given table format to this virtual table * @param format Table format to apply */ VTable.prototype.applyFormat = function (format) { if (!this.table) { return; } this.formatInfo = __assign(__assign(__assign({}, DEFAULT_FORMAT), (this.formatInfo || {})), (format || {})); if (!this.formatInfo.keepCellShade) { this.deleteCellShadeDataset(this.cells); } }; /** * Remove the cellShade dataset to apply a new style format at the cell. * @param cells */ VTable.prototype.deleteCellShadeDataset = function (cells) { cells === null || cells === void 0 ? void 0 : cells.forEach(function (row) { row.forEach(function (cell) { if (cell.td) { (0, metadata_1.removeMetadata)(cell.td); } }); }); }; /** * Edit table with given operation. * @param operation Table operation */ VTable.prototype.edit = function (operation) { var _this = this; var _a, _b; if (!this.table || !this.cells || this.row === undefined || this.col == undefined) { return; } var currentRow = this.cells[this.row]; var currentCell = currentRow[this.col]; var firstRow = this.selection ? this.selection.firstCell.y : this.row; var lastRow = this.selection ? this.selection.lastCell.y : this.row; var firstColumn = this.selection ? this.selection.firstCell.x : this.col; var lastColumn = this.selection ? this.selection.lastCell.x : this.col; switch (operation) { case 0 /* InsertAbove */: for (var i = firstRow; i <= lastRow; i++) { this.cells.splice(firstRow, 0, currentRow.map(cloneCell)); } break; case 1 /* InsertBelow */: var _loop_1 = function (i) { var newRow = lastRow + this_1.countSpanAbove(lastRow, this_1.col); this_1.cells.splice(newRow, 0, this_1.cells[newRow - 1].map(function (cell, colIndex) { var nextCell = _this.getCell(newRow, colIndex); if (nextCell.spanAbove) { return cloneCell(nextCell); } else if (cell.spanLeft) { var newCell = cloneCell(cell); newCell.spanAbove = false; return newCell; } else { return { td: cloneNode(_this.getTd(_this.row, colIndex)), }; } })); }; var this_1 = this; for (var i = firstRow; i <= lastRow; i++) { _loop_1(i); } break; case 2 /* InsertLeft */: var _loop_2 = function (i) { this_2.forEachCellOfCurrentColumn(function (cell, row) { row.splice(i, 0, cloneCell(cell)); }); }; var this_2 = this; for (var i = firstColumn; i <= lastColumn; i++) { _loop_2(i); } break; case 3 /* InsertRight */: var _loop_3 = function (i) { var newCol = lastColumn + this_3.countSpanLeft(this_3.row, lastColumn); this_3.forEachCellOfColumn(newCol - 1, function (cell, row, i) { var nextCell = _this.getCell(i, newCol); var newCell; if (nextCell.spanLeft) { newCell = cloneCell(nextCell); } else if (cell.spanAbove) { newCell = cloneCell(cell); newCell.spanLeft = false; } else { newCell = { td: cloneNode(_this.getTd(i, _this.col)), }; } row.splice(newCol, 0, newCell); }); }; var this_3 = this; for (var i = firstColumn; i <= lastColumn; i++) { _loop_3(i); } break; case 6 /* DeleteRow */: var _loop_4 = function (rowIndex) { this_4.forEachCellOfRow(rowIndex, function (cell, i) { var nextCell = _this.getCell(rowIndex + 1, i); if (cell.td && cell.td.rowSpan > 1 && nextCell.spanAbove) { nextCell.td = cell.td; } }); }; var this_4 = this; for (var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++) { _loop_4(rowIndex); } var removedRows = this.selection ? this.selection.lastCell.y - this.selection.firstCell.y : 0; this.cells.splice(firstRow, removedRows + 1); if (this.cells.length === 0) { this.cells = null; } break; case 5 /* DeleteColumn */: var deletedColumns_1 = 0; var _loop_5 = function (colIndex) { this_5.forEachCellOfColumn(colIndex, function (cell, row, i) { var nextCell = _this.getCell(i, colIndex + 1); if (cell.td && cell.td.colSpan > 1 && nextCell.spanLeft) { nextCell.td = cell.td; } var removedColumns = _this.selection ? colIndex - deletedColumns_1 : _this.col; row.splice(removedColumns, 1); }); deletedColumns_1++; }; var this_5 = this; for (var colIndex = firstColumn; colIndex <= lastColumn; colIndex++) { _loop_5(colIndex); } if (((_a = this.cells) === null || _a === void 0 ? void 0 : _a.length) === 0 || ((_b = this.cells) === null || _b === void 0 ? void 0 : _b.every(function (row) { return row.length === 0; }))) { this.cells = null; } break; case 7 /* MergeAbove */: case 8 /* MergeBelow */: var rowStep = operation == 7 /* MergeAbove */ ? -1 : 1; for (var rowIndex = this.row + rowStep; rowIndex >= 0 && rowIndex < this.cells.length; rowIndex += rowStep) { var cell = this.getCell(rowIndex, this.col); if (cell.td && !cell.spanAbove) { var aboveCell = rowIndex < this.row ? cell : currentCell; var belowCell = rowIndex < this.row ? currentCell : cell; this.mergeCells(aboveCell, belowCell); break; } } break; case 9 /* MergeLeft */: case 10 /* MergeRight */: var colStep = operation == 9 /* MergeLeft */ ? -1 : 1; for (var colIndex = this.col + colStep; colIndex >= 0 && colIndex < this.cells[this.row].length; colIndex += colStep) { var cell = this.getCell(this.row, colIndex); if (cell.td && !cell.spanLeft) { var leftCell = colIndex < this.col ? cell : currentCell; var rightCell = colIndex < this.col ? currentCell : cell; this.mergeCells(leftCell, rightCell, true /** horizontally */); break; } } break; case 11 /* MergeCells */: for (var colIndex = firstColumn; colIndex <= lastColumn; colIndex++) { for (var rowIndex = firstRow + 1; rowIndex <= lastRow; rowIndex++) { var cell = this.getCell(firstRow, colIndex); var nextCellBelow = this.getCell(rowIndex, colIndex); this.mergeCells(cell, nextCellBelow); } } for (var colIndex = firstColumn + 1; colIndex <= lastColumn; colIndex++) { var cell = this.getCell(firstRow, firstColumn); var nextCellRight = this.getCell(firstRow, colIndex); this.mergeCells(cell, nextCellRight, true /** horizontally */); } break; case 4 /* DeleteTable */: this.cells = null; break; case 13 /* SplitVertically */: if (currentCell.td && currentCell.td.rowSpan > 1) { this.getCell(this.row + 1, this.col).td = cloneNode(currentCell.td); } else { var splitRow = currentRow.map(function (cell) { return { td: cell == currentCell ? cloneNode(cell.td) : null, spanAbove: cell != currentCell, spanLeft: cell.spanLeft, }; }); this.cells.splice(this.row + 1, 0, splitRow); } break; case 12 /* SplitHorizontally */: if (currentCell.td && currentCell.td.colSpan > 1) { this.getCell(this.row, this.col + 1).td = cloneNode(currentCell.td); } else { this.forEachCellOfCurrentColumn(function (cell, row) { row.splice(_this.col + 1, 0, { td: row == currentRow ? cloneNode(cell.td) : null, spanAbove: cell.spanAbove, spanLeft: row != currentRow, }); }); } break; case 14 /* AlignCenter */: this.table.style.marginLeft = 'auto'; this.table.style.marginRight = 'auto'; break; case 15 /* AlignLeft */: this.table.style.marginLeft = ''; this.table.style.marginRight = 'auto'; break; case 16 /* AlignRight */: this.table.style.marginLeft = 'auto'; this.table.style.marginRight = ''; break; case 18 /* AlignCellCenter */: this.setAlignmentToSelectedCells(firstRow, lastRow, firstColumn, lastColumn, 'center'); break; case 17 /* AlignCellLeft */: this.setAlignmentToSelectedCells(firstRow, lastRow, firstColumn, lastColumn, 'left'); break; case 19 /* AlignCellRight */: this.setAlignmentToSelectedCells(firstRow, lastRow, firstColumn, lastColumn, 'right'); break; case 20 /* AlignCellTop */: this.setAlignmentToSelectedCells(firstRow, lastRow, firstColumn, lastColumn, 'top', true /** isVertical */); break; case 21 /* AlignCellMiddle */: this.setAlignmentToSelectedCells(firstRow, lastRow, firstColumn, lastColumn, 'middle', true /** isVertical */); break; case 22 /* AlignCellBottom */: this.setAlignmentToSelectedCells(firstRow, lastRow, firstColumn, lastColumn, 'bottom', true /** isVertical */); break; } }; VTable.prototype.setAlignmentToSelectedCells = function (firstRow, lastRow, firstColumn, lastColumn, alignmentType, isVertical) { var _a, _b; for (var i = firstRow; i <= lastRow; i++) { for (var j = firstColumn; j <= lastColumn; j++) { if (this.cells) { var cell = this.cells[i][j].td; if (isVertical && cell) { (_a = cell.style) === null || _a === void 0 ? void 0 : _a.setProperty('vertical-align', alignmentType); } else if (cell) { (_b = cell.style) === null || _b === void 0 ? void 0 : _b.setProperty('text-align', alignmentType); } } } } }; VTable.prototype.mergeCells = function (cell, nextCell, horizontally) { var _a, _b, _c, _d; var checkSpans = horizontally ? ((_a = cell.td) === null || _a === void 0 ? void 0 : _a.rowSpan) === ((_b = nextCell.td) === null || _b === void 0 ? void 0 : _b.rowSpan) && !cell.spanLeft : ((_c = cell.td) === null || _c === void 0 ? void 0 : _c.colSpan) === ((_d = nextCell.td) === null || _d === void 0 ? void 0 : _d.colSpan) && !cell.spanAbove; if (cell.td && nextCell.td && checkSpans) { this.mergeCellContents(cell.td, nextCell.td); nextCell.td = null; if (horizontally) { nextCell.spanLeft = true; } else { nextCell.spanAbove = true; } } }; VTable.prototype.isEmptyCell = function (td) { return td.childElementCount === 1 && (0, getTagOfNode_1.default)(td.firstChild) === 'BR'; }; VTable.prototype.mergeCellContents = function (cellTd, nextCellTd) { if (this.isEmptyCell(nextCellTd)) { (0, moveChildNodes_1.default)(cellTd, nextCellTd, false /*keepExistingChildren*/); } else { var br = document.createElement('br'); cellTd.appendChild(br); (0, moveChildNodes_1.default)(cellTd, nextCellTd, true /*keepExistingChildren*/); } }; /** * Loop each cell of current column and invoke a callback function * @param callback The callback function to invoke */ VTable.prototype.forEachCellOfCurrentColumn = function (callback) { this.forEachCellOfColumn(this.col, callback); }; /** * Loop each table cell and get all the cells that share the same border from one side * The result is an array of table cell elements * @param borderPos The position of the border * @param getLeftCells Get left-hand-side or right-hand-side cells of the border * * Example, consider having a 3 by 4 table as below with merged and split cells * * | 1 | 4 | 7 | 8 | * | 5 | 9 | * | 3 | 10 | * * input => borderPos: the 3rd border, getLeftCells: true * output => [4, 5, 3] * * input => borderPos: the 3rd border, getLeftCells: false * output => [7, 9, 10] * * input => borderPos: the 2nd border, getLeftCells: true * output => [1] * * input => borderPos: the 2nd border, getLeftCells: false * output => [4] */ VTable.prototype.getCellsWithBorder = function (borderPos, getLeftCells) { var cells = []; for (var i = 0; this.cells && i < this.cells.length; i++) { for (var j = 0; j < this.cells[i].length; j++) { var cell = this.getCell(i, j); if (cell.td) { var cellRect = (0, normalizeRect_1.default)(cell.td.getBoundingClientRect()); if (cellRect) { var found = false; if (getLeftCells) { if (cellRect.right == borderPos) { found = true; cells.push(cell.td); } else if (found) { break; } } else { if (cellRect.left == borderPos) { found = true; cells.push(cell.td); } else if (found) { break; } } } } } } return cells; }; /** * Loop each cell of current row and invoke a callback function * @param callback The callback function to invoke */ VTable.prototype.forEachCellOfCurrentRow = function (callback) { this.forEachCellOfRow(this.row, callback); }; /** * Get a table cell using its row and column index. This function will always return an object * even if the given indexes don't exist in table. * @param row The row index * @param col The column index */ VTable.prototype.getCell = function (row, col) { return (this.cells && this.cells[row] && this.cells[row][col]) || {}; }; /** * Get current HTML table cell object. If the current table cell is a virtual expanded cell, return its root cell */ VTable.prototype.getCurrentTd = function () { return this.getTd(this.row, this.col); }; /** * Get the Table Cell in a provided coordinate * @param row row of the cell * @param col column of the cell */ VTable.prototype.getTd = function (row, col) { if (this.cells && row !== undefined && col !== undefined) { row = Math.min(this.cells.length - 1, row); col = this.cells[row] ? Math.min(this.cells[row].length - 1, col) : col; if (!isNaN(row) && !isNaN(col)) { while (row >= 0 && col >= 0) { var cell = this.getCell(row, col); if (cell.td) { return cell.td; } else if (cell.spanLeft) { col--; } else if (cell.spanAbove) { row--; } else { break; } } } } return null; }; VTable.prototype.forEachCellOfColumn = function (col, callback) { if (col !== undefined) { for (var i = 0; this.cells && i < this.cells.length; i++) { callback(this.getCell(i, col), this.cells[i], i); } } }; VTable.prototype.forEachCellOfRow = function (row, callback) { if (row !== undefined) { for (var i = 0; this.cells && i < this.cells[row].length; i++) { callback(this.getCell(row, i), i); } } }; VTable.prototype.recalculateSpans = function (row, col) { var td = this.getCell(row, col).td; if (td) { td.colSpan = this.countSpanLeft(row, col); td.rowSpan = this.countSpanAbove(row, col); if (td.colSpan == 1) { td.removeAttribute('colSpan'); } if (td.rowSpan == 1) { td.removeAttribute('rowSpan'); } } }; VTable.prototype.countSpanLeft = function (row, col) { var result = 1; for (var i = col + 1; this.cells && i < this.cells[row].length; i++) { var cell = this.getCell(row, i); if (cell.td || !cell.spanLeft) { break; } result++; } return result; }; VTable.prototype.countSpanAbove = function (row, col) { var result = 1; for (var i = row + 1; this.cells && i < this.cells.length; i++) { var cell = this.getCell(i, col); if (cell.td || !cell.spanAbove) { break; } result++; } return result; }; VTable.prototype.normalizeEmptyTableCells = function () { for (var i = 0, row = void 0; (row = this.table.rows[i]); i++) { for (var j = 0, cell = void 0; (cell = row.cells[j]); j++) { if (cell) { if (!cell.innerHTML || !cell.innerHTML.trim()) { cell.appendChild(document.createElement('br')); } } } } }; /* normalize width/height for each cell in the table */ VTable.prototype.normalizeTableCellSize = function (zoomScale) { // remove width/height for each row for (var i = 0, row = void 0; (row = this.table.rows[i]); i++) { row.removeAttribute('width'); row.style.setProperty('width', null); row.removeAttribute('height'); row.style.setProperty('height', null); } // set width/height for each cell for (var i = 0; this.cells && i < this.cells.length; i++) { for (var j = 0; j < this.cells[i].length; j++) { var cell = this.cells[i][j]; if (cell) { var func = typeof zoomScale == 'number' ? function (n) { return n / zoomScale; } : zoomScale; var width = cell.width || 0; var height = cell.height || 0; setHTMLElementSizeInPx(cell.td, (func === null || func === void 0 ? void 0 : func(width)) || width, (func === null || func === void 0 ? void 0 : func(height)) || height); } } } }; VTable.prototype.normalizeSize = function (sizeTransformer) { this.normalizeEmptyTableCells(); this.normalizeTableCellSize(sizeTransformer); var rect = this.table.getBoundingClientRect(); // Make sure table width/height is fixed to avoid shifting effect setHTMLElementSizeInPx(this.table, (sizeTransformer === null || sizeTransformer === void 0 ? void 0 : sizeTransformer(rect.width)) || rect.width, (sizeTransformer === null || sizeTransformer === void 0 ? void 0 : sizeTransformer(rect.height)) || rect.height); }; return VTable; }()); exports.default = VTable; function setHTMLElementSizeInPx(element, newWidth, newHeight) { if (!!element) { element.removeAttribute('width'); element.removeAttribute('height'); element.style.boxSizing = 'border-box'; element.style.width = newWidth + "px"; element.style.height = newHeight + "px"; } } function getTableFromTd(td) { var result = td; for (; result && result.tagName != 'TABLE'; result = result.parentElement) { } return result; } /** * Clone a table cell * @param cell The cell to clone */ function cloneCell(cell) { return { td: cloneNode(cell.td), spanAbove: cell.spanAbove, spanLeft: cell.spanLeft, }; } /** * Clone a node without its children. * @param node The node to clone */ function cloneNode(node) { var newNode = node ? node.cloneNode(false /*deep*/) : null; if ((0, safeInstanceOf_1.default)(newNode, 'HTMLTableCellElement')) { newNode.removeAttribute('id'); if (!newNode.firstChild) { newNode.appendChild(node.ownerDocument.createElement('br')); } } return newNode; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/table/applyTableFormat.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/table/applyTableFormat.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var changeElementTag_1 = __webpack_require__(/*! ../utils/changeElementTag */ "./packages/roosterjs-editor-dom/lib/utils/changeElementTag.ts"); var setColor_1 = __webpack_require__(/*! ../utils/setColor */ "./packages/roosterjs-editor-dom/lib/utils/setColor.ts"); var tableCellInfo_1 = __webpack_require__(/*! ./tableCellInfo */ "./packages/roosterjs-editor-dom/lib/table/tableCellInfo.ts"); var TRANSPARENT = 'transparent'; var TABLE_CELL_TAG_NAME = 'TD'; var TABLE_HEADER_TAG_NAME = 'TH'; /** * @internal * Apply the given table format to this virtual table * @param format Table format to apply */ function applyTableFormat(table, cells, format) { if (!format) { return; } table.style.borderCollapse = 'collapse'; setBordersType(cells, format); setCellColor(cells, format); setFirstColumnFormat(cells, format); setHeaderRowFormat(cells, format); } exports.default = applyTableFormat; /** * Check if the cell has shade * @param cell * @returns */ function hasCellShade(cell) { var _a; if (!cell.td) { return false; } return !!((_a = (0, tableCellInfo_1.getTableCellMetadata)(cell.td)) === null || _a === void 0 ? void 0 : _a.bgColorOverride); } /** * Set color to the table * @param format the format that must be applied */ function setCellColor(cells, format) { var color = function (index) { return (index % 2 === 0 ? format.bgColorEven : format.bgColorOdd); }; var hasBandedRows = format.hasBandedRows, hasBandedColumns = format.hasBandedColumns, bgColorOdd = format.bgColorOdd, bgColorEven = format.bgColorEven; var shouldColorWholeTable = !hasBandedRows && bgColorOdd === bgColorEven ? true : false; cells.forEach(function (row, index) { row.forEach(function (cell) { if (cell.td && !hasCellShade(cell)) { if (hasBandedRows) { var backgroundColor = color(index); (0, setColor_1.default)(cell.td, backgroundColor || TRANSPARENT, true /** isBackgroundColor*/, undefined /** isDarkMode **/, true /** shouldAdaptFontColor */); } else if (shouldColorWholeTable) { (0, setColor_1.default)(cell.td, format.bgColorOdd || TRANSPARENT, true /** isBackgroundColor*/, undefined /** isDarkMode **/, true /** shouldAdaptFontColor */); } else { (0, setColor_1.default)(cell.td, TRANSPARENT, true /** isBackgroundColor*/, undefined /** isDarkMode **/, true /** shouldAdaptFontColor */); } } }); }); if (hasBandedColumns) { cells.forEach(function (row) { row.forEach(function (cell, index) { var backgroundColor = color(index); if (cell.td && backgroundColor && !hasCellShade(cell)) { (0, setColor_1.default)(cell.td, backgroundColor, true /** isBackgroundColor*/, undefined /** isDarkMode **/, true /** shouldAdaptFontColor */); } }); }); } } /** * Set color to borders of an table * @param format * @returns */ function setBorderColors(td, format) { td.style.borderTop = getBorderStyle(format.topBorderColor); td.style.borderLeft = getBorderStyle(format.verticalBorderColor); td.style.borderRight = getBorderStyle(format.verticalBorderColor); td.style.borderBottom = getBorderStyle(format.bottomBorderColor); } /** * Format the border type * @returns */ function formatBorders(format, td, isFirstRow, isLastRow, isFirstColumn, isLastColumn) { setBorderColors(td, format); switch (format.tableBorderFormat) { case 0 /* DEFAULT */: return; case 1 /* LIST_WITH_SIDE_BORDERS */: if (!isFirstColumn) { td.style.borderLeftColor = TRANSPARENT; } if (!isLastColumn) { td.style.borderRightColor = TRANSPARENT; } break; case 4 /* FIRST_COLUMN_HEADER_EXTERNAL */: if (!isFirstRow) { td.style.borderTopColor = TRANSPARENT; } if (!isLastRow && !isFirstRow) { td.style.borderBottomColor = TRANSPARENT; } if (!isFirstColumn) { td.style.borderLeftColor = TRANSPARENT; } if (!isLastColumn && !isFirstColumn) { td.style.borderRightColor = TRANSPARENT; } if (isFirstColumn && isFirstRow) { td.style.borderRightColor = TRANSPARENT; } break; case 2 /* NO_HEADER_BORDERS */: if (isFirstRow) { td.style.borderTopColor = TRANSPARENT; td.style.borderRightColor = TRANSPARENT; td.style.borderLeftColor = TRANSPARENT; } if (isFirstColumn) { td.style.borderLeftColor = TRANSPARENT; } if (isLastColumn) { td.style.borderRightColor = TRANSPARENT; } break; case 3 /* NO_SIDE_BORDERS */: if (isFirstColumn) { td.style.borderLeftColor = TRANSPARENT; } if (isLastColumn) { td.style.borderRightColor = TRANSPARENT; } break; case 5 /* ESPECIAL_TYPE_1 */: if (isFirstRow) { td.style.borderRightColor = TRANSPARENT; td.style.borderLeftColor = TRANSPARENT; } if (isFirstColumn) { td.style.borderBottomColor = TRANSPARENT; td.style.borderTopColor = TRANSPARENT; } if (isFirstRow && isFirstColumn) { td.style.borderLeftColor = format.verticalBorderColor || TRANSPARENT; td.style.borderBottomColor = format.bottomBorderColor || TRANSPARENT; td.style.borderTopColor = format.topBorderColor || TRANSPARENT; } break; case 6 /* ESPECIAL_TYPE_2 */: if (isFirstRow) { td.style.borderRightColor = TRANSPARENT; td.style.borderLeftColor = TRANSPARENT; } if (isFirstColumn) { td.style.borderBottomColor = TRANSPARENT; td.style.borderTopColor = TRANSPARENT; } if (isFirstRow && isFirstColumn) { td.style.borderLeftColor = format.verticalBorderColor || TRANSPARENT; td.style.borderBottomColor = format.bottomBorderColor || TRANSPARENT; td.style.borderTopColor = format.topBorderColor || TRANSPARENT; } if (!isFirstRow && !isFirstColumn) { td.style.borderLeftColor = TRANSPARENT; td.style.borderBottomColor = TRANSPARENT; td.style.borderTopColor = TRANSPARENT; td.style.borderRightColor = TRANSPARENT; } break; case 7 /* ESPECIAL_TYPE_3 */: if (isFirstRow) { td.style.borderLeftColor = TRANSPARENT; td.style.borderTopColor = TRANSPARENT; td.style.borderRightColor = TRANSPARENT; } if (isFirstColumn) { td.style.borderLeftColor = TRANSPARENT; td.style.borderTopColor = TRANSPARENT; td.style.borderBottomColor = TRANSPARENT; } if (!isFirstRow && !isFirstColumn) { td.style.borderLeftColor = TRANSPARENT; td.style.borderBottomColor = TRANSPARENT; td.style.borderTopColor = TRANSPARENT; td.style.borderRightColor = TRANSPARENT; } if (isFirstRow && isFirstColumn) { td.style.borderBottomColor = format.bottomBorderColor || TRANSPARENT; } break; } } /** * Organize the borders of table according to a border type * @param format * @returns */ function setBordersType(cells, format) { cells.forEach(function (row, rowIndex) { row.forEach(function (cell, cellIndex) { if (cell.td) { formatBorders(format, cell.td, rowIndex === 0, rowIndex === cells.length - 1, cellIndex === 0, cellIndex === row.length - 1); } }); }); } /** * Apply custom design to the first table column * @param format * @returns */ function setFirstColumnFormat(cells, format) { if (!format.hasFirstColumn) { cells.forEach(function (row) { row.forEach(function (cell, cellIndex) { if (cell.td && cellIndex === 0) { cell.td = (0, changeElementTag_1.default)(cell.td, TABLE_CELL_TAG_NAME); cell.td.scope = ''; } }); }); return; } cells.forEach(function (row, rowIndex) { row.forEach(function (cell, cellIndex) { if (cell.td && cellIndex === 0) { if (rowIndex !== 0 && !hasCellShade(cell)) { cell.td.style.borderTopColor = TRANSPARENT; (0, setColor_1.default)(cell.td, TRANSPARENT, true /** isBackgroundColor*/, undefined /** isDarkMode **/, true /** shouldAdaptFontColor */); } if (rowIndex !== cells.length - 1 && rowIndex !== 0) { cell.td.style.borderBottomColor = TRANSPARENT; } cell.td = (0, changeElementTag_1.default)(cell.td, TABLE_HEADER_TAG_NAME); cell.td.scope = 'col'; } }); }); } /** * Apply custom design to the Header Row * @param format * @returns */ function setHeaderRowFormat(cells, format) { var _a, _b; if (!format.hasHeaderRow) { (_a = cells[0]) === null || _a === void 0 ? void 0 : _a.forEach(function (cell) { if (cell.td) { cell.td = (0, changeElementTag_1.default)(cell.td, TABLE_CELL_TAG_NAME); cell.td.scope = ''; } }); return; } (_b = cells[0]) === null || _b === void 0 ? void 0 : _b.forEach(function (cell) { if (cell.td && format.headerRowColor) { if (!hasCellShade(cell)) { (0, setColor_1.default)(cell.td, format.headerRowColor, true /** isBackgroundColor*/, undefined /** isDarkMode **/, true /** shouldAdaptFontColor */); } cell.td.style.borderRightColor = format.headerRowColor; cell.td.style.borderLeftColor = format.headerRowColor; cell.td.style.borderTopColor = format.headerRowColor; cell.td = (0, changeElementTag_1.default)(cell.td, TABLE_HEADER_TAG_NAME); cell.td.scope = 'row'; } }); } function getBorderStyle(style) { var color = style ? style : 'transparent'; return 'solid 1px ' + color; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/table/cloneCellStyles.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/table/cloneCellStyles.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tableCellInfo_1 = __webpack_require__(/*! ./tableCellInfo */ "./packages/roosterjs-editor-dom/lib/table/tableCellInfo.ts"); /** * Clone css styles from a element an set to another. * @param cell cell that will receive the styles * @param styledCell cell where the styles will be clone */ function cloneCellStyles(cell, styledCell) { var styles = styledCell.getAttribute('style'); if (styles) { cell.setAttribute('style', styles); (0, tableCellInfo_1.saveTableCellMetadata)(cell, { bgColorOverride: true, }); } } exports.default = cloneCellStyles; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/table/isWholeTableSelected.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/table/isWholeTableSelected.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Check if the whole table is selected * @param vTable VTable to check whether all cells are selected * @param selection Table selection with first cell selected and last cell selected coordinates. * @returns */ function isWholeTableSelected(vTable, selection) { if (!selection || !vTable.cells) { return false; } var firstCell = selection.firstCell, lastCell = selection.lastCell; var rowsLength = vTable.cells.length - 1; var colIndex = vTable.cells[rowsLength].length - 1; var firstX = firstCell.x; var firstY = firstCell.y; var lastX = lastCell.x; var lastY = lastCell.y; return firstX == 0 && firstY == 0 && lastX == colIndex && lastY == rowsLength; } exports.default = isWholeTableSelected; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/table/pasteTable.ts": /*!***************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/table/pasteTable.ts ***! \***************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var cloneCellStyles_1 = __webpack_require__(/*! ./cloneCellStyles */ "./packages/roosterjs-editor-dom/lib/table/cloneCellStyles.ts"); var moveChildNodes_1 = __webpack_require__(/*! ../utils/moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts"); var VTable_1 = __webpack_require__(/*! ./VTable */ "./packages/roosterjs-editor-dom/lib/table/VTable.ts"); /** * * Pastes a table inside another, modifying the original to create a merged one * @param currentTd The cell where the cursor is in the table to paste into * @param rootNodeToInsert A Node containing the table to be inserted * @param position The position to paste the table * @param range The selected range of the table * * Position and range are here for when table selection allows to move pivot point */ function pasteTable(currentTd, rootNodeToInsert, position, range) { var _a, _b, _c, _d; // This is the table on the clipboard var newTable = new VTable_1.default(rootNodeToInsert); // This table is already on the editor var currentTable = new VTable_1.default(currentTd); // Which cell in the currentTable is the cursor placed var cursorRow = currentTable.row; var cursorCol = currentTable.col; // Total rows and columns of the final table var rows = (_b = cursorRow + ((_a = newTable.cells) === null || _a === void 0 ? void 0 : _a.length)) !== null && _b !== void 0 ? _b : 0; var columns = (_d = cursorCol + ((_c = newTable.cells) === null || _c === void 0 ? void 0 : _c[0].length)) !== null && _d !== void 0 ? _d : 0; // Add new rows currentTable.row = currentTable.cells.length - 1; while (currentTable.cells.length < rows) { currentTable.edit(1 /* InsertBelow */); } // Add new columns currentTable.col = currentTable.cells[0].length - 1; while (currentTable.cells[0].length < columns) { currentTable.edit(3 /* InsertRight */); } // Create final table for (var i = cursorRow; i < rows; i++) { for (var j = cursorCol; j < columns; j++) { var cell = currentTable.getCell(i, j); var newCell = newTable.getTd(i - cursorRow, j - cursorCol); if (cell.td && newCell) { (0, moveChildNodes_1.default)(cell.td, newCell); (0, cloneCellStyles_1.default)(cell.td, newCell); } else { cell.td = document.createElement('td'); } } } currentTable.writeBack(); } exports.default = pasteTable; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/table/tableCellInfo.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/table/tableCellInfo.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.saveTableCellMetadata = exports.getTableCellMetadata = void 0; var definitionCreators_1 = __webpack_require__(/*! ../metadata/definitionCreators */ "./packages/roosterjs-editor-dom/lib/metadata/definitionCreators.ts"); var metadata_1 = __webpack_require__(/*! ../metadata/metadata */ "./packages/roosterjs-editor-dom/lib/metadata/metadata.ts"); var BooleanDefinition = (0, definitionCreators_1.createBooleanDefinition)(false /** isOptional */, undefined /** value */, true /** allowNull */); var TableCellFormatMetadata = (0, definitionCreators_1.createObjectDefinition)({ bgColorOverride: BooleanDefinition, }, false /* isOptional */, true /** allowNull */); /** * @internal * Get the format info of a table cell * @param cell The table cell to use */ function getTableCellMetadata(cell) { return (0, metadata_1.getMetadata)(cell, TableCellFormatMetadata); } exports.getTableCellMetadata = getTableCellMetadata; /** * Add metadata to a cell * @param cell The table cell to add the metadata * @param format The format of the table */ function saveTableCellMetadata(cell, format) { if (cell && format) { (0, metadata_1.setMetadata)(cell, format, TableCellFormatMetadata); } } exports.saveTableCellMetadata = saveTableCellMetadata; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/table/tableFormatInfo.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/table/tableFormatInfo.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.saveTableInfo = exports.getTableFormatInfo = void 0; var metadata_1 = __webpack_require__(/*! ../metadata/metadata */ "./packages/roosterjs-editor-dom/lib/metadata/metadata.ts"); var definitionCreators_1 = __webpack_require__(/*! ../metadata/definitionCreators */ "./packages/roosterjs-editor-dom/lib/metadata/definitionCreators.ts"); var NullStringDefinition = (0, definitionCreators_1.createStringDefinition)(false /** isOptional */, undefined /** value */, true /** allowNull */); var BooleanDefinition = (0, definitionCreators_1.createBooleanDefinition)(false /** isOptional */); var TableFormatMetadata = (0, definitionCreators_1.createObjectDefinition)({ topBorderColor: NullStringDefinition, bottomBorderColor: NullStringDefinition, verticalBorderColor: NullStringDefinition, hasHeaderRow: BooleanDefinition, headerRowColor: NullStringDefinition, hasFirstColumn: BooleanDefinition, hasBandedColumns: BooleanDefinition, hasBandedRows: BooleanDefinition, bgColorEven: NullStringDefinition, bgColorOdd: NullStringDefinition, tableBorderFormat: (0, definitionCreators_1.createNumberDefinition)(false /** isOptional */, undefined /* value */, 0 /* DEFAULT */, 8 /* CLEAR */), keepCellShade: (0, definitionCreators_1.createBooleanDefinition)(true /** isOptional */), }, false /* isOptional */, true /** allowNull */); /** * Get the format info of a table * If the table does not have a info saved, it will be retrieved from the css styles * @param table The table that has the info */ function getTableFormatInfo(table) { return (0, metadata_1.getMetadata)(table, TableFormatMetadata); } exports.getTableFormatInfo = getTableFormatInfo; /** * @internal * Save the format info of a table * @param table The table the info will be saved * @param format The format of the table */ function saveTableInfo(table, format) { if (table && format) { (0, metadata_1.setMetadata)(table, format, TableFormatMetadata); } } exports.saveTableInfo = saveTableInfo; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/Browser.ts": /*!************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/Browser.ts ***! \************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Browser = exports.getBrowserInfo = void 0; var isAndroidRegex = /android/i; /** * Get current browser information from user agent string * @param userAgent The userAgent string of a browser * @param appVersion The appVersion string of a browser * @param vendor The vendor string of a browser * @returns The BrowserInfo object calculated from the given userAgent and appVersion */ function getBrowserInfo(userAgent, appVersion, vendor) { // checks whether the browser is running in IE // IE11 will use rv in UA instead of MSIE. Unfortunately Firefox also uses this. We should also look for "Trident" to confirm this. // There have been cases where companies using older version of IE and custom UserAgents have broken this logic (e.g. IE 10 and KellyServices) // therefore we should check that the Trident/rv combo is not just from an older IE browser var isIE11OrGreater = userAgent.indexOf('rv:') != -1 && userAgent.indexOf('Trident') != -1; var isIE = userAgent.indexOf('MSIE') != -1 || isIE11OrGreater; // IE11+ may also have 'Chrome', 'Firefox' and 'Safari' in user agent. But it will have 'trident' as well var isChrome = false; var isFirefox = false; var isSafari = false; var isEdge = false; var isWebKit = userAgent.indexOf('WebKit') != -1; var isMobileOrTablet = false; // Reference: http://detectmobilebrowsers.com/ // The default regex on the website doesn't consider tablet. // To support tablet, add |android|ipad|playbook|silk to the first regex according to the info in /about page (function (userAgentOrVendor) { if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(userAgentOrVendor) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgentOrVendor.substr(0, 4))) { isMobileOrTablet = true; } })(userAgent || vendor || ''); if (!isIE) { isChrome = userAgent.indexOf('Chrome') != -1; isFirefox = userAgent.indexOf('Firefox') != -1; if (userAgent.indexOf('Safari') != -1) { // Android and Chrome have Safari in the user string isSafari = userAgent.indexOf('Chrome') == -1 && userAgent.indexOf('Android') == -1; } // Sample Edge UA: Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10121 isEdge = userAgent.indexOf('Edge') != -1; // When it is edge, it should not be chrome or firefox. and it is also not webkit if (isEdge) { isWebKit = isChrome = isFirefox = false; } } var isMac = appVersion.indexOf('Mac') != -1; var isWin = appVersion.indexOf('Win') != -1 || appVersion.indexOf('NT') != -1; var isAndroid = isAndroidRegex.test(userAgent); return { isMac: isMac, isWin: isWin, isWebKit: isWebKit, isIE: isIE, isIE11OrGreater: isIE11OrGreater, isSafari: isSafari, isChrome: isChrome, isFirefox: isFirefox, isEdge: isEdge, isIEOrEdge: isIE || isEdge, isAndroid: isAndroid, isMobileOrTablet: isMobileOrTablet, }; } exports.getBrowserInfo = getBrowserInfo; /** * Browser object contains browser and operating system information of current environment */ exports.Browser = typeof window !== 'undefined' && window ? getBrowserInfo(window.navigator.userAgent, window.navigator.appVersion, window.navigator.vendor) : {}; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/applyFormat.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/applyFormat.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var setColor_1 = __webpack_require__(/*! ./setColor */ "./packages/roosterjs-editor-dom/lib/utils/setColor.ts"); /** * Apply format to an HTML element * @param element The HTML element to apply format to * @param format The format to apply * @param isDarkMode Whether the content should be formatted in dark mode * @param darkColorHandler An optional dark color handler object. When it is passed, we will use this handler to do variable-based dark color instead of original dataset base dark color */ function applyFormat(element, format, isDarkMode, darkColorHandler) { if (format) { var elementStyle = element.style; var fontFamily = format.fontFamily, fontSize = format.fontSize, textColor = format.textColor, textColors = format.textColors, backgroundColor = format.backgroundColor, backgroundColors = format.backgroundColors, bold = format.bold, italic = format.italic, underline = format.underline; if (fontFamily) { elementStyle.fontFamily = fontFamily; } if (fontSize) { elementStyle.fontSize = fontSize; } if (textColors) { (0, setColor_1.default)(element, textColors, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler); } else if (textColor) { (0, setColor_1.default)(element, textColor, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler); } if (backgroundColors) { (0, setColor_1.default)(element, backgroundColors, true /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler); } else if (backgroundColor) { (0, setColor_1.default)(element, backgroundColor, true /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler); } if (bold) { elementStyle.fontWeight = 'bold'; } if (italic) { elementStyle.fontStyle = 'italic'; } if (underline) { elementStyle.textDecoration = 'underline'; } } } exports.default = applyFormat; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/changeElementTag.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/changeElementTag.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getComputedStyles_1 = __webpack_require__(/*! ./getComputedStyles */ "./packages/roosterjs-editor-dom/lib/utils/getComputedStyles.ts"); var getTagOfNode_1 = __webpack_require__(/*! ./getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var moveChildNodes_1 = __webpack_require__(/*! ./moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts"); function changeElementTag(element, newTag) { var _a; if (!element || !newTag) { return null; } var origianlTag = (0, getTagOfNode_1.default)(element); if (origianlTag == newTag.toUpperCase()) { // Already in the target tag, no need to change return element; } var newElement = element.ownerDocument.createElement(newTag); for (var i = 0; i < element.attributes.length; i++) { var attr = element.attributes[i]; newElement.setAttribute(attr.name, attr.value); } (0, moveChildNodes_1.default)(newElement, element); if (origianlTag == 'P' || (0, getTagOfNode_1.default)(newElement) == 'P') { _a = (0, getComputedStyles_1.default)(element, [ 'margin-top', 'margin-bottom', ]), newElement.style.marginTop = _a[0], newElement.style.marginBottom = _a[1]; } if (element.parentNode) { element.parentNode.replaceChild(newElement, element); } return newElement; } exports.default = changeElementTag; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/collapseNodes.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/collapseNodes.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.collapse = void 0; var contains_1 = __webpack_require__(/*! ./contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var splitParentNode_1 = __webpack_require__(/*! ./splitParentNode */ "./packages/roosterjs-editor-dom/lib/utils/splitParentNode.ts"); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); /** * Collapse nodes within the given start and end nodes to their common ancestor node, * split parent nodes if necessary * @param root The root node of the scope * @param start The start node * @param end The end node * @param canSplitParent True to allow split parent node there are nodes before start or after end under the same parent * and the returned nodes will be all nodes from start through end after splitting * False to disallow split parent * @returns When canSplitParent is true, returns all node from start through end after splitting, * otherwise just return start and end */ function collapseNodes(root, start, end, canSplitParent) { var _a; if (!(0, contains_1.default)(root, start) || !(0, contains_1.default)(root, end)) { return []; } start = collapse(root, start, end, true /*isStart*/, canSplitParent); end = collapse(root, end, start, false /*isStart*/, canSplitParent); if ((0, contains_1.default)(start, end, true /*treatSameNodeAsContain*/)) { return [start]; } else if ((0, contains_1.default)(end, start)) { return [end]; } else if (start.parentNode == end.parentNode) { var nodes = start.parentNode ? (0, toArray_1.default)((_a = start.parentNode) === null || _a === void 0 ? void 0 : _a.childNodes) : []; var startIndex = nodes.indexOf(start); var endIndex = nodes.indexOf(end); return nodes.slice(startIndex, endIndex + 1); } else { return [start, end]; } } exports.default = collapseNodes; /** * @internal * Collapse a node by traversing its parent nodes until we get the common ancestor node of node and ref node * @param root Root node, traversing will be limited under this scope * @param node The node to collapse * @param ref Ref node. The result will be the nearest common ancestor node of the given node and this ref node * @param isStart Whether the given node is start of the sequence of nodes to collapse * @param canSplitParent Whether splitting parent node is allowed * @returns The common ancestor node of the given node ref node */ function collapse(root, node, ref, isStart, canSplitParent) { while (node.parentNode != root && !(0, contains_1.default)(node.parentNode, ref)) { if ((isStart && node.previousSibling) || (!isStart && node.nextSibling)) { if (!canSplitParent) { break; } (0, splitParentNode_1.default)(node, isStart); } if (!node.parentNode) { break; } node = node.parentNode; } return node; } exports.collapse = collapse; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/contains.ts": /*!*************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/contains.ts ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var safeInstanceOf_1 = __webpack_require__(/*! ./safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); function contains(container, contained, treatSameNodeAsContain) { if (!container || !contained) { return false; } if (treatSameNodeAsContain && container == contained) { return true; } if ((0, safeInstanceOf_1.default)(contained, 'Range')) { contained = contained && contained.commonAncestorContainer; treatSameNodeAsContain = true; } if (contained && contained.nodeType == 3 /* Text */) { contained = contained.parentNode; treatSameNodeAsContain = true; } if (container.nodeType != 1 /* Element */ && container.nodeType != 11 /* DocumentFragment */) { return !!treatSameNodeAsContain && container == contained; } return (!!(treatSameNodeAsContain || container != contained) && internalContains(container, contained)); } exports.default = contains; function internalContains(container, contained) { if (container.contains) { return container.contains(contained); } else { while (contained) { if (contained == container) { return true; } contained = contained.parentNode; } return false; } } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/createElement.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.KnownCreateElementData = void 0; var getObjectKeys_1 = __webpack_require__(/*! ../jsUtils/getObjectKeys */ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ./safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); var Browser_1 = __webpack_require__(/*! ./Browser */ "./packages/roosterjs-editor-dom/lib/utils/Browser.ts"); /** * All known CreateElementData used by roosterjs to create elements */ exports.KnownCreateElementData = (_a = {}, _a[0 /* None */] = { tag: '' }, // Edge can sometimes lose current format when Enter to new line. // So here we add an extra SPAN for Edge to workaround this bug _a[1 /* EmptyLine */] = Browser_1.Browser.isEdge ? { tag: 'div', children: [{ tag: 'span', children: [{ tag: 'br' }] }] } : { tag: 'div', children: [{ tag: 'br' }] }, _a[2 /* BlockquoteWrapper */] = { tag: 'blockquote', style: 'margin-top:0;margin-bottom:0', }, _a[3 /* CopyPasteTempDiv */] = { tag: 'div', style: 'width: 1px; height: 1px; overflow: hidden; position: fixed; top: 0; left; 0; -webkit-user-select: text', attributes: { contenteditable: 'true', }, }, _a[4 /* BlockListItem */] = { tag: 'li', style: 'display:block' }, _a[5 /* ContextMenuWrapper */] = { tag: 'div', style: 'position: fixed; width: 0; height: 0', }, _a[6 /* ImageEditWrapper */] = { tag: 'span', style: 'max-width:100%;vertical-align:bottom', children: [ { tag: 'div', style: 'width:100%;height:100%;position:relative;overflow:hidden', }, ], }, _a[7 /* TableHorizontalResizer */] = { tag: 'div', style: 'position: fixed; cursor: row-resize; user-select: none', }, _a[8 /* TableVerticalResizer */] = { tag: 'div', style: 'position: fixed; cursor: col-resize; user-select: none', }, _a[9 /* TableResizerLTR */] = { tag: 'div', style: 'position: fixed; cursor: nw-resize; user-select: none; border: 1px solid #808080', }, _a[10 /* TableResizerRTL */] = { tag: 'div', style: 'position: fixed; cursor: ne-resize; user-select: none; border: 1px solid #808080', }, _a[11 /* TableSelector */] = { tag: 'div', style: 'position: fixed; cursor: all-scroll; user-select: none; border: 1px solid #808080', }, _a[12 /* EmptyLineFormatInSpan */] = { tag: 'div', children: [{ tag: 'span', children: [{ tag: 'br' }] }], }, _a); /** * Create DOM element from the given CreateElementData * @param elementData The CreateElementData or an index of a known CreateElementData used for creating this element * @param document The document to create the element from * @returns The root DOM element just created */ function createElement(elementData, document) { if (typeof elementData == 'number') { elementData = exports.KnownCreateElementData[elementData]; } if (!elementData || !elementData.tag) { return null; } var tag = elementData.tag, namespace = elementData.namespace, className = elementData.className, style = elementData.style, dataset = elementData.dataset, attributes = elementData.attributes, children = elementData.children; var result = namespace ? document.createElementNS(namespace, tag) : document.createElement(tag); if (style) { result.setAttribute('style', style); } if (className) { result.className = className; } if (dataset && (0, safeInstanceOf_1.default)(result, 'HTMLElement')) { (0, getObjectKeys_1.default)(dataset).forEach(function (datasetName) { result.dataset[datasetName] = dataset[datasetName]; }); } if (attributes) { (0, getObjectKeys_1.default)(attributes).forEach(function (attrName) { result.setAttribute(attrName, attributes[attrName]); }); } if (children) { children.forEach(function (child) { if (typeof child === 'string') { result.appendChild(document.createTextNode(child)); } else if (child) { var childElement = createElement(child, document); if (childElement) { result.appendChild(childElement); } } }); } return result; } exports.default = createElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var contains_1 = __webpack_require__(/*! ./contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var matchesSelector_1 = __webpack_require__(/*! ./matchesSelector */ "./packages/roosterjs-editor-dom/lib/utils/matchesSelector.ts"); /** * Find closest element ancestor start from the given node which matches the given selector * @param node Find ancestor start from this node * @param root Root node where the search should stop at. The return value can never be this node * @param selector The expected selector. If null, return the first HTML Element found from start node * @returns An HTML element which matches the given selector. If the given start node matches the selector, * returns the given node */ function findClosestElementAncestor(node, root, selector) { node = !node ? null : node.nodeType == 1 /* Element */ ? node : node.parentNode; var element = node && node.nodeType == 1 /* Element */ ? node : null; if (element && selector) { if (element.closest) { element = element.closest(selector); } else { while (element && element != root && !(0, matchesSelector_1.default)(element, selector)) { element = element.parentElement; } } } return !root || (0, contains_1.default)(root, element) ? element : null; } exports.default = findClosestElementAncestor; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/fromHtml.ts": /*!*************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/fromHtml.ts ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); /** * @deprecated * Creates an HTML node array from html * @param html the html string to create HTML elements from * @param ownerDocument Owner document of the result HTML elements * @returns An HTML node array to represent the given html string */ function fromHtml(html, ownerDocument) { var element = ownerDocument.createElement('DIV'); element.innerHTML = html; return (0, toArray_1.default)(element.childNodes); } exports.default = fromHtml; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/getComputedStyles.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/getComputedStyles.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getComputedStyle = void 0; var findClosestElementAncestor_1 = __webpack_require__(/*! ./findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts"); /** * Get computed styles of a node * @param node The node to get computed styles from * @param styleNames Names of style to get, can be a single name or an array. * Default value is font-family, font-size, color, background-color * @returns An array of the computed styles */ function getComputedStyles(node, styleNames) { if (styleNames === void 0) { styleNames = ['font-family', 'font-size', 'color', 'background-color']; } var element = (0, findClosestElementAncestor_1.default)(node); var result = []; styleNames = Array.isArray(styleNames) ? styleNames : [styleNames]; if (element) { var win = element.ownerDocument.defaultView || window; var styles = win.getComputedStyle(element); if (styles) { for (var _i = 0, styleNames_1 = styleNames; _i < styleNames_1.length; _i++) { var style = styleNames_1[_i]; var value = styles.getPropertyValue(style) || ''; value = style != 'font-family' ? value.toLowerCase() : value; value = style == 'font-size' ? px2Pt(value) : value; result.push(value); } } } return result; } exports.default = getComputedStyles; /** * A shortcut for getComputedStyles() when only one style is to be retrieved * @param node The node to get style from * @param styleName The style name * @returns The style value */ function getComputedStyle(node, styleName) { return getComputedStyles(node, styleName)[0] || ''; } exports.getComputedStyle = getComputedStyle; function px2Pt(px) { if (px && px.indexOf('px') == px.length - 2) { // Edge may not handle the floating computing well which causes the calculated value is a little less than actual value // So add 0.05 to fix it return Math.round(parseFloat(px) * 75 + 0.05) / 100 + 'pt'; } return px; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/getInnerHTML.ts": /*!*****************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/getInnerHTML.ts ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var safeInstanceOf_1 = __webpack_require__(/*! ./safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); /** * Get innerHTML of the given node * @param node The DOM node to get innerHTML from */ function getInnerHTML(node) { if ((0, safeInstanceOf_1.default)(node, 'HTMLElement')) { return node.innerHTML; } else if (node) { var tempNode = node.ownerDocument.createElement('span'); tempNode.appendChild(node.cloneNode(true /*deep*/)); return tempNode.innerHTML; } else { return ''; } } exports.default = getInnerHTML; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/getIntersectedRect.ts": /*!***********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/getIntersectedRect.ts ***! \***********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var normalizeRect_1 = __webpack_require__(/*! ./normalizeRect */ "./packages/roosterjs-editor-dom/lib/utils/normalizeRect.ts"); /** * Get the intersected Rect of elements provided * * @example * The result of the following Elements Rects would be: { top: Element2.top, bottom: Element1.bottom, left: Element2.left, right: Element2.right } +-------------------------+ | Element 1 | | +-----------------+ | | | Element2 | | | | | | | | | | +-------------------------+ | | +-----------------+ * @param elements Elements to use. * @param additionalRects additional rects to use * @returns If the Rect is valid return the rect, if not, return null. */ function getIntersectedRect(elements, additionalRects) { if (additionalRects === void 0) { additionalRects = []; } var rects = elements .map(function (element) { return (0, normalizeRect_1.default)(element.getBoundingClientRect()); }) .filter(function (element) { return !!element; }) .concat(additionalRects); var result = { top: Math.max.apply(Math, rects.map(function (r) { return r.top; })), bottom: Math.min.apply(Math, rects.map(function (r) { return r.bottom; })), left: Math.max.apply(Math, rects.map(function (r) { return r.left; })), right: Math.min.apply(Math, rects.map(function (r) { return r.right; })), }; return result.top < result.bottom && result.left < result.right ? result : null; } exports.default = getIntersectedRect; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/getLeafNode.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/getLeafNode.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getLastLeafNode = exports.getFirstLeafNode = void 0; var shouldSkipNode_1 = __webpack_require__(/*! ./shouldSkipNode */ "./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts"); var getLeafSibling_1 = __webpack_require__(/*! ./getLeafSibling */ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts"); /** * Get first/last leaf node of the given root node. * @param rootNode Root node to get leaf node from * @param isFirst True to get first leaf node, false to get last leaf node */ function getLeafNode(rootNode, isFirst) { var getChild = function (node) { return (isFirst ? node.firstChild : node.lastChild); }; var result = getChild(rootNode); while (result && getChild(result)) { result = getChild(result); } if (result && (0, shouldSkipNode_1.default)(result)) { result = (0, getLeafSibling_1.getLeafSibling)(rootNode, result, isFirst); } return result; } /** * Get the first meaningful leaf node * @param rootNode Root node to get leaf node from */ function getFirstLeafNode(rootNode) { return getLeafNode(rootNode, true /*isFirst*/); } exports.getFirstLeafNode = getFirstLeafNode; /** * Get the last meaningful leaf node * @param rootNode Root node to get leaf node from */ function getLastLeafNode(rootNode) { return getLeafNode(rootNode, false /*isFirst*/); } exports.getLastLeafNode = getLastLeafNode; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getPreviousLeafSibling = exports.getNextLeafSibling = exports.getLeafSibling = void 0; var contains_1 = __webpack_require__(/*! ./contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts"); var getTagOfNode_1 = __webpack_require__(/*! ./getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var shouldSkipNode_1 = __webpack_require__(/*! ./shouldSkipNode */ "./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts"); /** * @internal * This walks forwards/backwards DOM tree to get next meaningful node * @param rootNode Root node to scope the leaf sibling node * @param startNode current node to get sibling node from * @param isNext True to get next leaf sibling node, false to get previous leaf sibling node * @param skipTags (Optional) tags that child elements will be skipped * @param ignoreSpace (Optional) Ignore pure space text node when check if the node should be skipped */ function getLeafSibling(rootNode, startNode, isNext, skipTags, ignoreSpace) { var result = null; var getSibling = isNext ? function (node) { return (node === null || node === void 0 ? void 0 : node.nextSibling) || null; } : function (node) { return (node === null || node === void 0 ? void 0 : node.previousSibling) || null; }; var getChild = isNext ? function (node) { return node.firstChild; } : function (node) { return node.lastChild; }; if ((0, contains_1.default)(rootNode, startNode)) { var curNode = startNode; var shouldContinue = true; while (shouldContinue) { // Find next/previous node, starting from next/previous sibling, then one level up to find next/previous sibling from parent // till a non-null nextSibling/previousSibling is found or the ceiling is encountered (rootNode) var parentNode = (curNode === null || curNode === void 0 ? void 0 : curNode.parentNode) || null; curNode = getSibling(curNode); while (!curNode && parentNode != rootNode) { curNode = getSibling(parentNode); parentNode = (parentNode === null || parentNode === void 0 ? void 0 : parentNode.parentNode) || null; } // Now traverse down to get first/last child while (curNode && (!skipTags || skipTags.indexOf((0, getTagOfNode_1.default)(curNode)) < 0) && getChild(curNode)) { curNode = getChild(curNode); } // Check special nodes (i.e. node that has a display:none etc.) and continue looping if so shouldContinue = !!curNode && (0, shouldSkipNode_1.default)(curNode, ignoreSpace); if (!shouldContinue) { // Found a good leaf node, assign and exit result = curNode; break; } } } return result; } exports.getLeafSibling = getLeafSibling; /** * This walks forwards DOM tree to get next meaningful node * @param rootNode Root node to scope the leaf sibling node * @param startNode current node to get sibling node from * @param skipTags (Optional) tags that child elements will be skipped */ function getNextLeafSibling(rootNode, startNode, skipTags) { return getLeafSibling(rootNode, startNode, true /*isNext*/, skipTags); } exports.getNextLeafSibling = getNextLeafSibling; /** * This walks backwards DOM tree to get next meaningful node * @param rootNode Root node to scope the leaf sibling node * @param startNode current node to get sibling node from * @param skipTags (Optional) tags that child elements will be skipped */ function getPreviousLeafSibling(rootNode, startNode, skipTags) { return getLeafSibling(rootNode, startNode, false /*isNext*/, skipTags); } exports.getPreviousLeafSibling = getPreviousLeafSibling; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/getPendableFormatState.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/getPendableFormatState.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PendableFormatCommandMap = void 0; var getObjectKeys_1 = __webpack_require__(/*! ../jsUtils/getObjectKeys */ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts"); /** * A map from pendable format name to document command */ exports.PendableFormatCommandMap = { /** * Bold */ isBold: "bold" /* Bold */, /** * Italic */ isItalic: "italic" /* Italic */, /** * Underline */ isUnderline: "underline" /* Underline */, /** * StrikeThrough */ isStrikeThrough: "strikeThrough" /* StrikeThrough */, /** * Subscript */ isSubscript: "subscript" /* Subscript */, /** * Superscript */ isSuperscript: "superscript" /* Superscript */, }; /** * Get Pendable Format State at cursor. * @param document The HTML Document to get format state from * @returns A PendableFormatState object which contains the values of pendable format states */ function getPendableFormatState(document) { var keys = (0, getObjectKeys_1.default)(exports.PendableFormatCommandMap); return keys.reduce(function (state, key) { state[key] = document.queryCommandState(exports.PendableFormatCommandMap[key]); return state; }, {}); } exports.default = getPendableFormatState; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts": /*!*****************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Get the html tag of a node, or empty if it is not an element * @param node The node to get tag of * @returns Tag name in upper case if the given node is an Element, or empty string otherwise */ function getTagOfNode(node) { return node && node.nodeType == 1 /* Element */ ? node.tagName.toUpperCase() : ''; } exports.default = getTagOfNode; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/isBlockElement.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/isBlockElement.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getTagOfNode_1 = __webpack_require__(/*! ./getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var BLOCK_ELEMENT_TAGS = 'ADDRESS,ARTICLE,ASIDE,BLOCKQUOTE,CANVAS,DD,DIV,DL,DT,FIELDSET,FIGCAPTION,FIGURE,FOOTER,FORM,H1,H2,H3,H4,H5,H6,HEADER,HR,LI,MAIN,NAV,NOSCRIPT,OL,OUTPUT,P,PRE,SECTION,TABLE,TD,TH,TFOOT,UL,VIDEO'.split(','); var BLOCK_DISPLAY_STYLES = ['block', 'list-item', 'table-cell']; /** * Checks if the node is a block like element. Block like element are usually those P, DIV, LI, TD etc. * @param node The node to check * @returns True if the node is a block element, otherwise false */ function isBlockElement(node) { var tag = (0, getTagOfNode_1.default)(node); return !!(tag && (BLOCK_DISPLAY_STYLES.indexOf(node.style.display) >= 0 || BLOCK_ELEMENT_TAGS.indexOf(tag) >= 0)); } exports.default = isBlockElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/isNodeAfter.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/isNodeAfter.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Checks if node1 is after node2 * @param node1 The node to check if it is after another node * @param node2 The node to check if another node is after this one * @returns True if node1 is after node2, otherwise false */ function isNodeAfter(node1, node2) { return !!(node1 && node2 && (node2.compareDocumentPosition(node1) & 4 /* Following */) == 4 /* Following */); } exports.default = isNodeAfter; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/isNodeEmpty.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/isNodeEmpty.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getTagOfNode_1 = __webpack_require__(/*! ./getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var VISIBLE_ELEMENT_TAGS = ['IMG']; var VISIBLE_CHILD_ELEMENT_SELECTOR = ['TABLE', 'IMG', 'LI'].join(','); var ZERO_WIDTH_SPACE = /\u200b/g; /** * Check if a given node has no visible content * @param node The node to check * @param trimContent Whether trim the text content so that spaces will be treated as empty. * Default value is false * @returns True if there isn't any visible element inside node, otherwise false */ function isNodeEmpty(node, trimContent, shouldCountBrAsVisible) { if (!node) { return false; } else if (node.nodeType == 3 /* Text */) { return trim(node.nodeValue || '', trimContent) == ''; } else if (node.nodeType == 1 /* Element */) { var element = node; var textContent = trim(element.textContent || '', trimContent); var visibleSelector = shouldCountBrAsVisible ? VISIBLE_CHILD_ELEMENT_SELECTOR + ",BR" : VISIBLE_CHILD_ELEMENT_SELECTOR; if (textContent != '' || VISIBLE_ELEMENT_TAGS.indexOf((0, getTagOfNode_1.default)(element)) >= 0 || element.querySelectorAll(visibleSelector)[0]) { return false; } } return true; } exports.default = isNodeEmpty; function trim(s, trim) { s = s.replace(ZERO_WIDTH_SPACE, ''); return trim ? s.trim() : s; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/isVoidHtmlElement.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/isVoidHtmlElement.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getTagOfNode_1 = __webpack_require__(/*! ./getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); /** * HTML void elements * Per https://www.w3.org/TR/html/syntax.html#syntax-elements, cannot have child nodes * This regex is used when we move focus to very begin of editor. We should avoid putting focus inside * void elements so users don't accidentally create child nodes in them */ var HTML_VOID_ELEMENTS = 'AREA,BASE,BR,COL,COMMAND,EMBED,HR,IMG,INPUT,KEYGEN,LINK,META,PARAM,SOURCE,TRACK,WBR'.split(','); /** * Check if the given node is html void element. Void element cannot have children * @param node The node to check */ function isVoidHtmlElement(node) { return !!node && HTML_VOID_ELEMENTS.indexOf((0, getTagOfNode_1.default)(node)) >= 0; } exports.default = isVoidHtmlElement; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/matchLink.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/matchLink.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getObjectKeys_1 = __webpack_require__(/*! ../jsUtils/getObjectKeys */ "./packages/roosterjs-editor-dom/lib/jsUtils/getObjectKeys.ts"); // http exclude matching regex // invalid URL example (in particular on IE and Edge): // - http://www.bing.com%00, %00 before ? (question mark) is considered invalid. IE/Edge throws invalid argument exception // - http://www.bing.com%1, %1 is invalid // - http://www.bing.com%g, %g is invalid (IE and Edge expects a two hex value after a %) // - http://www.bing.com%, % as ending is invalid (IE and Edge expects a two hex value after a %) // All above % cases if they're after ? (question mark) is then considered valid again // Similar for @, it needs to be after / (forward slash), or ? (question mark). Otherwise IE/Edge will throw security exception // - http://www.bing.com@name, @name before ? (question mark) is considered invalid // - http://www.bing.com/@name, is valid sine it is after / (forward slash) // - http://www.bing.com?@name, is also valid since it is after ? (question mark) // The regex below is essentially a break down of: // ^[^?]+%[^0-9a-f]+ => to exclude URL like www.bing.com%% // ^[^?]+%[0-9a-f][^0-9a-f]+ => to exclude URL like www.bing.com%1 // ^[^?]+%00 => to exclude URL like www.bing.com%00 // ^[^?]+%$ => to exclude URL like www.bing.com% // ^https?:\/\/[^?\/]+@ => to exclude URL like http://www.bing.com@name // ^www\.[^?\/]+@ => to exclude URL like www.bing.com@name // , => to exclude url like www.bing,,com var httpExcludeRegEx = /^[^?]+%[^0-9a-f]+|^[^?]+%[0-9a-f][^0-9a-f]+|^[^?]+%00|^[^?]+%$|^https?:\/\/[^?\/]+@|^www\.[^?\/]+@/i; // via https://tools.ietf.org/html/rfc1035 Page 7 var labelRegEx = '[a-z0-9](?:[a-z0-9-]*[a-z0-9])?'; // We're using case insensitive regexps below so don't bother including A-Z var domainNameRegEx = "(?:" + labelRegEx + "\\.)*" + labelRegEx; var domainPortRegEx = domainNameRegEx + "(?:\\:[0-9]+)?"; var domainPortWithUrlRegEx = domainPortRegEx + "(?:[\\/\\?]\\S*)?"; var linkMatchRules = { http: { match: new RegExp("^(?:microsoft-edge:)?http:\\/\\/" + domainPortWithUrlRegEx + "|www\\." + domainPortWithUrlRegEx, 'i'), except: httpExcludeRegEx, normalizeUrl: function (url) { return new RegExp('^(?:microsoft-edge:)?http:\\/\\/', 'i').test(url) ? url : 'http://' + url; }, }, https: { match: new RegExp("^(?:microsoft-edge:)?https:\\/\\/" + domainPortWithUrlRegEx, 'i'), except: httpExcludeRegEx, }, mailto: { match: new RegExp('^mailto:\\S+@\\S+\\.\\S+', 'i') }, notes: { match: new RegExp('^notes:\\/\\/\\S+', 'i') }, file: { match: new RegExp('^file:\\/\\/\\/?\\S+', 'i') }, unc: { match: new RegExp('^\\\\\\\\\\S+', 'i') }, ftp: { match: new RegExp("^ftp:\\/\\/" + domainPortWithUrlRegEx + "|ftp\\." + domainPortWithUrlRegEx, 'i'), normalizeUrl: function (url) { return (new RegExp('^ftp:\\/\\/', 'i').test(url) ? url : 'ftp://' + url); }, }, news: { match: new RegExp("^news:(\\/\\/)?" + domainPortWithUrlRegEx, 'i') }, telnet: { match: new RegExp("^telnet:(\\/\\/)?" + domainPortWithUrlRegEx, 'i') }, gopher: { match: new RegExp("^gopher:\\/\\/" + domainPortWithUrlRegEx, 'i') }, wais: { match: new RegExp("^wais:(\\/\\/)?" + domainPortWithUrlRegEx, 'i') }, }; /** * Try to match a given string with link match rules, return matched link * @param url Input url to match * @param option Link match option, exact or partial. If it is exact match, we need * to check the length of matched link and url * @param rules Optional link match rules, if not passed, only the default link match * rules will be applied * @returns The matched link data, or null if no match found. * The link data includes an original url and a normalized url */ function matchLink(url) { if (url) { for (var _i = 0, _a = (0, getObjectKeys_1.default)(linkMatchRules); _i < _a.length; _i++) { var schema = _a[_i]; var rule = linkMatchRules[schema]; var matches = url.match(rule.match); if (matches && matches[0] == url && (!rule.except || !rule.except.test(url))) { return { scheme: schema, originalUrl: url, normalizedUrl: rule.normalizeUrl ? rule.normalizeUrl(url) : url, }; } } } return null; } exports.default = matchLink; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/matchesSelector.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/matchesSelector.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var safeInstanceOf_1 = __webpack_require__(/*! ./safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); /** * A wrapper function of Element.matches * @param element The element to match * @param selector The selector to match */ function matchesSelector(element, selector) { return ((0, safeInstanceOf_1.default)(element, 'HTMLElement') && (element.matches || element.msMatchesSelector).call(element, selector)); } exports.default = matchesSelector; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Replace all child nodes of the given target node to the child nodes of source node. * @param target Target node, all child nodes of this node will be removed if keepExistingChildren is not set to true * @param source (Optional) source node, all child nodes of this node will be move to target node * @param keepExistingChildren (Optional) When set to true, all existing child nodes of target will be kept */ function moveChildNodes(target, source, keepExistingChildren) { if (!target) { return; } while (!keepExistingChildren && target.firstChild) { target.removeChild(target.firstChild); } while (source === null || source === void 0 ? void 0 : source.firstChild) { target.appendChild(source.firstChild); } } exports.default = moveChildNodes; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/normalizeRect.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/normalizeRect.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * A ClientRect of all 0 is possible. i.e. chrome returns a ClientRect of 0 when the cursor is on an empty p * We validate that and only return a rect when the passed in ClientRect is valid */ function normalizeRect(clientRect) { var _a = clientRect || { left: 0, right: 0, top: 0, bottom: 0 }, left = _a.left, right = _a.right, top = _a.top, bottom = _a.bottom; return left === 0 && right === 0 && top === 0 && bottom === 0 ? null : { left: Math.round(left), right: Math.round(right), top: Math.round(top), bottom: Math.round(bottom), }; } exports.default = normalizeRect; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/queryElements.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/queryElements.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var toArray_1 = __webpack_require__(/*! ../jsUtils/toArray */ "./packages/roosterjs-editor-dom/lib/jsUtils/toArray.ts"); /** * Query HTML elements in the container by a selector string * @param container Container element to query from * @param selector Selector string to query * @param forEachCallback An optional callback to be invoked on each node in query result * @param scope The scope of the query, default value is QueryScope.Body * @param range The selection range to query with. This is required when scope is not Body * @returns HTML Element array of the query result */ function queryElements(container, selector, forEachCallback, scope, range) { if (scope === void 0) { scope = 0 /* Body */; } if (!container || !selector) { return []; } var elements = (0, toArray_1.default)(container.querySelectorAll(selector)); if (scope != 0 /* Body */ && range) { var startContainer_1 = range.startContainer, startOffset = range.startOffset, endContainer_1 = range.endContainer, endOffset = range.endOffset; if (startContainer_1.nodeType == 1 /* Element */ && startContainer_1.firstChild) { var child = startContainer_1.childNodes[startOffset]; // range.startOffset can give a value of child.length+1 when selection is after the last child // In that case we will use the last child instead startContainer_1 = child || startContainer_1.lastChild; } endContainer_1 = endContainer_1.nodeType == 1 /* Element */ && endContainer_1.firstChild && endOffset > 0 ? endContainer_1.childNodes[endOffset - 1] : endContainer_1; elements = elements.filter(function (element) { return isIntersectWithNodeRange(element, startContainer_1, endContainer_1, scope == 2 /* InSelection */); }); } if (forEachCallback) { elements.forEach(forEachCallback); } return elements; } exports.default = queryElements; function isIntersectWithNodeRange(node, startNode, endNode, nodeContainedByRangeOnly) { var startPosition = node.compareDocumentPosition(startNode); var endPosition = node.compareDocumentPosition(endNode); var targetPositions = [0 /* Same */, 8 /* Contains */]; if (!nodeContainedByRangeOnly) { targetPositions.push(16 /* ContainedBy */); } return (checkPosition(startPosition, targetPositions) || // intersectStart checkPosition(endPosition, targetPositions) || // intersectEnd (checkPosition(startPosition, [2 /* Preceding */]) && // Contains checkPosition(endPosition, [4 /* Following */]) && !checkPosition(endPosition, [16 /* ContainedBy */]))); } function checkPosition(position, targets) { return targets.some(function (target) { return target == 0 /* Same */ ? position == 0 /* Same */ : (position & target) == target; }); } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/readFile.ts": /*!*************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/readFile.ts ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Read a file object and invoke a callback function with the data url of this file * @param file The file to read * @param callback the callback to invoke with data url of the file. * If fail to read, dataUrl will be null */ function readFile(file, callback) { if (file) { var reader_1 = new FileReader(); reader_1.onload = function () { callback(reader_1.result); }; reader_1.onerror = function () { callback(null); }; reader_1.readAsDataURL(file); } } exports.default = readFile; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getTargetWindow = void 0; // NOTE: Type TargetWindow is an auto-generated type. // Run node ./tools/generateTargetWindow.js to generate it. /** * @internal Export for test only * Try get window from the given node or range * @param node Source node to get window from */ function getTargetWindow(node) { var document = node && (node.ownerDocument || (Object.prototype.toString.apply(node) == '[object HTMLDocument]' ? node : null)); // If document exists but document.defaultView doesn't exist, it is a detached object, just use current window instead var targetWindow = document && (document.defaultView || window); return targetWindow; } exports.getTargetWindow = getTargetWindow; /** * Check if the given object is instance of the target type * @param obj Object to check * @param typeName Target type name */ function safeInstanceOf(obj, typeName) { var _a; if (typeName == 'Range') { return (Object.prototype.toString.apply(obj) == '[object Range]' && !!((_a = obj) === null || _a === void 0 ? void 0 : _a.commonAncestorContainer)); } var targetWindow = getTargetWindow(obj); var targetType = targetWindow && targetWindow[typeName]; var mainWindow = window; var mainWindowType = mainWindow && mainWindow[typeName]; return ((mainWindowType && obj instanceof mainWindowType) || (targetType && obj instanceof targetType)); } exports.default = safeInstanceOf; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/setColor.ts": /*!*************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/setColor.ts ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var WHITE = '#ffffff'; var GRAY = '#333333'; var BLACK = '#000000'; var TRANSPARENT = 'transparent'; //Using the HSL (hue, saturation and lightness) representation for RGB color values, if the value of the lightness is less than 20, the color is dark var DARK_COLORS_LIGHTNESS = 20; //If the value of the lightness is more than 80, the color is bright var BRIGHT_COLORS_LIGHTNESS = 80; var TRANSPARENT_COLOR = 'transparent'; /** * Set text color or background color to the given element * @param element The element to set color to * @param color The color to set, it can be a string of color name/value or a ModeIndependentColor object * @param isBackgroundColor Whether set background color or text color * @param isDarkMode Whether current mode is dark mode. @default false * @param shouldAdaptTheFontColor Whether the font color needs to be adapted to be visible in a dark or bright background color. @default false * @param darkColorHandler An optional dark color handler object. When it is passed, we will use this handler to do variable-based dark color instead of original dataset base dark color */ function setColor(element, color, isBackgroundColor, isDarkMode, shouldAdaptTheFontColor, darkColorHandler) { var colorString = typeof color === 'string' ? color.trim() : ''; var modeIndependentColor = typeof color === 'string' ? null : color; var cssName = isBackgroundColor ? 'background-color' : 'color'; if (colorString || modeIndependentColor) { if (darkColorHandler) { var colorValue = darkColorHandler.registerColor((modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.lightModeColor) || colorString, !!isDarkMode, modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.darkModeColor); element.style.setProperty(cssName, colorValue); } else { element.style.setProperty(cssName, (isDarkMode ? modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.darkModeColor : modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.lightModeColor) || colorString); if (element.dataset) { var dataSetName = isBackgroundColor ? "ogsb" /* OriginalStyleBackgroundColor */ : "ogsc" /* OriginalStyleColor */; if (!isDarkMode || color == TRANSPARENT_COLOR) { delete element.dataset[dataSetName]; } else if (modeIndependentColor) { element.dataset[dataSetName] = modeIndependentColor.lightModeColor; } } } if (isBackgroundColor && shouldAdaptTheFontColor) { adaptFontColorToBackgroundColor(element, (modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.lightModeColor) || colorString, isDarkMode, darkColorHandler); } } } exports.default = setColor; /** * Change the font color to white or some other color, so the text can be visible with a darker background * @param element The element that contains text. * @param lightModeBackgroundColor Existing background color in light mode * @param isDarkMode Whether the content is in dark mode * @param darkColorHandler An optional dark color handler object. When it is passed, we will use this handler to do variable-based dark color instead of original dataset base dark color */ function adaptFontColorToBackgroundColor(element, lightModeBackgroundColor, isDarkMode, darkColorHandler) { if (!lightModeBackgroundColor || lightModeBackgroundColor === TRANSPARENT) { return; } var isADarkOrBrightOrNone = isADarkOrBrightColor(lightModeBackgroundColor); switch (isADarkOrBrightOrNone) { case 1 /* DARK */: var fontForDark = { lightModeColor: WHITE, darkModeColor: GRAY, }; setColor(element, fontForDark, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler); break; case 0 /* BRIGHT */: var fontForLight = { lightModeColor: BLACK, darkModeColor: WHITE, }; setColor(element, fontForLight, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler); break; } } function isADarkOrBrightColor(color) { var lightness = calculateLightness(color); if (lightness < DARK_COLORS_LIGHTNESS) { return 1 /* DARK */; } else if (lightness > BRIGHT_COLORS_LIGHTNESS) { return 0 /* BRIGHT */; } return 2 /* NONE */; } /** * Calculate the lightness of HSL (hue, saturation and lightness) representation * @param color a RBG or RGBA COLOR * @returns */ function calculateLightness(color) { var _a, _b; var r; var g; var b; if (color.substring(0, 1) == '#') { _a = getColorsFromHEX(color), r = _a[0], g = _a[1], b = _a[2]; } else { _b = getColorsFromRGB(color), r = _b[0], g = _b[1], b = _b[2]; } // Use the values of r,g,b to calculate the lightness in the HSl representation //First calculate the fraction of the light in each color, since in css the value of r,g,b is in the interval of [0,255], we have var red = r / 255; var green = g / 255; var blue = b / 255; //Then the lightness in the HSL representation is the average between maximum fraction of r,g,b and the minimum fraction return (Math.max(red, green, blue) + Math.min(red, green, blue)) * 50; } function getColorsFromHEX(color) { if (color.length === 4) { color = color.replace(/(.)/g, '$1$1'); } var colors = color.replace('#', ''); var r = parseInt(colors.substr(0, 2), 16); var g = parseInt(colors.substr(2, 2), 16); var b = parseInt(colors.substr(4, 2), 16); return [r, g, b]; } function getColorsFromRGB(color) { var colors = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/); var r = parseInt(colors[1]); var g = parseInt(colors[2]); var b = parseInt(colors[3]); return [r, g, b]; } /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts": /*!*******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getTagOfNode_1 = __webpack_require__(/*! ./getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts"); var getComputedStyles_1 = __webpack_require__(/*! ./getComputedStyles */ "./packages/roosterjs-editor-dom/lib/utils/getComputedStyles.ts"); var CRLF = /^[\r\n]+$/g; var CRLF_SPACE = /[\t\r\n\u0020\u200B]/gm; // We should only find new line, real space or ZeroWidthSpace (TAB, %20, but not  ) /** * @internal * Skip a node when any of following conditions are true * - it is neither Element nor Text * - it is a text node but is empty * - it is a text node but contains just CRLF (noisy text node that often comes in-between elements) * - has a display:none * - it is just
    * @param node The node to check * @param ignoreSpace (Optional) True to ignore pure space text node of the node when check. * If the value of a node value is only space, set this to true will treat this node can be skipped. * Default value is false */ function shouldSkipNode(node, ignoreSpace) { if (node.nodeType == 3 /* Text */) { if (!node.nodeValue || node.textContent == '' || CRLF.test(node.nodeValue)) { return true; } else if (ignoreSpace && node.nodeValue.replace(CRLF_SPACE, '') == '') { return true; } else { return false; } } else if (node.nodeType == 1 /* Element */) { if ((0, getComputedStyles_1.getComputedStyle)(node, 'display') == 'none') { return true; } var tag = (0, getTagOfNode_1.default)(node); if (tag == 'DIV' || tag == 'SPAN') { // Empty SPAN/DIV or SPAN/DIV with only meaningless children is meaningless, // because it can render nothing. If we keep them here, there may be unexpected // LI elements added for those meaningless nodes. for (var child = node.firstChild; !!child; child = child.nextSibling) { if (!shouldSkipNode(child, ignoreSpace)) { return false; } } return true; } else { // There may still be other cases that the node is not meaningful. // We can add those cases here once we hit them. return false; } } else { return true; } } exports.default = shouldSkipNode; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/splitParentNode.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/splitParentNode.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.splitBalancedNodeRange = void 0; var isNodeAfter_1 = __webpack_require__(/*! ./isNodeAfter */ "./packages/roosterjs-editor-dom/lib/utils/isNodeAfter.ts"); /** * Split parent node of the given node before/after the given node. * When a parent node contains [A,B,C] and pass B as the given node, * If split before, the new nodes will be [A][B,C] and returns [A]; * otherwise, it will be [A,B][C] and returns [C]. * @param node The node to split before/after * @param splitBefore Whether split before or after * @param removeEmptyNewNode If the new node is empty (even then only child is space or ZER_WIDTH_SPACE), * we remove it. @default false * @returns The new parent node */ function splitParentNode(node, splitBefore) { var _a; if (!node || !node.parentNode) { return null; } var parentNode = node.parentNode; var newParent = parentNode.cloneNode(false /*deep*/); newParent.removeAttribute('id'); if (splitBefore) { while (parentNode.firstChild && parentNode.firstChild != node) { newParent.appendChild(parentNode.firstChild); } } else { while (node.nextSibling) { newParent.appendChild(node.nextSibling); } } // When the only child of new parent is ZERO_WIDTH_SPACE, we can still prevent keeping it by set removeEmptyNewNode to true if (newParent.firstChild && newParent.innerHTML != '') { (_a = parentNode.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(newParent, splitBefore ? parentNode : parentNode.nextSibling); } else { newParent = null; } return newParent; } exports.default = splitParentNode; /** * Split parent node by a balanced node range * @param nodes The nodes to split from. If only one node is passed, split it from all its siblings. * If two or nodes are passed, will split before the first one and after the last one, all other nodes will be ignored * @returns The parent node of the given node range if the given nodes are balanced, otherwise null */ function splitBalancedNodeRange(nodes) { var start = Array.isArray(nodes) ? nodes[0] : nodes; var end = Array.isArray(nodes) ? nodes[nodes.length - 1] : nodes; var parentNode = start && end && start.parentNode == end.parentNode ? start.parentNode : null; if (parentNode) { if ((0, isNodeAfter_1.default)(start, end)) { var temp = end; end = start; start = temp; } splitParentNode(start, true /*splitBefore*/); splitParentNode(end, false /*splitBefore*/); } return parentNode; } exports.splitBalancedNodeRange = splitBalancedNodeRange; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/splitTextNode.ts": /*!******************************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/splitTextNode.ts ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Split a text node into two parts by an offset number, and return one of them * @param textNode The text node to split * @param offset The offset number to split at * @param returnFirstPart True to return the first part, then the passed in textNode will become the second part. * Otherwise return the second part, and the passed in textNode will become the first part */ function splitTextNode(textNode, offset, returnFirstPart) { var _a, _b, _c; var firstPart = ((_a = textNode.nodeValue) === null || _a === void 0 ? void 0 : _a.substring(0, offset)) || ''; var secondPart = ((_b = textNode.nodeValue) === null || _b === void 0 ? void 0 : _b.substring(offset)) || ''; var newNode = textNode.ownerDocument.createTextNode(returnFirstPart ? firstPart : secondPart); textNode.nodeValue = returnFirstPart ? secondPart : firstPart; (_c = textNode.parentNode) === null || _c === void 0 ? void 0 : _c.insertBefore(newNode, returnFirstPart ? textNode : textNode.nextSibling); return newNode; } exports.default = splitTextNode; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/unwrap.ts": /*!***********************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/unwrap.ts ***! \***********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Removes the node and keep all children in place, return the parentNode where the children are attached * @param node the node to remove */ function unwrap(node) { // Unwrap requires a parentNode var parentNode = node ? node.parentNode : null; if (!parentNode) { return null; } while (node.firstChild) { parentNode.insertBefore(node.firstChild, node); } parentNode.removeChild(node); return parentNode; } exports.default = unwrap; /***/ }), /***/ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts": /*!*********************************************************!*\ !*** ./packages/roosterjs-editor-dom/lib/utils/wrap.ts ***! \*********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var createElement_1 = __webpack_require__(/*! ./createElement */ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts"); var fromHtml_1 = __webpack_require__(/*! ./fromHtml */ "./packages/roosterjs-editor-dom/lib/utils/fromHtml.ts"); var safeInstanceOf_1 = __webpack_require__(/*! ./safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts"); function wrap(nodes, wrapper) { nodes = !nodes ? [] : (0, safeInstanceOf_1.default)(nodes, 'Node') ? [nodes] : nodes; if (nodes.length == 0 || !nodes[0] || !nodes[0].ownerDocument) { return null; } if (!wrapper) { wrapper = 'div'; } if (!(0, safeInstanceOf_1.default)(wrapper, 'HTMLElement')) { var document_1 = nodes[0].ownerDocument; if (typeof wrapper === 'string') { wrapper = /^\w+$/.test(wrapper) ? document_1.createElement(wrapper) : (0, fromHtml_1.default)(wrapper, document_1)[0]; // This will be removed in next major release } else { wrapper = (0, createElement_1.default)(wrapper, document_1); } } var parentNode = nodes[0].parentNode; if (parentNode) { parentNode.insertBefore(wrapper, nodes[0]); } for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) { var node = nodes_1[_i]; wrapper.appendChild(node); } return wrapper; } exports.default = wrap; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/AutoFormat.ts": /*!*************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/AutoFormat.ts ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/AutoFormat/index */ "./packages/roosterjs-editor-plugins/lib/plugins/AutoFormat/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/ContentEdit.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/ContentEdit.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/ContentEdit/index */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/ContextMenu.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/ContextMenu.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/ContextMenu/index */ "./packages/roosterjs-editor-plugins/lib/plugins/ContextMenu/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/CustomReplace.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/CustomReplace.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/CustomReplace/index */ "./packages/roosterjs-editor-plugins/lib/plugins/CustomReplace/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/CutPasteListChain.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/CutPasteListChain.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/CutPasteListChain/index */ "./packages/roosterjs-editor-plugins/lib/plugins/CutPasteListChain/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/HyperLink.ts": /*!************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/HyperLink.ts ***! \************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/HyperLink/index */ "./packages/roosterjs-editor-plugins/lib/plugins/HyperLink/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/ImageEdit.ts": /*!************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/ImageEdit.ts ***! \************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/ImageEdit/index */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/ImageResize.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/ImageResize.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/ImageResize/index */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/Paste.ts": /*!********************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/Paste.ts ***! \********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/Paste/index */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/Picker.ts": /*!*********************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/Picker.ts ***! \*********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/Picker/index */ "./packages/roosterjs-editor-plugins/lib/plugins/Picker/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/TableCellSelection.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/TableCellSelection.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/TableCellSelection/index */ "./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/TableResize.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/TableResize.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/TableResize/index */ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/Watermark.ts": /*!************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/Watermark.ts ***! \************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./plugins/Watermark/index */ "./packages/roosterjs-editor-plugins/lib/plugins/Watermark/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/index.ts": /*!********************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/index.ts ***! \********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./ContentEdit */ "./packages/roosterjs-editor-plugins/lib/ContentEdit.ts"), exports); __exportStar(__webpack_require__(/*! ./ContextMenu */ "./packages/roosterjs-editor-plugins/lib/ContextMenu.ts"), exports); __exportStar(__webpack_require__(/*! ./CustomReplace */ "./packages/roosterjs-editor-plugins/lib/CustomReplace.ts"), exports); __exportStar(__webpack_require__(/*! ./CutPasteListChain */ "./packages/roosterjs-editor-plugins/lib/CutPasteListChain.ts"), exports); __exportStar(__webpack_require__(/*! ./HyperLink */ "./packages/roosterjs-editor-plugins/lib/HyperLink.ts"), exports); __exportStar(__webpack_require__(/*! ./ImageEdit */ "./packages/roosterjs-editor-plugins/lib/ImageEdit.ts"), exports); __exportStar(__webpack_require__(/*! ./ImageResize */ "./packages/roosterjs-editor-plugins/lib/ImageResize.ts"), exports); __exportStar(__webpack_require__(/*! ./Paste */ "./packages/roosterjs-editor-plugins/lib/Paste.ts"), exports); __exportStar(__webpack_require__(/*! ./Picker */ "./packages/roosterjs-editor-plugins/lib/Picker.ts"), exports); __exportStar(__webpack_require__(/*! ./TableResize */ "./packages/roosterjs-editor-plugins/lib/TableResize.ts"), exports); __exportStar(__webpack_require__(/*! ./Watermark */ "./packages/roosterjs-editor-plugins/lib/Watermark.ts"), exports); __exportStar(__webpack_require__(/*! ./TableCellSelection */ "./packages/roosterjs-editor-plugins/lib/TableCellSelection.ts"), exports); __exportStar(__webpack_require__(/*! ./AutoFormat */ "./packages/roosterjs-editor-plugins/lib/AutoFormat.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/pluginUtils/DragAndDropHelper.ts": /*!********************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/pluginUtils/DragAndDropHelper.ts ***! \********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Generate event names and getXY function based on different platforms to be compatible with desktop and mobile browsers */ var MOUSE_EVENT_INFO_DESKTOP = (function () { return { MOUSEDOWN: 'mousedown', MOUSEMOVE: 'mousemove', MOUSEUP: 'mouseup', getPageXY: getMouseEventPageXY, }; })(); var MOUSE_EVENT_INFO_MOBILE = (function () { return { MOUSEDOWN: 'touchstart', MOUSEMOVE: 'touchmove', MOUSEUP: 'touchend', getPageXY: getTouchEventPageXY, }; })(); function getMouseEventPageXY(e) { return [e.pageX, e.pageY]; } function getTouchEventPageXY(e) { var pageX = 0; var pageY = 0; if (e.targetTouches && e.targetTouches.length > 0) { var touch = e.targetTouches[0]; pageX = touch.pageX; pageY = touch.pageY; } return [pageX, pageY]; } /** * @internal * A helper class to help manage drag and drop to an HTML element */ var DragAndDropHelper = /** @class */ (function () { /** * Create a new instance of DragAndDropHelper class * @param trigger The trigger element. When user start drag on this element, * events will be fired to the handler object * @param context Context object that will be passed to handler function when event is fired, * so that the handler object knows which element it is triggered from. * @param onSubmit A callback that will be invoked when event handler in handler object returns true * @param handler The event handler object, see DragAndDropHandler interface for more information * @param zoomScale The zoom scale of the editor * @param forceMobile A boolean to force the use of touch controls for the helper */ function DragAndDropHelper(trigger, context, onSubmit, handler, zoomScale, forceMobile) { var _this = this; this.trigger = trigger; this.context = context; this.onSubmit = onSubmit; this.handler = handler; this.zoomScale = zoomScale; this.onMouseDown = function (e) { var _a; var _b, _c; e.preventDefault(); e.stopPropagation(); _this.addDocumentEvents(); _a = _this.dndMouse.getPageXY(e), _this.initX = _a[0], _this.initY = _a[1]; _this.initValue = (_c = (_b = _this.handler).onDragStart) === null || _c === void 0 ? void 0 : _c.call(_b, _this.context, e); }; this.onMouseMove = function (e) { var _a, _b, _c; e.preventDefault(); var _d = _this.dndMouse.getPageXY(e), pageX = _d[0], pageY = _d[1]; var deltaX = (pageX - _this.initX) / _this.zoomScale; var deltaY = (pageY - _this.initY) / _this.zoomScale; if ((_b = (_a = _this.handler).onDragging) === null || _b === void 0 ? void 0 : _b.call(_a, _this.context, e, _this.initValue, deltaX, deltaY)) { (_c = _this.onSubmit) === null || _c === void 0 ? void 0 : _c.call(_this, _this.context, _this.trigger); } }; this.onMouseUp = function (e) { var _a, _b, _c; e.preventDefault(); _this.removeDocumentEvents(); if ((_b = (_a = _this.handler).onDragEnd) === null || _b === void 0 ? void 0 : _b.call(_a, _this.context, e, _this.initValue)) { (_c = _this.onSubmit) === null || _c === void 0 ? void 0 : _c.call(_this, _this.context, _this.trigger); } }; this.dndMouse = forceMobile || roosterjs_editor_dom_1.Browser.isMobileOrTablet ? MOUSE_EVENT_INFO_MOBILE : MOUSE_EVENT_INFO_DESKTOP; trigger.addEventListener(this.dndMouse.MOUSEDOWN, this.onMouseDown); } /** * Dispose this object, remove all event listeners that has been attached */ DragAndDropHelper.prototype.dispose = function () { this.trigger.removeEventListener(this.dndMouse.MOUSEDOWN, this.onMouseDown); this.removeDocumentEvents(); }; Object.defineProperty(DragAndDropHelper.prototype, "mouseType", { get: function () { return this.dndMouse == MOUSE_EVENT_INFO_MOBILE ? 'touch' : 'mouse'; }, enumerable: false, configurable: true }); DragAndDropHelper.prototype.addDocumentEvents = function () { var doc = this.trigger.ownerDocument; doc.addEventListener(this.dndMouse.MOUSEMOVE, this.onMouseMove, true /*useCapture*/); doc.addEventListener(this.dndMouse.MOUSEUP, this.onMouseUp, true /*useCapture*/); }; DragAndDropHelper.prototype.removeDocumentEvents = function () { var doc = this.trigger.ownerDocument; doc.removeEventListener(this.dndMouse.MOUSEMOVE, this.onMouseMove, true /*useCapture*/); doc.removeEventListener(this.dndMouse.MOUSEUP, this.onMouseUp, true /*useCapture*/); }; return DragAndDropHelper; }()); exports.default = DragAndDropHelper; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/AutoFormat/AutoFormat.ts": /*!********************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/AutoFormat/AutoFormat.ts ***! \********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var specialCharacters = /[`!@#$%^&*()_+\=\[\]{};':"\\|,.<>\/?~]/; /** * Automatically transform -- into hyphen, if typed between two words. */ var AutoFormat = /** @class */ (function () { function AutoFormat() { this.editor = null; this.lastKeyTyped = null; } /** * Get a friendly name of this plugin */ AutoFormat.prototype.getName = function () { return 'AutoFormat'; }; /** * Initialize this plugin * @param editor The editor instance */ AutoFormat.prototype.initialize = function (editor) { this.editor = editor; }; /** * Dispose this plugin */ AutoFormat.prototype.dispose = function () { this.editor = null; this.lastKeyTyped = null; }; /** * Handle events triggered from editor * @param event PluginEvent object */ AutoFormat.prototype.onPluginEvent = function (event) { var _this = this; if (!this.editor) { return; } if (event.eventType === 7 /* ContentChanged */ || event.eventType === 5 /* MouseDown */ || event.eventType === 6 /* MouseUp */) { this.lastKeyTyped = ''; } if (event.eventType === 0 /* KeyDown */) { var keyTyped = event.rawEvent.key; if (keyTyped && keyTyped.length > 1) { this.lastKeyTyped = ''; } if (this.lastKeyTyped === '-' && !specialCharacters.test(keyTyped) && keyTyped !== ' ' && keyTyped !== '-') { var searcher = this.editor.getContentSearcherOfCursor(event); var textBeforeCursor = searcher === null || searcher === void 0 ? void 0 : searcher.getSubStringBefore(3); var dashes = searcher === null || searcher === void 0 ? void 0 : searcher.getSubStringBefore(2); var isPrecededByADash = (textBeforeCursor === null || textBeforeCursor === void 0 ? void 0 : textBeforeCursor[0]) === '-'; var isPrecededByASpace = (textBeforeCursor === null || textBeforeCursor === void 0 ? void 0 : textBeforeCursor[0]) === ' '; if (isPrecededByADash || isPrecededByASpace || (typeof textBeforeCursor === 'string' && specialCharacters.test(textBeforeCursor[0])) || dashes !== '--') { return; } var textRange_1 = searcher === null || searcher === void 0 ? void 0 : searcher.getRangeFromText(dashes, true /* exactMatch */); var nodeHyphen_1 = document.createTextNode('—'); this.editor.addUndoSnapshot(function () { if (textRange_1) { textRange_1.deleteContents(); textRange_1.insertNode(nodeHyphen_1); _this.editor.select(nodeHyphen_1, -1 /* End */); } }, "Format" /* Format */, true /*canUndoByBackspace*/, { formatApiName: 'autoHyphen' }); //After the substitution the last key typed needs to be cleaned this.lastKeyTyped = null; } else { this.lastKeyTyped = keyTyped; } } }; return AutoFormat; }()); exports.default = AutoFormat; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/AutoFormat/index.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/AutoFormat/index.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AutoFormat = void 0; var AutoFormat_1 = __webpack_require__(/*! ./AutoFormat */ "./packages/roosterjs-editor-plugins/lib/plugins/AutoFormat/AutoFormat.ts"); Object.defineProperty(exports, "AutoFormat", { enumerable: true, get: function () { return AutoFormat_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/ContentEdit.ts": /*!**********************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/ContentEdit.ts ***! \**********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getAllFeatures_1 = __webpack_require__(/*! ./getAllFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/getAllFeatures.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * An editor plugin to handle content edit event. * The following cases are included: * 1. Auto increase/decrease indentation on Tab, Shift+tab * 2. Enter, Backspace on empty list item * 3. Enter, Backspace on empty blockquote line * 4. Auto bullet/numbering * 5. Auto link * 6. Tab in table * 7. Up/Down in table * 8. Manage list style */ var ContentEdit = /** @class */ (function () { /** * Create instance of ContentEdit plugin * @param settingsOverride An optional feature set to override default feature settings * @param additionalFeatures Optional. More features to add */ function ContentEdit(settingsOverride, additionalFeatures) { this.settingsOverride = settingsOverride; this.additionalFeatures = additionalFeatures; this.editor = undefined; this.features = []; } /** * Get a friendly name of this plugin */ ContentEdit.prototype.getName = function () { return 'ContentEdit'; }; /** * Initialize this plugin * @param editor The editor instance */ ContentEdit.prototype.initialize = function (editor) { var _this = this; this.editor = editor; var allFeatures = (0, getAllFeatures_1.default)(); (0, roosterjs_editor_dom_1.getObjectKeys)(allFeatures).forEach(function (key) { var feature = allFeatures[key]; var hasSettingForKey = _this.settingsOverride && _this.settingsOverride[key] !== undefined; if ((hasSettingForKey && _this.settingsOverride[key]) || (!hasSettingForKey && !feature.defaultDisabled)) { _this.features.push(feature); } }); this.features = this.features.concat(this.additionalFeatures || []); this.features.forEach(function (feature) { return _this.editor.addContentEditFeature(feature); }); }; ContentEdit.prototype.disposeFeatures = function () { var _this = this; if (this.editor) { this.features.forEach(function (feature) { return _this.editor.removeContentEditFeature(feature); }); } this.features = []; }; /** * Dispose this plugin */ ContentEdit.prototype.dispose = function () { this.disposeFeatures(); this.editor = undefined; }; return ContentEdit; }()); exports.default = ContentEdit; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/autoLinkFeatures.ts": /*!************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/autoLinkFeatures.ts ***! \************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AutoLinkFeatures = void 0; var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * When user type, they may end a link with a punctuation, i.e. www.bing.com; * we need to trim off the trailing punctuation before turning it to link match */ var TRAILING_PUNCTUATION_REGEX = /[.+=\s:;"',>]+$/i; var MINIMUM_LENGTH = 5; /** * AutoLink edit feature, provides the ability to automatically convert text user typed or pasted * in hyperlink format into a real hyperlink */ var AutoLink = { keys: [13 /* ENTER */, 32 /* SPACE */, 257 /* CONTENTCHANGED */], shouldHandleEvent: cacheGetLinkData, handleEvent: autoLink, }; /** * UnlinkWhenBackspaceAfterLink edit feature, provides the ability to convert a hyperlink back into text * if user presses BACKSPACE right after a hyperlink */ var UnlinkWhenBackspaceAfterLink = { keys: [8 /* BACKSPACE */], shouldHandleEvent: hasLinkBeforeCursor, handleEvent: function (event, editor) { event.rawEvent.preventDefault(); (0, roosterjs_editor_api_1.removeLink)(editor); }, defaultDisabled: true, }; function cacheGetLinkData(event, editor) { return event.eventType == 0 /* KeyDown */ || (event.eventType == 7 /* ContentChanged */ && event.source == "Paste" /* Paste */) ? (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'LINK_DATA', function () { // First try to match link from the whole paste string from the plain text in clipboard. // This helps when we paste a link next to some existing character, and the text we got // from clipboard will only contain what we pasted, any existing characters will not // be included. var clipboardData = event.eventType == 7 /* ContentChanged */ && event.source == "Paste" /* Paste */ && event.data; var link = (0, roosterjs_editor_dom_1.matchLink)((clipboardData.text || '').trim()); var searcher = editor.getContentSearcherOfCursor(event); // In case the matched link is already inside a
    tag, we do a range search. // getRangeFromText will return null if the given text is already in a LinkInlineElement if (link && searcher.getRangeFromText(link.originalUrl, false /*exactMatch*/)) { return link; } var word = searcher && searcher.getWordBefore(); if (word && word.length > MINIMUM_LENGTH) { // Check for trailing punctuation var trailingPunctuations = word.match(TRAILING_PUNCTUATION_REGEX); var trailingPunctuation = (trailingPunctuations || [])[0] || ''; var candidate_1 = word.substring(0, word.length - trailingPunctuation.length); // Do special handling for ')', '}', ']' ['()', '{}', '[]'].forEach(function (str) { if (candidate_1[candidate_1.length - 1] == str[1] && candidate_1.indexOf(str[0]) < 0) { candidate_1 = candidate_1.substr(0, candidate_1.length - 1); } }); // Match and replace in editor return (0, roosterjs_editor_dom_1.matchLink)(candidate_1); } return null; }) : null; } function hasLinkBeforeCursor(event, editor) { var contentSearcher = editor.getContentSearcherOfCursor(event); var inline = contentSearcher.getInlineElementBefore(); return inline instanceof roosterjs_editor_dom_1.LinkInlineElement; } function autoLink(event, editor) { var anchor = editor.getDocument().createElement('a'); var linkData = cacheGetLinkData(event, editor); // Need to get searcher before we enter the async callback since the callback can happen when cursor is moved to next line // and at that time a new searcher won't be able to find the link text to replace var searcher = editor.getContentSearcherOfCursor(); anchor.textContent = linkData.originalUrl; anchor.href = linkData.normalizedUrl; editor.runAsync(function (editor) { editor.addUndoSnapshot(function () { (0, roosterjs_editor_api_1.replaceWithNode)(editor, linkData.originalUrl, anchor, false /* exactMatch */, searcher); // The content at cursor has changed. Should also clear the cursor data cache (0, roosterjs_editor_dom_1.clearEventDataCache)(event); return anchor; }, "AutoLink" /* AutoLink */, true /*canUndoByBackspace*/); }); } /** * @internal */ exports.AutoLinkFeatures = { autoLink: AutoLink, unlinkWhenBackspaceAfterLink: UnlinkWhenBackspaceAfterLink, }; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/cursorFeatures.ts": /*!**********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/cursorFeatures.ts ***! \**********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CursorFeatures = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var NoCycleCursorMove = { keys: [37 /* LEFT */, 39 /* RIGHT */], allowFunctionKeys: true, shouldHandleEvent: function (event, editor, ctrlOrMeta) { var range; var position; if (!ctrlOrMeta || !(range = editor.getSelectionRange()) || !range.collapsed || !(position = roosterjs_editor_dom_1.Position.getStart(range)) || !editor.isPositionAtBeginning(position)) { return false; } var rtl = (0, roosterjs_editor_dom_1.getComputedStyle)(position.element, 'direction') == 'rtl'; var rawEvent = event.rawEvent; return (!rtl && rawEvent.which == 37 /* LEFT */) || (rtl && rawEvent.which == 39 /* RIGHT */); }, handleEvent: function (event) { event.rawEvent.preventDefault(); }, defaultDisabled: !roosterjs_editor_dom_1.Browser.isChrome, }; /** * @internal */ exports.CursorFeatures = { noCycleCursorMove: NoCycleCursorMove, }; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/entityFeatures.ts": /*!**********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/entityFeatures.ts ***! \**********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EntityFeatures = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * A content edit feature to trigger EntityOperation event with operation "Click" when user * clicks on a readonly entity. */ var ClickOnEntityFeature = { keys: [13 /* ENTER */], shouldHandleEvent: function (event, editor) { return cacheGetReadonlyEntityElement(event, editor); }, handleEvent: function (event, editor) { cacheGetReadonlyEntityElement(event, editor, 1 /* Click */); }, }; /** * A content edit feature to trigger EntityOperation event with operation "Escape" when user * presses ESC on a readonly entity. */ var EscapeFromEntityFeature = { keys: [27 /* ESCAPE */], shouldHandleEvent: function (event, editor) { return cacheGetReadonlyEntityElement(event, editor); }, handleEvent: function (event, editor) { cacheGetReadonlyEntityElement(event, editor, 3 /* Escape */); }, }; function cacheGetReadonlyEntityElement(event, editor, operation) { var element = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'READONLY_ENTITY_ELEMENT', function () { var node = event.rawEvent.target; var entityElement = node && editor.getElementAtCursor((0, roosterjs_editor_dom_1.getEntitySelector)(), node); return entityElement && !entityElement.isContentEditable ? entityElement : null; }); if (element && operation !== undefined) { editor.triggerPluginEvent(15 /* EntityOperation */, { operation: operation, rawEvent: event.rawEvent, entity: (0, roosterjs_editor_dom_1.getEntityFromElement)(element), }); } return element; } /** * A content edit feature to split current line into two lines at the cursor when user presses * ENTER right before a readonly entity. * Browser's default behavior will insert an extra BR tag before the entity which causes an extra * empty line. So we override the default behavior here. */ var EnterBeforeReadonlyEntityFeature = { keys: [13 /* ENTER */], shouldHandleEvent: function (event, editor) { return cacheGetNeighborEntityElement(event, editor, true /*isNext*/, false /*collapseOnly*/); }, handleEvent: function (event, editor) { var _a; event.rawEvent.preventDefault(); var range = editor.getSelectionRange(); var node = roosterjs_editor_dom_1.Position.getEnd(range).normalize().node; var br = editor.getDocument().createElement('BR'); node.parentNode.insertBefore(br, node.nextSibling); var block = editor.getBlockElementAtNode(node); var newContainer; if (block) { newContainer = block.collapseToSingleElement(); (_a = br.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(br); } editor.getSelectionRange().deleteContents(); if (newContainer.nextSibling) { editor.select(newContainer.nextSibling, 0 /* Begin */); } }, }; /** * A content edit feature to trigger EntityOperation event with operation "RemoveFromEnd" when user * press BACKSPACE right after an entity */ var BackspaceAfterEntityFeature = { keys: [8 /* BACKSPACE */], shouldHandleEvent: function (event, editor) { return cacheGetNeighborEntityElement(event, editor, false /*isNext*/, true /*collapseOnly*/); }, handleEvent: function (event, editor) { cacheGetNeighborEntityElement(event, editor, false /*isNext*/, true /*collapseOnly*/, 5 /* RemoveFromEnd */); }, }; /** * A content edit feature to trigger EntityOperation event with operation "RemoveFromStart" when user * press DELETE right after an entity */ var DeleteBeforeEntityFeature = { keys: [46 /* DELETE */], shouldHandleEvent: function (event, editor) { return cacheGetNeighborEntityElement(event, editor, true /*isNext*/, true /*collapseOnly*/); }, handleEvent: function (event, editor) { cacheGetNeighborEntityElement(event, editor, true /*isNext*/, true /*collapseOnly*/, 4 /* RemoveFromStart */); }, }; function cacheGetNeighborEntityElement(event, editor, isNext, collapseOnly, operation) { var element = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'NEIGHBOR_ENTITY_ELEMENT_' + isNext + '_' + collapseOnly, function () { var range = editor.getSelectionRange(); if (!range || (collapseOnly && !range.collapsed)) { return null; } range.commonAncestorContainer.normalize(); var pos = roosterjs_editor_dom_1.Position.getEnd(range).normalize(); var isAtBeginOrEnd = pos.offset == 0 || pos.isAtEnd; var entityNode = null; if (isAtBeginOrEnd) { var traverser = editor.getBodyTraverser(pos.node); var sibling = isNext ? pos.offset == 0 ? traverser.currentInlineElement : traverser.getNextInlineElement() : pos.isAtEnd ? traverser.currentInlineElement : traverser.getPreviousInlineElement(); var node = sibling && sibling.getContainerNode(); if (!collapseOnly) { var block = editor.getBlockElementAtNode(pos.node); if (!block || !block.contains(node)) { node = null; } } entityNode = node && editor.getElementAtCursor((0, roosterjs_editor_dom_1.getEntitySelector)(), node); } return entityNode; }); if (element && operation !== undefined) { editor.triggerPluginEvent(15 /* EntityOperation */, { operation: operation, rawEvent: event.rawEvent, entity: (0, roosterjs_editor_dom_1.getEntityFromElement)(element), }); } return element; } /** * @internal */ exports.EntityFeatures = { clickOnEntity: ClickOnEntityFeature, escapeFromEntity: EscapeFromEntityFeature, enterBeforeReadonlyEntity: EnterBeforeReadonlyEntityFeature, backspaceAfterEntity: BackspaceAfterEntityFeature, deleteBeforeEntity: DeleteBeforeEntityFeature, }; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/listFeatures.ts": /*!********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/listFeatures.ts ***! \********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ListFeatures = void 0; var getAutoBulletListStyle_1 = __webpack_require__(/*! ../utils/getAutoBulletListStyle */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/utils/getAutoBulletListStyle.ts"); var getAutoNumberingListStyle_1 = __webpack_require__(/*! ../utils/getAutoNumberingListStyle */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/utils/getAutoNumberingListStyle.ts"); var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var PREVIOUS_BLOCK_CACHE_KEY = 'previousBlock'; var NEXT_BLOCK_CACHE_KEY = 'nextBlock'; var ListStyleDefinitionMetadata = (0, roosterjs_editor_dom_1.createObjectDefinition)({ orderedStyleType: (0, roosterjs_editor_dom_1.createNumberDefinition)(true /** isOptional */, undefined /** value **/, 1 /* Min */, 20 /* Max */), unorderedStyleType: (0, roosterjs_editor_dom_1.createNumberDefinition)(true /** isOptional */, undefined /** value **/, 1 /* Min */, 9 /* Max */), }, true /** isOptional */, true /** allowNull */); var shouldHandleIndentationEvent = function (indenting) { return function (event, editor) { var _a = event.rawEvent, keyCode = _a.keyCode, altKey = _a.altKey, shiftKey = _a.shiftKey, ctrlKey = _a.ctrlKey, metaKey = _a.metaKey; return (!ctrlKey && !metaKey && (keyCode === 9 /* TAB */ ? !altKey && shiftKey === !indenting : shiftKey && altKey && keyCode === (indenting ? 39 /* RIGHT */ : 37 /* LEFT */)) && cacheGetListElement(event, editor)); }; }; var handleIndentationEvent = function (indenting) { return function (event, editor) { var isRTL = event.rawEvent.keyCode !== 9 /* TAB */ && (0, roosterjs_editor_dom_1.getComputedStyle)(editor.getElementAtCursor(), 'direction') == 'rtl'; (0, roosterjs_editor_api_1.setIndentation)(editor, isRTL == indenting ? 1 /* Decrease */ : 0 /* Increase */); event.rawEvent.preventDefault(); }; }; /** * IndentWhenTab edit feature, provides the ability to indent current list when user press TAB */ var IndentWhenTab = { keys: [9 /* TAB */, 39 /* RIGHT */], shouldHandleEvent: shouldHandleIndentationEvent(true), handleEvent: handleIndentationEvent(true), allowFunctionKeys: true, }; /** * OutdentWhenShiftTab edit feature, provides the ability to outdent current list when user press Shift+TAB */ var OutdentWhenShiftTab = { keys: [9 /* TAB */, 37 /* LEFT */], shouldHandleEvent: shouldHandleIndentationEvent(false), handleEvent: handleIndentationEvent(false), allowFunctionKeys: true, }; /** * MergeInNewLine edit feature, provides the ability to merge current line into a new line when user press * BACKSPACE at beginning of a list item */ var MergeInNewLine = { keys: [8 /* BACKSPACE */], shouldHandleEvent: function (event, editor) { var li = editor.getElementAtCursor('LI', null /*startFrom*/, event); var range = editor.getSelectionRange(); return li && (range === null || range === void 0 ? void 0 : range.collapsed) && (0, roosterjs_editor_dom_1.isPositionAtBeginningOf)(roosterjs_editor_dom_1.Position.getStart(range), li); }, handleEvent: function (event, editor) { var li = editor.getElementAtCursor('LI', null /*startFrom*/, event); if (li.previousSibling) { (0, roosterjs_editor_api_1.blockFormat)(editor, function (region, start, end) { var vList = (0, roosterjs_editor_dom_1.createVListFromRegion)(region, false /*includeSiblingList*/, li); vList.setIndentation(start, end, 1 /* Decrease */, true /*softOutdent*/); vList.writeBack(editor.isFeatureEnabled("ReuseAllAncestorListElements" /* ReuseAllAncestorListElements */)); event.rawEvent.preventDefault(); }); } else { toggleListAndPreventDefault(event, editor); } }, defaultDisabled: true, }; /** * OutdentWhenBackOn1stEmptyLine edit feature, provides the ability to outdent current item if user press * BACKSPACE at the first and empty line of a list */ var OutdentWhenBackOn1stEmptyLine = { keys: [8 /* BACKSPACE */], shouldHandleEvent: function (event, editor) { var li = editor.getElementAtCursor('LI', null /*startFrom*/, event); return (li && (0, roosterjs_editor_dom_1.isNodeEmpty)(li) && !li.previousSibling && !li.getElementsByTagName('blockquote').length); }, handleEvent: toggleListAndPreventDefault, }; /** * MaintainListChainWhenDelete edit feature, provides the ability to indent the list if user press * DELETE before the first item of a list */ var MaintainListChainWhenDelete = { keys: [46 /* DELETE */], shouldHandleEvent: function (event, editor) { var li = editor.getElementAtCursor('LI', null /*startFrom*/, event); if (li) { return false; } var isAtEnd = roosterjs_editor_dom_1.Position.getEnd(editor.getSelectionRange()).isAtEnd; var nextSibling = isAtEnd ? getCacheNextSibling(event, editor) : null; var isAtEndAndBeforeLI = editor.getElementAtCursor('LI', nextSibling, event); return isAtEndAndBeforeLI; }, handleEvent: function (event, editor) { var chains = getListChains(editor); editor.runAsync(function (editor) { return (0, roosterjs_editor_api_1.commitListChains)(editor, chains); }); }, }; /** * OutdentWhenEnterOnEmptyLine edit feature, provides the ability to outdent current item if user press * ENTER at the beginning of an empty line of a list */ var OutdentWhenEnterOnEmptyLine = { keys: [13 /* ENTER */], shouldHandleEvent: function (event, editor) { var li = editor.getElementAtCursor('LI', null /*startFrom*/, event); return !event.rawEvent.shiftKey && li && (0, roosterjs_editor_dom_1.isNodeEmpty)(li); }, handleEvent: function (event, editor) { editor.addUndoSnapshot(function () { return toggleListAndPreventDefault(event, editor, false /* includeSiblingLists */); }, null /*changeSource*/, true /*canUndoByBackspace*/); }, defaultDisabled: !roosterjs_editor_dom_1.Browser.isIE && !roosterjs_editor_dom_1.Browser.isChrome, }; /** * Validate if a block of text is considered a list pattern * The regex expression will look for patterns of the form: * 1. 1> 1) 1- (1) * @returns if a text is considered a list pattern */ function isAListPattern(textBeforeCursor) { var REGEX = /^(\*|-|[0-9]{1,2}\.|[0-9]{1,2}\>|[0-9]{1,2}\)|[0-9]{1,2}\-|\([0-9]{1,2}\))$/; return REGEX.test(textBeforeCursor); } /** * AutoBullet edit feature, provides the ability to automatically convert current line into a list. * When user input "1. ", convert into a numbering list * When user input "- " or "* ", convert into a bullet list */ var AutoBullet = { keys: [32 /* SPACE */], shouldHandleEvent: function (event, editor) { if (!cacheGetListElement(event, editor) && !editor.isFeatureEnabled("AutoFormatList" /* AutoFormatList */)) { var searcher = editor.getContentSearcherOfCursor(event); var textBeforeCursor = searcher.getSubStringBefore(4); // Auto list is triggered if: // 1. Text before cursor exactly matches '*', '-' or '1.' // 2. There's no non-text inline entities before cursor return isAListPattern(textBeforeCursor) && !searcher.getNearestNonTextInlineElement(); } return false; }, handleEvent: function (event, editor) { editor.insertContent(' '); event.rawEvent.preventDefault(); editor.addUndoSnapshot(function () { var _a; var regions; var searcher = editor.getContentSearcherOfCursor(); var textBeforeCursor = searcher.getSubStringBefore(4); var textRange = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/); if (!textRange) { // no op if the range can't be found } else if (textBeforeCursor.indexOf('*') == 0 || textBeforeCursor.indexOf('-') == 0) { prepareAutoBullet(editor, textRange); (0, roosterjs_editor_api_1.toggleBullet)(editor); } else if (isAListPattern(textBeforeCursor)) { prepareAutoBullet(editor, textRange); (0, roosterjs_editor_api_1.toggleNumbering)(editor); } else if ((regions = editor.getSelectedRegions()) && regions.length == 1) { var num = parseInt(textBeforeCursor); prepareAutoBullet(editor, textRange); (0, roosterjs_editor_api_1.toggleNumbering)(editor, num); } (_a = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/)) === null || _a === void 0 ? void 0 : _a.deleteContents(); }, null /*changeSource*/, true /*canUndoByBackspace*/); }, }; /** * Requires @see ExperimentalFeatures.AutoFormatList to be enabled * AutoBulletList edit feature, provides the ability to automatically convert current line into a bullet list. */ var AutoBulletList = { keys: [32 /* SPACE */], shouldHandleEvent: function (event, editor) { if (!cacheGetListElement(event, editor) && editor.isFeatureEnabled("AutoFormatList" /* AutoFormatList */)) { return shouldTriggerList(event, editor, getAutoBulletListStyle_1.default, 2 /* Unordered */); } return false; }, handleEvent: function (event, editor) { editor.insertContent(' '); event.rawEvent.preventDefault(); editor.addUndoSnapshot(function () { var _a; var searcher = editor.getContentSearcherOfCursor(); var textBeforeCursor = searcher.getSubStringBefore(5); var textRange = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/); var listStyle = (0, getAutoBulletListStyle_1.default)(textBeforeCursor); if (textRange) { prepareAutoBullet(editor, textRange); (0, roosterjs_editor_api_1.toggleBullet)(editor, listStyle, 'autoToggleList' /** apiNameOverride */); } (_a = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/)) === null || _a === void 0 ? void 0 : _a.deleteContents(); }, null /*changeSource*/, true /*canUndoByBackspace*/); }, }; /** * Requires @see ExperimentalFeatures.AutoFormatList to be enabled * AutoNumberingList edit feature, provides the ability to automatically convert current line into a numbering list. */ var AutoNumberingList = { keys: [32 /* SPACE */], shouldHandleEvent: function (event, editor) { if (!cacheGetListElement(event, editor) && editor.isFeatureEnabled("AutoFormatList" /* AutoFormatList */)) { return shouldTriggerList(event, editor, getAutoNumberingListStyle_1.default, 1 /* Ordered */); } return false; }, handleEvent: function (event, editor) { editor.insertContent(' '); event.rawEvent.preventDefault(); editor.addUndoSnapshot(function () { var _a; var searcher = editor.getContentSearcherOfCursor(); var textBeforeCursor = searcher.getSubStringBefore(5); var textRange = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/); if (textRange) { var number = isFirstItemOfAList(textBeforeCursor) ? 1 : parseInt(textBeforeCursor); var isLi = getPreviousListItem(editor, textRange); var listStyle = (0, getAutoNumberingListStyle_1.default)(textBeforeCursor); prepareAutoBullet(editor, textRange); (0, roosterjs_editor_api_1.toggleNumbering)(editor, isLi && number !== 1 ? undefined : number /** startNumber */, listStyle, 'autoToggleList' /** apiNameOverride */); } (_a = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/)) === null || _a === void 0 ? void 0 : _a.deleteContents(); }, null /*changeSource*/, true /*canUndoByBackspace*/); }, }; var getPreviousListItem = function (editor, textRange) { var blockElement = editor .getBodyTraverser(textRange === null || textRange === void 0 ? void 0 : textRange.startContainer) .getPreviousBlockElement(); var previousNode = blockElement === null || blockElement === void 0 ? void 0 : blockElement.getEndNode(); return (0, roosterjs_editor_dom_1.getTagOfNode)(previousNode) === 'LI' ? previousNode : undefined; }; var getPreviousListType = function (editor, textRange, listType) { var type = listType === 1 /* Ordered */ ? 'orderedStyleType' : 'unorderedStyleType'; var listItem = getPreviousListItem(editor, textRange); var list = listItem ? (0, roosterjs_editor_dom_1.findClosestElementAncestor)(listItem, undefined /** root*/, listType === 1 /* Ordered */ ? 'ol' : 'ul') : null; var metadata = list ? (0, roosterjs_editor_dom_1.getMetadata)(list, ListStyleDefinitionMetadata) : null; return metadata ? metadata[type] : null; }; var isFirstItemOfAList = function (item) { var number = parseInt(item); if (number && number === 1) { return 1; } else { var letter = item.replace(/\(|\)|\-|\./g, '').trim(); return letter.length === 1 && ['i', 'a', 'I', 'A'].indexOf(letter) > -1 ? 1 : undefined; } }; /** * Maintain the list numbers in list chain * e.g. we have two lists: * 1, 2, 3 and 4, 5, 6 * Now we delete list item 2, so the first one becomes "1, 2". * This edit feature can maintain the list number of the second list to become "3, 4, 5" */ var MaintainListChain = { keys: [13 /* ENTER */, 9 /* TAB */, 46 /* DELETE */, 8 /* BACKSPACE */, 258 /* RANGE */], shouldHandleEvent: function (event, editor) { return editor .queryElements('li', 1 /* OnSelection */) .filter(function (li) { return !li.getElementsByTagName('blockquote').length; }).length > 0; }, handleEvent: function (event, editor) { var chains = getListChains(editor); editor.runAsync(function (editor) { return (0, roosterjs_editor_api_1.commitListChains)(editor, chains); }); }, }; function getListChains(editor) { return roosterjs_editor_dom_1.VListChain.createListChains(editor.getSelectedRegions()); } function getCacheNextSibling(event, editor) { var element = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'nextSibling', function () { var _a; var range = editor.getSelectionRange(); var pos = roosterjs_editor_dom_1.Position.getEnd(range).normalize(); var traverser = editor.getBodyTraverser(pos.node); return (_a = traverser === null || traverser === void 0 ? void 0 : traverser.getNextBlockElement()) === null || _a === void 0 ? void 0 : _a.getStartNode(); }); return element; } function prepareAutoBullet(editor, range) { var block = editor.getBlockElementAtNode(range.startContainer); var endNode = block === null || block === void 0 ? void 0 : block.getEndNode(); if (endNode && (0, roosterjs_editor_dom_1.getTagOfNode)(endNode) != 'BR') { var br = editor.getDocument().createElement('BR'); if ((0, roosterjs_editor_dom_1.isBlockElement)(endNode)) { endNode.appendChild(br); } else { endNode.parentNode.insertBefore(br, endNode.nextSibling); } editor.select(range.startContainer, range.startOffset); } } function toggleListAndPreventDefault(event, editor, includeSiblingLists) { if (includeSiblingLists === void 0) { includeSiblingLists = true; } var listInfo = cacheGetListElement(event, editor); if (listInfo) { var listElement = listInfo[0]; var tag = (0, roosterjs_editor_dom_1.getTagOfNode)(listElement); if (tag == 'UL' || tag == 'OL') { (0, roosterjs_editor_api_1.toggleListType)(editor, tag == 'UL' ? 2 /* Unordered */ : 1 /* Ordered */, null /* startNumber */, includeSiblingLists); } editor.focus(); event.rawEvent.preventDefault(); } } function cacheGetListElement(event, editor) { var li = editor.getElementAtCursor('LI,TABLE', null /*startFrom*/, event); var listElement = li && (0, roosterjs_editor_dom_1.getTagOfNode)(li) == 'LI' && editor.getElementAtCursor('UL,OL', li); return listElement ? [listElement, li] : null; } function shouldTriggerList(event, editor, getListStyle, listType) { var searcher = editor.getContentSearcherOfCursor(event); var textBeforeCursor = searcher.getSubStringBefore(4); var traverser = editor.getBlockTraverser(); var text = traverser && traverser.currentBlockElement ? traverser.currentBlockElement.getTextContent() : null; var isATheBeginning = text && text === textBeforeCursor; var listChains = getListChains(editor); var textRange = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/); var previousListType = getPreviousListType(editor, textRange, listType); var isFirstItem = isFirstItemOfAList(textBeforeCursor); var listStyle = getListStyle(textBeforeCursor, listChains, previousListType); var shouldTriggerNewListStyle = isFirstItem || !previousListType || previousListType === listStyle || listType === 2 /* Unordered */; return (isATheBeginning && !searcher.getNearestNonTextInlineElement() && listStyle && shouldTriggerNewListStyle); } /** * MergeListOnBackspaceAfterList edit feature, provides the ability to merge list on backspace on block after a list. */ var MergeListOnBackspaceAfterList = { keys: [8 /* BACKSPACE */], shouldHandleEvent: function (event, editor) { var _a, _b; var target = editor.getElementAtCursor(); if (target) { var cursorBlock = (_a = editor.getBlockElementAtNode(target)) === null || _a === void 0 ? void 0 : _a.getStartNode(); var previousBlock_1 = (_b = cursorBlock === null || cursorBlock === void 0 ? void 0 : cursorBlock.previousElementSibling) !== null && _b !== void 0 ? _b : null; if (isList(previousBlock_1)) { var range = editor.getSelectionRange(); var searcher = editor.getContentSearcherOfCursor(event); var textBeforeCursor = searcher === null || searcher === void 0 ? void 0 : searcher.getSubStringBefore(4); var nearestInline = searcher === null || searcher === void 0 ? void 0 : searcher.getNearestNonTextInlineElement(); if (range && range.collapsed && textBeforeCursor === '' && !nearestInline) { var tempBlock = cursorBlock === null || cursorBlock === void 0 ? void 0 : cursorBlock.nextElementSibling; var nextBlock_1 = isList(tempBlock) ? tempBlock : tempBlock === null || tempBlock === void 0 ? void 0 : tempBlock.firstChild; if (isList(nextBlock_1) && (0, roosterjs_editor_dom_1.getTagOfNode)(previousBlock_1) == (0, roosterjs_editor_dom_1.getTagOfNode)(nextBlock_1)) { var element = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, PREVIOUS_BLOCK_CACHE_KEY, function () { return previousBlock_1; }); var nextElement = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, NEXT_BLOCK_CACHE_KEY, function () { return nextBlock_1; }); return !!element && !!nextElement; } } } } return false; }, handleEvent: function (event, editor) { editor.runAsync(function (editor) { var previousList = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, PREVIOUS_BLOCK_CACHE_KEY, function () { return null; }); var targetBlock = (0, roosterjs_editor_dom_1.cacheGetEventData)(event, NEXT_BLOCK_CACHE_KEY, function () { return null; }); var rangeBeforeWriteBack = editor.getSelectionRange(); if (previousList && targetBlock && rangeBeforeWriteBack) { var fvList = new roosterjs_editor_dom_1.VList(previousList); fvList.mergeVList(new roosterjs_editor_dom_1.VList(targetBlock)); var span = editor.getDocument().createElement('span'); span.id = 'restoreRange'; rangeBeforeWriteBack.insertNode(span); fvList.writeBack(); span = editor.queryElements('#restoreRange')[0]; if (span.parentElement) { editor.select(new roosterjs_editor_dom_1.Position(span, -3 /* After */)); span.parentElement.removeChild(span); } } }); }, }; /** * @internal */ exports.ListFeatures = { autoBullet: AutoBullet, indentWhenTab: IndentWhenTab, outdentWhenShiftTab: OutdentWhenShiftTab, outdentWhenBackspaceOnEmptyFirstLine: OutdentWhenBackOn1stEmptyLine, outdentWhenEnterOnEmptyLine: OutdentWhenEnterOnEmptyLine, mergeInNewLineWhenBackspaceOnFirstChar: MergeInNewLine, maintainListChain: MaintainListChain, maintainListChainWhenDelete: MaintainListChainWhenDelete, autoNumberingList: AutoNumberingList, autoBulletList: AutoBulletList, mergeListOnBackspaceAfterList: MergeListOnBackspaceAfterList, }; function isList(element) { return (!!element && ((0, roosterjs_editor_dom_1.safeInstanceOf)(element, 'HTMLOListElement') || (0, roosterjs_editor_dom_1.safeInstanceOf)(element, 'HTMLUListElement'))); } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/markdownFeatures.ts": /*!************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/markdownFeatures.ts ***! \************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MarkdownFeatures = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var ZERO_WIDTH_SPACE = '\u200B'; function generateBasicMarkdownFeature(key, triggerCharacter, elementTag, useShiftKey) { return { keys: [key], shouldHandleEvent: function (event, editor) { return event.rawEvent.shiftKey === useShiftKey && !!cacheGetRangeForMarkdownOperation(event, editor, triggerCharacter); }, handleEvent: function (event, editor) { // runAsync is here to allow the event to complete so autocomplete will present the trigger character. editor.runAsync(function (editor) { handleMarkdownEvent(event, editor, triggerCharacter, elementTag); }); }, }; } function cacheGetRangeForMarkdownOperation(event, editor, triggerCharacter) { return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'MARKDOWN_RANGE', function () { var searcher = editor.getContentSearcherOfCursor(event); var startPosition; var endPosition; searcher === null || searcher === void 0 ? void 0 : searcher.forEachTextInlineElement(function (textInlineElement) { if (endPosition && startPosition) { return true; } var inlineTextContent = textInlineElement.getTextContent(); // special case for immediately preceding character being whitespace if (inlineTextContent[inlineTextContent.length - 1].trim().length == 0) { return false; } //if the text is pasted, it might create a inner element inside the text element, // then is necessary to check the parent block to get whole text var parentBlockText = textInlineElement.getParentBlock().getTextContent(); // special case for consecutive trigger characters // check parent block in case of pasted text if (parentBlockText[parentBlockText.length - 1].trim() === triggerCharacter) { return false; } if (!endPosition) { endPosition = textInlineElement.getStartPosition().move(inlineTextContent.length); } if (inlineTextContent[0] == triggerCharacter) { startPosition = textInlineElement.getStartPosition(); } else { var contentIndex = inlineTextContent.length - 1; for (; contentIndex > 0; contentIndex--) { if (startPosition) { return true; } if (inlineTextContent[contentIndex] == triggerCharacter && inlineTextContent[contentIndex - 1].trim().length == 0) { startPosition = textInlineElement.getStartPosition().move(contentIndex); return true; } } } }); return !!startPosition && !!endPosition && (0, roosterjs_editor_dom_1.createRange)(startPosition, endPosition); }); } function handleMarkdownEvent(event, editor, triggerCharacter, elementTag) { editor.addUndoSnapshot(function () { var range = cacheGetRangeForMarkdownOperation(event, editor, triggerCharacter); var lastTypedTriggerPosition = new roosterjs_editor_dom_1.Position(range.endContainer, -1 /* End */); var hasLastTypedTrigger = range.endOffset + 1 <= lastTypedTriggerPosition.offset; if (!!range && hasLastTypedTrigger) { // get the text content range var textContentRange = range.cloneRange(); textContentRange.setStart(textContentRange.startContainer, textContentRange.startOffset + 1); var text = textContentRange.extractContents().textContent; var textNode = editor.getDocument().createTextNode(text); // extract content and put it into a new element. var elementToWrap = (0, roosterjs_editor_dom_1.wrap)(textNode, elementTag); //include last typed character range.setEnd(range.endContainer, range.endOffset + 1); range.deleteContents(); // ZWS here ensures we don't end up inside the newly created node. var nonPrintedSpaceTextNode = editor .getDocument() .createTextNode(ZERO_WIDTH_SPACE); range.insertNode(nonPrintedSpaceTextNode); range.insertNode(elementToWrap); editor.select(nonPrintedSpaceTextNode, -1 /* End */); } }, "Format" /* Format */, true /*canUndoByBackspace*/); } /** * Markdown bold feature. Make bold text with markdown shortcuts. */ var MarkdownBold = generateBasicMarkdownFeature(56 /* EIGHT_ASTERISK */, '*', 'b', true /* useShiftKey */); /** * Markdown italics feature. Make italic text with markdown shortcuts. */ var MarkdownItalic = generateBasicMarkdownFeature(189 /* DASH_UNDERSCORE */, '_', 'i', true /* useShiftKey */); /** * Markdown strikethrough feature. MAke strikethrough text with markdown shortcuts. */ var MarkdownStrikethrough = generateBasicMarkdownFeature(192 /* GRAVE_TILDE */, '~', 's', true /* useShiftKey */); /** * Markdown inline code feature. Marks specific text as inline code with markdown shortcuts. */ var MarkdownInlineCode = generateBasicMarkdownFeature(192 /* GRAVE_TILDE */, '`', 'code', false /* useShiftKey */); /** * @internal */ exports.MarkdownFeatures = { markdownBold: MarkdownBold, markdownItalic: MarkdownItalic, markdownStrikethru: MarkdownStrikethrough, markdownInlineCode: MarkdownInlineCode, }; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/quoteFeatures.ts": /*!*********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/quoteFeatures.ts ***! \*********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QuoteFeatures = void 0; var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var QUOTE_TAG = 'BLOCKQUOTE'; var STRUCTURED_TAGS = [QUOTE_TAG, 'LI', 'TD', 'TH'].join(','); /** * UnquoteWhenBackOnEmpty1stLine edit feature, provides the ability to Unquote current line when * user press BACKSPACE on first and empty line of a BLOCKQUOTE */ var UnquoteWhenBackOnEmpty1stLine = { keys: [8 /* BACKSPACE */], shouldHandleEvent: function (event, editor) { var childOfQuote = cacheGetQuoteChild(event, editor); return childOfQuote && (0, roosterjs_editor_dom_1.isNodeEmpty)(childOfQuote) && !childOfQuote.previousSibling; }, handleEvent: splitQuote, }; /** * UnquoteWhenEnterOnEmptyLine edit feature, provides the ability to Unquote current line when * user press ENTER on an empty line of a BLOCKQUOTE */ var UnquoteWhenEnterOnEmptyLine = { keys: [13 /* ENTER */], shouldHandleEvent: function (event, editor) { var childOfQuote = cacheGetQuoteChild(event, editor); var shift = event.rawEvent.shiftKey; return !shift && childOfQuote && (0, roosterjs_editor_dom_1.isNodeEmpty)(childOfQuote); }, handleEvent: function (event, editor) { return editor.addUndoSnapshot(function () { return splitQuote(event, editor); }, null /*changeSource*/, true /*canUndoByBackspace*/); }, }; function cacheGetQuoteChild(event, editor) { return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'QUOTE_CHILD', function () { var quote = editor.getElementAtCursor(STRUCTURED_TAGS); if (quote && (0, roosterjs_editor_dom_1.getTagOfNode)(quote) == QUOTE_TAG) { var pos = editor.getFocusedPosition(); var block = pos && editor.getBlockElementAtNode(pos.normalize().node); if (block) { var node = block.getStartNode() == quote ? block.getStartNode() : block.collapseToSingleElement(); return (0, roosterjs_editor_dom_1.isNodeEmpty)(node) ? node : null; } } return null; }); } function splitQuote(event, editor) { editor.addUndoSnapshot(function () { var childOfQuote = cacheGetQuoteChild(event, editor); var parent; var shouldClearFormat; if ((0, roosterjs_editor_dom_1.getTagOfNode)(childOfQuote) == QUOTE_TAG) { childOfQuote = (0, roosterjs_editor_dom_1.wrap)((0, roosterjs_editor_dom_1.toArray)(childOfQuote.childNodes)); } parent = (0, roosterjs_editor_dom_1.splitBalancedNodeRange)(childOfQuote); shouldClearFormat = isStyledBlockquote(parent); var newParent = (0, roosterjs_editor_dom_1.unwrap)(parent); editor.select(childOfQuote, 0 /* Begin */); if (shouldClearFormat) { if ((0, roosterjs_editor_dom_1.safeInstanceOf)(newParent, 'HTMLLIElement')) { newParent.style.removeProperty('color'); } (0, roosterjs_editor_api_1.clearFormat)(editor); } }); event.rawEvent.preventDefault(); } var isStyledBlockquote = function (element) { if (element && (0, roosterjs_editor_dom_1.safeInstanceOf)(element, 'HTMLQuoteElement') && element.style.borderLeft && element.style.borderColor && element.style.paddingLeft && element.style.color) { return true; } return false; }; /** * @internal */ exports.QuoteFeatures = { unquoteWhenBackspaceOnEmptyFirstLine: UnquoteWhenBackOnEmpty1stLine, unquoteWhenEnterOnEmptyLine: UnquoteWhenEnterOnEmptyLine, }; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/shortcutFeatures.ts": /*!************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/shortcutFeatures.ts ***! \************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ShortcutFeatures = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts"); function createCommand(winKey, macKey, action, disabled) { if (disabled === void 0) { disabled = false; } if (disabled) { return null; } return { winKey: winKey, macKey: macKey, action: action, }; } var commands = [ createCommand(4096 /* Ctrl */ | 66 /* B */, 8192 /* Meta */ | 66 /* B */, roosterjs_editor_api_1.toggleBold), createCommand(4096 /* Ctrl */ | 73 /* I */, 8192 /* Meta */ | 73 /* I */, roosterjs_editor_api_1.toggleItalic), createCommand(4096 /* Ctrl */ | 85 /* U */, 8192 /* Meta */ | 85 /* U */, roosterjs_editor_api_1.toggleUnderline), createCommand(4096 /* Ctrl */ | 32 /* SPACE */, 8192 /* Meta */ | 32 /* SPACE */, roosterjs_editor_api_1.clearFormat), createCommand(4096 /* Ctrl */ | 90 /* Z */, 8192 /* Meta */ | 90 /* Z */, function (editor) { return editor.undo(); }), createCommand(18 /* ALT */ | 8 /* BACKSPACE */, 18 /* ALT */ | 8 /* BACKSPACE */, function (editor) { return editor.undo(); }, roosterjs_editor_dom_1.Browser.isMac /* Option+Backspace to be handled by browsers on Mac */), createCommand(4096 /* Ctrl */ | 89 /* Y */, 8192 /* Meta */ | 16384 /* Shift */ | 90 /* Z */, function (editor) { return editor.redo(); }), createCommand(4096 /* Ctrl */ | 190 /* PERIOD */, 8192 /* Meta */ | 190 /* PERIOD */, roosterjs_editor_api_1.toggleBullet), createCommand(4096 /* Ctrl */ | 191 /* FORWARD_SLASH */, 8192 /* Meta */ | 191 /* FORWARD_SLASH */, roosterjs_editor_api_1.toggleNumbering), createCommand(4096 /* Ctrl */ | 16384 /* Shift */ | 190 /* PERIOD */, 8192 /* Meta */ | 16384 /* Shift */ | 190 /* PERIOD */, function (editor) { return (0, roosterjs_editor_api_1.changeFontSize)(editor, 0 /* Increase */); }), createCommand(4096 /* Ctrl */ | 16384 /* Shift */ | 188 /* COMMA */, 8192 /* Meta */ | 16384 /* Shift */ | 188 /* COMMA */, function (editor) { return (0, roosterjs_editor_api_1.changeFontSize)(editor, 1 /* Decrease */); }), ].filter(function (command) { return !!command; }); /** * DefaultShortcut edit feature, provides shortcuts for the following features: * Ctrl/Meta+B: toggle bold style * Ctrl/Meta+I: toggle italic style * Ctrl/Meta+U: toggle underline style * Ctrl/Meta+Space: clear formatting * Alt+Backspace: undo * Ctrl/Meta+Z: undo * Ctrl+Y/Meta+Shift+Z: redo * Ctrl/Meta+PERIOD: toggle bullet list * Ctrl/Meta+/: toggle numbering list * Ctrl/Meta+Shift+>: increase font size * Ctrl/Meta+Shift+<: decrease font size */ var DefaultShortcut = { allowFunctionKeys: true, keys: [ 66 /* B */, 73 /* I */, 85 /* U */, 89 /* Y */, 90 /* Z */, 188 /* COMMA */, 190 /* PERIOD */, 191 /* FORWARD_SLASH */, 32 /* SPACE */, 8 /* BACKSPACE */, ], shouldHandleEvent: cacheGetCommand, handleEvent: function (event, editor) { var command = cacheGetCommand(event); if (command) { command.action(editor); event.rawEvent.preventDefault(); event.rawEvent.stopPropagation(); } }, }; function cacheGetCommand(event) { return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'DEFAULT_SHORT_COMMAND', function () { var e = event.rawEvent; var key = // Need to check AltGraph isn't being pressed since some languages (e.g. Polski) use AltGr // to input some special characters. In that case, ctrlKey and altKey are both true in Edge, // but we should not trigger any shortcut function here. However, we still want to capture // the ALT+BACKSPACE combination. event.eventType == 0 /* KeyDown */ && !e.getModifierState('AltGraph') ? e.which | (e.metaKey && 8192 /* Meta */) | (e.shiftKey && 16384 /* Shift */) | (e.ctrlKey && 4096 /* Ctrl */) | (e.altKey && 18 /* ALT */) : 0; return key && commands.filter(function (cmd) { return (roosterjs_editor_dom_1.Browser.isMac ? cmd.macKey : cmd.winKey) == key; })[0]; }); } /** * @internal */ exports.ShortcutFeatures = { defaultShortcut: DefaultShortcut, }; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/structuredNodeFeatures.ts": /*!******************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/structuredNodeFeatures.ts ***! \******************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StructuredNodeFeatures = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var CHILD_PARENT_TAG_MAP = { TD: 'TABLE', TH: 'TABLE', LI: 'OL,UL', }; var CHILD_SELECTOR = (0, roosterjs_editor_dom_1.getObjectKeys)(CHILD_PARENT_TAG_MAP).join(','); /** * InsertLineBeforeStructuredNode edit feature, provides the ability to insert an empty line before * a structured element (bullet/numbering list, blockquote, table) if the element is at beginning of * document */ var InsertLineBeforeStructuredNodeFeature = { keys: [13 /* ENTER */], shouldHandleEvent: cacheGetStructuredElement, handleEvent: function (event, editor) { var element = cacheGetStructuredElement(event, editor); var div = (0, roosterjs_editor_dom_1.createElement)(1 /* EmptyLine */, editor.getDocument()); editor.addUndoSnapshot(function () { element.parentNode.insertBefore(div, element); // Select the new line when we are in table. This is the same behavior with Word if ((0, roosterjs_editor_dom_1.getTagOfNode)(element) == 'TABLE') { editor.select(new roosterjs_editor_dom_1.Position(div, 0 /* Begin */).normalize()); } }); event.rawEvent.preventDefault(); }, defaultDisabled: true, }; function cacheGetStructuredElement(event, editor) { return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'FIRST_STRUCTURE', function () { // Provide a chance to keep browser default behavior by pressing SHIFT var element = event.rawEvent.shiftKey ? null : editor.getElementAtCursor(CHILD_SELECTOR); if (element) { var range = editor.getSelectionRange(); if (range && range.collapsed && (0, roosterjs_editor_dom_1.isPositionAtBeginningOf)(roosterjs_editor_dom_1.Position.getStart(range), element) && !editor.getBodyTraverser(element).getPreviousBlockElement()) { return editor.getElementAtCursor(CHILD_PARENT_TAG_MAP[(0, roosterjs_editor_dom_1.getTagOfNode)(element)]); } } return null; }); } /** * @internal */ exports.StructuredNodeFeatures = { insertLineBeforeStructuredNodeFeature: InsertLineBeforeStructuredNodeFeature, }; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/tableFeatures.ts": /*!*********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/tableFeatures.ts ***! \*********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TableFeatures = void 0; var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * TabInTable edit feature, provides the ability to jump between cells when user press TAB in table */ var TabInTable = { keys: [9 /* TAB */], shouldHandleEvent: function (event, editor) { return cacheGetTableCell(event, editor) && !cacheIsWholeTableSelected(event, editor); }, handleEvent: function (event, editor) { var shift = event.rawEvent.shiftKey; var td = cacheGetTableCell(event, editor); var vtable = cacheVTable(event, td); for (var step = shift ? -1 : 1, row = vtable.row, col = vtable.col + step;; col += step) { if (col < 0 || col >= vtable.cells[row].length) { row += step; if (row < 0) { editor.select(vtable.table, -2 /* Before */); break; } else if (row >= vtable.cells.length) { (0, roosterjs_editor_api_1.editTable)(editor, 1 /* InsertBelow */); break; } col = shift ? vtable.cells[row].length - 1 : 0; } var cell = vtable.getCell(row, col); if (cell.td) { editor.select(cell.td, 0 /* Begin */); break; } } event.rawEvent.preventDefault(); }, }; /** * IndentTableOnTab edit feature, provides the ability to indent the table if it is all cells are selected. */ var IndentTableOnTab = { keys: [9 /* TAB */], shouldHandleEvent: function (event, editor) { return cacheGetTableCell(event, editor) && cacheIsWholeTableSelected(event, editor); }, handleEvent: function (event, editor) { event.rawEvent.preventDefault(); editor.addUndoSnapshot(function () { var shift = event.rawEvent.shiftKey; var selection = editor.getSelectionRangeEx(); var td = cacheGetTableCell(event, editor); var vtable = cacheVTable(event, td); if (shift && editor.getElementAtCursor('blockquote', vtable.table, event)) { (0, roosterjs_editor_api_1.setIndentation)(editor, 1 /* Decrease */); } else if (!shift) { (0, roosterjs_editor_api_1.setIndentation)(editor, 0 /* Increase */); } editor.select(selection.table, selection.coordinates); }); }, }; /** * UpDownInTable edit feature, provides the ability to jump to cell above/below when user press UP/DOWN * in table */ var UpDownInTable = { keys: [38 /* UP */, 40 /* DOWN */], shouldHandleEvent: function (event, editor) { return cacheGetTableCell(event, editor) && !cacheIsWholeTableSelected(event, editor); }, handleEvent: function (event, editor) { var _a; var td = cacheGetTableCell(event, editor); var vtable = new roosterjs_editor_dom_1.VTable(td); var isUp = event.rawEvent.which == 38 /* UP */; var step = isUp ? -1 : 1; var hasShiftKey = event.rawEvent.shiftKey; var selection = (_a = editor.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.getSelection(); var targetTd = null; if (selection) { var anchorNode_1 = selection.anchorNode, anchorOffset_1 = selection.anchorOffset; for (var row = vtable.row; row >= 0 && row < vtable.cells.length; row += step) { var cell = vtable.getCell(row, vtable.col); if (cell.td && cell.td != td) { targetTd = cell.td; break; } } editor.runAsync(function (editor) { var _a; var newContainer = editor.getElementAtCursor(); if ((0, roosterjs_editor_dom_1.contains)(vtable.table, newContainer) && !(0, roosterjs_editor_dom_1.contains)(td, newContainer, true /*treatSameNodeAsContain*/)) { var newPos = targetTd ? new roosterjs_editor_dom_1.Position(targetTd, 0 /* Begin */) : new roosterjs_editor_dom_1.Position(vtable.table, isUp ? -2 /* Before */ : -3 /* After */); if (hasShiftKey) { newPos = newPos.node.nodeType == 1 /* Element */ && (0, roosterjs_editor_dom_1.isVoidHtmlElement)(newPos.node) ? new roosterjs_editor_dom_1.Position(newPos.node, newPos.isAtEnd ? -3 /* After */ : -2 /* Before */) : newPos; var selection_1 = (_a = editor.getDocument().defaultView) === null || _a === void 0 ? void 0 : _a.getSelection(); selection_1 === null || selection_1 === void 0 ? void 0 : selection_1.setBaseAndExtent(anchorNode_1, anchorOffset_1, newPos.node, newPos.offset); } else { editor.select(newPos); } } }); } }, defaultDisabled: !roosterjs_editor_dom_1.Browser.isChrome && !roosterjs_editor_dom_1.Browser.isSafari, }; function cacheGetTableCell(event, editor) { return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'TABLE_CELL_FOR_TABLE_FEATURES', function () { var pos = editor.getFocusedPosition(); var firstTd = pos && editor.getElementAtCursor('TD,TH,LI', pos.node); return (firstTd && ((0, roosterjs_editor_dom_1.getTagOfNode)(firstTd) == 'LI' ? null : firstTd)); }); } function cacheIsWholeTableSelected(event, editor) { return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'WHOLE_TABLE_SELECTED_FOR_FEATURES', function () { var td = cacheGetTableCell(event, editor); var vtable = cacheVTable(event, td); var selection = editor.getSelectionRangeEx(); return (selection.type == 1 /* TableSelection */ && (0, roosterjs_editor_dom_1.isWholeTableSelected)(vtable, selection.coordinates)); }); } function cacheVTable(event, td) { return (0, roosterjs_editor_dom_1.cacheGetEventData)(event, 'VTABLE_FOR_TABLE_FEATURES', function () { return new roosterjs_editor_dom_1.VTable(td); }); } /** * @internal */ exports.TableFeatures = { tabInTable: TabInTable, upDownInTable: UpDownInTable, indentTableOnTab: IndentTableOnTab, }; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/textFeatures.ts": /*!********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/textFeatures.ts ***! \********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TextFeatures = void 0; var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var TAB_SPACES = 6; /** * Requires @see ExperimentalFeatures.TabKeyTextFeatures to be enabled * Provides additional functionality when press Tab: * If Whole Paragraph selected, indent paragraph, * If range is collapsed, add tab spaces * If range is not collapsed but not all the paragraph is selected, replace selection with Tab spaces * If there are more than one block in the selection, indent all selection */ var IndentWhenTabText = { keys: [9 /* TAB */], shouldHandleEvent: function (event, editor) { if (editor.isFeatureEnabled("TabKeyTextFeatures" /* TabKeyTextFeatures */) && !event.rawEvent.shiftKey) { var activeElement = editor.getDocument().activeElement; var listOrTable = editor.getElementAtCursor('LI,TABLE', null /*startFrom*/, event); var entity = editor.getElementAtCursor((0, roosterjs_editor_dom_1.getEntitySelector)(), undefined /*startFrom*/, event); return (!listOrTable && (entity ? entity.isContentEditable : activeElement.isContentEditable)); } return false; }, handleEvent: function (event, editor) { var selection = editor.getSelectionRangeEx(); if (selection.type == 0 /* Normal */) { editor.addUndoSnapshot(function () { if (selection.areAllCollapsed) { insertTab(editor, event); } else { var ranges = selection.ranges; var range = ranges[0]; if (shouldSetIndentation(editor, range)) { (0, roosterjs_editor_api_1.setIndentation)(editor, 0 /* Increase */); } else { var tempRange = (0, roosterjs_editor_dom_1.createRange)(range.startContainer, range.startOffset); ranges.forEach(function (range) { return range.deleteContents(); }); editor.select(tempRange); insertTab(editor, event); } } }); event.rawEvent.preventDefault(); } }, }; /** * Requires @see ExperimentalFeatures.TabKeyTextFeatures to be enabled * If Whole Paragraph selected, outdent paragraph on Tab press */ var OutdentWhenTabText = { keys: [9 /* TAB */], shouldHandleEvent: function (event, editor) { if (event.rawEvent.shiftKey && editor.isFeatureEnabled("TabKeyTextFeatures" /* TabKeyTextFeatures */)) { var selection = editor.getSelectionRangeEx(); return (selection.type == 0 /* Normal */ && !selection.areAllCollapsed && editor.getElementAtCursor('blockquote', null, event) && !editor.getElementAtCursor('LI,TABLE', null /*startFrom*/, event) && shouldSetIndentation(editor, selection.ranges[0])); } return false; }, handleEvent: function (event, editor) { editor.addUndoSnapshot(function () { return (0, roosterjs_editor_api_1.setIndentation)(editor, 1 /* Decrease */); }); event.rawEvent.preventDefault(); }, }; /** * @deprecated * Automatically transform -- into hyphen, if typed between two words. */ var AutoHyphen = { keys: [], shouldHandleEvent: function (event, editor) { return false; }, handleEvent: function (event, editor) { return false; }, defaultDisabled: true, }; /** * @internal */ exports.TextFeatures = { indentWhenTabText: IndentWhenTabText, outdentWhenTabText: OutdentWhenTabText, autoHyphen: AutoHyphen, }; function shouldSetIndentation(editor, range) { var result = false; var startPosition = roosterjs_editor_dom_1.Position.getStart(range); var endPosition = roosterjs_editor_dom_1.Position.getEnd(range); var firstBlock = editor.getBlockElementAtNode(startPosition.node); var lastBlock = editor.getBlockElementAtNode(endPosition.node); if (!firstBlock || !lastBlock) { return false; } if (!firstBlock.equals(lastBlock)) { //If the selections has more than one block, we indent all the blocks in the selection return true; } else { //We only indent a single block if all the block is selected. var blockStart = new roosterjs_editor_dom_1.Position(firstBlock.getStartNode(), 0 /* Begin */); var blockEnd = new roosterjs_editor_dom_1.Position(firstBlock.getEndNode(), -1 /* End */); var rangeBefore = (0, roosterjs_editor_dom_1.createRange)(blockStart, roosterjs_editor_dom_1.Position.getStart(range)); var rangeAfter = (0, roosterjs_editor_dom_1.createRange)(roosterjs_editor_dom_1.Position.getEnd(range), blockEnd); if (!result && isRangeEmpty(rangeBefore) && isRangeEmpty(rangeAfter)) { result = true; } return result; } } function isRangeEmpty(range) { return (range.toString() == '' && (0, roosterjs_editor_dom_1.queryElements)(range.commonAncestorContainer, 'img,table,ul,ol', null, 2 /* InSelection */, range).length == 0); } function insertTab(editor, event) { var span = editor.getDocument().createElement('span'); var searcher = editor.getContentSearcherOfCursor(event); var charsBefore = searcher.getSubStringBefore(Number.MAX_SAFE_INTEGER); var numberOfChars = TAB_SPACES - (charsBefore.length % TAB_SPACES); var span2; var textContent = ''; for (var index = 0; index < numberOfChars; index++) { textContent += ' '; } editor.insertNode(span); if (span.nextElementSibling && (0, roosterjs_editor_dom_1.getTagOfNode)(span.nextElementSibling) == 'A') { span2 = editor.getDocument().createElement('span'); span2.textContent = ' '; editor.insertNode(span2); editor.select((0, roosterjs_editor_dom_1.createRange)(span2, -2 /* Before */)); } editor.insertContent(textContent, { position: 5 /* Range */, range: (0, roosterjs_editor_dom_1.createRange)(span, 0 /* Begin */), updateCursor: false, }); editor.select((0, roosterjs_editor_dom_1.createRange)(span, -3 /* After */)); if (span2) { editor.deleteNode(span2); } } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/getAllFeatures.ts": /*!*************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/getAllFeatures.ts ***! \*************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); var autoLinkFeatures_1 = __webpack_require__(/*! ./features/autoLinkFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/autoLinkFeatures.ts"); var cursorFeatures_1 = __webpack_require__(/*! ./features/cursorFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/cursorFeatures.ts"); var entityFeatures_1 = __webpack_require__(/*! ./features/entityFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/entityFeatures.ts"); var listFeatures_1 = __webpack_require__(/*! ./features/listFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/listFeatures.ts"); var markdownFeatures_1 = __webpack_require__(/*! ./features/markdownFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/markdownFeatures.ts"); var quoteFeatures_1 = __webpack_require__(/*! ./features/quoteFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/quoteFeatures.ts"); var shortcutFeatures_1 = __webpack_require__(/*! ./features/shortcutFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/shortcutFeatures.ts"); var structuredNodeFeatures_1 = __webpack_require__(/*! ./features/structuredNodeFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/structuredNodeFeatures.ts"); var tableFeatures_1 = __webpack_require__(/*! ./features/tableFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/tableFeatures.ts"); var textFeatures_1 = __webpack_require__(/*! ./features/textFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/textFeatures.ts"); var allFeatures = __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, listFeatures_1.ListFeatures), quoteFeatures_1.QuoteFeatures), tableFeatures_1.TableFeatures), structuredNodeFeatures_1.StructuredNodeFeatures), autoLinkFeatures_1.AutoLinkFeatures), shortcutFeatures_1.ShortcutFeatures), cursorFeatures_1.CursorFeatures), markdownFeatures_1.MarkdownFeatures), entityFeatures_1.EntityFeatures), textFeatures_1.TextFeatures); /** * Get all content edit features provided by roosterjs */ function getAllFeatures() { return allFeatures; } exports.default = getAllFeatures; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/index.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/index.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAllFeatures = exports.ContentEdit = void 0; var ContentEdit_1 = __webpack_require__(/*! ./ContentEdit */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/ContentEdit.ts"); Object.defineProperty(exports, "ContentEdit", { enumerable: true, get: function () { return ContentEdit_1.default; } }); var getAllFeatures_1 = __webpack_require__(/*! ./getAllFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/getAllFeatures.ts"); Object.defineProperty(exports, "getAllFeatures", { enumerable: true, get: function () { return getAllFeatures_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/utils/convertAlphaToDecimals.ts": /*!***************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/utils/convertAlphaToDecimals.ts ***! \***************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * @internal * Convert english alphabet numbers into decimal numbers * @param letter The letter that needs to be converted * @returns */ function convertAlphaToDecimals(letter) { var alpha = letter.toLocaleLowerCase(); if (alpha) { var size = alpha.length - 1; var number = 26 * size + alpha.charCodeAt(size) - 96; return number; } return null; } exports.default = convertAlphaToDecimals; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/utils/getAutoBulletListStyle.ts": /*!***************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/utils/getAutoBulletListStyle.ts ***! \***************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var bulletListType = { '*': 1 /* Disc */, '-': 2 /* Dash */, '--': 3 /* Square */, '->': 5 /* LongArrow */, '-->': 8 /* DoubleLongArrow */, '=>': 6 /* UnfilledArrow */, '>': 4 /* ShortArrow */, '—': 7 /* Hyphen */, }; var identifyBulletListType = function (bullet) { return bulletListType[bullet] || null; }; /** * @internal * @param textBeforeCursor The trigger character * @returns The style of a bullet list triggered by a string */ function getAutoBulletListStyle(textBeforeCursor) { var trigger = textBeforeCursor.trim(); var bulletType = identifyBulletListType(trigger); return bulletType; } exports.default = getAutoBulletListStyle; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/utils/getAutoNumberingListStyle.ts": /*!******************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/utils/getAutoNumberingListStyle.ts ***! \******************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var _a, _b, _c, _d, _e, _f; Object.defineProperty(exports, "__esModule", { value: true }); var convertAlphaToDecimals_1 = __webpack_require__(/*! ./convertAlphaToDecimals */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/utils/convertAlphaToDecimals.ts"); var characters = { '.': 1 /* Dot */, '-': 2 /* Dash */, ')': 3 /* Parenthesis */, }; var lowerRomanTypes = [ 13 /* LowerRoman */, 16 /* LowerRomanDash */, 15 /* LowerRomanDoubleParenthesis */, 14 /* LowerRomanParenthesis */, ]; var upperRomanTypes = [ 17 /* UpperRoman */, 20 /* UpperRomanDash */, 19 /* UpperRomanDoubleParenthesis */, 18 /* UpperRomanParenthesis */, ]; var numberingTriggers = ['1', 'a', 'A', 'I', 'i']; var lowerRomanNumbers = ['i', 'v', 'x', 'l', 'c', 'd', 'm']; var upperRomanNumbers = ['I', 'V', 'X', 'L', 'C', 'D', 'M']; var identifyNumberingType = function (text, previousListStyle) { if (!isNaN(parseInt(text))) { return 1 /* Decimal */; } else if (/[a-z]+/g.test(text)) { if ((lowerRomanTypes.indexOf(previousListStyle) > -1 && lowerRomanNumbers.indexOf(text[0]) > -1) || (!previousListStyle && text === 'i')) { return 4 /* LowerRoman */; } else if (previousListStyle || (!previousListStyle && text === 'a')) { return 2 /* LowerAlpha */; } } else if (/[A-Z]+/g.test(text)) { if ((upperRomanTypes.indexOf(previousListStyle) > -1 && upperRomanNumbers.indexOf(text[0]) > -1) || (!previousListStyle && text === 'I')) { return 5 /* UpperRoman */; } else if (previousListStyle || (!previousListStyle && text === 'A')) { return 3 /* UpperAlpha */; } } }; var numberingListTypes = (_a = {}, _a[1 /* Decimal */] = function (char) { return DecimalsTypes[char] || null; }, _a[2 /* LowerAlpha */] = function (char) { return LowerAlphaTypes[char] || null; }, _a[3 /* UpperAlpha */] = function (char) { return UpperAlphaTypes[char] || null; }, _a[4 /* LowerRoman */] = function (char) { return LowerRomanTypes[char] || null; }, _a[5 /* UpperRoman */] = function (char) { return UpperRomanTypes[char] || null; }, _a); var UpperRomanTypes = (_b = {}, _b[1 /* Dot */] = 17 /* UpperRoman */, _b[2 /* Dash */] = 20 /* UpperRomanDash */, _b[3 /* Parenthesis */] = 18 /* UpperRomanParenthesis */, _b[4 /* DoubleParenthesis */] = 19 /* UpperRomanDoubleParenthesis */, _b); var LowerRomanTypes = (_c = {}, _c[1 /* Dot */] = 13 /* LowerRoman */, _c[2 /* Dash */] = 16 /* LowerRomanDash */, _c[3 /* Parenthesis */] = 14 /* LowerRomanParenthesis */, _c[4 /* DoubleParenthesis */] = 15 /* LowerRomanDoubleParenthesis */, _c); var UpperAlphaTypes = (_d = {}, _d[1 /* Dot */] = 9 /* UpperAlpha */, _d[2 /* Dash */] = 12 /* UpperAlphaDash */, _d[3 /* Parenthesis */] = 10 /* UpperAlphaParenthesis */, _d[4 /* DoubleParenthesis */] = 11 /* UpperAlphaDoubleParenthesis */, _d); var LowerAlphaTypes = (_e = {}, _e[1 /* Dot */] = 5 /* LowerAlpha */, _e[2 /* Dash */] = 8 /* LowerAlphaDash */, _e[3 /* Parenthesis */] = 6 /* LowerAlphaParenthesis */, _e[4 /* DoubleParenthesis */] = 7 /* LowerAlphaDoubleParenthesis */, _e); var DecimalsTypes = (_f = {}, _f[1 /* Dot */] = 1 /* Decimal */, _f[2 /* Dash */] = 2 /* DecimalDash */, _f[3 /* Parenthesis */] = 3 /* DecimalParenthesis */, _f[4 /* DoubleParenthesis */] = 4 /* DecimalDoubleParenthesis */, _f); var identifyNumberingListType = function (numbering, isDoubleParenthesis, previousListStyle) { var separatorCharacter = isDoubleParenthesis ? 4 /* DoubleParenthesis */ : characters[numbering[numbering.length - 1]]; // if separator is not valid, no need to check if the number is valid. if (separatorCharacter) { var number = isDoubleParenthesis ? numbering.slice(1, -1) : numbering.slice(0, -1); var numberingType = identifyNumberingType(number, previousListStyle); return numberingType ? numberingListTypes[numberingType](separatorCharacter) : null; } return null; }; /** * @internal * @param textBeforeCursor The trigger character * @param previousListChain @optional This parameters is used to keep the list chain, if the is not a new list * @param previousListStyle @optional The list style of the previous list * @returns The style of a numbering list triggered by a string */ function getAutoNumberingListStyle(textBeforeCursor, previousListChain, previousListStyle) { var _a; var trigger = textBeforeCursor.trim(); var isDoubleParenthesis = trigger[0] === '(' && trigger[trigger.length - 1] === ')'; //Only the staring items ['1', 'a', 'A', 'I', 'i'] must trigger a new list. All the other triggers is used to keep the list chain. //The index is always the characters before the last character var listIndex = isDoubleParenthesis ? trigger.slice(1, -1) : trigger.slice(0, -1); var indexNumber = parseInt(listIndex); var index = !isNaN(indexNumber) ? indexNumber : (0, convertAlphaToDecimals_1.default)(listIndex); if (!index || index < 1) { return null; } if (previousListChain && index > 1) { if ((previousListChain.length < 1 && numberingTriggers.indexOf(listIndex) < 0) || ((previousListChain === null || previousListChain === void 0 ? void 0 : previousListChain.length) > 0 && !((_a = previousListChain[previousListChain.length - 1]) === null || _a === void 0 ? void 0 : _a.canAppendAtCursor(index)))) { return null; } } var numberingType = isValidNumbering(listIndex) ? identifyNumberingListType(trigger, isDoubleParenthesis, previousListStyle) : null; return numberingType; } exports.default = getAutoNumberingListStyle; /** * Check if index has only numbers or only letters to avoid sequence of character such 1:1. trigger a list. * @param index * @returns */ function isValidNumbering(index) { return Number(index) || /^[A-Za-z\s]*$/.test(index); } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContextMenu/ContextMenu.ts": /*!**********************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContextMenu/ContextMenu.ts ***! \**********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * An editor plugin that support showing a context menu using render() function from options parameter */ var ContextMenu = /** @class */ (function () { /** * Create a new instance of ContextMenu class * @param options An options object to determine how to show/hide the context menu */ function ContextMenu(options) { var _this = this; this.options = options; this.container = null; this.editor = null; this.isMenuShowing = false; this.onDismiss = function () { var _a, _b; if (_this.container && _this.isMenuShowing) { (_b = (_a = _this.options).dismiss) === null || _b === void 0 ? void 0 : _b.call(_a, _this.container); _this.isMenuShowing = false; } }; } /** * Get a friendly name of this plugin */ ContextMenu.prototype.getName = function () { return 'ContextMenu'; }; /** * Initialize this plugin * @param editor The editor instance */ ContextMenu.prototype.initialize = function (editor) { this.editor = editor; }; /** * Dispose this plugin */ ContextMenu.prototype.dispose = function () { var _a; this.onDismiss(); if ((_a = this.container) === null || _a === void 0 ? void 0 : _a.parentNode) { this.container.parentNode.removeChild(this.container); this.container = null; } this.editor = null; }; /** * Handle events triggered from editor * @param event PluginEvent object */ ContextMenu.prototype.onPluginEvent = function (event) { if (event.eventType == 16 /* ContextMenu */ && event.items.length > 0) { var rawEvent = event.rawEvent, items = event.items; this.onDismiss(); if (!this.options.allowDefaultMenu) { rawEvent.preventDefault(); } if (this.initContainer(rawEvent.pageX, rawEvent.pageY)) { this.options.render(this.container, items, this.onDismiss); this.isMenuShowing = true; } } }; ContextMenu.prototype.initContainer = function (x, y) { var _a, _b; if (!this.container && this.editor) { this.container = (0, roosterjs_editor_dom_1.createElement)(5 /* ContextMenuWrapper */, this.editor.getDocument()); this.editor.getDocument().body.appendChild(this.container); } (_a = this.container) === null || _a === void 0 ? void 0 : _a.style.setProperty('left', x + 'px'); (_b = this.container) === null || _b === void 0 ? void 0 : _b.style.setProperty('top', y + 'px'); return !!this.container; }; return ContextMenu; }()); exports.default = ContextMenu; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContextMenu/index.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContextMenu/index.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ContextMenu = void 0; var ContextMenu_1 = __webpack_require__(/*! ./ContextMenu */ "./packages/roosterjs-editor-plugins/lib/plugins/ContextMenu/ContextMenu.ts"); Object.defineProperty(exports, "ContextMenu", { enumerable: true, get: function () { return ContextMenu_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/CustomReplace/CustomReplace.ts": /*!**************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/CustomReplace/CustomReplace.ts ***! \**************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var makeReplacement = function (sourceString, replacementHTML, matchSourceCaseSensitive, shouldReplace) { return ({ sourceString: sourceString, replacementHTML: replacementHTML, matchSourceCaseSensitive: matchSourceCaseSensitive, shouldReplace: shouldReplace, }); }; var defaultReplacements = [ makeReplacement(':)', '🙂', true), makeReplacement(';)', '😉', true), makeReplacement(':O', '😲', true), makeReplacement(':o', '😯', true), makeReplacement('<3', '❤️', true), ]; /** * Wrapper for CustomReplaceContentEditFeature that provides an API for updating the * content edit feature */ var CustomReplacePlugin = /** @class */ (function () { /** * Create instance of CustomReplace plugin * @param replacements Replacement rules. If not passed, a default replacement rule set will be applied */ function CustomReplacePlugin(replacements) { if (replacements === void 0) { replacements = defaultReplacements; } this.longestReplacementLength = null; this.editor = null; this.replacements = null; this.replacementEndCharacters = null; this.updateReplacements(replacements); } /** * Set the replacements that this plugin is looking for. * @param newReplacements new set of replacements for this plugin */ CustomReplacePlugin.prototype.updateReplacements = function (newReplacements) { this.replacements = newReplacements; this.longestReplacementLength = getLongestReplacementSourceLength(this.replacements); this.replacementEndCharacters = getReplacementEndCharacters(this.replacements); }; /** * Get a friendly name of this plugin */ CustomReplacePlugin.prototype.getName = function () { return 'CustomReplace'; }; /** * Initialize this plugin * @param editor The editor instance */ CustomReplacePlugin.prototype.initialize = function (editor) { this.editor = editor; }; /** * Dispose this plugin */ CustomReplacePlugin.prototype.dispose = function () { this.editor = null; }; /** * Handle events triggered from editor * @param event PluginEvent object */ CustomReplacePlugin.prototype.onPluginEvent = function (event) { var _this = this; var _a; if (event.eventType != 3 /* Input */ || !this.editor || this.editor.isInIME()) { return; } // Exit early on input events that do not insert a replacement's final character. if (!event.rawEvent.data || !((_a = this.replacementEndCharacters) === null || _a === void 0 ? void 0 : _a.has(event.rawEvent.data))) { return; } // Get the matching replacement var searcher = this.editor.getContentSearcherOfCursor(event); if (!searcher || this.longestReplacementLength == null) { return; } var stringToSearch = searcher.getSubStringBefore(this.longestReplacementLength); var replacement = this.getMatchingReplacement(stringToSearch); if (!replacement || (replacement.shouldReplace && searcher && !replacement.shouldReplace(replacement, searcher.getWordBefore(), this.editor))) { return; } // Reconstruct a selection of the text on the document that matches the // replacement we selected. var matchingText = searcher.getSubStringBefore(replacement.sourceString.length); var matchingRange = searcher.getRangeFromText(matchingText, true /* exactMatch */); // parse the html string off the dom and inline the resulting element. var document = this.editor.getDocument(); var parsingSpan = document.createElement('span'); parsingSpan.innerHTML = this.editor.getTrustedHTMLHandler()(replacement.replacementHTML); var nodeToInsert = parsingSpan.childNodes.length == 1 ? parsingSpan.childNodes[0] : parsingSpan; // Switch the node for the selection range if (matchingRange) { this.editor.addUndoSnapshot(function () { var _a; matchingRange.deleteContents(); matchingRange.insertNode(nodeToInsert); (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.select(nodeToInsert, -1 /* End */); }, undefined /*changeSource*/, true /*canUndoByBackspace*/); } }; CustomReplacePlugin.prototype.getMatchingReplacement = function (stringToSearch) { if (stringToSearch.length == 0 || !this.replacements) { return null; } var originalStringToSearch = stringToSearch.replace(/\s/g, ' '); var lowerCaseStringToSearch = originalStringToSearch.toLocaleLowerCase(); for (var _i = 0, _a = this.replacements; _i < _a.length; _i++) { var replacement = _a[_i]; var _b = replacement.matchSourceCaseSensitive ? [originalStringToSearch, replacement.sourceString] : [lowerCaseStringToSearch, replacement.sourceString.toLocaleLowerCase()], sourceMatch = _b[0], replacementMatch = _b[1]; if (sourceMatch.substring(sourceMatch.length - replacementMatch.length) == replacementMatch) { return replacement; } } return null; }; return CustomReplacePlugin; }()); exports.default = CustomReplacePlugin; function getLongestReplacementSourceLength(replacements) { return Math.max.apply(null, replacements.map(function (replacement) { return replacement.sourceString.length; })); } function getReplacementEndCharacters(replacements) { var endChars = new Set(); for (var _i = 0, replacements_1 = replacements; _i < replacements_1.length; _i++) { var replacement = replacements_1[_i]; var sourceString = replacement.sourceString; if (sourceString.length == 0) { continue; } var lastChar = sourceString[sourceString.length - 1]; if (!replacement.matchSourceCaseSensitive) { endChars.add(lastChar.toLocaleLowerCase()); endChars.add(lastChar.toLocaleUpperCase()); } else { endChars.add(lastChar); } } return endChars; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/CustomReplace/index.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/CustomReplace/index.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CustomReplace = void 0; var CustomReplace_1 = __webpack_require__(/*! ./CustomReplace */ "./packages/roosterjs-editor-plugins/lib/plugins/CustomReplace/CustomReplace.ts"); Object.defineProperty(exports, "CustomReplace", { enumerable: true, get: function () { return CustomReplace_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/CutPasteListChain/CutPasteListChain.ts": /*!**********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/CutPasteListChain/CutPasteListChain.ts ***! \**********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * Maintain list numbers of list chain when content is modified by cut/paste/drag&drop */ var CutPasteListChain = /** @class */ (function () { function CutPasteListChain() { var _this = this; this.chains = null; this.expectedChangeSource = null; this.editor = null; this.disposer = null; this.onDrop = function () { _this.cacheListChains("Drop" /* Drop */); }; } /** * Get a friendly name of this plugin */ CutPasteListChain.prototype.getName = function () { return 'CutPasteListChain'; }; /** * Initialize this plugin * @param editor The editor instance */ CutPasteListChain.prototype.initialize = function (editor) { this.editor = editor; this.disposer = this.editor.addDomEventHandler('drop', this.onDrop); }; /** * Dispose this plugin */ CutPasteListChain.prototype.dispose = function () { var _a; (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this); this.disposer = null; this.editor = null; }; /** * Handle events triggered from editor * @param event PluginEvent object */ CutPasteListChain.prototype.onPluginEvent = function (event) { switch (event.eventType) { case 9 /* BeforeCutCopy */: if (event.isCut) { this.cacheListChains("Cut" /* Cut */); } break; case 10 /* BeforePaste */: this.cacheListChains("Paste" /* Paste */); break; case 7 /* ContentChanged */: if (this.chains && this.chains.length > 0 && this.expectedChangeSource == event.source && this.editor) { (0, roosterjs_editor_api_1.commitListChains)(this.editor, this.chains); this.chains = null; this.expectedChangeSource = null; } break; } }; CutPasteListChain.prototype.cacheListChains = function (source) { var _a; var selectedRegions = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getSelectedRegions(); if (selectedRegions) { this.chains = roosterjs_editor_dom_1.VListChain.createListChains(selectedRegions); this.expectedChangeSource = source; } }; return CutPasteListChain; }()); exports.default = CutPasteListChain; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/CutPasteListChain/index.ts": /*!**********************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/CutPasteListChain/index.ts ***! \**********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CutPasteListChain = void 0; var CutPasteListChain_1 = __webpack_require__(/*! ./CutPasteListChain */ "./packages/roosterjs-editor-plugins/lib/plugins/CutPasteListChain/CutPasteListChain.ts"); Object.defineProperty(exports, "CutPasteListChain", { enumerable: true, get: function () { return CutPasteListChain_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/HyperLink/HyperLink.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/HyperLink/HyperLink.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * An editor plugin that show a tooltip for existing link */ var HyperLink = /** @class */ (function () { /** * Create a new instance of HyperLink class * @param getTooltipCallback A callback function to get tooltip text for an existing hyperlink. * Default value is to return the href itself. If null, there will be no tooltip text. * @param target (Optional) Target window name for hyperlink. If null, will use "_blank" * @param onLinkClick (Optional) Open link callback (return false to use default behavior) */ function HyperLink(getTooltipCallback, target, onLinkClick) { var _this = this; if (getTooltipCallback === void 0) { getTooltipCallback = function (href) { return href; }; } this.getTooltipCallback = getTooltipCallback; this.target = target; this.onLinkClick = onLinkClick; this.originalHref = null; this.trackedLink = null; this.editor = null; this.disposer = null; this.onMouse = function (e) { var _a, _b; var a = (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.getElementAtCursor('a[href]', e.target); var href = a && _this.tryGetHref(a); if (href) { (_b = _this.editor) === null || _b === void 0 ? void 0 : _b.setEditorDomAttribute('title', e.type == 'mouseover' ? _this.getTooltipCallback(href, a) : null); } }; this.onBlur = function (e) { if (_this.trackedLink) { _this.updateLinkHrefIfShouldUpdate(); } _this.resetLinkTracking(); }; } /** * Get a friendly name of this plugin */ HyperLink.prototype.getName = function () { return 'Hyperlink'; }; /** * Initialize this plugin * @param editor The editor instance */ HyperLink.prototype.initialize = function (editor) { this.editor = editor; this.disposer = editor.addDomEventHandler({ mouseover: this.onMouse, mouseout: this.onMouse, blur: this.onBlur, }); }; /** * Dispose this plugin */ HyperLink.prototype.dispose = function () { if (this.disposer) { this.disposer(); this.disposer = null; } this.editor = null; }; /** * Handle events triggered from editor * @param event PluginEvent object */ HyperLink.prototype.onPluginEvent = function (event) { var _a, _b, _c; if (event.eventType == 6 /* MouseUp */ || (event.eventType == 2 /* KeyUp */ && (!this.isContentEditValue(event.rawEvent) || event.rawEvent.which == 32 /* SPACE */)) || event.eventType == 7 /* ContentChanged */) { var anchor = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getElementAtCursor('A[href]', undefined /*startFrom*/, event); var shouldCheckUpdateLink = (anchor && anchor !== this.trackedLink) || event.eventType == 2 /* KeyUp */ || event.eventType == 7 /* ContentChanged */; if (this.trackedLink && (shouldCheckUpdateLink || this.tryGetHref(this.trackedLink) !== this.originalHref)) { // If cursor has moved out of previously tracked link // update link href if display text doesn't match href anymore. if (shouldCheckUpdateLink) { this.updateLinkHrefIfShouldUpdate(); } // If the link's href value was edited, or the cursor has moved out of the // previously tracked link, stop tracking the link. this.resetLinkTracking(); } // Cache link and href value if its href attribute currently matches its display text if (!this.trackedLink && anchor && this.doesLinkDisplayMatchHref(anchor)) { this.trackedLink = anchor; this.originalHref = this.tryGetHref(anchor); } } if (event.eventType == 6 /* MouseUp */) { var anchor = (_b = this.editor) === null || _b === void 0 ? void 0 : _b.getElementAtCursor('A', event.rawEvent.srcElement); if (anchor) { if (this.onLinkClick && this.onLinkClick(anchor, event.rawEvent) !== false) { return; } var href = void 0; if ((href = this.tryGetHref(anchor)) && (0, roosterjs_editor_dom_1.isCtrlOrMetaPressed)(event.rawEvent) && event.rawEvent.button === 0) { event.rawEvent.preventDefault(); try { var target = this.target || '_blank'; var window_1 = (_c = this.editor) === null || _c === void 0 ? void 0 : _c.getDocument().defaultView; window_1 === null || window_1 === void 0 ? void 0 : window_1.open(href, target); } catch (_d) { } } } } }; /** * Try get href from an anchor element * The reason this is put in a try-catch is that * it has been seen that accessing href may throw an exception, in particular on IE/Edge */ HyperLink.prototype.tryGetHref = function (anchor) { try { return anchor ? anchor.href : null; } catch (_a) { return null; } }; /** * Determines if KeyboardEvent is meant to edit content */ HyperLink.prototype.isContentEditValue = function (event) { return ((0, roosterjs_editor_dom_1.isCharacterValue)(event) || event.which == 8 /* BACKSPACE */ || event.which == 46 /* DELETE */); }; /** * Updates the href of the tracked link if the display text doesn't match href anymore */ HyperLink.prototype.updateLinkHrefIfShouldUpdate = function () { if (this.trackedLink && !this.doesLinkDisplayMatchHref(this.trackedLink)) { this.updateLinkHref(); } }; /** * Clears the tracked link and its original href value so that it's back to default state */ HyperLink.prototype.resetLinkTracking = function () { this.trackedLink = null; this.originalHref = ''; }; /** * Compares the normalized URL of inner text of element to its href to see if they match. */ HyperLink.prototype.doesLinkDisplayMatchHref = function (element) { if (element) { var display = element.innerText.trim(); // We first escape the display text so that any text passed into the regex is not // treated as a special character. var escapedDisplay = display.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); var rule = new RegExp("^(?:https?:\\/\\/)?" + escapedDisplay + "\\/?", 'i'); var href = this.tryGetHref(element); if (href !== null) { return rule.test(href); } } return false; }; /** * Update href of an element in place to new display text if it's a valid URL */ HyperLink.prototype.updateLinkHref = function () { var _this = this; var _a; if (this.trackedLink) { var linkData_1 = (0, roosterjs_editor_dom_1.matchLink)(this.trackedLink.innerText.trim()); if (linkData_1 !== null) { (_a = this.editor) === null || _a === void 0 ? void 0 : _a.addUndoSnapshot(function () { _this.trackedLink.href = linkData_1.normalizedUrl; }); } } }; return HyperLink; }()); exports.default = HyperLink; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/HyperLink/index.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/HyperLink/index.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HyperLink = void 0; var HyperLink_1 = __webpack_require__(/*! ./HyperLink */ "./packages/roosterjs-editor-plugins/lib/plugins/HyperLink/HyperLink.ts"); Object.defineProperty(exports, "HyperLink", { enumerable: true, get: function () { return HyperLink_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/ImageEdit.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/ImageEdit.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); var applyChange_1 = __webpack_require__(/*! ./editInfoUtils/applyChange */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/applyChange.ts"); var canRegenerateImage_1 = __webpack_require__(/*! ./api/canRegenerateImage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/canRegenerateImage.ts"); var DragAndDropHelper_1 = __webpack_require__(/*! ../../pluginUtils/DragAndDropHelper */ "./packages/roosterjs-editor-plugins/lib/pluginUtils/DragAndDropHelper.ts"); var getGeneratedImageSize_1 = __webpack_require__(/*! ./editInfoUtils/getGeneratedImageSize */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getGeneratedImageSize.ts"); var Cropper_1 = __webpack_require__(/*! ./imageEditors/Cropper */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Cropper.ts"); var editInfo_1 = __webpack_require__(/*! ./editInfoUtils/editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts"); var Rotator_1 = __webpack_require__(/*! ./imageEditors/Rotator */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Rotator.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var Resizer_1 = __webpack_require__(/*! ./imageEditors/Resizer */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Resizer.ts"); var PI = Math.PI; var DIRECTIONS = 8; var DirectionRad = (PI * 2) / DIRECTIONS; var DirectionOrder = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w']; /** * Default image edit options */ var DefaultOptions = { borderColor: '#DB626C', minWidth: 10, minHeight: 10, preserveRatio: false, minRotateDeg: 5, imageSelector: 'img', rotateIconHTML: null, disableCrop: false, disableRotate: false, disableSideResize: false, onSelectState: 7 /* ResizeAndRotate */, }; /** * Map the image edit operation to a function that returns editing elements HTML to help * build image editing UI */ var ImageEditHTMLMap = (_a = {}, _a[1 /* CornerResize */] = Resizer_1.getCornerResizeHTML, _a[2 /* SideResize */] = Resizer_1.getSideResizeHTML, _a[4 /* Rotate */] = Rotator_1.getRotateHTML, _a[8 /* Crop */] = Cropper_1.getCropHTML, _a); /** * Default background colors for rotate handle */ var LIGHT_MODE_BGCOLOR = 'white'; var DARK_MODE_BGCOLOR = '#333'; /** * The biggest area of image with 4 handles */ var MAX_SMALL_SIZE_IMAGE = 10000; /** * ImageEdit plugin provides the ability to edit an inline image in editor, including image resizing, rotation and cropping */ var ImageEdit = /** @class */ (function () { /** * Create a new instance of ImageEdit * @param options Image editing options * @param onShowResizeHandle An optional callback to allow customize resize handle element of image resizing. * To customize the resize handle element, add this callback and change the attributes of elementData then it * will be picked up by ImageEdit code */ function ImageEdit(options, onShowResizeHandle) { var _this = this; this.onShowResizeHandle = onShowResizeHandle; /** * quit editing mode when editor lose focus */ this.onBlur = function () { _this.setEditingImage(null, true); }; /** * Remove the temp wrapper of the image */ this.removeWrapper = function () { if (_this.editor.contains(_this.image) && _this.wrapper) { (0, roosterjs_editor_dom_1.unwrap)(_this.image.parentNode); } _this.wrapper = null; _this.shadowSpan = null; }; /** * Update image edit elements to reflect current editing result * @param context */ this.updateWrapper = function (context) { var wrapper = _this.wrapper; if (wrapper) { // Prepare: get related editing elements var cropContainers = getEditElements(wrapper, "r_cropC" /* CropContainer */); var cropOverlays = getEditElements(wrapper, "r_cropO" /* CropOverlay */); var resizeHandles = getEditElements(wrapper, "r_resizeH" /* ResizeHandle */); var rotateCenter = getEditElements(wrapper, "r_rotateC" /* RotateCenter */)[0]; var rotateHandle = getEditElements(wrapper, "r_rotateH" /* RotateHandle */)[0]; var cropHandles = getEditElements(wrapper, "r_cropH" /* CropHandle */); // Cropping and resizing will show different UI, so check if it is cropping here first _this.isCropping = cropContainers.length == 1 && cropOverlays.length == 4; var _a = _this.editInfo, angleRad = _a.angleRad, bottomPercent = _a.bottomPercent, leftPercent = _a.leftPercent, rightPercent = _a.rightPercent, topPercent = _a.topPercent; // Width/height of the image var _b = (0, getGeneratedImageSize_1.default)(_this.editInfo, _this.isCropping), targetWidth = _b.targetWidth, targetHeight = _b.targetHeight, originalWidth = _b.originalWidth, originalHeight = _b.originalHeight, visibleWidth = _b.visibleWidth, visibleHeight = _b.visibleHeight; var marginHorizontal = (targetWidth - visibleWidth) / 2; var marginVertical = (targetHeight - visibleHeight) / 2; var cropLeftPx = originalWidth * leftPercent; var cropRightPx = originalWidth * rightPercent; var cropTopPx = originalHeight * topPercent; var cropBottomPx = originalHeight * bottomPercent; // Update size and margin of the wrapper wrapper.style.width = getPx(visibleWidth); wrapper.style.height = getPx(visibleHeight); wrapper.style.margin = marginVertical + "px " + marginHorizontal + "px"; wrapper.style.transform = "rotate(" + angleRad + "rad)"; _this.wrapper.style.width = getPx(visibleWidth); _this.wrapper.style.height = getPx(visibleHeight); // Update the text-alignment to avoid the image to overflow if the parent element have align center or right // or if the direction is Right To Left wrapper.style.textAlign = isRtl(wrapper.parentNode) ? 'right' : 'left'; // Update size of the image _this.clonedImage.style.width = getPx(originalWidth); _this.clonedImage.style.height = getPx(originalHeight); if (_this.isCropping) { // For crop, we also need to set position of the overlays setSize(cropContainers[0], cropLeftPx, cropTopPx, cropRightPx, cropBottomPx, undefined, undefined); setSize(cropOverlays[0], 0, 0, cropRightPx, undefined, undefined, cropTopPx); setSize(cropOverlays[1], undefined, 0, 0, cropBottomPx, cropRightPx, undefined); setSize(cropOverlays[2], cropLeftPx, undefined, 0, 0, undefined, cropBottomPx); setSize(cropOverlays[3], 0, cropTopPx, undefined, 0, cropLeftPx, undefined); updateHandleCursor(cropHandles, angleRad); } else { // For rotate/resize, set the margin of the image so that cropped part won't be visible _this.clonedImage.style.margin = -cropTopPx + "px 0 0 " + -cropLeftPx + "px"; // Double check resize if ((context === null || context === void 0 ? void 0 : context.elementClass) == "r_resizeH" /* ResizeHandle */) { var clientWidth = wrapper.clientWidth; var clientHeight = wrapper.clientHeight; _this.wasResized = true; (0, Resizer_1.doubleCheckResize)(_this.editInfo, _this.options.preserveRatio, clientWidth, clientHeight); _this.updateWrapper(); } (0, Rotator_1.updateRotateHandlePosition)(_this.editInfo, _this.editor.getVisibleViewport(), marginVertical, rotateCenter, rotateHandle); updateHandleCursor(resizeHandles, angleRad); } } }; this.options = __assign(__assign({}, DefaultOptions), (options || {})); this.allowedOperations = 1 /* CornerResize */ | (this.options.disableCrop ? 0 : 8 /* Crop */) | (this.options.disableRotate ? 0 : 4 /* Rotate */) | (this.options.disableSideResize ? 0 : 2 /* SideResize */); } /** * Get a friendly name of this plugin */ ImageEdit.prototype.getName = function () { return 'ImageEdit'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ ImageEdit.prototype.initialize = function (editor) { var _this = this; this.editor = editor; this.disposer = editor.addDomEventHandler({ blur: function () { return _this.onBlur; }, dragstart: function (e) { if (_this.image) { e.preventDefault(); } }, }); }; /** * Dispose this plugin */ ImageEdit.prototype.dispose = function () { this.clearDndHelpers(); this.disposer(); this.disposer = null; this.editor = null; }; /** * Handle events triggered from editor * @param e PluginEvent object */ ImageEdit.prototype.onPluginEvent = function (e) { switch (e.eventType) { case 22 /* SelectionChanged */: if (e.selectionRangeEx && e.selectionRangeEx.type === 2 /* ImageSelection */) { this.setEditingImage(e.selectionRangeEx.image, this.options.onSelectState); } break; case 5 /* MouseDown */: // When left click in a image that already in editing mode, do not quit edit mode var mouseTarget = e.rawEvent.target; var button = e.rawEvent.button; if (this.shadowSpan !== mouseTarget || (this.shadowSpan === mouseTarget && button !== 0) || this.isCropping) { this.setEditingImage(null); } break; case 0 /* KeyDown */: this.setEditingImage(null); break; case 7 /* ContentChanged */: //After contentChanged event, the current image wrapper may not be valid any more, remove all of them if any this.removeWrapper(); break; case 8 /* ExtractContentWithDom */: // When extract content, remove all image info since they may not be valid when load the content again (0, roosterjs_editor_dom_1.toArray)(e.clonedRoot.querySelectorAll(this.options.imageSelector)).forEach(function (img) { (0, editInfo_1.deleteEditInfo)(img); }); break; case 12 /* BeforeDispose */: this.removeWrapper(); break; } }; /** * Check if the given image edit operation is allowed by this plugin * @param operation The image edit operation to check * @returns True means it is allowed, otherwise false */ ImageEdit.prototype.isOperationAllowed = function (operation) { return !!(this.allowedOperations & operation); }; ImageEdit.prototype.setEditingImage = function (image, operationOrSelect) { var _this = this; var operation = typeof operationOrSelect === 'number' ? operationOrSelect : 0 /* None */; var selectImage = typeof operationOrSelect === 'number' ? false : !!operationOrSelect; if (!image && this.image) { // When there is image in editing, clean up any cached objects and elements this.clearDndHelpers(); // Apply the changes, and add undo snapshot if necessary (0, applyChange_1.default)(this.editor, this.image, this.editInfo, this.lastSrc, this.wasResized, this.clonedImage); // Remove editing wrapper this.removeWrapper(); this.editor.addUndoSnapshot(function () { return _this.image; }, "ImageResize" /* ImageResize */); if (selectImage) { this.editor.select(this.image); } this.image = null; this.editInfo = null; this.lastSrc = null; this.clonedImage = null; this.isCropping = false; } if (!this.image && (image === null || image === void 0 ? void 0 : image.isContentEditable)) { // If there is new image to edit, enter editing mode for this image this.editor.addUndoSnapshot(); this.image = image; // Get initial edit info this.editInfo = (0, editInfo_1.getEditInfoFromImage)(image); //Check if the image was resized by the user this.wasResized = checkIfImageWasResized(this.image); operation = ((0, canRegenerateImage_1.default)(image) ? operation : 3 /* Resize */) & this.allowedOperations; // Create and update editing wrapper and elements this.createWrapper(operation); this.updateWrapper(); // Init drag and drop this.dndHelpers = __spreadArray(__spreadArray(__spreadArray(__spreadArray([], this.createDndHelpers("r_resizeH" /* ResizeHandle */, Resizer_1.Resizer), true), this.createDndHelpers("r_rotateH" /* RotateHandle */, Rotator_1.Rotator), true), this.createDndHelpers("r_cropH" /* CropHandle */, Cropper_1.Cropper), true), this.createDndHelpers("r_cropC" /* CropContainer */, Cropper_1.Cropper), true); this.editor.select(this.image); } }; /** * Create editing wrapper for the image */ ImageEdit.prototype.createWrapper = function (operation) { var _this = this; //Clone the image and insert the clone in a entity this.clonedImage = this.image.cloneNode(true); this.clonedImage.removeAttribute('id'); this.wrapper = (0, roosterjs_editor_dom_1.createElement)(6 /* ImageEditWrapper */, this.image.ownerDocument); this.wrapper.firstChild.appendChild(this.clonedImage); this.wrapper.style.display = roosterjs_editor_dom_1.Browser.isSafari ? 'inline-block' : 'inline-flex'; // Cache current src so that we can compare it after edit see if src is changed this.lastSrc = this.image.getAttribute('src'); // Set image src to original src to help show editing UI, also it will be used when regenerate image dataURL after editing this.clonedImage.src = this.editInfo.src; this.clonedImage.style.position = 'absolute'; // Get HTML for all edit elements (resize handle, rotate handle, crop handle and overlay, ...) and create HTML element var options = { borderColor: getColorString(this.options.borderColor, this.editor.isDarkMode()), rotateIconHTML: this.options.rotateIconHTML, rotateHandleBackColor: this.editor.isDarkMode() ? DARK_MODE_BGCOLOR : LIGHT_MODE_BGCOLOR, isSmallImage: isASmallImage(this.editInfo), }; var htmlData = [(0, Resizer_1.getResizeBordersHTML)(options)]; (0, roosterjs_editor_dom_1.getObjectKeys)(ImageEditHTMLMap).forEach(function (thisOperation) { if ((operation & thisOperation) == thisOperation) { (0, roosterjs_editor_dom_1.arrayPush)(htmlData, ImageEditHTMLMap[thisOperation](options, _this.onShowResizeHandle)); } }); htmlData.forEach(function (data) { var element = (0, roosterjs_editor_dom_1.createElement)(data, _this.image.ownerDocument); if (element) { _this.wrapper.appendChild(element); } }); this.insertImageWrapper(this.wrapper); }; ImageEdit.prototype.insertImageWrapper = function (wrapper) { this.shadowSpan = (0, roosterjs_editor_dom_1.wrap)(this.image, 'span'); var shadowRoot = this.shadowSpan.attachShadow({ mode: 'open', }); this.shadowSpan.style.verticalAlign = 'bottom'; shadowRoot.appendChild(wrapper); }; /** * Create drag and drop helpers * @param wrapper * @param elementClass * @param dragAndDrop */ ImageEdit.prototype.createDndHelpers = function (elementClass, dragAndDrop) { var _this = this; var commonContext = { editInfo: this.editInfo, options: this.options, elementClass: elementClass, }; var wrapper = this.wrapper; return wrapper ? getEditElements(wrapper, elementClass).map(function (element) { return new DragAndDropHelper_1.default(element, __assign(__assign({}, commonContext), { x: element.dataset.x, y: element.dataset.y }), _this.updateWrapper, dragAndDrop, _this.editor.getZoomScale()); }) : []; }; /** * Clean up drag and drop helpers */ ImageEdit.prototype.clearDndHelpers = function () { var _a; (_a = this.dndHelpers) === null || _a === void 0 ? void 0 : _a.forEach(function (helper) { return helper.dispose(); }); this.dndHelpers = null; }; return ImageEdit; }()); exports.default = ImageEdit; function setSize(element, left, top, right, bottom, width, height) { element.style.left = getPx(left); element.style.top = getPx(top); element.style.right = getPx(right); element.style.bottom = getPx(bottom); element.style.width = getPx(width); element.style.height = getPx(height); } function getPx(value) { return value === undefined ? null : value + 'px'; } function getEditElements(wrapper, elementClass) { return (0, roosterjs_editor_dom_1.toArray)(wrapper.querySelectorAll('.' + elementClass)); } function isRtl(element) { return (0, roosterjs_editor_dom_1.safeInstanceOf)(element, 'HTMLElement') ? (0, roosterjs_editor_dom_1.getComputedStyle)(element, 'direction') == 'rtl' : false; } function handleRadIndexCalculator(angleRad) { var idx = Math.round(angleRad / DirectionRad) % DIRECTIONS; return idx < 0 ? idx + DIRECTIONS : idx; } function rotateHandles(element, angleRad) { var radIndex = handleRadIndexCalculator(angleRad); var originalDirection = element.dataset.y + element.dataset.x; var originalIndex = DirectionOrder.indexOf(originalDirection); var rotatedIndex = originalIndex >= 0 && originalIndex + radIndex; return DirectionOrder[rotatedIndex % DIRECTIONS]; } /** * Rotate the resizer and cropper handles according to the image position. * @param handles The resizer handles. * @param angleRad The angle that the image was rotated. */ function updateHandleCursor(handles, angleRad) { handles.map(function (handle) { handle.style.cursor = rotateHandles(handle, angleRad) + "-resize"; }); } /** * Check if the current image was resized by the user * @param image the current image * @returns if the user resized the image, returns true, otherwise, returns false */ function checkIfImageWasResized(image) { var width = image.width, height = image.height, style = image.style; var isMaxWidthInitial = style.maxWidth === '' || style.maxWidth === 'initial' || style.maxWidth === 'auto'; if (isMaxWidthInitial && (isFixedNumberValue(style.height) || isFixedNumberValue(style.width) || isFixedNumberValue(width) || isFixedNumberValue(height))) { return true; } else { return false; } } function isFixedNumberValue(value) { var numberValue = typeof value === 'string' ? parseInt(value) : value; return !isNaN(numberValue); } function isASmallImage(editInfo) { var widthPx = editInfo.widthPx, heightPx = editInfo.heightPx; return widthPx && heightPx && widthPx * widthPx < MAX_SMALL_SIZE_IMAGE; } function getColorString(color, isDarkMode) { if (typeof color === 'string') { return color.trim(); } return isDarkMode ? color.darkModeColor.trim() : color.lightModeColor.trim(); } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/canRegenerateImage.ts": /*!*******************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/canRegenerateImage.ts ***! \*******************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Check if we can regenerate edited image from the source image. * An image can't regenerate result when there is CORS issue of the source content. * @param img The image element to test * @returns True when we can regenerate the edited image, otherwise false */ function canRegenerateImage(img) { if (!img) { return false; } try { var canvas = img.ownerDocument.createElement('canvas'); canvas.width = 10; canvas.height = 10; var context = canvas.getContext('2d'); context.drawImage(img, 0, 0); context.getImageData(0, 0, 1, 1); return true; } catch (_a) { return false; } } exports.default = canRegenerateImage; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/isResizedTo.ts": /*!************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/isResizedTo.ts ***! \************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getTargetSizeByPercentage_1 = __webpack_require__(/*! ../editInfoUtils/getTargetSizeByPercentage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getTargetSizeByPercentage.ts"); var editInfo_1 = __webpack_require__(/*! ../editInfoUtils/editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts"); /** * Check if the image is already resized to the given percentage * @param image The image to check * @param percentage The percentage to check */ function isResizedTo(image, percentage) { var editInfo = (0, editInfo_1.getEditInfoFromImage)(image); var _a = (0, getTargetSizeByPercentage_1.default)(editInfo, percentage), width = _a.width, height = _a.height; return (Math.round(width) == Math.round(editInfo.widthPx) && Math.round(height) == Math.round(editInfo.heightPx)); } exports.default = isResizedTo; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/resetImage.ts": /*!***********************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/resetImage.ts ***! \***********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var editInfo_1 = __webpack_require__(/*! ../editInfoUtils/editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts"); /** * Remove explicit width & height attributes on the image element. * @param editor The editor that contains the image * @param image The image to remove w/h from */ function resetImage(editor, image) { editor.addUndoSnapshot(function () { image.style.width = ''; image.style.height = ''; image.style.maxWidth = '100%'; image.removeAttribute('width'); image.removeAttribute('height'); (0, editInfo_1.deleteEditInfo)(image); }, "ImageResize" /* ImageResize */); } exports.default = resetImage; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/resizeByPercentage.ts": /*!*******************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/resizeByPercentage.ts ***! \*******************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var applyChange_1 = __webpack_require__(/*! ../editInfoUtils/applyChange */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/applyChange.ts"); var getTargetSizeByPercentage_1 = __webpack_require__(/*! ../editInfoUtils/getTargetSizeByPercentage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getTargetSizeByPercentage.ts"); var isResizedTo_1 = __webpack_require__(/*! ./isResizedTo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/isResizedTo.ts"); var editInfo_1 = __webpack_require__(/*! ../editInfoUtils/editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts"); /** * Resize the image by percentage of its natural size. If the image is cropped or rotated, * the final size will also calculated with crop and rotate info. * @param editor The editor that contains the image * @param image The image to resize * @param percentage Percentage to resize to * @param minWidth Minimum width * @param minHeight Minimum height */ function resizeByPercentage(editor, image, percentage, minWidth, minHeight) { var editInfo = (0, editInfo_1.getEditInfoFromImage)(image); if (!(0, isResizedTo_1.default)(image, percentage)) { loadImage(image, image.src, function () { if (!editor.isDisposed() && editor.contains(image)) { var lastSrc_1 = image.getAttribute('src'); var _a = (0, getTargetSizeByPercentage_1.default)(editInfo, percentage), width = _a.width, height = _a.height; editInfo.widthPx = Math.max(width, minWidth); editInfo.heightPx = Math.max(height, minHeight); editor.addUndoSnapshot(function () { (0, applyChange_1.default)(editor, image, editInfo, lastSrc_1, true /*wasResized*/); }, "ImageResize" /* ImageResize */); } }); } } exports.default = resizeByPercentage; function loadImage(img, src, callback) { img.onload = function () { img.onload = null; img.onerror = null; callback(); }; img.onerror = function () { img.onload = null; img.onerror = null; callback(); }; img.src = src; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/applyChange.ts": /*!**********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/applyChange.ts ***! \**********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var checkEditInfoState_1 = __webpack_require__(/*! ./checkEditInfoState */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/checkEditInfoState.ts"); var generateDataURL_1 = __webpack_require__(/*! ./generateDataURL */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/generateDataURL.ts"); var getGeneratedImageSize_1 = __webpack_require__(/*! ./getGeneratedImageSize */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getGeneratedImageSize.ts"); var editInfo_1 = __webpack_require__(/*! ./editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts"); /** * @internal * Apply changes from the edit info of an image, write result to the image * @param editor The editor object that contains the image * @param image The image to apply the change * @param editInfo Edit info that contains the changed information of the image * @param previousSrc Last src value of the image before the change was made * @param editingImage (optional) Image in editing state */ function applyChange(editor, image, editInfo, previousSrc, wasResized, editingImage) { var newSrc = ''; var initEditInfo = (0, editInfo_1.getEditInfoFromImage)(editingImage !== null && editingImage !== void 0 ? editingImage : image); var state = (0, checkEditInfoState_1.default)(editInfo, initEditInfo); switch (state) { case 1 /* ResizeOnly */: // For resize only case, no need to generate a new image, just reuse the original one newSrc = editInfo.src; break; case 2 /* SameWithLast */: // For SameWithLast case, image may be resized but the content is still the same with last one, // so no need to create a new image, but just reuse last one newSrc = previousSrc; break; case 3 /* FullyChanged */: // For other cases (cropped, rotated, ...) we need to create a new image to reflect the change newSrc = (0, generateDataURL_1.default)(editingImage !== null && editingImage !== void 0 ? editingImage : image, editInfo); break; } var srcChanged = newSrc != previousSrc; if (srcChanged) { // If the src is changed, fire an EditImage event so that plugins knows that a new image is used, and can // replace the new src with some other string and it will be used and set to the image var event_1 = editor.triggerPluginEvent(19 /* EditImage */, { image: image, originalSrc: editInfo.src, previousSrc: previousSrc, newSrc: newSrc, }); newSrc = event_1.newSrc; } if (newSrc == editInfo.src) { // If newSrc is the same with original one, it means there is only size change, but no rotation, no cropping, // so we don't need to keep edit info, we can delete it (0, editInfo_1.deleteEditInfo)(image); } else { // Otherwise, save the new edit info to the image so that next time when we edit the same image, we know // the edit info (0, editInfo_1.saveEditInfo)(image, editInfo); } // Write back the change to image, and set its new size var _a = (0, getGeneratedImageSize_1.default)(editInfo), targetWidth = _a.targetWidth, targetHeight = _a.targetHeight; image.src = newSrc; if (wasResized || state == 3 /* FullyChanged */) { image.width = targetWidth; image.height = targetHeight; image.style.width = targetWidth + 'px'; image.style.height = targetHeight + 'px'; } } exports.default = applyChange; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/checkEditInfoState.ts": /*!*****************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/checkEditInfoState.ts ***! \*****************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); var RESIZE_KEYS = ['widthPx', 'heightPx']; var ROTATE_KEYS = ['angleRad']; var CROP_KEYS = [ 'leftPercent', 'rightPercent', 'topPercent', 'bottomPercent', ]; var ROTATE_CROP_KEYS = __spreadArray(__spreadArray([], ROTATE_KEYS, true), CROP_KEYS, true); var ALL_KEYS = __spreadArray(__spreadArray([], ROTATE_CROP_KEYS, true), RESIZE_KEYS, true); /** * @internal * Check the state of an edit info * @param editInfo The edit info to check * @param compareTo An optional edit info to compare to * @returns If the source edit info is not valid (wrong type, missing field, ...), returns Invalid. * If the source edit info doesn't contain any rotation or cropping, returns ResizeOnly * If the compare edit info exists, and both of them don't contain rotation, and the have same cropping values, * returns SameWithLast. Otherwise, returns FullyChanged */ function checkEditInfoState(editInfo, compareTo) { if (!editInfo || !editInfo.src || ALL_KEYS.some(function (key) { return !isNumber(editInfo[key]); })) { return 0 /* Invalid */; } else if (ROTATE_CROP_KEYS.every(function (key) { return areSameNumber(editInfo[key], 0); })) { return 1 /* ResizeOnly */; } else if (compareTo && ROTATE_KEYS.every(function (key) { return areSameNumber(editInfo[key], 0); }) && ROTATE_KEYS.every(function (key) { return areSameNumber(compareTo[key], 0); }) && CROP_KEYS.every(function (key) { return areSameNumber(editInfo[key], compareTo[key]); })) { return 2 /* SameWithLast */; } else { return 3 /* FullyChanged */; } } exports.default = checkEditInfoState; function isNumber(o) { return typeof o === 'number'; } function areSameNumber(n1, n2) { return Math.abs(n1 - n2) < 1e-3; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts": /*!*******************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts ***! \*******************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getEditInfoFromImage = exports.deleteEditInfo = exports.saveEditInfo = void 0; var checkEditInfoState_1 = __webpack_require__(/*! ./checkEditInfoState */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/checkEditInfoState.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Save edit info to image * @param image The image to save edit info to * @param editInfo The edit info to save */ function saveEditInfo(image, editInfo) { if (image) { (0, roosterjs_editor_dom_1.setMetadata)(image, editInfo); } } exports.saveEditInfo = saveEditInfo; /** * @internal * Delete edit info of an image if any * @param image The image to delete edit info from */ function deleteEditInfo(image) { if (image) { (0, roosterjs_editor_dom_1.removeMetadata)(image); } } exports.deleteEditInfo = deleteEditInfo; /** * @internal * Get image edit info from an image. If the image doesn't have edit info, create one from this image. * When create new edit info, it will have width/height set to the image's current client width/height, and * natural width/height set to the image's natural width/height, src set to its current src, and all * other fields set to 0. * @param image The image to get edit info from */ function getEditInfoFromImage(image) { var obj = (0, roosterjs_editor_dom_1.getMetadata)(image); return (0, checkEditInfoState_1.default)(obj) == 0 /* Invalid */ ? getInitialEditInfo(image) : obj; } exports.getEditInfoFromImage = getEditInfoFromImage; function getInitialEditInfo(image) { return { src: image.getAttribute('src') || '', widthPx: image.clientWidth, heightPx: image.clientHeight, naturalWidth: image.naturalWidth, naturalHeight: image.naturalHeight, leftPercent: 0, rightPercent: 0, topPercent: 0, bottomPercent: 0, angleRad: 0, }; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/generateDataURL.ts": /*!**************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/generateDataURL.ts ***! \**************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var getGeneratedImageSize_1 = __webpack_require__(/*! ./getGeneratedImageSize */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getGeneratedImageSize.ts"); /** * @internal * Generate new dataURL from an image and edit info * @param image The image to generate data URL from. It is supposed to have original src loaded * @param editInfo Edit info of the image * @returns A BASE64 encoded string with image prefix that represents the content of the generated image. * If there are rotate/crop/resize info in the edit info, the generated image will also reflect the result. * It is possible to throw exception since the original image may not be able to read its content from * the code, so better check canRegenerateImage() of the image first. * @throws Exception when fail to generate dataURL from canvas */ function generateDataURL(image, editInfo) { var angle = editInfo.angleRad, width = editInfo.widthPx, height = editInfo.heightPx, bottom = editInfo.bottomPercent, left = editInfo.leftPercent, right = editInfo.rightPercent, top = editInfo.topPercent, naturalWidth = editInfo.naturalWidth, naturalHeight = editInfo.naturalHeight; var imageWidth = naturalWidth * (1 - left - right); var imageHeight = naturalHeight * (1 - top - bottom); var canvas = document.createElement('canvas'); var _a = (0, getGeneratedImageSize_1.default)(editInfo), targetWidth = _a.targetWidth, targetHeight = _a.targetHeight; canvas.width = targetWidth; canvas.height = targetHeight; var context = canvas.getContext('2d'); context.translate(targetWidth / 2, targetHeight / 2); context.rotate(angle); context.drawImage(image, naturalWidth * left, naturalHeight * top, imageWidth, imageHeight, -width / 2, -height / 2, width, height); return canvas.toDataURL('image/png', 1.0); } exports.default = generateDataURL; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getGeneratedImageSize.ts": /*!********************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getGeneratedImageSize.ts ***! \********************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * @internal * Calculate the target size of an image. * For image that is not rotated, target size is the same with resizing/cropping size. * For image that is rotated, target size is calculated from resizing/cropping size and its rotate angle * Say an image is resized to 100w*100h, cropped 25% on each side, then rotated 45deg, so that cropped size * will be (both height and width) 100*(1-0.25-0,25) = 50px, then final image size will be 50*sqrt(2) = 71px * @param editInfo The edit info to calculate size from * @param beforeCrop True to calculate the full size of original image before crop, false to calculate the size * after crop * @returns A GeneratedImageSize object which contains original, visible and target target width and height of the image */ function getGeneratedImageSize(editInfo, beforeCrop) { var width = editInfo.widthPx, height = editInfo.heightPx, angle = editInfo.angleRad, left = editInfo.leftPercent, right = editInfo.rightPercent, top = editInfo.topPercent, bottom = editInfo.bottomPercent; // Original image size before crop and rotate var originalWidth = width / (1 - left - right); var originalHeight = height / (1 - top - bottom); // Visible size var visibleWidth = beforeCrop ? originalWidth : width; var visibleHeight = beforeCrop ? originalHeight : height; // Target size after crop and rotate var targetWidth = Math.abs(visibleWidth * Math.cos(angle)) + Math.abs(visibleHeight * Math.sin(angle)); var targetHeight = Math.abs(visibleWidth * Math.sin(angle)) + Math.abs(visibleHeight * Math.cos(angle)); return { targetWidth: targetWidth, targetHeight: targetHeight, originalWidth: originalWidth, originalHeight: originalHeight, visibleWidth: visibleWidth, visibleHeight: visibleHeight, }; } exports.default = getGeneratedImageSize; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getTargetSizeByPercentage.ts": /*!************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getTargetSizeByPercentage.ts ***! \************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * @internal * Get target size of an image with a percentage * @param editInfo * @param percentage * @returns [width, height] array */ function getTargetSizeByPercentage(editInfo, percentage) { var naturalWidth = editInfo.naturalWidth, naturalHeight = editInfo.naturalHeight, left = editInfo.leftPercent, top = editInfo.topPercent, right = editInfo.rightPercent, bottom = editInfo.bottomPercent; var width = naturalWidth * (1 - left - right) * percentage; var height = naturalHeight * (1 - top - bottom) * percentage; return { width: width, height: height }; } exports.default = getTargetSizeByPercentage; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Cropper.ts": /*!*****************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Cropper.ts ***! \*****************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getCropHTML = exports.Cropper = void 0; var Resizer_1 = __webpack_require__(/*! ./Resizer */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Resizer.ts"); var CROP_HANDLE_SIZE = 22; var CROP_HANDLE_WIDTH = 7; var Xs = ['w', 'e']; var Ys = ['s', 'n']; var ROTATION = { sw: 0, nw: 90, ne: 180, se: 270, }; /** * @internal * Crop handle for DragAndDropHelper */ exports.Cropper = { onDragStart: function (_a) { var editInfo = _a.editInfo; return (__assign({}, editInfo)); }, onDragging: function (_a, e, base, dx, dy) { var _b; var editInfo = _a.editInfo, x = _a.x, y = _a.y, options = _a.options; _b = (0, Resizer_1.rotateCoordinate)(dx, dy, editInfo.angleRad), dx = _b[0], dy = _b[1]; var widthPx = editInfo.widthPx, heightPx = editInfo.heightPx, leftPercent = editInfo.leftPercent, rightPercent = editInfo.rightPercent, topPercent = editInfo.topPercent, bottomPercent = editInfo.bottomPercent; var minWidth = options.minWidth, minHeight = options.minHeight; var widthPercent = 1 - leftPercent - rightPercent; var heightPercent = 1 - topPercent - bottomPercent; if (widthPercent > 0 && heightPercent > 0) { var fullWidth = widthPx / widthPercent; var fullHeight = heightPx / heightPercent; var newLeft = x != 'e' ? crop(base.leftPercent, dx, fullWidth, rightPercent, minWidth) : leftPercent; var newRight = x != 'w' ? crop(base.rightPercent, -dx, fullWidth, leftPercent, minWidth) : rightPercent; var newTop = y != 's' ? crop(base.topPercent, dy, fullHeight, bottomPercent, minHeight) : topPercent; var newBottom = y != 'n' ? crop(base.bottomPercent, -dy, fullHeight, topPercent, minHeight) : bottomPercent; editInfo.leftPercent = newLeft; editInfo.rightPercent = newRight; editInfo.topPercent = newTop; editInfo.bottomPercent = newBottom; editInfo.widthPx = fullWidth * (1 - newLeft - newRight); editInfo.heightPx = fullHeight * (1 - newTop - newBottom); return true; } else { return false; } }, }; function crop(basePercentage, deltaValue, fullValue, currentPercentage, minValue) { var maxValue = fullValue * (1 - currentPercentage) - minValue; var newValue = fullValue * basePercentage + deltaValue; var validValue = Math.max(Math.min(newValue, maxValue), 0); return validValue / fullValue; } /** * @internal * Get HTML for crop elements, including 4 overlays (to show dark shadow), 1 container and 4 crop handles */ function getCropHTML() { var overlayHTML = { tag: 'div', style: 'position:absolute;background-color:rgb(0,0,0,0.5);pointer-events:none', className: "r_cropO" /* CropOverlay */, }; var containerHTML = { tag: 'div', style: 'position:absolute;overflow:hidden', className: "r_cropC" /* CropContainer */, children: [], }; Xs.forEach(function (x) { return Ys.forEach(function (y) { return containerHTML.children.push(getCropHTMLInternal(x, y)); }); }); return [containerHTML, overlayHTML, overlayHTML, overlayHTML, overlayHTML]; } exports.getCropHTML = getCropHTML; function getCropHTMLInternal(x, y) { var leftOrRight = x == 'w' ? 'left' : 'right'; var topOrBottom = y == 'n' ? 'top' : 'bottom'; var rotation = ROTATION[y + x]; return { tag: 'div', className: "r_cropH" /* CropHandle */, style: "position:absolute;pointer-events:auto;cursor:" + y + x + "-resize;" + leftOrRight + ":0;" + topOrBottom + ":0;width:" + CROP_HANDLE_SIZE + "px;height:" + CROP_HANDLE_SIZE + "px;transform:rotate(" + rotation + "deg)", dataset: { x: x, y: y }, children: getCropHandleHTML(), }; } function getCropHandleHTML() { var result = []; [0, 1].forEach(function (layer) { return [0, 1].forEach(function (dir) { result.push(getCropHandleHTMLInternal(layer, dir)); }); }); return result; } function getCropHandleHTMLInternal(layer, dir) { var position = dir == 0 ? "right:" + layer + "px;height:" + (CROP_HANDLE_WIDTH - layer * 2) + "px;" : "top:" + layer + "px;width:" + (CROP_HANDLE_WIDTH - layer * 2) + "px;"; var bgColor = layer == 0 ? 'white' : 'black'; return { tag: 'div', style: "position:absolute;left:" + layer + "px;bottom:" + layer + "px;" + position + ";background-color:" + bgColor, }; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Resizer.ts": /*!*****************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Resizer.ts ***! \*****************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getResizeBordersHTML = exports.getSideResizeHTML = exports.getCornerResizeHTML = exports.doubleCheckResize = exports.rotateCoordinate = exports.Resizer = void 0; var RESIZE_HANDLE_SIZE = 10; var RESIZE_HANDLE_MARGIN = 3; var Xs = ['w', '', 'e']; var Ys = ['s', '', 'n']; /** * @internal * The resize drag and drop handler */ exports.Resizer = { onDragStart: function (_a) { var editInfo = _a.editInfo; return (__assign({}, editInfo)); }, onDragging: function (_a, e, base, deltaX, deltaY) { var _b; var x = _a.x, y = _a.y, editInfo = _a.editInfo, options = _a.options; var ratio = base.widthPx > 0 && base.heightPx > 0 ? (base.widthPx * 1.0) / base.heightPx : 0; _b = rotateCoordinate(deltaX, deltaY, editInfo.angleRad), deltaX = _b[0], deltaY = _b[1]; var horizontalOnly = x == ''; var verticalOnly = y == ''; var shouldPreserveRatio = !(horizontalOnly || verticalOnly) && (options.preserveRatio || e.shiftKey); var newWidth = horizontalOnly ? base.widthPx : Math.max(base.widthPx + deltaX * (x == 'w' ? -1 : 1), options.minWidth); var newHeight = verticalOnly ? base.heightPx : Math.max(base.heightPx + deltaY * (y == 'n' ? -1 : 1), options.minHeight); if (shouldPreserveRatio && ratio > 0) { if (ratio > 1) { // first sure newHeight is right,calculate newWidth newWidth = newHeight * ratio; if (newWidth < options.minWidth) { newWidth = options.minWidth; newHeight = newWidth / ratio; } } else { // first sure newWidth is right,calculate newHeight newHeight = newWidth / ratio; if (newHeight < options.minHeight) { newHeight = options.minHeight; newWidth = newHeight * ratio; } } } editInfo.widthPx = newWidth; editInfo.heightPx = newHeight; return true; }, }; /** * @internal Calculate the rotated x and y distance for mouse moving * @param x Original x distance * @param y Original y distance * @param angle Rotated angle, in radian * @returns rotated x and y distances */ function rotateCoordinate(x, y, angle) { if (x == 0 && y == 0) { return [0, 0]; } var hypotenuse = Math.sqrt(x * x + y * y); angle = Math.atan2(y, x) - angle; return [hypotenuse * Math.cos(angle), hypotenuse * Math.sin(angle)]; } exports.rotateCoordinate = rotateCoordinate; /** * @internal * Double check if the changed size can satisfy current width of container. * When resize an image and preserve ratio, its size can be limited by the size of container. * So we need to check the actual size and calculate the size again * @param editInfo Edit info of the image * @param preserveRatio Whether w/h ratio need to be preserved * @param actualWidth Actual width of the image after resize * @param actualHeight Actual height of the image after resize */ function doubleCheckResize(editInfo, preserveRatio, actualWidth, actualHeight) { var widthPx = editInfo.widthPx, heightPx = editInfo.heightPx; var ratio = heightPx > 0 ? widthPx / heightPx : 0; actualWidth = Math.floor(actualWidth); actualHeight = Math.floor(actualHeight); widthPx = Math.floor(widthPx); heightPx = Math.floor(heightPx); editInfo.widthPx = actualWidth; editInfo.heightPx = actualHeight; if (preserveRatio && ratio > 0 && (widthPx !== actualWidth || heightPx !== actualHeight)) { if (actualWidth < widthPx) { editInfo.heightPx = actualWidth / ratio; } else { editInfo.widthPx = actualHeight * ratio; } } } exports.doubleCheckResize = doubleCheckResize; /** * @internal * Get HTML for resize handles at the corners */ function getCornerResizeHTML(_a, onShowResizeHandle) { var resizeBorderColor = _a.borderColor; var result = []; Xs.forEach(function (x) { return Ys.forEach(function (y) { var elementData = (x == '') == (y == '') ? getResizeHandleHTML(x, y, resizeBorderColor, 1 /* CircularHandlesCorner */) : null; if (onShowResizeHandle) { onShowResizeHandle(elementData, x, y); } result.push(elementData); }); }); return result; } exports.getCornerResizeHTML = getCornerResizeHTML; /** * @internal * Get HTML for resize handles on the sides */ function getSideResizeHTML(_a, onShowResizeHandle) { var resizeBorderColor = _a.borderColor, isSmallImage = _a.isSmallImage; if (isSmallImage) { return null; } var result = []; Xs.forEach(function (x) { return Ys.forEach(function (y) { var elementData = (x == '') != (y == '') ? getResizeHandleHTML(x, y, resizeBorderColor, 1 /* CircularHandlesCorner */) : null; if (onShowResizeHandle) { onShowResizeHandle(elementData, x, y); } result.push(elementData); }); }); return result; } exports.getSideResizeHTML = getSideResizeHTML; /** * @internal * Get HTML for resize borders */ function getResizeBordersHTML(_a) { var resizeBorderColor = _a.borderColor; return { tag: 'div', style: "position:absolute;left:0;right:0;top:0;bottom:0;border:solid 2px " + resizeBorderColor + ";pointer-events:none;", }; } exports.getResizeBordersHTML = getResizeBordersHTML; function getResizeHandleHTML(x, y, borderColor, handleTypes) { var leftOrRight = x == 'w' ? 'left' : 'right'; var topOrBottom = y == 'n' ? 'top' : 'bottom'; var leftOrRightValue = x == '' ? '50%' : '0px'; var topOrBottomValue = y == '' ? '50%' : '0px'; var direction = y + x; return x == '' && y == '' ? null : { tag: 'div', style: "position:absolute;" + leftOrRight + ":" + leftOrRightValue + ";" + topOrBottom + ":" + topOrBottomValue, children: [ { tag: 'div', style: setHandleStyle[handleTypes](direction, topOrBottom, leftOrRight, borderColor), className: "r_resizeH" /* ResizeHandle */, dataset: { x: x, y: y }, }, ], }; } var setHandleStyle = { 0: function (direction, leftOrRight, topOrBottom, borderColor) { return "position:relative;width:" + RESIZE_HANDLE_SIZE + "px;height:" + RESIZE_HANDLE_SIZE + "px;background-color: " + borderColor + ";cursor:" + direction + "-resize;" + topOrBottom + ":-" + RESIZE_HANDLE_MARGIN + "px;" + leftOrRight + ":-" + RESIZE_HANDLE_MARGIN + "px;"; }, 1: function (direction, leftOrRight, topOrBottom) { return "position:relative;width:" + RESIZE_HANDLE_SIZE + "px;height:" + RESIZE_HANDLE_SIZE + "px;background-color: #FFFFFF;cursor:" + direction + "-resize;" + topOrBottom + ":-" + RESIZE_HANDLE_MARGIN + "px;" + leftOrRight + ":-" + RESIZE_HANDLE_MARGIN + "px;border-radius:100%;border: 2px solid #bfbfbf;box-shadow: 0px 0.36316px 1.36185px rgba(100, 100, 100, 0.25);"; }, }; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Rotator.ts": /*!*****************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Rotator.ts ***! \*****************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getRotateHTML = exports.updateRotateHandlePosition = exports.Rotator = void 0; var ROTATE_SIZE = 32; var ROTATE_GAP = 15; var DEG_PER_RAD = 180 / Math.PI; var DEFAULT_ROTATE_HANDLE_HEIGHT = ROTATE_SIZE / 2 + ROTATE_GAP; var ROTATE_ICON_MARGIN = 8; /** * @internal * The rotate drag and drop handler */ exports.Rotator = { onDragStart: function (_a) { var editInfo = _a.editInfo; return (__assign({}, editInfo)); }, onDragging: function (_a, e, base, deltaX, deltaY) { var editInfo = _a.editInfo, options = _a.options; var distance = editInfo.heightPx / 2 + DEFAULT_ROTATE_HANDLE_HEIGHT; var newX = distance * Math.sin(base.angleRad) + deltaX; var newY = distance * Math.cos(base.angleRad) - deltaY; var angleInRad = Math.atan2(newX, newY); if (!e.altKey) { var angleInDeg = angleInRad * DEG_PER_RAD; var adjustedAngleInDeg = Math.round(angleInDeg / options.minRotateDeg) * options.minRotateDeg; angleInRad = adjustedAngleInDeg / DEG_PER_RAD; } if (editInfo.angleRad != angleInRad) { editInfo.angleRad = angleInRad; return true; } else { return false; } }, }; /** * @internal * Move rotate handle. When image is very close to the border of editor, rotate handle may not be visible. * Fix it by reduce the distance from image to rotate handle */ function updateRotateHandlePosition(editInfo, editorRect, marginVertical, rotateCenter, rotateHandle) { var _a; var top = ((_a = rotateHandle.getBoundingClientRect()) === null || _a === void 0 ? void 0 : _a.top) - (editorRect === null || editorRect === void 0 ? void 0 : editorRect.top); var angleRad = editInfo.angleRad, heightPx = editInfo.heightPx; var cosAngle = Math.cos(angleRad); var adjustedDistance = cosAngle <= 0 ? Number.MAX_SAFE_INTEGER : (top + heightPx / 2 + marginVertical) / cosAngle - heightPx / 2; var rotateGap = Math.max(Math.min(ROTATE_GAP, adjustedDistance), 0); var rotateTop = Math.max(Math.min(ROTATE_SIZE, adjustedDistance - rotateGap), 0); rotateCenter.style.top = -rotateGap + 'px'; rotateCenter.style.height = rotateGap + 'px'; rotateHandle.style.top = -rotateTop + 'px'; } exports.updateRotateHandlePosition = updateRotateHandlePosition; /** * @internal * Get HTML for rotate elements, including the rotate handle with icon, and a line between the handle and the image */ function getRotateHTML(_a) { var borderColor = _a.borderColor, rotateHandleBackColor = _a.rotateHandleBackColor; var handleLeft = ROTATE_SIZE / 2; return [ { tag: 'div', className: "r_rotateC" /* RotateCenter */, style: "position:absolute;left:50%;width:1px;background-color:" + borderColor + ";top:" + -ROTATE_GAP + "px;height:" + ROTATE_GAP + "px;", children: [ { tag: 'div', className: "r_rotateH" /* RotateHandle */, style: "position:absolute;background-color:" + rotateHandleBackColor + ";border:solid 1px " + borderColor + ";border-radius:50%;width:" + ROTATE_SIZE + "px;height:" + ROTATE_SIZE + "px;left:-" + handleLeft + "px;cursor:move;top:" + -ROTATE_SIZE + "px;", children: [getRotateIconHTML(borderColor)], }, ], }, ]; } exports.getRotateHTML = getRotateHTML; function getRotateIconHTML(borderColor) { var _a; return { tag: 'svg', namespace: 'http://www.w3.org/2000/svg', style: "width:16px;height:16px;margin: " + ROTATE_ICON_MARGIN + "px " + ROTATE_ICON_MARGIN + "px", children: [ { tag: 'path', namespace: 'http://www.w3.org/2000/svg', attributes: (_a = { d: 'M 10.5,10.0 A 3.8,3.8 0 1 1 6.7,6.3', transform: 'matrix(1.1 1.1 -1.1 1.1 11.6 -10.8)' }, _a['fill-opacity'] = '0', _a.stroke = borderColor, _a), }, { tag: 'path', namespace: 'http://www.w3.org/2000/svg', attributes: { d: 'M12.0 3.648l.884-.884.53 2.298-2.298-.53z', stroke: borderColor, }, }, ], }; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/index.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/index.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.resetImage = exports.isResizedTo = exports.resizeByPercentage = exports.canRegenerateImage = exports.ImageEdit = void 0; var ImageEdit_1 = __webpack_require__(/*! ./ImageEdit */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/ImageEdit.ts"); Object.defineProperty(exports, "ImageEdit", { enumerable: true, get: function () { return ImageEdit_1.default; } }); var canRegenerateImage_1 = __webpack_require__(/*! ./api/canRegenerateImage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/canRegenerateImage.ts"); Object.defineProperty(exports, "canRegenerateImage", { enumerable: true, get: function () { return canRegenerateImage_1.default; } }); var resizeByPercentage_1 = __webpack_require__(/*! ./api/resizeByPercentage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/resizeByPercentage.ts"); Object.defineProperty(exports, "resizeByPercentage", { enumerable: true, get: function () { return resizeByPercentage_1.default; } }); var isResizedTo_1 = __webpack_require__(/*! ./api/isResizedTo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/isResizedTo.ts"); Object.defineProperty(exports, "isResizedTo", { enumerable: true, get: function () { return isResizedTo_1.default; } }); var resetImage_1 = __webpack_require__(/*! ./api/resetImage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/resetImage.ts"); Object.defineProperty(exports, "resetImage", { enumerable: true, get: function () { return resetImage_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/ImageResize.ts": /*!**********************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/ImageResize.ts ***! \**********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var ImageEdit_1 = __webpack_require__(/*! ../ImageEdit/ImageEdit */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/ImageEdit.ts"); /** * @deprecated Use ImageEdit plugin instead */ var ImageResize = /** @class */ (function (_super) { __extends(ImageResize, _super); /** * Create a new instance of ImageResize * @param minWidth Minimum width of image when resize in pixel, default value is 10 * @param minHeight Minimum height of image when resize in pixel, default value is 10 * @param selectionBorderColor Color of resize border and handles, default value is #DB626C * @param forcePreserveRatio Whether always preserve width/height ratio when resize, default value is false * @param resizableImageSelector Selector for picking which image is resizable (e.g. for all images not placeholders), note * that the tag must be IMG regardless what the selector is */ function ImageResize(minWidth, minHeight, selectionBorderColor, forcePreserveRatio, resizableImageSelector) { if (minWidth === void 0) { minWidth = 10; } if (minHeight === void 0) { minHeight = 10; } if (selectionBorderColor === void 0) { selectionBorderColor = '#DB626C'; } if (forcePreserveRatio === void 0) { forcePreserveRatio = false; } if (resizableImageSelector === void 0) { resizableImageSelector = 'img'; } return _super.call(this, { minHeight: minHeight, minWidth: minWidth, borderColor: selectionBorderColor, preserveRatio: forcePreserveRatio, imageSelector: resizableImageSelector, }) || this; } /** * @deprecated */ ImageResize.prototype.showResizeHandle = function (img) { this.setEditingImage(img, 3 /* Resize */); }; /** * @deprecated */ ImageResize.prototype.hideResizeHandle = function (selectImageAfterUnSelect) { this.setEditingImage(null /*image*/, selectImageAfterUnSelect); }; return ImageResize; }(ImageEdit_1.default)); exports.default = ImageResize; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/index.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/index.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ImageResize = void 0; var ImageResize_1 = __webpack_require__(/*! ./ImageResize */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/ImageResize.ts"); Object.defineProperty(exports, "ImageResize", { enumerable: true, get: function () { return ImageResize_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/Paste.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/Paste.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var convertPasteContentForSingleImage_1 = __webpack_require__(/*! ./imageConverter/convertPasteContentForSingleImage */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/imageConverter/convertPasteContentForSingleImage.ts"); var convertPastedContentForLI_1 = __webpack_require__(/*! ./commonConverter/convertPastedContentForLI */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/commonConverter/convertPastedContentForLI.ts"); var convertPastedContentFromExcel_1 = __webpack_require__(/*! ./excelConverter/convertPastedContentFromExcel */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/excelConverter/convertPastedContentFromExcel.ts"); var convertPastedContentFromOfficeOnline_1 = __webpack_require__(/*! ./officeOnlineConverter/convertPastedContentFromOfficeOnline */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/convertPastedContentFromOfficeOnline.ts"); var convertPastedContentFromPowerPoint_1 = __webpack_require__(/*! ./pptConverter/convertPastedContentFromPowerPoint */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/pptConverter/convertPastedContentFromPowerPoint.ts"); var convertPastedContentFromWord_1 = __webpack_require__(/*! ./wordConverter/convertPastedContentFromWord */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/convertPastedContentFromWord.ts"); var getPasteSource_1 = __webpack_require__(/*! ./sourceValidations/getPasteSource */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/getPasteSource.ts"); var handleLineMerge_1 = __webpack_require__(/*! ./lineMerge/handleLineMerge */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/lineMerge/handleLineMerge.ts"); var sanitizeHtmlColorsFromPastedContent_1 = __webpack_require__(/*! ./sanitizeHtmlColorsFromPastedContent/sanitizeHtmlColorsFromPastedContent */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sanitizeHtmlColorsFromPastedContent/sanitizeHtmlColorsFromPastedContent.ts"); var sanitizeLinks_1 = __webpack_require__(/*! ./sanitizeLinks/sanitizeLinks */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sanitizeLinks/sanitizeLinks.ts"); var constants_1 = __webpack_require__(/*! ./sourceValidations/constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts"); /** * Paste plugin, handles BeforePaste event and reformat some special content, including: * 1. Content copied from Word * 2. Content copied from Excel * 3. Content copied from Word Online or OneNote Online */ var Paste = /** @class */ (function () { /** * Construct a new instance of Paste class * @param unknownTagReplacement Replace solution of unknown tags, default behavior is to replace with SPAN * @param convertSingleImageBody When enabled, if clipboard HTML contains a single image, we reuse the image without modifying the src attribute. * When disabled, pasted image src attribute will use the dataUri from clipboard data -- By Default disabled. */ function Paste(unknownTagReplacement, convertSingleImageBody) { if (unknownTagReplacement === void 0) { unknownTagReplacement = 'SPAN'; } if (convertSingleImageBody === void 0) { convertSingleImageBody = false; } this.unknownTagReplacement = unknownTagReplacement; this.convertSingleImageBody = convertSingleImageBody; } /** * Get a friendly name of this plugin */ Paste.prototype.getName = function () { return 'Paste'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ Paste.prototype.initialize = function (editor) { this.editor = editor; }; /** * Dispose this plugin */ Paste.prototype.dispose = function () { this.editor = null; }; /** * Handle events triggered from editor * @param event PluginEvent object */ Paste.prototype.onPluginEvent = function (event) { if (event.eventType == 10 /* BeforePaste */) { var fragment = event.fragment, sanitizingOption = event.sanitizingOption; var trustedHTMLHandler = this.editor.getTrustedHTMLHandler(); switch ((0, getPasteSource_1.default)(event, this.convertSingleImageBody)) { case 0 /* WordDesktop */: // Handle HTML copied from Word (0, convertPastedContentFromWord_1.default)(event); break; case 1 /* ExcelDesktop */: // Handle HTML copied from Excel (0, convertPastedContentFromExcel_1.default)(event, trustedHTMLHandler); break; case 2 /* PowerPointDesktop */: (0, convertPastedContentFromPowerPoint_1.default)(event, trustedHTMLHandler); break; case 4 /* WacComponents */: (0, convertPastedContentFromOfficeOnline_1.default)(fragment); break; case 3 /* GoogleSheets */: sanitizingOption.additionalTagReplacements[constants_1.GOOGLE_SHEET_NODE_NAME] = '*'; break; case 6 /* SingleImage */: (0, convertPasteContentForSingleImage_1.default)(event, trustedHTMLHandler); break; case 5 /* Default */: (0, convertPastedContentForLI_1.default)(fragment); (0, handleLineMerge_1.default)(fragment); break; } (0, sanitizeLinks_1.default)(sanitizingOption); (0, sanitizeHtmlColorsFromPastedContent_1.default)(sanitizingOption); // Replace unknown tags with SPAN sanitizingOption.unknownTagReplacement = this.unknownTagReplacement; } }; return Paste; }()); exports.default = Paste; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/commonConverter/convertPastedContentForLI.ts": /*!**********************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/commonConverter/convertPastedContentForLI.ts ***! \**********************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Convert content copied from Teams to be well-formed */ function convertPastedContentForLI(fragment) { // Sometimes it is possible that we get LI nodes directly under DIV. // In that case we need to convert DIV to UL. It is also possible to be OL, but we don't know it. // So always assume it is UL here, and later user can change it. if (isPureLiNode(fragment)) { (0, roosterjs_editor_dom_1.wrap)((0, roosterjs_editor_dom_1.toArray)(fragment.childNodes), 'UL'); } else if ((0, roosterjs_editor_dom_1.safeInstanceOf)(fragment.firstChild, 'HTMLElement') && isPureLiNode(fragment.firstChild)) { (0, roosterjs_editor_dom_1.changeElementTag)(fragment.firstChild, 'UL'); } } exports.default = convertPastedContentForLI; function isPureLiNode(node) { if (node && !node.nextSibling && ['OL', 'UL', 'MENU'].indexOf((0, roosterjs_editor_dom_1.getTagOfNode)(node)) < 0) { var hasLi_1 = false; if ((0, roosterjs_editor_dom_1.toArray)(node.childNodes).every(function (childNode) { var _a; if ((0, roosterjs_editor_dom_1.safeInstanceOf)(childNode, 'Text') && !((_a = childNode.nodeValue) === null || _a === void 0 ? void 0 : _a.trim())) { return true; } else if ((0, roosterjs_editor_dom_1.getTagOfNode)(childNode) == 'LI') { hasLi_1 = true; return true; } else { return false; } }) && hasLi_1) { return true; } } return false; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/excelConverter/convertPastedContentFromExcel.ts": /*!*************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/excelConverter/convertPastedContentFromExcel.ts ***! \*************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.excelHandler = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var LAST_TD_END_REGEX = /<\/\s*td\s*>((?!<\/\s*tr\s*>)[\s\S])*$/i; var LAST_TR_END_REGEX = /<\/\s*tr\s*>((?!<\/\s*table\s*>)[\s\S])*$/i; var LAST_TR_REGEX = /]*>[^<]*/i; var LAST_TABLE_REGEX = /]*>[^<]*/i; var DEFAULT_BORDER_STYLE = 'solid 1px #d4d4d4'; /** * @internal * Convert pasted content from Excel, add borders when source doc doesn't have a border * @param event The BeforePaste event */ function convertPastedContentFromExcel(event, trustedHTMLHandler) { var fragment = event.fragment, sanitizingOption = event.sanitizingOption, htmlBefore = event.htmlBefore, clipboardData = event.clipboardData; var html = excelHandler(clipboardData.html, htmlBefore); if (clipboardData.html != html) { var doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html'); (0, roosterjs_editor_dom_1.moveChildNodes)(fragment, doc === null || doc === void 0 ? void 0 : doc.body); } (0, roosterjs_editor_dom_1.chainSanitizerCallback)(sanitizingOption.elementCallbacks, 'TD', function (element) { if (element.style.borderStyle == 'none') { element.style.border = DEFAULT_BORDER_STYLE; } return true; }); } exports.default = convertPastedContentFromExcel; /** * @internal Export for test only * @param html Source html */ function excelHandler(html, htmlBefore) { if (html.match(LAST_TD_END_REGEX)) { var trMatch = htmlBefore.match(LAST_TR_REGEX); var tr = trMatch ? trMatch[0] : ''; html = tr + html + ''; } if (html.match(LAST_TR_END_REGEX)) { var tableMatch = htmlBefore.match(LAST_TABLE_REGEX); var table = tableMatch ? tableMatch[0] : ''; html = table + html + '
    '; } return html; } exports.excelHandler = excelHandler; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/imageConverter/convertPasteContentForSingleImage.ts": /*!*****************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/imageConverter/convertPasteContentForSingleImage.ts ***! \*****************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Convert pasted content if there are HTML and Image data in the Clipboard * @param event The BeforePaste event */ function convertPasteContentForSingleImage(event, trustedHTMLHandler) { var fragment = event.fragment, clipboardData = event.clipboardData; var html = clipboardData.html, image = clipboardData.image; if (html && image) { //If there are Html in the clipboard, and the html body only have one img children, use the HTML var doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html'); (0, roosterjs_editor_dom_1.moveChildNodes)(fragment, doc === null || doc === void 0 ? void 0 : doc.body); } } exports.default = convertPasteContentForSingleImage; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/index.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/index.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Paste = void 0; var Paste_1 = __webpack_require__(/*! ./Paste */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/Paste.ts"); Object.defineProperty(exports, "Paste", { enumerable: true, get: function () { return Paste_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/lineMerge/handleLineMerge.ts": /*!******************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/lineMerge/handleLineMerge.ts ***! \******************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Process pasted content, if there are multiple blocks that are not wrapped by a shared ancestor node, * change the tag of first and last node to be SPAN so that it will be merged into current block * @param root Root node of content to process */ function handleLineMerge(root) { var traverser = roosterjs_editor_dom_1.ContentTraverser.createBodyTraverser(root); var blocks = []; for (var block = traverser === null || traverser === void 0 ? void 0 : traverser.currentBlockElement; block; block = traverser.getNextBlockElement()) { blocks.push({ start: block.getStartNode(), end: block.getEndNode(), }); } if (blocks.length > 0) { var blocksLength = blocks.length - 1; processBlock(blocks[0]); processBlock(blocks[blocksLength]); checkAndAddBr(root, blocks[0], true /*isFirst*/); checkAndAddBr(root, blocks[blocksLength], false /*isFirst*/, blocks[0]); } } exports.default = handleLineMerge; function processBlock(block) { var _a, _b; var start = block.start, end = block.end; if (start == end && (0, roosterjs_editor_dom_1.getTagOfNode)(start) == 'DIV') { var node = (0, roosterjs_editor_dom_1.changeElementTag)(start, 'SPAN'); block.start = node; block.end = node; if ((0, roosterjs_editor_dom_1.getTagOfNode)(node.lastChild) == 'BR') { node.removeChild(node.lastChild); } } else if ((0, roosterjs_editor_dom_1.getTagOfNode)(end) == 'BR') { var node = end.ownerDocument.createTextNode(''); (_a = end.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(node, end); block.end = node; (_b = end.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(end); } } function checkAndAddBr(root, block, isFirst, firstBlock) { var _a, _b, _c, _d; var blockElement = (0, roosterjs_editor_dom_1.getBlockElementAtNode)(root, block.start); var sibling = isFirst ? (0, roosterjs_editor_dom_1.getNextLeafSibling)(root, block.end) : (0, roosterjs_editor_dom_1.getPreviousLeafSibling)(root, block.start); if (!sibling) { return; } if (blockElement === null || blockElement === void 0 ? void 0 : blockElement.contains(sibling)) { var br = (_a = block.start.ownerDocument) === null || _a === void 0 ? void 0 : _a.createElement('br'); if (br) { var blockToUse = isFirst ? block.end : block.start; (_b = blockToUse.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(br, isFirst ? block.end.nextSibling : block.start); } } else if (firstBlock && firstBlock.end == firstBlock.start && (0, roosterjs_editor_dom_1.getTagOfNode)(firstBlock.end) == 'SPAN') { // If the first block and the last block are Siblings, add a BR before so the only two // lines that are being pasted are not merged. var previousSibling = (0, roosterjs_editor_dom_1.getPreviousLeafSibling)(root, block.start); if (firstBlock.end.contains(previousSibling)) { var br = (_c = block.start.ownerDocument) === null || _c === void 0 ? void 0 : _c.createElement('br'); if (br) { (_d = block.start.parentNode) === null || _d === void 0 ? void 0 : _d.insertBefore(br, block.start); } } } } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/ListItemBlock.ts": /*!****************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/ListItemBlock.ts ***! \****************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createListItemBlock = void 0; /** * @internal * Initialize an empty ListItemBlock */ function createListItemBlock(listItem) { if (listItem === void 0) { listItem = null; } return { startElement: listItem, endElement: listItem, insertPositionNode: null, listItemContainers: listItem ? [listItem] : [], }; } exports.createListItemBlock = createListItemBlock; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/convertPastedContentFromOfficeOnline.ts": /*!***************************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/convertPastedContentFromOfficeOnline.ts ***! \***************************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var constants_1 = __webpack_require__(/*! ../sourceValidations/constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts"); var convertPastedContentFromWordOnline_1 = __webpack_require__(/*! ./convertPastedContentFromWordOnline */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/convertPastedContentFromWordOnline.ts"); /** * @internal * Convert pasted content from Office Online * Once it is known that the document is from WAC * We need to remove the display property and margin from all the list item * @param event The BeforePaste event */ function convertPastedContentFromOfficeOnline(fragment) { fragment.querySelectorAll(constants_1.WAC_IDENTIFY_SELECTOR).forEach(function (el) { el.style.display = null; el.style.margin = null; }); // call conversion function if the pasted content is from word online and // has list element in the pasted content. if ((0, convertPastedContentFromWordOnline_1.isWordOnlineWithList)(fragment)) { (0, convertPastedContentFromWordOnline_1.default)(fragment); } } exports.default = convertPastedContentFromOfficeOnline; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/convertPastedContentFromWordOnline.ts": /*!*************************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/convertPastedContentFromWordOnline.ts ***! \*************************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isWordOnlineWithList = void 0; var ListItemBlock_1 = __webpack_require__(/*! ./ListItemBlock */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/ListItemBlock.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var WORD_ONLINE_IDENTIFYING_SELECTOR = 'div.ListContainerWrapper>ul[class^="BulletListStyle"],div.ListContainerWrapper>ol[class^="NumberListStyle"],span.WACImageContainer > img'; var LIST_CONTAINER_ELEMENT_CLASS_NAME = 'ListContainerWrapper'; var IMAGE_CONTAINER_ELEMENT_CLASS_NAME = 'WACImageContainer'; //When the list style is a symbol and the value is not in the clipboard, WordOnline var VALID_LIST_STYLE_CHAR_CODES = [ '111', '9643', '9830', //'♦' ]; /** * @internal */ function isWordOnlineWithList(fragment) { return !!(fragment && fragment.querySelector(WORD_ONLINE_IDENTIFYING_SELECTOR)); } exports.isWordOnlineWithList = isWordOnlineWithList; // Word Online pasted content DOM structure as of July 12th 2019 // // //
    ----------> this layer may exist depend on the content user paste //
    ----------> text content //

    //
    //
    ----------> list items: for unordered list, all the items on the same level is under the same wrapper //
      list items in the same list can be divided into different ListItemWrapper //
    • list items in the same list can also be divided into different Outline Group; //
    • //
    //
    //
    //
    //
    ----------> list items: for ordered list, each items has it's own wrapper //
      //
    1. //
    //
    //
    //
      //
    1. //
    //
    //
    // // // /** * @internal * Convert text copied from word online into text that's workable with rooster editor * @param fragment Document fragment that is being pasted into editor. */ function convertPastedContentFromWordOnline(fragment) { sanitizeListItemContainer(fragment); var listItemBlocks = getListItemBlocks(fragment); listItemBlocks.forEach(function (itemBlock) { // There are cases where consecutive List Elements are separated into different nodes: //
    //
    //
      //
      //
      //
        //
        //
        //
        //
        //
          //
          //
          // in the above case we want to collapse the two root level div into one and unwrap the list item nodes. // after the following flattening the list will become following: // //
          //
            //
            //
            //
              //
              //
              //
                //
                // Then we are start processing. flattenListBlock(fragment, itemBlock); // Find the node to insertBefore, which is next sibling node of the end of a listItemBlock. itemBlock.insertPositionNode = itemBlock.endElement.nextSibling; var convertedListElement; var doc = fragment.ownerDocument; itemBlock.listItemContainers.forEach(function (listItemContainer) { var listType = getContainerListType(listItemContainer); // list type that is contained by iterator. // Initialize processed element with proper listType if this is the first element if (!convertedListElement) { convertedListElement = createNewList(listItemContainer, doc, listType); } // Get all list items(
              1. ) in the current iterator element. var currentListItems = (0, roosterjs_editor_dom_1.toArray)(listItemContainer.querySelectorAll('li')); currentListItems.forEach(function (item) { // If item is in root level and the type of list changes then // insert the current list into body and then reinitialize the convertedListElement // Word Online is using data-aria-level to determine the the depth of the list item. var itemLevel = parseInt(item.getAttribute('data-aria-level')); // In first level list, there are cases where a consecutive list item DIV may have different list type // When that happens we need to insert the processed elements into the document, then change the list type // and keep the processing going. if ((0, roosterjs_editor_dom_1.getTagOfNode)(convertedListElement) != listType && itemLevel == 1) { insertConvertedListToDoc(convertedListElement, fragment, itemBlock); convertedListElement = createNewList(listItemContainer, doc, listType); } insertListItem(convertedListElement, item, listType, doc); }); }); insertConvertedListToDoc(convertedListElement, fragment, itemBlock); // Once we finish the process the list items and put them into a list. // After inserting the processed element, // we need to remove all the non processed node from the parent node. var parentContainer = itemBlock.startElement.parentNode; if (parentContainer) { itemBlock.listItemContainers.forEach(function (listItemContainer) { parentContainer.removeChild(listItemContainer); }); } }); var imageNodes = getImageNodes(fragment); imageNodes.forEach(function (node) { // Structure when pasting Word Wac Image as of 10/22/2021 // // // // // // // Since the second span inside of WACImageContainer have style display block it displays an additional space at the bottom of the image. // Removing the nodes that are not img will resolve the additional space if ((0, roosterjs_editor_dom_1.safeInstanceOf)(node, 'HTMLSpanElement')) { node.childNodes.forEach(function (childNode) { if ((0, roosterjs_editor_dom_1.getTagOfNode)(childNode) != 'IMG') { childNode.parentElement.removeChild(childNode); } }); } }); } exports.default = convertPastedContentFromWordOnline; function createNewList(listItemContainer, doc, tag) { var _a; var newList = doc.createElement(tag); var startAttribute = (_a = listItemContainer.firstElementChild) === null || _a === void 0 ? void 0 : _a.getAttribute('start'); if (startAttribute) { newList.setAttribute('start', startAttribute); } return newList; } /** * The node processing is based on the premise of only ol/ul is in ListContainerWrapper class * However the html might be malformed, this function is to split all the other elements out of ListContainerWrapper * @param fragment pasted document that contains all the list element. */ function sanitizeListItemContainer(fragment) { var listItemContainerListEl = (0, roosterjs_editor_dom_1.toArray)(fragment.querySelectorAll(WORD_ONLINE_IDENTIFYING_SELECTOR)); listItemContainerListEl.forEach(function (el) { var replaceRegex = new RegExp("\\b" + LIST_CONTAINER_ELEMENT_CLASS_NAME + "\\b", 'g'); if (el.previousSibling) { var prevParent = (0, roosterjs_editor_dom_1.splitParentNode)(el, true); prevParent.className = prevParent.className.replace(replaceRegex, ''); } if (el.nextSibling) { var nextParent = (0, roosterjs_editor_dom_1.splitParentNode)(el, false); nextParent.className = nextParent.className.replace(replaceRegex, ''); } }); } /** * Take all the list items in the document, and group the consecutive list times in a list block; * @param fragment pasted document that contains all the list element. */ function getListItemBlocks(fragment) { var listElements = fragment.querySelectorAll('.' + LIST_CONTAINER_ELEMENT_CLASS_NAME); var result = []; var curListItemBlock; for (var i = 0; i < listElements.length; i++) { var curItem = listElements[i]; if (!curListItemBlock) { curListItemBlock = (0, ListItemBlock_1.createListItemBlock)(curItem); } else { var listItemContainers = curListItemBlock.listItemContainers; var lastItemInCurBlock = listItemContainers[listItemContainers.length - 1]; if (curItem == lastItemInCurBlock.nextSibling || (0, roosterjs_editor_dom_1.getFirstLeafNode)(curItem) == (0, roosterjs_editor_dom_1.getNextLeafSibling)(lastItemInCurBlock.parentNode, lastItemInCurBlock)) { listItemContainers.push(curItem); curListItemBlock.endElement = curItem; } else { curListItemBlock.endElement = lastItemInCurBlock; result.push(curListItemBlock); curListItemBlock = (0, ListItemBlock_1.createListItemBlock)(curItem); } } } if ((curListItemBlock === null || curListItemBlock === void 0 ? void 0 : curListItemBlock.listItemContainers.length) > 0) { result.push(curListItemBlock); } return result; } /** * Flatten the list items, so that all the consecutive list items are under the same parent. * @param fragment Root element of that contains the element. * @param listItemBlock The list item block needed to be flattened. */ function flattenListBlock(fragment, listItemBlock) { var collapsedListItemSections = (0, roosterjs_editor_dom_1.collapseNodes)(fragment, listItemBlock.startElement, listItemBlock.endElement, true); collapsedListItemSections.forEach(function (section) { if ((0, roosterjs_editor_dom_1.getTagOfNode)(section.firstChild) == 'DIV') { (0, roosterjs_editor_dom_1.unwrap)(section); } }); } /** * Get the list type that the container contains. If there is no list in the container * return null; * @param listItemContainer Container that contains a list */ function getContainerListType(listItemContainer) { var tag = (0, roosterjs_editor_dom_1.getTagOfNode)(listItemContainer.firstChild); return tag == 'UL' || tag == 'OL' ? tag : null; } /** * Insert list item into the correct position of a list * @param listRootElement Root element of the list that is accepting a coming element. * @param itemToInsert List item that needed to be inserted. * @param listType Type of list(ul/ol) */ function insertListItem(listRootElement, itemToInsert, listType, doc) { var _a; if (!listType) { return; } // Get item level from 'data-aria-level' attribute var itemLevel = parseInt((_a = itemToInsert.getAttribute('data-aria-level')) !== null && _a !== void 0 ? _a : ''); // Try to reuse the List Marker var style = itemToInsert.getAttribute('data-leveltext'); if (listType == 'UL' && style && VALID_LIST_STYLE_CHAR_CODES.indexOf(style.charCodeAt(0).toString()) > -1) { itemToInsert.style.listStyleType = "\"" + style + " \""; } var curListLevel = listRootElement; // Level iterator to find the correct place for the current element. // if the itemLevel is 1 it means the level iterator is at the correct place. while (itemLevel > 1) { if (!curListLevel.firstChild) { // If the current level is empty, create empty list within the current level // then move the level iterator into the next level. curListLevel.appendChild(doc.createElement(listType)); curListLevel = curListLevel.firstElementChild; } else { // If the current level is not empty, the last item in the needs to be a UL or OL // and the level iterator should move to the UL/OL at the last position. var lastChild = curListLevel.lastElementChild; var lastChildTag = (0, roosterjs_editor_dom_1.getTagOfNode)(lastChild); if (lastChildTag == 'UL' || lastChildTag == 'OL') { // If the last child is a list(UL/OL), then move the level iterator to last child. curListLevel = lastChild; } else { // If the last child is not a list, then append a new list to the level // and move the level iterator to the new level. curListLevel.appendChild(doc.createElement(listType)); curListLevel = curListLevel.lastElementChild; } } itemLevel--; } // Once the level iterator is at the right place, then append the list item in the level. curListLevel.appendChild(itemToInsert); } /** * Insert the converted list item into the correct place. * @param convertedListElement List element that is converted from list item block * @param fragment Root element of that contains the converted listItemBlock * @param listItemBlock List item block that was converted. */ function insertConvertedListToDoc(convertedListElement, fragment, listItemBlock) { if (!convertedListElement) { return; } var insertPositionNode = listItemBlock.insertPositionNode; if (insertPositionNode) { var parentNode = insertPositionNode.parentNode; if (parentNode) { parentNode.insertBefore(convertedListElement, insertPositionNode); } } else { var parentNode = listItemBlock.startElement.parentNode; if (parentNode) { parentNode.appendChild(convertedListElement); } else { fragment.appendChild(convertedListElement); } } } function getImageNodes(fragment) { return fragment.querySelectorAll('.' + IMAGE_CONTAINER_ELEMENT_CLASS_NAME); } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/pptConverter/convertPastedContentFromPowerPoint.ts": /*!****************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/pptConverter/convertPastedContentFromPowerPoint.ts ***! \****************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Convert pasted content from PowerPoint * @param event The BeforePaste event */ function convertPastedContentFromPowerPoint(event, trustedHTMLHandler) { var fragment = event.fragment, clipboardData = event.clipboardData; if (clipboardData.html && !clipboardData.text && clipboardData.image) { // It is possible that PowerPoint copied both image and HTML but not plain text. // We always prefer HTML if any. var doc = new DOMParser().parseFromString(trustedHTMLHandler(clipboardData.html), 'text/html'); (0, roosterjs_editor_dom_1.moveChildNodes)(fragment, doc === null || doc === void 0 ? void 0 : doc.body); } } exports.default = convertPastedContentFromPowerPoint; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sanitizeHtmlColorsFromPastedContent/deprecatedColorList.ts": /*!************************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sanitizeHtmlColorsFromPastedContent/deprecatedColorList.ts ***! \************************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @internal * List of deprecated colors that should be removed */ Object.defineProperty(exports, "__esModule", { value: true }); exports.DeprecatedColorList = void 0; exports.DeprecatedColorList = [ 'activeborder', 'activecaption', 'appworkspace', 'background', 'buttonhighlight', 'buttonshadow', 'captiontext', 'inactiveborder', 'inactivecaption', 'inactivecaptiontext', 'infobackground', 'infotext', 'menu', 'menutext', 'scrollbar', 'threeddarkshadow', 'threedface', 'threedhighlight', 'threedlightshadow', 'threedfhadow', 'window', 'windowframe', 'windowtext', ]; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sanitizeHtmlColorsFromPastedContent/sanitizeHtmlColorsFromPastedContent.ts": /*!****************************************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sanitizeHtmlColorsFromPastedContent/sanitizeHtmlColorsFromPastedContent.ts ***! \****************************************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var deprecatedColorList_1 = __webpack_require__(/*! ./deprecatedColorList */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sanitizeHtmlColorsFromPastedContent/deprecatedColorList.ts"); /** * @internal * Remove the deprecated colors from pasted content * @param sanitizingOption the sanitizingOption of BeforePasteEvent * */ function sanitizeHtmlColorsFromPastedContent(sanitizingOption) { ['color', 'background-color'].forEach(function (property) { (0, roosterjs_editor_dom_1.chainSanitizerCallback)(sanitizingOption.cssStyleCallbacks, property, function (value) { return deprecatedColorList_1.DeprecatedColorList.indexOf(value) < 0; }); }); } exports.default = sanitizeHtmlColorsFromPastedContent; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sanitizeLinks/sanitizeLinks.ts": /*!********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sanitizeLinks/sanitizeLinks.ts ***! \********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var HTTP = 'http:'; var HTTPS = 'https:'; /** * @internal * Clear local paths and remove link * @param sanitizingOption the sanitizingOption of BeforePasteEvent * */ function sanitizeLinks(sanitizingOption) { (0, roosterjs_editor_dom_1.chainSanitizerCallback)(sanitizingOption.attributeCallbacks, 'href', function (value, element) { return validateLink(value, element); }); } exports.default = sanitizeLinks; function validateLink(link, htmlElement) { var url; try { url = new URL(link); } catch (_a) { url = undefined; } if (url && (url.protocol === HTTP || url.protocol === HTTPS)) { return link; } htmlElement.removeAttribute('href'); return ''; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts": /*!********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts ***! \********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WAC_IDENTIFY_SELECTOR = exports.PROG_ID_NAME = exports.GOOGLE_SHEET_NODE_NAME = void 0; /** * @internal * Node attribute used to identify if the content is from Google Sheets. */ exports.GOOGLE_SHEET_NODE_NAME = 'google-sheets-html-origin'; /** * @internal * Name of the HTMLMeta Property that provides the Office App Source of the pasted content */ exports.PROG_ID_NAME = 'ProgId'; /** * @internal * Selector used to identify Wac Elements */ exports.WAC_IDENTIFY_SELECTOR = 'ul[class^="BulletListStyle"]>.OutlineElement,ol[class^="NumberListStyle"]>.OutlineElement,span.WACImageContainer'; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/documentContainWacElements.ts": /*!*************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/documentContainWacElements.ts ***! \*************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var constants_1 = __webpack_require__(/*! ./constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts"); /** * @internal * Check whether the fragment provided contain Wac Elements * @param props Properties related to the PasteEvent * @returns */ var documentContainWacElements = function (props) { var fragment = props.fragment; return !!fragment.querySelector(constants_1.WAC_IDENTIFY_SELECTOR); }; exports.default = documentContainWacElements; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/getPasteSource.ts": /*!*************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/getPasteSource.ts ***! \*************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var documentContainWacElements_1 = __webpack_require__(/*! ./documentContainWacElements */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/documentContainWacElements.ts"); var isExcelDesktopDocument_1 = __webpack_require__(/*! ./isExcelDesktopDocument */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isExcelDesktopDocument.ts"); var isGoogleSheetDocument_1 = __webpack_require__(/*! ./isGoogleSheetDocument */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isGoogleSheetDocument.ts"); var isPowerPointDesktopDocument_1 = __webpack_require__(/*! ./isPowerPointDesktopDocument */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isPowerPointDesktopDocument.ts"); var isWordDesktopDocument_1 = __webpack_require__(/*! ./isWordDesktopDocument */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isWordDesktopDocument.ts"); var shouldConvertToSingleImage_1 = __webpack_require__(/*! ./shouldConvertToSingleImage */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/shouldConvertToSingleImage.ts"); var getSourceFunctions = new Map([ [0 /* WordDesktop */, isWordDesktopDocument_1.default], [1 /* ExcelDesktop */, isExcelDesktopDocument_1.default], [2 /* PowerPointDesktop */, isPowerPointDesktopDocument_1.default], [4 /* WacComponents */, documentContainWacElements_1.default], [3 /* GoogleSheets */, isGoogleSheetDocument_1.default], [6 /* SingleImage */, shouldConvertToSingleImage_1.default], ]); /** * @internal * This function tries to get the source of the Pasted content * @param event the before paste event * @param shouldConvertSingleImage Whether convert single image is enabled. * @returns The Type of pasted content, if no type found will return {KnownSourceType.Default} */ function getPasteSource(event, shouldConvertSingleImage) { var htmlAttributes = event.htmlAttributes, clipboardData = event.clipboardData, fragment = event.fragment; var result = null; var param = { htmlAttributes: htmlAttributes, fragment: fragment, shouldConvertSingleImage: shouldConvertSingleImage, clipboardData: clipboardData, }; getSourceFunctions.forEach(function (func, key) { if (!result && func(param)) { result = key; } }); return result !== null && result !== void 0 ? result : 5 /* Default */; } exports.default = getPasteSource; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isExcelDesktopDocument.ts": /*!*********************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isExcelDesktopDocument.ts ***! \*********************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var constants_1 = __webpack_require__(/*! ./constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts"); var EXCEL_ATTRIBUTE_NAME = 'xmlns:x'; var EXCEL_ATTRIBUTE_VALUE = 'urn:schemas-microsoft-com:office:excel'; var EXCEL_ONLINE_ATTRIBUTE_VALUE = 'Excel.Sheet'; /** * @internal * Checks whether the Array provided contains strings that identify Excel Desktop documents * @param props Properties related to the PasteEvent * @returns */ var isExcelDesktopDocument = function (props) { var htmlAttributes = props.htmlAttributes; return (htmlAttributes[EXCEL_ATTRIBUTE_NAME] == EXCEL_ATTRIBUTE_VALUE || htmlAttributes[constants_1.PROG_ID_NAME] == EXCEL_ONLINE_ATTRIBUTE_VALUE); }; exports.default = isExcelDesktopDocument; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isGoogleSheetDocument.ts": /*!********************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isGoogleSheetDocument.ts ***! \********************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var constants_1 = __webpack_require__(/*! ./constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts"); /** * @internal * Checks whether the fragment provided contain elements from Google sheets * @param props Properties related to the PasteEvent * @returns */ var isGoogleSheetDocument = function (props) { var fragment = props.fragment; return !!fragment.querySelector(constants_1.GOOGLE_SHEET_NODE_NAME); }; exports.default = isGoogleSheetDocument; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isPowerPointDesktopDocument.ts": /*!**************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isPowerPointDesktopDocument.ts ***! \**************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var constants_1 = __webpack_require__(/*! ./constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts"); var POWERPOINT_ATTRIBUTE_VALUE = 'PowerPoint.Slide'; /** * @internal * Checks whether the Array provided contains strings that identify Power Point Desktop documents * @param props Properties related to the PasteEvent * @returns */ var isPowerPointDesktopDocument = function (props) { return props.htmlAttributes[constants_1.PROG_ID_NAME] == POWERPOINT_ATTRIBUTE_VALUE; }; exports.default = isPowerPointDesktopDocument; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isWordDesktopDocument.ts": /*!********************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/isWordDesktopDocument.ts ***! \********************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var constants_1 = __webpack_require__(/*! ./constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/constants.ts"); var WORD_ATTRIBUTE_NAME = 'xmlns:w'; var WORD_ATTRIBUTE_VALUE = 'urn:schemas-microsoft-com:office:word'; var WORD_PROG_ID = 'Word.Document'; /** * @internal * Checks whether the Array provided contains strings that identify Word Desktop documents * @param props Properties related to the PasteEvent * @returns */ var isWordDesktopDocument = function (props) { var htmlAttributes = props.htmlAttributes; return (htmlAttributes[WORD_ATTRIBUTE_NAME] == WORD_ATTRIBUTE_VALUE || htmlAttributes[constants_1.PROG_ID_NAME] == WORD_PROG_ID); }; exports.default = isWordDesktopDocument; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/shouldConvertToSingleImage.ts": /*!*************************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/sourceValidations/shouldConvertToSingleImage.ts ***! \*************************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * @internal * Checks whether the fragment only contains a single image to paste * and the editor have the ConvertSingleImageBody Experimental feature * @param props Properties related to the PasteEvent * @returns */ var shouldConvertToSingleImage = function (props) { var _a; var shouldConvertSingleImage = props.shouldConvertSingleImage, clipboardData = props.clipboardData; return (shouldConvertSingleImage && ((_a = clipboardData.htmlFirstLevelChildTags) === null || _a === void 0 ? void 0 : _a.length) == 1 && clipboardData.htmlFirstLevelChildTags[0] == 'IMG'); }; exports.default = shouldConvertToSingleImage; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/LevelLists.ts": /*!*****************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/LevelLists.ts ***! \*****************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createLevelLists = void 0; /** * @internal * create an empty LevelLists */ function createLevelLists() { return { listsMetadata: {}, currentUniqueListId: -1, }; } exports.createLevelLists = createLevelLists; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/WordConverterArguments.ts": /*!*****************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/WordConverterArguments.ts ***! \*****************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createWordConverterArguments = void 0; var LevelLists_1 = __webpack_require__(/*! ./LevelLists */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/LevelLists.ts"); /** * @internal * create an empty WordConverterArguments */ function createWordConverterArguments(nodes) { return { nodes: nodes, currentIndex: 0, lists: {}, listItems: [], currentListIdsByLevels: [(0, LevelLists_1.createLevelLists)()], lastProcessedItem: null, }; } exports.createWordConverterArguments = createWordConverterArguments; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/WordCustomData.ts": /*!*********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/WordCustomData.ts ***! \*********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getObject = exports.setObject = exports.createCustomData = void 0; /** NodeId attribute */ var NODE_ID_ATTRIBUTE_NAME = 'NodeId'; /** * @internal * Create an empty WordCustomData */ function createCustomData() { return { dict: {}, nextNodeId: 1, }; } exports.createCustomData = createCustomData; /** * @internal * Sets the specified object data */ function setObject(wordCustomData, element, key, value) { // Get the id for the element if (element.nodeType == 1 /* Element */) { var id = getAndSetNodeId(wordCustomData, element); if (id != '') { // Get the values for the element if (!wordCustomData.dict[id]) { // First time dictionary creation wordCustomData.dict[id] = {}; } wordCustomData.dict[id][key] = value; } } } exports.setObject = setObject; /** * @internal * Reads the specified object data */ function getObject(wordCustomData, element, key) { if (element.nodeType == 1 /* Element */) { var id = getAndSetNodeId(wordCustomData, element); if (id != '') { return wordCustomData.dict[id] && wordCustomData.dict[id][key]; } } return null; } exports.getObject = getObject; /** * Get the unique id for the specified node... */ function getAndSetNodeId(wordCustomData, element) { var id = element.getAttribute(NODE_ID_ATTRIBUTE_NAME); if (!id) { id = wordCustomData.nextNodeId.toString(); wordCustomData.nextNodeId++; element.setAttribute(NODE_ID_ATTRIBUTE_NAME, id); } return id; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/commentsRemoval.ts": /*!**********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/commentsRemoval.ts ***! \**********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var MSO_COMMENT_PARENT = 'mso-comment-parent'; var MSO_COMMENT_REFERENCE = 'mso-comment-reference'; var MSO_COMMENT_DATE = 'mso-comment-date'; var MSO_COMMENT_ANCHOR_HREF_REGEX = /#_msocom_/; var MSO_SPECIAL_CHARACTER = 'mso-special-character'; var MSO_SPECIAL_CHARACTER_COMMENT = 'comment'; var MSO_COMMENT_CONTINUATION = 'mso-comment-continuation'; var MSO_ELEMENT = 'mso-element'; var MSO_ELEMENT_COMMENT_LIST = 'comment-list'; var MSO_COMMENT_DONE = 'mso-comment-done'; /** * @internal * Removes comments when pasting Word content. */ function commentsRemoval(elementCallbacks, styleCallbacks) { // 1st Step, Remove SPAN elements added after each comment. // Word adds multiple elements for comments as SPAN elements. // In this step we remove these elements: // Structure as of 4/18/2022 // 1.   // 2. // // // [RS2] //   // // // (0, roosterjs_editor_dom_1.chainSanitizerCallback)(elementCallbacks, 'SPAN', function (element) { var _a; var styles = (0, roosterjs_editor_dom_1.getStyles)(element); if (styles[MSO_SPECIAL_CHARACTER] == MSO_SPECIAL_CHARACTER_COMMENT) { (_a = element.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(element); } return true; }); // 2nd Step, Modify Anchor elements. // 1. When the element was selected to add a comment in Word, the selection is converted to // an anchor element, so we change the tag to span. // 2. Word also adds some Anchor elements with the following structure: // Structure as of 4/18/2022 // [SS3] // In this step we remove this Anchor elements. (0, roosterjs_editor_dom_1.chainSanitizerCallback)(elementCallbacks, 'A', function (element) { var _a; if ((0, roosterjs_editor_dom_1.safeInstanceOf)(element, 'HTMLAnchorElement') && MSO_COMMENT_ANCHOR_HREF_REGEX.test(element.href)) { (_a = element.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(element); } return true; }); // 3rd Step, remove List of comments. // When the document have a long thread of comments, these comments are appended // at the end of the copied fragment, we also need to remove it. // Structure as of 4/18/2022 // //
                //
                //
                ...
                //
                ...
                //
                ...
                //
                // (0, roosterjs_editor_dom_1.chainSanitizerCallback)(elementCallbacks, 'DIV', function (element) { var styles = (0, roosterjs_editor_dom_1.getStyles)(element); if (styles[MSO_ELEMENT] == MSO_ELEMENT_COMMENT_LIST) { (0, roosterjs_editor_dom_1.moveChildNodes)(element); } return true; }); /** * Remove styles related to Office Comments that can cause unwanted behaviors * depending on the user client */ [ MSO_COMMENT_REFERENCE, MSO_COMMENT_DATE, MSO_COMMENT_PARENT, MSO_COMMENT_CONTINUATION, MSO_COMMENT_DONE, ].forEach(function (style) { return (0, roosterjs_editor_dom_1.chainSanitizerCallback)(styleCallbacks, style, function () { return false; }); }); } exports.default = commentsRemoval; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/convertPastedContentFromWord.ts": /*!***********************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/convertPastedContentFromWord.ts ***! \***********************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var commentsRemoval_1 = __webpack_require__(/*! ./commentsRemoval */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/commentsRemoval.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var wordConverter_1 = __webpack_require__(/*! ./wordConverter */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/wordConverter.ts"); var WordConverterArguments_1 = __webpack_require__(/*! ./WordConverterArguments */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/WordConverterArguments.ts"); var converterUtils_1 = __webpack_require__(/*! ./converterUtils */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/converterUtils.ts"); var PERCENTAGE_REGEX = /%/; var DEFAULT_BROWSER_LINE_HEIGHT_PERCENTAGE = 120; var LIST_ELEMENTS_SELECTOR = 'p,h1,h2,h3,h4,h5,h6'; /** * @internal * Converts all the Word generated list items in the specified node into standard HTML UL and OL tags */ function convertPastedContentFromWord(event) { var sanitizingOption = event.sanitizingOption, fragment = event.fragment; // Preserve when its innerHTML is " " to avoid dropping an empty line (0, roosterjs_editor_dom_1.chainSanitizerCallback)(sanitizingOption.elementCallbacks, 'O:P', function (element) { (0, roosterjs_editor_dom_1.moveChildNodes)(element); element.appendChild(element.ownerDocument.createTextNode('\u00A0')); //   return true; }); var wordConverter = (0, wordConverter_1.createWordConverter)(); // First find all the nodes that we need to check for list item information // This call will return all the p and header elements under the root node.. These are the elements that // Word uses a list items, so we'll only process them and avoid walking the whole tree. var elements = fragment.querySelectorAll(LIST_ELEMENTS_SELECTOR); if (elements.length > 0) { wordConverter.wordConverterArgs = (0, WordConverterArguments_1.createWordConverterArguments)(elements); if ((0, converterUtils_1.processNodesDiscovery)(wordConverter)) { (0, converterUtils_1.processNodeConvert)(wordConverter); } } // If the List style contains marginBottom = 0in, the space after the list is going to be too narrow. // Remove this style so the list displays correctly. ['OL', 'UL'].forEach(function (tag) { (0, roosterjs_editor_dom_1.chainSanitizerCallback)(sanitizingOption.elementCallbacks, tag, function (element) { if (element.style.marginBottom == '0in') { element.style.marginBottom = ''; } return true; }); }); //If the line height is less than the browser default line height, line between the text is going to be too narrow (0, roosterjs_editor_dom_1.chainSanitizerCallback)(sanitizingOption.cssStyleCallbacks, 'line-height', function (value) { var parsedLineHeight; if (PERCENTAGE_REGEX.test(value) && !isNaN((parsedLineHeight = parseInt(value))) && parsedLineHeight < DEFAULT_BROWSER_LINE_HEIGHT_PERCENTAGE) { return false; } return true; }); (0, commentsRemoval_1.default)(sanitizingOption.elementCallbacks, sanitizingOption.cssStyleCallbacks); } exports.default = convertPastedContentFromWord; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/converterUtils.ts": /*!*********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/converterUtils.ts ***! \*********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.processNodeConvert = exports.processNodesDiscovery = void 0; var LevelLists_1 = __webpack_require__(/*! ./LevelLists */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/LevelLists.ts"); var WordCustomData_1 = __webpack_require__(/*! ./WordCustomData */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/WordCustomData.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** Word list metadata style name */ var LOOKUP_DEPTH = 5; /** Name for the word list id property in the custom data */ var UNIQUE_LIST_ID_CUSTOM_DATA = 'UniqueListId'; /** Word list metadata style name */ var MSO_LIST_STYLE_NAME = 'mso-list'; /** Regular expression to match line breaks */ var LINE_BREAKS = /[\n|\r]/gi; /** * @internal * Handles the pass 1: Discovery * During discovery, we'll parse the metadata out of the elements and store it in the list items dictionary. * We'll detect cases where the list items for a particular ordered list are not next to each other. Word does these * for numbered headers, and we don't want to convert those, because the numbering would be completely wrong. */ function processNodesDiscovery(wordConverter) { var args = wordConverter.wordConverterArgs; while (args.currentIndex < args.nodes.length) { var node = args.nodes.item(args.currentIndex); // Try to get the list metadata for the specified node var itemMetadata = getListItemMetadata(node); if (itemMetadata) { var levelInfo = args.currentListIdsByLevels[itemMetadata.level - 1] || (0, LevelLists_1.createLevelLists)(); args.currentListIdsByLevels[itemMetadata.level - 1] = levelInfo; // We need to drop some list information if this is not an item next to another if (args.lastProcessedItem && getRealPreviousSibling(node) != args.lastProcessedItem) { // This list item is not next to the previous one. This means that there is some content in between them // so we need to reset our list of list ids per level resetCurrentLists(args); } // Get the list metadata for the list that will hold this item var listMetadata = levelInfo.listsMetadata[itemMetadata.wordListId]; if (!listMetadata) { // Get the first item fake bullet.. This will be used later to check what is the right type of list var firstFakeBullet = getFakeBulletText(node, LOOKUP_DEPTH); // This is a the first item of a list.. We'll create the list metadata using the information // we already have from this first item listMetadata = { numberOfItems: 0, uniqueListId: wordConverter.nextUniqueId++, firstFakeBullet: firstFakeBullet, // If the bullet we got is empty or not found, we ignore the list out.. this means // that this is not an item we need to convert of that the format doesn't match what // we are expecting ignore: !firstFakeBullet || firstFakeBullet.length == 0, // We'll use the first fake bullet to try to figure out which type of list we create. If this list has a second // item, we'll perform a better comparison, but for one item lists, this will be check that will determine the list type tagName: getFakeBulletTagName(firstFakeBullet), }; levelInfo.listsMetadata[itemMetadata.wordListId] = listMetadata; args.lists[listMetadata.uniqueListId.toString()] = listMetadata; } else if (!listMetadata.ignore && listMetadata.numberOfItems == 1) { // This is the second item we've seen for this list.. we'll compare the 2 fake bullet // items we have an decide if we create ordered or unordered lists based on this. // This is the best way we can do this since we cannot read the metadata that Word // puts in the head of the HTML... var secondFakeBullet = getFakeBulletText(node, LOOKUP_DEPTH); listMetadata.tagName = listMetadata.firstFakeBullet == secondFakeBullet ? 'UL' : 'OL'; } // Set the unique id to the list itemMetadata.uniqueListId = listMetadata.uniqueListId; // Check if we need to ignore this list... we'll either know already that we need to ignore // it, or we'll know it because the previous list items are not next to this one if (listMetadata.ignore || (listMetadata.tagName == 'OL' && listMetadata.numberOfItems > 0 && levelInfo.currentUniqueListId != itemMetadata.uniqueListId)) { // We need to ignore this item... and we also need to forget about the lists that // are not at the root level listMetadata.ignore = true; args.currentListIdsByLevels[0].currentUniqueListId = -1; args.currentListIdsByLevels = args.currentListIdsByLevels.slice(0, 1); } else { // This is an item we don't need to ignore... If added lists deep under this one before // we'll drop their ids from the list of ids per level.. this is because this list item // breaks the deeper lists. if (args.currentListIdsByLevels.length > itemMetadata.level) { args.currentListIdsByLevels = args.currentListIdsByLevels.slice(0, itemMetadata.level); } levelInfo.currentUniqueListId = itemMetadata.uniqueListId; // Add the list item into the list of items to be processed args.listItems.push(itemMetadata); listMetadata.numberOfItems++; } args.lastProcessedItem = node; } else { // Here, we know that this is not a list item, but we'll want to check if it is one "no bullet" list items... // these can be created by creating a bullet and hitting delete on it it... The content will continue to be indented, but there will // be no bullet and the list will continue correctly after that. Visually, it looks like the previous item has multiple lines, but // the HTML generated has multiple paragraphs with the same class. We'll merge these when we find them, so the logic doesn't skips // the list conversion thinking that the list items are not together... var last = args.lastProcessedItem; if (last && getRealPreviousSibling(node) == last && node.tagName == last.tagName && node.className == last.className) { // Add 2 line breaks and move all the nodes to the last item last.appendChild(last.ownerDocument.createElement('br')); last.appendChild(last.ownerDocument.createElement('br')); (0, roosterjs_editor_dom_1.moveChildNodes)(last, node, true /*keepExistingChildren*/); // Remove the item that we don't need anymore node.parentNode.removeChild(node); } } // Move to the next element are return true if more elements need to be processed args.currentIndex++; } return args.listItems.length > 0; } exports.processNodesDiscovery = processNodesDiscovery; /** * @internal * Handles the pass 2: Conversion * During conversion, we'll go over the elements that belong to a list that we've marked as a list to convert, and we'll perform the * conversion needed */ function processNodeConvert(wordConverter) { var args = wordConverter.wordConverterArgs; args.currentIndex = 0; while (args.currentIndex < args.listItems.length) { var metadata = args.listItems[args.currentIndex]; var node = metadata.originalNode; var listMetadata = args.lists[metadata.uniqueListId.toString()]; if (!listMetadata.ignore) { // We have a list item that we need to convert, get or create the list // that hold this item out var list = getOrCreateListForNode(wordConverter, node, metadata, listMetadata); if (list) { // Clean the element out.. this call gets rid of the fake bullet and unneeded nodes cleanupListIgnore(node, LOOKUP_DEPTH); // Create a new list item and transfer the children var li = node.ownerDocument.createElement('LI'); if ((0, roosterjs_editor_dom_1.getTagOfNode)(node).startsWith('H')) { var clone = node.cloneNode(true /* deep */); clone.style.textIndent = ''; clone.style.marginLeft = ''; clone.style.marginRight = ''; li.appendChild(clone); } else { (0, roosterjs_editor_dom_1.moveChildNodes)(li, node); } // Append the list item into the list list.appendChild(li); // Remove the node we just converted node.parentNode.removeChild(node); if (listMetadata.tagName == 'UL') { wordConverter.numBulletsConverted++; } else { wordConverter.numNumberedConverted++; } } } args.currentIndex++; } return wordConverter.numBulletsConverted > 0 || wordConverter.numNumberedConverted > 0; } exports.processNodeConvert = processNodeConvert; /** * Gets or creates the list (UL or OL) that holds this item out based on the * items content and the specified metadata */ function getOrCreateListForNode(wordConverter, node, metadata, listMetadata) { // First get the last list next to this node under the specified level. This code // path will return the list or will create lists if needed var list = recurringGetOrCreateListAtNode(node, metadata.level, listMetadata); // Here use the unique list ID to detect if we have the right list... // it is possible to have 2 different lists next to each other with different formats, so // we want to detect this an create separate lists for those cases var listId = (0, WordCustomData_1.getObject)(wordConverter.wordCustomData, list, UNIQUE_LIST_ID_CUSTOM_DATA); // If we have a list with and ID, but the ID is different than the ID for this list item, this // is a completely new list, so we'll append a new list for that if ((listId && listId != metadata.uniqueListId) || (!listId && list.firstChild)) { var newList = node.ownerDocument.createElement(listMetadata.tagName); list.parentNode.insertBefore(newList, list.nextSibling); list = newList; } // Set the list id into the custom data (0, WordCustomData_1.setObject)(wordConverter.wordCustomData, list, UNIQUE_LIST_ID_CUSTOM_DATA, metadata.uniqueListId); // This call will convert the list if needed to the right type of list required. This can happen // on the cases where the first list item for this list is located after a deeper list. for that // case, we will have created a UL for it, and we may need to convert it return convertListIfNeeded(wordConverter, list, listMetadata); } /** * Converts the list between UL and OL if needed, by using the fake bullet and * information already stored in the list itself */ function convertListIfNeeded(wordConverter, list, listMetadata) { // Check if we need to convert the list out if (listMetadata.tagName != (0, roosterjs_editor_dom_1.getTagOfNode)(list)) { // We have the wrong list type.. convert it, set the id again and transfer all the children var newList = list.ownerDocument.createElement(listMetadata.tagName); (0, WordCustomData_1.setObject)(wordConverter.wordCustomData, newList, UNIQUE_LIST_ID_CUSTOM_DATA, (0, WordCustomData_1.getObject)(wordConverter.wordCustomData, list, UNIQUE_LIST_ID_CUSTOM_DATA)); (0, roosterjs_editor_dom_1.moveChildNodes)(newList, list); list.parentNode.insertBefore(newList, list); list.parentNode.removeChild(list); list = newList; } return list; } /** * Gets or creates the specified list */ function recurringGetOrCreateListAtNode(node, level, listMetadata) { var parent = null; var possibleList; if (level == 1) { // Root case, we'll check if the list is the previous sibling of the node possibleList = getRealPreviousSibling(node); } else { // If we get here, we are looking for level 2 or deeper... get the upper list // and check if the last element is a list parent = recurringGetOrCreateListAtNode(node, level - 1, null); possibleList = parent.lastChild; } // Check the element that we got and verify that it is a list if (possibleList && possibleList.nodeType == 1 /* Element */) { var tag = (0, roosterjs_editor_dom_1.getTagOfNode)(possibleList); if (tag == 'UL' || tag == 'OL') { // We have a list.. use it return possibleList; } } // If we get here, it means we don't have a list and we need to create one // this code path will always create new lists as UL lists var newList = node.ownerDocument.createElement(listMetadata ? listMetadata.tagName : 'UL'); if (level == 1) { // For level 1, we'll insert the list before the node node.parentNode.insertBefore(newList, node); } else { // Any level 2 or above, we insert the list as the last // child of the upper level list parent.appendChild(newList); } return newList; } /** * Cleans up the node children by removing the children marked as mso-list: Ignore. * This nodes hold the fake bullet information that Word puts in and when * conversion is happening, we want to get rid of these elements */ function cleanupListIgnore(node, levels) { var nodesToRemove = []; for (var child = node.firstChild; child; child = child.nextSibling) { // Clean up the item internally first if we need to based on the number of levels if (child.nodeType == 1 /* Element */ && levels > 1) { cleanupListIgnore(child, levels - 1); } // Try to convert word comments into ignore elements if we haven't done so for this element child = fixWordListComments(child, true /*removeComments*/); // Check if we can remove this item out if (isEmptySpan(child) || isIgnoreNode(child)) { nodesToRemove.push(child); } } nodesToRemove.forEach(function (child) { return node.removeChild(child); }); } /** * Reads the word list meta dada out of the specified node. If the node * is not a Word list item, it returns null. */ function getListItemMetadata(node) { if (node.nodeType == 1 /* Element */) { var listAttribute = getStyleValue(node, MSO_LIST_STYLE_NAME); if (listAttribute && listAttribute.length > 0) { try { // Word mso-list property holds 3 space separated values in the following format: lst1 level1 lfo0 // Where: // (0) List identified for the metadata in the <head> of the document. We cannot read the <head> meta data // (1) Level of the list. This also maps to the <head> metadata that we cannot read, but // for almost all cases, it maps to the list indentation (or level). We'll use it as the // list indentation value // (2) Contains a specific list identifier. // Example value: "l0 level1 lfo1" var listProps = listAttribute.split(' '); if (listProps.length == 3) { return { level: parseInt(listProps[1].substr('level'.length)), wordListId: listAttribute, originalNode: node, uniqueListId: 0, }; } } catch (e) { } } } return null; } function isFakeBullet(fakeBullet) { return ['o', '·', '§', '-'].indexOf(fakeBullet) >= 0; } /** Given a fake bullet text, returns the type of list that should be used for it */ function getFakeBulletTagName(fakeBullet) { return isFakeBullet(fakeBullet) ? 'UL' : 'OL'; } /** * Finds the fake bullet text out of the specified node and returns it. For images, it will return * a bullet string. If not found, it returns null... */ function getFakeBulletText(node, levels) { // Word uses the following format for their bullets: // <p style="mso-list:l1 level1 lfo2"> // <span style="..."> // <span style="mso-list:Ignore">1.<span style="...">      </span></span> // </span> // Content here... // </p> // // Basically, we need to locate the mso-list:Ignore SPAN, which holds either one text or image node. That // text or image node will be the fake bullet we are looking for var result = null; var child = node.firstChild; while (!result && child) { // First, check if we need to convert the Word list comments into real elements child = fixWordListComments(child, true /*removeComments*/); // Check if this is the node that holds the fake bullets (mso-list: Ignore) if (isIgnoreNode(child)) { // Yes... this is the node that holds either the text or image data result = child.textContent.trim(); // This is the case for image case if (result.length == 0) { result = 'o'; } } else if (child.nodeType == 1 /* Element */ && levels > 1) { // If this is an element and we are not in the last level, try to get the fake bullet // out of the child result = getFakeBulletText(child, levels - 1); } child = child.nextSibling; } return result; } /** * If the specified element is a Word List comments, this code verifies and fixes * the markup when needed to ensure that Chrome bullet conversions work as expected * ----- * We'll convert <!--[if !supportLists]--> and <!--[endif]--> comments into * <span style="mso-list:Ignore"></span>... Chrome has a bug where it drops the * styles of the span, but we'll use these comments to recreate them out */ function fixWordListComments(child, removeComments) { if (child.nodeType == 8 /* Comment */) { var value = child.data; if (value && value.trim().toLowerCase() == '[if !supportlists]') { // We have a list ignore start, find the end.. We know is not more than // 3 nodes away, so we'll optimize our checks var nextElement = child; var endComment = null; for (var j = 0; j < 4; j++) { nextElement = getRealNextSibling(nextElement); if (!nextElement) { break; } if (nextElement.nodeType == 8 /* Comment */) { value = nextElement.data; if (value && value.trim().toLowerCase() == '[endif]') { endComment = nextElement; break; } } } // if we found the end node, wrap everything out if (endComment) { var newSpan = child.ownerDocument.createElement('span'); newSpan.setAttribute('style', 'mso-list: ignore'); nextElement = getRealNextSibling(child); while (nextElement != endComment) { nextElement = nextElement.nextSibling; newSpan.appendChild(nextElement.previousSibling); } // Insert the element out and use that one as the current child endComment.parentNode.insertBefore(newSpan, endComment); // Remove the comments out if the call specified it out if (removeComments) { child.parentNode.removeChild(child); endComment.parentNode.removeChild(endComment); } // Last, make sure we return the new element out instead of the comment child = newSpan; } } } return child; } /** Finds the real previous sibling, ignoring empty text nodes */ function getRealPreviousSibling(node) { var prevSibling = node; do { prevSibling = prevSibling.previousSibling; } while (prevSibling && isEmptyTextNode(prevSibling)); return prevSibling; } /** Finds the real next sibling, ignoring empty text nodes */ function getRealNextSibling(node) { var nextSibling = node; do { nextSibling = nextSibling.nextSibling; } while (nextSibling && isEmptyTextNode(nextSibling)); return nextSibling; } /** * Checks if the specified node is marked as a mso-list: Ignore. These * nodes need to be ignored when a list item is converted into standard * HTML lists */ function isIgnoreNode(node) { if (node.nodeType == 1 /* Element */) { var listAttribute = getStyleValue(node, MSO_LIST_STYLE_NAME); if (listAttribute && listAttribute.length > 0 && listAttribute.trim().toLowerCase() == 'ignore') { return true; } } return false; } /** Checks if the specified node is an empty span. */ function isEmptySpan(node) { return (0, roosterjs_editor_dom_1.getTagOfNode)(node) == 'SPAN' && !node.firstChild; } /** Reads the specified style value from the node */ function getStyleValue(node, styleName) { // Word uses non-standard names for the metadata that puts in the style of the element... // Most browsers will not provide the information for those nonstandard values through the node.style // property, so the only reliable way to read them is to get the attribute directly and do // the required parsing.. return (0, roosterjs_editor_dom_1.getStyles)(node)[styleName] || null; } /** Checks if the node is an empty text node that can be ignored */ function isEmptyTextNode(node) { // No node is empty if (!node) { return true; } // Empty text node is empty if (node.nodeType == 3 /* Text */) { var value = node.nodeValue; value = value.replace(LINE_BREAKS, ''); return value.trim().length == 0; } // Span or Font with an empty child node is empty var tagName = (0, roosterjs_editor_dom_1.getTagOfNode)(node); if (node.firstChild == node.lastChild && (tagName == 'SPAN' || tagName == 'FONT')) { return isEmptyTextNode(node.firstChild); } // If not found, then this is not empty return false; } /** Resets the list */ function resetCurrentLists(args) { for (var i = 0; i < args.currentListIdsByLevels.length; i++) { var ll = args.currentListIdsByLevels[i]; if (ll) { ll.currentUniqueListId = -1; } } } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/wordConverter.ts": /*!********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/wordConverter.ts ***! \********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createWordConverter = void 0; var WordCustomData_1 = __webpack_require__(/*! ./WordCustomData */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/WordCustomData.ts"); /** * @internal * create an empty WordConverter */ function createWordConverter() { return { nextUniqueId: 1, numBulletsConverted: 0, numNumberedConverted: 0, wordConverterArgs: null, wordCustomData: (0, WordCustomData_1.createCustomData)(), }; } exports.createWordConverter = createWordConverter; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Picker/PickerPlugin.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Picker/PickerPlugin.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); // Character codes. // IE11 uses different character codes. which are noted below. // If adding a new key, test in IE to figure out what the code is. var BACKSPACE_CHAR_CODE = 'Backspace'; var TAB_CHAR_CODE = 'Tab'; var ENTER_CHAR_CODE = 'Enter'; var ESC_CHAR_CODE = !roosterjs_editor_dom_1.Browser.isIE ? 'Escape' : 'Esc'; var LEFT_ARROW_CHAR_CODE = !roosterjs_editor_dom_1.Browser.isIE ? 'ArrowLeft' : 'Left'; var UP_ARROW_CHAR_CODE = !roosterjs_editor_dom_1.Browser.isIE ? 'ArrowUp' : 'Up'; var RIGHT_ARROW_CHAR_CODE = !roosterjs_editor_dom_1.Browser.isIE ? 'ArrowRight' : 'Right'; var DOWN_ARROW_CHAR_CODE = !roosterjs_editor_dom_1.Browser.isIE ? 'ArrowDown' : 'Down'; var DELETE_CHAR_CODE = !roosterjs_editor_dom_1.Browser.isIE ? 'Delete' : 'Del'; // Input event input types. var DELETE_CONTENT_BACKWARDS_INPUT_TYPE = 'deleteContentBackwards'; // Unidentified key, the code for Android keyboard events. var UNIDENTIFIED_KEY = 'Unidentified'; // the char code for Android keyboard events on Webview below 51. var UNIDENTIFIED_CODE = [0, 229]; /** * PickerPlugin represents a plugin of editor which can handle picker related behaviors, including * - Show picker when special trigger key is pressed * - Hide picker * - Change selection in picker by Up/Down/Left/Right * - Apply selected item in picker * * PickerPlugin doesn't provide any UI, it just wraps related DOM events and invoke callback functions. */ var PickerPlugin = /** @class */ (function () { function PickerPlugin(dataProvider, pickerOptions) { this.dataProvider = dataProvider; this.pickerOptions = pickerOptions; // For detecting backspace in Android this.isPendingInputEventHandling = false; } /** * Get a friendly name */ PickerPlugin.prototype.getName = function () { return 'Picker'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ PickerPlugin.prototype.initialize = function (editor) { var _this = this; this.editor = editor; this.dataProvider.onInitalize(function (htmlNode) { _this.editor.focus(); var wordToReplace = _this.getWord(null); // Safari drops our focus out so we get an empty word to replace when we call getWord. // We fall back to using the lastKnownRange to try to get around this. if ((!wordToReplace || wordToReplace.length == 0) && _this.lastKnownRange) { _this.editor.select(_this.lastKnownRange); wordToReplace = _this.getWord(null); } var insertNode = function () { if (wordToReplace) { (0, roosterjs_editor_api_1.replaceWithNode)(_this.editor, wordToReplace, htmlNode, true /* exactMatch */); } else { _this.editor.insertNode(htmlNode); } _this.setIsSuggesting(false); }; _this.editor.addUndoSnapshot(insertNode, _this.pickerOptions.changeSource, _this.pickerOptions.handleAutoComplete); }, function (isSuggesting) { _this.setIsSuggesting(isSuggesting); }, editor); }; /** * Dispose this plugin */ PickerPlugin.prototype.dispose = function () { this.editor = null; this.isSuggesting = null; this.blockSuggestions = null; this.eventHandledOnKeyDown = null; this.lastKnownRange = null; this.isPendingInputEventHandling = null; this.currentInputLength = null; this.newInputLength = null; this.dataProvider.onDispose(); }; /** * Check if the plugin should handle the given event exclusively. * Handle an event exclusively means other plugin will not receive this event in * onPluginEvent method. * If two plugins will return true in willHandleEventExclusively() for the same event, * the final result depends on the order of the plugins are added into editor * @param event The event to check */ PickerPlugin.prototype.willHandleEventExclusively = function (event) { return (this.isSuggesting && (event.eventType == 0 /* KeyDown */ || event.eventType == 2 /* KeyUp */ || event.eventType == 3 /* Input */)); }; /** * Handle events triggered from editor * @param event PluginEvent object */ PickerPlugin.prototype.onPluginEvent = function (event) { switch (event.eventType) { case 7 /* ContentChanged */: if (event.source == "SetContent" /* SetContent */ && this.dataProvider.onContentChanged) { // Stop suggesting since content is fully changed if (this.isSuggesting) { this.setIsSuggesting(false); } // Undo and other major changes to document content fire this type of event. // Inform the data provider of the current picker placed elements in the body. var elementIds_1 = []; this.editor.queryElements("[id^='" + this.pickerOptions.elementIdPrefix + "']", function (element) { if (element.id) { elementIds_1.push(element.id); } }); this.dataProvider.onContentChanged(elementIds_1); } break; case 0 /* KeyDown */: this.eventHandledOnKeyDown = false; if (this.isAndroidKeyboardEvent(event)) { // On Android, the key for KeyboardEvent is "Unidentified" or undefined, // so handling should be done using the input rather than key down event // Since the key down event happens right before the input event, calculate the input // length here in preparation for onAndroidInputEvent this.currentInputLength = this.calcInputLength(event); this.isPendingInputEventHandling = true; } else { this.onKeyDownEvent(event); this.isPendingInputEventHandling = false; } break; case 3 /* Input */: if (this.isPendingInputEventHandling) { this.onAndroidInputEvent(event); } break; case 2 /* KeyUp */: if (!this.eventHandledOnKeyDown && this.shouldHandleKeyUpEvent(event)) { this.onKeyUpDomEvent(event); this.isPendingInputEventHandling = false; } break; case 6 /* MouseUp */: if (this.isSuggesting) { this.setIsSuggesting(false); } break; case 14 /* Scroll */: if (this.dataProvider.onScroll) { // Dispatch scroll event to data provider this.dataProvider.onScroll(event.scrollContainer); } break; } }; PickerPlugin.prototype.setLastKnownRange = function (range) { this.lastKnownRange = range; }; PickerPlugin.prototype.setIsSuggesting = function (isSuggesting) { this.isSuggesting = isSuggesting; if (!isSuggesting) { this.setLastKnownRange(null); } this.dataProvider.onIsSuggestingChanged(isSuggesting); this.setAriaOwns(isSuggesting); this.setAriaActiveDescendant(isSuggesting ? 0 : null); }; PickerPlugin.prototype.cancelDefaultKeyDownEvent = function (event) { this.eventHandledOnKeyDown = true; event.rawEvent.preventDefault(); event.rawEvent.stopImmediatePropagation(); }; PickerPlugin.prototype.getIdValue = function (node) { var element = node; return element.attributes && element.attributes.getNamedItem('id') ? element.attributes.getNamedItem('id').value : null; }; PickerPlugin.prototype.getWordBeforeCursor = function (event) { var searcher = this.editor.getContentSearcherOfCursor(event); return searcher ? searcher.getWordBefore() : null; }; PickerPlugin.prototype.replaceNode = function (currentNode, replacementNode) { if (currentNode) { this.editor.deleteNode(currentNode); } if (replacementNode) { this.editor.insertNode(replacementNode); } }; PickerPlugin.prototype.getRangeUntilAt = function (event) { var _this = this; var positionContentSearcher = this.editor.getContentSearcherOfCursor(event); var startPos; var endPos; positionContentSearcher.forEachTextInlineElement(function (textInline) { var hasMatched = false; var nodeContent = textInline.getTextContent(); var nodeIndex = nodeContent ? nodeContent.length : -1; while (nodeIndex >= 0) { if (nodeContent[nodeIndex] == _this.pickerOptions.triggerCharacter) { startPos = textInline.getStartPosition().move(nodeIndex); hasMatched = true; break; } nodeIndex--; } if (hasMatched) { endPos = textInline.getEndPosition(); } return hasMatched; }); return (0, roosterjs_editor_dom_1.createRange)(startPos, endPos) || this.editor.getDocument().createRange(); }; PickerPlugin.prototype.shouldHandleKeyUpEvent = function (event) { // onKeyUpDomEvent should only be called when a key that produces a character value is pressed // This check will always fail on Android since the KeyboardEvent's key is "Unidentified" or undefined // However, we don't need to check for modifier events on mobile, so can ignore this check return (this.isAndroidKeyboardEvent(event) || (0, roosterjs_editor_dom_1.isCharacterValue)(event.rawEvent) || (this.isSuggesting && !(0, roosterjs_editor_dom_1.isModifierKey)(event.rawEvent))); }; PickerPlugin.prototype.onKeyUpDomEvent = function (event) { if (this.isSuggesting) { // Word before cursor represents the text prior to the cursor, up to and including the trigger symbol. var wordBeforeCursor = this.getWord(event); var wordBeforeCursorWithoutTriggerChar = wordBeforeCursor.substring(1); var trimmedWordBeforeCursor = wordBeforeCursorWithoutTriggerChar.trim(); // If we hit a case where wordBeforeCursor is just the trigger character, // that means we've gotten a onKeyUp event right after it's been typed. // Otherwise, update the query string when: // 1. There's an actual value // 2. That actual value isn't just pure whitespace // 3. That actual value isn't more than 4 words long (at which point we assume the person kept typing) // Otherwise, we want to dismiss the picker plugin's UX. if (wordBeforeCursor == this.pickerOptions.triggerCharacter || (trimmedWordBeforeCursor && trimmedWordBeforeCursor.length > 0 && trimmedWordBeforeCursor.split(' ').length <= 4)) { this.dataProvider.queryStringUpdated(trimmedWordBeforeCursor, wordBeforeCursorWithoutTriggerChar == trimmedWordBeforeCursor); this.setLastKnownRange(this.editor.getSelectionRange()); } else { this.setIsSuggesting(false); } } else { var wordBeforeCursor = this.getWordBeforeCursor(event); if (!this.blockSuggestions) { if (wordBeforeCursor != null && wordBeforeCursor.split(' ').length <= 4 && wordBeforeCursor[0] == this.pickerOptions.triggerCharacter) { this.setIsSuggesting(true); var wordBeforeCursorWithoutTriggerChar = wordBeforeCursor.substring(1); var trimmedWordBeforeCursor = wordBeforeCursorWithoutTriggerChar.trim(); this.dataProvider.queryStringUpdated(trimmedWordBeforeCursor, wordBeforeCursorWithoutTriggerChar == trimmedWordBeforeCursor); this.setLastKnownRange(this.editor.getSelectionRange()); if (this.dataProvider.setCursorPoint) { // Determine the bounding rectangle for the @mention var searcher = this.editor.getContentSearcherOfCursor(event); var rangeNode = this.editor.getDocument().createRange(); var nodeBeforeCursor = searcher.getInlineElementBefore().getContainerNode(); var rangeStartSuccessfullySet = this.setRangeStart(rangeNode, nodeBeforeCursor, wordBeforeCursor); if (!rangeStartSuccessfullySet) { // VSO 24891: Out of range error is occurring because nodeBeforeCursor // is not including the trigger character. In this case, the node before // the node before cursor is the trigger character, and this is where the range should start. var nodeBeforeNodeBeforeCursor = nodeBeforeCursor.previousSibling; this.setRangeStart(rangeNode, nodeBeforeNodeBeforeCursor, this.pickerOptions.triggerCharacter); } var rect = rangeNode.getBoundingClientRect(); // Safari's support for range.getBoundingClientRect is incomplete. // We perform this check to fall back to getClientRects in case it's at the page origin. if (rect.left == 0 && rect.bottom == 0 && rect.top == 0) { rect = rangeNode.getClientRects()[0]; } if (rect) { rangeNode.detach(); // Display the @mention popup in the correct place var targetPoint = { x: rect.left, y: (rect.bottom + rect.top) / 2 }; var bufferZone = (rect.bottom - rect.top) / 2; this.dataProvider.setCursorPoint(targetPoint, bufferZone); } } } } else { if (wordBeforeCursor != null && wordBeforeCursor[0] != this.pickerOptions.triggerCharacter) { this.blockSuggestions = false; } } } }; PickerPlugin.prototype.onKeyDownEvent = function (event) { var keyboardEvent = event.rawEvent; if (this.isSuggesting) { if (keyboardEvent.key == ESC_CHAR_CODE) { this.setIsSuggesting(false); this.blockSuggestions = true; this.cancelDefaultKeyDownEvent(event); } else if (keyboardEvent.key == BACKSPACE_CHAR_CODE) { // #483: If we are backspacing over the trigger character that triggered this Picker // then we need to hide the Picker var wordBeforeCursor = this.getWord(event); if (wordBeforeCursor == this.pickerOptions.triggerCharacter) { this.setIsSuggesting(false); } } else if (this.dataProvider.shiftHighlight && (this.pickerOptions.isHorizontal ? keyboardEvent.key == LEFT_ARROW_CHAR_CODE || keyboardEvent.key == RIGHT_ARROW_CHAR_CODE : keyboardEvent.key == UP_ARROW_CHAR_CODE || keyboardEvent.key == DOWN_ARROW_CHAR_CODE)) { this.dataProvider.shiftHighlight(this.pickerOptions.isHorizontal ? keyboardEvent.key == RIGHT_ARROW_CHAR_CODE : keyboardEvent.key == DOWN_ARROW_CHAR_CODE); if (this.dataProvider.getSelectedIndex) { this.setAriaActiveDescendant(this.dataProvider.getSelectedIndex()); } this.cancelDefaultKeyDownEvent(event); } else if (this.dataProvider.selectOption && (keyboardEvent.key == ENTER_CHAR_CODE || keyboardEvent.key == TAB_CHAR_CODE)) { this.dataProvider.selectOption(); this.cancelDefaultKeyDownEvent(event); } else { // Currently no op. } } else { if (keyboardEvent.key == BACKSPACE_CHAR_CODE) { var nodeRemoved = this.tryRemoveNode(event); if (nodeRemoved) { this.cancelDefaultKeyDownEvent(event); } } else if (keyboardEvent.key == DELETE_CHAR_CODE) { var searcher = this.editor.getContentSearcherOfCursor(event); var nodeAfterCursor = searcher.getInlineElementAfter() ? searcher.getInlineElementAfter().getContainerNode() : null; var nodeId = nodeAfterCursor ? this.getIdValue(nodeAfterCursor) : null; if (nodeId && nodeId.indexOf(this.pickerOptions.elementIdPrefix) == 0) { var replacementNode = this.dataProvider.onRemove(nodeAfterCursor, false); this.replaceNode(nodeAfterCursor, replacementNode); this.cancelDefaultKeyDownEvent(event); } } } }; PickerPlugin.prototype.onAndroidInputEvent = function (event) { this.newInputLength = this.calcInputLength(event); if (this.newInputLength < this.currentInputLength || event.rawEvent.inputType === DELETE_CONTENT_BACKWARDS_INPUT_TYPE) { var nodeRemoved = this.tryRemoveNode(event); if (nodeRemoved) { this.eventHandledOnKeyDown = true; } } }; PickerPlugin.prototype.calcInputLength = function (event) { var wordBeforeCursor = this.getInlineElementBeforeCursor(event); return wordBeforeCursor ? wordBeforeCursor.length : 0; }; PickerPlugin.prototype.tryRemoveNode = function (event) { var searcher = this.editor.getContentSearcherOfCursor(event); var inlineElementBefore = searcher.getInlineElementBefore(); var nodeBeforeCursor = inlineElementBefore ? inlineElementBefore.getContainerNode() : null; var nodeId = nodeBeforeCursor ? this.getIdValue(nodeBeforeCursor) : null; var inlineElementAfter = searcher.getInlineElementAfter(); if (nodeId && nodeId.indexOf(this.pickerOptions.elementIdPrefix) == 0 && (inlineElementAfter == null || !(inlineElementAfter instanceof roosterjs_editor_dom_1.PartialInlineElement))) { var replacementNode_1 = this.dataProvider.onRemove(nodeBeforeCursor, true); if (replacementNode_1) { this.replaceNode(nodeBeforeCursor, replacementNode_1); if (this.isPendingInputEventHandling) { this.editor.runAsync(function (editor) { editor.select(replacementNode_1, -3 /* After */); }); } else { this.editor.select(replacementNode_1, -3 /* After */); } } else { this.editor.deleteNode(nodeBeforeCursor); } return true; } return false; }; PickerPlugin.prototype.getWord = function (event) { var wordFromRange = this.getRangeUntilAt(event).toString(); var wordFromCache = this.getWordBeforeCursor(event); // VSO 24891: In picker, trigger and mention are separated into two nodes. // In this case, wordFromRange is the trigger character while wordFromCache is the whole string, // so wordFromCache is what we want to return. if (wordFromRange == this.pickerOptions.triggerCharacter && wordFromRange != wordFromCache) { return wordFromCache; } return wordFromRange; }; PickerPlugin.prototype.setRangeStart = function (rangeNode, node, target) { var nodeOffset = node ? node.textContent.lastIndexOf(target) : -1; if (nodeOffset > -1) { rangeNode.setStart(node, nodeOffset); return true; } return false; }; PickerPlugin.prototype.setAriaOwns = function (isSuggesting) { this.editor.setEditorDomAttribute('aria-owns', isSuggesting && this.pickerOptions.suggestionsLabel ? this.pickerOptions.suggestionsLabel : null); }; PickerPlugin.prototype.setAriaActiveDescendant = function (selectedIndex) { this.editor.setEditorDomAttribute('aria-activedescendant', selectedIndex != null && this.pickerOptions.suggestionLabelPrefix ? this.pickerOptions.suggestionLabelPrefix + selectedIndex.toString() : null); }; PickerPlugin.prototype.getInlineElementBeforeCursor = function (event) { var searcher = this.editor.getContentSearcherOfCursor(event); var element = searcher ? searcher.getInlineElementBefore() : null; return element ? element.getTextContent() : null; }; PickerPlugin.prototype.isAndroidKeyboardEvent = function (event) { // Check keyboard events on Android for further handling. // On Android Webview later 51, the KeyboardEvent's key is "Unidentified". // On Android Webview below 51, the KeyboardEvent's key is not supported and always returns undefined, // so using the charCode property, which is 0 or 229. return (event.rawEvent.key == UNIDENTIFIED_KEY || (event.rawEvent.key == undefined && UNIDENTIFIED_CODE.indexOf(event.rawEvent.charCode) > -1)); }; return PickerPlugin; }()); exports.default = PickerPlugin; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Picker/index.ts": /*!***********************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Picker/index.ts ***! \***********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PickerPlugin = void 0; var PickerPlugin_1 = __webpack_require__(/*! ./PickerPlugin */ "./packages/roosterjs-editor-plugins/lib/plugins/Picker/PickerPlugin.ts"); Object.defineProperty(exports, "PickerPlugin", { enumerable: true, get: function () { return PickerPlugin_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/TableCellSelection.ts": /*!************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/TableCellSelection.ts ***! \************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var normalizeTableSelection_1 = __webpack_require__(/*! ./utils/normalizeTableSelection */ "./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/utils/normalizeTableSelection.ts"); var DeleteTableContents_1 = __webpack_require__(/*! ./features/DeleteTableContents */ "./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/features/DeleteTableContents.ts"); var getCellCoordinates_1 = __webpack_require__(/*! ./utils/getCellCoordinates */ "./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/utils/getCellCoordinates.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var TABLE_CELL_SELECTOR = 'td,th'; var LEFT_CLICK = 1; var RIGHT_CLICK = 3; var IGNORE_KEY_UP_KEYS = [ 16 /* SHIFT */, 18 /* ALT */, 91 /* META_LEFT */, 17 /* CTRL_LEFT */, 44 /* PRINT_SCREEN */, ]; /** * TableCellSelectionPlugin help highlight table cells */ var TableCellSelection = /** @class */ (function () { function TableCellSelection() { var _this = this; this.onMouseMove = function (event) { if (!_this.editor.contains(event.target)) { return; } //If already in table selection and the new target is contained in the last target cell, no need to //Apply selection styles again. if (_this.tableSelection && (0, roosterjs_editor_dom_1.contains)(_this.lastTarget, event.target, true)) { updateSelection(_this.editor, _this.firstTarget, 0); event.preventDefault(); return; } if ((0, roosterjs_editor_dom_1.getTagOfNode)(event.target) == 'TABLE') { event.preventDefault(); return; } _this.setData(event.target); // If there is a first target, but is not inside a table, no more actions to perform. if (_this.firstTarget && !_this.firstTable) { return; } //Ignore if // Is a DIV that only contains a Table // If the event target is not contained in the editor. if ((_this.lastTarget.lastChild == _this.lastTarget.firstChild && (0, roosterjs_editor_dom_1.getTagOfNode)(_this.lastTarget.lastChild) == 'TABLE' && (0, roosterjs_editor_dom_1.getTagOfNode)(_this.lastTarget) == 'DIV') || !_this.editor.contains(_this.lastTarget)) { event.preventDefault(); return; } _this.prepareSelection(); var isNewTDContainingFirstTable = (0, roosterjs_editor_dom_1.safeInstanceOf)(_this.lastTarget, 'HTMLTableCellElement') ? (0, roosterjs_editor_dom_1.contains)(_this.lastTarget, _this.firstTable) : false; if ((_this.firstTable && _this.firstTable == _this.targetTable) || isNewTDContainingFirstTable) { //When starting selection inside of a table and ends inside of the same table. _this.selectionInsideTableMouseMove(event); } else if (_this.tableSelection) { _this.restoreSelection(); } if (_this.tableSelection) { updateSelection(_this.editor, _this.firstTarget, 0); event.preventDefault(); } }; this.onMouseUp = function () { if (_this.editor) { _this.removeMouseUpEventListener(); } }; this.lastTarget = null; this.firstTarget = null; this.tableSelection = false; this.tableRange = { firstCell: null, lastCell: null, }; this.startedSelection = false; } /** * Get a friendly name of this plugin */ TableCellSelection.prototype.getName = function () { return 'TableCellSelection'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ TableCellSelection.prototype.initialize = function (editor) { this.editor = editor; this.editor.addContentEditFeature(DeleteTableContents_1.DeleteTableContents); }; /** * Dispose this plugin */ TableCellSelection.prototype.dispose = function () { this.editor.select(null); this.removeMouseUpEventListener(); this.editor = null; }; /** * Handle events triggered from editor * @param event PluginEvent object */ TableCellSelection.prototype.onPluginEvent = function (event) { if (this.editor) { switch (event.eventType) { case 17 /* EnteredShadowEdit */: var selection = this.editor.getSelectionRangeEx(); if (selection.type == 1 /* TableSelection */) { this.tableRange = selection.coordinates; this.firstTable = selection.table; this.tableSelection = true; this.editor.select(selection.table, null); } break; case 18 /* LeavingShadowEdit */: if (this.firstTable && this.tableSelection && this.tableRange) { var table = this.editor.queryElements('#' + this.firstTable.id); if (table.length == 1) { this.firstTable = table[0]; this.editor.select(this.firstTable, this.tableRange); } } break; case 5 /* MouseDown */: if (!this.startedSelection) { this.handleMouseDownEvent(event); } break; case 0 /* KeyDown */: if (!this.startedSelection) { this.handleKeyDownEvent(event); } else { event.rawEvent.preventDefault(); } break; case 2 /* KeyUp */: if (!this.startedSelection) { this.handleKeyUpEvent(event); } else { event.rawEvent.preventDefault(); } break; case 14 /* Scroll */: if (this.startedSelection) { this.handleScrollEvent(); } break; case 20 /* BeforeSetContent */: if (this.tableRange) { this.tableRange = null; this.firstTable = null; this.tableSelection = false; this.editor.select(null); } break; } } }; /** * Handle Scroll Event and mantains the selection range, * Since when we scroll the cursor does not trigger the on Mouse Move event * The table selection gets removed. */ TableCellSelection.prototype.handleScrollEvent = function () { this.setData(this.editor.getElementAtCursor()); if (this.firstTable == this.targetTable) { if (this.tableSelection) { this.vTable.selection.lastCell = (0, getCellCoordinates_1.getCellCoordinates)(this.vTable, this.lastTarget); this.selectTable(); this.tableRange.lastCell = this.vTable.selection.lastCell; updateSelection(this.editor, this.firstTarget, 0); } } else if (this.tableSelection) { this.restoreSelection(); } }; //#region Key events /** * Handles the on key event. * @param event the plugin event */ TableCellSelection.prototype.handleKeyDownEvent = function (event) { var _this = this; var _a; var _b = event.rawEvent, shiftKey = _b.shiftKey, ctrlKey = _b.ctrlKey, metaKey = _b.metaKey, which = _b.which, defaultPrevented = _b.defaultPrevented; if ((shiftKey && (ctrlKey || metaKey)) || which == 16 /* SHIFT */ || defaultPrevented) { this.preventKeyUp = defaultPrevented; return; } if (shiftKey) { if (!this.firstTarget) { var pos = this.editor.getFocusedPosition(); var cell = pos && getCellAtCursor(this.editor, pos.node); this.firstTarget = this.firstTarget || cell; } //If first target is not a table cell, we should ignore this plugin if (!(0, roosterjs_editor_dom_1.safeInstanceOf)(this.firstTarget, 'HTMLTableCellElement')) { return; } this.editor.runAsync(function (editor) { var pos = editor.getFocusedPosition(); var newTarget = _this.tableSelection ? _this.lastTarget : pos === null || pos === void 0 ? void 0 : pos.node; if (newTarget) { _this.setData(newTarget); } if (_this.firstTable == _this.targetTable) { if (!_this.shouldConvertToTableSelection() && !_this.tableSelection) { return; } //When selection start and end is inside of the same table _this.handleKeySelectionInsideTable(event); } else if (_this.tableSelection) { if (_this.firstTable) { _this.editor.select(_this.firstTable, null); } _this.tableSelection = false; } }); } else if (((_a = this.editor.getSelectionRangeEx()) === null || _a === void 0 ? void 0 : _a.type) == 1 /* TableSelection */ && (!(0, roosterjs_editor_dom_1.isCtrlOrMetaPressed)(event.rawEvent) || which == 36 /* HOME */ || which == 35 /* END */)) { this.editor.select(null); } }; TableCellSelection.prototype.handleKeyUpEvent = function (event) { var _a = event.rawEvent, shiftKey = _a.shiftKey, which = _a.which, ctrlKey = _a.ctrlKey; if (!shiftKey && !ctrlKey && this.firstTarget && !this.preventKeyUp && IGNORE_KEY_UP_KEYS.indexOf(which) == -1) { this.clearState(); } this.preventKeyUp = false; }; TableCellSelection.prototype.handleKeySelectionInsideTable = function (event) { this.firstTarget = getCellAtCursor(this.editor, this.firstTarget); this.lastTarget = getCellAtCursor(this.editor, this.lastTarget); updateSelection(this.editor, this.firstTarget, 0); this.vTable = this.vTable || new roosterjs_editor_dom_1.VTable(this.firstTable); this.tableRange = { firstCell: (0, getCellCoordinates_1.getCellCoordinates)(this.vTable, this.firstTarget), lastCell: this.getNextTD(event), }; if (!this.tableRange.lastCell || this.tableRange.lastCell.y > this.vTable.cells.length - 1 || this.tableRange.lastCell.y == -1) { //When selection is moving from inside of a table to outside this.lastTarget = this.editor.getElementAtCursor(TABLE_CELL_SELECTOR + ',div', this.firstTable); if ((0, roosterjs_editor_dom_1.safeInstanceOf)(this.lastTarget, 'HTMLTableCellElement')) { this.prepareSelection(); } else { var position = new roosterjs_editor_dom_1.Position(this.targetTable, this.tableRange.lastCell.y == null || this.tableRange.lastCell.y == -1 ? -2 /* Before */ : -3 /* After */); var sel = this.editor.getDocument().defaultView.getSelection(); var anchorNode = sel.anchorNode, anchorOffset = sel.anchorOffset; this.editor.select(sel.getRangeAt(0)); sel.setBaseAndExtent(anchorNode, anchorOffset, position.node, position.offset); this.lastTarget = position.node; event.rawEvent.preventDefault(); return; } } this.vTable.selection = this.tableRange; this.selectTable(); var isBeginAboveEnd = this.isAfter(this.firstTarget, this.lastTarget); var targetPosition = new roosterjs_editor_dom_1.Position(this.lastTarget, isBeginAboveEnd ? 0 /* Begin */ : -1 /* End */); updateSelection(this.editor, targetPosition.node, targetPosition.offset); this.tableSelection = true; event.rawEvent.preventDefault(); }; //#endregion //#region Mouse events TableCellSelection.prototype.handleMouseDownEvent = function (event) { var _this = this; var _a = event.rawEvent, which = _a.which, shiftKey = _a.shiftKey; if (which == RIGHT_CLICK && this.tableSelection) { //If the user is right clicking To open context menu var td = this.editor.getElementAtCursor(TABLE_CELL_SELECTOR); var coord = (0, getCellCoordinates_1.getCellCoordinates)(this.vTable, td); if (coord) { var _b = (0, normalizeTableSelection_1.default)(this.vTable), firstCell = _b.firstCell, lastCell = _b.lastCell; if (coord.y >= firstCell.y && coord.y <= lastCell.y && coord.x >= firstCell.x && coord.x <= lastCell.x) { this.firstTarget = this.vTable.getCell(firstCell.y, firstCell.x).td; this.lastTarget = this.vTable.getCell(lastCell.y, lastCell.x).td; if (this.firstTarget && this.lastTarget) { var selection = this.editor.getDocument().defaultView.getSelection(); selection.setBaseAndExtent(this.firstTarget, 0, this.lastTarget, 0); this.selectTable(); } return; } } } if (which == LEFT_CLICK && !shiftKey) { this.clearState(); if (getTableAtCursor(this.editor, event.rawEvent.target)) { this.editor .getDocument() .addEventListener('mouseup', this.onMouseUp, true /*setCapture*/); this.editor .getDocument() .addEventListener('mousemove', this.onMouseMove, true /*setCapture*/); this.startedSelection = true; } } if (which == LEFT_CLICK && shiftKey) { this.editor.runAsync(function (editor) { var sel = editor.getDocument().defaultView.getSelection(); var first = getCellAtCursor(editor, sel.anchorNode); var last = getCellAtCursor(editor, sel.focusNode); var firstTable = getTableAtCursor(editor, first); var targetTable = getTableAtCursor(editor, first); if (firstTable == targetTable && (0, roosterjs_editor_dom_1.safeInstanceOf)(first, 'HTMLTableCellElement') && (0, roosterjs_editor_dom_1.safeInstanceOf)(last, 'HTMLTableCellElement')) { _this.vTable = new roosterjs_editor_dom_1.VTable(first); var firstCord = (0, getCellCoordinates_1.getCellCoordinates)(_this.vTable, first); var lastCord = (0, getCellCoordinates_1.getCellCoordinates)(_this.vTable, last); _this.vTable.selection = { firstCell: firstCord, lastCell: lastCord, }; _this.firstTarget = first; _this.lastTarget = last; _this.selectTable(); _this.tableRange = _this.vTable.selection; _this.tableSelection = true; _this.firstTable = firstTable; _this.targetTable = targetTable; updateSelection(editor, first, 0); } }); } }; TableCellSelection.prototype.restoreSelection = function () { if (this.firstTable) { this.editor.select(this.firstTable, null); } this.tableSelection = false; var isBeginAboveEnd = this.isAfter(this.firstTarget, this.lastTarget); var targetPosition = new roosterjs_editor_dom_1.Position(this.lastTarget, isBeginAboveEnd ? -1 /* End */ : 0 /* Begin */); var firstTargetRange = new Range(); if (this.firstTarget) { firstTargetRange.selectNodeContents(this.firstTarget); } updateSelection(this.editor, this.firstTarget, isBeginAboveEnd ? roosterjs_editor_dom_1.Position.getEnd(firstTargetRange).offset : roosterjs_editor_dom_1.Position.getStart(firstTargetRange).offset, targetPosition.element, targetPosition.offset); }; /** * @internal * Public only for unit testing * @param event mouse event */ TableCellSelection.prototype.selectionInsideTableMouseMove = function (event) { var _a; if (this.lastTarget != this.firstTarget) { updateSelection(this.editor, this.firstTarget, 0); if (this.firstTable != this.targetTable && ((_a = this.targetTable) === null || _a === void 0 ? void 0 : _a.contains(this.firstTable))) { //If selection started in a table that is inside of another table and moves to parent table //Make the firstTarget the TD of the parent table. this.firstTarget = this.editor.getElementAtCursor(TABLE_CELL_SELECTOR, this.lastTarget); } if (this.firstTable) { this.tableSelection = true; this.vTable = this.vTable || new roosterjs_editor_dom_1.VTable(this.firstTable); this.tableRange = { firstCell: (0, getCellCoordinates_1.getCellCoordinates)(this.vTable, this.firstTarget), lastCell: (0, getCellCoordinates_1.getCellCoordinates)(this.vTable, this.lastTarget), }; this.vTable.selection = this.tableRange; this.selectTable(); } event.preventDefault(); } else if (this.lastTarget == this.firstTarget && this.tableSelection) { this.vTable = new roosterjs_editor_dom_1.VTable(this.firstTable); var cell = (0, getCellCoordinates_1.getCellCoordinates)(this.vTable, this.firstTarget); this.tableRange = { firstCell: cell, lastCell: cell, }; this.vTable.selection = this.tableRange; this.selectTable(); } }; TableCellSelection.prototype.removeMouseUpEventListener = function () { if (this.startedSelection) { this.startedSelection = false; this.editor.getDocument().removeEventListener('mouseup', this.onMouseUp, true); this.editor.getDocument().removeEventListener('mousemove', this.onMouseMove, true); } }; //#endregion //#region utils TableCellSelection.prototype.clearState = function () { this.editor.select(null); this.vTable = null; this.firstTarget = null; this.lastTarget = null; this.tableRange = { firstCell: null, lastCell: null, }; this.tableSelection = false; this.firstTable = null; this.targetTable = null; }; TableCellSelection.prototype.getNextTD = function (event) { this.lastTarget = this.editor.getElementAtCursor(TABLE_CELL_SELECTOR, this.lastTarget); if ((0, roosterjs_editor_dom_1.safeInstanceOf)(this.lastTarget, 'HTMLTableCellElement')) { var coordinates = (0, getCellCoordinates_1.getCellCoordinates)(this.vTable, this.lastTarget); if (this.tableSelection) { switch (event.rawEvent.which) { case 39 /* RIGHT */: coordinates.x += this.lastTarget.colSpan; if (this.vTable.cells[coordinates.y][coordinates.x] == null) { coordinates.x = this.vTable.cells[coordinates.y].length - 1; coordinates.y++; } break; case 37 /* LEFT */: if (coordinates.x == 0) { coordinates.y--; } else { coordinates.x--; } break; case 38 /* UP */: coordinates.y--; break; case 40 /* DOWN */: coordinates.y++; break; } } if (coordinates.y >= 0 && coordinates.x >= 0) { this.lastTarget = this.vTable.getTd(coordinates.y, coordinates.x); } return coordinates; } return null; }; //Check if the selection started in a inner table. TableCellSelection.prototype.prepareSelection = function () { var _a, _b, _c, _d; var isNewTargetTableContained = this.lastTarget != this.firstTarget && ((_a = this.firstTable) === null || _a === void 0 ? void 0 : _a.contains((0, roosterjs_editor_dom_1.findClosestElementAncestor)(this.targetTable, this.firstTable, TABLE_CELL_SELECTOR))); if (isNewTargetTableContained && this.tableSelection) { while (isNewTargetTableContained) { this.lastTarget = (0, roosterjs_editor_dom_1.findClosestElementAncestor)(this.targetTable, this.firstTable, TABLE_CELL_SELECTOR); this.targetTable = getTableAtCursor(this.editor, this.lastTarget); isNewTargetTableContained = this.lastTarget != this.firstTarget && ((_b = this.firstTable) === null || _b === void 0 ? void 0 : _b.contains((0, roosterjs_editor_dom_1.findClosestElementAncestor)(this.targetTable, this.firstTable, TABLE_CELL_SELECTOR))); } } var isFirstTargetTableContained = this.lastTarget != this.firstTarget && ((_c = this.targetTable) === null || _c === void 0 ? void 0 : _c.contains((0, roosterjs_editor_dom_1.findClosestElementAncestor)(this.firstTable, this.targetTable, TABLE_CELL_SELECTOR))); if (isFirstTargetTableContained && this.tableSelection) { while (isFirstTargetTableContained) { this.firstTarget = (0, roosterjs_editor_dom_1.findClosestElementAncestor)(this.firstTable, this.targetTable, TABLE_CELL_SELECTOR); this.firstTable = this.editor.getElementAtCursor('table', this.firstTarget); isFirstTargetTableContained = this.lastTarget != this.firstTarget && ((_d = this.targetTable) === null || _d === void 0 ? void 0 : _d.contains((0, roosterjs_editor_dom_1.findClosestElementAncestor)(this.firstTable, this.targetTable, TABLE_CELL_SELECTOR))); } } }; TableCellSelection.prototype.setData = function (eventTarget) { var pos = this.editor.getFocusedPosition(); if (pos) { this.firstTarget = this.firstTarget || getCellAtCursor(this.editor, pos.node); if (this.firstTarget.nodeType == Node.TEXT_NODE) { this.firstTarget = this.editor.getElementAtCursor(TABLE_CELL_SELECTOR, this.firstTarget); } if (!this.editor.contains(this.firstTarget) && this.lastTarget) { this.firstTarget = this.lastTarget; } } this.firstTable = getTableAtCursor(this.editor, this.firstTarget); this.lastTarget = getCellAtCursor(this.editor, eventTarget); this.targetTable = getTableAtCursor(this.editor, this.lastTarget); }; TableCellSelection.prototype.isAfter = function (node1, node2) { var _a, _b, _c, _d; if (node1 && node2) { if (node2.contains(node1)) { var r1 = (_b = (_a = node1).getBoundingClientRect) === null || _b === void 0 ? void 0 : _b.call(_a); var r2 = (_d = (_c = node2).getBoundingClientRect) === null || _d === void 0 ? void 0 : _d.call(_c); if (r1 && r2) { return r1.top > r2.top && r1.bottom < r2.bottom; } } var position = new roosterjs_editor_dom_1.Position(node1, -1 /* End */); return position.isAfter(new roosterjs_editor_dom_1.Position(node2, -1 /* End */)); } return false; }; // if the user selected all the text in a cell and started selecting another TD, we should convert to vSelection TableCellSelection.prototype.shouldConvertToTableSelection = function () { var _this = this; if (!this.firstTable || !this.editor) { return false; } var regions = this.editor.getSelectedRegions(); if (regions.length == 1) { return false; } var result = true; regions.forEach(function (value) { if (!(0, roosterjs_editor_dom_1.contains)(_this.firstTable, value.rootNode)) { result = false; } }); return result; }; TableCellSelection.prototype.selectTable = function () { var _a; if (this.editor && this.vTable) { (_a = this.editor) === null || _a === void 0 ? void 0 : _a.select(this.vTable.table, (0, normalizeTableSelection_1.default)(this.vTable)); } }; return TableCellSelection; }()); exports.default = TableCellSelection; function updateSelection(editor, start, offset, end, endOffset) { var selection = editor.getDocument().defaultView.getSelection(); end = end || start; endOffset = endOffset || offset; selection.setBaseAndExtent(start, offset, end, endOffset); } function getCellAtCursor(editor, node) { if (editor) { return editor.getElementAtCursor(TABLE_CELL_SELECTOR, node) || node; } return node; } function getTableAtCursor(editor, node) { if (editor) { return editor.getElementAtCursor('table', node); } return null; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/features/DeleteTableContents.ts": /*!**********************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/features/DeleteTableContents.ts ***! \**********************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DeleteTableContents = void 0; var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); /** * @internal * Feature that when Backspace is pressed and there is Table Selection, delete the contents inside of the selection */ exports.DeleteTableContents = { keys: [46 /* DELETE */, 8 /* BACKSPACE */], shouldHandleEvent: function (_, editor) { var selection = editor.getSelectionRangeEx(); return selection.type == 1 /* TableSelection */; }, handleEvent: function (_, editor) { var selection = editor.getSelectionRangeEx(); if (selection.type == 1 /* TableSelection */) { editor.addUndoSnapshot(function () { editor.getSelectedRegions().forEach(function (region) { if ((0, roosterjs_editor_dom_1.safeInstanceOf)(region.rootNode, 'HTMLTableCellElement')) { deleteNodeContents(region.rootNode, editor); } }); }); } }, }; function deleteNodeContents(element, editor) { var range = new Range(); range.selectNodeContents(element); range.deleteContents(); element.appendChild(editor.getDocument().createElement('br')); } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/index.ts": /*!***********************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/index.ts ***! \***********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TableCellSelection = void 0; var TableCellSelection_1 = __webpack_require__(/*! ./TableCellSelection */ "./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/TableCellSelection.ts"); Object.defineProperty(exports, "TableCellSelection", { enumerable: true, get: function () { return TableCellSelection_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/utils/getCellCoordinates.ts": /*!******************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/utils/getCellCoordinates.ts ***! \******************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getCellCoordinates = void 0; /** * @internal * Gets the coordinates of a cell * @param cellInput The cell the to find the coordinates * @returns Coordinates of the cell, null if not found */ function getCellCoordinates(vTable, cellInput) { var result; if (vTable === null || vTable === void 0 ? void 0 : vTable.cells) { for (var indexY = 0; indexY < vTable.cells.length; indexY++) { for (var indexX = 0; indexX < vTable.cells[indexY].length; indexX++) { if (cellInput == vTable.cells[indexY][indexX].td) { result = { x: indexX, y: indexY, }; } } } } return result; } exports.getCellCoordinates = getCellCoordinates; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/utils/normalizeTableSelection.ts": /*!***********************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableCellSelection/utils/normalizeTableSelection.ts ***! \***********************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * @internal * Make the first Cell of a table selection always be on top of the last cell. * @param input Table selection * @returns Table Selection where the first cell is always going to be first selected in the table * and the last cell always going to be last selected in the table. */ function normalizeTableSelection(vTable) { var _a = (vTable === null || vTable === void 0 ? void 0 : vTable.selection) || {}, firstCell = _a.firstCell, lastCell = _a.lastCell; if (!vTable || !vTable.selection || !firstCell || !lastCell) { return null; } var cells = vTable.cells; var newFirst = { x: Math.min(firstCell.x, lastCell.x), y: Math.min(firstCell.y, lastCell.y), }; var newLast = { x: Math.max(firstCell.x, lastCell.x), y: Math.max(firstCell.y, lastCell.y), }; var fixCoordinates = function (coord) { if (coord.x < 0) { coord.x = 0; } if (coord.y < 0) { coord.y = 0; } if (coord.y >= cells.length) { coord.y = cells.length - 1; } var rowsCells = cells[coord.y].length; if (coord.x >= rowsCells) { coord.x = rowsCells - 1; } }; fixCoordinates(newFirst); fixCoordinates(newLast); return { firstCell: newFirst, lastCell: newLast }; } exports.default = normalizeTableSelection; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/TableResize.ts": /*!**********************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableResize/TableResize.ts ***! \**********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var TableEditor_1 = __webpack_require__(/*! ./editors/TableEditor */ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableEditor.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var TABLE_RESIZER_LENGTH = 12; /** * TableResize plugin, provides the ability to resize a table by drag-and-drop */ var TableResize = /** @class */ (function () { /** * Construct a new instance of TableResize plugin * @param onShowHelperElement An optional callback to allow customize helper element of table resizing. * To customize the helper element, add this callback and change the attributes of elementData then it * will be picked up by TableResize code */ function TableResize(onShowHelperElement) { var _this = this; this.onShowHelperElement = onShowHelperElement; this.tableRectMap = null; this.onMouseMove = function (e) { var _a; if (e.buttons > 0) { return; } _this.ensureTableRects(); var editorWindow = _this.editor.getDocument().defaultView; var x = e.pageX - editorWindow.scrollX; var y = e.pageY - editorWindow.scrollY; var currentTable = null; for (var i = _this.tableRectMap.length - 1; i >= 0; i--) { var _b = _this.tableRectMap[i], table = _b.table, rect = _b.rect; if (x >= rect.left - TABLE_RESIZER_LENGTH && x <= rect.right + TABLE_RESIZER_LENGTH && y >= rect.top - TABLE_RESIZER_LENGTH && y <= rect.bottom + TABLE_RESIZER_LENGTH) { currentTable = table; break; } } _this.setTableEditor(currentTable, e); (_a = _this.tableEditor) === null || _a === void 0 ? void 0 : _a.onMouseMove(x, y); }; this.invalidateTableRects = function () { _this.tableRectMap = null; }; } /** * Get a friendly name of this plugin */ TableResize.prototype.getName = function () { return 'TableResize'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ TableResize.prototype.initialize = function (editor) { this.editor = editor; this.onMouseMoveDisposer = this.editor.addDomEventHandler({ mousemove: this.onMouseMove }); }; /** * Dispose this plugin */ TableResize.prototype.dispose = function () { this.onMouseMoveDisposer(); this.invalidateTableRects(); this.disposeTableEditor(); this.editor = null; }; /** * Handle events triggered from editor * @param event PluginEvent object */ TableResize.prototype.onPluginEvent = function (e) { switch (e.eventType) { case 3 /* Input */: case 7 /* ContentChanged */: case 14 /* Scroll */: case 21 /* ZoomChanged */: this.setTableEditor(null); this.invalidateTableRects(); break; } }; TableResize.prototype.setTableEditor = function (table, e) { if (this.tableEditor && !this.tableEditor.isEditing() && table != this.tableEditor.table) { this.disposeTableEditor(); } if (!this.tableEditor && table) { this.tableEditor = new TableEditor_1.default(this.editor, table, this.invalidateTableRects, this.onShowHelperElement, e.currentTarget); } }; TableResize.prototype.disposeTableEditor = function () { var _a; (_a = this.tableEditor) === null || _a === void 0 ? void 0 : _a.dispose(); this.tableEditor = null; }; TableResize.prototype.ensureTableRects = function () { var _this = this; if (!this.tableRectMap) { this.tableRectMap = []; this.editor.queryElements('table', function (table) { if (table.isContentEditable) { var rect = (0, roosterjs_editor_dom_1.normalizeRect)(table.getBoundingClientRect()); if (rect) { _this.tableRectMap.push({ table: table, rect: rect, }); } } }); } }; return TableResize; }()); exports.default = TableResize; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/CellResizer.ts": /*!******************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/CellResizer.ts ***! \******************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var DragAndDropHelper_1 = __webpack_require__(/*! ../../../pluginUtils/DragAndDropHelper */ "./packages/roosterjs-editor-plugins/lib/pluginUtils/DragAndDropHelper.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var CELL_RESIZER_WIDTH = 4; var MIN_CELL_WIDTH = 30; /** * @internal */ function createCellResizer(td, zoomScale, isRTL, isHorizontal, onStart, onEnd, onShowHelperElement) { var document = td.ownerDocument; var createElementData = { tag: 'div', style: "position: fixed; cursor: " + (isHorizontal ? 'row' : 'col') + "-resize; user-select: none", }; onShowHelperElement === null || onShowHelperElement === void 0 ? void 0 : onShowHelperElement(createElementData, 'CellResizer'); var div = (0, roosterjs_editor_dom_1.createElement)(createElementData, document); document.body.appendChild(div); var context = { td: td, isRTL: isRTL, zoomScale: zoomScale, onStart: onStart }; var setPosition = isHorizontal ? setHorizontalPosition : setVerticalPosition; setPosition(context, div); var handler = { onDragStart: onDragStart, onDragging: isHorizontal ? onDraggingHorizontal : onDraggingVertical, onDragEnd: onEnd, }; var featureHandler = new DragAndDropHelper_1.default(div, context, setPosition, handler, zoomScale); return { node: td, div: div, featureHandler: featureHandler }; } exports.default = createCellResizer; function onDragStart(context, event) { var td = context.td, isRTL = context.isRTL, zoomScale = context.zoomScale, onStart = context.onStart; var vTable = new roosterjs_editor_dom_1.VTable(td, true /*normalizeSize*/, zoomScale); var rect = (0, roosterjs_editor_dom_1.normalizeRect)(td.getBoundingClientRect()); if (rect) { onStart(); // calculate and retrieve the cells of the two columns shared by the current vertical resizer var currentCells = vTable.getCellsWithBorder(isRTL ? rect.left : rect.right, !isRTL); var nextCells = vTable.getCellsWithBorder(isRTL ? rect.left : rect.right, isRTL); return { vTable: vTable, currentCells: currentCells, nextCells: nextCells, initialX: event.pageX, }; } else { return { vTable: vTable, currentCells: [], nextCells: [], initialX: 0 }; // Just a fallback } } function onDraggingHorizontal(context, event, initValue, deltaX, deltaY) { var td = context.td, zoomScale = context.zoomScale; var vTable = initValue.vTable; vTable.table.removeAttribute('height'); vTable.table.style.height = null; vTable.forEachCellOfCurrentRow(function (cell) { if (cell.td) { cell.td.style.height = cell.td == td ? cell.height / zoomScale + deltaY + "px" : null; } }); // To avoid apply format styles when the table is being resizing, the skipApplyFormat is set to true. vTable.writeBack(true /**skipApplyFormat*/); return true; } function onDraggingVertical(context, event, initValue, deltaX) { var isRTL = context.isRTL, zoomScale = context.zoomScale; var vTable = initValue.vTable, nextCells = initValue.nextCells, currentCells = initValue.currentCells, initialX = initValue.initialX; if (!canResizeColumns(event.pageX, currentCells, nextCells, isRTL, zoomScale)) { return false; } // Since we allow the user to resize the table width on adjusting the border of the last cell, // we need to make the table width resizable by setting it as null; // We also allow the user to resize the table width if Shift key is pressed var isLastCell = nextCells.length == 0; var isShiftPressed = event.shiftKey; if (isLastCell || isShiftPressed) { vTable.table.style.width = null; } var newWidthList = new Map(); currentCells.forEach(function (td) { var rect = (0, roosterjs_editor_dom_1.normalizeRect)(td.getBoundingClientRect()); if (rect) { td.style.wordBreak = 'break-word'; td.style.whiteSpace = 'normal'; td.style.boxSizing = 'border-box'; var newWidth = getHorizontalDistance(rect, event.pageX, !isRTL) / zoomScale; newWidthList.set(td, newWidth); } }); newWidthList.forEach(function (newWidth, td) { td.style.width = newWidth + "px"; }); if (!isShiftPressed) { nextCells.forEach(function (td) { var width = td.rowSpan > 1 ? 0 : td.getBoundingClientRect().right - initialX; td.style.wordBreak = 'break-word'; td.style.whiteSpace = 'normal'; td.style.boxSizing = 'border-box'; td.style.width = td.rowSpan > 1 ? '' : width / zoomScale - deltaX + 'px'; }); } // To avoid apply format styles when the table is being resizing, the skipApplyFormat is set to true. vTable.writeBack(true /**skipApplyFormat*/); return true; } function getHorizontalDistance(rect, pos, toLeft) { return toLeft ? pos - rect.left : rect.right - pos; } function setHorizontalPosition(context, trigger) { var td = context.td; var rect = (0, roosterjs_editor_dom_1.normalizeRect)(td.getBoundingClientRect()); if (rect) { trigger.style.top = rect.bottom - CELL_RESIZER_WIDTH + 'px'; trigger.style.left = rect.left + 'px'; trigger.style.width = rect.right - rect.left + 'px'; trigger.style.height = CELL_RESIZER_WIDTH + 'px'; } } function setVerticalPosition(context, trigger) { var td = context.td, isRTL = context.isRTL; var rect = (0, roosterjs_editor_dom_1.normalizeRect)(td.getBoundingClientRect()); if (rect) { trigger.style.top = rect.top + 'px'; trigger.style.left = (isRTL ? rect.left : rect.right) - CELL_RESIZER_WIDTH + 1 + 'px'; trigger.style.width = CELL_RESIZER_WIDTH + 'px'; trigger.style.height = rect.bottom - rect.top + 'px'; } } /** * * @param newPos The position to where we want to move the vertical border * @returns if the move is allowed, or, if any of the cells on either side of the vertical border is smaller than * the minimum width, such move is not allowed */ function canResizeColumns(newPos, currentCells, nextCells, isRTL, zoomScale) { for (var i = 0; i < currentCells.length; i++) { var td = currentCells[i]; var rect = (0, roosterjs_editor_dom_1.normalizeRect)(td.getBoundingClientRect()); if (rect) { var width = getHorizontalDistance(rect, newPos, !isRTL) / zoomScale; if (width < MIN_CELL_WIDTH) { return false; } } } for (var i = 0; i < nextCells.length; i++) { var td = nextCells[i]; var width = Number.MAX_SAFE_INTEGER; if (td) { var rect = (0, roosterjs_editor_dom_1.normalizeRect)(td.getBoundingClientRect()); if (rect) { width = getHorizontalDistance(rect, newPos, isRTL) / zoomScale; } } if (width < MIN_CELL_WIDTH) { return false; } } return true; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableEditor.ts": /*!******************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableEditor.ts ***! \******************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var CellResizer_1 = __webpack_require__(/*! ./CellResizer */ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/CellResizer.ts"); var TableInserter_1 = __webpack_require__(/*! ./TableInserter */ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableInserter.ts"); var TableResizer_1 = __webpack_require__(/*! ./TableResizer */ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableResizer.ts"); var TableSelector_1 = __webpack_require__(/*! ./TableSelector */ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableSelector.ts"); var TableEditorFeature_1 = __webpack_require__(/*! ./TableEditorFeature */ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableEditorFeature.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var INSERTER_HOVER_OFFSET = 5; /** * @internal * * A table has 6 hot areas to be resized/edited (take LTR example): * * [6] [ ] * +[ 1 ]+--------------------+ * |[ ]| | * [ ] [ ] | * [ ] [ ] | * [2] [3] | * [ ] [ ] | * [ ][ 4 ]| | * +------------------+--------------------+ * | | | * | | | * | | | * +------------------+--------------------+ * [5] * * 1 - Hover area to show insert column button * 2 - Hover area to show insert row button * 3 - Hover area to show vertical resizing bar * 4 - Hover area to show horizontal resizing bar * 5 - Hover area to show whole table resize button * 6 - Hover area to show whole table selector button * * When set a different current table or change current TD, we need to update these areas */ var TableEditor = /** @class */ (function () { function TableEditor(editor, table, onChanged, onShowHelperElement, contentDiv) { var _this = this; this.editor = editor; this.table = table; this.onChanged = onChanged; this.onShowHelperElement = onShowHelperElement; // 1, 2 - Insert a column or a row this.horizontalInserter = null; this.verticalInserter = null; // 3, 4 - Resize a column or a row from a cell this.horizontalResizer = null; this.verticalResizer = null; this.onFinishEditing = function () { _this.editor.focus(); _this.editor.select(_this.start, _this.end); _this.editor.addUndoSnapshot(null /*callback*/, "Format" /* Format */); _this.onChanged(); _this.isCurrentlyEditing = false; return false; }; this.onStartTableResize = function () { _this.isCurrentlyEditing = true; _this.onStartResize(); }; this.onStartCellResize = function () { _this.isCurrentlyEditing = true; _this.disposeTableResizer(); _this.onStartResize(); }; this.onInserted = function (table) { _this.editor.transformToDarkColor(table); _this.disposeTableResizer(); _this.onFinishEditing(); }; /** * Public only for testing purposes * @param table the table to select */ this.onSelect = function (table) { _this.editor.focus(); if (table) { var vTable = new roosterjs_editor_dom_1.VTable(table); if (vTable.cells) { var rows = vTable.cells.length - 1; var lastCellIndex_1 = 0; vTable.cells[rows].forEach(function (cell, index) { lastCellIndex_1 = index; }); var selection = { firstCell: { x: 0, y: 0, }, lastCell: { y: rows, x: lastCellIndex_1, }, }; _this.editor.select(table, selection); } } }; this.isRTL = (0, roosterjs_editor_dom_1.getComputedStyle)(table, 'direction') == 'rtl'; var zoomScale = editor.getZoomScale(); this.tableResizer = (0, TableResizer_1.default)(table, zoomScale, this.isRTL, this.onStartTableResize, this.onFinishEditing, this.onShowHelperElement); this.tableSelector = (0, TableSelector_1.default)(table, zoomScale, editor, this.onSelect, this.onShowHelperElement, contentDiv); this.isCurrentlyEditing = false; } TableEditor.prototype.dispose = function () { this.disposeTableResizer(); this.disposeCellResizers(); this.disposeTableInserter(); this.disposeTableSelector(); }; TableEditor.prototype.isEditing = function () { return this.isCurrentlyEditing; }; TableEditor.prototype.onMouseMove = function (x, y) { var _a; for (var i = 0; i < this.table.rows.length; i++) { var tr = this.table.rows[i]; var j = 0; for (; j < tr.cells.length; j++) { var td = tr.cells[j]; var tableRect = (0, roosterjs_editor_dom_1.normalizeRect)(this.table.getBoundingClientRect()); var tdRect = (0, roosterjs_editor_dom_1.normalizeRect)(td.getBoundingClientRect()); if (!tdRect || !tableRect) { continue; } var lessThanBottom = y <= tdRect.bottom; var lessThanRight = this.isRTL ? x >= tdRect.right : x <= tdRect.right; if (lessThanRight && lessThanBottom) { var isOnLeftOrRight = this.isRTL ? tdRect.right <= tableRect.right && tdRect.right >= tableRect.right - 1 : tdRect.left >= tableRect.left && tdRect.left <= tableRect.left + 1; if (i === 0 && y <= tdRect.top + INSERTER_HOVER_OFFSET) { var center = (tdRect.left + tdRect.right) / 2; var isOnRightHalf = this.isRTL ? x < center : x > center; this.setInserterTd(isOnRightHalf ? td : tr.cells[j - 1], false /*isHorizontal*/); } else if (j == 0 && (this.isRTL ? x >= tdRect.right - INSERTER_HOVER_OFFSET : x <= tdRect.left + INSERTER_HOVER_OFFSET) && isOnLeftOrRight) { var tdAbove = (_a = this.table.rows[i - 1]) === null || _a === void 0 ? void 0 : _a.cells[0]; var tdAboveRect = tdAbove ? (0, roosterjs_editor_dom_1.normalizeRect)(tdAbove.getBoundingClientRect()) : null; var isTdNotAboveMerged = !tdAboveRect ? null : this.isRTL ? tdAboveRect.right === tdRect.right : tdAboveRect.left === tdRect.left; this.setInserterTd(y < (tdRect.top + tdRect.bottom) / 2 && isTdNotAboveMerged ? tdAbove : td, true /*isHorizontal*/); } else { this.setInserterTd(null); } this.setResizingTd(td); break; } } if (j < tr.cells.length) { break; } } }; TableEditor.prototype.setResizingTd = function (td) { if (this.horizontalResizer && this.horizontalResizer.node != td) { this.disposeCellResizers(); } if (!this.horizontalResizer && td) { var zoomScale = this.editor.getZoomScale(); this.horizontalResizer = (0, CellResizer_1.default)(td, zoomScale, this.isRTL, true /*isHorizontal*/, this.onStartCellResize, this.onFinishEditing, this.onShowHelperElement); this.verticalResizer = (0, CellResizer_1.default)(td, zoomScale, this.isRTL, false /*isHorizontal*/, this.onStartCellResize, this.onFinishEditing, this.onShowHelperElement); } }; /** * create or remove TableInserter * @param td td to attach to, set this to null to remove inserters (both horizontal and vertical) */ TableEditor.prototype.setInserterTd = function (td, isHorizontal) { var inserter = isHorizontal ? this.horizontalInserter : this.verticalInserter; if (td === null || (inserter && inserter.node != td)) { this.disposeTableInserter(); } if (!this.horizontalInserter && !this.verticalInserter && td) { var newInserter = (0, TableInserter_1.default)(this.editor, td, this.isRTL, !!isHorizontal, this.onInserted, this.onShowHelperElement); if (isHorizontal) { this.horizontalInserter = newInserter; } else { this.verticalInserter = newInserter; } } }; TableEditor.prototype.disposeTableResizer = function () { if (this.tableResizer) { (0, TableEditorFeature_1.disposeTableEditFeature)(this.tableResizer); this.tableResizer = null; } }; TableEditor.prototype.disposeTableInserter = function () { if (this.horizontalInserter) { (0, TableEditorFeature_1.disposeTableEditFeature)(this.horizontalInserter); this.horizontalInserter = null; } if (this.verticalInserter) { (0, TableEditorFeature_1.disposeTableEditFeature)(this.verticalInserter); this.verticalInserter = null; } }; TableEditor.prototype.disposeCellResizers = function () { if (this.horizontalResizer) { (0, TableEditorFeature_1.disposeTableEditFeature)(this.horizontalResizer); this.horizontalResizer = null; } if (this.verticalResizer) { (0, TableEditorFeature_1.disposeTableEditFeature)(this.verticalResizer); this.verticalResizer = null; } }; TableEditor.prototype.disposeTableSelector = function () { if (this.tableSelector) { (0, TableEditorFeature_1.disposeTableEditFeature)(this.tableSelector); this.tableSelector = null; } }; TableEditor.prototype.onStartResize = function () { this.isCurrentlyEditing = true; var range = this.editor.getSelectionRange(); if (range) { this.start = roosterjs_editor_dom_1.Position.getStart(range); this.end = roosterjs_editor_dom_1.Position.getEnd(range); } this.editor.addUndoSnapshot(); }; return TableEditor; }()); exports.default = TableEditor; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableEditorFeature.ts": /*!*************************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableEditorFeature.ts ***! \*************************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.disposeTableEditFeature = void 0; /** * @internal */ function disposeTableEditFeature(resizer) { var _a, _b, _c; if (resizer) { (_b = (_a = resizer.div) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(resizer.div); resizer.div = null; (_c = resizer.featureHandler) === null || _c === void 0 ? void 0 : _c.dispose(); resizer.featureHandler = null; } } exports.disposeTableEditFeature = disposeTableEditFeature; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableInserter.ts": /*!********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableInserter.ts ***! \********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var INSERTER_COLOR = '#4A4A4A'; var INSERTER_COLOR_DARK_MODE = 'white'; var INSERTER_SIDE_LENGTH = 12; var INSERTER_BORDER_SIZE = 1; /** * @internal */ function createTableInserter(editor, td, isRTL, isHorizontal, onInsert, onShowHelperElement) { var table = editor.getElementAtCursor('table', td); var tdRect = (0, roosterjs_editor_dom_1.normalizeRect)(td.getBoundingClientRect()); var tableRect = table ? (0, roosterjs_editor_dom_1.getIntersectedRect)([table], [editor.getVisibleViewport()]) : null; // set inserter position if (tdRect && tableRect) { var document_1 = td.ownerDocument; var createElementData = getInsertElementData(isHorizontal, editor.isDarkMode(), isRTL, editor.getDefaultFormat().backgroundColor || 'white'); onShowHelperElement === null || onShowHelperElement === void 0 ? void 0 : onShowHelperElement(createElementData, 'TableInserter'); var div = (0, roosterjs_editor_dom_1.createElement)(createElementData, document_1); if (isHorizontal) { div.style.left = (isRTL ? tdRect.right : tdRect.left - (INSERTER_SIDE_LENGTH - 1 + 2 * INSERTER_BORDER_SIZE)) + "px"; div.style.top = tdRect.bottom - 8 + "px"; div.firstChild.style.width = tableRect.right - tableRect.left + "px"; } else { div.style.left = (isRTL ? tdRect.left - 8 : tdRect.right - 8) + "px"; div.style.top = tdRect.top - (INSERTER_SIDE_LENGTH - 1 + 2 * INSERTER_BORDER_SIZE) + "px"; div.firstChild.style.height = tableRect.bottom - tableRect.top + "px"; } document_1.body.appendChild(div); var handler = new TableInsertHandler(div, td, isHorizontal, editor, onInsert); return { div: div, featureHandler: handler, node: td }; } return null; } exports.default = createTableInserter; var TableInsertHandler = /** @class */ (function () { function TableInsertHandler(div, td, isHorizontal, editor, onInsert) { var _this = this; this.div = div; this.td = td; this.isHorizontal = isHorizontal; this.editor = editor; this.onInsert = onInsert; this.insertTd = function () { var vtable = new roosterjs_editor_dom_1.VTable(_this.td); if (!_this.isHorizontal) { vtable.normalizeTableCellSize(_this.editor.getZoomScale()); // Since adding new column will cause table width to change, we need to remove width properties vtable.table.removeAttribute('width'); vtable.table.style.width = null; } vtable.edit(_this.isHorizontal ? 1 /* InsertBelow */ : 3 /* InsertRight */); vtable.writeBack(); _this.onInsert(vtable.table); }; this.div.addEventListener('click', this.insertTd); } TableInsertHandler.prototype.dispose = function () { this.div.removeEventListener('click', this.insertTd); this.div = null; this.editor = null; }; return TableInsertHandler; }()); function getInsertElementData(isHorizontal, isDark, isRTL, backgroundColor) { var inserterColor = isDark ? INSERTER_COLOR_DARK_MODE : INSERTER_COLOR; var outerDivStyle = "position: fixed; width: " + INSERTER_SIDE_LENGTH + "px; height: " + INSERTER_SIDE_LENGTH + "px; font-size: 16px; color: " + inserterColor + "; line-height: 10px; vertical-align: middle; text-align: center; cursor: pointer; border: solid " + INSERTER_BORDER_SIZE + "px " + inserterColor + "; border-radius: 50%; background-color: " + backgroundColor; var leftOrRight = isRTL ? 'right' : 'left'; var childBaseStyles = "position: absolute; box-sizing: border-box; background-color: " + backgroundColor + ";"; var childInfo = { tag: 'div', style: childBaseStyles + (isHorizontal ? leftOrRight + ": 12px; top: 5px; height: 3px; border-top: 1px solid " + inserterColor + "; border-bottom: 1px solid " + inserterColor + "; border-right: 1px solid " + inserterColor + "; border-left: 0px;" : "left: 5px; top: 12px; width: 3px; border-left: 1px solid " + inserterColor + "; border-right: 1px solid " + inserterColor + "; border-bottom: 1px solid " + inserterColor + "; border-top: 0px;"), }; return { tag: 'div', style: outerDivStyle, children: [childInfo, '+'], }; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableResizer.ts": /*!*******************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableResizer.ts ***! \*******************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var DragAndDropHelper_1 = __webpack_require__(/*! ../../../pluginUtils/DragAndDropHelper */ "./packages/roosterjs-editor-plugins/lib/pluginUtils/DragAndDropHelper.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var TABLE_RESIZER_LENGTH = 12; var MIN_CELL_WIDTH = 30; var MIN_CELL_HEIGHT = 20; /** * @internal */ function createTableResizer(table, zoomScale, isRTL, onStart, onDragEnd, onShowHelperElement) { var document = table.ownerDocument; var createElementData = { tag: 'div', style: "position: fixed; cursor: " + (isRTL ? 'ne' : 'nw') + "-resize; user-select: none; border: 1px solid #808080", }; onShowHelperElement === null || onShowHelperElement === void 0 ? void 0 : onShowHelperElement(createElementData, 'TableResizer'); var div = (0, roosterjs_editor_dom_1.createElement)(createElementData, document); div.style.width = TABLE_RESIZER_LENGTH + "px"; div.style.height = TABLE_RESIZER_LENGTH + "px"; document.body.appendChild(div); var context = { isRTL: isRTL, table: table, zoomScale: zoomScale, onStart: onStart, }; setResizeDivPosition(context, div); var featureHandler = new DragAndDropHelper_1.default(div, context, setResizeDivPosition, { onDragStart: onDragStart, onDragging: onDragging, onDragEnd: onDragEnd, }, zoomScale); return { node: table, div: div, featureHandler: featureHandler }; } exports.default = createTableResizer; function onDragStart(context) { context.onStart(); return { originalRect: context.table.getBoundingClientRect(), vTable: new roosterjs_editor_dom_1.VTable(context.table, true /*normalizeTable*/, context.zoomScale), }; } function onDragging(context, event, initValue, deltaX, deltaY) { var isRTL = context.isRTL, zoomScale = context.zoomScale; var originalRect = initValue.originalRect, vTable = initValue.vTable; var ratioX = 1.0 + (deltaX / originalRect.width) * zoomScale * (isRTL ? -1 : 1); var ratioY = 1.0 + (deltaY / originalRect.height) * zoomScale; var shouldResizeX = Math.abs(ratioX - 1.0) > 1e-3; var shouldResizeY = Math.abs(ratioY - 1.0) > 1e-3; if (shouldResizeX || shouldResizeY) { for (var i = 0; i < vTable.cells.length; i++) { for (var j = 0; j < vTable.cells[i].length; j++) { var cell = vTable.cells[i][j]; if (cell.td) { if (shouldResizeX) { // the width of some external table is fixed, we need to make it resizable vTable.table.style.width = null; var newWidth = (cell.width * ratioX) / zoomScale; cell.td.style.boxSizing = 'border-box'; if (newWidth >= MIN_CELL_WIDTH) { cell.td.style.wordBreak = 'break-word'; cell.td.style.whiteSpace = 'normal'; cell.td.style.width = newWidth + "px"; } } if (shouldResizeY) { // the height of some external table is fixed, we need to make it resizable vTable.table.style.height = null; if (j == 0) { var newHeight = (cell.height * ratioY) / zoomScale; if (newHeight >= MIN_CELL_HEIGHT) { cell.td.style.height = newHeight + "px"; } } else { cell.td.style.height = null; } } } } } // To avoid apply format styles when the table is being resizing, the skipApplyFormat is set to true. vTable.writeBack(true /**skipApplyFormat*/); return true; } else { return false; } } function setResizeDivPosition(context, trigger) { var table = context.table, isRTL = context.isRTL; var rect = (0, roosterjs_editor_dom_1.normalizeRect)(table.getBoundingClientRect()); if (rect) { trigger.style.top = rect.bottom + "px"; trigger.style.left = isRTL ? rect.left - TABLE_RESIZER_LENGTH - 2 + "px" : rect.right + "px"; } } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableSelector.ts": /*!********************************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableSelector.ts ***! \********************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var DragAndDropHelper_1 = __webpack_require__(/*! ../../../pluginUtils/DragAndDropHelper */ "./packages/roosterjs-editor-plugins/lib/pluginUtils/DragAndDropHelper.ts"); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var TABLE_SELECTOR_LENGTH = 12; var TABLE_SELECTOR_ID = '_Table_Selector'; /** * @internal */ function createTableSelector(table, zoomScale, editor, onFinishDragging, onShowHelperElement, contentDiv) { var rect = (0, roosterjs_editor_dom_1.normalizeRect)(table.getBoundingClientRect()); if (!isTableTopVisible(editor, rect, contentDiv)) { return null; } var document = table.ownerDocument; var createElementData = { tag: 'div', style: 'position: fixed; cursor: all-scroll; user-select: none; border: 1px solid #808080', }; onShowHelperElement === null || onShowHelperElement === void 0 ? void 0 : onShowHelperElement(createElementData, 'TableSelector'); var div = (0, roosterjs_editor_dom_1.createElement)(createElementData, document); div.id = TABLE_SELECTOR_ID; div.style.width = TABLE_SELECTOR_LENGTH + "px"; div.style.height = TABLE_SELECTOR_LENGTH + "px"; document.body.appendChild(div); var context = { table: table, zoomScale: zoomScale, rect: rect, }; setSelectorDivPosition(context, div); var onDragEnd = function (context, event) { if (event.target == div) { onFinishDragging(context.table); } return false; }; var featureHandler = new DragAndDropHelper_1.default(div, context, setSelectorDivPosition, { onDragEnd: onDragEnd, }, zoomScale); return { div: div, featureHandler: featureHandler, node: table }; } exports.default = createTableSelector; function setSelectorDivPosition(context, trigger) { var rect = context.rect; if (rect) { trigger.style.top = rect.top - TABLE_SELECTOR_LENGTH + "px"; trigger.style.left = rect.left - TABLE_SELECTOR_LENGTH - 2 + "px"; } } function isTableTopVisible(editor, rect, contentDiv) { var visibleViewport = editor.getVisibleViewport(); if (contentDiv && (0, roosterjs_editor_dom_1.safeInstanceOf)(contentDiv, 'HTMLElement') && visibleViewport && rect) { var containerRect = (0, roosterjs_editor_dom_1.normalizeRect)(contentDiv.getBoundingClientRect()); return containerRect.top <= rect.top && visibleViewport.top <= rect.top; } return true; } /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/index.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/TableResize/index.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TableResize = void 0; var TableResize_1 = __webpack_require__(/*! ./TableResize */ "./packages/roosterjs-editor-plugins/lib/plugins/TableResize/TableResize.ts"); Object.defineProperty(exports, "TableResize", { enumerable: true, get: function () { return TableResize_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Watermark/Watermark.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Watermark/Watermark.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"); var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts"); var ENTITY_TYPE = 'WATERMARK_WRAPPER'; /** * A watermark plugin to manage watermark string for roosterjs */ var Watermark = /** @class */ (function () { /** * Create an instance of Watermark plugin * @param watermark The watermark string */ function Watermark(watermark, format, customClass) { var _this = this; this.watermark = watermark; this.customClass = customClass; this.editor = null; this.disposer = null; this.showHideWatermark = function () { if (!_this.editor) { return; } var hasFocus = _this.editor.hasFocus(); var watermarks = _this.editor.queryElements((0, roosterjs_editor_dom_1.getEntitySelector)(ENTITY_TYPE)); var isShowing = watermarks.length > 0; if (hasFocus && isShowing) { watermarks.forEach(_this.removeWatermark); _this.editor.focus(); } else if (!hasFocus && !isShowing && _this.editor.isEmpty()) { var newEntity = (0, roosterjs_editor_api_1.insertEntity)(_this.editor, ENTITY_TYPE, _this.editor.getDocument().createTextNode(_this.watermark), false /*isBlock*/, false /*isReadonly*/, 0 /* Begin */); if (_this.customClass) { newEntity.wrapper.classList.add(_this.customClass); } } }; this.removeWatermark = function (wrapper) { var _a; var parentNode = wrapper.parentNode; parentNode === null || parentNode === void 0 ? void 0 : parentNode.removeChild(wrapper); // After remove watermark node, if it leaves an empty DIV, append a BR node into it to make it a regular empty line if (parentNode && ((_a = _this.editor) === null || _a === void 0 ? void 0 : _a.contains(parentNode)) && (0, roosterjs_editor_dom_1.getTagOfNode)(parentNode) == 'DIV' && !parentNode.firstChild) { parentNode.appendChild(_this.editor.getDocument().createElement('BR')); } }; this.format = format || { fontSize: '14px', textColors: { lightModeColor: '#AAAAAA', darkModeColor: '#6B6B6B', }, }; } /** * Get a friendly name of this plugin */ Watermark.prototype.getName = function () { return 'Watermark'; }; /** * Initialize this plugin. This should only be called from Editor * @param editor Editor instance */ Watermark.prototype.initialize = function (editor) { this.editor = editor; this.disposer = this.editor.addDomEventHandler({ focus: this.showHideWatermark, blur: this.showHideWatermark, }); }; /** * Dispose this plugin */ Watermark.prototype.dispose = function () { var _a; (_a = this.disposer) === null || _a === void 0 ? void 0 : _a.call(this); this.disposer = null; this.editor = null; }; /** * Handle events triggered from editor * @param event PluginEvent object */ Watermark.prototype.onPluginEvent = function (event) { var _a; if (event.eventType == 11 /* EditorReady */ || (event.eventType == 7 /* ContentChanged */ && ((_a = event.data) === null || _a === void 0 ? void 0 : _a.type) != ENTITY_TYPE)) { this.showHideWatermark(); } else if (event.eventType == 15 /* EntityOperation */ && event.entity.type == ENTITY_TYPE && this.editor) { var operation = event.operation, wrapper = event.entity.wrapper; if (operation == 8 /* ReplaceTemporaryContent */) { this.removeWatermark(wrapper); } else if (event.operation == 0 /* NewEntity */) { (0, roosterjs_editor_dom_1.applyFormat)(wrapper, this.format, this.editor.isDarkMode(), this.editor.getDarkColorHandler()); wrapper.spellcheck = false; } } }; return Watermark; }()); exports.default = Watermark; /***/ }), /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Watermark/index.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Watermark/index.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Watermark = void 0; var Watermark_1 = __webpack_require__(/*! ./Watermark */ "./packages/roosterjs-editor-plugins/lib/plugins/Watermark/Watermark.ts"); Object.defineProperty(exports, "Watermark", { enumerable: true, get: function () { return Watermark_1.default; } }); /***/ }), /***/ "./packages/roosterjs-editor-types-compatible/lib/index.ts": /*!*****************************************************************!*\ !*** ./packages/roosterjs-editor-types-compatible/lib/index.ts ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! roosterjs-editor-types/lib/compatibleTypes */ "./packages/roosterjs-editor-types/lib/compatibleTypes.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/browser/index.ts": /*!**************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/browser/index.ts ***! \**************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/Alignment.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/Alignment.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleAlignment = void 0; /** * enum for setting block alignment, used by setAlignment API */ var CompatibleAlignment; (function (CompatibleAlignment) { /** * Align left */ CompatibleAlignment[CompatibleAlignment["Left"] = 0] = "Left"; /** * Align center */ CompatibleAlignment[CompatibleAlignment["Center"] = 1] = "Center"; /** * Align right */ CompatibleAlignment[CompatibleAlignment["Right"] = 2] = "Right"; })(CompatibleAlignment = exports.CompatibleAlignment || (exports.CompatibleAlignment = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/BulletListType.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/BulletListType.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleBulletListType = void 0; /** * Enum used to control the different types of bullet list */ var CompatibleBulletListType; (function (CompatibleBulletListType) { /** * Minimum value of the enum */ CompatibleBulletListType[CompatibleBulletListType["Min"] = 1] = "Min"; /** * Bullet triggered by * */ CompatibleBulletListType[CompatibleBulletListType["Disc"] = 1] = "Disc"; /** * Bullet triggered by - */ CompatibleBulletListType[CompatibleBulletListType["Dash"] = 2] = "Dash"; /** * Bullet triggered by -- */ CompatibleBulletListType[CompatibleBulletListType["Square"] = 3] = "Square"; /** * Bullet triggered by > */ CompatibleBulletListType[CompatibleBulletListType["ShortArrow"] = 4] = "ShortArrow"; /** * Bullet triggered by -> */ CompatibleBulletListType[CompatibleBulletListType["LongArrow"] = 5] = "LongArrow"; /** * Bullet triggered by => */ CompatibleBulletListType[CompatibleBulletListType["UnfilledArrow"] = 6] = "UnfilledArrow"; /** * Bullet triggered by — */ CompatibleBulletListType[CompatibleBulletListType["Hyphen"] = 7] = "Hyphen"; /** * Bullet triggered by --> */ CompatibleBulletListType[CompatibleBulletListType["DoubleLongArrow"] = 8] = "DoubleLongArrow"; /** * Bullet type circle */ CompatibleBulletListType[CompatibleBulletListType["Circle"] = 9] = "Circle"; /** * Maximum value of the enum */ CompatibleBulletListType[CompatibleBulletListType["Max"] = 9] = "Max"; })(CompatibleBulletListType = exports.CompatibleBulletListType || (exports.CompatibleBulletListType = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/Capitalization.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/Capitalization.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleCapitalization = void 0; /** * The enum used for controlling the capitalization of text. * Used by changeCapitalization API */ var CompatibleCapitalization; (function (CompatibleCapitalization) { /** * Transforms the first character after punctuation mark followed by space * to uppercase and the rest of characters to lowercase. */ CompatibleCapitalization["Sentence"] = "sentence"; /** * Transforms all characters to lowercase */ CompatibleCapitalization["Lowercase"] = "lowercase"; /** * Transforms all characters to uppercase */ CompatibleCapitalization["Uppercase"] = "uppercase"; /** * Transforms the first character of each word to uppercase */ CompatibleCapitalization["CapitalizeEachWord"] = "capitalize"; })(CompatibleCapitalization = exports.CompatibleCapitalization || (exports.CompatibleCapitalization = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/ChangeSource.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/ChangeSource.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleChangeSource = void 0; /** * Possible change sources. Here are the predefined sources. * It can also be other string if the change source can't fall into these sources. */ var CompatibleChangeSource; (function (CompatibleChangeSource) { /** * Content changed by auto link */ CompatibleChangeSource["AutoLink"] = "AutoLink"; /** * Content changed by create link */ CompatibleChangeSource["CreateLink"] = "CreateLink"; /** * Content changed by format */ CompatibleChangeSource["Format"] = "Format"; /** * Content changed by image resize */ CompatibleChangeSource["ImageResize"] = "ImageResize"; /** * Content changed by paste */ CompatibleChangeSource["Paste"] = "Paste"; /** * Content changed by setContent API */ CompatibleChangeSource["SetContent"] = "SetContent"; /** * Content changed by cut operation */ CompatibleChangeSource["Cut"] = "Cut"; /** * Content changed by drag & drop operation */ CompatibleChangeSource["Drop"] = "Drop"; /** * Insert a new entity into editor */ CompatibleChangeSource["InsertEntity"] = "InsertEntity"; /** * Editor is switched to dark mode, content color is changed */ CompatibleChangeSource["SwitchToDarkMode"] = "SwitchToDarkMode"; /** * Editor is switched to light mode, content color is changed */ CompatibleChangeSource["SwitchToLightMode"] = "SwitchToLightMode"; /** * List chain reorganized numbers of lists */ CompatibleChangeSource["ListChain"] = "ListChain"; })(CompatibleChangeSource = exports.CompatibleChangeSource || (exports.CompatibleChangeSource = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/ClearFormatMode.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/ClearFormatMode.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleClearFormatMode = void 0; /** * Represents the strategy to clear the format of the current editor selection */ var CompatibleClearFormatMode; (function (CompatibleClearFormatMode) { /** * Inline format. Remove text format. */ CompatibleClearFormatMode[CompatibleClearFormatMode["Inline"] = 0] = "Inline"; /** * BLock format. Remove text and structure format of the block. */ CompatibleClearFormatMode[CompatibleClearFormatMode["Block"] = 1] = "Block"; /** * Detect Inline or Block format based on the current editor selector. */ CompatibleClearFormatMode[CompatibleClearFormatMode["AutoDetect"] = 2] = "AutoDetect"; })(CompatibleClearFormatMode = exports.CompatibleClearFormatMode || (exports.CompatibleClearFormatMode = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/ColorTransformDirection.ts": /*!***************************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/ColorTransformDirection.ts ***! \***************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleColorTransformDirection = void 0; /** * Represents the mode of color transformation */ var CompatibleColorTransformDirection; (function (CompatibleColorTransformDirection) { /** * Transform from light to dark */ CompatibleColorTransformDirection[CompatibleColorTransformDirection["LightToDark"] = 0] = "LightToDark"; /** * Transform from dark to light */ CompatibleColorTransformDirection[CompatibleColorTransformDirection["DarkToLight"] = 1] = "DarkToLight"; })(CompatibleColorTransformDirection = exports.CompatibleColorTransformDirection || (exports.CompatibleColorTransformDirection = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/ContentPosition.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/ContentPosition.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleContentPosition = void 0; /** * The position. Mostly used for content insertion and traversing * On insertion, we will need to specify where we want the content to be placed (begin, end, selection or outside) * On content traversing, we will need to specify the start position of traversing */ var CompatibleContentPosition; (function (CompatibleContentPosition) { /** * Begin of the container */ CompatibleContentPosition[CompatibleContentPosition["Begin"] = 0] = "Begin"; /** * End of the container */ CompatibleContentPosition[CompatibleContentPosition["End"] = 1] = "End"; /** * End of the content div domain. */ CompatibleContentPosition[CompatibleContentPosition["DomEnd"] = 2] = "DomEnd"; /** * Selection start */ CompatibleContentPosition[CompatibleContentPosition["SelectionStart"] = 3] = "SelectionStart"; /** * Outside of editor */ CompatibleContentPosition[CompatibleContentPosition["Outside"] = 4] = "Outside"; /** * Manually defined range */ CompatibleContentPosition[CompatibleContentPosition["Range"] = 5] = "Range"; })(CompatibleContentPosition = exports.CompatibleContentPosition || (exports.CompatibleContentPosition = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/ContentType.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/ContentType.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleContentType = exports.CompatibleContentTypePrefix = void 0; /** * Prefix of content types */ var CompatibleContentTypePrefix; (function (CompatibleContentTypePrefix) { /** * Text type prefix */ CompatibleContentTypePrefix["Text"] = "text/"; /** * Image type prefix */ CompatibleContentTypePrefix["Image"] = "image/"; })(CompatibleContentTypePrefix = exports.CompatibleContentTypePrefix || (exports.CompatibleContentTypePrefix = {})); /** * Known content types */ var CompatibleContentType; (function (CompatibleContentType) { /** * Plain text content type */ CompatibleContentType["PlainText"] = "text/plain"; /** * HTML content type */ CompatibleContentType["HTML"] = "text/html"; })(CompatibleContentType = exports.CompatibleContentType || (exports.CompatibleContentType = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/DarkModeDatasetNames.ts": /*!************************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/DarkModeDatasetNames.ts ***! \************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleDarkModeDatasetNames = void 0; /** * Constants string for dataset names used by dark mode */ var CompatibleDarkModeDatasetNames; (function (CompatibleDarkModeDatasetNames) { /** * Original style text color */ CompatibleDarkModeDatasetNames["OriginalStyleColor"] = "ogsc"; /** * Original style background color */ CompatibleDarkModeDatasetNames["OriginalStyleBackgroundColor"] = "ogsb"; /** * Original attribute text color */ CompatibleDarkModeDatasetNames["OriginalAttributeColor"] = "ogac"; /** * Original attribute background color */ CompatibleDarkModeDatasetNames["OriginalAttributeBackgroundColor"] = "ogab"; })(CompatibleDarkModeDatasetNames = exports.CompatibleDarkModeDatasetNames || (exports.CompatibleDarkModeDatasetNames = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/DefinitionType.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/DefinitionType.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleDefinitionType = void 0; /** * Types of definitions, used by Definition type */ var CompatibleDefinitionType; (function (CompatibleDefinitionType) { /** * Boolean type definition, represents a boolean type value */ CompatibleDefinitionType[CompatibleDefinitionType["Boolean"] = 0] = "Boolean"; /** * Number type definition, represents a number type value */ CompatibleDefinitionType[CompatibleDefinitionType["Number"] = 1] = "Number"; /** * String type definition, represents a string type value */ CompatibleDefinitionType[CompatibleDefinitionType["String"] = 2] = "String"; /** * Array type definition, represents an array with a given item type */ CompatibleDefinitionType[CompatibleDefinitionType["Array"] = 3] = "Array"; /** * Object type definition, represents an object with the given property types */ CompatibleDefinitionType[CompatibleDefinitionType["Object"] = 4] = "Object"; /** * Customize type definition, represents a customized type with a validator function */ CompatibleDefinitionType[CompatibleDefinitionType["Customize"] = 5] = "Customize"; })(CompatibleDefinitionType = exports.CompatibleDefinitionType || (exports.CompatibleDefinitionType = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/Direction.ts": /*!*************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/Direction.ts ***! \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleDirection = void 0; /** * enum for setting block direction, used by setDirection API */ var CompatibleDirection; (function (CompatibleDirection) { /** * Left to right */ CompatibleDirection[CompatibleDirection["LeftToRight"] = 0] = "LeftToRight"; /** * Right to left */ CompatibleDirection[CompatibleDirection["RightToLeft"] = 1] = "RightToLeft"; })(CompatibleDirection = exports.CompatibleDirection || (exports.CompatibleDirection = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/DocumentCommand.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/DocumentCommand.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleDocumentCommand = void 0; /** * Command strings for Document.execCommand() API * https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand */ var CompatibleDocumentCommand; (function (CompatibleDocumentCommand) { /** * Changes the browser auto-link behavior (Internet Explorer only) */ CompatibleDocumentCommand["AutoUrlDetect"] = "AutoUrlDetect"; /** * Changes the document background color. In styleWithCss mode, it affects the background color of the containing block instead. * This requires a <color> value string to be passed in as a value argument. Note that Internet Explorer uses this to set the * text background color. */ CompatibleDocumentCommand["BackColor"] = "backColor"; /** * Toggles bold on/off for the selection or at the insertion point. Internet Explorer uses the <strong> tag instead of <b>. */ CompatibleDocumentCommand["Bold"] = "bold"; /** * Clears all authentication credentials from the cache. */ CompatibleDocumentCommand["ClearAuthenticationCache"] = "ClearAuthenticationCache"; /** * Makes the content document either read-only or editable. This requires a boolean true/false as the value argument. * (Not supported by Internet Explorer.) */ CompatibleDocumentCommand["ContentReadOnly"] = "contentReadOnly"; /** * Copies the current selection to the clipboard. Conditions of having this behavior enabled vary from one browser to another, * and have evolved over time. Check the compatibility table to determine if you can use it in your case. */ CompatibleDocumentCommand["Copy"] = "copy"; /** * Creates an hyperlink from the selection, but only if there is a selection. Requires a URI string as a value argument for the * hyperlink's href. The URI must contain at least a single character, which may be whitespace. * (Internet Explorer will create a link with a null value.) */ CompatibleDocumentCommand["CreateLink"] = "createLink"; /** * Removes the current selection and copies it to the clipboard. When this behavior is enabled varies between browsers, * and its conditions have evolved over time. Check the compatibility table for usage details. */ CompatibleDocumentCommand["Cut"] = "cut"; /** * Adds a <small> tag around the selection or at the insertion point. (Not supported by Internet Explorer.) */ CompatibleDocumentCommand["DecreaseFontSize"] = "decreaseFontSize"; /** * Changes the paragraph separator used when new paragraphs are created in editable text regions. See Differences in markup * generation for more details. */ CompatibleDocumentCommand["DefaultParagraphSeparator"] = "defaultParagraphSeparator"; /** * Deletes the current selection. */ CompatibleDocumentCommand["Delete"] = "delete"; /** * Enables or disables the table row/column insertion and deletion controls. (Not supported by Internet Explorer.) */ CompatibleDocumentCommand["EnableInlineTableEditing"] = "enableInlineTableEditing"; /** * Enables or disables the resize handles on images and other resizable objects. (Not supported by Internet Explorer.) */ CompatibleDocumentCommand["EnableObjectResizing"] = "enableObjectResizing"; /** * Changes the font name for the selection or at the insertion point. This requires a font name string (like "Arial") * as a value argument. */ CompatibleDocumentCommand["FontName"] = "fontName"; /** * Changes the font size for the selection or at the insertion point. This requires an integer from 1-7 as a value argument. */ CompatibleDocumentCommand["FontSize"] = "fontSize"; /** * Changes a font color for the selection or at the insertion point. This requires a hexadecimal color value string * as a value argument. */ CompatibleDocumentCommand["ForeColor"] = "foreColor"; /** * Adds an HTML block-level element around the line containing the current selection, replacing the block element containing * the line if one exists (in Firefox, <blockquote> is the exception — it will wrap any containing block element). * Requires a tag-name string as a value argument. Virtually all block-level elements can be used. * (Internet Explorer supports only heading tags H1–H6, ADDRESS, and PRE, which must be wrapped in angle brackets, such as "<H1>".) */ CompatibleDocumentCommand["FormatBlock"] = "formatBlock"; /** * Deletes the character ahead of the cursor's position, identical to hitting the Delete key on a Windows keyboard. */ CompatibleDocumentCommand["ForwardDelete"] = "forwardDelete"; /** * Adds a heading element around a selection or insertion point line. Requires the tag-name strings a value argument (i.e. "H1", "H6"). * (Not supported by Internet Explorer and Safari.) */ CompatibleDocumentCommand["Heading"] = "heading"; /** * Changes the background color for the selection or at the insertion point. Requires a color value string as a value argument. * useCSS must be true for this to function. (Not supported by Internet Explorer.) */ CompatibleDocumentCommand["HiliteColor"] = "hiliteColor"; /** * Adds a <big> tag around the selection or at the insertion point. (Not supported by Internet Explorer.) */ CompatibleDocumentCommand["IncreaseFontSize"] = "increaseFontSize"; /** * Indents the line containing the selection or insertion point. In Firefox, if the selection spans multiple lines at different * levels of indentation, only the least indented lines in the selection will be indented. */ CompatibleDocumentCommand["Indent"] = "indent"; /** * Controls whether the Enter key inserts a <br> element, or splits the current block element into two. * (Not supported by Internet Explorer.) */ CompatibleDocumentCommand["InsertBrOnReturn"] = "insertBrOnReturn"; /** * Inserts a <hr> element at the insertion point, or replaces the selection with it. */ CompatibleDocumentCommand["InsertHorizontalRule"] = "insertHorizontalRule"; /** * Inserts an HTML string at the insertion point (deletes selection). Requires a valid HTML string as a value argument. * (Not supported by Internet Explorer.) */ CompatibleDocumentCommand["InsertHTML"] = "insertHTML"; /** * Inserts an image at the insertion point (deletes selection). Requires a URL string for the image's src as a value argument. * The requirements for this string are the same as createLink. */ CompatibleDocumentCommand["InsertImage"] = "insertImage"; /** * Creates a numbered ordered list for the selection or at the insertion point. */ CompatibleDocumentCommand["InsertOrderedList"] = "insertOrderedList"; /** * Creates a bulleted unordered list for the selection or at the insertion point. */ CompatibleDocumentCommand["InsertUnorderedList"] = "insertUnorderedList"; /** * Inserts a paragraph around the selection or the current line. * (Internet Explorer inserts a paragraph at the insertion point and deletes the selection.) */ CompatibleDocumentCommand["InsertParagraph"] = "insertParagraph"; /** * Inserts the given plain text at the insertion point (deletes selection). */ CompatibleDocumentCommand["InsertText"] = "insertText"; /** * Toggles italics on/off for the selection or at the insertion point. * (Internet Explorer uses the <em> element instead of <i>.) */ CompatibleDocumentCommand["Italic"] = "italic"; /** * Centers the selection or insertion point. */ CompatibleDocumentCommand["JustifyCenter"] = "justifyCenter"; /** * Justifies the selection or insertion point. */ CompatibleDocumentCommand["JustifyFull"] = "justifyFull"; /** * Justifies the selection or insertion point to the left. */ CompatibleDocumentCommand["JustifyLeft"] = "justifyLeft"; /** * Right-justifies the selection or the insertion point. */ CompatibleDocumentCommand["JustifyRight"] = "justifyRight"; /** * Outdents the line containing the selection or insertion point. */ CompatibleDocumentCommand["Outdent"] = "outdent"; /** * Pastes the clipboard contents at the insertion point (replaces current selection). Disabled for web content. See [1]. */ CompatibleDocumentCommand["Paste"] = "paste"; /** * Redoes the previous undo command. */ CompatibleDocumentCommand["Redo"] = "redo"; /** * Removes all formatting from the current selection. */ CompatibleDocumentCommand["RemoveFormat"] = "removeFormat"; /** * Selects all of the content of the editable region. */ CompatibleDocumentCommand["SelectAll"] = "selectAll"; /** * Toggles strikethrough on/off for the selection or at the insertion point. */ CompatibleDocumentCommand["StrikeThrough"] = "strikeThrough"; /** * Toggles subscript on/off for the selection or at the insertion point. */ CompatibleDocumentCommand["Subscript"] = "subscript"; /** * Toggles superscript on/off for the selection or at the insertion point. */ CompatibleDocumentCommand["Superscript"] = "superscript"; /** * Toggles underline on/off for the selection or at the insertion point. */ CompatibleDocumentCommand["Underline"] = "underline"; /** * Undoes the last executed command. */ CompatibleDocumentCommand["Undo"] = "undo"; /** * Removes the anchor element from a selected hyperlink. */ CompatibleDocumentCommand["Unlink"] = "unlink"; /** * Replaces the useCSS command. true modifies/generates style attributes in markup, false generates presentational elements. */ CompatibleDocumentCommand["StyleWithCSS"] = "styleWithCSS"; })(CompatibleDocumentCommand = exports.CompatibleDocumentCommand || (exports.CompatibleDocumentCommand = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/DocumentPosition.ts": /*!********************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/DocumentPosition.ts ***! \********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleDocumentPosition = void 0; /** * The is essentially an enum representing result from browser compareDocumentPosition API * https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition */ var CompatibleDocumentPosition; (function (CompatibleDocumentPosition) { /** * Same node */ CompatibleDocumentPosition[CompatibleDocumentPosition["Same"] = 0] = "Same"; /** * Node is disconnected from document */ CompatibleDocumentPosition[CompatibleDocumentPosition["Disconnected"] = 1] = "Disconnected"; /** * Node is preceding the comparing node */ CompatibleDocumentPosition[CompatibleDocumentPosition["Preceding"] = 2] = "Preceding"; /** * Node is following the comparing node */ CompatibleDocumentPosition[CompatibleDocumentPosition["Following"] = 4] = "Following"; /** * Node contains the comparing node */ CompatibleDocumentPosition[CompatibleDocumentPosition["Contains"] = 8] = "Contains"; /** * Node is contained by the comparing node */ CompatibleDocumentPosition[CompatibleDocumentPosition["ContainedBy"] = 16] = "ContainedBy"; })(CompatibleDocumentPosition = exports.CompatibleDocumentPosition || (exports.CompatibleDocumentPosition = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/EntityClasses.ts": /*!*****************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/EntityClasses.ts ***! \*****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleEntityClasses = void 0; /** * CSS Class names for Entity */ var CompatibleEntityClasses; (function (CompatibleEntityClasses) { /** * Class name to specify this is an entity */ CompatibleEntityClasses["ENTITY_INFO_NAME"] = "_Entity"; /** * Class name to specify the type of an entity */ CompatibleEntityClasses["ENTITY_TYPE_PREFIX"] = "_EType_"; /** * Class name to specify the ID of an entity */ CompatibleEntityClasses["ENTITY_ID_PREFIX"] = "_EId_"; /** * Class name to specify if the entity is readonly */ CompatibleEntityClasses["ENTITY_READONLY_PREFIX"] = "_EReadonly_"; })(CompatibleEntityClasses = exports.CompatibleEntityClasses || (exports.CompatibleEntityClasses = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/EntityOperation.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/EntityOperation.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleEntityOperation = void 0; /** * Define possible operations to an entity */ var CompatibleEntityOperation; (function (CompatibleEntityOperation) { /** * Notify plugins that there is a new plugin was added into editor. * Plugin can handle this event to entity hydration. * This event will be only fired once for each entity DOM node. * After undo, or copy/paste, since new DOM nodes were added, this event will be fired * for those entities represented by newly added nodes. */ CompatibleEntityOperation[CompatibleEntityOperation["NewEntity"] = 0] = "NewEntity"; /** * Notify plugins that user is clicking target to an entity */ CompatibleEntityOperation[CompatibleEntityOperation["Click"] = 1] = "Click"; /** * Notify plugins that user is triggering context menu to an entity */ CompatibleEntityOperation[CompatibleEntityOperation["ContextMenu"] = 2] = "ContextMenu"; /** * Notify plugins that user is escaping from an entity by pressing ESC key */ CompatibleEntityOperation[CompatibleEntityOperation["Escape"] = 3] = "Escape"; /** * Notify plugins that user is removing an entity from its start position using DELETE key */ CompatibleEntityOperation[CompatibleEntityOperation["RemoveFromStart"] = 4] = "RemoveFromStart"; /** * Notify plugins that user is remove an entity from its end position using BACKSPACE key */ CompatibleEntityOperation[CompatibleEntityOperation["RemoveFromEnd"] = 5] = "RemoveFromEnd"; /** * Notify plugins that an entity is being overwritten. * This can be caused by key in, cut, paste, delete, backspace ... on a selection * which contains some entities. */ CompatibleEntityOperation[CompatibleEntityOperation["Overwrite"] = 6] = "Overwrite"; /** * Notify plugins that an entity is being partially overwritten. * This happens when user selected part of the entity then do key press, or cut, paste, delete, backspace, ... */ CompatibleEntityOperation[CompatibleEntityOperation["PartialOverwrite"] = 7] = "PartialOverwrite"; /** * Notify plugins that editor is generating HTML content for save. * Plugin should use this event to remove any temporary content, and only leave DOM nodes that * should be saved as HTML string. * This event will provide a cloned DOM tree for each entity, do NOT compare the DOM nodes with cached nodes * because it will always return false. */ CompatibleEntityOperation[CompatibleEntityOperation["ReplaceTemporaryContent"] = 8] = "ReplaceTemporaryContent"; /** * Notify plugins that editor has attached shadow root for an entity. * Plugins can handle this event to do extra operations to the shadow root */ CompatibleEntityOperation[CompatibleEntityOperation["AddShadowRoot"] = 9] = "AddShadowRoot"; /** * Notify plugins that editor has removed the shadow root of an entity * Plugins can handle this event to do any necessary clean up for shadow root */ CompatibleEntityOperation[CompatibleEntityOperation["RemoveShadowRoot"] = 10] = "RemoveShadowRoot"; })(CompatibleEntityOperation = exports.CompatibleEntityOperation || (exports.CompatibleEntityOperation = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/ExperimentalFeatures.ts": /*!************************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/ExperimentalFeatures.ts ***! \************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleExperimentalFeatures = void 0; /** * Experimental feature flags */ var CompatibleExperimentalFeatures; (function (CompatibleExperimentalFeatures) { /** * @deprecated This feature is always enabled */ CompatibleExperimentalFeatures["NewIndentation"] = "NewIndentation"; /** * @deprecated This feature is always enabled */ CompatibleExperimentalFeatures["NewBullet"] = "NewBullet"; /** * @deprecated This feature is always enabled */ CompatibleExperimentalFeatures["NewNumbering"] = "NewNumbering"; /** * @deprecated This feature is always enabled */ CompatibleExperimentalFeatures["ListChain"] = "ListChain"; /** * @deprecated This feature is always enabled */ CompatibleExperimentalFeatures["MergePastedLine"] = "MergePastedLine"; /** * @deprecated This feature is always enabled */ CompatibleExperimentalFeatures["SingleDirectionResize"] = "SingleDirectionResize"; /** * @deprecated This feature is always enabled */ CompatibleExperimentalFeatures["PasteWithLinkPreview"] = "PasteWithLinkPreview"; /** * @deprecated This feature is always enabled */ CompatibleExperimentalFeatures["ImageRotate"] = "ImageRotate"; /** * @deprecated This feature is always enabled */ CompatibleExperimentalFeatures["ImageCrop"] = "ImageCrop"; /** * @deprecated This feature is always enabled * Check if the element has a style attribute, if not, apply the default format */ CompatibleExperimentalFeatures["AlwaysApplyDefaultFormat"] = "AlwaysApplyDefaultFormat"; /** * @deprecated This feature can be enabled/disabled using Paste Plugin contructor param * Paste the Html instead of the Img when the Html Body only have one IMG Child node */ CompatibleExperimentalFeatures["ConvertSingleImageBody"] = "ConvertSingleImageBody"; /** * @deprecated This feature is always enabled * Align table elements to left, center and right using setAlignment API */ CompatibleExperimentalFeatures["TableAlignment"] = "TableAlignment"; /** * Provide additional Tab Key Features. Requires Text Features Content Editable Features */ CompatibleExperimentalFeatures["TabKeyTextFeatures"] = "TabKeyTextFeatures"; /** * @deprecated this feature is always enabled * Provide a circular resize handles that adaptive the number od handles to the size of the image */ CompatibleExperimentalFeatures["AdaptiveHandlesResizer"] = "AdaptiveHandlesResizer"; /** * Align list elements elements to left, center and right using setAlignment API */ CompatibleExperimentalFeatures["ListItemAlignment"] = "ListItemAlignment"; /** * Trigger formatting by a especial characters. Ex: (A), 1. i). */ CompatibleExperimentalFeatures["AutoFormatList"] = "AutoFormatList"; /** * @deprecated this feature is always disabled * Automatically transform -- into hyphen, if typed between two words. */ CompatibleExperimentalFeatures["AutoHyphen"] = "AutoHyphen"; /** * @deprecated this feature is always disabled * Use pending format strategy to do style based format, e.g. Font size, Color. * With this feature enabled, we don't need to insert temp ZeroWidthSpace character to hold pending format * when selection is collapsed. Instead, we will hold the pending format in memory and only apply it when type something */ CompatibleExperimentalFeatures["PendingStyleBasedFormat"] = "PendingStyleBasedFormat"; /** * @deprecated this feature is always disabled * Normalize list to make sure it can be displayed correctly in other client * e.g. We will move list items with "display: block" into previous list item and change tag to be DIV */ CompatibleExperimentalFeatures["NormalizeList"] = "NormalizeList"; /** * @deprecated this feature is always enabled * When a html image is selected, the selected image data will be stored by editor core. */ CompatibleExperimentalFeatures["ImageSelection"] = "ImageSelection"; /** * With this feature enabled, when writing back a list item we will re-use all * ancestor list elements, even if they don't match the types currently in the * listTypes array for that item. The only list that we will ensure is correct * is the one closest to the item. */ CompatibleExperimentalFeatures["ReuseAllAncestorListElements"] = "ReuseAllAncestorListElements"; /** * When apply default format when initialize or user type, apply the format on a SPAN element rather than * the block element (In most case, the DIV element) so keep the block element clean. */ CompatibleExperimentalFeatures["DefaultFormatInSpan"] = "DefaultFormatInSpan"; /** * Use variable-based dark mode solution rather than dataset-based solution. * When enable this feature, need to pass in a DarkModelHandler object to each call of setColor and applyFormat * if you need them work for dark mode */ CompatibleExperimentalFeatures["VariableBasedDarkColor"] = "VariableBasedDarkColor"; })(CompatibleExperimentalFeatures = exports.CompatibleExperimentalFeatures || (exports.CompatibleExperimentalFeatures = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/FontSizeChange.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/FontSizeChange.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleFontSizeChange = void 0; /** * The enum used for increase or decrease font size * Used by setFontSize API */ var CompatibleFontSizeChange; (function (CompatibleFontSizeChange) { /** * Increase font size */ CompatibleFontSizeChange[CompatibleFontSizeChange["Increase"] = 0] = "Increase"; /** * Decrease font size */ CompatibleFontSizeChange[CompatibleFontSizeChange["Decrease"] = 1] = "Decrease"; })(CompatibleFontSizeChange = exports.CompatibleFontSizeChange || (exports.CompatibleFontSizeChange = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/GetContentMode.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/GetContentMode.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleGetContentMode = void 0; /** * Represents a mode number to indicate what kind of content to retrieve when call Editor.getContent() */ var CompatibleGetContentMode; (function (CompatibleGetContentMode) { /** * The clean content without any temporary content only for editor. * This is the default value. Call to Editor.getContent() with trigger an ExtractContentWithDom event * so that plugins can remove their temporary content, and will return the HTML content * which is ready for save to storage. */ CompatibleGetContentMode[CompatibleGetContentMode["CleanHTML"] = 0] = "CleanHTML"; /** * Retrieve the raw HTML string in current editor. Temporary content will be included. */ CompatibleGetContentMode[CompatibleGetContentMode["RawHTMLOnly"] = 1] = "RawHTMLOnly"; /** * Retrieve the raw HTML string in current editor with a selection marker. This can be used for * save current editor state and call to SetContent with this result can fully restore editor state * including current selection */ CompatibleGetContentMode[CompatibleGetContentMode["RawHTMLWithSelection"] = 2] = "RawHTMLWithSelection"; /** * Get plain text content only, all format will be ignored */ CompatibleGetContentMode[CompatibleGetContentMode["PlainText"] = 3] = "PlainText"; /** * A fast way to get plain text content, the line-end positions may not be exactly same with HTML content, * but the text content should be the same. This is used for quickly retrieve text content and check * text only */ CompatibleGetContentMode[CompatibleGetContentMode["PlainTextFast"] = 4] = "PlainTextFast"; })(CompatibleGetContentMode = exports.CompatibleGetContentMode || (exports.CompatibleGetContentMode = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/ImageEditOperation.ts": /*!**********************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/ImageEditOperation.ts ***! \**********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleImageEditOperation = void 0; /** * Operation flags for ImageEdit plugin */ var CompatibleImageEditOperation; (function (CompatibleImageEditOperation) { /** * No operation */ CompatibleImageEditOperation[CompatibleImageEditOperation["None"] = 0] = "None"; /** * Resize image from corner ( horizontal and vertical resize) */ CompatibleImageEditOperation[CompatibleImageEditOperation["CornerResize"] = 1] = "CornerResize"; /** * Resize image from side ( either horizontal or vertical resize) */ CompatibleImageEditOperation[CompatibleImageEditOperation["SideResize"] = 2] = "SideResize"; /** * Image resize */ CompatibleImageEditOperation[CompatibleImageEditOperation["Resize"] = 3] = "Resize"; /** * Image rotate */ CompatibleImageEditOperation[CompatibleImageEditOperation["Rotate"] = 4] = "Rotate"; /** * Image resize and rotate */ CompatibleImageEditOperation[CompatibleImageEditOperation["ResizeAndRotate"] = 7] = "ResizeAndRotate"; /** * Image crop */ CompatibleImageEditOperation[CompatibleImageEditOperation["Crop"] = 8] = "Crop"; /** * All operations */ CompatibleImageEditOperation[CompatibleImageEditOperation["All"] = 15] = "All"; })(CompatibleImageEditOperation = exports.CompatibleImageEditOperation || (exports.CompatibleImageEditOperation = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/Indentation.ts": /*!***************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/Indentation.ts ***! \***************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleIndentation = void 0; /** * The enum used for increase or decrease indentation of a block * Used by setIndentation API */ var CompatibleIndentation; (function (CompatibleIndentation) { /** * Increase indentation */ CompatibleIndentation[CompatibleIndentation["Increase"] = 0] = "Increase"; /** * Decrease indentation */ CompatibleIndentation[CompatibleIndentation["Decrease"] = 1] = "Decrease"; })(CompatibleIndentation = exports.CompatibleIndentation || (exports.CompatibleIndentation = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/Keys.ts": /*!********************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/Keys.ts ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleKeys = void 0; /** * Key numbers common used keys */ var CompatibleKeys; (function (CompatibleKeys) { CompatibleKeys[CompatibleKeys["NULL"] = 0] = "NULL"; CompatibleKeys[CompatibleKeys["BACKSPACE"] = 8] = "BACKSPACE"; CompatibleKeys[CompatibleKeys["TAB"] = 9] = "TAB"; CompatibleKeys[CompatibleKeys["ENTER"] = 13] = "ENTER"; CompatibleKeys[CompatibleKeys["SHIFT"] = 16] = "SHIFT"; CompatibleKeys[CompatibleKeys["CTRL_LEFT"] = 17] = "CTRL_LEFT"; CompatibleKeys[CompatibleKeys["ALT"] = 18] = "ALT"; CompatibleKeys[CompatibleKeys["ESCAPE"] = 27] = "ESCAPE"; CompatibleKeys[CompatibleKeys["SPACE"] = 32] = "SPACE"; CompatibleKeys[CompatibleKeys["PAGEUP"] = 33] = "PAGEUP"; CompatibleKeys[CompatibleKeys["END"] = 35] = "END"; CompatibleKeys[CompatibleKeys["HOME"] = 36] = "HOME"; CompatibleKeys[CompatibleKeys["LEFT"] = 37] = "LEFT"; CompatibleKeys[CompatibleKeys["UP"] = 38] = "UP"; CompatibleKeys[CompatibleKeys["RIGHT"] = 39] = "RIGHT"; CompatibleKeys[CompatibleKeys["DOWN"] = 40] = "DOWN"; CompatibleKeys[CompatibleKeys["PRINT_SCREEN"] = 44] = "PRINT_SCREEN"; CompatibleKeys[CompatibleKeys["DELETE"] = 46] = "DELETE"; /** * @deprecated Just for backward compatibility */ CompatibleKeys[CompatibleKeys["EIGHT_ASTIRISK"] = 56] = "EIGHT_ASTIRISK"; CompatibleKeys[CompatibleKeys["EIGHT_ASTERISK"] = 56] = "EIGHT_ASTERISK"; CompatibleKeys[CompatibleKeys["B"] = 66] = "B"; CompatibleKeys[CompatibleKeys["I"] = 73] = "I"; CompatibleKeys[CompatibleKeys["U"] = 85] = "U"; CompatibleKeys[CompatibleKeys["Y"] = 89] = "Y"; CompatibleKeys[CompatibleKeys["Z"] = 90] = "Z"; CompatibleKeys[CompatibleKeys["META_LEFT"] = 91] = "META_LEFT"; CompatibleKeys[CompatibleKeys["COMMA"] = 188] = "COMMA"; CompatibleKeys[CompatibleKeys["DASH_UNDERSCORE"] = 189] = "DASH_UNDERSCORE"; CompatibleKeys[CompatibleKeys["PERIOD"] = 190] = "PERIOD"; /** * @deprecated Just for backward compatibility */ CompatibleKeys[CompatibleKeys["FORWARDSLASH"] = 191] = "FORWARDSLASH"; CompatibleKeys[CompatibleKeys["FORWARD_SLASH"] = 191] = "FORWARD_SLASH"; CompatibleKeys[CompatibleKeys["GRAVE_TILDE"] = 192] = "GRAVE_TILDE"; /** * Keys below are non-standard, and should be used in ContentEditFeatures only */ CompatibleKeys[CompatibleKeys["CONTENTCHANGED"] = 257] = "CONTENTCHANGED"; CompatibleKeys[CompatibleKeys["RANGE"] = 258] = "RANGE"; CompatibleKeys[CompatibleKeys["Ctrl"] = 4096] = "Ctrl"; CompatibleKeys[CompatibleKeys["Meta"] = 8192] = "Meta"; CompatibleKeys[CompatibleKeys["Shift"] = 16384] = "Shift"; })(CompatibleKeys = exports.CompatibleKeys || (exports.CompatibleKeys = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/KnownCreateElementDataIndex.ts": /*!*******************************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/KnownCreateElementDataIndex.ts ***! \*******************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleKnownCreateElementDataIndex = void 0; /** * Index of known CreateElementData used by createElement function */ var CompatibleKnownCreateElementDataIndex; (function (CompatibleKnownCreateElementDataIndex) { /** * Set a none value to help createElement function ignore falsy value */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["None"] = 0] = "None"; /** * An empty line without format */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["EmptyLine"] = 1] = "EmptyLine"; /** * Wrapper for blockquote */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["BlockquoteWrapper"] = 2] = "BlockquoteWrapper"; /** * Temp DIV for copy/paste */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["CopyPasteTempDiv"] = 3] = "CopyPasteTempDiv"; /** * ListItem with block style */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["BlockListItem"] = 4] = "BlockListItem"; /** * Wrapper element for context menu */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["ContextMenuWrapper"] = 5] = "ContextMenuWrapper"; /** * Wrapper element for image edit */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["ImageEditWrapper"] = 6] = "ImageEditWrapper"; /** * @deprecated */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["TableHorizontalResizer"] = 7] = "TableHorizontalResizer"; /** * @deprecated */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["TableVerticalResizer"] = 8] = "TableVerticalResizer"; /** * @deprecated */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["TableResizerLTR"] = 9] = "TableResizerLTR"; /** * @deprecated */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["TableResizerRTL"] = 10] = "TableResizerRTL"; /** * @deprecated */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["TableSelector"] = 11] = "TableSelector"; /** * An empty line without format with span inside of it. */ CompatibleKnownCreateElementDataIndex[CompatibleKnownCreateElementDataIndex["EmptyLineFormatInSpan"] = 12] = "EmptyLineFormatInSpan"; })(CompatibleKnownCreateElementDataIndex = exports.CompatibleKnownCreateElementDataIndex || (exports.CompatibleKnownCreateElementDataIndex = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/ListType.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/ListType.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleListType = void 0; /** * Type of list (numbering or bullet) */ var CompatibleListType; (function (CompatibleListType) { /** * None list type * It means this is not a list */ CompatibleListType[CompatibleListType["None"] = 0] = "None"; /** * Ordered List type (numbering list) * Represented by "OL" tag */ CompatibleListType[CompatibleListType["Ordered"] = 1] = "Ordered"; /** * Unordered List type (bullet list) * Represented by "UL" tag */ CompatibleListType[CompatibleListType["Unordered"] = 2] = "Unordered"; })(CompatibleListType = exports.CompatibleListType || (exports.CompatibleListType = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/NodeType.ts": /*!************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/NodeType.ts ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleNodeType = void 0; /** * The is essentially an enum represents the type of the node * https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType * Values not listed here are deprecated. */ var CompatibleNodeType; (function (CompatibleNodeType) { /** * An Element node such as <p> or <div>. */ CompatibleNodeType[CompatibleNodeType["Element"] = 1] = "Element"; /** * An Attribute node such as name="value". */ CompatibleNodeType[CompatibleNodeType["Attribute"] = 2] = "Attribute"; /** * The actual Text of Element or Attr. */ CompatibleNodeType[CompatibleNodeType["Text"] = 3] = "Text"; /** * A ProcessingInstruction of an XML document such as <?xml-stylesheet ... ?> declaration. */ CompatibleNodeType[CompatibleNodeType["ProcessingInstruction"] = 7] = "ProcessingInstruction"; /** * A Comment node. */ CompatibleNodeType[CompatibleNodeType["Comment"] = 8] = "Comment"; /** * A Document node. */ CompatibleNodeType[CompatibleNodeType["Document"] = 9] = "Document"; /** * A DocumentType node e.g. <!DOCTYPE html> for HTML5 documents. */ CompatibleNodeType[CompatibleNodeType["DocumentType"] = 10] = "DocumentType"; /** * A DocumentFragment node. */ CompatibleNodeType[CompatibleNodeType["DocumentFragment"] = 11] = "DocumentFragment"; })(CompatibleNodeType = exports.CompatibleNodeType || (exports.CompatibleNodeType = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/NumberingListType.ts": /*!*********************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/NumberingListType.ts ***! \*********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleNumberingListType = void 0; /** * Enum used to control the different types of numbering list */ var CompatibleNumberingListType; (function (CompatibleNumberingListType) { /** * Minimum value of the enum */ CompatibleNumberingListType[CompatibleNumberingListType["Min"] = 1] = "Min"; /** * Numbering triggered by 1. */ CompatibleNumberingListType[CompatibleNumberingListType["Decimal"] = 1] = "Decimal"; /** * Numbering triggered by 1- */ CompatibleNumberingListType[CompatibleNumberingListType["DecimalDash"] = 2] = "DecimalDash"; /** * Numbering triggered by 1) */ CompatibleNumberingListType[CompatibleNumberingListType["DecimalParenthesis"] = 3] = "DecimalParenthesis"; /** * Numbering triggered by (1) */ CompatibleNumberingListType[CompatibleNumberingListType["DecimalDoubleParenthesis"] = 4] = "DecimalDoubleParenthesis"; /** * Numbering triggered by a. */ CompatibleNumberingListType[CompatibleNumberingListType["LowerAlpha"] = 5] = "LowerAlpha"; /** * Numbering triggered by a) */ CompatibleNumberingListType[CompatibleNumberingListType["LowerAlphaParenthesis"] = 6] = "LowerAlphaParenthesis"; /** * Numbering triggered by (a) */ CompatibleNumberingListType[CompatibleNumberingListType["LowerAlphaDoubleParenthesis"] = 7] = "LowerAlphaDoubleParenthesis"; /** * Numbering triggered by a- */ CompatibleNumberingListType[CompatibleNumberingListType["LowerAlphaDash"] = 8] = "LowerAlphaDash"; /** * Numbering triggered by A. */ CompatibleNumberingListType[CompatibleNumberingListType["UpperAlpha"] = 9] = "UpperAlpha"; /** * Numbering triggered by A) */ CompatibleNumberingListType[CompatibleNumberingListType["UpperAlphaParenthesis"] = 10] = "UpperAlphaParenthesis"; /** * Numbering triggered by (A) */ CompatibleNumberingListType[CompatibleNumberingListType["UpperAlphaDoubleParenthesis"] = 11] = "UpperAlphaDoubleParenthesis"; /** * Numbering triggered by A- */ CompatibleNumberingListType[CompatibleNumberingListType["UpperAlphaDash"] = 12] = "UpperAlphaDash"; /** * Numbering triggered by i. */ CompatibleNumberingListType[CompatibleNumberingListType["LowerRoman"] = 13] = "LowerRoman"; /** * Numbering triggered by i) */ CompatibleNumberingListType[CompatibleNumberingListType["LowerRomanParenthesis"] = 14] = "LowerRomanParenthesis"; /** * Numbering triggered by (i) */ CompatibleNumberingListType[CompatibleNumberingListType["LowerRomanDoubleParenthesis"] = 15] = "LowerRomanDoubleParenthesis"; /** * Numbering triggered by i- */ CompatibleNumberingListType[CompatibleNumberingListType["LowerRomanDash"] = 16] = "LowerRomanDash"; /** * Numbering triggered by I. */ CompatibleNumberingListType[CompatibleNumberingListType["UpperRoman"] = 17] = "UpperRoman"; /** * Numbering triggered by I) */ CompatibleNumberingListType[CompatibleNumberingListType["UpperRomanParenthesis"] = 18] = "UpperRomanParenthesis"; /** * Numbering triggered by (I) */ CompatibleNumberingListType[CompatibleNumberingListType["UpperRomanDoubleParenthesis"] = 19] = "UpperRomanDoubleParenthesis"; /** * Numbering triggered by I- */ CompatibleNumberingListType[CompatibleNumberingListType["UpperRomanDash"] = 20] = "UpperRomanDash"; /** * Maximum value of the enum */ CompatibleNumberingListType[CompatibleNumberingListType["Max"] = 20] = "Max"; })(CompatibleNumberingListType = exports.CompatibleNumberingListType || (exports.CompatibleNumberingListType = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/PluginEventType.ts": /*!*******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/PluginEventType.ts ***! \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatiblePluginEventType = void 0; /** * Editor plugin event type */ var CompatiblePluginEventType; (function (CompatiblePluginEventType) { /** * HTML KeyDown event */ CompatiblePluginEventType[CompatiblePluginEventType["KeyDown"] = 0] = "KeyDown"; /** * HTML KeyPress event */ CompatiblePluginEventType[CompatiblePluginEventType["KeyPress"] = 1] = "KeyPress"; /** * HTML KeyUp event */ CompatiblePluginEventType[CompatiblePluginEventType["KeyUp"] = 2] = "KeyUp"; /** * HTML Input / TextInput event */ CompatiblePluginEventType[CompatiblePluginEventType["Input"] = 3] = "Input"; /** * HTML CompositionEnd event */ CompatiblePluginEventType[CompatiblePluginEventType["CompositionEnd"] = 4] = "CompositionEnd"; /** * HTML MouseDown event */ CompatiblePluginEventType[CompatiblePluginEventType["MouseDown"] = 5] = "MouseDown"; /** * HTML MouseUp event */ CompatiblePluginEventType[CompatiblePluginEventType["MouseUp"] = 6] = "MouseUp"; /** * Content changed event */ CompatiblePluginEventType[CompatiblePluginEventType["ContentChanged"] = 7] = "ContentChanged"; /** * Extract Content with a DOM tree event * This event is triggered when getContent() is called with triggerExtractContentEvent = true * Plugin can handle this event to remove the UI only markups to return clean HTML * by operating on a cloned DOM tree */ CompatiblePluginEventType[CompatiblePluginEventType["ExtractContentWithDom"] = 8] = "ExtractContentWithDom"; /** * Before Paste event, provide a chance to change copied content */ CompatiblePluginEventType[CompatiblePluginEventType["BeforeCutCopy"] = 9] = "BeforeCutCopy"; /** * Before Paste event, provide a chance to change paste content */ CompatiblePluginEventType[CompatiblePluginEventType["BeforePaste"] = 10] = "BeforePaste"; /** * Let plugin know editor is ready now */ CompatiblePluginEventType[CompatiblePluginEventType["EditorReady"] = 11] = "EditorReady"; /** * Let plugin know editor is about to dispose */ CompatiblePluginEventType[CompatiblePluginEventType["BeforeDispose"] = 12] = "BeforeDispose"; /** * Pending format state (bold, italic, underline, ... with collapsed selection) is changed */ CompatiblePluginEventType[CompatiblePluginEventType["PendingFormatStateChanged"] = 13] = "PendingFormatStateChanged"; /** * Scroll event triggered by scroll container */ CompatiblePluginEventType[CompatiblePluginEventType["Scroll"] = 14] = "Scroll"; /** * Operating on an entity. See enum EntityOperation for more details about each operation */ CompatiblePluginEventType[CompatiblePluginEventType["EntityOperation"] = 15] = "EntityOperation"; /** * HTML ContextMenu event */ CompatiblePluginEventType[CompatiblePluginEventType["ContextMenu"] = 16] = "ContextMenu"; /** * Editor has entered shadow edit mode */ CompatiblePluginEventType[CompatiblePluginEventType["EnteredShadowEdit"] = 17] = "EnteredShadowEdit"; /** * Editor is about to leave shadow edit mode */ CompatiblePluginEventType[CompatiblePluginEventType["LeavingShadowEdit"] = 18] = "LeavingShadowEdit"; /** * Content of image is being changed from client side */ CompatiblePluginEventType[CompatiblePluginEventType["EditImage"] = 19] = "EditImage"; /** * Content of editor is about to be cleared by SetContent API, handle this event to cache anything you need * before it is gone */ CompatiblePluginEventType[CompatiblePluginEventType["BeforeSetContent"] = 20] = "BeforeSetContent"; /** * Zoom scale value is changed, triggered by Editor.setZoomScale() when set a different scale number */ CompatiblePluginEventType[CompatiblePluginEventType["ZoomChanged"] = 21] = "ZoomChanged"; /** * EXPERIMENTAL FEATURE * Editor changed the selection. */ CompatiblePluginEventType[CompatiblePluginEventType["SelectionChanged"] = 22] = "SelectionChanged"; })(CompatiblePluginEventType = exports.CompatiblePluginEventType || (exports.CompatiblePluginEventType = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/PositionType.ts": /*!****************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/PositionType.ts ***! \****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatiblePositionType = void 0; /** * Represent the type of a position */ var CompatiblePositionType; (function (CompatiblePositionType) { /** * At the beginning of a node */ CompatiblePositionType[CompatiblePositionType["Begin"] = 0] = "Begin"; /** * At the end of a node */ CompatiblePositionType[CompatiblePositionType["End"] = -1] = "End"; /** * Before a node */ CompatiblePositionType[CompatiblePositionType["Before"] = -2] = "Before"; /** * After a node */ CompatiblePositionType[CompatiblePositionType["After"] = -3] = "After"; })(CompatiblePositionType = exports.CompatiblePositionType || (exports.CompatiblePositionType = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/QueryScope.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/QueryScope.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleQueryScope = void 0; /** * Query scope for queryElements() API */ var CompatibleQueryScope; (function (CompatibleQueryScope) { /** * Query from the whole body of root node. This is default value. */ CompatibleQueryScope[CompatibleQueryScope["Body"] = 0] = "Body"; /** * Query elements on a given selection (intersect) * The result element can contain the selection, contain part of selection, or inside selection */ CompatibleQueryScope[CompatibleQueryScope["OnSelection"] = 1] = "OnSelection"; /** * Query elements inside a given selection only */ CompatibleQueryScope[CompatibleQueryScope["InSelection"] = 2] = "InSelection"; })(CompatibleQueryScope = exports.CompatibleQueryScope || (exports.CompatibleQueryScope = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/RegionType.ts": /*!**************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/RegionType.ts ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleRegionType = void 0; /** * Type of all possible regions. Currently we only support region of Table */ var CompatibleRegionType; (function (CompatibleRegionType) { /** * Region split by Table */ CompatibleRegionType[CompatibleRegionType["Table"] = 0] = "Table"; })(CompatibleRegionType = exports.CompatibleRegionType || (exports.CompatibleRegionType = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/SelectionRangeTypes.ts": /*!***********************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/SelectionRangeTypes.ts ***! \***********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleSelectionRangeTypes = void 0; /** * Types of Selection Ranges that the SelectionRangeEx can return */ var CompatibleSelectionRangeTypes; (function (CompatibleSelectionRangeTypes) { /** * Normal selection range provided by browser. */ CompatibleSelectionRangeTypes[CompatibleSelectionRangeTypes["Normal"] = 0] = "Normal"; /** * Selection made inside of a single table. */ CompatibleSelectionRangeTypes[CompatibleSelectionRangeTypes["TableSelection"] = 1] = "TableSelection"; /** * Selection made in a image. */ CompatibleSelectionRangeTypes[CompatibleSelectionRangeTypes["ImageSelection"] = 2] = "ImageSelection"; })(CompatibleSelectionRangeTypes = exports.CompatibleSelectionRangeTypes || (exports.CompatibleSelectionRangeTypes = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/TableBorderFormat.ts": /*!*********************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/TableBorderFormat.ts ***! \*********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleTableBorderFormat = void 0; /** * Table format border */ var CompatibleTableBorderFormat; (function (CompatibleTableBorderFormat) { /** * All border of the table are displayed * __ __ __ * |__|__|__| * |__|__|__| * |__|__|__| */ CompatibleTableBorderFormat[CompatibleTableBorderFormat["DEFAULT"] = 0] = "DEFAULT"; /** * Middle vertical border are not displayed * __ __ __ * |__ __ __| * |__ __ __| * |__ __ __| */ CompatibleTableBorderFormat[CompatibleTableBorderFormat["LIST_WITH_SIDE_BORDERS"] = 1] = "LIST_WITH_SIDE_BORDERS"; /** * All borders except header rows borders are displayed * __ __ __ * __|__|__ * __|__|__ */ CompatibleTableBorderFormat[CompatibleTableBorderFormat["NO_HEADER_BORDERS"] = 2] = "NO_HEADER_BORDERS"; /** * The left and right border of the table are not displayed * __ __ __ * __|__|__ * __|__|__ * __|__|__ */ CompatibleTableBorderFormat[CompatibleTableBorderFormat["NO_SIDE_BORDERS"] = 3] = "NO_SIDE_BORDERS"; /** * Only the borders that divides the header row, first column and externals are displayed * __ __ __ * |__ __ __| * | | | * |__|__ __| */ CompatibleTableBorderFormat[CompatibleTableBorderFormat["FIRST_COLUMN_HEADER_EXTERNAL"] = 4] = "FIRST_COLUMN_HEADER_EXTERNAL"; /** * The header row has no vertical border, except for the first one * The first column has no horizontal border, except for the first one * __ __ __ * |__ __ __ * | |__|__| * | |__|__| */ CompatibleTableBorderFormat[CompatibleTableBorderFormat["ESPECIAL_TYPE_1"] = 5] = "ESPECIAL_TYPE_1"; /** * The header row has no vertical border, except for the first one * The only horizontal border of the table is the top and bottom of header row * __ __ __ * |__ __ __ * | | | * | | | */ CompatibleTableBorderFormat[CompatibleTableBorderFormat["ESPECIAL_TYPE_2"] = 6] = "ESPECIAL_TYPE_2"; /** * The only borders are the bottom of header row and the right border of first column * __ __ __ * | * | */ CompatibleTableBorderFormat[CompatibleTableBorderFormat["ESPECIAL_TYPE_3"] = 7] = "ESPECIAL_TYPE_3"; /** * No border */ CompatibleTableBorderFormat[CompatibleTableBorderFormat["CLEAR"] = 8] = "CLEAR"; })(CompatibleTableBorderFormat = exports.CompatibleTableBorderFormat || (exports.CompatibleTableBorderFormat = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/TableOperation.ts": /*!******************************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/TableOperation.ts ***! \******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleTableOperation = void 0; /** * Operations used by editTable() API */ var CompatibleTableOperation; (function (CompatibleTableOperation) { /** * Insert a row above current row */ CompatibleTableOperation[CompatibleTableOperation["InsertAbove"] = 0] = "InsertAbove"; /** * Insert a row below current row */ CompatibleTableOperation[CompatibleTableOperation["InsertBelow"] = 1] = "InsertBelow"; /** * Insert a column on the left of current column */ CompatibleTableOperation[CompatibleTableOperation["InsertLeft"] = 2] = "InsertLeft"; /** * Insert a column on the right of current column */ CompatibleTableOperation[CompatibleTableOperation["InsertRight"] = 3] = "InsertRight"; /** * Delete the whole table */ CompatibleTableOperation[CompatibleTableOperation["DeleteTable"] = 4] = "DeleteTable"; /** * Delete current column */ CompatibleTableOperation[CompatibleTableOperation["DeleteColumn"] = 5] = "DeleteColumn"; /** * Delete current row */ CompatibleTableOperation[CompatibleTableOperation["DeleteRow"] = 6] = "DeleteRow"; /** * Merge current row with the row above */ CompatibleTableOperation[CompatibleTableOperation["MergeAbove"] = 7] = "MergeAbove"; /** * Merge current row with the row below */ CompatibleTableOperation[CompatibleTableOperation["MergeBelow"] = 8] = "MergeBelow"; /** * Merge current column with the column on the left */ CompatibleTableOperation[CompatibleTableOperation["MergeLeft"] = 9] = "MergeLeft"; /** * Merge current column with the column on the right */ CompatibleTableOperation[CompatibleTableOperation["MergeRight"] = 10] = "MergeRight"; /** * Merge all selected cells */ CompatibleTableOperation[CompatibleTableOperation["MergeCells"] = 11] = "MergeCells"; /** * Split current table cell horizontally */ CompatibleTableOperation[CompatibleTableOperation["SplitHorizontally"] = 12] = "SplitHorizontally"; /** * Split current table cell vertically */ CompatibleTableOperation[CompatibleTableOperation["SplitVertically"] = 13] = "SplitVertically"; /** * Align current table at the center */ CompatibleTableOperation[CompatibleTableOperation["AlignCenter"] = 14] = "AlignCenter"; /** * Align current table at the left */ CompatibleTableOperation[CompatibleTableOperation["AlignLeft"] = 15] = "AlignLeft"; /** * Align current table at the right */ CompatibleTableOperation[CompatibleTableOperation["AlignRight"] = 16] = "AlignRight"; /** * Align current content table cell at the left */ CompatibleTableOperation[CompatibleTableOperation["AlignCellLeft"] = 17] = "AlignCellLeft"; /** * Align current content table cell at the center */ CompatibleTableOperation[CompatibleTableOperation["AlignCellCenter"] = 18] = "AlignCellCenter"; /** * Align current content table cell at the right */ CompatibleTableOperation[CompatibleTableOperation["AlignCellRight"] = 19] = "AlignCellRight"; /** * Align current content table cell at the top */ CompatibleTableOperation[CompatibleTableOperation["AlignCellTop"] = 20] = "AlignCellTop"; /** * Align current table cell at the middle */ CompatibleTableOperation[CompatibleTableOperation["AlignCellMiddle"] = 21] = "AlignCellMiddle"; /** * Align current table cell at the bottom */ CompatibleTableOperation[CompatibleTableOperation["AlignCellBottom"] = 22] = "AlignCellBottom"; })(CompatibleTableOperation = exports.CompatibleTableOperation || (exports.CompatibleTableOperation = {})); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleEnum/index.ts": /*!*********************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleEnum/index.ts ***! \*********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CompatibleTableOperation = exports.CompatibleTableBorderFormat = exports.CompatibleSelectionRangeTypes = exports.CompatibleRegionType = exports.CompatibleQueryScope = exports.CompatiblePositionType = exports.CompatiblePluginEventType = exports.CompatibleNumberingListType = exports.CompatibleNodeType = exports.CompatibleListType = exports.CompatibleKnownCreateElementDataIndex = exports.CompatibleKeys = exports.CompatibleIndentation = exports.CompatibleImageEditOperation = exports.CompatibleGetContentMode = exports.CompatibleFontSizeChange = exports.CompatibleExperimentalFeatures = exports.CompatibleEntityOperation = exports.CompatibleEntityClasses = exports.CompatibleDocumentPosition = exports.CompatibleDocumentCommand = exports.CompatibleDirection = exports.CompatibleDefinitionType = exports.CompatibleDarkModeDatasetNames = exports.CompatibleContentType = exports.CompatibleContentTypePrefix = exports.CompatibleContentPosition = exports.CompatibleColorTransformDirection = exports.CompatibleClearFormatMode = exports.CompatibleChangeSource = exports.CompatibleCapitalization = exports.CompatibleBulletListType = exports.CompatibleAlignment = void 0; var Alignment_1 = __webpack_require__(/*! ./Alignment */ "./packages/roosterjs-editor-types/lib/compatibleEnum/Alignment.ts"); Object.defineProperty(exports, "CompatibleAlignment", { enumerable: true, get: function () { return Alignment_1.CompatibleAlignment; } }); var BulletListType_1 = __webpack_require__(/*! ./BulletListType */ "./packages/roosterjs-editor-types/lib/compatibleEnum/BulletListType.ts"); Object.defineProperty(exports, "CompatibleBulletListType", { enumerable: true, get: function () { return BulletListType_1.CompatibleBulletListType; } }); var Capitalization_1 = __webpack_require__(/*! ./Capitalization */ "./packages/roosterjs-editor-types/lib/compatibleEnum/Capitalization.ts"); Object.defineProperty(exports, "CompatibleCapitalization", { enumerable: true, get: function () { return Capitalization_1.CompatibleCapitalization; } }); var ChangeSource_1 = __webpack_require__(/*! ./ChangeSource */ "./packages/roosterjs-editor-types/lib/compatibleEnum/ChangeSource.ts"); Object.defineProperty(exports, "CompatibleChangeSource", { enumerable: true, get: function () { return ChangeSource_1.CompatibleChangeSource; } }); var ClearFormatMode_1 = __webpack_require__(/*! ./ClearFormatMode */ "./packages/roosterjs-editor-types/lib/compatibleEnum/ClearFormatMode.ts"); Object.defineProperty(exports, "CompatibleClearFormatMode", { enumerable: true, get: function () { return ClearFormatMode_1.CompatibleClearFormatMode; } }); var ColorTransformDirection_1 = __webpack_require__(/*! ./ColorTransformDirection */ "./packages/roosterjs-editor-types/lib/compatibleEnum/ColorTransformDirection.ts"); Object.defineProperty(exports, "CompatibleColorTransformDirection", { enumerable: true, get: function () { return ColorTransformDirection_1.CompatibleColorTransformDirection; } }); var ContentPosition_1 = __webpack_require__(/*! ./ContentPosition */ "./packages/roosterjs-editor-types/lib/compatibleEnum/ContentPosition.ts"); Object.defineProperty(exports, "CompatibleContentPosition", { enumerable: true, get: function () { return ContentPosition_1.CompatibleContentPosition; } }); var ContentType_1 = __webpack_require__(/*! ./ContentType */ "./packages/roosterjs-editor-types/lib/compatibleEnum/ContentType.ts"); Object.defineProperty(exports, "CompatibleContentTypePrefix", { enumerable: true, get: function () { return ContentType_1.CompatibleContentTypePrefix; } }); Object.defineProperty(exports, "CompatibleContentType", { enumerable: true, get: function () { return ContentType_1.CompatibleContentType; } }); var DarkModeDatasetNames_1 = __webpack_require__(/*! ./DarkModeDatasetNames */ "./packages/roosterjs-editor-types/lib/compatibleEnum/DarkModeDatasetNames.ts"); Object.defineProperty(exports, "CompatibleDarkModeDatasetNames", { enumerable: true, get: function () { return DarkModeDatasetNames_1.CompatibleDarkModeDatasetNames; } }); var DefinitionType_1 = __webpack_require__(/*! ./DefinitionType */ "./packages/roosterjs-editor-types/lib/compatibleEnum/DefinitionType.ts"); Object.defineProperty(exports, "CompatibleDefinitionType", { enumerable: true, get: function () { return DefinitionType_1.CompatibleDefinitionType; } }); var Direction_1 = __webpack_require__(/*! ./Direction */ "./packages/roosterjs-editor-types/lib/compatibleEnum/Direction.ts"); Object.defineProperty(exports, "CompatibleDirection", { enumerable: true, get: function () { return Direction_1.CompatibleDirection; } }); var DocumentCommand_1 = __webpack_require__(/*! ./DocumentCommand */ "./packages/roosterjs-editor-types/lib/compatibleEnum/DocumentCommand.ts"); Object.defineProperty(exports, "CompatibleDocumentCommand", { enumerable: true, get: function () { return DocumentCommand_1.CompatibleDocumentCommand; } }); var DocumentPosition_1 = __webpack_require__(/*! ./DocumentPosition */ "./packages/roosterjs-editor-types/lib/compatibleEnum/DocumentPosition.ts"); Object.defineProperty(exports, "CompatibleDocumentPosition", { enumerable: true, get: function () { return DocumentPosition_1.CompatibleDocumentPosition; } }); var EntityClasses_1 = __webpack_require__(/*! ./EntityClasses */ "./packages/roosterjs-editor-types/lib/compatibleEnum/EntityClasses.ts"); Object.defineProperty(exports, "CompatibleEntityClasses", { enumerable: true, get: function () { return EntityClasses_1.CompatibleEntityClasses; } }); var EntityOperation_1 = __webpack_require__(/*! ./EntityOperation */ "./packages/roosterjs-editor-types/lib/compatibleEnum/EntityOperation.ts"); Object.defineProperty(exports, "CompatibleEntityOperation", { enumerable: true, get: function () { return EntityOperation_1.CompatibleEntityOperation; } }); var ExperimentalFeatures_1 = __webpack_require__(/*! ./ExperimentalFeatures */ "./packages/roosterjs-editor-types/lib/compatibleEnum/ExperimentalFeatures.ts"); Object.defineProperty(exports, "CompatibleExperimentalFeatures", { enumerable: true, get: function () { return ExperimentalFeatures_1.CompatibleExperimentalFeatures; } }); var FontSizeChange_1 = __webpack_require__(/*! ./FontSizeChange */ "./packages/roosterjs-editor-types/lib/compatibleEnum/FontSizeChange.ts"); Object.defineProperty(exports, "CompatibleFontSizeChange", { enumerable: true, get: function () { return FontSizeChange_1.CompatibleFontSizeChange; } }); var GetContentMode_1 = __webpack_require__(/*! ./GetContentMode */ "./packages/roosterjs-editor-types/lib/compatibleEnum/GetContentMode.ts"); Object.defineProperty(exports, "CompatibleGetContentMode", { enumerable: true, get: function () { return GetContentMode_1.CompatibleGetContentMode; } }); var ImageEditOperation_1 = __webpack_require__(/*! ./ImageEditOperation */ "./packages/roosterjs-editor-types/lib/compatibleEnum/ImageEditOperation.ts"); Object.defineProperty(exports, "CompatibleImageEditOperation", { enumerable: true, get: function () { return ImageEditOperation_1.CompatibleImageEditOperation; } }); var Indentation_1 = __webpack_require__(/*! ./Indentation */ "./packages/roosterjs-editor-types/lib/compatibleEnum/Indentation.ts"); Object.defineProperty(exports, "CompatibleIndentation", { enumerable: true, get: function () { return Indentation_1.CompatibleIndentation; } }); var Keys_1 = __webpack_require__(/*! ./Keys */ "./packages/roosterjs-editor-types/lib/compatibleEnum/Keys.ts"); Object.defineProperty(exports, "CompatibleKeys", { enumerable: true, get: function () { return Keys_1.CompatibleKeys; } }); var KnownCreateElementDataIndex_1 = __webpack_require__(/*! ./KnownCreateElementDataIndex */ "./packages/roosterjs-editor-types/lib/compatibleEnum/KnownCreateElementDataIndex.ts"); Object.defineProperty(exports, "CompatibleKnownCreateElementDataIndex", { enumerable: true, get: function () { return KnownCreateElementDataIndex_1.CompatibleKnownCreateElementDataIndex; } }); var ListType_1 = __webpack_require__(/*! ./ListType */ "./packages/roosterjs-editor-types/lib/compatibleEnum/ListType.ts"); Object.defineProperty(exports, "CompatibleListType", { enumerable: true, get: function () { return ListType_1.CompatibleListType; } }); var NodeType_1 = __webpack_require__(/*! ./NodeType */ "./packages/roosterjs-editor-types/lib/compatibleEnum/NodeType.ts"); Object.defineProperty(exports, "CompatibleNodeType", { enumerable: true, get: function () { return NodeType_1.CompatibleNodeType; } }); var NumberingListType_1 = __webpack_require__(/*! ./NumberingListType */ "./packages/roosterjs-editor-types/lib/compatibleEnum/NumberingListType.ts"); Object.defineProperty(exports, "CompatibleNumberingListType", { enumerable: true, get: function () { return NumberingListType_1.CompatibleNumberingListType; } }); var PluginEventType_1 = __webpack_require__(/*! ./PluginEventType */ "./packages/roosterjs-editor-types/lib/compatibleEnum/PluginEventType.ts"); Object.defineProperty(exports, "CompatiblePluginEventType", { enumerable: true, get: function () { return PluginEventType_1.CompatiblePluginEventType; } }); var PositionType_1 = __webpack_require__(/*! ./PositionType */ "./packages/roosterjs-editor-types/lib/compatibleEnum/PositionType.ts"); Object.defineProperty(exports, "CompatiblePositionType", { enumerable: true, get: function () { return PositionType_1.CompatiblePositionType; } }); var QueryScope_1 = __webpack_require__(/*! ./QueryScope */ "./packages/roosterjs-editor-types/lib/compatibleEnum/QueryScope.ts"); Object.defineProperty(exports, "CompatibleQueryScope", { enumerable: true, get: function () { return QueryScope_1.CompatibleQueryScope; } }); var RegionType_1 = __webpack_require__(/*! ./RegionType */ "./packages/roosterjs-editor-types/lib/compatibleEnum/RegionType.ts"); Object.defineProperty(exports, "CompatibleRegionType", { enumerable: true, get: function () { return RegionType_1.CompatibleRegionType; } }); var SelectionRangeTypes_1 = __webpack_require__(/*! ./SelectionRangeTypes */ "./packages/roosterjs-editor-types/lib/compatibleEnum/SelectionRangeTypes.ts"); Object.defineProperty(exports, "CompatibleSelectionRangeTypes", { enumerable: true, get: function () { return SelectionRangeTypes_1.CompatibleSelectionRangeTypes; } }); var TableBorderFormat_1 = __webpack_require__(/*! ./TableBorderFormat */ "./packages/roosterjs-editor-types/lib/compatibleEnum/TableBorderFormat.ts"); Object.defineProperty(exports, "CompatibleTableBorderFormat", { enumerable: true, get: function () { return TableBorderFormat_1.CompatibleTableBorderFormat; } }); var TableOperation_1 = __webpack_require__(/*! ./TableOperation */ "./packages/roosterjs-editor-types/lib/compatibleEnum/TableOperation.ts"); Object.defineProperty(exports, "CompatibleTableOperation", { enumerable: true, get: function () { return TableOperation_1.CompatibleTableOperation; } }); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/compatibleTypes.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/compatibleTypes.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./browser/index */ "./packages/roosterjs-editor-types/lib/browser/index.ts"), exports); __exportStar(__webpack_require__(/*! ./corePluginState/index */ "./packages/roosterjs-editor-types/lib/corePluginState/index.ts"), exports); __exportStar(__webpack_require__(/*! ./compatibleEnum/index */ "./packages/roosterjs-editor-types/lib/compatibleEnum/index.ts"), exports); __exportStar(__webpack_require__(/*! ./event/index */ "./packages/roosterjs-editor-types/lib/event/index.ts"), exports); __exportStar(__webpack_require__(/*! ./interface/index */ "./packages/roosterjs-editor-types/lib/interface/index.ts"), exports); __exportStar(__webpack_require__(/*! ./type/index */ "./packages/roosterjs-editor-types/lib/type/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/corePluginState/index.ts": /*!**********************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/corePluginState/index.ts ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/enum/index.ts": /*!***********************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/enum/index.ts ***! \***********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/event/index.ts": /*!************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/event/index.ts ***! \************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/index.ts": /*!******************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/index.ts ***! \******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(__webpack_require__(/*! ./browser/index */ "./packages/roosterjs-editor-types/lib/browser/index.ts"), exports); __exportStar(__webpack_require__(/*! ./corePluginState/index */ "./packages/roosterjs-editor-types/lib/corePluginState/index.ts"), exports); __exportStar(__webpack_require__(/*! ./enum/index */ "./packages/roosterjs-editor-types/lib/enum/index.ts"), exports); __exportStar(__webpack_require__(/*! ./event/index */ "./packages/roosterjs-editor-types/lib/event/index.ts"), exports); __exportStar(__webpack_require__(/*! ./interface/index */ "./packages/roosterjs-editor-types/lib/interface/index.ts"), exports); __exportStar(__webpack_require__(/*! ./type/index */ "./packages/roosterjs-editor-types/lib/type/index.ts"), exports); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/interface/index.ts": /*!****************************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/interface/index.ts ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /***/ }), /***/ "./packages/roosterjs-editor-types/lib/type/index.ts": /*!***********************************************************!*\ !*** ./packages/roosterjs-editor-types/lib/type/index.ts ***! \***********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /***/ }), /***/ "./packages/roosterjs/lib/createEditor.ts": /*!************************************************!*\ !*** ./packages/roosterjs/lib/createEditor.ts ***! \************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var roosterjs_editor_core_1 = __webpack_require__(/*! roosterjs-editor-core */ "./packages/roosterjs-editor-core/lib/index.ts"); var roosterjs_color_utils_1 = __webpack_require__(/*! roosterjs-color-utils */ "./packages/roosterjs-color-utils/lib/index.ts"); var roosterjs_editor_plugins_1 = __webpack_require__(/*! roosterjs-editor-plugins */ "./packages/roosterjs-editor-plugins/lib/index.ts"); /** * Create an editor instance with most common options * @param contentDiv The html div element needed for creating the editor * @param additionalPlugins The additional user defined plugins. Currently the default plugins that are already included are * ContentEdit, HyperLink and Paste, user don't need to add those. * @param initialContent The initial content to show in editor. It can't be removed by undo, user need to manually remove it if needed. * @returns The editor instance */ function createEditor(contentDiv, additionalPlugins, initialContent) { var plugins = [new roosterjs_editor_plugins_1.HyperLink(), new roosterjs_editor_plugins_1.Paste(), new roosterjs_editor_plugins_1.ContentEdit()]; if (additionalPlugins) { plugins = plugins.concat(additionalPlugins); } var options = { plugins: plugins, initialContent: initialContent, getDarkColor: roosterjs_color_utils_1.getDarkColor, defaultFormat: { fontFamily: 'Calibri,Arial,Helvetica,sans-serif', fontSize: '11pt', textColor: '#000000', }, }; return new roosterjs_editor_core_1.Editor(contentDiv, options); } exports.default = createEditor; /***/ }), /***/ "./packages/roosterjs/lib/index.ts": /*!*****************************************!*\ !*** ./packages/roosterjs/lib/index.ts ***! \*****************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createEditor = void 0; var createEditor_1 = __webpack_require__(/*! ./createEditor */ "./packages/roosterjs/lib/createEditor.ts"); Object.defineProperty(exports, "createEditor", { enumerable: true, get: function () { return createEditor_1.default; } }); __exportStar(__webpack_require__(/*! roosterjs-editor-types */ "./packages/roosterjs-editor-types/lib/index.ts"), exports); __exportStar(__webpack_require__(/*! roosterjs-editor-types-compatible */ "./packages/roosterjs-editor-types-compatible/lib/index.ts"), exports); __exportStar(__webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts"), exports); __exportStar(__webpack_require__(/*! roosterjs-editor-core */ "./packages/roosterjs-editor-core/lib/index.ts"), exports); __exportStar(__webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts"), exports); __exportStar(__webpack_require__(/*! roosterjs-editor-plugins */ "./packages/roosterjs-editor-plugins/lib/index.ts"), exports); __exportStar(__webpack_require__(/*! roosterjs-color-utils */ "./packages/roosterjs-color-utils/lib/index.ts"), exports); /***/ }) /******/ }); //# sourceMappingURL=rooster.js.map