/**
* TinyMCE version 6.7.0 (2023-08-30)
*/
(function () {
"use strict";
var typeOf$1 = function (x) {
if (x === null) {
return "null";
}
if (x === undefined) {
return "undefined";
}
var t = typeof x;
if (
t === "object" &&
(Array.prototype.isPrototypeOf(x) ||
(x.constructor && x.constructor.name === "Array"))
) {
return "array";
}
if (
t === "object" &&
(String.prototype.isPrototypeOf(x) ||
(x.constructor && x.constructor.name === "String"))
) {
return "string";
}
return t;
};
var isEquatableType = function (x) {
return (
[
"undefined",
"boolean",
"number",
"string",
"function",
"xml",
"null",
].indexOf(x) !== -1
);
};
var sort$1 = function (xs, compareFn) {
var clone = Array.prototype.slice.call(xs);
return clone.sort(compareFn);
};
var contramap = function (eqa, f) {
return eq$2(function (x, y) {
return eqa.eq(f(x), f(y));
});
};
var eq$2 = function (f) {
return { eq: f };
};
var tripleEq = eq$2(function (x, y) {
return x === y;
});
var eqString = tripleEq;
var eqArray = function (eqa) {
return eq$2(function (x, y) {
if (x.length !== y.length) {
return false;
}
var len = x.length;
for (var i = 0; i < len; i++) {
if (!eqa.eq(x[i], y[i])) {
return false;
}
}
return true;
});
};
var eqSortedArray = function (eqa, compareFn) {
return contramap(eqArray(eqa), function (xs) {
return sort$1(xs, compareFn);
});
};
var eqRecord = function (eqa) {
return eq$2(function (x, y) {
var kx = Object.keys(x);
var ky = Object.keys(y);
if (!eqSortedArray(eqString).eq(kx, ky)) {
return false;
}
var len = kx.length;
for (var i = 0; i < len; i++) {
var q = kx[i];
if (!eqa.eq(x[q], y[q])) {
return false;
}
}
return true;
});
};
var eqAny = eq$2(function (x, y) {
if (x === y) {
return true;
}
var tx = typeOf$1(x);
var ty = typeOf$1(y);
if (tx !== ty) {
return false;
}
if (isEquatableType(tx)) {
return x === y;
} else if (tx === "array") {
return eqArray(eqAny).eq(x, y);
} else if (tx === "object") {
return eqRecord(eqAny).eq(x, y);
}
return false;
});
const getPrototypeOf$2 = Object.getPrototypeOf;
const hasProto = (v, constructor, predicate) => {
var _a;
if (predicate(v, constructor.prototype)) {
return true;
} else {
return (
((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) ===
constructor.name
);
}
};
const typeOf = (x) => {
const t = typeof x;
if (x === null) {
return "null";
} else if (t === "object" && Array.isArray(x)) {
return "array";
} else if (
t === "object" &&
hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))
) {
return "string";
} else {
return t;
}
};
const isType$1 = (type) => (value) => typeOf(value) === type;
const isSimpleType = (type) => (value) => typeof value === type;
const eq$1 = (t) => (a) => t === a;
const is$4 = (value, constructor) =>
isObject(value) &&
hasProto(value, constructor, (o, proto) => getPrototypeOf$2(o) === proto);
const isString = isType$1("string");
const isObject = isType$1("object");
const isPlainObject = (value) => is$4(value, Object);
const isArray$1 = isType$1("array");
const isNull = eq$1(null);
const isBoolean = isSimpleType("boolean");
const isUndefined = eq$1(undefined);
const isNullable = (a) => a === null || a === undefined;
const isNonNullable = (a) => !isNullable(a);
const isFunction = isSimpleType("function");
const isNumber = isSimpleType("number");
const isArrayOf = (value, pred) => {
if (isArray$1(value)) {
for (let i = 0, len = value.length; i < len; ++i) {
if (!pred(value[i])) {
return false;
}
}
return true;
}
return false;
};
const noop = () => {};
const compose = (fa, fb) => {
return (...args) => {
return fa(fb.apply(null, args));
};
};
const compose1 = (fbc, fab) => (a) => fbc(fab(a));
const constant = (value) => {
return () => {
return value;
};
};
const identity = (x) => {
return x;
};
const tripleEquals = (a, b) => {
return a === b;
};
function curry(fn, ...initialArgs) {
return (...restArgs) => {
const all = initialArgs.concat(restArgs);
return fn.apply(null, all);
};
}
const not = (f) => (t) => !f(t);
const die = (msg) => {
return () => {
throw new Error(msg);
};
};
const apply$1 = (f) => {
return f();
};
const call = (f) => {
f();
};
const never = constant(false);
const always = constant(true);
class Optional {
constructor(tag, value) {
this.tag = tag;
this.value = value;
}
static some(value) {
return new Optional(true, value);
}
static none() {
return Optional.singletonNone;
}
fold(onNone, onSome) {
if (this.tag) {
return onSome(this.value);
} else {
return onNone();
}
}
isSome() {
return this.tag;
}
isNone() {
return !this.tag;
}
map(mapper) {
if (this.tag) {
return Optional.some(mapper(this.value));
} else {
return Optional.none();
}
}
bind(binder) {
if (this.tag) {
return binder(this.value);
} else {
return Optional.none();
}
}
exists(predicate) {
return this.tag && predicate(this.value);
}
forall(predicate) {
return !this.tag || predicate(this.value);
}
filter(predicate) {
if (!this.tag || predicate(this.value)) {
return this;
} else {
return Optional.none();
}
}
getOr(replacement) {
return this.tag ? this.value : replacement;
}
or(replacement) {
return this.tag ? this : replacement;
}
getOrThunk(thunk) {
return this.tag ? this.value : thunk();
}
orThunk(thunk) {
return this.tag ? this : thunk();
}
getOrDie(message) {
if (!this.tag) {
throw new Error(
message !== null && message !== void 0
? message
: "Called getOrDie on None"
);
} else {
return this.value;
}
}
static from(value) {
return isNonNullable(value) ? Optional.some(value) : Optional.none();
}
getOrNull() {
return this.tag ? this.value : null;
}
getOrUndefined() {
return this.value;
}
each(worker) {
if (this.tag) {
worker(this.value);
}
}
toArray() {
return this.tag ? [this.value] : [];
}
toString() {
return this.tag ? `some(${this.value})` : "none()";
}
}
Optional.singletonNone = new Optional(false);
const nativeSlice = Array.prototype.slice;
const nativeIndexOf = Array.prototype.indexOf;
const nativePush = Array.prototype.push;
const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
const indexOf$1 = (xs, x) => {
const r = rawIndexOf(xs, x);
return r === -1 ? Optional.none() : Optional.some(r);
};
const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
const exists = (xs, pred) => {
for (let i = 0, len = xs.length; i < len; i++) {
const x = xs[i];
if (pred(x, i)) {
return true;
}
}
return false;
};
const map$3 = (xs, f) => {
const len = xs.length;
const r = new Array(len);
for (let i = 0; i < len; i++) {
const x = xs[i];
r[i] = f(x, i);
}
return r;
};
const each$e = (xs, f) => {
for (let i = 0, len = xs.length; i < len; i++) {
const x = xs[i];
f(x, i);
}
};
const eachr = (xs, f) => {
for (let i = xs.length - 1; i >= 0; i--) {
const x = xs[i];
f(x, i);
}
};
const partition$2 = (xs, pred) => {
const pass = [];
const fail = [];
for (let i = 0, len = xs.length; i < len; i++) {
const x = xs[i];
const arr = pred(x, i) ? pass : fail;
arr.push(x);
}
return {
pass,
fail,
};
};
const filter$5 = (xs, pred) => {
const r = [];
for (let i = 0, len = xs.length; i < len; i++) {
const x = xs[i];
if (pred(x, i)) {
r.push(x);
}
}
return r;
};
const foldr = (xs, f, acc) => {
eachr(xs, (x, i) => {
acc = f(acc, x, i);
});
return acc;
};
const foldl = (xs, f, acc) => {
each$e(xs, (x, i) => {
acc = f(acc, x, i);
});
return acc;
};
const findUntil$1 = (xs, pred, until) => {
for (let i = 0, len = xs.length; i < len; i++) {
const x = xs[i];
if (pred(x, i)) {
return Optional.some(x);
} else if (until(x, i)) {
break;
}
}
return Optional.none();
};
const find$2 = (xs, pred) => {
return findUntil$1(xs, pred, never);
};
const findIndex$2 = (xs, pred) => {
for (let i = 0, len = xs.length; i < len; i++) {
const x = xs[i];
if (pred(x, i)) {
return Optional.some(i);
}
}
return Optional.none();
};
const flatten = (xs) => {
const r = [];
for (let i = 0, len = xs.length; i < len; ++i) {
if (!isArray$1(xs[i])) {
throw new Error(
"Arr.flatten item " + i + " was not an array, input: " + xs
);
}
nativePush.apply(r, xs[i]);
}
return r;
};
const bind$3 = (xs, f) => flatten(map$3(xs, f));
const forall = (xs, pred) => {
for (let i = 0, len = xs.length; i < len; ++i) {
const x = xs[i];
if (pred(x, i) !== true) {
return false;
}
}
return true;
};
const reverse = (xs) => {
const r = nativeSlice.call(xs, 0);
r.reverse();
return r;
};
const difference = (a1, a2) => filter$5(a1, (x) => !contains$2(a2, x));
const mapToObject = (xs, f) => {
const r = {};
for (let i = 0, len = xs.length; i < len; i++) {
const x = xs[i];
r[String(x)] = f(x, i);
}
return r;
};
const sort = (xs, comparator) => {
const copy = nativeSlice.call(xs, 0);
copy.sort(comparator);
return copy;
};
const get$b = (xs, i) =>
i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
const head = (xs) => get$b(xs, 0);
const last$3 = (xs) => get$b(xs, xs.length - 1);
const from = isFunction(Array.from) ? Array.from : (x) => nativeSlice.call(x);
const findMap = (arr, f) => {
for (let i = 0; i < arr.length; i++) {
const r = f(arr[i], i);
if (r.isSome()) {
return r;
}
}
return Optional.none();
};
const unique$1 = (xs, comparator) => {
const r = [];
const isDuplicated = isFunction(comparator)
? (x) => exists(r, (i) => comparator(i, x))
: (x) => contains$2(r, x);
for (let i = 0, len = xs.length; i < len; i++) {
const x = xs[i];
if (!isDuplicated(x)) {
r.push(x);
}
}
return r;
};
const keys = Object.keys;
const hasOwnProperty$2 = Object.hasOwnProperty;
const each$d = (obj, f) => {
const props = keys(obj);
for (let k = 0, len = props.length; k < len; k++) {
const i = props[k];
const x = obj[i];
f(x, i);
}
};
const map$2 = (obj, f) => {
return tupleMap(obj, (x, i) => ({
k: i,
v: f(x, i),
}));
};
const tupleMap = (obj, f) => {
const r = {};
each$d(obj, (x, i) => {
const tuple = f(x, i);
r[tuple.k] = tuple.v;
});
return r;
};
const objAcc = (r) => (x, i) => {
r[i] = x;
};
const internalFilter = (obj, pred, onTrue, onFalse) => {
each$d(obj, (x, i) => {
(pred(x, i) ? onTrue : onFalse)(x, i);
});
};
const bifilter = (obj, pred) => {
const t = {};
const f = {};
internalFilter(obj, pred, objAcc(t), objAcc(f));
return {
t,
f,
};
};
const filter$4 = (obj, pred) => {
const t = {};
internalFilter(obj, pred, objAcc(t), noop);
return t;
};
const mapToArray = (obj, f) => {
const r = [];
each$d(obj, (value, name) => {
r.push(f(value, name));
});
return r;
};
const values = (obj) => {
return mapToArray(obj, identity);
};
const get$a = (obj, key) => {
return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
};
const has$2 = (obj, key) => hasOwnProperty$2.call(obj, key);
const hasNonNullableKey = (obj, key) =>
has$2(obj, key) && obj[key] !== undefined && obj[key] !== null;
const equal$1 = (a1, a2, eq = eqAny) => eqRecord(eq).eq(a1, a2);
const stringArray = (a) => {
const all = {};
each$e(a, (key) => {
all[key] = {};
});
return keys(all);
};
const isArrayLike = (o) => o.length !== undefined;
const isArray = Array.isArray;
const toArray$1 = (obj) => {
if (!isArray(obj)) {
const array = [];
for (let i = 0, l = obj.length; i < l; i++) {
array[i] = obj[i];
}
return array;
} else {
return obj;
}
};
const each$c = (o, cb, s) => {
if (!o) {
return false;
}
s = s || o;
if (isArrayLike(o)) {
for (let n = 0, l = o.length; n < l; n++) {
if (cb.call(s, o[n], n, o) === false) {
return false;
}
}
} else {
for (const n in o) {
if (has$2(o, n)) {
if (cb.call(s, o[n], n, o) === false) {
return false;
}
}
}
}
return true;
};
const map$1 = (array, callback) => {
const out = [];
each$c(array, (item, index) => {
out.push(callback(item, index, array));
});
return out;
};
const filter$3 = (a, f) => {
const o = [];
each$c(a, (v, index) => {
if (!f || f(v, index, a)) {
o.push(v);
}
});
return o;
};
const indexOf = (a, v) => {
if (a) {
for (let i = 0, l = a.length; i < l; i++) {
if (a[i] === v) {
return i;
}
}
}
return -1;
};
const reduce = (collection, iteratee, accumulator, thisArg) => {
let acc = isUndefined(accumulator) ? collection[0] : accumulator;
for (let i = 0; i < collection.length; i++) {
acc = iteratee.call(thisArg, acc, collection[i], i);
}
return acc;
};
const findIndex$1 = (array, predicate, thisArg) => {
for (let i = 0, l = array.length; i < l; i++) {
if (predicate.call(thisArg, array[i], i, array)) {
return i;
}
}
return -1;
};
const last$2 = (collection) => collection[collection.length - 1];
const cached = (f) => {
let called = false;
let r;
return (...args) => {
if (!called) {
called = true;
r = f.apply(null, args);
}
return r;
};
};
const DeviceType = (os, browser, userAgent, mediaMatch) => {
const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
const isiPhone = os.isiOS() && !isiPad;
const isMobile = os.isiOS() || os.isAndroid();
const isTouch = isMobile || mediaMatch("(pointer:coarse)");
const isTablet =
isiPad ||
(!isiPhone && isMobile && mediaMatch("(min-device-width:768px)"));
const isPhone = isiPhone || (isMobile && !isTablet);
const iOSwebview =
browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
const isDesktop = !isPhone && !isTablet && !iOSwebview;
return {
isiPad: constant(isiPad),
isiPhone: constant(isiPhone),
isTablet: constant(isTablet),
isPhone: constant(isPhone),
isTouch: constant(isTouch),
isAndroid: os.isAndroid,
isiOS: os.isiOS,
isWebView: constant(iOSwebview),
isDesktop: constant(isDesktop),
};
};
const firstMatch = (regexes, s) => {
for (let i = 0; i < regexes.length; i++) {
const x = regexes[i];
if (x.test(s)) {
return x;
}
}
return undefined;
};
const find$1 = (regexes, agent) => {
const r = firstMatch(regexes, agent);
if (!r) {
return {
major: 0,
minor: 0,
};
}
const group = (i) => {
return Number(agent.replace(r, "$" + i));
};
return nu$3(group(1), group(2));
};
const detect$5 = (versionRegexes, agent) => {
const cleanedAgent = String(agent).toLowerCase();
if (versionRegexes.length === 0) {
return unknown$2();
}
return find$1(versionRegexes, cleanedAgent);
};
const unknown$2 = () => {
return nu$3(0, 0);
};
const nu$3 = (major, minor) => {
return {
major,
minor,
};
};
const Version = {
nu: nu$3,
detect: detect$5,
unknown: unknown$2,
};
const detectBrowser$1 = (browsers, userAgentData) => {
return findMap(userAgentData.brands, (uaBrand) => {
const lcBrand = uaBrand.brand.toLowerCase();
return find$2(browsers, (browser) => {
var _a;
return (
lcBrand ===
((_a = browser.brand) === null || _a === void 0
? void 0
: _a.toLowerCase())
);
}).map((info) => ({
current: info.name,
version: Version.nu(parseInt(uaBrand.version, 10), 0),
}));
});
};
const detect$4 = (candidates, userAgent) => {
const agent = String(userAgent).toLowerCase();
return find$2(candidates, (candidate) => {
return candidate.search(agent);
});
};
const detectBrowser = (browsers, userAgent) => {
return detect$4(browsers, userAgent).map((browser) => {
const version = Version.detect(browser.versionRegexes, userAgent);
return {
current: browser.name,
version,
};
});
};
const detectOs = (oses, userAgent) => {
return detect$4(oses, userAgent).map((os) => {
const version = Version.detect(os.versionRegexes, userAgent);
return {
current: os.name,
version,
};
});
};
const removeFromStart = (str, numChars) => {
return str.substring(numChars);
};
const checkRange = (str, substr, start) =>
substr === "" ||
(str.length >= substr.length &&
str.substr(start, start + substr.length) === substr);
const removeLeading = (str, prefix) => {
return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str;
};
const contains$1 = (str, substr, start = 0, end) => {
const idx = str.indexOf(substr, start);
if (idx !== -1) {
return isUndefined(end) ? true : idx + substr.length <= end;
} else {
return false;
}
};
const startsWith = (str, prefix) => {
return checkRange(str, prefix, 0);
};
const endsWith = (str, suffix) => {
return checkRange(str, suffix, str.length - suffix.length);
};
const blank = (r) => (s) => s.replace(r, "");
const trim$3 = blank(/^\s+|\s+$/g);
const lTrim = blank(/^\s+/g);
const rTrim = blank(/\s+$/g);
const isNotEmpty = (s) => s.length > 0;
const isEmpty$3 = (s) => !isNotEmpty(s);
const repeat = (s, count) => (count <= 0 ? "" : new Array(count + 1).join(s));
const toInt = (value, radix = 10) => {
const num = parseInt(value, radix);
return isNaN(num) ? Optional.none() : Optional.some(num);
};
const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
const checkContains = (target) => {
return (uastring) => {
return contains$1(uastring, target);
};
};
const browsers = [
{
name: "Edge",
versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
search: (uastring) => {
return (
contains$1(uastring, "edge/") &&
contains$1(uastring, "chrome") &&
contains$1(uastring, "safari") &&
contains$1(uastring, "applewebkit")
);
},
},
{
name: "Chromium",
brand: "Chromium",
versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/, normalVersionRegex],
search: (uastring) => {
return (
contains$1(uastring, "chrome") && !contains$1(uastring, "chromeframe")
);
},
},
{
name: "IE",
versionRegexes: [
/.*?msie\ ?([0-9]+)\.([0-9]+).*/,
/.*?rv:([0-9]+)\.([0-9]+).*/,
],
search: (uastring) => {
return contains$1(uastring, "msie") || contains$1(uastring, "trident");
},
},
{
name: "Opera",
versionRegexes: [normalVersionRegex, /.*?opera\/([0-9]+)\.([0-9]+).*/],
search: checkContains("opera"),
},
{
name: "Firefox",
versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
search: checkContains("firefox"),
},
{
name: "Safari",
versionRegexes: [normalVersionRegex, /.*?cpu os ([0-9]+)_([0-9]+).*/],
search: (uastring) => {
return (
(contains$1(uastring, "safari") || contains$1(uastring, "mobile/")) &&
contains$1(uastring, "applewebkit")
);
},
},
];
const oses = [
{
name: "Windows",
search: checkContains("win"),
versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/],
},
{
name: "iOS",
search: (uastring) => {
return contains$1(uastring, "iphone") || contains$1(uastring, "ipad");
},
versionRegexes: [
/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
/.*cpu os ([0-9]+)_([0-9]+).*/,
/.*cpu iphone os ([0-9]+)_([0-9]+).*/,
],
},
{
name: "Android",
search: checkContains("android"),
versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/],
},
{
name: "macOS",
search: checkContains("mac os x"),
versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/],
},
{
name: "Linux",
search: checkContains("linux"),
versionRegexes: [],
},
{
name: "Solaris",
search: checkContains("sunos"),
versionRegexes: [],
},
{
name: "FreeBSD",
search: checkContains("freebsd"),
versionRegexes: [],
},
{
name: "ChromeOS",
search: checkContains("cros"),
versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/],
},
];
const PlatformInfo = {
browsers: constant(browsers),
oses: constant(oses),
};
const edge = "Edge";
const chromium = "Chromium";
const ie = "IE";
const opera = "Opera";
const firefox = "Firefox";
const safari = "Safari";
const unknown$1 = () => {
return nu$2({
current: undefined,
version: Version.unknown(),
});
};
const nu$2 = (info) => {
const current = info.current;
const version = info.version;
const isBrowser = (name) => () => current === name;
return {
current,
version,
isEdge: isBrowser(edge),
isChromium: isBrowser(chromium),
isIE: isBrowser(ie),
isOpera: isBrowser(opera),
isFirefox: isBrowser(firefox),
isSafari: isBrowser(safari),
};
};
const Browser = {
unknown: unknown$1,
nu: nu$2,
edge: constant(edge),
chromium: constant(chromium),
ie: constant(ie),
opera: constant(opera),
firefox: constant(firefox),
safari: constant(safari),
};
const windows = "Windows";
const ios = "iOS";
const android = "Android";
const linux = "Linux";
const macos = "macOS";
const solaris = "Solaris";
const freebsd = "FreeBSD";
const chromeos = "ChromeOS";
const unknown = () => {
return nu$1({
current: undefined,
version: Version.unknown(),
});
};
const nu$1 = (info) => {
const current = info.current;
const version = info.version;
const isOS = (name) => () => current === name;
return {
current,
version,
isWindows: isOS(windows),
isiOS: isOS(ios),
isAndroid: isOS(android),
isMacOS: isOS(macos),
isLinux: isOS(linux),
isSolaris: isOS(solaris),
isFreeBSD: isOS(freebsd),
isChromeOS: isOS(chromeos),
};
};
const OperatingSystem = {
unknown,
nu: nu$1,
windows: constant(windows),
ios: constant(ios),
android: constant(android),
linux: constant(linux),
macos: constant(macos),
solaris: constant(solaris),
freebsd: constant(freebsd),
chromeos: constant(chromeos),
};
const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => {
const browsers = PlatformInfo.browsers();
const oses = PlatformInfo.oses();
const browser = userAgentDataOpt
.bind((userAgentData) => detectBrowser$1(browsers, userAgentData))
.orThunk(() => detectBrowser(browsers, userAgent))
.fold(Browser.unknown, Browser.nu);
const os = detectOs(oses, userAgent).fold(
OperatingSystem.unknown,
OperatingSystem.nu
);
const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
return {
browser,
os,
deviceType,
};
};
const PlatformDetection = { detect: detect$3 };
const mediaMatch = (query) => window.matchMedia(query).matches;
let platform$4 = cached(() =>
PlatformDetection.detect(
navigator.userAgent,
Optional.from(navigator.userAgentData),
mediaMatch
)
);
const detect$2 = () => platform$4();
const userAgent = navigator.userAgent;
const platform$3 = detect$2();
const browser$3 = platform$3.browser;
const os$1 = platform$3.os;
const deviceType = platform$3.deviceType;
const windowsPhone = userAgent.indexOf("Windows Phone") !== -1;
const Env = {
transparentSrc:
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
documentMode: browser$3.isIE() ? document.documentMode || 7 : 10,
cacheSuffix: null,
container: null,
canHaveCSP: !browser$3.isIE(),
windowsPhone,
browser: {
current: browser$3.current,
version: browser$3.version,
isChromium: browser$3.isChromium,
isEdge: browser$3.isEdge,
isFirefox: browser$3.isFirefox,
isIE: browser$3.isIE,
isOpera: browser$3.isOpera,
isSafari: browser$3.isSafari,
},
os: {
current: os$1.current,
version: os$1.version,
isAndroid: os$1.isAndroid,
isChromeOS: os$1.isChromeOS,
isFreeBSD: os$1.isFreeBSD,
isiOS: os$1.isiOS,
isLinux: os$1.isLinux,
isMacOS: os$1.isMacOS,
isSolaris: os$1.isSolaris,
isWindows: os$1.isWindows,
},
deviceType: {
isDesktop: deviceType.isDesktop,
isiPad: deviceType.isiPad,
isiPhone: deviceType.isiPhone,
isPhone: deviceType.isPhone,
isTablet: deviceType.isTablet,
isTouch: deviceType.isTouch,
isWebView: deviceType.isWebView,
},
};
const whiteSpaceRegExp$1 = /^\s*|\s*$/g;
const trim$2 = (str) => {
return isNullable(str) ? "" : ("" + str).replace(whiteSpaceRegExp$1, "");
};
const is$3 = (obj, type) => {
if (!type) {
return obj !== undefined;
}
if (type === "array" && isArray(obj)) {
return true;
}
return typeof obj === type;
};
const makeMap$4 = (items, delim, map = {}) => {
const resolvedItems = isString(items)
? items.split(delim || ",")
: items || [];
let i = resolvedItems.length;
while (i--) {
map[resolvedItems[i]] = {};
}
return map;
};
const hasOwnProperty$1 = has$2;
const extend$3 = (obj, ...exts) => {
for (let i = 0; i < exts.length; i++) {
const ext = exts[i];
for (const name in ext) {
if (has$2(ext, name)) {
const value = ext[name];
if (value !== undefined) {
obj[name] = value;
}
}
}
}
return obj;
};
const walk$4 = function (o, f, n, s) {
s = s || this;
if (o) {
if (n) {
o = o[n];
}
each$c(o, (o, i) => {
if (f.call(s, o, i, n) === false) {
return false;
} else {
walk$4(o, f, n, s);
return true;
}
});
}
};
const resolve$3 = (n, o = window) => {
const path = n.split(".");
for (let i = 0, l = path.length; i < l; i++) {
o = o[path[i]];
if (!o) {
break;
}
}
return o;
};
const explode$3 = (s, d) => {
if (isArray$1(s)) {
return s;
} else if (s === "") {
return [];
} else {
return map$1(s.split(d || ","), trim$2);
}
};
const _addCacheSuffix = (url) => {
const cacheSuffix = Env.cacheSuffix;
if (cacheSuffix) {
url += (url.indexOf("?") === -1 ? "?" : "&") + cacheSuffix;
}
return url;
};
const Tools = {
trim: trim$2,
isArray: isArray,
is: is$3,
toArray: toArray$1,
makeMap: makeMap$4,
each: each$c,
map: map$1,
grep: filter$3,
inArray: indexOf,
hasOwn: hasOwnProperty$1,
extend: extend$3,
walk: walk$4,
resolve: resolve$3,
explode: explode$3,
_addCacheSuffix,
};
const is$2 = (lhs, rhs, comparator = tripleEquals) =>
lhs.exists((left) => comparator(left, rhs));
const equals = (lhs, rhs, comparator = tripleEquals) =>
lift2(lhs, rhs, comparator).getOr(lhs.isNone() && rhs.isNone());
const cat = (arr) => {
const r = [];
const push = (x) => {
r.push(x);
};
for (let i = 0; i < arr.length; i++) {
arr[i].each(push);
}
return r;
};
const lift2 = (oa, ob, f) =>
oa.isSome() && ob.isSome()
? Optional.some(f(oa.getOrDie(), ob.getOrDie()))
: Optional.none();
const lift3 = (oa, ob, oc, f) =>
oa.isSome() && ob.isSome() && oc.isSome()
? Optional.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie()))
: Optional.none();
const someIf = (b, a) => (b ? Optional.some(a) : Optional.none());
const Global =
typeof window !== "undefined" ? window : Function("return this;")();
const path = (parts, scope) => {
let o = scope !== undefined && scope !== null ? scope : Global;
for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
o = o[parts[i]];
}
return o;
};
const resolve$2 = (p, scope) => {
const parts = p.split(".");
return path(parts, scope);
};
const unsafe = (name, scope) => {
return resolve$2(name, scope);
};
const getOrDie = (name, scope) => {
const actual = unsafe(name, scope);
if (actual === undefined || actual === null) {
throw new Error(name + " not available on this browser");
}
return actual;
};
const getPrototypeOf$1 = Object.getPrototypeOf;
const sandHTMLElement = (scope) => {
return getOrDie("HTMLElement", scope);
};
const isPrototypeOf = (x) => {
const scope = resolve$2("ownerDocument.defaultView", x);
return (
isObject(x) &&
(sandHTMLElement(scope).prototype.isPrototypeOf(x) ||
/^HTML\w*Element$/.test(getPrototypeOf$1(x).constructor.name))
);
};
const COMMENT = 8;
const DOCUMENT = 9;
const DOCUMENT_FRAGMENT = 11;
const ELEMENT = 1;
const TEXT = 3;
const name = (element) => {
const r = element.dom.nodeName;
return r.toLowerCase();
};
const type$1 = (element) => element.dom.nodeType;
const isType = (t) => (element) => type$1(element) === t;
const isComment$1 = (element) =>
type$1(element) === COMMENT || name(element) === "#comment";
const isHTMLElement = (element) =>
isElement$7(element) && isPrototypeOf(element.dom);
const isElement$7 = isType(ELEMENT);
const isText$b = isType(TEXT);
const isDocument$2 = isType(DOCUMENT);
const isDocumentFragment$1 = isType(DOCUMENT_FRAGMENT);
const isTag = (tag) => (e) => isElement$7(e) && name(e) === tag;
const rawSet = (dom, key, value) => {
if (isString(value) || isBoolean(value) || isNumber(value)) {
dom.setAttribute(key, value + "");
} else {
console.error(
"Invalid call to Attribute.set. Key ",
key,
":: Value ",
value,
":: Element ",
dom
);
throw new Error("Attribute value was not simple");
}
};
const set$3 = (element, key, value) => {
rawSet(element.dom, key, value);
};
const setAll$1 = (element, attrs) => {
const dom = element.dom;
each$d(attrs, (v, k) => {
rawSet(dom, k, v);
});
};
const get$9 = (element, key) => {
const v = element.dom.getAttribute(key);
return v === null ? undefined : v;
};
const getOpt = (element, key) => Optional.from(get$9(element, key));
const has$1 = (element, key) => {
const dom = element.dom;
return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
};
const remove$a = (element, key) => {
element.dom.removeAttribute(key);
};
const hasNone = (element) => {
const attrs = element.dom.attributes;
return attrs === undefined || attrs === null || attrs.length === 0;
};
const clone$4 = (element) =>
foldl(
element.dom.attributes,
(acc, attr) => {
acc[attr.name] = attr.value;
return acc;
},
{}
);
const read$4 = (element, attr) => {
const value = get$9(element, attr);
return value === undefined || value === "" ? [] : value.split(" ");
};
const add$4 = (element, attr, id) => {
const old = read$4(element, attr);
const nu = old.concat([id]);
set$3(element, attr, nu.join(" "));
return true;
};
const remove$9 = (element, attr, id) => {
const nu = filter$5(read$4(element, attr), (v) => v !== id);
if (nu.length > 0) {
set$3(element, attr, nu.join(" "));
} else {
remove$a(element, attr);
}
return false;
};
const supports = (element) => element.dom.classList !== undefined;
const get$8 = (element) => read$4(element, "class");
const add$3 = (element, clazz) => add$4(element, "class", clazz);
const remove$8 = (element, clazz) => remove$9(element, "class", clazz);
const toggle$2 = (element, clazz) => {
if (contains$2(get$8(element), clazz)) {
return remove$8(element, clazz);
} else {
return add$3(element, clazz);
}
};
const add$2 = (element, clazz) => {
if (supports(element)) {
element.dom.classList.add(clazz);
} else {
add$3(element, clazz);
}
};
const cleanClass = (element) => {
const classList = supports(element)
? element.dom.classList
: get$8(element);
if (classList.length === 0) {
remove$a(element, "class");
}
};
const remove$7 = (element, clazz) => {
if (supports(element)) {
const classList = element.dom.classList;
classList.remove(clazz);
} else {
remove$8(element, clazz);
}
cleanClass(element);
};
const toggle$1 = (element, clazz) => {
const result = supports(element)
? element.dom.classList.toggle(clazz)
: toggle$2(element, clazz);
cleanClass(element);
return result;
};
const has = (element, clazz) =>
supports(element) && element.dom.classList.contains(clazz);
const fromHtml$1 = (html, scope) => {
const doc = scope || document;
const div = doc.createElement("div");
div.innerHTML = html;
if (!div.hasChildNodes() || div.childNodes.length > 1) {
const message = "HTML does not have a single root node";
console.error(message, html);
throw new Error(message);
}
return fromDom$2(div.childNodes[0]);
};
const fromTag = (tag, scope) => {
const doc = scope || document;
const node = doc.createElement(tag);
return fromDom$2(node);
};
const fromText = (text, scope) => {
const doc = scope || document;
const node = doc.createTextNode(text);
return fromDom$2(node);
};
const fromDom$2 = (node) => {
if (node === null || node === undefined) {
throw new Error("Node cannot be null or undefined");
}
return { dom: node };
};
const fromPoint$2 = (docElm, x, y) =>
Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$2);
const SugarElement = {
fromHtml: fromHtml$1,
fromTag,
fromText,
fromDom: fromDom$2,
fromPoint: fromPoint$2,
};
const toArray = (target, f) => {
const r = [];
const recurse = (e) => {
r.push(e);
return f(e);
};
let cur = f(target);
do {
cur = cur.bind(recurse);
} while (cur.isSome());
return r;
};
const is$1 = (element, selector) => {
const dom = element.dom;
if (dom.nodeType !== ELEMENT) {
return false;
} else {
const elem = dom;
if (elem.matches !== undefined) {
return elem.matches(selector);
} else if (elem.msMatchesSelector !== undefined) {
return elem.msMatchesSelector(selector);
} else if (elem.webkitMatchesSelector !== undefined) {
return elem.webkitMatchesSelector(selector);
} else if (elem.mozMatchesSelector !== undefined) {
return elem.mozMatchesSelector(selector);
} else {
throw new Error("Browser lacks native selectors");
}
}
};
const bypassSelector = (dom) =>
(dom.nodeType !== ELEMENT &&
dom.nodeType !== DOCUMENT &&
dom.nodeType !== DOCUMENT_FRAGMENT) ||
dom.childElementCount === 0;
const all = (selector, scope) => {
const base = scope === undefined ? document : scope.dom;
return bypassSelector(base)
? []
: map$3(base.querySelectorAll(selector), SugarElement.fromDom);
};
const one = (selector, scope) => {
const base = scope === undefined ? document : scope.dom;
return bypassSelector(base)
? Optional.none()
: Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
};
const eq = (e1, e2) => e1.dom === e2.dom;
const contains = (e1, e2) => {
const d1 = e1.dom;
const d2 = e2.dom;
return d1 === d2 ? false : d1.contains(d2);
};
const owner$1 = (element) => SugarElement.fromDom(element.dom.ownerDocument);
const documentOrOwner = (dos) => (isDocument$2(dos) ? dos : owner$1(dos));
const documentElement = (element) =>
SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
const defaultView = (element) =>
SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
const parent = (element) =>
Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
const parentElement = (element) =>
Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
const parents$1 = (element, isRoot) => {
const stop = isFunction(isRoot) ? isRoot : never;
let dom = element.dom;
const ret = [];
while (dom.parentNode !== null && dom.parentNode !== undefined) {
const rawParent = dom.parentNode;
const p = SugarElement.fromDom(rawParent);
ret.push(p);
if (stop(p) === true) {
break;
} else {
dom = rawParent;
}
}
return ret;
};
const siblings = (element) => {
const filterSelf = (elements) => filter$5(elements, (x) => !eq(element, x));
return parent(element).map(children$1).map(filterSelf).getOr([]);
};
const prevSibling = (element) =>
Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
const nextSibling = (element) =>
Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
const prevSiblings = (element) => reverse(toArray(element, prevSibling));
const nextSiblings = (element) => toArray(element, nextSibling);
const children$1 = (element) =>
map$3(element.dom.childNodes, SugarElement.fromDom);
const child$1 = (element, index) => {
const cs = element.dom.childNodes;
return Optional.from(cs[index]).map(SugarElement.fromDom);
};
const firstChild = (element) => child$1(element, 0);
const lastChild = (element) =>
child$1(element, element.dom.childNodes.length - 1);
const childNodesCount = (element) => element.dom.childNodes.length;
const hasChildNodes = (element) => element.dom.hasChildNodes();
const getHead = (doc) => {
const b = doc.dom.head;
if (b === null || b === undefined) {
throw new Error("Head is not available yet");
}
return SugarElement.fromDom(b);
};
const isShadowRoot = (dos) =>
isDocumentFragment$1(dos) && isNonNullable(dos.dom.host);
const supported =
isFunction(Element.prototype.attachShadow) &&
isFunction(Node.prototype.getRootNode);
const isSupported$1 = constant(supported);
const getRootNode = supported
? (e) => SugarElement.fromDom(e.dom.getRootNode())
: documentOrOwner;
const getStyleContainer = (dos) =>
isShadowRoot(dos) ? dos : getHead(documentOrOwner(dos));
const getContentContainer = (dos) =>
isShadowRoot(dos)
? dos
: SugarElement.fromDom(documentOrOwner(dos).dom.body);
const getShadowRoot = (e) => {
const r = getRootNode(e);
return isShadowRoot(r) ? Optional.some(r) : Optional.none();
};
const getShadowHost = (e) => SugarElement.fromDom(e.dom.host);
const getOriginalEventTarget = (event) => {
if (isSupported$1() && isNonNullable(event.target)) {
const el = SugarElement.fromDom(event.target);
if (isElement$7(el) && isOpenShadowHost(el)) {
if (event.composed && event.composedPath) {
const composedPath = event.composedPath();
if (composedPath) {
return head(composedPath);
}
}
}
}
return Optional.from(event.target);
};
const isOpenShadowHost = (element) => isNonNullable(element.dom.shadowRoot);
const inBody = (element) => {
const dom = isText$b(element) ? element.dom.parentNode : element.dom;
if (dom === undefined || dom === null || dom.ownerDocument === null) {
return false;
}
const doc = dom.ownerDocument;
return getShadowRoot(SugarElement.fromDom(dom)).fold(
() => doc.body.contains(dom),
compose1(inBody, getShadowHost)
);
};
var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
if (is(scope, a)) {
return Optional.some(scope);
} else if (isFunction(isRoot) && isRoot(scope)) {
return Optional.none();
} else {
return ancestor(scope, a, isRoot);
}
};
const ancestor$4 = (scope, predicate, isRoot) => {
let element = scope.dom;
const stop = isFunction(isRoot) ? isRoot : never;
while (element.parentNode) {
element = element.parentNode;
const el = SugarElement.fromDom(element);
if (predicate(el)) {
return Optional.some(el);
} else if (stop(el)) {
break;
}
}
return Optional.none();
};
const closest$4 = (scope, predicate, isRoot) => {
const is = (s, test) => test(s);
return ClosestOrAncestor(is, ancestor$4, scope, predicate, isRoot);
};
const sibling$1 = (scope, predicate) => {
const element = scope.dom;
if (!element.parentNode) {
return Optional.none();
}
return child(
SugarElement.fromDom(element.parentNode),
(x) => !eq(scope, x) && predicate(x)
);
};
const child = (scope, predicate) => {
const pred = (node) => predicate(SugarElement.fromDom(node));
const result = find$2(scope.dom.childNodes, pred);
return result.map(SugarElement.fromDom);
};
const descendant$1 = (scope, predicate) => {
const descend = (node) => {
for (let i = 0; i < node.childNodes.length; i++) {
const child = SugarElement.fromDom(node.childNodes[i]);
if (predicate(child)) {
return Optional.some(child);
}
const res = descend(node.childNodes[i]);
if (res.isSome()) {
return res;
}
}
return Optional.none();
};
return descend(scope.dom);
};
const ancestor$3 = (scope, selector, isRoot) =>
ancestor$4(scope, (e) => is$1(e, selector), isRoot);
const descendant = (scope, selector) => one(selector, scope);
const closest$3 = (scope, selector, isRoot) => {
const is = (element, selector) => is$1(element, selector);
return ClosestOrAncestor(is, ancestor$3, scope, selector, isRoot);
};
const closest$2 = (target) => closest$3(target, "[contenteditable]");
const isEditable$3 = (element, assumeEditable = false) => {
if (inBody(element)) {
return element.dom.isContentEditable;
} else {
return closest$2(element).fold(
constant(assumeEditable),
(editable) => getRaw$1(editable) === "true"
);
}
};
const getRaw$1 = (element) => element.dom.contentEditable;
const isSupported = (dom) =>
dom.style !== undefined && isFunction(dom.style.getPropertyValue);
const internalSet = (dom, property, value) => {
if (!isString(value)) {
console.error(
"Invalid call to CSS.set. Property ",
property,
":: Value ",
value,
":: Element ",
dom
);
throw new Error("CSS value must be a string: " + value);
}
if (isSupported(dom)) {
dom.style.setProperty(property, value);
}
};
const internalRemove = (dom, property) => {
if (isSupported(dom)) {
dom.style.removeProperty(property);
}
};
const set$2 = (element, property, value) => {
const dom = element.dom;
internalSet(dom, property, value);
};
const setAll = (element, css) => {
const dom = element.dom;
each$d(css, (v, k) => {
internalSet(dom, k, v);
});
};
const get$7 = (element, property) => {
const dom = element.dom;
const styles = window.getComputedStyle(dom);
const r = styles.getPropertyValue(property);
return r === "" && !inBody(element) ? getUnsafeProperty(dom, property) : r;
};
const getUnsafeProperty = (dom, property) =>
isSupported(dom) ? dom.style.getPropertyValue(property) : "";
const getRaw = (element, property) => {
const dom = element.dom;
const raw = getUnsafeProperty(dom, property);
return Optional.from(raw).filter((r) => r.length > 0);
};
const getAllRaw = (element) => {
const css = {};
const dom = element.dom;
if (isSupported(dom)) {
for (let i = 0; i < dom.style.length; i++) {
const ruleName = dom.style.item(i);
css[ruleName] = dom.style[ruleName];
}
}
return css;
};
const remove$6 = (element, property) => {
const dom = element.dom;
internalRemove(dom, property);
if (is$2(getOpt(element, "style").map(trim$3), "")) {
remove$a(element, "style");
}
};
const reflow = (e) => e.dom.offsetWidth;
const before$3 = (marker, element) => {
const parent$1 = parent(marker);
parent$1.each((v) => {
v.dom.insertBefore(element.dom, marker.dom);
});
};
const after$4 = (marker, element) => {
const sibling = nextSibling(marker);
sibling.fold(
() => {
const parent$1 = parent(marker);
parent$1.each((v) => {
append$1(v, element);
});
},
(v) => {
before$3(v, element);
}
);
};
const prepend = (parent, element) => {
const firstChild$1 = firstChild(parent);
firstChild$1.fold(
() => {
append$1(parent, element);
},
(v) => {
parent.dom.insertBefore(element.dom, v.dom);
}
);
};
const append$1 = (parent, element) => {
parent.dom.appendChild(element.dom);
};
const wrap$2 = (element, wrapper) => {
before$3(element, wrapper);
append$1(wrapper, element);
};
const after$3 = (marker, elements) => {
each$e(elements, (x, i) => {
const e = i === 0 ? marker : elements[i - 1];
after$4(e, x);
});
};
const append = (parent, elements) => {
each$e(elements, (x) => {
append$1(parent, x);
});
};
const empty = (element) => {
element.dom.textContent = "";
each$e(children$1(element), (rogue) => {
remove$5(rogue);
});
};
const remove$5 = (element) => {
const dom = element.dom;
if (dom.parentNode !== null) {
dom.parentNode.removeChild(dom);
}
};
const unwrap = (wrapper) => {
const children = children$1(wrapper);
if (children.length > 0) {
after$3(wrapper, children);
}
remove$5(wrapper);
};
const fromHtml = (html, scope) => {
const doc = scope || document;
const div = doc.createElement("div");
div.innerHTML = html;
return children$1(SugarElement.fromDom(div));
};
const fromDom$1 = (nodes) => map$3(nodes, SugarElement.fromDom);
const get$6 = (element) => element.dom.innerHTML;
const set$1 = (element, content) => {
const owner = owner$1(element);
const docDom = owner.dom;
const fragment = SugarElement.fromDom(docDom.createDocumentFragment());
const contentElements = fromHtml(content, docDom);
append(fragment, contentElements);
empty(element);
append$1(element, fragment);
};
const getOuter = (element) => {
const container = SugarElement.fromTag("div");
const clone = SugarElement.fromDom(element.dom.cloneNode(true));
append$1(container, clone);
return get$6(container);
};
const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
target,
x,
y,
stop,
prevent,
kill,
raw,
});
const fromRawEvent = (rawEvent) => {
const target = SugarElement.fromDom(
getOriginalEventTarget(rawEvent).getOr(rawEvent.target)
);
const stop = () => rawEvent.stopPropagation();
const prevent = () => rawEvent.preventDefault();
const kill = compose(prevent, stop);
return mkEvent(
target,
rawEvent.clientX,
rawEvent.clientY,
stop,
prevent,
kill,
rawEvent
);
};
const handle$1 = (filter, handler) => (rawEvent) => {
if (filter(rawEvent)) {
handler(fromRawEvent(rawEvent));
}
};
const binder = (element, event, filter, handler, useCapture) => {
const wrapped = handle$1(filter, handler);
element.dom.addEventListener(event, wrapped, useCapture);
return { unbind: curry(unbind, element, event, wrapped, useCapture) };
};
const bind$2 = (element, event, filter, handler) =>
binder(element, event, filter, handler, false);
const unbind = (element, event, handler, useCapture) => {
element.dom.removeEventListener(event, handler, useCapture);
};
const r = (left, top) => {
const translate = (x, y) => r(left + x, top + y);
return {
left,
top,
translate,
};
};
const SugarPosition = r;
const boxPosition = (dom) => {
const box = dom.getBoundingClientRect();
return SugarPosition(box.left, box.top);
};
const firstDefinedOrZero = (a, b) => {
if (a !== undefined) {
return a;
} else {
return b !== undefined ? b : 0;
}
};
const absolute = (element) => {
const doc = element.dom.ownerDocument;
const body = doc.body;
const win = doc.defaultView;
const html = doc.documentElement;
if (body === element.dom) {
return SugarPosition(body.offsetLeft, body.offsetTop);
}
const scrollTop = firstDefinedOrZero(
win === null || win === void 0 ? void 0 : win.pageYOffset,
html.scrollTop
);
const scrollLeft = firstDefinedOrZero(
win === null || win === void 0 ? void 0 : win.pageXOffset,
html.scrollLeft
);
const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
return viewport(element).translate(
scrollLeft - clientLeft,
scrollTop - clientTop
);
};
const viewport = (element) => {
const dom = element.dom;
const doc = dom.ownerDocument;
const body = doc.body;
if (body === dom) {
return SugarPosition(body.offsetLeft, body.offsetTop);
}
if (!inBody(element)) {
return SugarPosition(0, 0);
}
return boxPosition(dom);
};
const get$5 = (_DOC) => {
const doc = _DOC !== undefined ? _DOC.dom : document;
const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
const y = doc.body.scrollTop || doc.documentElement.scrollTop;
return SugarPosition(x, y);
};
const to = (x, y, _DOC) => {
const doc = _DOC !== undefined ? _DOC.dom : document;
const win = doc.defaultView;
if (win) {
win.scrollTo(x, y);
}
};
const intoView = (element, alignToTop) => {
const isSafari = detect$2().browser.isSafari();
if (isSafari && isFunction(element.dom.scrollIntoViewIfNeeded)) {
element.dom.scrollIntoViewIfNeeded(false);
} else {
element.dom.scrollIntoView(alignToTop);
}
};
const get$4 = (_win) => {
const win = _win === undefined ? window : _win;
if (detect$2().browser.isFirefox()) {
return Optional.none();
} else {
return Optional.from(win.visualViewport);
}
};
const bounds = (x, y, width, height) => ({
x,
y,
width,
height,
right: x + width,
bottom: y + height,
});
const getBounds = (_win) => {
const win = _win === undefined ? window : _win;
const doc = win.document;
const scroll = get$5(SugarElement.fromDom(doc));
return get$4(win).fold(
() => {
const html = win.document.documentElement;
const width = html.clientWidth;
const height = html.clientHeight;
return bounds(scroll.left, scroll.top, width, height);
},
(visualViewport) =>
bounds(
Math.max(visualViewport.pageLeft, scroll.left),
Math.max(visualViewport.pageTop, scroll.top),
visualViewport.width,
visualViewport.height
)
);
};
const children = (scope, predicate) => filter$5(children$1(scope), predicate);
const descendants$1 = (scope, predicate) => {
let result = [];
each$e(children$1(scope), (x) => {
if (predicate(x)) {
result = result.concat([x]);
}
result = result.concat(descendants$1(x, predicate));
});
return result;
};
const descendants = (scope, selector) => all(selector, scope);
const ancestor$2 = (scope, selector, isRoot) =>
ancestor$3(scope, selector, isRoot).isSome();
class DomTreeWalker {
constructor(startNode, rootNode) {
this.node = startNode;
this.rootNode = rootNode;
this.current = this.current.bind(this);
this.next = this.next.bind(this);
this.prev = this.prev.bind(this);
this.prev2 = this.prev2.bind(this);
}
current() {
return this.node;
}
next(shallow) {
this.node = this.findSibling(
this.node,
"firstChild",
"nextSibling",
shallow
);
return this.node;
}
prev(shallow) {
this.node = this.findSibling(
this.node,
"lastChild",
"previousSibling",
shallow
);
return this.node;
}
prev2(shallow) {
this.node = this.findPreviousNode(this.node, shallow);
return this.node;
}
findSibling(node, startName, siblingName, shallow) {
if (node) {
if (!shallow && node[startName]) {
return node[startName];
}
if (node !== this.rootNode) {
let sibling = node[siblingName];
if (sibling) {
return sibling;
}
for (
let parent = node.parentNode;
parent && parent !== this.rootNode;
parent = parent.parentNode
) {
sibling = parent[siblingName];
if (sibling) {
return sibling;
}
}
}
}
return undefined;
}
findPreviousNode(node, shallow) {
if (node) {
const sibling = node.previousSibling;
if (this.rootNode && sibling === this.rootNode) {
return;
}
if (sibling) {
if (!shallow) {
for (
let child = sibling.lastChild;
child;
child = child.lastChild
) {
if (!child.lastChild) {
return child;
}
}
}
return sibling;
}
const parent = node.parentNode;
if (parent && parent !== this.rootNode) {
return parent;
}
}
return undefined;
}
}
const isNodeType = (type) => {
return (node) => {
return !!node && node.nodeType === type;
};
};
const isRestrictedNode = (node) => !!node && !Object.getPrototypeOf(node);
const isElement$6 = isNodeType(1);
const matchNodeName = (name) => {
const lowerCasedName = name.toLowerCase();
return (node) =>
isNonNullable(node) && node.nodeName.toLowerCase() === lowerCasedName;
};
const matchNodeNames = (names) => {
const lowerCasedNames = names.map((s) => s.toLowerCase());
return (node) => {
if (node && node.nodeName) {
const nodeName = node.nodeName.toLowerCase();
return contains$2(lowerCasedNames, nodeName);
}
return false;
};
};
const matchStyleValues = (name, values) => {
const items = values.toLowerCase().split(" ");
return (node) => {
if (isElement$6(node)) {
const win = node.ownerDocument.defaultView;
if (win) {
for (let i = 0; i < items.length; i++) {
const computed = win.getComputedStyle(node, null);
const cssValue = computed ? computed.getPropertyValue(name) : null;
if (cssValue === items[i]) {
return true;
}
}
}
}
return false;
};
};
const hasAttribute = (attrName) => {
return (node) => {
return isElement$6(node) && node.hasAttribute(attrName);
};
};
const hasAttributeValue = (attrName, attrValue) => {
return (node) => {
return isElement$6(node) && node.getAttribute(attrName) === attrValue;
};
};
const isBogus$2 = (node) =>
isElement$6(node) && node.hasAttribute("data-mce-bogus");
const isBogusAll$1 = (node) =>
isElement$6(node) && node.getAttribute("data-mce-bogus") === "all";
const isTable$2 = (node) => isElement$6(node) && node.tagName === "TABLE";
const hasContentEditableState = (value) => {
return (node) => {
if (isElement$6(node)) {
if (node.contentEditable === value) {
return true;
}
if (node.getAttribute("data-mce-contenteditable") === value) {
return true;
}
}
return false;
};
};
const isTextareaOrInput = matchNodeNames(["textarea", "input"]);
const isText$a = isNodeType(3);
const isCData = isNodeType(4);
const isPi = isNodeType(7);
const isComment = isNodeType(8);
const isDocument$1 = isNodeType(9);
const isDocumentFragment = isNodeType(11);
const isBr$6 = matchNodeName("br");
const isImg = matchNodeName("img");
const isContentEditableTrue$3 = hasContentEditableState("true");
const isContentEditableFalse$b = hasContentEditableState("false");
const isTableCell$3 = matchNodeNames(["td", "th"]);
const isTableCellOrCaption = matchNodeNames(["td", "th", "caption"]);
const isMedia$2 = matchNodeNames(["video", "audio", "object", "embed"]);
const isListItem$2 = matchNodeName("li");
const isDetails = matchNodeName("details");
const isSummary = matchNodeName("summary");
const zeroWidth = "\uFEFF";
const nbsp = "\xA0";
const isZwsp$2 = (char) => char === zeroWidth;
const removeZwsp = (s) => s.replace(/\uFEFF/g, "");
const NodeValue = (is, name) => {
const get = (element) => {
if (!is(element)) {
throw new Error(
"Can only get " + name + " value of a " + name + " node"
);
}
return getOption(element).getOr("");
};
const getOption = (element) =>
is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
const set = (element, value) => {
if (!is(element)) {
throw new Error(
"Can only set raw " + name + " value of a " + name + " node"
);
}
element.dom.nodeValue = value;
};
return {
get,
getOption,
set,
};
};
const api$1 = NodeValue(isText$b, "text");
const get$3 = (element) => api$1.get(element);
const getOption = (element) => api$1.getOption(element);
const set = (element, value) => api$1.set(element, value);
const blocks = [
"article",
"aside",
"details",
"div",
"dt",
"figcaption",
"footer",
"form",
"fieldset",
"header",
"hgroup",
"html",
"main",
"nav",
"section",
"summary",
"body",
"p",
"dl",
"multicol",
"dd",
"figure",
"address",
"center",
"blockquote",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"listing",
"xmp",
"pre",
"plaintext",
"menu",
"dir",
"ul",
"ol",
"li",
"hr",
"table",
"tbody",
"thead",
"tfoot",
"th",
"tr",
"td",
"caption",
];
const tableCells = ["td", "th"];
const tableSections = ["thead", "tbody", "tfoot"];
const textBlocks = [
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"p",
"div",
"address",
"pre",
"form",
"blockquote",
"center",
"dir",
"fieldset",
"header",
"footer",
"article",
"section",
"hgroup",
"aside",
"nav",
"figure",
];
const headings = ["h1", "h2", "h3", "h4", "h5", "h6"];
const listItems$1 = ["li", "dd", "dt"];
const lists = ["ul", "ol", "dl"];
const wsElements = ["pre", "script", "textarea", "style"];
const wrapBlockElements = ["pre"].concat(headings);
const lazyLookup = (items) => {
let lookup;
return (node) => {
lookup = lookup ? lookup : mapToObject(items, always);
return has$2(lookup, name(node));
};
};
const isBlock$2 = lazyLookup(blocks);
const isTable$1 = (node) => name(node) === "table";
const isInline$1 = (node) => isElement$7(node) && !isBlock$2(node);
const isBr$5 = (node) => isElement$7(node) && name(node) === "br";
const isTextBlock$2 = lazyLookup(textBlocks);
const isList = lazyLookup(lists);
const isListItem$1 = lazyLookup(listItems$1);
const isTableSection = lazyLookup(tableSections);
const isTableCell$2 = lazyLookup(tableCells);
const isWsPreserveElement = lazyLookup(wsElements);
const isWrapBlockElement = lazyLookup(wrapBlockElements);
const isWrapElement = (node) => isWrapBlockElement(node) || isInline$1(node);
const getLastChildren$1 = (elm) => {
const children = [];
let rawNode = elm.dom;
while (rawNode) {
children.push(SugarElement.fromDom(rawNode));
rawNode = rawNode.lastChild;
}
return children;
};
const removeTrailingBr = (elm) => {
const allBrs = descendants(elm, "br");
const brs = filter$5(getLastChildren$1(elm).slice(-1), isBr$5);
if (allBrs.length === brs.length) {
each$e(brs, remove$5);
}
};
const createPaddingBr = () => {
const br = SugarElement.fromTag("br");
set$3(br, "data-mce-bogus", "1");
return br;
};
const fillWithPaddingBr = (elm) => {
empty(elm);
append$1(elm, createPaddingBr());
};
const trimBlockTrailingBr = (elm) => {
lastChild(elm).each((lastChild) => {
prevSibling(lastChild).each((lastChildPrevSibling) => {
if (
isBlock$2(elm) &&
isBr$5(lastChild) &&
isBlock$2(lastChildPrevSibling)
) {
remove$5(lastChild);
}
});
});
};
const ZWSP$1 = zeroWidth;
const isZwsp$1 = isZwsp$2;
const trim$1 = removeZwsp;
const isElement$5 = isElement$6;
const isText$9 = isText$a;
const isCaretContainerBlock$1 = (node) => {
if (isText$9(node)) {
node = node.parentNode;
}
return isElement$5(node) && node.hasAttribute("data-mce-caret");
};
const isCaretContainerInline = (node) =>
isText$9(node) && isZwsp$1(node.data);
const isCaretContainer$2 = (node) =>
isCaretContainerBlock$1(node) || isCaretContainerInline(node);
const hasContent = (node) =>
node.firstChild !== node.lastChild || !isBr$6(node.firstChild);
const insertInline$1 = (node, before) => {
var _a;
const doc =
(_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
const textNode = doc.createTextNode(ZWSP$1);
const parentNode = node.parentNode;
if (!before) {
const sibling = node.nextSibling;
if (isText$9(sibling)) {
if (isCaretContainer$2(sibling)) {
return sibling;
}
if (startsWithCaretContainer$1(sibling)) {
sibling.splitText(1);
return sibling;
}
}
if (node.nextSibling) {
parentNode === null || parentNode === void 0
? void 0
: parentNode.insertBefore(textNode, node.nextSibling);
} else {
parentNode === null || parentNode === void 0
? void 0
: parentNode.appendChild(textNode);
}
} else {
const sibling = node.previousSibling;
if (isText$9(sibling)) {
if (isCaretContainer$2(sibling)) {
return sibling;
}
if (endsWithCaretContainer$1(sibling)) {
return sibling.splitText(sibling.data.length - 1);
}
}
parentNode === null || parentNode === void 0
? void 0
: parentNode.insertBefore(textNode, node);
}
return textNode;
};
const isBeforeInline = (pos) => {
const container = pos.container();
if (!isText$a(container)) {
return false;
}
return (
container.data.charAt(pos.offset()) === ZWSP$1 ||
(pos.isAtStart() && isCaretContainerInline(container.previousSibling))
);
};
const isAfterInline = (pos) => {
const container = pos.container();
if (!isText$a(container)) {
return false;
}
return (
container.data.charAt(pos.offset() - 1) === ZWSP$1 ||
(pos.isAtEnd() && isCaretContainerInline(container.nextSibling))
);
};
const insertBlock = (blockName, node, before) => {
var _a;
const doc =
(_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
const blockNode = doc.createElement(blockName);
blockNode.setAttribute("data-mce-caret", before ? "before" : "after");
blockNode.setAttribute("data-mce-bogus", "all");
blockNode.appendChild(createPaddingBr().dom);
const parentNode = node.parentNode;
if (!before) {
if (node.nextSibling) {
parentNode === null || parentNode === void 0
? void 0
: parentNode.insertBefore(blockNode, node.nextSibling);
} else {
parentNode === null || parentNode === void 0
? void 0
: parentNode.appendChild(blockNode);
}
} else {
parentNode === null || parentNode === void 0
? void 0
: parentNode.insertBefore(blockNode, node);
}
return blockNode;
};
const startsWithCaretContainer$1 = (node) =>
isText$9(node) && node.data[0] === ZWSP$1;
const endsWithCaretContainer$1 = (node) =>
isText$9(node) && node.data[node.data.length - 1] === ZWSP$1;
const trimBogusBr = (elm) => {
var _a;
const brs = elm.getElementsByTagName("br");
const lastBr = brs[brs.length - 1];
if (isBogus$2(lastBr)) {
(_a = lastBr.parentNode) === null || _a === void 0
? void 0
: _a.removeChild(lastBr);
}
};
const showCaretContainerBlock = (caretContainer) => {
if (caretContainer && caretContainer.hasAttribute("data-mce-caret")) {
trimBogusBr(caretContainer);
caretContainer.removeAttribute("data-mce-caret");
caretContainer.removeAttribute("data-mce-bogus");
caretContainer.removeAttribute("style");
caretContainer.removeAttribute("data-mce-style");
caretContainer.removeAttribute("_moz_abspos");
return caretContainer;
}
return null;
};
const isRangeInCaretContainerBlock = (range) =>
isCaretContainerBlock$1(range.startContainer);
const isContentEditableTrue$2 = isContentEditableTrue$3;
const isContentEditableFalse$a = isContentEditableFalse$b;
const isBr$4 = isBr$6;
const isText$8 = isText$a;
const isInvalidTextElement = matchNodeNames(["script", "style", "textarea"]);
const isAtomicInline = matchNodeNames([
"img",
"input",
"textarea",
"hr",
"iframe",
"video",
"audio",
"object",
"embed",
]);
const isTable = matchNodeNames(["table"]);
const isCaretContainer$1 = isCaretContainer$2;
const isCaretCandidate$3 = (node) => {
if (isCaretContainer$1(node)) {
return false;
}
if (isText$8(node)) {
return !isInvalidTextElement(node.parentNode);
}
return (
isAtomicInline(node) ||
isBr$4(node) ||
isTable(node) ||
isNonUiContentEditableFalse(node)
);
};
const isUnselectable = (node) =>
isElement$6(node) && node.getAttribute("unselectable") === "true";
const isNonUiContentEditableFalse = (node) =>
!isUnselectable(node) && isContentEditableFalse$a(node);
const isInEditable = (node, root) => {
for (
let tempNode = node.parentNode;
tempNode && tempNode !== root;
tempNode = tempNode.parentNode
) {
if (isNonUiContentEditableFalse(tempNode)) {
return false;
}
if (isContentEditableTrue$2(tempNode)) {
return true;
}
}
return true;
};
const isAtomicContentEditableFalse = (node) => {
if (!isNonUiContentEditableFalse(node)) {
return false;
}
return !foldl(
from(node.getElementsByTagName("*")),
(result, elm) => {
return result || isContentEditableTrue$2(elm);
},
false
);
};
const isAtomic$1 = (node) =>
isAtomicInline(node) || isAtomicContentEditableFalse(node);
const isEditableCaretCandidate$1 = (node, root) =>
isCaretCandidate$3(node) && isInEditable(node, root);
const whiteSpaceRegExp = /^[ \t\r\n]*$/;
const isWhitespaceText = (text) => whiteSpaceRegExp.test(text);
const isZwsp = (text) => {
for (const c of text) {
if (!isZwsp$2(c)) {
return false;
}
}
return true;
};
const isCollapsibleWhitespace$1 = (c) => " \f\t\x0B".indexOf(c) !== -1;
const isNewLineChar = (c) => c === "\n" || c === "\r";
const isNewline = (text, idx) =>
idx < text.length && idx >= 0 ? isNewLineChar(text[idx]) : false;
const normalize$4 = (
text,
tabSpaces = 4,
isStartOfContent = true,
isEndOfContent = true
) => {
const tabSpace = repeat(" ", tabSpaces);
const normalizedText = text.replace(/\t/g, tabSpace);
const result = foldl(
normalizedText,
(acc, c) => {
if (isCollapsibleWhitespace$1(c) || c === nbsp) {
if (
acc.pcIsSpace ||
(acc.str === "" && isStartOfContent) ||
(acc.str.length === normalizedText.length - 1 && isEndOfContent) ||
isNewline(normalizedText, acc.str.length + 1)
) {
return {
pcIsSpace: false,
str: acc.str + nbsp,
};
} else {
return {
pcIsSpace: true,
str: acc.str + " ",
};
}
} else {
return {
pcIsSpace: isNewLineChar(c),
str: acc.str + c,
};
}
},
{
pcIsSpace: false,
str: "",
}
);
return result.str;
};
const hasWhitespacePreserveParent = (node, rootNode) => {
const rootElement = SugarElement.fromDom(rootNode);
const startNode = SugarElement.fromDom(node);
return ancestor$2(startNode, "pre,code", curry(eq, rootElement));
};
const isWhitespace$1 = (node, rootNode) => {
return (
isText$a(node) &&
isWhitespaceText(node.data) &&
!hasWhitespacePreserveParent(node, rootNode)
);
};
const isNamedAnchor = (node) => {
return (
isElement$6(node) &&
node.nodeName === "A" &&
!node.hasAttribute("href") &&
(node.hasAttribute("name") || node.hasAttribute("id"))
);
};
const isContent$1 = (node, rootNode) => {
return (
(isCaretCandidate$3(node) && !isWhitespace$1(node, rootNode)) ||
isNamedAnchor(node) ||
isBookmark(node)
);
};
const isBookmark = hasAttribute("data-mce-bookmark");
const isBogus$1 = hasAttribute("data-mce-bogus");
const isBogusAll = hasAttributeValue("data-mce-bogus", "all");
const isEmptyNode = (targetNode, skipBogus) => {
let brCount = 0;
if (isContent$1(targetNode, targetNode)) {
return false;
} else {
let node = targetNode.firstChild;
if (!node) {
return true;
}
const walker = new DomTreeWalker(node, targetNode);
do {
if (skipBogus) {
if (isBogusAll(node)) {
node = walker.next(true);
continue;
}
if (isBogus$1(node)) {
node = walker.next();
continue;
}
}
if (isBr$6(node)) {
brCount++;
node = walker.next();
continue;
}
if (isContent$1(node, targetNode)) {
return false;
}
node = walker.next();
} while (node);
return brCount <= 1;
}
};
const isEmpty$2 = (elm, skipBogus = true) => isEmptyNode(elm.dom, skipBogus);
const transparentBlockAttr = "data-mce-block";
const elementNames = (map) =>
filter$5(keys(map), (key) => !/[A-Z]/.test(key));
const makeSelectorFromSchemaMap = (map) => elementNames(map).join(",");
const updateTransparent = (blocksSelector, transparent) => {
if (isNonNullable(transparent.querySelector(blocksSelector))) {
transparent.setAttribute(transparentBlockAttr, "true");
if (transparent.getAttribute("data-mce-selected") === "inline-boundary") {
transparent.removeAttribute("data-mce-selected");
}
return true;
} else {
transparent.removeAttribute(transparentBlockAttr);
return false;
}
};
const updateBlockStateOnChildren = (schema, scope) => {
const transparentSelector = makeSelectorFromSchemaMap(
schema.getTransparentElements()
);
const blocksSelector = makeSelectorFromSchemaMap(schema.getBlockElements());
return filter$5(
scope.querySelectorAll(transparentSelector),
(transparent) => updateTransparent(blocksSelector, transparent)
);
};
const trimEdge = (el, leftSide) => {
var _a;
const childPropertyName = leftSide ? "lastChild" : "firstChild";
for (
let child = el[childPropertyName];
child;
child = child[childPropertyName]
) {
if (isEmpty$2(SugarElement.fromDom(child))) {
(_a = child.parentNode) === null || _a === void 0
? void 0
: _a.removeChild(child);
return;
}
}
};
const split$2 = (parentElm, splitElm) => {
const range = document.createRange();
const parentNode = parentElm.parentNode;
if (parentNode) {
range.setStartBefore(parentElm);
range.setEndBefore(splitElm);
const beforeFragment = range.extractContents();
trimEdge(beforeFragment, true);
range.setStartAfter(splitElm);
range.setEndAfter(parentElm);
const afterFragment = range.extractContents();
trimEdge(afterFragment, false);
if (!isEmpty$2(SugarElement.fromDom(beforeFragment))) {
parentNode.insertBefore(beforeFragment, parentElm);
}
if (!isEmpty$2(SugarElement.fromDom(splitElm))) {
parentNode.insertBefore(splitElm, parentElm);
}
if (!isEmpty$2(SugarElement.fromDom(afterFragment))) {
parentNode.insertBefore(afterFragment, parentElm);
}
parentNode.removeChild(parentElm);
}
};
const splitInvalidChildren = (schema, scope, transparentBlocks) => {
const blocksElements = schema.getBlockElements();
const rootNode = SugarElement.fromDom(scope);
const isBlock = (el) => name(el) in blocksElements;
const isRoot = (el) => eq(el, rootNode);
each$e(fromDom$1(transparentBlocks), (transparentBlock) => {
ancestor$4(transparentBlock, isBlock, isRoot).each((parentBlock) => {
const invalidChildren = children(
transparentBlock,
(el) =>
isBlock(el) && !schema.isValidChild(name(parentBlock), name(el))
);
if (invalidChildren.length > 0) {
const stateScope = parentElement(parentBlock);
each$e(invalidChildren, (child) => {
ancestor$4(child, isBlock, isRoot).each((parentBlock) => {
split$2(parentBlock.dom, child.dom);
});
});
stateScope.each((scope) =>
updateBlockStateOnChildren(schema, scope.dom)
);
}
});
});
};
const unwrapInvalidChildren = (schema, scope, transparentBlocks) => {
each$e(
[
...transparentBlocks,
...(isTransparentBlock(schema, scope) ? [scope] : []),
],
(block) =>
each$e(
descendants(
SugarElement.fromDom(block),
block.nodeName.toLowerCase()
),
(elm) => {
if (isTransparentInline(schema, elm.dom)) {
unwrap(elm);
}
}
)
);
};
const updateChildren = (schema, scope) => {
const transparentBlocks = updateBlockStateOnChildren(schema, scope);
splitInvalidChildren(schema, scope, transparentBlocks);
unwrapInvalidChildren(schema, scope, transparentBlocks);
};
const updateElement = (schema, target) => {
if (isTransparentElement(schema, target)) {
const blocksSelector = makeSelectorFromSchemaMap(
schema.getBlockElements()
);
updateTransparent(blocksSelector, target);
}
};
const updateCaret = (schema, root, caretParent) => {
const isRoot = (el) => eq(el, SugarElement.fromDom(root));
const parents = parents$1(SugarElement.fromDom(caretParent), isRoot);
get$b(parents, parents.length - 2)
.filter(isElement$7)
.fold(
() => updateChildren(schema, root),
(scope) => updateChildren(schema, scope.dom)
);
};
const hasBlockAttr = (el) => el.hasAttribute(transparentBlockAttr);
const isTransparentElementName = (schema, name) =>
has$2(schema.getTransparentElements(), name);
const isTransparentElement = (schema, node) =>
isElement$6(node) && isTransparentElementName(schema, node.nodeName);
const isTransparentBlock = (schema, node) =>
isTransparentElement(schema, node) && hasBlockAttr(node);
const isTransparentInline = (schema, node) =>
isTransparentElement(schema, node) && !hasBlockAttr(node);
const isTransparentAstBlock = (schema, node) =>
node.type === 1 &&
isTransparentElementName(schema, node.name) &&
isString(node.attr(transparentBlockAttr));
const browser$2 = detect$2().browser;
const firstElement = (nodes) => find$2(nodes, isElement$7);
const getTableCaptionDeltaY = (elm) => {
if (browser$2.isFirefox() && name(elm) === "table") {
return firstElement(children$1(elm))
.filter((elm) => {
return name(elm) === "caption";
})
.bind((caption) => {
return firstElement(nextSiblings(caption)).map((body) => {
const bodyTop = body.dom.offsetTop;
const captionTop = caption.dom.offsetTop;
const captionHeight = caption.dom.offsetHeight;
return bodyTop <= captionTop ? -captionHeight : 0;
});
})
.getOr(0);
} else {
return 0;
}
};
const hasChild = (elm, child) =>
elm.children && contains$2(elm.children, child);
const getPos = (body, elm, rootElm) => {
let x = 0,
y = 0;
const doc = body.ownerDocument;
rootElm = rootElm ? rootElm : body;
if (elm) {
if (
rootElm === body &&
elm.getBoundingClientRect &&
get$7(SugarElement.fromDom(body), "position") === "static"
) {
const pos = elm.getBoundingClientRect();
x =
pos.left +
(doc.documentElement.scrollLeft || body.scrollLeft) -
doc.documentElement.clientLeft;
y =
pos.top +
(doc.documentElement.scrollTop || body.scrollTop) -
doc.documentElement.clientTop;
return {
x,
y,
};
}
let offsetParent = elm;
while (
offsetParent &&
offsetParent !== rootElm &&
offsetParent.nodeType &&
!hasChild(offsetParent, rootElm)
) {
const castOffsetParent = offsetParent;
x += castOffsetParent.offsetLeft || 0;
y += castOffsetParent.offsetTop || 0;
offsetParent = castOffsetParent.offsetParent;
}
offsetParent = elm.parentNode;
while (
offsetParent &&
offsetParent !== rootElm &&
offsetParent.nodeType &&
!hasChild(offsetParent, rootElm)
) {
x -= offsetParent.scrollLeft || 0;
y -= offsetParent.scrollTop || 0;
offsetParent = offsetParent.parentNode;
}
y += getTableCaptionDeltaY(SugarElement.fromDom(elm));
}
return {
x,
y,
};
};
const StyleSheetLoader = (documentOrShadowRoot, settings = {}) => {
let idCount = 0;
const loadedStates = {};
const edos = SugarElement.fromDom(documentOrShadowRoot);
const doc = documentOrOwner(edos);
const _setReferrerPolicy = (referrerPolicy) => {
settings.referrerPolicy = referrerPolicy;
};
const _setContentCssCors = (contentCssCors) => {
settings.contentCssCors = contentCssCors;
};
const addStyle = (element) => {
append$1(getStyleContainer(edos), element);
};
const removeStyle = (id) => {
const styleContainer = getStyleContainer(edos);
descendant(styleContainer, "#" + id).each(remove$5);
};
const getOrCreateState = (url) =>
get$a(loadedStates, url).getOrThunk(() => ({
id: "mce-u" + idCount++,
passed: [],
failed: [],
count: 0,
}));
const load = (url) =>
new Promise((success, failure) => {
let link;
const urlWithSuffix = Tools._addCacheSuffix(url);
const state = getOrCreateState(urlWithSuffix);
loadedStates[urlWithSuffix] = state;
state.count++;
const resolve = (callbacks, status) => {
each$e(callbacks, call);
state.status = status;
state.passed = [];
state.failed = [];
if (link) {
link.onload = null;
link.onerror = null;
link = null;
}
};
const passed = () => resolve(state.passed, 2);
const failed = () => resolve(state.failed, 3);
if (success) {
state.passed.push(success);
}
if (failure) {
state.failed.push(failure);
}
if (state.status === 1) {
return;
}
if (state.status === 2) {
passed();
return;
}
if (state.status === 3) {
failed();
return;
}
state.status = 1;
const linkElem = SugarElement.fromTag("link", doc.dom);
setAll$1(linkElem, {
rel: "stylesheet",
type: "text/css",
id: state.id,
});
if (settings.contentCssCors) {
set$3(linkElem, "crossOrigin", "anonymous");
}
if (settings.referrerPolicy) {
set$3(linkElem, "referrerpolicy", settings.referrerPolicy);
}
link = linkElem.dom;
link.onload = passed;
link.onerror = failed;
addStyle(linkElem);
set$3(linkElem, "href", urlWithSuffix);
});
const loadAll = (urls) => {
const loadedUrls = Promise.allSettled(
map$3(urls, (url) => load(url).then(constant(url)))
);
return loadedUrls.then((results) => {
const parts = partition$2(results, (r) => r.status === "fulfilled");
if (parts.fail.length > 0) {
return Promise.reject(map$3(parts.fail, (result) => result.reason));
} else {
return map$3(parts.pass, (result) => result.value);
}
});
};
const unload = (url) => {
const urlWithSuffix = Tools._addCacheSuffix(url);
get$a(loadedStates, urlWithSuffix).each((state) => {
const count = --state.count;
if (count === 0) {
delete loadedStates[urlWithSuffix];
removeStyle(state.id);
}
});
};
const unloadAll = (urls) => {
each$e(urls, (url) => {
unload(url);
});
};
return {
load,
loadAll,
unload,
unloadAll,
_setReferrerPolicy,
_setContentCssCors,
};
};
const create$d = () => {
const map = new WeakMap();
const forElement = (referenceElement, settings) => {
const root = getRootNode(referenceElement);
const rootDom = root.dom;
return Optional.from(map.get(rootDom)).getOrThunk(() => {
const sl = StyleSheetLoader(rootDom, settings);
map.set(rootDom, sl);
return sl;
});
};
return { forElement };
};
const instance = create$d();
const isSpan = (node) => node.nodeName.toLowerCase() === "span";
const isInlineContent = (node, root) =>
isNonNullable(node) &&
(isContent$1(node, root) || isInline$1(SugarElement.fromDom(node)));
const surroundedByInlineContent = (node, root) => {
const prev = new DomTreeWalker(node, root).prev(false);
const next = new DomTreeWalker(node, root).next(false);
const prevIsInline = isUndefined(prev) || isInlineContent(prev, root);
const nextIsInline = isUndefined(next) || isInlineContent(next, root);
return prevIsInline && nextIsInline;
};
const isBookmarkNode$2 = (node) =>
isSpan(node) && node.getAttribute("data-mce-type") === "bookmark";
const isKeepTextNode = (node, root) =>
isText$a(node) &&
node.data.length > 0 &&
surroundedByInlineContent(node, root);
const isKeepElement = (node) =>
isElement$6(node) ? node.childNodes.length > 0 : false;
const isDocument = (node) => isDocumentFragment(node) || isDocument$1(node);
const trimNode = (dom, node, root) => {
var _a;
const rootNode = root || node;
if (isElement$6(node) && isBookmarkNode$2(node)) {
return node;
}
const children = node.childNodes;
for (let i = children.length - 1; i >= 0; i--) {
trimNode(dom, children[i], rootNode);
}
if (isElement$6(node)) {
const currentChildren = node.childNodes;
if (
currentChildren.length === 1 &&
isBookmarkNode$2(currentChildren[0])
) {
(_a = node.parentNode) === null || _a === void 0
? void 0
: _a.insertBefore(currentChildren[0], node);
}
}
if (
!isDocument(node) &&
!isContent$1(node, rootNode) &&
!isKeepElement(node) &&
!isKeepTextNode(node, rootNode)
) {
dom.remove(node);
}
return node;
};
const makeMap$3 = Tools.makeMap;
const attrsCharsRegExp =
/[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
const textCharsRegExp =
/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
const rawCharsRegExp = /[<>&\"\']/g;
const entityRegExp = /([a-z0-9]+);?|&([a-z0-9]+);/gi;
const asciiMap = {
128: "\u20AC",
130: "\u201A",
131: "\u0192",
132: "\u201E",
133: "\u2026",
134: "\u2020",
135: "\u2021",
136: "\u02c6",
137: "\u2030",
138: "\u0160",
139: "\u2039",
140: "\u0152",
142: "\u017d",
145: "\u2018",
146: "\u2019",
147: "\u201C",
148: "\u201D",
149: "\u2022",
150: "\u2013",
151: "\u2014",
152: "\u02DC",
153: "\u2122",
154: "\u0161",
155: "\u203A",
156: "\u0153",
158: "\u017e",
159: "\u0178",
};
const baseEntities = {
'"': """,
"'": "'",
"<": "<",
">": ">",
"&": "&",
"`": "`",
};
const reverseEntities = {
"<": "<",
">": ">",
"&": "&",
""": '"',
"'": `'`,
};
const nativeDecode = (text) => {
const elm = SugarElement.fromTag("div").dom;
elm.innerHTML = text;
return elm.textContent || elm.innerText || text;
};
const buildEntitiesLookup = (items, radix) => {
const lookup = {};
if (items) {
const itemList = items.split(",");
radix = radix || 10;
for (let i = 0; i < itemList.length; i += 2) {
const chr = String.fromCharCode(parseInt(itemList[i], radix));
if (!baseEntities[chr]) {
const entity = "&" + itemList[i + 1] + ";";
lookup[chr] = entity;
lookup[entity] = chr;
}
}
return lookup;
} else {
return undefined;
}
};
const namedEntities = buildEntitiesLookup(
"50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy," +
"5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute," +
"5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34," +
"5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil," +
"68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde," +
"6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute," +
"6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml," +
"75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc," +
"7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash," +
"7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta," +
"sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu," +
"st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi," +
"t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota," +
"tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau," +
"u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip," +
"81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym," +
"8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr," +
"8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod," +
"8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup," +
"8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4," +
"nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob," +
"rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0," +
"Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm," +
"80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger," +
"811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",
32
);
const encodeRaw = (text, attr) =>
text.replace(attr ? attrsCharsRegExp : textCharsRegExp, (chr) => {
return baseEntities[chr] || chr;
});
const encodeAllRaw = (text) =>
("" + text).replace(rawCharsRegExp, (chr) => {
return baseEntities[chr] || chr;
});
const encodeNumeric = (text, attr) =>
text.replace(attr ? attrsCharsRegExp : textCharsRegExp, (chr) => {
if (chr.length > 1) {
return (
"" +
((chr.charCodeAt(0) - 55296) * 1024 +
(chr.charCodeAt(1) - 56320) +
65536) +
";"
);
}
return baseEntities[chr] || "" + chr.charCodeAt(0) + ";";
});
const encodeNamed = (text, attr, entities) => {
const resolveEntities = entities || namedEntities;
return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, (chr) => {
return baseEntities[chr] || resolveEntities[chr] || chr;
});
};
const getEncodeFunc = (name, entities) => {
const entitiesMap = buildEntitiesLookup(entities) || namedEntities;
const encodeNamedAndNumeric = (text, attr) =>
text.replace(attr ? attrsCharsRegExp : textCharsRegExp, (chr) => {
if (baseEntities[chr] !== undefined) {
return baseEntities[chr];
}
if (entitiesMap[chr] !== undefined) {
return entitiesMap[chr];
}
if (chr.length > 1) {
return (
"" +
((chr.charCodeAt(0) - 55296) * 1024 +
(chr.charCodeAt(1) - 56320) +
65536) +
";"
);
}
return "" + chr.charCodeAt(0) + ";";
});
const encodeCustomNamed = (text, attr) => {
return encodeNamed(text, attr, entitiesMap);
};
const nameMap = makeMap$3(name.replace(/\+/g, ","));
if (nameMap.named && nameMap.numeric) {
return encodeNamedAndNumeric;
}
if (nameMap.named) {
if (entities) {
return encodeCustomNamed;
}
return encodeNamed;
}
if (nameMap.numeric) {
return encodeNumeric;
}
return encodeRaw;
};
const decode = (text) =>
text.replace(entityRegExp, (all, numeric) => {
if (numeric) {
if (numeric.charAt(0).toLowerCase() === "x") {
numeric = parseInt(numeric.substr(1), 16);
} else {
numeric = parseInt(numeric, 10);
}
if (numeric > 65535) {
numeric -= 65536;
return String.fromCharCode(
55296 + (numeric >> 10),
56320 + (numeric & 1023)
);
}
return asciiMap[numeric] || String.fromCharCode(numeric);
}
return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
});
const Entities = {
encodeRaw,
encodeAllRaw,
encodeNumeric,
encodeNamed,
getEncodeFunc,
decode,
};
const split$1 = (items, delim) => {
items = Tools.trim(items);
return items ? items.split(delim || " ") : [];
};
const patternToRegExp = (str) =>
new RegExp("^" + str.replace(/([?+*])/g, ".$1") + "$");
const parseCustomElementsRules = (value) => {
const customElementRegExp = /^(~)?(.+)$/;
return bind$3(split$1(value, ","), (rule) => {
const matches = customElementRegExp.exec(rule);
if (matches) {
const inline = matches[1] === "~";
const cloneName = inline ? "span" : "div";
const name = matches[2];
return [
{
inline,
cloneName,
name,
},
];
} else {
return [];
}
});
};
const getElementSetsAsStrings = (type) => {
let globalAttributes, blockContent;
let phrasingContent, flowContent;
globalAttributes = "id accesskey class dir lang style tabindex title role";
blockContent =
"address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul";
phrasingContent =
"a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd " +
"label map noscript object q s samp script select small span strong sub sup " +
"textarea u var #text #comment";
if (type !== "html4") {
const transparentContent = "a ins del canvas map";
globalAttributes +=
" contenteditable contextmenu draggable dropzone " +
"hidden spellcheck translate";
blockContent +=
" article aside details dialog figure main header footer hgroup section nav " +
transparentContent;
phrasingContent +=
" audio canvas command datalist mark meter output picture " +
"progress time wbr video ruby bdi keygen";
}
if (type !== "html5-strict") {
globalAttributes += " xml:lang";
const html4PhrasingContent = "acronym applet basefont big font strike tt";
phrasingContent = [phrasingContent, html4PhrasingContent].join(" ");
const html4BlockContent = "center dir isindex noframes";
blockContent = [blockContent, html4BlockContent].join(" ");
flowContent = [blockContent, phrasingContent].join(" ");
}
flowContent = flowContent || [blockContent, phrasingContent].join(" ");
return {
globalAttributes,
blockContent,
phrasingContent,
flowContent,
};
};
const makeSchema = (type) => {
const { globalAttributes, phrasingContent, flowContent } =
getElementSetsAsStrings(type);
const schema = {};
const add = (name, attributes = "", children = "") => {
const childNames = split$1(children);
const names = split$1(name);
let ni = names.length;
while (ni--) {
const attributesOrder = split$1(
[globalAttributes, attributes].join(" ")
);
schema[names[ni]] = {
attributes: mapToObject(attributesOrder, constant({})),
attributesOrder,
children: mapToObject(childNames, constant({})),
};
}
};
const addAttrs = (name, attributes) => {
const names = split$1(name);
const attrs = split$1(attributes);
let ni = names.length;
while (ni--) {
const schemaItem = schema[names[ni]];
for (let i = 0, l = attrs.length; i < l; i++) {
schemaItem.attributes[attrs[i]] = {};
schemaItem.attributesOrder.push(attrs[i]);
}
}
};
if (type !== "html5-strict") {
const html4PhrasingContent = "acronym applet basefont big font strike tt";
each$e(split$1(html4PhrasingContent), (name) => {
add(name, "", phrasingContent);
});
const html4BlockContent = "center dir isindex noframes";
each$e(split$1(html4BlockContent), (name) => {
add(name, "", flowContent);
});
}
add("html", "manifest", "head body");
add("head", "", "base command link meta noscript script style title");
add("title hr noscript br");
add("base", "href target");
add("link", "href rel media hreflang type sizes hreflang");
add("meta", "name http-equiv content charset");
add("style", "media type scoped");
add("script", "src async defer type charset");
add(
"body",
"onafterprint onbeforeprint onbeforeunload onblur onerror onfocus " +
"onhashchange onload onmessage onoffline ononline onpagehide onpageshow " +
"onpopstate onresize onscroll onstorage onunload",
flowContent
);
add("dd div", "", flowContent);
add(
"address dt caption",
"",
type === "html4" ? phrasingContent : flowContent
);
add(
"h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn",
"",
phrasingContent
);
add("blockquote", "cite", flowContent);
add("ol", "reversed start type", "li");
add("ul", "", "li");
add("li", "value", flowContent);
add("dl", "", "dt dd");
add(
"a",
"href target rel media hreflang type",
type === "html4" ? phrasingContent : flowContent
);
add("q", "cite", phrasingContent);
add("ins del", "cite datetime", flowContent);
add("img", "src sizes srcset alt usemap ismap width height");
add("iframe", "src name width height", flowContent);
add("embed", "src type width height");
add(
"object",
"data type typemustmatch name usemap form width height",
[flowContent, "param"].join(" ")
);
add("param", "name value");
add("map", "name", [flowContent, "area"].join(" "));
add("area", "alt coords shape href target rel media hreflang type");
add(
"table",
"border",
"caption colgroup thead tfoot tbody tr" + (type === "html4" ? " col" : "")
);
add("colgroup", "span", "col");
add("col", "span");
add("tbody thead tfoot", "", "tr");
add("tr", "", "td th");
add("td", "colspan rowspan headers", flowContent);
add("th", "colspan rowspan headers scope abbr", flowContent);
add(
"form",
"accept-charset action autocomplete enctype method name novalidate target",
flowContent
);
add("fieldset", "disabled form name", [flowContent, "legend"].join(" "));
add("label", "form for", phrasingContent);
add(
"input",
"accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate " +
"formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"
);
add(
"button",
"disabled form formaction formenctype formmethod formnovalidate formtarget name type value",
type === "html4" ? flowContent : phrasingContent
);
add(
"select",
"disabled form multiple name required size",
"option optgroup"
);
add("optgroup", "disabled label", "option");
add("option", "disabled label selected value");
add(
"textarea",
"cols dirname disabled form maxlength name readonly required rows wrap"
);
add("menu", "type label", [flowContent, "li"].join(" "));
add("noscript", "", flowContent);
if (type !== "html4") {
add("wbr");
add("ruby", "", [phrasingContent, "rt rp"].join(" "));
add("figcaption", "", flowContent);
add("mark rt rp summary bdi", "", phrasingContent);
add("canvas", "width height", flowContent);
add(
"video",
"src crossorigin poster preload autoplay mediagroup loop " +
"muted controls width height buffered",
[flowContent, "track source"].join(" ")
);
add(
"audio",
"src crossorigin preload autoplay mediagroup loop muted controls " +
"buffered volume",
[flowContent, "track source"].join(" ")
);
add("picture", "", "img source");
add("source", "src srcset type media sizes");
add("track", "kind src srclang label default");
add("datalist", "", [phrasingContent, "option"].join(" "));
add("article section nav aside main header footer", "", flowContent);
add("hgroup", "", "h1 h2 h3 h4 h5 h6");
add("figure", "", [flowContent, "figcaption"].join(" "));
add("time", "datetime", phrasingContent);
add("dialog", "open", flowContent);
add("command", "type label icon disabled checked radiogroup command");
add("output", "for form name", phrasingContent);
add("progress", "value max", phrasingContent);
add("meter", "value min max low high optimum", phrasingContent);
add("details", "open", [flowContent, "summary"].join(" "));
add("keygen", "autofocus challenge disabled form keytype name");
}
if (type !== "html5-strict") {
addAttrs("script", "language xml:space");
addAttrs("style", "xml:space");
addAttrs(
"object",
"declare classid code codebase codetype archive standby align border hspace vspace"
);
addAttrs("embed", "align name hspace vspace");
addAttrs("param", "valuetype type");
addAttrs("a", "charset name rev shape coords");
addAttrs("br", "clear");
addAttrs(
"applet",
"codebase archive code object alt name width height align hspace vspace"
);
addAttrs("img", "name longdesc align border hspace vspace");
addAttrs(
"iframe",
"longdesc frameborder marginwidth marginheight scrolling align"
);
addAttrs("font basefont", "size color face");
addAttrs("input", "usemap align");
addAttrs("select");
addAttrs("textarea");
addAttrs("h1 h2 h3 h4 h5 h6 div p legend caption", "align");
addAttrs("ul", "type compact");
addAttrs("li", "type");
addAttrs("ol dl menu dir", "compact");
addAttrs("pre", "width xml:space");
addAttrs("hr", "align noshade size width");
addAttrs("isindex", "prompt");
addAttrs(
"table",
"summary width frame rules cellspacing cellpadding align bgcolor"
);
addAttrs("col", "width align char charoff valign");
addAttrs("colgroup", "width align char charoff valign");
addAttrs("thead", "align char charoff valign");
addAttrs("tr", "align char charoff valign bgcolor");
addAttrs(
"th",
"axis align char charoff valign nowrap bgcolor width height"
);
addAttrs("form", "accept");
addAttrs(
"td",
"abbr axis scope align char charoff valign nowrap bgcolor width height"
);
addAttrs("tfoot", "align char charoff valign");
addAttrs("tbody", "align char charoff valign");
addAttrs("area", "nohref");
addAttrs("body", "background bgcolor text link vlink alink");
}
if (type !== "html4") {
addAttrs("input button select textarea", "autofocus");
addAttrs("input textarea", "placeholder");
addAttrs("a", "download");
addAttrs("link script img", "crossorigin");
addAttrs("img", "loading");
addAttrs("iframe", "sandbox seamless allow allowfullscreen loading");
}
if (type !== "html4") {
each$e([schema.video, schema.audio], (item) => {
delete item.children.audio;
delete item.children.video;
});
}
each$e(split$1("a form meter progress dfn"), (name) => {
if (schema[name]) {
delete schema[name].children[name];
}
});
delete schema.caption.children.table;
delete schema.script;
return schema;
};
const prefixToOperation = (prefix) => (prefix === "-" ? "remove" : "add");
const parseValidChildrenRules = (value) => {
const childRuleRegExp =
/^([+\-]?)([A-Za-z0-9_\-.\u00b7\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u037d\u037f-\u1fff\u200c-\u200d\u203f-\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]+)\[([^\]]+)]$/;
return bind$3(split$1(value, ","), (rule) => {
const matches = childRuleRegExp.exec(rule);
if (matches) {
const prefix = matches[1];
const operation = prefix ? prefixToOperation(prefix) : "replace";
const name = matches[2];
const validChildren = split$1(matches[3], "|");
return [
{
operation,
name,
validChildren,
},
];
} else {
return [];
}
});
};
const parseValidElementsAttrDataIntoElement = (attrData, targetElement) => {
const attrRuleRegExp = /^([!\-])?(\w+[\\:]:\w+|[^=~<]+)?(?:([=~<])(.*))?$/;
const hasPatternsRegExp = /[*?+]/;
const { attributes, attributesOrder } = targetElement;
return each$e(split$1(attrData, "|"), (rule) => {
const matches = attrRuleRegExp.exec(rule);
if (matches) {
const attr = {};
const attrType = matches[1];
const attrName = matches[2].replace(/[\\:]:/g, ":");
const attrPrefix = matches[3];
const value = matches[4];
if (attrType === "!") {
targetElement.attributesRequired =
targetElement.attributesRequired || [];
targetElement.attributesRequired.push(attrName);
attr.required = true;
}
if (attrType === "-") {
delete attributes[attrName];
attributesOrder.splice(Tools.inArray(attributesOrder, attrName), 1);
return;
}
if (attrPrefix) {
if (attrPrefix === "=") {
targetElement.attributesDefault =
targetElement.attributesDefault || [];
targetElement.attributesDefault.push({
name: attrName,
value,
});
attr.defaultValue = value;
} else if (attrPrefix === "~") {
targetElement.attributesForced =
targetElement.attributesForced || [];
targetElement.attributesForced.push({
name: attrName,
value,
});
attr.forcedValue = value;
} else if (attrPrefix === "<") {
attr.validValues = Tools.makeMap(value, "?");
}
}
if (hasPatternsRegExp.test(attrName)) {
const attrPattern = attr;
targetElement.attributePatterns =
targetElement.attributePatterns || [];
attrPattern.pattern = patternToRegExp(attrName);
targetElement.attributePatterns.push(attrPattern);
} else {
if (!attributes[attrName]) {
attributesOrder.push(attrName);
}
attributes[attrName] = attr;
}
}
});
};
const cloneAttributesInto = (from, to) => {
each$d(from.attributes, (value, key) => {
to.attributes[key] = value;
});
to.attributesOrder.push(...from.attributesOrder);
};
const parseValidElementsRules = (globalElement, validElements) => {
const elementRuleRegExp =
/^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)])?$/;
return bind$3(split$1(validElements, ","), (rule) => {
const matches = elementRuleRegExp.exec(rule);
if (matches) {
const prefix = matches[1];
const elementName = matches[2];
const outputName = matches[3];
const attrsPrefix = matches[4];
const attrData = matches[5];
const element = {
attributes: {},
attributesOrder: [],
};
globalElement.each((el) => cloneAttributesInto(el, element));
if (prefix === "#") {
element.paddEmpty = true;
} else if (prefix === "-") {
element.removeEmpty = true;
}
if (attrsPrefix === "!") {
element.removeEmptyAttrs = true;
}
if (attrData) {
parseValidElementsAttrDataIntoElement(attrData, element);
}
if (outputName) {
element.outputName = elementName;
}
if (elementName === "@") {
if (globalElement.isNone()) {
globalElement = Optional.some(element);
} else {
return [];
}
}
return [
outputName
? {
name: elementName,
element,
aliasName: outputName,
}
: {
name: elementName,
element,
},
];
} else {
return [];
}
});
};
const mapCache = {};
const makeMap$2 = Tools.makeMap,
each$b = Tools.each,
extend$2 = Tools.extend,
explode$2 = Tools.explode;
const createMap = (defaultValue, extendWith = {}) => {
const value = makeMap$2(
defaultValue,
" ",
makeMap$2(defaultValue.toUpperCase(), " ")
);
return extend$2(value, extendWith);
};
const getTextRootBlockElements = (schema) =>
createMap(
"td th li dt dd figcaption caption details summary",
schema.getTextBlockElements()
);
const compileElementMap = (value, mode) => {
if (value) {
const styles = {};
if (isString(value)) {
value = { "*": value };
}
each$b(value, (value, key) => {
styles[key] = styles[key.toUpperCase()] =
mode === "map" ? makeMap$2(value, /[, ]/) : explode$2(value, /[, ]/);
});
return styles;
} else {
return undefined;
}
};
const Schema = (settings = {}) => {
var _a;
const elements = {};
const children = {};
let patternElements = [];
const customElementsMap = {};
const specialElements = {};
const createLookupTable = (option, defaultValue, extendWith) => {
const value = settings[option];
if (!value) {
let newValue = mapCache[option];
if (!newValue) {
newValue = createMap(defaultValue, extendWith);
mapCache[option] = newValue;
}
return newValue;
} else {
return makeMap$2(value, /[, ]/, makeMap$2(value.toUpperCase(), /[, ]/));
}
};
const schemaType =
(_a = settings.schema) !== null && _a !== void 0 ? _a : "html5";
const schemaItems = makeSchema(schemaType);
if (settings.verify_html === false) {
settings.valid_elements = "*[*]";
}
const validStyles = compileElementMap(settings.valid_styles);
const invalidStyles = compileElementMap(settings.invalid_styles, "map");
const validClasses = compileElementMap(settings.valid_classes, "map");
const whitespaceElementsMap = createLookupTable(
"whitespace_elements",
"pre script noscript style textarea video audio iframe object code"
);
const selfClosingElementsMap = createLookupTable(
"self_closing_elements",
"colgroup dd dt li option p td tfoot th thead tr"
);
const voidElementsMap = createLookupTable(
"void_elements",
"area base basefont br col frame hr img input isindex link " +
"meta param embed source wbr track"
);
const boolAttrMap = createLookupTable(
"boolean_attributes",
"checked compact declare defer disabled ismap multiple nohref noresize " +
"noshade nowrap readonly selected autoplay loop controls allowfullscreen"
);
const nonEmptyOrMoveCaretBeforeOnEnter =
"td th iframe video audio object script code";
const nonEmptyElementsMap = createLookupTable(
"non_empty_elements",
nonEmptyOrMoveCaretBeforeOnEnter + " pre",
voidElementsMap
);
const moveCaretBeforeOnEnterElementsMap = createLookupTable(
"move_caret_before_on_enter_elements",
nonEmptyOrMoveCaretBeforeOnEnter + " table",
voidElementsMap
);
const textBlockElementsMap = createLookupTable(
"text_block_elements",
"h1 h2 h3 h4 h5 h6 p div address pre form " +
"blockquote center dir fieldset header footer article section hgroup aside main nav figure"
);
const blockElementsMap = createLookupTable(
"block_elements",
"hr table tbody thead tfoot " +
"th tr td li ol ul caption dl dt dd noscript menu isindex option " +
"datalist select optgroup figcaption details summary",
textBlockElementsMap
);
const textInlineElementsMap = createLookupTable(
"text_inline_elements",
"span strong b em i font s strike u var cite " +
"dfn code mark q sup sub samp"
);
const transparentElementsMap = createLookupTable(
"transparent_elements",
"a ins del canvas map"
);
each$b(
"script noscript iframe noframes noembed title style textarea xmp plaintext".split(
" "
),
(name) => {
specialElements[name] = new RegExp("" + name + "[^>]*>", "gi");
}
);
const addValidElements = (validElements) => {
const globalElement = Optional.from(elements["@"]);
const hasPatternsRegExp = /[*?+]/;
each$e(
parseValidElementsRules(
globalElement,
validElements !== null && validElements !== void 0
? validElements
: ""
),
({ name, element, aliasName }) => {
if (aliasName) {
elements[aliasName] = element;
}
if (hasPatternsRegExp.test(name)) {
const patternElement = element;
patternElement.pattern = patternToRegExp(name);
patternElements.push(patternElement);
} else {
elements[name] = element;
}
}
);
};
const setValidElements = (validElements) => {
patternElements = [];
each$e(keys(elements), (name) => {
delete elements[name];
});
addValidElements(validElements);
};
const addCustomElements = (customElements) => {
delete mapCache.text_block_elements;
delete mapCache.block_elements;
each$e(
parseCustomElementsRules(
customElements !== null && customElements !== void 0
? customElements
: ""
),
({ inline, name, cloneName }) => {
children[name] = children[cloneName];
customElementsMap[name] = cloneName;
nonEmptyElementsMap[name.toUpperCase()] = {};
nonEmptyElementsMap[name] = {};
if (!inline) {
blockElementsMap[name.toUpperCase()] = {};
blockElementsMap[name] = {};
}
if (!elements[name]) {
let customRule = elements[cloneName];
customRule = extend$2({}, customRule);
delete customRule.removeEmptyAttrs;
delete customRule.removeEmpty;
elements[name] = customRule;
}
each$d(children, (element, elmName) => {
if (element[cloneName]) {
children[elmName] = element = extend$2({}, children[elmName]);
element[name] = element[cloneName];
}
});
}
);
};
const addValidChildren = (validChildren) => {
each$e(
parseValidChildrenRules(
validChildren !== null && validChildren !== void 0
? validChildren
: ""
),
({ operation, name, validChildren }) => {
const parent =
operation === "replace" ? { "#comment": {} } : children[name];
each$e(validChildren, (child) => {
if (operation === "remove") {
delete parent[child];
} else {
parent[child] = {};
}
});
children[name] = parent;
}
);
};
const getElementRule = (name) => {
const element = elements[name];
if (element) {
return element;
}
let i = patternElements.length;
while (i--) {
const patternElement = patternElements[i];
if (patternElement.pattern.test(name)) {
return patternElement;
}
}
return undefined;
};
if (!settings.valid_elements) {
each$b(schemaItems, (element, name) => {
elements[name] = {
attributes: element.attributes,
attributesOrder: element.attributesOrder,
};
children[name] = element.children;
});
each$b(split$1("strong/b em/i"), (item) => {
const items = split$1(item, "/");
elements[items[1]].outputName = items[0];
});
each$b(textInlineElementsMap, (_val, name) => {
if (elements[name]) {
if (settings.padd_empty_block_inline_children) {
elements[name].paddInEmptyBlock = true;
}
elements[name].removeEmpty = true;
}
});
each$b(split$1("ol ul blockquote a table tbody"), (name) => {
if (elements[name]) {
elements[name].removeEmpty = true;
}
});
each$b(
split$1("p h1 h2 h3 h4 h5 h6 th td pre div address caption li summary"),
(name) => {
if (elements[name]) {
elements[name].paddEmpty = true;
}
}
);
each$b(split$1("span"), (name) => {
elements[name].removeEmptyAttrs = true;
});
} else {
setValidElements(settings.valid_elements);
each$b(schemaItems, (element, name) => {
children[name] = element.children;
});
}
addCustomElements(settings.custom_elements);
addValidChildren(settings.valid_children);
addValidElements(settings.extended_valid_elements);
addValidChildren("+ol[ul|ol],+ul[ul|ol]");
each$b(
{
dd: "dl",
dt: "dl",
li: "ul ol",
td: "tr",
th: "tr",
tr: "tbody thead tfoot",
tbody: "table",
thead: "table",
tfoot: "table",
legend: "fieldset",
area: "map",
param: "video audio object",
},
(parents, item) => {
if (elements[item]) {
elements[item].parentsRequired = split$1(parents);
}
}
);
if (settings.invalid_elements) {
each$b(explode$2(settings.invalid_elements), (item) => {
if (elements[item]) {
delete elements[item];
}
});
}
if (!getElementRule("span")) {
addValidElements("span[!data-mce-type|*]");
}
const getValidStyles = constant(validStyles);
const getInvalidStyles = constant(invalidStyles);
const getValidClasses = constant(validClasses);
const getBoolAttrs = constant(boolAttrMap);
const getBlockElements = constant(blockElementsMap);
const getTextBlockElements = constant(textBlockElementsMap);
const getTextInlineElements = constant(textInlineElementsMap);
const getVoidElements = constant(Object.seal(voidElementsMap));
const getSelfClosingElements = constant(selfClosingElementsMap);
const getNonEmptyElements = constant(nonEmptyElementsMap);
const getMoveCaretBeforeOnEnterElements = constant(
moveCaretBeforeOnEnterElementsMap
);
const getWhitespaceElements = constant(whitespaceElementsMap);
const getTransparentElements = constant(transparentElementsMap);
const getSpecialElements = constant(Object.seal(specialElements));
const isValidChild = (name, child) => {
const parent = children[name.toLowerCase()];
return !!(parent && parent[child.toLowerCase()]);
};
const isValid = (name, attr) => {
const rule = getElementRule(name);
if (rule) {
if (attr) {
if (rule.attributes[attr]) {
return true;
}
const attrPatterns = rule.attributePatterns;
if (attrPatterns) {
let i = attrPatterns.length;
while (i--) {
if (attrPatterns[i].pattern.test(attr)) {
return true;
}
}
}
} else {
return true;
}
}
return false;
};
const getCustomElements = constant(customElementsMap);
return {
type: schemaType,
children,
elements,
getValidStyles,
getValidClasses,
getBlockElements,
getInvalidStyles,
getVoidElements,
getTextBlockElements,
getTextInlineElements,
getBoolAttrs,
getElementRule,
getSelfClosingElements,
getNonEmptyElements,
getMoveCaretBeforeOnEnterElements,
getWhitespaceElements,
getTransparentElements,
getSpecialElements,
isValidChild,
isValid,
getCustomElements,
addValidElements,
setValidElements,
addCustomElements,
addValidChildren,
};
};
const Styles = (settings = {}, schema) => {
const urlOrStrRegExp =
/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi;
const styleRegExp = /\s*([^:]+):\s*([^;]+);?/g;
const trimRightRegExp = /\s+$/;
const encodingLookup = {};
let validStyles;
let invalidStyles;
const invisibleChar = zeroWidth;
if (schema) {
validStyles = schema.getValidStyles();
invalidStyles = schema.getInvalidStyles();
}
const encodingItems = (`\\" \\' \\; \\: ; : ` + invisibleChar).split(" ");
for (let i = 0; i < encodingItems.length; i++) {
encodingLookup[encodingItems[i]] = invisibleChar + i;
encodingLookup[invisibleChar + i] = encodingItems[i];
}
const self = {
parse: (css) => {
const styles = {};
let isEncoded = false;
const urlConverter = settings.url_converter;
const urlConverterScope = settings.url_converter_scope || self;
const compress = (prefix, suffix, noJoin) => {
const top = styles[prefix + "-top" + suffix];
if (!top) {
return;
}
const right = styles[prefix + "-right" + suffix];
if (!right) {
return;
}
const bottom = styles[prefix + "-bottom" + suffix];
if (!bottom) {
return;
}
const left = styles[prefix + "-left" + suffix];
if (!left) {
return;
}
const box = [top, right, bottom, left];
let i = box.length - 1;
while (i--) {
if (box[i] !== box[i + 1]) {
break;
}
}
if (i > -1 && noJoin) {
return;
}
styles[prefix + suffix] = i === -1 ? box[0] : box.join(" ");
delete styles[prefix + "-top" + suffix];
delete styles[prefix + "-right" + suffix];
delete styles[prefix + "-bottom" + suffix];
delete styles[prefix + "-left" + suffix];
};
const canCompress = (key) => {
const value = styles[key];
if (!value) {
return;
}
const values = value.indexOf(",") > -1 ? [value] : value.split(" ");
let i = values.length;
while (i--) {
if (values[i] !== values[0]) {
return false;
}
}
styles[key] = values[0];
return true;
};
const compress2 = (target, a, b, c) => {
if (!canCompress(a)) {
return;
}
if (!canCompress(b)) {
return;
}
if (!canCompress(c)) {
return;
}
styles[target] = styles[a] + " " + styles[b] + " " + styles[c];
delete styles[a];
delete styles[b];
delete styles[c];
};
const encode = (str) => {
isEncoded = true;
return encodingLookup[str];
};
const decode = (str, keepSlashes) => {
if (isEncoded) {
str = str.replace(/\uFEFF[0-9]/g, (str) => {
return encodingLookup[str];
});
}
if (!keepSlashes) {
str = str.replace(/\\([\'\";:])/g, "$1");
}
return str;
};
const decodeSingleHexSequence = (escSeq) => {
return String.fromCharCode(parseInt(escSeq.slice(1), 16));
};
const decodeHexSequences = (value) => {
return value.replace(/\\[0-9a-f]+/gi, decodeSingleHexSequence);
};
const processUrl = (match, url, url2, url3, str, str2) => {
str = str || str2;
if (str) {
str = decode(str);
return `'` + str.replace(/\'/g, `\\'`) + `'`;
}
url = decode(url || url2 || url3 || "");
if (!settings.allow_script_urls) {
const scriptUrl = url.replace(/[\s\r\n]+/g, "");
if (/(java|vb)script:/i.test(scriptUrl)) {
return "";
}
if (
!settings.allow_svg_data_urls &&
/^data:image\/svg/i.test(scriptUrl)
) {
return "";
}
}
if (urlConverter) {
url = urlConverter.call(urlConverterScope, url, "style");
}
return `url('` + url.replace(/\'/g, `\\'`) + `')`;
};
if (css) {
css = css.replace(/[\u0000-\u001F]/g, "");
css = css
.replace(/\\[\"\';:\uFEFF]/g, encode)
.replace(/\"[^\"]+\"|\'[^\']+\'/g, (str) => {
return str.replace(/[;:]/g, encode);
});
let matches;
while ((matches = styleRegExp.exec(css))) {
styleRegExp.lastIndex = matches.index + matches[0].length;
let name = matches[1].replace(trimRightRegExp, "").toLowerCase();
let value = matches[2].replace(trimRightRegExp, "");
if (name && value) {
name = decodeHexSequences(name);
value = decodeHexSequences(value);
if (
name.indexOf(invisibleChar) !== -1 ||
name.indexOf('"') !== -1
) {
continue;
}
if (
!settings.allow_script_urls &&
(name === "behavior" || /expression\s*\(|\/\*|\*\//.test(value))
) {
continue;
}
if (name === "font-weight" && value === "700") {
value = "bold";
} else if (name === "color" || name === "background-color") {
value = value.toLowerCase();
}
value = value.replace(urlOrStrRegExp, processUrl);
styles[name] = isEncoded ? decode(value, true) : value;
}
}
compress("border", "", true);
compress("border", "-width");
compress("border", "-color");
compress("border", "-style");
compress("padding", "");
compress("margin", "");
compress2("border", "border-width", "border-style", "border-color");
if (styles.border === "medium none") {
delete styles.border;
}
if (styles["border-image"] === "none") {
delete styles["border-image"];
}
}
return styles;
},
serialize: (styles, elementName) => {
let css = "";
const serializeStyles = (elemName, validStyleList) => {
const styleList = validStyleList[elemName];
if (styleList) {
for (let i = 0, l = styleList.length; i < l; i++) {
const name = styleList[i];
const value = styles[name];
if (value) {
css += (css.length > 0 ? " " : "") + name + ": " + value + ";";
}
}
}
};
const isValid = (name, elemName) => {
if (!invalidStyles || !elemName) {
return true;
}
let styleMap = invalidStyles["*"];
if (styleMap && styleMap[name]) {
return false;
}
styleMap = invalidStyles[elemName];
return !(styleMap && styleMap[name]);
};
if (elementName && validStyles) {
serializeStyles("*", validStyles);
serializeStyles(elementName, validStyles);
} else {
each$d(styles, (value, name) => {
if (value && isValid(name, elementName)) {
css += (css.length > 0 ? " " : "") + name + ": " + value + ";";
}
});
}
return css;
},
};
return self;
};
const deprecated = {
keyLocation: true,
layerX: true,
layerY: true,
returnValue: true,
webkitMovementX: true,
webkitMovementY: true,
keyIdentifier: true,
mozPressure: true,
};
const isNativeEvent = (event) =>
event instanceof Event || isFunction(event.initEvent);
const hasIsDefaultPrevented = (event) =>
event.isDefaultPrevented === always || event.isDefaultPrevented === never;
const needsNormalizing = (event) =>
isNullable(event.preventDefault) || isNativeEvent(event);
const clone$3 = (originalEvent, data) => {
const event = data !== null && data !== void 0 ? data : {};
for (const name in originalEvent) {
if (!has$2(deprecated, name)) {
event[name] = originalEvent[name];
}
}
if (isNonNullable(originalEvent.composedPath)) {
event.composedPath = () => originalEvent.composedPath();
}
return event;
};
const normalize$3 = (type, originalEvent, fallbackTarget, data) => {
var _a;
const event = clone$3(originalEvent, data);
event.type = type;
if (isNullable(event.target)) {
event.target =
(_a = event.srcElement) !== null && _a !== void 0 ? _a : fallbackTarget;
}
if (needsNormalizing(originalEvent)) {
event.preventDefault = () => {
event.defaultPrevented = true;
event.isDefaultPrevented = always;
if (isFunction(originalEvent.preventDefault)) {
originalEvent.preventDefault();
}
};
event.stopPropagation = () => {
event.cancelBubble = true;
event.isPropagationStopped = always;
if (isFunction(originalEvent.stopPropagation)) {
originalEvent.stopPropagation();
}
};
event.stopImmediatePropagation = () => {
event.isImmediatePropagationStopped = always;
event.stopPropagation();
};
if (!hasIsDefaultPrevented(event)) {
event.isDefaultPrevented =
event.defaultPrevented === true ? always : never;
event.isPropagationStopped =
event.cancelBubble === true ? always : never;
event.isImmediatePropagationStopped = never;
}
}
return event;
};
const eventExpandoPrefix = "mce-data-";
const mouseEventRe = /^(?:mouse|contextmenu)|click/;
const addEvent = (target, name, callback, capture) => {
target.addEventListener(name, callback, capture || false);
};
const removeEvent = (target, name, callback, capture) => {
target.removeEventListener(name, callback, capture || false);
};
const isMouseEvent = (event) =>
isNonNullable(event) && mouseEventRe.test(event.type);
const fix = (originalEvent, data) => {
const event = normalize$3(
originalEvent.type,
originalEvent,
document,
data
);
if (
isMouseEvent(originalEvent) &&
isUndefined(originalEvent.pageX) &&
!isUndefined(originalEvent.clientX)
) {
const eventDoc = event.target.ownerDocument || document;
const doc = eventDoc.documentElement;
const body = eventDoc.body;
const mouseEvent = event;
mouseEvent.pageX =
originalEvent.clientX +
((doc && doc.scrollLeft) || (body && body.scrollLeft) || 0) -
((doc && doc.clientLeft) || (body && body.clientLeft) || 0);
mouseEvent.pageY =
originalEvent.clientY +
((doc && doc.scrollTop) || (body && body.scrollTop) || 0) -
((doc && doc.clientTop) || (body && body.clientTop) || 0);
}
return event;
};
const bindOnReady = (win, callback, eventUtils) => {
const doc = win.document,
event = { type: "ready" };
if (eventUtils.domLoaded) {
callback(event);
return;
}
const isDocReady = () => {
return (
doc.readyState === "complete" ||
(doc.readyState === "interactive" && doc.body)
);
};
const readyHandler = () => {
removeEvent(win, "DOMContentLoaded", readyHandler);
removeEvent(win, "load", readyHandler);
if (!eventUtils.domLoaded) {
eventUtils.domLoaded = true;
callback(event);
}
win = null;
};
if (isDocReady()) {
readyHandler();
} else {
addEvent(win, "DOMContentLoaded", readyHandler);
}
if (!eventUtils.domLoaded) {
addEvent(win, "load", readyHandler);
}
};
class EventUtils {
constructor() {
this.domLoaded = false;
this.events = {};
this.count = 1;
this.expando = eventExpandoPrefix + (+new Date()).toString(32);
this.hasFocusIn = "onfocusin" in document.documentElement;
this.count = 1;
}
bind(target, names, callback, scope) {
const self = this;
let callbackList;
const win = window;
const defaultNativeHandler = (evt) => {
self.executeHandlers(fix(evt || win.event), id);
};
if (!target || isText$a(target) || isComment(target)) {
return callback;
}
let id;
if (!target[self.expando]) {
id = self.count++;
target[self.expando] = id;
self.events[id] = {};
} else {
id = target[self.expando];
}
scope = scope || target;
const namesList = names.split(" ");
let i = namesList.length;
while (i--) {
let name = namesList[i];
let nativeHandler = defaultNativeHandler;
let capture = false;
let fakeName = false;
if (name === "DOMContentLoaded") {
name = "ready";
}
if (
self.domLoaded &&
name === "ready" &&
target.readyState === "complete"
) {
callback.call(scope, fix({ type: name }));
continue;
}
if (!self.hasFocusIn && (name === "focusin" || name === "focusout")) {
capture = true;
fakeName = name === "focusin" ? "focus" : "blur";
nativeHandler = (evt) => {
const event = fix(evt || win.event);
event.type = event.type === "focus" ? "focusin" : "focusout";
self.executeHandlers(event, id);
};
}
callbackList = self.events[id][name];
if (!callbackList) {
self.events[id][name] = callbackList = [
{
func: callback,
scope,
},
];
callbackList.fakeName = fakeName;
callbackList.capture = capture;
callbackList.nativeHandler = nativeHandler;
if (name === "ready") {
bindOnReady(target, nativeHandler, self);
} else {
addEvent(target, fakeName || name, nativeHandler, capture);
}
} else {
if (name === "ready" && self.domLoaded) {
callback(fix({ type: name }));
} else {
callbackList.push({
func: callback,
scope,
});
}
}
}
target = callbackList = null;
return callback;
}
unbind(target, names, callback) {
if (!target || isText$a(target) || isComment(target)) {
return this;
}
const id = target[this.expando];
if (id) {
let eventMap = this.events[id];
if (names) {
const namesList = names.split(" ");
let i = namesList.length;
while (i--) {
const name = namesList[i];
const callbackList = eventMap[name];
if (callbackList) {
if (callback) {
let ci = callbackList.length;
while (ci--) {
if (callbackList[ci].func === callback) {
const nativeHandler = callbackList.nativeHandler;
const fakeName = callbackList.fakeName,
capture = callbackList.capture;
const newCallbackList = callbackList
.slice(0, ci)
.concat(callbackList.slice(ci + 1));
newCallbackList.nativeHandler = nativeHandler;
newCallbackList.fakeName = fakeName;
newCallbackList.capture = capture;
eventMap[name] = newCallbackList;
}
}
}
if (!callback || callbackList.length === 0) {
delete eventMap[name];
removeEvent(
target,
callbackList.fakeName || name,
callbackList.nativeHandler,
callbackList.capture
);
}
}
}
} else {
each$d(eventMap, (callbackList, name) => {
removeEvent(
target,
callbackList.fakeName || name,
callbackList.nativeHandler,
callbackList.capture
);
});
eventMap = {};
}
for (const name in eventMap) {
if (has$2(eventMap, name)) {
return this;
}
}
delete this.events[id];
try {
delete target[this.expando];
} catch (ex) {
target[this.expando] = null;
}
}
return this;
}
fire(target, name, args) {
return this.dispatch(target, name, args);
}
dispatch(target, name, args) {
if (!target || isText$a(target) || isComment(target)) {
return this;
}
const event = fix(
{
type: name,
target,
},
args
);
do {
const id = target[this.expando];
if (id) {
this.executeHandlers(event, id);
}
target =
target.parentNode ||
target.ownerDocument ||
target.defaultView ||
target.parentWindow;
} while (target && !event.isPropagationStopped());
return this;
}
clean(target) {
if (!target || isText$a(target) || isComment(target)) {
return this;
}
if (target[this.expando]) {
this.unbind(target);
}
if (!target.getElementsByTagName) {
target = target.document;
}
if (target && target.getElementsByTagName) {
this.unbind(target);
const children = target.getElementsByTagName("*");
let i = children.length;
while (i--) {
target = children[i];
if (target[this.expando]) {
this.unbind(target);
}
}
}
return this;
}
destroy() {
this.events = {};
}
cancel(e) {
if (e) {
e.preventDefault();
e.stopImmediatePropagation();
}
return false;
}
executeHandlers(evt, id) {
const container = this.events[id];
const callbackList = container && container[evt.type];
if (callbackList) {
for (let i = 0, l = callbackList.length; i < l; i++) {
const callback = callbackList[i];
if (callback && callback.func.call(callback.scope, evt) === false) {
evt.preventDefault();
}
if (evt.isImmediatePropagationStopped()) {
return;
}
}
}
}
}
EventUtils.Event = new EventUtils();
const each$a = Tools.each;
const grep = Tools.grep;
const internalStyleName = "data-mce-style";
const numericalCssMap = Tools.makeMap(
"fill-opacity font-weight line-height opacity orphans widows z-index zoom",
" "
);
const legacySetAttribute = (elm, name, value) => {
if (isNullable(value) || value === "") {
remove$a(elm, name);
} else {
set$3(elm, name, value);
}
};
const camelCaseToHyphens = (name) =>
name.replace(/[A-Z]/g, (v) => "-" + v.toLowerCase());
const findNodeIndex = (node, normalized) => {
let idx = 0;
if (node) {
for (
let lastNodeType = node.nodeType, tempNode = node.previousSibling;
tempNode;
tempNode = tempNode.previousSibling
) {
const nodeType = tempNode.nodeType;
if (normalized && isText$a(tempNode)) {
if (nodeType === lastNodeType || !tempNode.data.length) {
continue;
}
}
idx++;
lastNodeType = nodeType;
}
}
return idx;
};
const updateInternalStyleAttr = (styles, elm) => {
const rawValue = get$9(elm, "style");
const value = styles.serialize(styles.parse(rawValue), name(elm));
legacySetAttribute(elm, internalStyleName, value);
};
const convertStyleToString = (cssValue, cssName) => {
if (isNumber(cssValue)) {
return has$2(numericalCssMap, cssName) ? cssValue + "" : cssValue + "px";
} else {
return cssValue;
}
};
const applyStyle$1 = ($elm, cssName, cssValue) => {
const normalizedName = camelCaseToHyphens(cssName);
if (isNullable(cssValue) || cssValue === "") {
remove$6($elm, normalizedName);
} else {
set$2(
$elm,
normalizedName,
convertStyleToString(cssValue, normalizedName)
);
}
};
const setupAttrHooks = (styles, settings, getContext) => {
const keepValues = settings.keep_values;
const keepUrlHook = {
set: (elm, value, name) => {
const sugarElm = SugarElement.fromDom(elm);
if (isFunction(settings.url_converter) && isNonNullable(value)) {
value = settings.url_converter.call(
settings.url_converter_scope || getContext(),
String(value),
name,
elm
);
}
const internalName = "data-mce-" + name;
legacySetAttribute(sugarElm, internalName, value);
legacySetAttribute(sugarElm, name, value);
},
get: (elm, name) => {
const sugarElm = SugarElement.fromDom(elm);
return get$9(sugarElm, "data-mce-" + name) || get$9(sugarElm, name);
},
};
const attrHooks = {
style: {
set: (elm, value) => {
const sugarElm = SugarElement.fromDom(elm);
if (keepValues) {
legacySetAttribute(sugarElm, internalStyleName, value);
}
remove$a(sugarElm, "style");
if (isString(value)) {
setAll(sugarElm, styles.parse(value));
}
},
get: (elm) => {
const sugarElm = SugarElement.fromDom(elm);
const value =
get$9(sugarElm, internalStyleName) || get$9(sugarElm, "style");
return styles.serialize(styles.parse(value), name(sugarElm));
},
},
};
if (keepValues) {
attrHooks.href = attrHooks.src = keepUrlHook;
}
return attrHooks;
};
const DOMUtils = (doc, settings = {}) => {
const addedStyles = {};
const win = window;
const files = {};
let counter = 0;
const stdMode = true;
const boxModel = true;
const styleSheetLoader = instance.forElement(SugarElement.fromDom(doc), {
contentCssCors: settings.contentCssCors,
referrerPolicy: settings.referrerPolicy,
});
const boundEvents = [];
const schema = settings.schema ? settings.schema : Schema({});
const styles = Styles(
{
url_converter: settings.url_converter,
url_converter_scope: settings.url_converter_scope,
},
settings.schema
);
const events = settings.ownEvents ? new EventUtils() : EventUtils.Event;
const blockElementsMap = schema.getBlockElements();
const isBlock = (node) => {
if (isString(node)) {
return has$2(blockElementsMap, node);
} else {
return (
isElement$6(node) &&
(has$2(blockElementsMap, node.nodeName) ||
isTransparentBlock(schema, node))
);
}
};
const get = (elm) =>
elm && doc && isString(elm) ? doc.getElementById(elm) : elm;
const _get = (elm) => {
const value = get(elm);
return isNonNullable(value) ? SugarElement.fromDom(value) : null;
};
const getAttrib = (elm, name, defaultVal = "") => {
let value;
const $elm = _get(elm);
if (isNonNullable($elm) && isElement$7($elm)) {
const hook = attrHooks[name];
if (hook && hook.get) {
value = hook.get($elm.dom, name);
} else {
value = get$9($elm, name);
}
}
return isNonNullable(value) ? value : defaultVal;
};
const getAttribs = (elm) => {
const node = get(elm);
return isNullable(node) ? [] : node.attributes;
};
const setAttrib = (elm, name, value) => {
run(elm, (e) => {
if (isElement$6(e)) {
const $elm = SugarElement.fromDom(e);
const val = value === "" ? null : value;
const originalValue = get$9($elm, name);
const hook = attrHooks[name];
if (hook && hook.set) {
hook.set($elm.dom, val, name);
} else {
legacySetAttribute($elm, name, val);
}
if (originalValue !== val && settings.onSetAttrib) {
settings.onSetAttrib({
attrElm: $elm.dom,
attrName: name,
attrValue: val,
});
}
}
});
};
const clone = (node, deep) => {
return node.cloneNode(deep);
};
const getRoot = () => settings.root_element || doc.body;
const getViewPort = (argWin) => {
const vp = getBounds(argWin);
return {
x: vp.x,
y: vp.y,
w: vp.width,
h: vp.height,
};
};
const getPos$1 = (elm, rootElm) => getPos(doc.body, get(elm), rootElm);
const setStyle = (elm, name, value) => {
run(elm, (e) => {
const $elm = SugarElement.fromDom(e);
applyStyle$1($elm, name, value);
if (settings.update_styles) {
updateInternalStyleAttr(styles, $elm);
}
});
};
const setStyles = (elm, stylesArg) => {
run(elm, (e) => {
const $elm = SugarElement.fromDom(e);
each$d(stylesArg, (v, n) => {
applyStyle$1($elm, n, v);
});
if (settings.update_styles) {
updateInternalStyleAttr(styles, $elm);
}
});
};
const getStyle = (elm, name, computed) => {
const $elm = get(elm);
if (isNullable($elm) || !isElement$6($elm)) {
return undefined;
}
if (computed) {
return get$7(SugarElement.fromDom($elm), camelCaseToHyphens(name));
} else {
name = name.replace(/-(\D)/g, (a, b) => b.toUpperCase());
if (name === "float") {
name = "cssFloat";
}
return $elm.style ? $elm.style[name] : undefined;
}
};
const getSize = (elm) => {
const $elm = get(elm);
if (!$elm) {
return {
w: 0,
h: 0,
};
}
let w = getStyle($elm, "width");
let h = getStyle($elm, "height");
if (!w || w.indexOf("px") === -1) {
w = "0";
}
if (!h || h.indexOf("px") === -1) {
h = "0";
}
return {
w: parseInt(w, 10) || $elm.offsetWidth || $elm.clientWidth,
h: parseInt(h, 10) || $elm.offsetHeight || $elm.clientHeight,
};
};
const getRect = (elm) => {
const $elm = get(elm);
const pos = getPos$1($elm);
const size = getSize($elm);
return {
x: pos.x,
y: pos.y,
w: size.w,
h: size.h,
};
};
const is = (elm, selector) => {
if (!elm) {
return false;
}
const elms = isArray$1(elm) ? elm : [elm];
return exists(elms, (e) => {
return is$1(SugarElement.fromDom(e), selector);
});
};
const getParents = (elm, selector, root, collect) => {
const result = [];
let node = get(elm);
collect = collect === undefined;
const resolvedRoot =
root || (getRoot().nodeName !== "BODY" ? getRoot().parentNode : null);
if (isString(selector)) {
if (selector === "*") {
selector = isElement$6;
} else {
const selectorVal = selector;
selector = (node) => is(node, selectorVal);
}
}
while (node) {
if (
node === resolvedRoot ||
isNullable(node.nodeType) ||
isDocument$1(node) ||
isDocumentFragment(node)
) {
break;
}
if (!selector || selector(node)) {
if (collect) {
result.push(node);
} else {
return [node];
}
}
node = node.parentNode;
}
return collect ? result : null;
};
const getParent = (node, selector, root) => {
const parents = getParents(node, selector, root, false);
return parents && parents.length > 0 ? parents[0] : null;
};
const _findSib = (node, selector, name) => {
let func = selector;
if (node) {
if (isString(selector)) {
func = (node) => {
return is(node, selector);
};
}
for (let tempNode = node[name]; tempNode; tempNode = tempNode[name]) {
if (isFunction(func) && func(tempNode)) {
return tempNode;
}
}
}
return null;
};
const getNext = (node, selector) => _findSib(node, selector, "nextSibling");
const getPrev = (node, selector) =>
_findSib(node, selector, "previousSibling");
const isParentNode = (node) => isFunction(node.querySelectorAll);
const select = (selector, scope) => {
var _a, _b;
const elm =
(_b =
(_a = get(scope)) !== null && _a !== void 0
? _a
: settings.root_element) !== null && _b !== void 0
? _b
: doc;
return isParentNode(elm) ? from(elm.querySelectorAll(selector)) : [];
};
const run = function (elm, func, scope) {
const context = scope !== null && scope !== void 0 ? scope : this;
if (isArray$1(elm)) {
const result = [];
each$a(elm, (e, i) => {
const node = get(e);
if (node) {
result.push(func.call(context, node, i));
}
});
return result;
} else {
const node = get(elm);
return !node ? false : func.call(context, node);
}
};
const setAttribs = (elm, attrs) => {
run(elm, ($elm) => {
each$d(attrs, (value, name) => {
setAttrib($elm, name, value);
});
});
};
const setHTML = (elm, html) => {
run(elm, (e) => {
const $elm = SugarElement.fromDom(e);
set$1($elm, html);
});
};
const add = (parentElm, name, attrs, html, create) =>
run(parentElm, (parentElm) => {
const newElm = isString(name) ? doc.createElement(name) : name;
if (isNonNullable(attrs)) {
setAttribs(newElm, attrs);
}
if (html) {
if (!isString(html) && html.nodeType) {
newElm.appendChild(html);
} else if (isString(html)) {
setHTML(newElm, html);
}
}
return !create ? parentElm.appendChild(newElm) : newElm;
});
const create = (name, attrs, html) =>
add(doc.createElement(name), name, attrs, html, true);
const decode = Entities.decode;
const encode = Entities.encodeAllRaw;
const createHTML = (name, attrs, html = "") => {
let outHtml = "<" + name;
for (const key in attrs) {
if (hasNonNullableKey(attrs, key)) {
outHtml += " " + key + '="' + encode(attrs[key]) + '"';
}
}
if (isEmpty$3(html) && has$2(schema.getVoidElements(), name)) {
return outHtml + " />";
} else {
return outHtml + ">" + html + "" + name + ">";
}
};
const createFragment = (html) => {
const container = doc.createElement("div");
const frag = doc.createDocumentFragment();
frag.appendChild(container);
if (html) {
container.innerHTML = html;
}
let node;
while ((node = container.firstChild)) {
frag.appendChild(node);
}
frag.removeChild(container);
return frag;
};
const remove = (node, keepChildren) => {
return run(node, (n) => {
const $node = SugarElement.fromDom(n);
if (keepChildren) {
each$e(children$1($node), (child) => {
if (isText$b(child) && child.dom.length === 0) {
remove$5(child);
} else {
before$3($node, child);
}
});
}
remove$5($node);
return $node.dom;
});
};
const removeAllAttribs = (e) =>
run(e, (e) => {
const attrs = e.attributes;
for (let i = attrs.length - 1; i >= 0; i--) {
e.removeAttributeNode(attrs.item(i));
}
});
const parseStyle = (cssText) => styles.parse(cssText);
const serializeStyle = (stylesArg, name) =>
styles.serialize(stylesArg, name);
const addStyle = (cssText) => {
if (self !== DOMUtils.DOM && doc === document) {
if (addedStyles[cssText]) {
return;
}
addedStyles[cssText] = true;
}
let styleElm = doc.getElementById("mceDefaultStyles");
if (!styleElm) {
styleElm = doc.createElement("style");
styleElm.id = "mceDefaultStyles";
styleElm.type = "text/css";
const head = doc.head;
if (head.firstChild) {
head.insertBefore(styleElm, head.firstChild);
} else {
head.appendChild(styleElm);
}
}
if (styleElm.styleSheet) {
styleElm.styleSheet.cssText += cssText;
} else {
styleElm.appendChild(doc.createTextNode(cssText));
}
};
const loadCSS = (urls) => {
if (!urls) {
urls = "";
}
each$e(urls.split(","), (url) => {
files[url] = true;
styleSheetLoader.load(url).catch(noop);
});
};
const toggleClass = (elm, cls, state) => {
run(elm, (e) => {
if (isElement$6(e)) {
const $elm = SugarElement.fromDom(e);
const classes = cls.split(" ");
each$e(classes, (c) => {
if (isNonNullable(state)) {
const fn = state ? add$2 : remove$7;
fn($elm, c);
} else {
toggle$1($elm, c);
}
});
}
});
};
const addClass = (elm, cls) => {
toggleClass(elm, cls, true);
};
const removeClass = (elm, cls) => {
toggleClass(elm, cls, false);
};
const hasClass = (elm, cls) => {
const $elm = _get(elm);
const classes = cls.split(" ");
return isNonNullable($elm) && forall(classes, (c) => has($elm, c));
};
const show = (elm) => {
run(elm, (e) => remove$6(SugarElement.fromDom(e), "display"));
};
const hide = (elm) => {
run(elm, (e) => set$2(SugarElement.fromDom(e), "display", "none"));
};
const isHidden = (elm) => {
const $elm = _get(elm);
return isNonNullable($elm) && is$2(getRaw($elm, "display"), "none");
};
const uniqueId = (prefix) => (!prefix ? "mce_" : prefix) + counter++;
const getOuterHTML = (elm) => {
const $elm = _get(elm);
if (isNonNullable($elm)) {
return isElement$6($elm.dom) ? $elm.dom.outerHTML : getOuter($elm);
} else {
return "";
}
};
const setOuterHTML = (elm, html) => {
run(elm, ($elm) => {
if (isElement$6($elm)) {
$elm.outerHTML = html;
}
});
};
const insertAfter = (node, reference) => {
const referenceNode = get(reference);
return run(node, (node) => {
const parent =
referenceNode === null || referenceNode === void 0
? void 0
: referenceNode.parentNode;
const nextSibling =
referenceNode === null || referenceNode === void 0
? void 0
: referenceNode.nextSibling;
if (parent) {
if (nextSibling) {
parent.insertBefore(node, nextSibling);
} else {
parent.appendChild(node);
}
}
return node;
});
};
const replace = (newElm, oldElm, keepChildren) =>
run(oldElm, (elm) => {
var _a;
const replacee = isArray$1(oldElm) ? newElm.cloneNode(true) : newElm;
if (keepChildren) {
each$a(grep(elm.childNodes), (node) => {
replacee.appendChild(node);
});
}
(_a = elm.parentNode) === null || _a === void 0
? void 0
: _a.replaceChild(replacee, elm);
return elm;
});
const rename = (elm, name) => {
if (elm.nodeName !== name.toUpperCase()) {
const newElm = create(name);
each$a(getAttribs(elm), (attrNode) => {
setAttrib(
newElm,
attrNode.nodeName,
getAttrib(elm, attrNode.nodeName)
);
});
replace(newElm, elm, true);
return newElm;
} else {
return elm;
}
};
const findCommonAncestor = (a, b) => {
let ps = a;
while (ps) {
let pe = b;
while (pe && ps !== pe) {
pe = pe.parentNode;
}
if (ps === pe) {
break;
}
ps = ps.parentNode;
}
if (!ps && a.ownerDocument) {
return a.ownerDocument.documentElement;
} else {
return ps;
}
};
const isNonEmptyElement = (node) => {
if (isElement$6(node)) {
const isNamedAnchor =
node.nodeName.toLowerCase() === "a" &&
!getAttrib(node, "href") &&
getAttrib(node, "id");
if (
getAttrib(node, "name") ||
getAttrib(node, "data-mce-bookmark") ||
isNamedAnchor
) {
return true;
}
}
return false;
};
const isEmpty = (node, elements, options) => {
let brCount = 0;
if (isNonEmptyElement(node)) {
return false;
}
const firstChild = node.firstChild;
if (firstChild) {
const walker = new DomTreeWalker(firstChild, node);
const whitespaceElements = schema ? schema.getWhitespaceElements() : {};
const nonEmptyElements =
elements || (schema ? schema.getNonEmptyElements() : null);
let tempNode = firstChild;
do {
if (isElement$6(tempNode)) {
const bogusVal = tempNode.getAttribute("data-mce-bogus");
if (bogusVal) {
tempNode = walker.next(bogusVal === "all");
continue;
}
const name = tempNode.nodeName.toLowerCase();
if (nonEmptyElements && nonEmptyElements[name]) {
if (name === "br") {
brCount++;
tempNode = walker.next();
continue;
}
return false;
}
if (isNonEmptyElement(tempNode)) {
return false;
}
}
if (isComment(tempNode)) {
return false;
}
if (
isText$a(tempNode) &&
!isWhitespaceText(tempNode.data) &&
(!(options === null || options === void 0
? void 0
: options.includeZwsp) ||
!isZwsp(tempNode.data))
) {
return false;
}
if (
isText$a(tempNode) &&
tempNode.parentNode &&
whitespaceElements[tempNode.parentNode.nodeName] &&
isWhitespaceText(tempNode.data)
) {
return false;
}
tempNode = walker.next();
} while (tempNode);
}
return brCount <= 1;
};
const createRng = () => doc.createRange();
const split = (parentElm, splitElm, replacementElm) => {
let range = createRng();
let beforeFragment;
let afterFragment;
if (
parentElm &&
splitElm &&
parentElm.parentNode &&
splitElm.parentNode
) {
const parentNode = parentElm.parentNode;
range.setStart(parentNode, findNodeIndex(parentElm));
range.setEnd(splitElm.parentNode, findNodeIndex(splitElm));
beforeFragment = range.extractContents();
range = createRng();
range.setStart(splitElm.parentNode, findNodeIndex(splitElm) + 1);
range.setEnd(parentNode, findNodeIndex(parentElm) + 1);
afterFragment = range.extractContents();
parentNode.insertBefore(trimNode(self, beforeFragment), parentElm);
if (replacementElm) {
parentNode.insertBefore(replacementElm, parentElm);
} else {
parentNode.insertBefore(splitElm, parentElm);
}
parentNode.insertBefore(trimNode(self, afterFragment), parentElm);
remove(parentElm);
return replacementElm || splitElm;
} else {
return undefined;
}
};
const bind = (target, name, func, scope) => {
if (isArray$1(target)) {
let i = target.length;
const rv = [];
while (i--) {
rv[i] = bind(target[i], name, func, scope);
}
return rv;
} else {
if (settings.collect && (target === doc || target === win)) {
boundEvents.push([target, name, func, scope]);
}
return events.bind(target, name, func, scope || self);
}
};
const unbind = (target, name, func) => {
if (isArray$1(target)) {
let i = target.length;
const rv = [];
while (i--) {
rv[i] = unbind(target[i], name, func);
}
return rv;
} else {
if (boundEvents.length > 0 && (target === doc || target === win)) {
let i = boundEvents.length;
while (i--) {
const [boundTarget, boundName, boundFunc] = boundEvents[i];
if (
target === boundTarget &&
(!name || name === boundName) &&
(!func || func === boundFunc)
) {
events.unbind(boundTarget, boundName, boundFunc);
}
}
}
return events.unbind(target, name, func);
}
};
const dispatch = (target, name, evt) => events.dispatch(target, name, evt);
const fire = (target, name, evt) => events.dispatch(target, name, evt);
const getContentEditable = (node) => {
if (node && isElement$6(node)) {
const contentEditable = node.getAttribute("data-mce-contenteditable");
if (contentEditable && contentEditable !== "inherit") {
return contentEditable;
}
return node.contentEditable !== "inherit" ? node.contentEditable : null;
} else {
return null;
}
};
const getContentEditableParent = (node) => {
const root = getRoot();
let state = null;
for (
let tempNode = node;
tempNode && tempNode !== root;
tempNode = tempNode.parentNode
) {
state = getContentEditable(tempNode);
if (state !== null) {
break;
}
}
return state;
};
const isEditable = (node) => {
if (isNonNullable(node)) {
const scope = isElement$6(node) ? node : node.parentElement;
return (
isNonNullable(scope) && isEditable$3(SugarElement.fromDom(scope))
);
} else {
return false;
}
};
const destroy = () => {
if (boundEvents.length > 0) {
let i = boundEvents.length;
while (i--) {
const [boundTarget, boundName, boundFunc] = boundEvents[i];
events.unbind(boundTarget, boundName, boundFunc);
}
}
each$d(files, (_, url) => {
styleSheetLoader.unload(url);
delete files[url];
});
};
const isChildOf = (node, parent) => {
return node === parent || parent.contains(node);
};
const dumpRng = (r) =>
"startContainer: " +
r.startContainer.nodeName +
", startOffset: " +
r.startOffset +
", endContainer: " +
r.endContainer.nodeName +
", endOffset: " +
r.endOffset;
const self = {
doc,
settings,
win,
files,
stdMode,
boxModel,
styleSheetLoader,
boundEvents,
styles,
schema,
events,
isBlock: isBlock,
root: null,
clone,
getRoot,
getViewPort,
getRect,
getSize,
getParent,
getParents: getParents,
get,
getNext,
getPrev,
select,
is,
add,
create,
createHTML,
createFragment,
remove,
setStyle,
getStyle: getStyle,
setStyles,
removeAllAttribs,
setAttrib,
setAttribs,
getAttrib,
getPos: getPos$1,
parseStyle,
serializeStyle,
addStyle,
loadCSS,
addClass,
removeClass,
hasClass,
toggleClass,
show,
hide,
isHidden,
uniqueId,
setHTML,
getOuterHTML,
setOuterHTML,
decode,
encode,
insertAfter,
replace,
rename,
findCommonAncestor,
run,
getAttribs,
isEmpty,
createRng,
nodeIndex: findNodeIndex,
split,
bind: bind,
unbind: unbind,
fire,
dispatch,
getContentEditable,
getContentEditableParent,
isEditable,
destroy,
isChildOf,
dumpRng,
};
const attrHooks = setupAttrHooks(styles, settings, constant(self));
return self;
};
DOMUtils.DOM = DOMUtils(document);
DOMUtils.nodeIndex = findNodeIndex;
const DOM$b = DOMUtils.DOM;
const QUEUED = 0;
const LOADING = 1;
const LOADED = 2;
const FAILED = 3;
class ScriptLoader {
constructor(settings = {}) {
this.states = {};
this.queue = [];
this.scriptLoadedCallbacks = {};
this.queueLoadedCallbacks = [];
this.loading = false;
this.settings = settings;
}
_setReferrerPolicy(referrerPolicy) {
this.settings.referrerPolicy = referrerPolicy;
}
loadScript(url) {
return new Promise((resolve, reject) => {
const dom = DOM$b;
let elm;
const cleanup = () => {
dom.remove(id);
if (elm) {
elm.onerror = elm.onload = elm = null;
}
};
const done = () => {
cleanup();
resolve();
};
const error = () => {
cleanup();
reject("Failed to load script: " + url);
};
const id = dom.uniqueId();
elm = document.createElement("script");
elm.id = id;
elm.type = "text/javascript";
elm.src = Tools._addCacheSuffix(url);
if (this.settings.referrerPolicy) {
dom.setAttrib(elm, "referrerpolicy", this.settings.referrerPolicy);
}
elm.onload = done;
elm.onerror = error;
(document.getElementsByTagName("head")[0] || document.body).appendChild(
elm
);
});
}
isDone(url) {
return this.states[url] === LOADED;
}
markDone(url) {
this.states[url] = LOADED;
}
add(url) {
const self = this;
self.queue.push(url);
const state = self.states[url];
if (state === undefined) {
self.states[url] = QUEUED;
}
return new Promise((resolve, reject) => {
if (!self.scriptLoadedCallbacks[url]) {
self.scriptLoadedCallbacks[url] = [];
}
self.scriptLoadedCallbacks[url].push({
resolve,
reject,
});
});
}
load(url) {
return this.add(url);
}
remove(url) {
delete this.states[url];
delete this.scriptLoadedCallbacks[url];
}
loadQueue() {
const queue = this.queue;
this.queue = [];
return this.loadScripts(queue);
}
loadScripts(scripts) {
const self = this;
const execCallbacks = (name, url) => {
get$a(self.scriptLoadedCallbacks, url).each((callbacks) => {
each$e(callbacks, (callback) => callback[name](url));
});
delete self.scriptLoadedCallbacks[url];
};
const processResults = (results) => {
const failures = filter$5(
results,
(result) => result.status === "rejected"
);
if (failures.length > 0) {
return Promise.reject(
bind$3(failures, ({ reason }) =>
isArray$1(reason) ? reason : [reason]
)
);
} else {
return Promise.resolve();
}
};
const load = (urls) =>
Promise.allSettled(
map$3(urls, (url) => {
if (self.states[url] === LOADED) {
execCallbacks("resolve", url);
return Promise.resolve();
} else if (self.states[url] === FAILED) {
execCallbacks("reject", url);
return Promise.reject(url);
} else {
self.states[url] = LOADING;
return self.loadScript(url).then(
() => {
self.states[url] = LOADED;
execCallbacks("resolve", url);
const queue = self.queue;
if (queue.length > 0) {
self.queue = [];
return load(queue).then(processResults);
} else {
return Promise.resolve();
}
},
() => {
self.states[url] = FAILED;
execCallbacks("reject", url);
return Promise.reject(url);
}
);
}
})
);
const processQueue = (urls) => {
self.loading = true;
return load(urls).then((results) => {
self.loading = false;
const nextQueuedItem = self.queueLoadedCallbacks.shift();
Optional.from(nextQueuedItem).each(call);
return processResults(results);
});
};
const uniqueScripts = stringArray(scripts);
if (self.loading) {
return new Promise((resolve, reject) => {
self.queueLoadedCallbacks.push(() => {
processQueue(uniqueScripts).then(resolve, reject);
});
});
} else {
return processQueue(uniqueScripts);
}
}
}
ScriptLoader.ScriptLoader = new ScriptLoader();
const Cell = (initial) => {
let value = initial;
const get = () => {
return value;
};
const set = (v) => {
value = v;
};
return {
get,
set,
};
};
const isDuplicated = (items, item) => {
const firstIndex = items.indexOf(item);
return (
firstIndex !== -1 && items.indexOf(item, firstIndex + 1) > firstIndex
);
};
const isRaw = (str) => isObject(str) && has$2(str, "raw");
const isTokenised = (str) => isArray$1(str) && str.length > 1;
const data = {};
const currentCode = Cell("en");
const getLanguageData = () => get$a(data, currentCode.get());
const getData$1 = () => map$2(data, (value) => ({ ...value }));
const setCode = (newCode) => {
if (newCode) {
currentCode.set(newCode);
}
};
const getCode = () => currentCode.get();
const add$1 = (code, items) => {
let langData = data[code];
if (!langData) {
data[code] = langData = {};
}
const lcNames = map$3(keys(items), (name) => name.toLowerCase());
each$d(items, (translation, name) => {
const lcName = name.toLowerCase();
if (lcName !== name && isDuplicated(lcNames, lcName)) {
if (!has$2(items, lcName)) {
langData[lcName] = translation;
}
langData[name] = translation;
} else {
langData[lcName] = translation;
}
});
};
const translate = (text) => {
const langData = getLanguageData().getOr({});
const toString = (obj) => {
if (isFunction(obj)) {
return Object.prototype.toString.call(obj);
}
return !isEmpty(obj) ? "" + obj : "";
};
const isEmpty = (text) =>
text === "" || text === null || text === undefined;
const getLangData = (text) => {
const textStr = toString(text);
return has$2(langData, textStr)
? toString(langData[textStr])
: get$a(langData, textStr.toLowerCase()).map(toString).getOr(textStr);
};
const removeContext = (str) => str.replace(/{context:\w+}$/, "");
if (isEmpty(text)) {
return "";
}
if (isRaw(text)) {
return toString(text.raw);
}
if (isTokenised(text)) {
const values = text.slice(1);
const substitued = getLangData(text[0]).replace(
/\{([0-9]+)\}/g,
($1, $2) => (has$2(values, $2) ? toString(values[$2]) : $1)
);
return removeContext(substitued);
}
return removeContext(getLangData(text));
};
const isRtl$1 = () =>
getLanguageData()
.bind((items) => get$a(items, "_dir"))
.exists((dir) => dir === "rtl");
const hasCode = (code) => has$2(data, code);
const I18n = {
getData: getData$1,
setCode,
getCode,
add: add$1,
translate,
isRtl: isRtl$1,
hasCode,
};
const AddOnManager = () => {
const items = [];
const urls = {};
const lookup = {};
const _listeners = [];
const runListeners = (name, state) => {
const matchedListeners = filter$5(
_listeners,
(listener) => listener.name === name && listener.state === state
);
each$e(matchedListeners, (listener) => listener.resolve());
};
const isLoaded = (name) => has$2(urls, name);
const isAdded = (name) => has$2(lookup, name);
const get = (name) => {
if (lookup[name]) {
return lookup[name].instance;
}
return undefined;
};
const loadLanguagePack = (name, languages) => {
const language = I18n.getCode();
const wrappedLanguages = "," + (languages || "") + ",";
if (
!language ||
(languages && wrappedLanguages.indexOf("," + language + ",") === -1)
) {
return;
}
ScriptLoader.ScriptLoader.add(urls[name] + "/langs/" + language + ".js");
};
const requireLangPack = (name, languages) => {
if (AddOnManager.languageLoad !== false) {
if (isLoaded(name)) {
loadLanguagePack(name, languages);
} else {
waitFor(name, "loaded").then(() => loadLanguagePack(name, languages));
}
}
};
const add = (id, addOn) => {
items.push(addOn);
lookup[id] = { instance: addOn };
runListeners(id, "added");
return addOn;
};
const remove = (name) => {
delete urls[name];
delete lookup[name];
};
const createUrl = (baseUrl, dep) => {
if (isString(dep)) {
return isString(baseUrl)
? {
prefix: "",
resource: dep,
suffix: "",
}
: {
prefix: baseUrl.prefix,
resource: dep,
suffix: baseUrl.suffix,
};
} else {
return dep;
}
};
const load = (name, addOnUrl) => {
if (urls[name]) {
return Promise.resolve();
}
let urlString = isString(addOnUrl)
? addOnUrl
: addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix;
if (urlString.indexOf("/") !== 0 && urlString.indexOf("://") === -1) {
urlString = AddOnManager.baseURL + "/" + urlString;
}
urls[name] = urlString.substring(0, urlString.lastIndexOf("/"));
const done = () => {
runListeners(name, "loaded");
return Promise.resolve();
};
if (lookup[name]) {
return done();
} else {
return ScriptLoader.ScriptLoader.add(urlString).then(done);
}
};
const waitFor = (name, state = "added") => {
if (state === "added" && isAdded(name)) {
return Promise.resolve();
} else if (state === "loaded" && isLoaded(name)) {
return Promise.resolve();
} else {
return new Promise((resolve) => {
_listeners.push({
name,
state,
resolve,
});
});
}
};
return {
items,
urls,
lookup,
get,
requireLangPack,
add,
remove,
createUrl,
load,
waitFor,
};
};
AddOnManager.languageLoad = true;
AddOnManager.baseURL = "";
AddOnManager.PluginManager = AddOnManager();
AddOnManager.ThemeManager = AddOnManager();
AddOnManager.ModelManager = AddOnManager();
const singleton = (doRevoke) => {
const subject = Cell(Optional.none());
const revoke = () => subject.get().each(doRevoke);
const clear = () => {
revoke();
subject.set(Optional.none());
};
const isSet = () => subject.get().isSome();
const get = () => subject.get();
const set = (s) => {
revoke();
subject.set(Optional.some(s));
};
return {
clear,
isSet,
get,
set,
};
};
const repeatable = (delay) => {
const intervalId = Cell(Optional.none());
const revoke = () => intervalId.get().each((id) => clearInterval(id));
const clear = () => {
revoke();
intervalId.set(Optional.none());
};
const isSet = () => intervalId.get().isSome();
const get = () => intervalId.get();
const set = (functionToRepeat) => {
revoke();
intervalId.set(Optional.some(setInterval(functionToRepeat, delay)));
};
return {
clear,
isSet,
get,
set,
};
};
const value$2 = () => {
const subject = singleton(noop);
const on = (f) => subject.get().each(f);
return {
...subject,
on,
};
};
const first$1 = (fn, rate) => {
let timer = null;
const cancel = () => {
if (!isNull(timer)) {
clearTimeout(timer);
timer = null;
}
};
const throttle = (...args) => {
if (isNull(timer)) {
timer = setTimeout(() => {
timer = null;
fn.apply(null, args);
}, rate);
}
};
return {
cancel,
throttle,
};
};
const last$1 = (fn, rate) => {
let timer = null;
const cancel = () => {
if (!isNull(timer)) {
clearTimeout(timer);
timer = null;
}
};
const throttle = (...args) => {
cancel();
timer = setTimeout(() => {
timer = null;
fn.apply(null, args);
}, rate);
};
return {
cancel,
throttle,
};
};
const annotation = constant("mce-annotation");
const dataAnnotation = constant("data-mce-annotation");
const dataAnnotationId = constant("data-mce-annotation-uid");
const dataAnnotationActive = constant("data-mce-annotation-active");
const dataAnnotationClasses = constant("data-mce-annotation-classes");
const dataAnnotationAttributes = constant("data-mce-annotation-attrs");
const isRoot$1 = (root) => (node) => eq(node, root);
const identify = (editor, annotationName) => {
const rng = editor.selection.getRng();
const start = SugarElement.fromDom(rng.startContainer);
const root = SugarElement.fromDom(editor.getBody());
const selector = annotationName.fold(
() => "." + annotation(),
(an) => `[${dataAnnotation()}="${an}"]`
);
const newStart = child$1(start, rng.startOffset).getOr(start);
const closest = closest$3(newStart, selector, isRoot$1(root));
return closest.bind((c) =>
getOpt(c, `${dataAnnotationId()}`).bind((uid) =>
getOpt(c, `${dataAnnotation()}`).map((name) => {
const elements = findMarkers(editor, uid);
return {
uid,
name,
elements,
};
})
)
);
};
const isAnnotation = (elem) => isElement$7(elem) && has(elem, annotation());
const isBogusElement = (elem, root) =>
has$1(elem, "data-mce-bogus") ||
ancestor$2(elem, '[data-mce-bogus="all"]', isRoot$1(root));
const findMarkers = (editor, uid) => {
const body = SugarElement.fromDom(editor.getBody());
const descendants$1 = descendants(body, `[${dataAnnotationId()}="${uid}"]`);
return filter$5(
descendants$1,
(descendant) => !isBogusElement(descendant, body)
);
};
const findAll = (editor, name) => {
const body = SugarElement.fromDom(editor.getBody());
const markers = descendants(body, `[${dataAnnotation()}="${name}"]`);
const directory = {};
each$e(markers, (m) => {
if (!isBogusElement(m, body)) {
const uid = get$9(m, dataAnnotationId());
const nodesAlready = get$a(directory, uid).getOr([]);
directory[uid] = nodesAlready.concat([m]);
}
});
return directory;
};
const setup$x = (editor, registry) => {
const changeCallbacks = Cell({});
const initData = () => ({
listeners: [],
previous: value$2(),
});
const withCallbacks = (name, f) => {
updateCallbacks(name, (data) => {
f(data);
return data;
});
};
const updateCallbacks = (name, f) => {
const callbackMap = changeCallbacks.get();
const data = get$a(callbackMap, name).getOrThunk(initData);
const outputData = f(data);
callbackMap[name] = outputData;
changeCallbacks.set(callbackMap);
};
const fireCallbacks = (name, uid, elements) => {
withCallbacks(name, (data) => {
each$e(data.listeners, (f) =>
f(true, name, {
uid,
nodes: map$3(elements, (elem) => elem.dom),
})
);
});
};
const fireNoAnnotation = (name) => {
withCallbacks(name, (data) => {
each$e(data.listeners, (f) => f(false, name));
});
};
const toggleActiveAttr = (uid, state) => {
each$e(findMarkers(editor, uid), (elem) => {
if (state) {
set$3(elem, dataAnnotationActive(), "true");
} else {
remove$a(elem, dataAnnotationActive());
}
});
};
const onNodeChange = last$1(() => {
const annotations = sort(registry.getNames());
each$e(annotations, (name) => {
updateCallbacks(name, (data) => {
const prev = data.previous.get();
identify(editor, Optional.some(name)).fold(
() => {
prev.each((uid) => {
fireNoAnnotation(name);
data.previous.clear();
toggleActiveAttr(uid, false);
});
},
({ uid, name, elements }) => {
if (!is$2(prev, uid)) {
prev.each((uid) => toggleActiveAttr(uid, false));
fireCallbacks(name, uid, elements);
data.previous.set(uid);
toggleActiveAttr(uid, true);
}
}
);
return {
previous: data.previous,
listeners: data.listeners,
};
});
});
}, 30);
editor.on("remove", () => {
onNodeChange.cancel();
});
editor.on("NodeChange", () => {
onNodeChange.throttle();
});
const addListener = (name, f) => {
updateCallbacks(name, (data) => ({
previous: data.previous,
listeners: data.listeners.concat([f]),
}));
};
return { addListener };
};
const setup$w = (editor, registry) => {
const dataAnnotation$1 = dataAnnotation();
const identifyParserNode = (node) =>
Optional.from(node.attr(dataAnnotation$1)).bind(registry.lookup);
const removeDirectAnnotation = (node) => {
var _a, _b;
node.attr(dataAnnotationId(), null);
node.attr(dataAnnotation(), null);
node.attr(dataAnnotationActive(), null);
const customAttrNames = Optional.from(
node.attr(dataAnnotationAttributes())
)
.map((names) => names.split(","))
.getOr([]);
const customClasses = Optional.from(node.attr(dataAnnotationClasses()))
.map((names) => names.split(","))
.getOr([]);
each$e(customAttrNames, (name) => node.attr(name, null));
const classList =
(_b =
(_a = node.attr("class")) === null || _a === void 0
? void 0
: _a.split(" ")) !== null && _b !== void 0
? _b
: [];
const newClassList = difference(
classList,
[annotation()].concat(customClasses)
);
node.attr(
"class",
newClassList.length > 0 ? newClassList.join(" ") : null
);
node.attr(dataAnnotationClasses(), null);
node.attr(dataAnnotationAttributes(), null);
};
editor.serializer.addTempAttr(dataAnnotationActive());
editor.serializer.addAttributeFilter(dataAnnotation$1, (nodes) => {
for (const node of nodes) {
identifyParserNode(node).each((settings) => {
if (settings.persistent === false) {
if (node.name === "span") {
node.unwrap();
} else {
removeDirectAnnotation(node);
}
}
});
}
});
};
const create$c = () => {
const annotations = {};
const register = (name, settings) => {
annotations[name] = {
name,
settings,
};
};
const lookup = (name) => get$a(annotations, name).map((a) => a.settings);
const getNames = () => keys(annotations);
return {
register,
lookup,
getNames,
};
};
let unique = 0;
const generate$1 = (prefix) => {
const date = new Date();
const time = date.getTime();
const random = Math.floor(Math.random() * 1000000000);
unique++;
return prefix + "_" + random + unique + String(time);
};
const add = (element, classes) => {
each$e(classes, (x) => {
add$2(element, x);
});
};
const remove$4 = (element, classes) => {
each$e(classes, (x) => {
remove$7(element, x);
});
};
const clone$2 = (original, isDeep) =>
SugarElement.fromDom(original.dom.cloneNode(isDeep));
const shallow$1 = (original) => clone$2(original, false);
const deep$1 = (original) => clone$2(original, true);
const shallowAs = (original, tag) => {
const nu = SugarElement.fromTag(tag);
const attributes = clone$4(original);
setAll$1(nu, attributes);
return nu;
};
const mutate = (original, tag) => {
const nu = shallowAs(original, tag);
after$4(original, nu);
const children = children$1(original);
append(nu, children);
remove$5(original);
return nu;
};
const TextWalker = (startNode, rootNode, isBoundary = never) => {
const walker = new DomTreeWalker(startNode, rootNode);
const walk = (direction) => {
let next;
do {
next = walker[direction]();
} while (next && !isText$a(next) && !isBoundary(next));
return Optional.from(next).filter(isText$a);
};
return {
current: () => Optional.from(walker.current()).filter(isText$a),
next: () => walk("next"),
prev: () => walk("prev"),
prev2: () => walk("prev2"),
};
};
const TextSeeker = (dom, isBoundary) => {
const isBlockBoundary = isBoundary
? isBoundary
: (node) =>
dom.isBlock(node) || isBr$6(node) || isContentEditableFalse$b(node);
const walk = (node, offset, walker, process) => {
if (isText$a(node)) {
const newOffset = process(node, offset, node.data);
if (newOffset !== -1) {
return Optional.some({
container: node,
offset: newOffset,
});
}
}
return walker().bind((next) =>
walk(next.container, next.offset, walker, process)
);
};
const backwards = (node, offset, process, root) => {
const walker = TextWalker(
node,
root !== null && root !== void 0 ? root : dom.getRoot(),
isBlockBoundary
);
return walk(
node,
offset,
() =>
walker.prev().map((prev) => ({
container: prev,
offset: prev.length,
})),
process
).getOrNull();
};
const forwards = (node, offset, process, root) => {
const walker = TextWalker(
node,
root !== null && root !== void 0 ? root : dom.getRoot(),
isBlockBoundary
);
return walk(
node,
offset,
() =>
walker.next().map((next) => ({
container: next,
offset: 0,
})),
process
).getOrNull();
};
return {
backwards,
forwards,
};
};
const round$2 = Math.round;
const clone$1 = (rect) => {
if (!rect) {
return {
left: 0,
top: 0,
bottom: 0,
right: 0,
width: 0,
height: 0,
};
}
return {
left: round$2(rect.left),
top: round$2(rect.top),
bottom: round$2(rect.bottom),
right: round$2(rect.right),
width: round$2(rect.width),
height: round$2(rect.height),
};
};
const collapse = (rect, toStart) => {
rect = clone$1(rect);
if (toStart) {
rect.right = rect.left;
} else {
rect.left = rect.left + rect.width;
rect.right = rect.left;
}
rect.width = 0;
return rect;
};
const isEqual = (rect1, rect2) =>
rect1.left === rect2.left &&
rect1.top === rect2.top &&
rect1.bottom === rect2.bottom &&
rect1.right === rect2.right;
const isValidOverflow = (overflowY, rect1, rect2) =>
overflowY >= 0 && overflowY <= Math.min(rect1.height, rect2.height) / 2;
const isAbove$1 = (rect1, rect2) => {
const halfHeight = Math.min(rect2.height / 2, rect1.height / 2);
if (rect1.bottom - halfHeight < rect2.top) {
return true;
}
if (rect1.top > rect2.bottom) {
return false;
}
return isValidOverflow(rect2.top - rect1.bottom, rect1, rect2);
};
const isBelow$1 = (rect1, rect2) => {
if (rect1.top > rect2.bottom) {
return true;
}
if (rect1.bottom < rect2.top) {
return false;
}
return isValidOverflow(rect2.bottom - rect1.top, rect1, rect2);
};
const containsXY = (rect, clientX, clientY) =>
clientX >= rect.left &&
clientX <= rect.right &&
clientY >= rect.top &&
clientY <= rect.bottom;
const boundingClientRectFromRects = (rects) => {
return foldl(
rects,
(acc, rect) => {
return acc.fold(
() => Optional.some(rect),
(prevRect) => {
const left = Math.min(rect.left, prevRect.left);
const top = Math.min(rect.top, prevRect.top);
const right = Math.max(rect.right, prevRect.right);
const bottom = Math.max(rect.bottom, prevRect.bottom);
return Optional.some({
top,
right,
bottom,
left,
width: right - left,
height: bottom - top,
});
}
);
},
Optional.none()
);
};
const distanceToRectEdgeFromXY = (rect, x, y) => {
const cx = Math.max(Math.min(x, rect.left + rect.width), rect.left);
const cy = Math.max(Math.min(y, rect.top + rect.height), rect.top);
return Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
};
const overlapY = (r1, r2) =>
Math.max(0, Math.min(r1.bottom, r2.bottom) - Math.max(r1.top, r2.top));
const clamp$2 = (value, min, max) => Math.min(Math.max(value, min), max);
const getSelectedNode = (range) => {
const startContainer = range.startContainer,
startOffset = range.startOffset;
if (
startContainer === range.endContainer &&
startContainer.hasChildNodes() &&
range.endOffset === startOffset + 1
) {
return startContainer.childNodes[startOffset];
}
return null;
};
const getNode$1 = (container, offset) => {
if (isElement$6(container) && container.hasChildNodes()) {
const childNodes = container.childNodes;
const safeOffset = clamp$2(offset, 0, childNodes.length - 1);
return childNodes[safeOffset];
} else {
return container;
}
};
const getNodeUnsafe = (container, offset) => {
if (offset < 0 && isElement$6(container) && container.hasChildNodes()) {
return undefined;
} else {
return getNode$1(container, offset);
}
};
const extendingChars = new RegExp(
"[\u0300-\u036f\u0483-\u0487\u0488-\u0489\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a" +
"\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0" +
"\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e3-\u0902\u093a\u093c" +
"\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2-\u09e3" +
"\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc" +
"\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57" +
"\u0b62-\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c00\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56" +
"\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc-\u0ccd\u0cd5-\u0cd6\u0ce2-\u0ce3\u0d01\u0d3e\u0d41-\u0d44" +
"\u0d4d\u0d57\u0d62-\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9" +
"\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97" +
"\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074" +
"\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5" +
"\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18" +
"\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1ABE\u1b00-\u1b03\u1b34" +
"\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9" +
"\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9" +
"\u1dc0-\u1df5\u1dfc-\u1dff\u200c-\u200d\u20d0-\u20dc\u20DD-\u20E0\u20e1\u20E2-\u20E4\u20e5-\u20f0\u2cef-\u2cf1" +
"\u2d7f\u2de0-\u2dff\u302a-\u302d\u302e-\u302f\u3099-\u309a\ua66f\uA670-\uA672\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1" +
"\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc" +
"\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1" +
"\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\uff9e-\uff9f]"
);
const isExtendingChar = (ch) =>
isString(ch) && ch.charCodeAt(0) >= 768 && extendingChars.test(ch);
const or = (...args) => {
return (x) => {
for (let i = 0; i < args.length; i++) {
if (args[i](x)) {
return true;
}
}
return false;
};
};
const and = (...args) => {
return (x) => {
for (let i = 0; i < args.length; i++) {
if (!args[i](x)) {
return false;
}
}
return true;
};
};
const isElement$4 = isElement$6;
const isCaretCandidate$2 = isCaretCandidate$3;
const isBlock$1 = matchStyleValues("display", "block table");
const isFloated = matchStyleValues("float", "left right");
const isValidElementCaretCandidate = and(
isElement$4,
isCaretCandidate$2,
not(isFloated)
);
const isNotPre = not(
matchStyleValues("white-space", "pre pre-line pre-wrap")
);
const isText$7 = isText$a;
const isBr$3 = isBr$6;
const nodeIndex$1 = DOMUtils.nodeIndex;
const resolveIndex$1 = getNodeUnsafe;
const createRange$1 = (doc) =>
doc ? doc.createRange() : DOMUtils.DOM.createRng();
const isWhiteSpace$1 = (chr) => isString(chr) && /[\r\n\t ]/.test(chr);
const isRange = (rng) => !!rng.setStart && !!rng.setEnd;
const isHiddenWhiteSpaceRange = (range) => {
const container = range.startContainer;
const offset = range.startOffset;
if (
isWhiteSpace$1(range.toString()) &&
isNotPre(container.parentNode) &&
isText$a(container)
) {
const text = container.data;
if (
isWhiteSpace$1(text[offset - 1]) ||
isWhiteSpace$1(text[offset + 1])
) {
return true;
}
}
return false;
};
const getBrClientRect = (brNode) => {
const doc = brNode.ownerDocument;
const rng = createRange$1(doc);
const nbsp$1 = doc.createTextNode(nbsp);
const parentNode = brNode.parentNode;
parentNode.insertBefore(nbsp$1, brNode);
rng.setStart(nbsp$1, 0);
rng.setEnd(nbsp$1, 1);
const clientRect = clone$1(rng.getBoundingClientRect());
parentNode.removeChild(nbsp$1);
return clientRect;
};
const getBoundingClientRectWebKitText = (rng) => {
const sc = rng.startContainer;
const ec = rng.endContainer;
const so = rng.startOffset;
const eo = rng.endOffset;
if (sc === ec && isText$a(ec) && so === 0 && eo === 1) {
const newRng = rng.cloneRange();
newRng.setEndAfter(ec);
return getBoundingClientRect$1(newRng);
} else {
return null;
}
};
const isZeroRect = (r) =>
r.left === 0 && r.right === 0 && r.top === 0 && r.bottom === 0;
const getBoundingClientRect$1 = (item) => {
var _a;
let clientRect;
const clientRects = item.getClientRects();
if (clientRects.length > 0) {
clientRect = clone$1(clientRects[0]);
} else {
clientRect = clone$1(item.getBoundingClientRect());
}
if (!isRange(item) && isBr$3(item) && isZeroRect(clientRect)) {
return getBrClientRect(item);
}
if (isZeroRect(clientRect) && isRange(item)) {
return (_a = getBoundingClientRectWebKitText(item)) !== null &&
_a !== void 0
? _a
: clientRect;
}
return clientRect;
};
const collapseAndInflateWidth = (clientRect, toStart) => {
const newClientRect = collapse(clientRect, toStart);
newClientRect.width = 1;
newClientRect.right = newClientRect.left + 1;
return newClientRect;
};
const getCaretPositionClientRects = (caretPosition) => {
const clientRects = [];
const addUniqueAndValidRect = (clientRect) => {
if (clientRect.height === 0) {
return;
}
if (clientRects.length > 0) {
if (isEqual(clientRect, clientRects[clientRects.length - 1])) {
return;
}
}
clientRects.push(clientRect);
};
const addCharacterOffset = (container, offset) => {
const range = createRange$1(container.ownerDocument);
if (offset < container.data.length) {
if (isExtendingChar(container.data[offset])) {
return;
}
if (isExtendingChar(container.data[offset - 1])) {
range.setStart(container, offset);
range.setEnd(container, offset + 1);
if (!isHiddenWhiteSpaceRange(range)) {
addUniqueAndValidRect(
collapseAndInflateWidth(getBoundingClientRect$1(range), false)
);
return;
}
}
}
if (offset > 0) {
range.setStart(container, offset - 1);
range.setEnd(container, offset);
if (!isHiddenWhiteSpaceRange(range)) {
addUniqueAndValidRect(
collapseAndInflateWidth(getBoundingClientRect$1(range), false)
);
}
}
if (offset < container.data.length) {
range.setStart(container, offset);
range.setEnd(container, offset + 1);
if (!isHiddenWhiteSpaceRange(range)) {
addUniqueAndValidRect(
collapseAndInflateWidth(getBoundingClientRect$1(range), true)
);
}
}
};
const container = caretPosition.container();
const offset = caretPosition.offset();
if (isText$7(container)) {
addCharacterOffset(container, offset);
return clientRects;
}
if (isElement$4(container)) {
if (caretPosition.isAtEnd()) {
const node = resolveIndex$1(container, offset);
if (isText$7(node)) {
addCharacterOffset(node, node.data.length);
}
if (isValidElementCaretCandidate(node) && !isBr$3(node)) {
addUniqueAndValidRect(
collapseAndInflateWidth(getBoundingClientRect$1(node), false)
);
}
} else {
const node = resolveIndex$1(container, offset);
if (isText$7(node)) {
addCharacterOffset(node, 0);
}
if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) {
addUniqueAndValidRect(
collapseAndInflateWidth(getBoundingClientRect$1(node), false)
);
return clientRects;
}
const beforeNode = resolveIndex$1(
caretPosition.container(),
caretPosition.offset() - 1
);
if (isValidElementCaretCandidate(beforeNode) && !isBr$3(beforeNode)) {
if (
isBlock$1(beforeNode) ||
isBlock$1(node) ||
!isValidElementCaretCandidate(node)
) {
addUniqueAndValidRect(
collapseAndInflateWidth(
getBoundingClientRect$1(beforeNode),
false
)
);
}
}
if (isValidElementCaretCandidate(node)) {
addUniqueAndValidRect(
collapseAndInflateWidth(getBoundingClientRect$1(node), true)
);
}
}
}
return clientRects;
};
const CaretPosition = (container, offset, clientRects) => {
const isAtStart = () => {
if (isText$7(container)) {
return offset === 0;
}
return offset === 0;
};
const isAtEnd = () => {
if (isText$7(container)) {
return offset >= container.data.length;
}
return offset >= container.childNodes.length;
};
const toRange = () => {
const range = createRange$1(container.ownerDocument);
range.setStart(container, offset);
range.setEnd(container, offset);
return range;
};
const getClientRects = () => {
if (!clientRects) {
clientRects = getCaretPositionClientRects(
CaretPosition(container, offset)
);
}
return clientRects;
};
const isVisible = () => getClientRects().length > 0;
const isEqual = (caretPosition) =>
caretPosition &&
container === caretPosition.container() &&
offset === caretPosition.offset();
const getNode = (before) =>
resolveIndex$1(container, before ? offset - 1 : offset);
return {
container: constant(container),
offset: constant(offset),
toRange,
getClientRects,
isVisible,
isAtStart,
isAtEnd,
isEqual,
getNode,
};
};
CaretPosition.fromRangeStart = (range) =>
CaretPosition(range.startContainer, range.startOffset);
CaretPosition.fromRangeEnd = (range) =>
CaretPosition(range.endContainer, range.endOffset);
CaretPosition.after = (node) =>
CaretPosition(node.parentNode, nodeIndex$1(node) + 1);
CaretPosition.before = (node) =>
CaretPosition(node.parentNode, nodeIndex$1(node));
CaretPosition.isAbove = (pos1, pos2) =>
lift2(
head(pos2.getClientRects()),
last$3(pos1.getClientRects()),
isAbove$1
).getOr(false);
CaretPosition.isBelow = (pos1, pos2) =>
lift2(
last$3(pos2.getClientRects()),
head(pos1.getClientRects()),
isBelow$1
).getOr(false);
CaretPosition.isAtStart = (pos) => (pos ? pos.isAtStart() : false);
CaretPosition.isAtEnd = (pos) => (pos ? pos.isAtEnd() : false);
CaretPosition.isTextPosition = (pos) =>
pos ? isText$a(pos.container()) : false;
CaretPosition.isElementPosition = (pos) => !CaretPosition.isTextPosition(pos);
const trimEmptyTextNode$1 = (dom, node) => {
if (isText$a(node) && node.data.length === 0) {
dom.remove(node);
}
};
const insertNode = (dom, rng, node) => {
rng.insertNode(node);
trimEmptyTextNode$1(dom, node.previousSibling);
trimEmptyTextNode$1(dom, node.nextSibling);
};
const insertFragment = (dom, rng, frag) => {
const firstChild = Optional.from(frag.firstChild);
const lastChild = Optional.from(frag.lastChild);
rng.insertNode(frag);
firstChild.each((child) => trimEmptyTextNode$1(dom, child.previousSibling));
lastChild.each((child) => trimEmptyTextNode$1(dom, child.nextSibling));
};
const rangeInsertNode = (dom, rng, node) => {
if (isDocumentFragment(node)) {
insertFragment(dom, rng, node);
} else {
insertNode(dom, rng, node);
}
};
const isText$6 = isText$a;
const isBogus = isBogus$2;
const nodeIndex = DOMUtils.nodeIndex;
const normalizedParent = (node) => {
const parentNode = node.parentNode;
if (isBogus(parentNode)) {
return normalizedParent(parentNode);
}
return parentNode;
};
const getChildNodes = (node) => {
if (!node) {
return [];
}
return reduce(
node.childNodes,
(result, node) => {
if (isBogus(node) && node.nodeName !== "BR") {
result = result.concat(getChildNodes(node));
} else {
result.push(node);
}
return result;
},
[]
);
};
const normalizedTextOffset = (node, offset) => {
let tempNode = node;
while ((tempNode = tempNode.previousSibling)) {
if (!isText$6(tempNode)) {
break;
}
offset += tempNode.data.length;
}
return offset;
};
const equal = (a) => (b) => a === b;
const normalizedNodeIndex = (node) => {
let nodes, index;
nodes = getChildNodes(normalizedParent(node));
index = findIndex$1(nodes, equal(node), node);
nodes = nodes.slice(0, index + 1);
const numTextFragments = reduce(
nodes,
(result, node, i) => {
if (isText$6(node) && isText$6(nodes[i - 1])) {
result++;
}
return result;
},
0
);
nodes = filter$3(nodes, matchNodeNames([node.nodeName]));
index = findIndex$1(nodes, equal(node), node);
return index - numTextFragments;
};
const createPathItem = (node) => {
const name = isText$6(node) ? "text()" : node.nodeName.toLowerCase();
return name + "[" + normalizedNodeIndex(node) + "]";
};
const parentsUntil$1 = (root, node, predicate) => {
const parents = [];
for (
let tempNode = node.parentNode;
tempNode && tempNode !== root;
tempNode = tempNode.parentNode
) {
if (predicate && predicate(tempNode)) {
break;
}
parents.push(tempNode);
}
return parents;
};
const create$b = (root, caretPosition) => {
let path = [];
let container = caretPosition.container();
let offset = caretPosition.offset();
let outputOffset;
if (isText$6(container)) {
outputOffset = normalizedTextOffset(container, offset);
} else {
const childNodes = container.childNodes;
if (offset >= childNodes.length) {
outputOffset = "after";
offset = childNodes.length - 1;
} else {
outputOffset = "before";
}
container = childNodes[offset];
}
path.push(createPathItem(container));
let parents = parentsUntil$1(root, container);
parents = filter$3(parents, not(isBogus$2));
path = path.concat(
map$1(parents, (node) => {
return createPathItem(node);
})
);
return path.reverse().join("/") + "," + outputOffset;
};
const resolvePathItem = (node, name, index) => {
let nodes = getChildNodes(node);
nodes = filter$3(nodes, (node, index) => {
return !isText$6(node) || !isText$6(nodes[index - 1]);
});
nodes = filter$3(nodes, matchNodeNames([name]));
return nodes[index];
};
const findTextPosition = (container, offset) => {
let node = container;
let targetOffset = 0;
while (isText$6(node)) {
const dataLen = node.data.length;
if (offset >= targetOffset && offset <= targetOffset + dataLen) {
container = node;
offset = offset - targetOffset;
break;
}
if (!isText$6(node.nextSibling)) {
container = node;
offset = dataLen;
break;
}
targetOffset += dataLen;
node = node.nextSibling;
}
if (isText$6(container) && offset > container.data.length) {
offset = container.data.length;
}
return CaretPosition(container, offset);
};
const resolve$1 = (root, path) => {
if (!path) {
return null;
}
const parts = path.split(",");
const paths = parts[0].split("/");
const offset = parts.length > 1 ? parts[1] : "before";
const container = reduce(
paths,
(result, value) => {
const match = /([\w\-\(\)]+)\[([0-9]+)\]/.exec(value);
if (!match) {
return null;
}
if (match[1] === "text()") {
match[1] = "#text";
}
return resolvePathItem(result, match[1], parseInt(match[2], 10));
},
root
);
if (!container) {
return null;
}
if (!isText$6(container) && container.parentNode) {
let nodeOffset;
if (offset === "after") {
nodeOffset = nodeIndex(container) + 1;
} else {
nodeOffset = nodeIndex(container);
}
return CaretPosition(container.parentNode, nodeOffset);
}
return findTextPosition(container, parseInt(offset, 10));
};
const isContentEditableFalse$9 = isContentEditableFalse$b;
const getNormalizedTextOffset$1 = (trim, container, offset) => {
let trimmedOffset = trim(container.data.slice(0, offset)).length;
for (
let node = container.previousSibling;
node && isText$a(node);
node = node.previousSibling
) {
trimmedOffset += trim(node.data).length;
}
return trimmedOffset;
};
const getPoint = (dom, trim, normalized, rng, start) => {
const container = start ? rng.startContainer : rng.endContainer;
let offset = start ? rng.startOffset : rng.endOffset;
const point = [];
const root = dom.getRoot();
if (isText$a(container)) {
point.push(
normalized ? getNormalizedTextOffset$1(trim, container, offset) : offset
);
} else {
let after = 0;
const childNodes = container.childNodes;
if (offset >= childNodes.length && childNodes.length) {
after = 1;
offset = Math.max(0, childNodes.length - 1);
}
point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
}
for (let node = container; node && node !== root; node = node.parentNode) {
point.push(dom.nodeIndex(node, normalized));
}
return point;
};
const getLocation = (trim, selection, normalized, rng) => {
const dom = selection.dom;
const start = getPoint(dom, trim, normalized, rng, true);
const forward = selection.isForward();
const fakeCaret = isRangeInCaretContainerBlock(rng)
? { isFakeCaret: true }
: {};
if (!selection.isCollapsed()) {
const end = getPoint(dom, trim, normalized, rng, false);
return {
start,
end,
forward,
...fakeCaret,
};
} else {
return {
start,
forward,
...fakeCaret,
};
}
};
const findIndex = (dom, name, element) => {
let count = 0;
Tools.each(dom.select(name), (node) => {
if (node.getAttribute("data-mce-bogus") === "all") {
return;
} else if (node === element) {
return false;
} else {
count++;
return;
}
});
return count;
};
const moveEndPoint$1 = (rng, start) => {
let container = start ? rng.startContainer : rng.endContainer;
let offset = start ? rng.startOffset : rng.endOffset;
if (isElement$6(container) && container.nodeName === "TR") {
const childNodes = container.childNodes;
container =
childNodes[
Math.min(start ? offset : offset - 1, childNodes.length - 1)
];
if (container) {
offset = start ? 0 : container.childNodes.length;
if (start) {
rng.setStart(container, offset);
} else {
rng.setEnd(container, offset);
}
}
}
};
const normalizeTableCellSelection = (rng) => {
moveEndPoint$1(rng, true);
moveEndPoint$1(rng, false);
return rng;
};
const findSibling = (node, offset) => {
if (isElement$6(node)) {
node = getNode$1(node, offset);
if (isContentEditableFalse$9(node)) {
return node;
}
}
if (isCaretContainer$2(node)) {
if (isText$a(node) && isCaretContainerBlock$1(node)) {
node = node.parentNode;
}
let sibling = node.previousSibling;
if (isContentEditableFalse$9(sibling)) {
return sibling;
}
sibling = node.nextSibling;
if (isContentEditableFalse$9(sibling)) {
return sibling;
}
}
return undefined;
};
const findAdjacentContentEditableFalseElm = (rng) => {
return (
findSibling(rng.startContainer, rng.startOffset) ||
findSibling(rng.endContainer, rng.endOffset)
);
};
const getOffsetBookmark = (trim, normalized, selection) => {
const element = selection.getNode();
const rng = selection.getRng();
if (element.nodeName === "IMG" || isContentEditableFalse$9(element)) {
const name = element.nodeName;
return {
name,
index: findIndex(selection.dom, name, element),
};
}
const sibling = findAdjacentContentEditableFalseElm(rng);
if (sibling) {
const name = sibling.tagName;
return {
name,
index: findIndex(selection.dom, name, sibling),
};
}
return getLocation(trim, selection, normalized, rng);
};
const getCaretBookmark = (selection) => {
const rng = selection.getRng();
return {
start: create$b(
selection.dom.getRoot(),
CaretPosition.fromRangeStart(rng)
),
end: create$b(selection.dom.getRoot(), CaretPosition.fromRangeEnd(rng)),
forward: selection.isForward(),
};
};
const getRangeBookmark = (selection) => {
return {
rng: selection.getRng(),
forward: selection.isForward(),
};
};
const createBookmarkSpan = (dom, id, filled) => {
const args = {
"data-mce-type": "bookmark",
id,
style: "overflow:hidden;line-height:0px",
};
return filled
? dom.create("span", args, "")
: dom.create("span", args);
};
const getPersistentBookmark = (selection, filled) => {
const dom = selection.dom;
let rng = selection.getRng();
const id = dom.uniqueId();
const collapsed = selection.isCollapsed();
const element = selection.getNode();
const name = element.nodeName;
const forward = selection.isForward();
if (name === "IMG") {
return {
name,
index: findIndex(dom, name, element),
};
}
const rng2 = normalizeTableCellSelection(rng.cloneRange());
if (!collapsed) {
rng2.collapse(false);
const endBookmarkNode = createBookmarkSpan(dom, id + "_end", filled);
rangeInsertNode(dom, rng2, endBookmarkNode);
}
rng = normalizeTableCellSelection(rng);
rng.collapse(true);
const startBookmarkNode = createBookmarkSpan(dom, id + "_start", filled);
rangeInsertNode(dom, rng, startBookmarkNode);
selection.moveToBookmark({
id,
keep: true,
forward,
});
return {
id,
forward,
};
};
const getBookmark$2 = (selection, type, normalized = false) => {
if (type === 2) {
return getOffsetBookmark(trim$1, normalized, selection);
} else if (type === 3) {
return getCaretBookmark(selection);
} else if (type) {
return getRangeBookmark(selection);
} else {
return getPersistentBookmark(selection, false);
}
};
const getUndoBookmark = curry(getOffsetBookmark, identity, true);
const value$1 = (value) => {
const applyHelper = (fn) => fn(value);
const constHelper = constant(value);
const outputHelper = () => output;
const output = {
tag: true,
inner: value,
fold: (_onError, onValue) => onValue(value),
isValue: always,
isError: never,
map: (mapper) => Result.value(mapper(value)),
mapError: outputHelper,
bind: applyHelper,
exists: applyHelper,
forall: applyHelper,
getOr: constHelper,
or: outputHelper,
getOrThunk: constHelper,
orThunk: outputHelper,
getOrDie: constHelper,
each: (fn) => {
fn(value);
},
toOptional: () => Optional.some(value),
};
return output;
};
const error = (error) => {
const outputHelper = () => output;
const output = {
tag: false,
inner: error,
fold: (onError, _onValue) => onError(error),
isValue: never,
isError: always,
map: outputHelper,
mapError: (mapper) => Result.error(mapper(error)),
bind: outputHelper,
exists: never,
forall: always,
getOr: identity,
or: identity,
getOrThunk: apply$1,
orThunk: apply$1,
getOrDie: die(String(error)),
each: noop,
toOptional: Optional.none,
};
return output;
};
const fromOption = (optional, err) =>
optional.fold(() => error(err), value$1);
const Result = {
value: value$1,
error,
fromOption,
};
const generate = (cases) => {
if (!isArray$1(cases)) {
throw new Error("cases must be an array");
}
if (cases.length === 0) {
throw new Error("there must be at least one case");
}
const constructors = [];
const adt = {};
each$e(cases, (acase, count) => {
const keys$1 = keys(acase);
if (keys$1.length !== 1) {
throw new Error("one and only one name per case");
}
const key = keys$1[0];
const value = acase[key];
if (adt[key] !== undefined) {
throw new Error("duplicate key detected:" + key);
} else if (key === "cata") {
throw new Error("cannot have a case named cata (sorry)");
} else if (!isArray$1(value)) {
throw new Error("case arguments must be an array");
}
constructors.push(key);
adt[key] = (...args) => {
const argLength = args.length;
if (argLength !== value.length) {
throw new Error(
"Wrong number of arguments to case " +
key +
". Expected " +
value.length +
" (" +
value +
"), got " +
argLength
);
}
const match = (branches) => {
const branchKeys = keys(branches);
if (constructors.length !== branchKeys.length) {
throw new Error(
"Wrong number of arguments to match. Expected: " +
constructors.join(",") +
"\nActual: " +
branchKeys.join(",")
);
}
const allReqd = forall(constructors, (reqKey) => {
return contains$2(branchKeys, reqKey);
});
if (!allReqd) {
throw new Error(
"Not all branches were specified when using match. Specified: " +
branchKeys.join(", ") +
"\nRequired: " +
constructors.join(", ")
);
}
return branches[key].apply(null, args);
};
return {
fold: (...foldArgs) => {
if (foldArgs.length !== cases.length) {
throw new Error(
"Wrong number of arguments to fold. Expected " +
cases.length +
", got " +
foldArgs.length
);
}
const target = foldArgs[count];
return target.apply(null, args);
},
match,
log: (label) => {
console.log(label, {
constructors,
constructor: key,
params: args,
});
},
};
};
});
return adt;
};
const Adt = { generate };
Adt.generate([
{
bothErrors: ["error1", "error2"],
},
{
firstError: ["error1", "value2"],
},
{
secondError: ["value1", "error2"],
},
{
bothValues: ["value1", "value2"],
},
]);
const partition$1 = (results) => {
const errors = [];
const values = [];
each$e(results, (result) => {
result.fold(
(err) => {
errors.push(err);
},
(value) => {
values.push(value);
}
);
});
return {
errors,
values,
};
};
const isInlinePattern = (pattern) =>
pattern.type === "inline-command" || pattern.type === "inline-format";
const isBlockPattern = (pattern) =>
pattern.type === "block-command" || pattern.type === "block-format";
const normalizePattern = (pattern) => {
const err = (message) =>
Result.error({
message,
pattern,
});
const formatOrCmd = (name, onFormat, onCommand) => {
if (pattern.format !== undefined) {
let formats;
if (isArray$1(pattern.format)) {
if (!forall(pattern.format, isString)) {
return err(
name + " pattern has non-string items in the `format` array"
);
}
formats = pattern.format;
} else if (isString(pattern.format)) {
formats = [pattern.format];
} else {
return err(name + " pattern has non-string `format` parameter");
}
return Result.value(onFormat(formats));
} else if (pattern.cmd !== undefined) {
if (!isString(pattern.cmd)) {
return err(name + " pattern has non-string `cmd` parameter");
}
return Result.value(onCommand(pattern.cmd, pattern.value));
} else {
return err(
name + " pattern is missing both `format` and `cmd` parameters"
);
}
};
if (!isObject(pattern)) {
return err("Raw pattern is not an object");
}
if (!isString(pattern.start)) {
return err("Raw pattern is missing `start` parameter");
}
if (pattern.end !== undefined) {
if (!isString(pattern.end)) {
return err("Inline pattern has non-string `end` parameter");
}
if (pattern.start.length === 0 && pattern.end.length === 0) {
return err("Inline pattern has empty `start` and `end` parameters");
}
let start = pattern.start;
let end = pattern.end;
if (end.length === 0) {
end = start;
start = "";
}
return formatOrCmd(
"Inline",
(format) => ({
type: "inline-format",
start,
end,
format,
}),
(cmd, value) => ({
type: "inline-command",
start,
end,
cmd,
value,
})
);
} else if (pattern.replacement !== undefined) {
if (!isString(pattern.replacement)) {
return err(
"Replacement pattern has non-string `replacement` parameter"
);
}
if (pattern.start.length === 0) {
return err("Replacement pattern has empty `start` parameter");
}
return Result.value({
type: "inline-command",
start: "",
end: pattern.start,
cmd: "mceInsertContent",
value: pattern.replacement,
});
} else {
if (pattern.start.length === 0) {
return err("Block pattern has empty `start` parameter");
}
return formatOrCmd(
"Block",
(formats) => ({
type: "block-format",
start: pattern.start,
format: formats[0],
}),
(command, commandValue) => ({
type: "block-command",
start: pattern.start,
cmd: command,
value: commandValue,
})
);
}
};
const getBlockPatterns = (patterns) => filter$5(patterns, isBlockPattern);
const getInlinePatterns = (patterns) => filter$5(patterns, isInlinePattern);
const createPatternSet = (patterns, dynamicPatternsLookup) => ({
inlinePatterns: getInlinePatterns(patterns),
blockPatterns: getBlockPatterns(patterns),
dynamicPatternsLookup,
});
const fromRawPatterns = (patterns) => {
const normalized = partition$1(map$3(patterns, normalizePattern));
each$e(normalized.errors, (err) => console.error(err.message, err.pattern));
return normalized.values;
};
const fromRawPatternsLookup = (lookupFn) => {
return (ctx) => {
const rawPatterns = lookupFn(ctx);
return fromRawPatterns(rawPatterns);
};
};
const deviceDetection$1 = detect$2().deviceType;
const isTouch = deviceDetection$1.isTouch();
const DOM$a = DOMUtils.DOM;
const getHash = (value) => {
const items =
value.indexOf("=") > 0
? value.split(/[;,](?![^=;,]*(?:[;,]|$))/)
: value.split(",");
return foldl(
items,
(output, item) => {
const arr = item.split("=");
const key = arr[0];
const val = arr.length > 1 ? arr[1] : key;
output[trim$3(key)] = trim$3(val);
return output;
},
{}
);
};
const isRegExp = (x) => is$4(x, RegExp);
const option = (name) => (editor) => editor.options.get(name);
const stringOrObjectProcessor = (value) => isString(value) || isObject(value);
const bodyOptionProcessor =
(editor, defaultValue = "") =>
(value) => {
const valid = isString(value);
if (valid) {
if (value.indexOf("=") !== -1) {
const bodyObj = getHash(value);
return {
value: get$a(bodyObj, editor.id).getOr(defaultValue),
valid,
};
} else {
return {
value,
valid,
};
}
} else {
return {
valid: false,
message: "Must be a string.",
};
}
};
const register$7 = (editor) => {
const registerOption = editor.options.register;
registerOption("id", {
processor: "string",
default: editor.id,
});
registerOption("selector", { processor: "string" });
registerOption("target", { processor: "object" });
registerOption("suffix", { processor: "string" });
registerOption("cache_suffix", { processor: "string" });
registerOption("base_url", { processor: "string" });
registerOption("referrer_policy", {
processor: "string",
default: "",
});
registerOption("language_load", {
processor: "boolean",
default: true,
});
registerOption("inline", {
processor: "boolean",
default: false,
});
registerOption("iframe_attrs", {
processor: "object",
default: {},
});
registerOption("doctype", {
processor: "string",
default: "",
});
registerOption("document_base_url", {
processor: "string",
default: editor.documentBaseUrl,
});
registerOption("body_id", {
processor: bodyOptionProcessor(editor, "tinymce"),
default: "tinymce",
});
registerOption("body_class", {
processor: bodyOptionProcessor(editor),
default: "",
});
registerOption("content_security_policy", {
processor: "string",
default: "",
});
registerOption("br_in_pre", {
processor: "boolean",
default: true,
});
registerOption("forced_root_block", {
processor: (value) => {
const valid = isString(value) && isNotEmpty(value);
if (valid) {
return {
value,
valid,
};
} else {
return {
valid: false,
message: "Must be a non-empty string.",
};
}
},
default: "p",
});
registerOption("forced_root_block_attrs", {
processor: "object",
default: {},
});
registerOption("newline_behavior", {
processor: (value) => {
const valid = contains$2(
["block", "linebreak", "invert", "default"],
value
);
return valid
? {
value,
valid,
}
: {
valid: false,
message: "Must be one of: block, linebreak, invert or default.",
};
},
default: "default",
});
registerOption("br_newline_selector", {
processor: "string",
default: ".mce-toc h2,figcaption,caption",
});
registerOption("no_newline_selector", {
processor: "string",
default: "",
});
registerOption("keep_styles", {
processor: "boolean",
default: true,
});
registerOption("end_container_on_empty_block", {
processor: (value) => {
if (isBoolean(value)) {
return {
valid: true,
value,
};
} else if (isString(value)) {
return {
valid: true,
value,
};
} else {
return {
valid: false,
message: "Must be boolean or a string",
};
}
},
default: "blockquote",
});
registerOption("font_size_style_values", {
processor: "string",
default: "xx-small,x-small,small,medium,large,x-large,xx-large",
});
registerOption("font_size_legacy_values", {
processor: "string",
default: "xx-small,small,medium,large,x-large,xx-large,300%",
});
registerOption("font_size_classes", {
processor: "string",
default: "",
});
registerOption("automatic_uploads", {
processor: "boolean",
default: true,
});
registerOption("images_reuse_filename", {
processor: "boolean",
default: false,
});
registerOption("images_replace_blob_uris", {
processor: "boolean",
default: true,
});
registerOption("icons", {
processor: "string",
default: "",
});
registerOption("icons_url", {
processor: "string",
default: "",
});
registerOption("images_upload_url", {
processor: "string",
default: "",
});
registerOption("images_upload_base_path", {
processor: "string",
default: "",
});
registerOption("images_upload_credentials", {
processor: "boolean",
default: false,
});
registerOption("images_upload_handler", { processor: "function" });
registerOption("language", {
processor: "string",
default: "en",
});
registerOption("language_url", {
processor: "string",
default: "",
});
registerOption("entity_encoding", {
processor: "string",
default: "named",
});
registerOption("indent", {
processor: "boolean",
default: true,
});
registerOption("indent_before", {
processor: "string",
default:
"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead," +
"tfoot,tbody,tr,section,details,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",
});
registerOption("indent_after", {
processor: "string",
default:
"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead," +
"tfoot,tbody,tr,section,details,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",
});
registerOption("indent_use_margin", {
processor: "boolean",
default: false,
});
registerOption("indentation", {
processor: "string",
default: "40px",
});
registerOption("content_css", {
processor: (value) => {
const valid =
value === false || isString(value) || isArrayOf(value, isString);
if (valid) {
if (isString(value)) {
return {
value: map$3(value.split(","), trim$3),
valid,
};
} else if (isArray$1(value)) {
return {
value,
valid,
};
} else if (value === false) {
return {
value: [],
valid,
};
} else {
return {
value,
valid,
};
}
} else {
return {
valid: false,
message: "Must be false, a string or an array of strings.",
};
}
},
default: isInline(editor) ? [] : ["default"],
});
registerOption("content_style", { processor: "string" });
registerOption("content_css_cors", {
processor: "boolean",
default: false,
});
registerOption("font_css", {
processor: (value) => {
const valid = isString(value) || isArrayOf(value, isString);
if (valid) {
const newValue = isArray$1(value)
? value
: map$3(value.split(","), trim$3);
return {
value: newValue,
valid,
};
} else {
return {
valid: false,
message: "Must be a string or an array of strings.",
};
}
},
default: [],
});
registerOption("inline_boundaries", {
processor: "boolean",
default: true,
});
registerOption("inline_boundaries_selector", {
processor: "string",
default: "a[href],code,span.mce-annotation",
});
registerOption("object_resizing", {
processor: (value) => {
const valid = isBoolean(value) || isString(value);
if (valid) {
if (
value === false ||
deviceDetection$1.isiPhone() ||
deviceDetection$1.isiPad()
) {
return {
value: "",
valid,
};
} else {
return {
value:
value === true
? "table,img,figure.image,div,video,iframe"
: value,
valid,
};
}
} else {
return {
valid: false,
message: "Must be boolean or a string",
};
}
},
default: !isTouch,
});
registerOption("resize_img_proportional", {
processor: "boolean",
default: true,
});
registerOption("event_root", { processor: "object" });
registerOption("service_message", { processor: "string" });
registerOption("theme", {
processor: (value) =>
value === false || isString(value) || isFunction(value),
default: "silver",
});
registerOption("theme_url", { processor: "string" });
registerOption("formats", { processor: "object" });
registerOption("format_empty_lines", {
processor: "boolean",
default: false,
});
registerOption("format_noneditable_selector", {
processor: "string",
default: "",
});
registerOption("preview_styles", {
processor: (value) => {
const valid = value === false || isString(value);
if (valid) {
return {
value: value === false ? "" : value,
valid,
};
} else {
return {
valid: false,
message: "Must be false or a string",
};
}
},
default:
"font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow",
});
registerOption("custom_ui_selector", {
processor: "string",
default: "",
});
registerOption("hidden_input", {
processor: "boolean",
default: true,
});
registerOption("submit_patch", {
processor: "boolean",
default: true,
});
registerOption("encoding", { processor: "string" });
registerOption("add_form_submit_trigger", {
processor: "boolean",
default: true,
});
registerOption("add_unload_trigger", {
processor: "boolean",
default: true,
});
registerOption("custom_undo_redo_levels", {
processor: "number",
default: 0,
});
registerOption("disable_nodechange", {
processor: "boolean",
default: false,
});
registerOption("readonly", {
processor: "boolean",
default: false,
});
registerOption("editable_root", {
processor: "boolean",
default: true,
});
registerOption("plugins", {
processor: "string[]",
default: [],
});
registerOption("external_plugins", { processor: "object" });
registerOption("forced_plugins", { processor: "string[]" });
registerOption("model", {
processor: "string",
default: editor.hasPlugin("rtc") ? "plugin" : "dom",
});
registerOption("model_url", { processor: "string" });
registerOption("block_unsupported_drop", {
processor: "boolean",
default: true,
});
registerOption("visual", {
processor: "boolean",
default: true,
});
registerOption("visual_table_class", {
processor: "string",
default: "mce-item-table",
});
registerOption("visual_anchor_class", {
processor: "string",
default: "mce-item-anchor",
});
registerOption("iframe_aria_text", {
processor: "string",
default: "Rich Text Area. Press ALT-0 for help.",
});
registerOption("setup", { processor: "function" });
registerOption("init_instance_callback", { processor: "function" });
registerOption("url_converter", {
processor: "function",
default: editor.convertURL,
});
registerOption("url_converter_scope", {
processor: "object",
default: editor,
});
registerOption("urlconverter_callback", { processor: "function" });
registerOption("allow_conditional_comments", {
processor: "boolean",
default: false,
});
registerOption("allow_html_data_urls", {
processor: "boolean",
default: false,
});
registerOption("allow_svg_data_urls", { processor: "boolean" });
registerOption("allow_html_in_named_anchor", {
processor: "boolean",
default: false,
});
registerOption("allow_script_urls", {
processor: "boolean",
default: false,
});
registerOption("allow_unsafe_link_target", {
processor: "boolean",
default: false,
});
registerOption("convert_fonts_to_spans", {
processor: "boolean",
default: true,
deprecated: true,
});
registerOption("fix_list_elements", {
processor: "boolean",
default: false,
});
registerOption("preserve_cdata", {
processor: "boolean",
default: false,
});
registerOption("remove_trailing_brs", {
processor: "boolean",
default: true,
});
registerOption("pad_empty_with_br", {
processor: "boolean",
default: false,
});
registerOption("inline_styles", {
processor: "boolean",
default: true,
deprecated: true,
});
registerOption("element_format", {
processor: "string",
default: "html",
});
registerOption("entities", { processor: "string" });
registerOption("schema", {
processor: "string",
default: "html5",
});
registerOption("convert_urls", {
processor: "boolean",
default: true,
});
registerOption("relative_urls", {
processor: "boolean",
default: true,
});
registerOption("remove_script_host", {
processor: "boolean",
default: true,
});
registerOption("custom_elements", { processor: "string" });
registerOption("extended_valid_elements", { processor: "string" });
registerOption("invalid_elements", { processor: "string" });
registerOption("invalid_styles", { processor: stringOrObjectProcessor });
registerOption("valid_children", { processor: "string" });
registerOption("valid_classes", { processor: stringOrObjectProcessor });
registerOption("valid_elements", { processor: "string" });
registerOption("valid_styles", { processor: stringOrObjectProcessor });
registerOption("verify_html", {
processor: "boolean",
default: true,
});
registerOption("auto_focus", {
processor: (value) => isString(value) || value === true,
});
registerOption("browser_spellcheck", {
processor: "boolean",
default: false,
});
registerOption("protect", { processor: "array" });
registerOption("images_file_types", {
processor: "string",
default: "jpeg,jpg,jpe,jfi,jif,jfif,png,gif,bmp,webp",
});
registerOption("deprecation_warnings", {
processor: "boolean",
default: true,
});
registerOption("a11y_advanced_options", {
processor: "boolean",
default: false,
});
registerOption("api_key", { processor: "string" });
registerOption("paste_block_drop", {
processor: "boolean",
default: false,
});
registerOption("paste_data_images", {
processor: "boolean",
default: true,
});
registerOption("paste_preprocess", { processor: "function" });
registerOption("paste_postprocess", { processor: "function" });
registerOption("paste_webkit_styles", {
processor: "string",
default: "none",
});
registerOption("paste_remove_styles_if_webkit", {
processor: "boolean",
default: true,
});
registerOption("paste_merge_formats", {
processor: "boolean",
default: true,
});
registerOption("smart_paste", {
processor: "boolean",
default: true,
});
registerOption("paste_as_text", {
processor: "boolean",
default: false,
});
registerOption("paste_tab_spaces", {
processor: "number",
default: 4,
});
registerOption("text_patterns", {
processor: (value) => {
if (isArrayOf(value, isObject) || value === false) {
const patterns = value === false ? [] : value;
return {
value: fromRawPatterns(patterns),
valid: true,
};
} else {
return {
valid: false,
message: "Must be an array of objects or false.",
};
}
},
default: [
{
start: "*",
end: "*",
format: "italic",
},
{
start: "**",
end: "**",
format: "bold",
},
{
start: "#",
format: "h1",
},
{
start: "##",
format: "h2",
},
{
start: "###",
format: "h3",
},
{
start: "####",
format: "h4",
},
{
start: "#####",
format: "h5",
},
{
start: "######",
format: "h6",
},
{
start: "1. ",
cmd: "InsertOrderedList",
},
{
start: "* ",
cmd: "InsertUnorderedList",
},
{
start: "- ",
cmd: "InsertUnorderedList",
},
],
});
registerOption("text_patterns_lookup", {
processor: (value) => {
if (isFunction(value)) {
return {
value: fromRawPatternsLookup(value),
valid: true,
};
} else {
return {
valid: false,
message: "Must be a single function",
};
}
},
default: (_ctx) => [],
});
registerOption("noneditable_class", {
processor: "string",
default: "mceNonEditable",
});
registerOption("editable_class", {
processor: "string",
default: "mceEditable",
});
registerOption("noneditable_regexp", {
processor: (value) => {
if (isArrayOf(value, isRegExp)) {
return {
value,
valid: true,
};
} else if (isRegExp(value)) {
return {
value: [value],
valid: true,
};
} else {
return {
valid: false,
message: "Must be a RegExp or an array of RegExp.",
};
}
},
default: [],
});
registerOption("table_tab_navigation", {
processor: "boolean",
default: true,
});
registerOption("highlight_on_focus", {
processor: "boolean",
default: false,
});
registerOption("xss_sanitization", {
processor: "boolean",
default: true,
});
registerOption("details_initial_state", {
processor: (value) => {
const valid = contains$2(["inherited", "collapsed", "expanded"], value);
return valid
? {
value,
valid,
}
: {
valid: false,
message: "Must be one of: inherited, collapsed, or expanded.",
};
},
default: "inherited",
});
registerOption("details_serialized_state", {
processor: (value) => {
const valid = contains$2(["inherited", "collapsed", "expanded"], value);
return valid
? {
value,
valid,
}
: {
valid: false,
message: "Must be one of: inherited, collapsed, or expanded.",
};
},
default: "inherited",
});
registerOption("init_content_sync", {
processor: "boolean",
default: false,
});
registerOption("newdocument_content", {
processor: "string",
default: "",
});
editor.on("ScriptsLoaded", () => {
registerOption("directionality", {
processor: "string",
default: I18n.isRtl() ? "rtl" : undefined,
});
registerOption("placeholder", {
processor: "string",
default: DOM$a.getAttrib(editor.getElement(), "placeholder"),
});
});
};
const getIframeAttrs = option("iframe_attrs");
const getDocType = option("doctype");
const getDocumentBaseUrl = option("document_base_url");
const getBodyId = option("body_id");
const getBodyClass = option("body_class");
const getContentSecurityPolicy = option("content_security_policy");
const shouldPutBrInPre$1 = option("br_in_pre");
const getForcedRootBlock = option("forced_root_block");
const getForcedRootBlockAttrs = option("forced_root_block_attrs");
const getNewlineBehavior = option("newline_behavior");
const getBrNewLineSelector = option("br_newline_selector");
const getNoNewLineSelector = option("no_newline_selector");
const shouldKeepStyles = option("keep_styles");
const shouldEndContainerOnEmptyBlock = option("end_container_on_empty_block");
const isAutomaticUploadsEnabled = option("automatic_uploads");
const shouldReuseFileName = option("images_reuse_filename");
const shouldReplaceBlobUris = option("images_replace_blob_uris");
const getIconPackName = option("icons");
const getIconsUrl = option("icons_url");
const getImageUploadUrl = option("images_upload_url");
const getImageUploadBasePath = option("images_upload_base_path");
const getImagesUploadCredentials = option("images_upload_credentials");
const getImagesUploadHandler = option("images_upload_handler");
const shouldUseContentCssCors = option("content_css_cors");
const getReferrerPolicy = option("referrer_policy");
const getLanguageCode = option("language");
const getLanguageUrl = option("language_url");
const shouldIndentUseMargin = option("indent_use_margin");
const getIndentation = option("indentation");
const getContentCss = option("content_css");
const getContentStyle = option("content_style");
const getFontCss = option("font_css");
const getDirectionality = option("directionality");
const getInlineBoundarySelector = option("inline_boundaries_selector");
const getObjectResizing = option("object_resizing");
const getResizeImgProportional = option("resize_img_proportional");
const getPlaceholder = option("placeholder");
const getEventRoot = option("event_root");
const getServiceMessage = option("service_message");
const getTheme = option("theme");
const getThemeUrl = option("theme_url");
const getModel = option("model");
const getModelUrl = option("model_url");
const isInlineBoundariesEnabled = option("inline_boundaries");
const getFormats = option("formats");
const getPreviewStyles = option("preview_styles");
const canFormatEmptyLines = option("format_empty_lines");
const getFormatNoneditableSelector = option("format_noneditable_selector");
const getCustomUiSelector = option("custom_ui_selector");
const isInline = option("inline");
const hasHiddenInput = option("hidden_input");
const shouldPatchSubmit = option("submit_patch");
const shouldAddFormSubmitTrigger = option("add_form_submit_trigger");
const shouldAddUnloadTrigger = option("add_unload_trigger");
const getCustomUndoRedoLevels = option("custom_undo_redo_levels");
const shouldDisableNodeChange = option("disable_nodechange");
const isReadOnly$1 = option("readonly");
const hasEditableRoot$1 = option("editable_root");
const hasContentCssCors = option("content_css_cors");
const getPlugins = option("plugins");
const getExternalPlugins$1 = option("external_plugins");
const shouldBlockUnsupportedDrop = option("block_unsupported_drop");
const isVisualAidsEnabled = option("visual");
const getVisualAidsTableClass = option("visual_table_class");
const getVisualAidsAnchorClass = option("visual_anchor_class");
const getIframeAriaText = option("iframe_aria_text");
const getSetupCallback = option("setup");
const getInitInstanceCallback = option("init_instance_callback");
const getUrlConverterCallback = option("urlconverter_callback");
const getAutoFocus = option("auto_focus");
const shouldBrowserSpellcheck = option("browser_spellcheck");
const getProtect = option("protect");
const shouldPasteBlockDrop = option("paste_block_drop");
const shouldPasteDataImages = option("paste_data_images");
const getPastePreProcess = option("paste_preprocess");
const getPastePostProcess = option("paste_postprocess");
const getNewDocumentContent = option("newdocument_content");
const getPasteWebkitStyles = option("paste_webkit_styles");
const shouldPasteRemoveWebKitStyles = option("paste_remove_styles_if_webkit");
const shouldPasteMergeFormats = option("paste_merge_formats");
const isSmartPasteEnabled = option("smart_paste");
const isPasteAsTextEnabled = option("paste_as_text");
const getPasteTabSpaces = option("paste_tab_spaces");
const shouldAllowHtmlDataUrls = option("allow_html_data_urls");
const getTextPatterns = option("text_patterns");
const getTextPatternsLookup = option("text_patterns_lookup");
const getNonEditableClass = option("noneditable_class");
const getEditableClass = option("editable_class");
const getNonEditableRegExps = option("noneditable_regexp");
const shouldPreserveCData = option("preserve_cdata");
const shouldHighlightOnFocus = option("highlight_on_focus");
const shouldSanitizeXss = option("xss_sanitization");
const shouldUseDocumentWrite = option("init_content_sync");
const hasTextPatternsLookup = (editor) =>
editor.options.isSet("text_patterns_lookup");
const getFontStyleValues = (editor) =>
Tools.explode(editor.options.get("font_size_style_values"));
const getFontSizeClasses = (editor) =>
Tools.explode(editor.options.get("font_size_classes"));
const isEncodingXml = (editor) => editor.options.get("encoding") === "xml";
const getAllowedImageFileTypes = (editor) =>
Tools.explode(editor.options.get("images_file_types"));
const hasTableTabNavigation = option("table_tab_navigation");
const getDetailsInitialState = option("details_initial_state");
const getDetailsSerializedState = option("details_serialized_state");
const isElement$3 = isElement$6;
const isText$5 = isText$a;
const removeNode$1 = (node) => {
const parentNode = node.parentNode;
if (parentNode) {
parentNode.removeChild(node);
}
};
const trimCount = (text) => {
const trimmedText = trim$1(text);
return {
count: text.length - trimmedText.length,
text: trimmedText,
};
};
const deleteZwspChars = (caretContainer) => {
let idx;
while ((idx = caretContainer.data.lastIndexOf(ZWSP$1)) !== -1) {
caretContainer.deleteData(idx, 1);
}
};
const removeUnchanged = (caretContainer, pos) => {
remove$3(caretContainer);
return pos;
};
const removeTextAndReposition = (caretContainer, pos) => {
const before = trimCount(caretContainer.data.substr(0, pos.offset()));
const after = trimCount(caretContainer.data.substr(pos.offset()));
const text = before.text + after.text;
if (text.length > 0) {
deleteZwspChars(caretContainer);
return CaretPosition(caretContainer, pos.offset() - before.count);
} else {
return pos;
}
};
const removeElementAndReposition = (caretContainer, pos) => {
const parentNode = pos.container();
const newPosition = indexOf$1(from(parentNode.childNodes), caretContainer)
.map((index) => {
return index < pos.offset()
? CaretPosition(parentNode, pos.offset() - 1)
: pos;
})
.getOr(pos);
remove$3(caretContainer);
return newPosition;
};
const removeTextCaretContainer = (caretContainer, pos) =>
isText$5(caretContainer) && pos.container() === caretContainer
? removeTextAndReposition(caretContainer, pos)
: removeUnchanged(caretContainer, pos);
const removeElementCaretContainer = (caretContainer, pos) =>
pos.container() === caretContainer.parentNode
? removeElementAndReposition(caretContainer, pos)
: removeUnchanged(caretContainer, pos);
const removeAndReposition = (container, pos) =>
CaretPosition.isTextPosition(pos)
? removeTextCaretContainer(container, pos)
: removeElementCaretContainer(container, pos);
const remove$3 = (caretContainerNode) => {
if (
isElement$3(caretContainerNode) &&
isCaretContainer$2(caretContainerNode)
) {
if (hasContent(caretContainerNode)) {
caretContainerNode.removeAttribute("data-mce-caret");
} else {
removeNode$1(caretContainerNode);
}
}
if (isText$5(caretContainerNode)) {
deleteZwspChars(caretContainerNode);
if (caretContainerNode.data.length === 0) {
removeNode$1(caretContainerNode);
}
}
};
const isContentEditableFalse$8 = isContentEditableFalse$b;
const isMedia$1 = isMedia$2;
const isTableCell$1 = isTableCell$3;
const inlineFakeCaretSelector =
"*[contentEditable=false],video,audio,embed,object";
const getAbsoluteClientRect = (root, element, before) => {
const clientRect = collapse(element.getBoundingClientRect(), before);
let scrollX;
let scrollY;
if (root.tagName === "BODY") {
const docElm = root.ownerDocument.documentElement;
scrollX = root.scrollLeft || docElm.scrollLeft;
scrollY = root.scrollTop || docElm.scrollTop;
} else {
const rootRect = root.getBoundingClientRect();
scrollX = root.scrollLeft - rootRect.left;
scrollY = root.scrollTop - rootRect.top;
}
clientRect.left += scrollX;
clientRect.right += scrollX;
clientRect.top += scrollY;
clientRect.bottom += scrollY;
clientRect.width = 1;
let margin = element.offsetWidth - element.clientWidth;
if (margin > 0) {
if (before) {
margin *= -1;
}
clientRect.left += margin;
clientRect.right += margin;
}
return clientRect;
};
const trimInlineCaretContainers = (root) => {
var _a, _b;
const fakeCaretTargetNodes = descendants(
SugarElement.fromDom(root),
inlineFakeCaretSelector
);
for (let i = 0; i < fakeCaretTargetNodes.length; i++) {
const node = fakeCaretTargetNodes[i].dom;
let sibling = node.previousSibling;
if (endsWithCaretContainer$1(sibling)) {
const data = sibling.data;
if (data.length === 1) {
(_a = sibling.parentNode) === null || _a === void 0
? void 0
: _a.removeChild(sibling);
} else {
sibling.deleteData(data.length - 1, 1);
}
}
sibling = node.nextSibling;
if (startsWithCaretContainer$1(sibling)) {
const data = sibling.data;
if (data.length === 1) {
(_b = sibling.parentNode) === null || _b === void 0
? void 0
: _b.removeChild(sibling);
} else {
sibling.deleteData(0, 1);
}
}
}
};
const FakeCaret = (editor, root, isBlock, hasFocus) => {
const lastVisualCaret = value$2();
let cursorInterval;
let caretContainerNode;
const caretBlock = getForcedRootBlock(editor);
const dom = editor.dom;
const show = (before, element) => {
let rng;
hide();
if (isTableCell$1(element)) {
return null;
}
if (isBlock(element)) {
const caretContainer = insertBlock(caretBlock, element, before);
const clientRect = getAbsoluteClientRect(root, element, before);
dom.setStyle(caretContainer, "top", clientRect.top);
caretContainerNode = caretContainer;
const caret = dom.create("div", {
class: "mce-visual-caret",
"data-mce-bogus": "all",
});
dom.setStyles(caret, { ...clientRect });
dom.add(root, caret);
lastVisualCaret.set({
caret,
element,
before,
});
if (before) {
dom.addClass(caret, "mce-visual-caret-before");
}
startBlink();
rng = element.ownerDocument.createRange();
rng.setStart(caretContainer, 0);
rng.setEnd(caretContainer, 0);
} else {
caretContainerNode = insertInline$1(element, before);
rng = element.ownerDocument.createRange();
if (isInlineFakeCaretTarget(caretContainerNode.nextSibling)) {
rng.setStart(caretContainerNode, 0);
rng.setEnd(caretContainerNode, 0);
} else {
rng.setStart(caretContainerNode, 1);
rng.setEnd(caretContainerNode, 1);
}
return rng;
}
return rng;
};
const hide = () => {
trimInlineCaretContainers(root);
if (caretContainerNode) {
remove$3(caretContainerNode);
caretContainerNode = null;
}
lastVisualCaret.on((caretState) => {
dom.remove(caretState.caret);
lastVisualCaret.clear();
});
if (cursorInterval) {
clearInterval(cursorInterval);
cursorInterval = undefined;
}
};
const startBlink = () => {
cursorInterval = setInterval(() => {
lastVisualCaret.on((caretState) => {
if (hasFocus()) {
dom.toggleClass(caretState.caret, "mce-visual-caret-hidden");
} else {
dom.addClass(caretState.caret, "mce-visual-caret-hidden");
}
});
}, 500);
};
const reposition = () => {
lastVisualCaret.on((caretState) => {
const clientRect = getAbsoluteClientRect(
root,
caretState.element,
caretState.before
);
dom.setStyles(caretState.caret, { ...clientRect });
});
};
const destroy = () => clearInterval(cursorInterval);
const getCss = () =>
".mce-visual-caret {" +
"position: absolute;" +
"background-color: black;" +
"background-color: currentcolor;" +
"}" +
".mce-visual-caret-hidden {" +
"display: none;" +
"}" +
"*[data-mce-caret] {" +
"position: absolute;" +
"left: -1000px;" +
"right: auto;" +
"top: 0;" +
"margin: 0;" +
"padding: 0;" +
"}";
return {
show,
hide,
getCss,
reposition,
destroy,
};
};
const isFakeCaretTableBrowser = () => Env.browser.isFirefox();
const isInlineFakeCaretTarget = (node) =>
isContentEditableFalse$8(node) || isMedia$1(node);
const isFakeCaretTarget = (node) => {
const isTarget =
isInlineFakeCaretTarget(node) ||
(isTable$2(node) && isFakeCaretTableBrowser());
return (
isTarget && parentElement(SugarElement.fromDom(node)).exists(isEditable$3)
);
};
const isContentEditableTrue$1 = isContentEditableTrue$3;
const isContentEditableFalse$7 = isContentEditableFalse$b;
const isMedia = isMedia$2;
const isBlockLike = matchStyleValues(
"display",
"block table table-cell table-caption list-item"
);
const isCaretContainer = isCaretContainer$2;
const isCaretContainerBlock = isCaretContainerBlock$1;
const isElement$2 = isElement$6;
const isText$4 = isText$a;
const isCaretCandidate$1 = isCaretCandidate$3;
const isForwards = (direction) => direction > 0;
const isBackwards = (direction) => direction < 0;
const skipCaretContainers = (walk, shallow) => {
let node;
while ((node = walk(shallow))) {
if (!isCaretContainerBlock(node)) {
return node;
}
}
return null;
};
const findNode = (node, direction, predicateFn, rootNode, shallow) => {
const walker = new DomTreeWalker(node, rootNode);
const isCefOrCaretContainer =
isContentEditableFalse$7(node) || isCaretContainerBlock(node);
let tempNode;
if (isBackwards(direction)) {
if (isCefOrCaretContainer) {
tempNode = skipCaretContainers(walker.prev.bind(walker), true);
if (predicateFn(tempNode)) {
return tempNode;
}
}
while (
(tempNode = skipCaretContainers(walker.prev.bind(walker), shallow))
) {
if (predicateFn(tempNode)) {
return tempNode;
}
}
}
if (isForwards(direction)) {
if (isCefOrCaretContainer) {
tempNode = skipCaretContainers(walker.next.bind(walker), true);
if (predicateFn(tempNode)) {
return tempNode;
}
}
while (
(tempNode = skipCaretContainers(walker.next.bind(walker), shallow))
) {
if (predicateFn(tempNode)) {
return tempNode;
}
}
}
return null;
};
const getEditingHost = (node, rootNode) => {
const isCETrue = (node) => isContentEditableTrue$1(node.dom);
const isRoot = (node) => node.dom === rootNode;
return ancestor$4(SugarElement.fromDom(node), isCETrue, isRoot)
.map((elm) => elm.dom)
.getOr(rootNode);
};
const getParentBlock$3 = (node, rootNode) => {
while (node && node !== rootNode) {
if (isBlockLike(node)) {
return node;
}
node = node.parentNode;
}
return null;
};
const isInSameBlock = (caretPosition1, caretPosition2, rootNode) =>
getParentBlock$3(caretPosition1.container(), rootNode) ===
getParentBlock$3(caretPosition2.container(), rootNode);
const getChildNodeAtRelativeOffset = (relativeOffset, caretPosition) => {
if (!caretPosition) {
return Optional.none();
}
const container = caretPosition.container();
const offset = caretPosition.offset();
if (!isElement$2(container)) {
return Optional.none();
}
return Optional.from(container.childNodes[offset + relativeOffset]);
};
const beforeAfter = (before, node) => {
var _a;
const doc =
(_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
const range = doc.createRange();
if (before) {
range.setStartBefore(node);
range.setEndBefore(node);
} else {
range.setStartAfter(node);
range.setEndAfter(node);
}
return range;
};
const isNodesInSameBlock = (root, node1, node2) =>
getParentBlock$3(node1, root) === getParentBlock$3(node2, root);
const lean = (left, root, node) => {
const siblingName = left ? "previousSibling" : "nextSibling";
let tempNode = node;
while (tempNode && tempNode !== root) {
let sibling = tempNode[siblingName];
if (sibling && isCaretContainer(sibling)) {
sibling = sibling[siblingName];
}
if (isContentEditableFalse$7(sibling) || isMedia(sibling)) {
if (isNodesInSameBlock(root, sibling, tempNode)) {
return sibling;
}
break;
}
if (isCaretCandidate$1(sibling)) {
break;
}
tempNode = tempNode.parentNode;
}
return null;
};
const before$2 = curry(beforeAfter, true);
const after$2 = curry(beforeAfter, false);
const normalizeRange = (direction, root, range) => {
let node;
const leanLeft = curry(lean, true, root);
const leanRight = curry(lean, false, root);
const container = range.startContainer;
const offset = range.startOffset;
if (isCaretContainerBlock$1(container)) {
const block = isText$4(container) ? container.parentNode : container;
const location = block.getAttribute("data-mce-caret");
if (location === "before") {
node = block.nextSibling;
if (isFakeCaretTarget(node)) {
return before$2(node);
}
}
if (location === "after") {
node = block.previousSibling;
if (isFakeCaretTarget(node)) {
return after$2(node);
}
}
}
if (!range.collapsed) {
return range;
}
if (isText$a(container)) {
if (isCaretContainer(container)) {
if (direction === 1) {
node = leanRight(container);
if (node) {
return before$2(node);
}
node = leanLeft(container);
if (node) {
return after$2(node);
}
}
if (direction === -1) {
node = leanLeft(container);
if (node) {
return after$2(node);
}
node = leanRight(container);
if (node) {
return before$2(node);
}
}
return range;
}
if (
endsWithCaretContainer$1(container) &&
offset >= container.data.length - 1
) {
if (direction === 1) {
node = leanRight(container);
if (node) {
return before$2(node);
}
}
return range;
}
if (startsWithCaretContainer$1(container) && offset <= 1) {
if (direction === -1) {
node = leanLeft(container);
if (node) {
return after$2(node);
}
}
return range;
}
if (offset === container.data.length) {
node = leanRight(container);
if (node) {
return before$2(node);
}
return range;
}
if (offset === 0) {
node = leanLeft(container);
if (node) {
return after$2(node);
}
return range;
}
}
return range;
};
const getRelativeCefElm = (forward, caretPosition) =>
getChildNodeAtRelativeOffset(forward ? 0 : -1, caretPosition).filter(
isContentEditableFalse$7
);
const getNormalizedRangeEndPoint = (direction, root, range) => {
const normalizedRange = normalizeRange(direction, root, range);
return direction === -1
? CaretPosition.fromRangeStart(normalizedRange)
: CaretPosition.fromRangeEnd(normalizedRange);
};
const getElementFromPosition = (pos) =>
Optional.from(pos.getNode()).map(SugarElement.fromDom);
const getElementFromPrevPosition = (pos) =>
Optional.from(pos.getNode(true)).map(SugarElement.fromDom);
const getVisualCaretPosition = (walkFn, caretPosition) => {
let pos = caretPosition;
while ((pos = walkFn(pos))) {
if (pos.isVisible()) {
return pos;
}
}
return pos;
};
const isMoveInsideSameBlock = (from, to) => {
const inSameBlock = isInSameBlock(from, to);
if (!inSameBlock && isBr$6(from.getNode())) {
return true;
}
return inSameBlock;
};
var HDirection;
(function (HDirection) {
HDirection[(HDirection["Backwards"] = -1)] = "Backwards";
HDirection[(HDirection["Forwards"] = 1)] = "Forwards";
})(HDirection || (HDirection = {}));
const isContentEditableFalse$6 = isContentEditableFalse$b;
const isText$3 = isText$a;
const isElement$1 = isElement$6;
const isBr$2 = isBr$6;
const isCaretCandidate = isCaretCandidate$3;
const isAtomic = isAtomic$1;
const isEditableCaretCandidate = isEditableCaretCandidate$1;
const getParents$3 = (node, root) => {
const parents = [];
let tempNode = node;
while (tempNode && tempNode !== root) {
parents.push(tempNode);
tempNode = tempNode.parentNode;
}
return parents;
};
const nodeAtIndex = (container, offset) => {
if (container.hasChildNodes() && offset < container.childNodes.length) {
return container.childNodes[offset];
}
return null;
};
const getCaretCandidatePosition = (direction, node) => {
if (isForwards(direction)) {
if (
isCaretCandidate(node.previousSibling) &&
!isText$3(node.previousSibling)
) {
return CaretPosition.before(node);
}
if (isText$3(node)) {
return CaretPosition(node, 0);
}
}
if (isBackwards(direction)) {
if (isCaretCandidate(node.nextSibling) && !isText$3(node.nextSibling)) {
return CaretPosition.after(node);
}
if (isText$3(node)) {
return CaretPosition(node, node.data.length);
}
}
if (isBackwards(direction)) {
if (isBr$2(node)) {
return CaretPosition.before(node);
}
return CaretPosition.after(node);
}
return CaretPosition.before(node);
};
const moveForwardFromBr = (root, nextNode) => {
const nextSibling = nextNode.nextSibling;
if (nextSibling && isCaretCandidate(nextSibling)) {
if (isText$3(nextSibling)) {
return CaretPosition(nextSibling, 0);
} else {
return CaretPosition.before(nextSibling);
}
} else {
return findCaretPosition$1(
HDirection.Forwards,
CaretPosition.after(nextNode),
root
);
}
};
const findCaretPosition$1 = (direction, startPos, root) => {
let node;
let nextNode;
let innerNode;
let caretPosition;
if (!isElement$1(root) || !startPos) {
return null;
}
if (startPos.isEqual(CaretPosition.after(root)) && root.lastChild) {
caretPosition = CaretPosition.after(root.lastChild);
if (
isBackwards(direction) &&
isCaretCandidate(root.lastChild) &&
isElement$1(root.lastChild)
) {
return isBr$2(root.lastChild)
? CaretPosition.before(root.lastChild)
: caretPosition;
}
} else {
caretPosition = startPos;
}
const container = caretPosition.container();
let offset = caretPosition.offset();
if (isText$3(container)) {
if (isBackwards(direction) && offset > 0) {
return CaretPosition(container, --offset);
}
if (isForwards(direction) && offset < container.length) {
return CaretPosition(container, ++offset);
}
node = container;
} else {
if (isBackwards(direction) && offset > 0) {
nextNode = nodeAtIndex(container, offset - 1);
if (isCaretCandidate(nextNode)) {
if (!isAtomic(nextNode)) {
innerNode = findNode(
nextNode,
direction,
isEditableCaretCandidate,
nextNode
);
if (innerNode) {
if (isText$3(innerNode)) {
return CaretPosition(innerNode, innerNode.data.length);
}
return CaretPosition.after(innerNode);
}
}
if (isText$3(nextNode)) {
return CaretPosition(nextNode, nextNode.data.length);
}
return CaretPosition.before(nextNode);
}
}
if (isForwards(direction) && offset < container.childNodes.length) {
nextNode = nodeAtIndex(container, offset);
if (isCaretCandidate(nextNode)) {
if (isBr$2(nextNode)) {
return moveForwardFromBr(root, nextNode);
}
if (!isAtomic(nextNode)) {
innerNode = findNode(
nextNode,
direction,
isEditableCaretCandidate,
nextNode
);
if (innerNode) {
if (isText$3(innerNode)) {
return CaretPosition(innerNode, 0);
}
return CaretPosition.before(innerNode);
}
}
if (isText$3(nextNode)) {
return CaretPosition(nextNode, 0);
}
return CaretPosition.after(nextNode);
}
}
node = nextNode ? nextNode : caretPosition.getNode();
}
if (
node &&
((isForwards(direction) && caretPosition.isAtEnd()) ||
(isBackwards(direction) && caretPosition.isAtStart()))
) {
node = findNode(node, direction, always, root, true);
if (isEditableCaretCandidate(node, root)) {
return getCaretCandidatePosition(direction, node);
}
}
nextNode = node
? findNode(node, direction, isEditableCaretCandidate, root)
: node;
const rootContentEditableFalseElm = last$2(
filter$5(getParents$3(container, root), isContentEditableFalse$6)
);
if (
rootContentEditableFalseElm &&
(!nextNode || !rootContentEditableFalseElm.contains(nextNode))
) {
if (isForwards(direction)) {
caretPosition = CaretPosition.after(rootContentEditableFalseElm);
} else {
caretPosition = CaretPosition.before(rootContentEditableFalseElm);
}
return caretPosition;
}
if (nextNode) {
return getCaretCandidatePosition(direction, nextNode);
}
return null;
};
const CaretWalker = (root) => ({
next: (caretPosition) => {
return findCaretPosition$1(HDirection.Forwards, caretPosition, root);
},
prev: (caretPosition) => {
return findCaretPosition$1(HDirection.Backwards, caretPosition, root);
},
});
const walkToPositionIn = (forward, root, start) => {
const position = forward
? CaretPosition.before(start)
: CaretPosition.after(start);
return fromPosition(forward, root, position);
};
const afterElement = (node) =>
isBr$6(node) ? CaretPosition.before(node) : CaretPosition.after(node);
const isBeforeOrStart = (position) => {
if (CaretPosition.isTextPosition(position)) {
return position.offset() === 0;
} else {
return isCaretCandidate$3(position.getNode());
}
};
const isAfterOrEnd = (position) => {
if (CaretPosition.isTextPosition(position)) {
const container = position.container();
return position.offset() === container.data.length;
} else {
return isCaretCandidate$3(position.getNode(true));
}
};
const isBeforeAfterSameElement = (from, to) =>
!CaretPosition.isTextPosition(from) &&
!CaretPosition.isTextPosition(to) &&
from.getNode() === to.getNode(true);
const isAtBr = (position) =>
!CaretPosition.isTextPosition(position) && isBr$6(position.getNode());
const shouldSkipPosition = (forward, from, to) => {
if (forward) {
return (
!isBeforeAfterSameElement(from, to) &&
!isAtBr(from) &&
isAfterOrEnd(from) &&
isBeforeOrStart(to)
);
} else {
return (
!isBeforeAfterSameElement(to, from) &&
isBeforeOrStart(from) &&
isAfterOrEnd(to)
);
}
};
const fromPosition = (forward, root, pos) => {
const walker = CaretWalker(root);
return Optional.from(forward ? walker.next(pos) : walker.prev(pos));
};
const navigate = (forward, root, from) =>
fromPosition(forward, root, from).bind((to) => {
if (
isInSameBlock(from, to, root) &&
shouldSkipPosition(forward, from, to)
) {
return fromPosition(forward, root, to);
} else {
return Optional.some(to);
}
});
const navigateIgnore = (forward, root, from, ignoreFilter) =>
navigate(forward, root, from).bind((pos) =>
ignoreFilter(pos)
? navigateIgnore(forward, root, pos, ignoreFilter)
: Optional.some(pos)
);
const positionIn = (forward, element) => {
const startNode = forward ? element.firstChild : element.lastChild;
if (isText$a(startNode)) {
return Optional.some(
CaretPosition(startNode, forward ? 0 : startNode.data.length)
);
} else if (startNode) {
if (isCaretCandidate$3(startNode)) {
return Optional.some(
forward ? CaretPosition.before(startNode) : afterElement(startNode)
);
} else {
return walkToPositionIn(forward, element, startNode);
}
} else {
return Optional.none();
}
};
const nextPosition = curry(fromPosition, true);
const prevPosition = curry(fromPosition, false);
const firstPositionIn = curry(positionIn, true);
const lastPositionIn = curry(positionIn, false);
const CARET_ID = "_mce_caret";
const isCaretNode = (node) => isElement$6(node) && node.id === CARET_ID;
const getParentCaretContainer = (body, node) => {
let currentNode = node;
while (currentNode && currentNode !== body) {
if (isCaretNode(currentNode)) {
return currentNode;
}
currentNode = currentNode.parentNode;
}
return null;
};
const isStringPathBookmark = (bookmark) => isString(bookmark.start);
const isRangeBookmark = (bookmark) => has$2(bookmark, "rng");
const isIdBookmark = (bookmark) => has$2(bookmark, "id");
const isIndexBookmark = (bookmark) => has$2(bookmark, "name");
const isPathBookmark = (bookmark) => Tools.isArray(bookmark.start);
const isForwardBookmark = (bookmark) =>
!isIndexBookmark(bookmark) && isBoolean(bookmark.forward)
? bookmark.forward
: true;
const addBogus = (dom, node) => {
if (isElement$6(node) && dom.isBlock(node) && !node.innerHTML) {
node.innerHTML = '
';
}
return node;
};
const resolveCaretPositionBookmark = (dom, bookmark) => {
const startPos = Optional.from(resolve$1(dom.getRoot(), bookmark.start));
const endPos = Optional.from(resolve$1(dom.getRoot(), bookmark.end));
return lift2(startPos, endPos, (start, end) => {
const range = dom.createRng();
range.setStart(start.container(), start.offset());
range.setEnd(end.container(), end.offset());
return {
range,
forward: isForwardBookmark(bookmark),
};
});
};
const insertZwsp = (node, rng) => {
var _a;
const doc =
(_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
const textNode = doc.createTextNode(ZWSP$1);
node.appendChild(textNode);
rng.setStart(textNode, 0);
rng.setEnd(textNode, 0);
};
const isEmpty$1 = (node) => !node.hasChildNodes();
const tryFindRangePosition = (node, rng) =>
lastPositionIn(node).fold(never, (pos) => {
rng.setStart(pos.container(), pos.offset());
rng.setEnd(pos.container(), pos.offset());
return true;
});
const padEmptyCaretContainer = (root, node, rng) => {
if (isEmpty$1(node) && getParentCaretContainer(root, node)) {
insertZwsp(node, rng);
return true;
} else {
return false;
}
};
const setEndPoint = (dom, start, bookmark, rng) => {
const point = bookmark[start ? "start" : "end"];
const root = dom.getRoot();
if (point) {
let node = root;
let offset = point[0];
for (let i = point.length - 1; node && i >= 1; i--) {
const children = node.childNodes;
if (padEmptyCaretContainer(root, node, rng)) {
return true;
}
if (point[i] > children.length - 1) {
if (padEmptyCaretContainer(root, node, rng)) {
return true;
}
return tryFindRangePosition(node, rng);
}
node = children[point[i]];
}
if (isText$a(node)) {
offset = Math.min(point[0], node.data.length);
}
if (isElement$6(node)) {
offset = Math.min(point[0], node.childNodes.length);
}
if (start) {
rng.setStart(node, offset);
} else {
rng.setEnd(node, offset);
}
}
return true;
};
const isValidTextNode = (node) => isText$a(node) && node.data.length > 0;
const restoreEndPoint = (dom, suffix, bookmark) => {
const marker = dom.get(bookmark.id + "_" + suffix);
const markerParent =
marker === null || marker === void 0 ? void 0 : marker.parentNode;
const keep = bookmark.keep;
if (marker && markerParent) {
let container;
let offset;
if (suffix === "start") {
if (!keep) {
container = markerParent;
offset = dom.nodeIndex(marker);
} else {
if (marker.hasChildNodes()) {
container = marker.firstChild;
offset = 1;
} else if (isValidTextNode(marker.nextSibling)) {
container = marker.nextSibling;
offset = 0;
} else if (isValidTextNode(marker.previousSibling)) {
container = marker.previousSibling;
offset = marker.previousSibling.data.length;
} else {
container = markerParent;
offset = dom.nodeIndex(marker) + 1;
}
}
} else {
if (!keep) {
container = markerParent;
offset = dom.nodeIndex(marker);
} else {
if (marker.hasChildNodes()) {
container = marker.firstChild;
offset = 1;
} else if (isValidTextNode(marker.previousSibling)) {
container = marker.previousSibling;
offset = marker.previousSibling.data.length;
} else {
container = markerParent;
offset = dom.nodeIndex(marker);
}
}
}
if (!keep) {
const prev = marker.previousSibling;
const next = marker.nextSibling;
Tools.each(Tools.grep(marker.childNodes), (node) => {
if (isText$a(node)) {
node.data = node.data.replace(/\uFEFF/g, "");
}
});
let otherMarker;
while ((otherMarker = dom.get(bookmark.id + "_" + suffix))) {
dom.remove(otherMarker, true);
}
if (isText$a(next) && isText$a(prev) && !Env.browser.isOpera()) {
const idx = prev.data.length;
prev.appendData(next.data);
dom.remove(next);
container = prev;
offset = idx;
}
}
return Optional.some(CaretPosition(container, offset));
} else {
return Optional.none();
}
};
const resolvePaths = (dom, bookmark) => {
const range = dom.createRng();
if (
setEndPoint(dom, true, bookmark, range) &&
setEndPoint(dom, false, bookmark, range)
) {
return Optional.some({
range,
forward: isForwardBookmark(bookmark),
});
} else {
return Optional.none();
}
};
const resolveId = (dom, bookmark) => {
const startPos = restoreEndPoint(dom, "start", bookmark);
const endPos = restoreEndPoint(dom, "end", bookmark);
return lift2(startPos, endPos.or(startPos), (spos, epos) => {
const range = dom.createRng();
range.setStart(addBogus(dom, spos.container()), spos.offset());
range.setEnd(addBogus(dom, epos.container()), epos.offset());
return {
range,
forward: isForwardBookmark(bookmark),
};
});
};
const resolveIndex = (dom, bookmark) =>
Optional.from(dom.select(bookmark.name)[bookmark.index]).map((elm) => {
const range = dom.createRng();
range.selectNode(elm);
return {
range,
forward: true,
};
});
const resolve = (selection, bookmark) => {
const dom = selection.dom;
if (bookmark) {
if (isPathBookmark(bookmark)) {
return resolvePaths(dom, bookmark);
} else if (isStringPathBookmark(bookmark)) {
return resolveCaretPositionBookmark(dom, bookmark);
} else if (isIdBookmark(bookmark)) {
return resolveId(dom, bookmark);
} else if (isIndexBookmark(bookmark)) {
return resolveIndex(dom, bookmark);
} else if (isRangeBookmark(bookmark)) {
return Optional.some({
range: bookmark.rng,
forward: isForwardBookmark(bookmark),
});
}
}
return Optional.none();
};
const getBookmark$1 = (selection, type, normalized) => {
return getBookmark$2(selection, type, normalized);
};
const moveToBookmark = (selection, bookmark) => {
resolve(selection, bookmark).each(({ range, forward }) => {
selection.setRng(range, forward);
});
};
const isBookmarkNode$1 = (node) => {
return (
isElement$6(node) &&
node.tagName === "SPAN" &&
node.getAttribute("data-mce-type") === "bookmark"
);
};
const is = (expected) => (actual) => expected === actual;
const isNbsp = is(nbsp);
const isWhiteSpace = (chr) =>
chr !== "" && " \f\n\r\t\x0B".indexOf(chr) !== -1;
const isContent = (chr) =>
!isWhiteSpace(chr) && !isNbsp(chr) && !isZwsp$2(chr);
const hexColour = (value) => ({ value: normalizeHex(value) });
const normalizeHex = (hex) => removeLeading(hex, "#").toUpperCase();
const toHex = (component) => {
const hex = component.toString(16);
return (hex.length === 1 ? "0" + hex : hex).toUpperCase();
};
const fromRgba = (rgbaColour) => {
const value =
toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
return hexColour(value);
};
const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
const rgbaRegex =
/^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
const rgbaColour = (red, green, blue, alpha) => ({
red,
green,
blue,
alpha,
});
const fromStringValues = (red, green, blue, alpha) => {
const r = parseInt(red, 10);
const g = parseInt(green, 10);
const b = parseInt(blue, 10);
const a = parseFloat(alpha);
return rgbaColour(r, g, b, a);
};
const fromString = (rgbaString) => {
if (rgbaString === "transparent") {
return Optional.some(rgbaColour(0, 0, 0, 0));
}
const rgbMatch = rgbRegex.exec(rgbaString);
if (rgbMatch !== null) {
return Optional.some(
fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], "1")
);
}
const rgbaMatch = rgbaRegex.exec(rgbaString);
if (rgbaMatch !== null) {
return Optional.some(
fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4])
);
}
return Optional.none();
};
const rgbaToHexString = (color) =>
fromString(color)
.map(fromRgba)
.map((h) => "#" + h.value)
.getOr(color);
const getRanges$1 = (selection) => {
const ranges = [];
if (selection) {
for (let i = 0; i < selection.rangeCount; i++) {
ranges.push(selection.getRangeAt(i));
}
}
return ranges;
};
const getSelectedNodes = (ranges) => {
return bind$3(ranges, (range) => {
const node = getSelectedNode(range);
return node ? [SugarElement.fromDom(node)] : [];
});
};
const hasMultipleRanges = (selection) => {
return getRanges$1(selection).length > 1;
};
const getCellsFromRanges = (ranges) =>
filter$5(getSelectedNodes(ranges), isTableCell$2);
const getCellsFromElement = (elm) =>
descendants(elm, "td[data-mce-selected],th[data-mce-selected]");
const getCellsFromElementOrRanges = (ranges, element) => {
const selectedCells = getCellsFromElement(element);
return selectedCells.length > 0
? selectedCells
: getCellsFromRanges(ranges);
};
const getCellsFromEditor = (editor) =>
getCellsFromElementOrRanges(
getRanges$1(editor.selection.getSel()),
SugarElement.fromDom(editor.getBody())
);
const getClosestTable = (cell, isRoot) => ancestor$3(cell, "table", isRoot);
const getStartNode = (rng) => {
const sc = rng.startContainer,
so = rng.startOffset;
if (isText$a(sc)) {
return so === 0
? Optional.some(SugarElement.fromDom(sc))
: Optional.none();
} else {
return Optional.from(sc.childNodes[so]).map(SugarElement.fromDom);
}
};
const getEndNode = (rng) => {
const ec = rng.endContainer,
eo = rng.endOffset;
if (isText$a(ec)) {
return eo === ec.data.length
? Optional.some(SugarElement.fromDom(ec))
: Optional.none();
} else {
return Optional.from(ec.childNodes[eo - 1]).map(SugarElement.fromDom);
}
};
const getFirstChildren = (node) => {
return firstChild(node).fold(constant([node]), (child) => {
return [node].concat(getFirstChildren(child));
});
};
const getLastChildren = (node) => {
return lastChild(node).fold(constant([node]), (child) => {
if (name(child) === "br") {
return prevSibling(child)
.map((sibling) => {
return [node].concat(getLastChildren(sibling));
})
.getOr([]);
} else {
return [node].concat(getLastChildren(child));
}
});
};
const hasAllContentsSelected = (elm, rng) => {
return lift2(getStartNode(rng), getEndNode(rng), (startNode, endNode) => {
const start = find$2(getFirstChildren(elm), curry(eq, startNode));
const end = find$2(getLastChildren(elm), curry(eq, endNode));
return start.isSome() && end.isSome();
}).getOr(false);
};
const moveEndPoint = (dom, rng, node, start) => {
const root = node;
const walker = new DomTreeWalker(node, root);
const moveCaretBeforeOnEnterElementsMap = filter$4(
dom.schema.getMoveCaretBeforeOnEnterElements(),
(_, name) => !contains$2(["td", "th", "table"], name.toLowerCase())
);
let currentNode = node;
do {
if (isText$a(currentNode) && Tools.trim(currentNode.data).length !== 0) {
if (start) {
rng.setStart(currentNode, 0);
} else {
rng.setEnd(currentNode, currentNode.data.length);
}
return;
}
if (moveCaretBeforeOnEnterElementsMap[currentNode.nodeName]) {
if (start) {
rng.setStartBefore(currentNode);
} else {
if (currentNode.nodeName === "BR") {
rng.setEndBefore(currentNode);
} else {
rng.setEndAfter(currentNode);
}
}
return;
}
} while ((currentNode = start ? walker.next() : walker.prev()));
if (root.nodeName === "BODY") {
if (start) {
rng.setStart(root, 0);
} else {
rng.setEnd(root, root.childNodes.length);
}
}
};
const hasAnyRanges = (editor) => {
const sel = editor.selection.getSel();
return isNonNullable(sel) && sel.rangeCount > 0;
};
const runOnRanges = (editor, executor) => {
const fakeSelectionNodes = getCellsFromEditor(editor);
if (fakeSelectionNodes.length > 0) {
each$e(fakeSelectionNodes, (elem) => {
const node = elem.dom;
const fakeNodeRng = editor.dom.createRng();
fakeNodeRng.setStartBefore(node);
fakeNodeRng.setEndAfter(node);
executor(fakeNodeRng, true);
});
} else {
executor(editor.selection.getRng(), false);
}
};
const preserve = (selection, fillBookmark, executor) => {
const bookmark = getPersistentBookmark(selection, fillBookmark);
executor(bookmark);
selection.moveToBookmark(bookmark);
};
const isNode = (node) =>
isNumber(node === null || node === void 0 ? void 0 : node.nodeType);
const isElementNode$1 = (node) =>
isElement$6(node) &&
!isBookmarkNode$1(node) &&
!isCaretNode(node) &&
!isBogus$2(node);
const isElementDirectlySelected = (dom, node) => {
if (isElementNode$1(node) && !/^(TD|TH)$/.test(node.nodeName)) {
const selectedAttr = dom.getAttrib(node, "data-mce-selected");
const value = parseInt(selectedAttr, 10);
return !isNaN(value) && value > 0;
} else {
return false;
}
};
const isEditable$2 = (elm) => elm.isContentEditable === true;
const preserveSelection = (editor, action, shouldMoveStart) => {
const { selection, dom } = editor;
const selectedNodeBeforeAction = selection.getNode();
const isSelectedBeforeNodeNoneditable = isContentEditableFalse$b(
selectedNodeBeforeAction
);
preserve(selection, true, () => {
action();
});
const isBeforeNodeStillNoneditable =
isSelectedBeforeNodeNoneditable &&
isContentEditableFalse$b(selectedNodeBeforeAction);
if (
isBeforeNodeStillNoneditable &&
dom.isChildOf(selectedNodeBeforeAction, editor.getBody())
) {
editor.selection.select(selectedNodeBeforeAction);
} else if (shouldMoveStart(selection.getStart())) {
moveStartToNearestText(dom, selection);
}
};
const moveStartToNearestText = (dom, selection) => {
var _a, _b;
const rng = selection.getRng();
const { startContainer, startOffset } = rng;
const selectedNode = selection.getNode();
if (isElementDirectlySelected(dom, selectedNode)) {
return;
}
if (isElement$6(startContainer)) {
const nodes = startContainer.childNodes;
const root = dom.getRoot();
let walker;
if (startOffset < nodes.length) {
const startNode = nodes[startOffset];
walker = new DomTreeWalker(
startNode,
(_a = dom.getParent(startNode, dom.isBlock)) !== null && _a !== void 0
? _a
: root
);
} else {
const startNode = nodes[nodes.length - 1];
walker = new DomTreeWalker(
startNode,
(_b = dom.getParent(startNode, dom.isBlock)) !== null && _b !== void 0
? _b
: root
);
walker.next(true);
}
for (let node = walker.current(); node; node = walker.next()) {
if (dom.getContentEditable(node) === "false") {
return;
} else if (isText$a(node) && !isWhiteSpaceNode$1(node)) {
rng.setStart(node, 0);
selection.setRng(rng);
return;
}
}
}
};
const getNonWhiteSpaceSibling = (node, next, inc) => {
if (node) {
const nextName = next ? "nextSibling" : "previousSibling";
for (node = inc ? node : node[nextName]; node; node = node[nextName]) {
if (isElement$6(node) || !isWhiteSpaceNode$1(node)) {
return node;
}
}
}
return undefined;
};
const isTextBlock$1 = (schema, node) =>
!!schema.getTextBlockElements()[node.nodeName.toLowerCase()] ||
isTransparentBlock(schema, node);
const isValid = (ed, parent, child) => {
return ed.schema.isValidChild(parent, child);
};
const isWhiteSpaceNode$1 = (node, allowSpaces = false) => {
if (isNonNullable(node) && isText$a(node)) {
const data = allowSpaces ? node.data.replace(/ /g, "\xA0") : node.data;
return isWhitespaceText(data);
} else {
return false;
}
};
const isEmptyTextNode$1 = (node) => {
return isNonNullable(node) && isText$a(node) && node.length === 0;
};
const isWrapNoneditableTarget = (editor, node) => {
const baseDataSelector = "[data-mce-cef-wrappable]";
const formatNoneditableSelector = getFormatNoneditableSelector(editor);
const selector = isEmpty$3(formatNoneditableSelector)
? baseDataSelector
: `${baseDataSelector},${formatNoneditableSelector}`;
return is$1(SugarElement.fromDom(node), selector);
};
const isWrappableNoneditable = (editor, node) => {
const dom = editor.dom;
return (
isElementNode$1(node) &&
dom.getContentEditable(node) === "false" &&
isWrapNoneditableTarget(editor, node) &&
dom.select('[contenteditable="true"]', node).length === 0
);
};
const replaceVars = (value, vars) => {
if (isFunction(value)) {
return value(vars);
} else if (isNonNullable(vars)) {
value = value.replace(/%(\w+)/g, (str, name) => {
return vars[name] || str;
});
}
return value;
};
const isEq$5 = (str1, str2) => {
str1 = str1 || "";
str2 = str2 || "";
str1 = "" + (str1.nodeName || str1);
str2 = "" + (str2.nodeName || str2);
return str1.toLowerCase() === str2.toLowerCase();
};
const normalizeStyleValue = (value, name) => {
if (isNullable(value)) {
return null;
} else {
let strValue = String(value);
if (name === "color" || name === "backgroundColor") {
strValue = rgbaToHexString(strValue);
}
if (name === "fontWeight" && value === 700) {
strValue = "bold";
}
if (name === "fontFamily") {
strValue = strValue.replace(/[\'\"]/g, "").replace(/,\s+/g, ",");
}
return strValue;
}
};
const getStyle = (dom, node, name) => {
const style = dom.getStyle(node, name);
return normalizeStyleValue(style, name);
};
const getTextDecoration = (dom, node) => {
let decoration;
dom.getParent(node, (n) => {
if (isElement$6(n)) {
decoration = dom.getStyle(n, "text-decoration");
return !!decoration && decoration !== "none";
} else {
return false;
}
});
return decoration;
};
const getParents$2 = (dom, node, selector) => {
return dom.getParents(node, selector, dom.getRoot());
};
const isFormatPredicate = (editor, formatName, predicate) => {
const formats = editor.formatter.get(formatName);
return isNonNullable(formats) && exists(formats, predicate);
};
const isVariableFormatName = (editor, formatName) => {
const hasVariableValues = (format) => {
const isVariableValue = (val) =>
isFunction(val) || (val.length > 1 && val.charAt(0) === "%");
return exists(["styles", "attributes"], (key) =>
get$a(format, key).exists((field) => {
const fieldValues = isArray$1(field) ? field : values(field);
return exists(fieldValues, isVariableValue);
})
);
};
return isFormatPredicate(editor, formatName, hasVariableValues);
};
const areSimilarFormats = (editor, formatName, otherFormatName) => {
const validKeys = [
"inline",
"block",
"selector",
"attributes",
"styles",
"classes",
];
const filterObj = (format) =>
filter$4(format, (_, key) =>
exists(validKeys, (validKey) => validKey === key)
);
return isFormatPredicate(editor, formatName, (fmt1) => {
const filteredFmt1 = filterObj(fmt1);
return isFormatPredicate(editor, otherFormatName, (fmt2) => {
const filteredFmt2 = filterObj(fmt2);
return equal$1(filteredFmt1, filteredFmt2);
});
});
};
const isBlockFormat = (format) => hasNonNullableKey(format, "block");
const isWrappingBlockFormat = (format) =>
isBlockFormat(format) && format.wrapper === true;
const isNonWrappingBlockFormat = (format) =>
isBlockFormat(format) && format.wrapper !== true;
const isSelectorFormat = (format) => hasNonNullableKey(format, "selector");
const isInlineFormat = (format) => hasNonNullableKey(format, "inline");
const isMixedFormat = (format) =>
isSelectorFormat(format) &&
isInlineFormat(format) &&
is$2(get$a(format, "mixed"), true);
const shouldExpandToSelector = (format) =>
isSelectorFormat(format) &&
format.expand !== false &&
!isInlineFormat(format);
const isBookmarkNode = isBookmarkNode$1;
const getParents$1 = getParents$2;
const isWhiteSpaceNode = isWhiteSpaceNode$1;
const isTextBlock = isTextBlock$1;
const isBogusBr = (node) => {
return (
isBr$6(node) && node.getAttribute("data-mce-bogus") && !node.nextSibling
);
};
const findParentContentEditable = (dom, node) => {
let parent = node;
while (parent) {
if (isElement$6(parent) && dom.getContentEditable(parent)) {
return dom.getContentEditable(parent) === "false" ? parent : node;
}
parent = parent.parentNode;
}
return node;
};
const walkText = (start, node, offset, predicate) => {
const str = node.data;
if (start) {
for (let i = offset; i > 0; i--) {
if (predicate(str.charAt(i - 1))) {
return i;
}
}
} else {
for (let i = offset; i < str.length; i++) {
if (predicate(str.charAt(i))) {
return i;
}
}
}
return -1;
};
const findSpace = (start, node, offset) =>
walkText(start, node, offset, (c) => isNbsp(c) || isWhiteSpace(c));
const findContent = (start, node, offset) =>
walkText(start, node, offset, isContent);
const findWordEndPoint = (
dom,
body,
container,
offset,
start,
includeTrailingSpaces
) => {
let lastTextNode;
const rootNode = dom.getParent(container, dom.isBlock) || body;
const walk = (container, offset, pred) => {
const textSeeker = TextSeeker(dom);
const walker = start ? textSeeker.backwards : textSeeker.forwards;
return Optional.from(
walker(
container,
offset,
(text, textOffset) => {
if (isBookmarkNode(text.parentNode)) {
return -1;
} else {
lastTextNode = text;
return pred(start, text, textOffset);
}
},
rootNode
)
);
};
const spaceResult = walk(container, offset, findSpace);
return spaceResult
.bind((result) =>
includeTrailingSpaces
? walk(
result.container,
result.offset + (start ? -1 : 0),
findContent
)
: Optional.some(result)
)
.orThunk(() =>
lastTextNode
? Optional.some({
container: lastTextNode,
offset: start ? 0 : lastTextNode.length,
})
: Optional.none()
);
};
const findSelectorEndPoint = (
dom,
formatList,
rng,
container,
siblingName
) => {
const sibling = container[siblingName];
if (isText$a(container) && isEmpty$3(container.data) && sibling) {
container = sibling;
}
const parents = getParents$1(dom, container);
for (let i = 0; i < parents.length; i++) {
for (let y = 0; y < formatList.length; y++) {
const curFormat = formatList[y];
if (
isNonNullable(curFormat.collapsed) &&
curFormat.collapsed !== rng.collapsed
) {
continue;
}
if (
isSelectorFormat(curFormat) &&
dom.is(parents[i], curFormat.selector)
) {
return parents[i];
}
}
}
return container;
};
const findBlockEndPoint = (dom, formatList, container, siblingName) => {
var _a;
let node = container;
const root = dom.getRoot();
const format = formatList[0];
if (isBlockFormat(format)) {
node = format.wrapper
? null
: dom.getParent(container, format.block, root);
}
if (!node) {
const scopeRoot =
(_a = dom.getParent(container, "LI,TD,TH")) !== null && _a !== void 0
? _a
: root;
node = dom.getParent(
isText$a(container) ? container.parentNode : container,
(node) => node !== root && isTextBlock(dom.schema, node),
scopeRoot
);
}
if (node && isBlockFormat(format) && format.wrapper) {
node = getParents$1(dom, node, "ul,ol").reverse()[0] || node;
}
if (!node) {
node = container;
while (node && node[siblingName] && !dom.isBlock(node[siblingName])) {
node = node[siblingName];
if (isEq$5(node, "br")) {
break;
}
}
}
return node || container;
};
const isAtBlockBoundary$1 = (dom, root, container, siblingName) => {
const parent = container.parentNode;
if (isNonNullable(container[siblingName])) {
return false;
} else if (parent === root || isNullable(parent) || dom.isBlock(parent)) {
return true;
} else {
return isAtBlockBoundary$1(dom, root, parent, siblingName);
}
};
const findParentContainer = (dom, formatList, container, offset, start) => {
let parent = container;
const siblingName = start ? "previousSibling" : "nextSibling";
const root = dom.getRoot();
if (isText$a(container) && !isWhiteSpaceNode(container)) {
if (start ? offset > 0 : offset < container.data.length) {
return container;
}
}
while (parent) {
if (!formatList[0].block_expand && dom.isBlock(parent)) {
return parent;
}
for (
let sibling = parent[siblingName];
sibling;
sibling = sibling[siblingName]
) {
const allowSpaces =
isText$a(sibling) &&
!isAtBlockBoundary$1(dom, root, sibling, siblingName);
if (
!isBookmarkNode(sibling) &&
!isBogusBr(sibling) &&
!isWhiteSpaceNode(sibling, allowSpaces)
) {
return parent;
}
}
if (parent === root || parent.parentNode === root) {
container = parent;
break;
}
parent = parent.parentNode;
}
return container;
};
const isSelfOrParentBookmark = (container) =>
isBookmarkNode(container.parentNode) || isBookmarkNode(container);
const expandRng = (dom, rng, formatList, includeTrailingSpace = false) => {
let { startContainer, startOffset, endContainer, endOffset } = rng;
const format = formatList[0];
if (isElement$6(startContainer) && startContainer.hasChildNodes()) {
startContainer = getNode$1(startContainer, startOffset);
if (isText$a(startContainer)) {
startOffset = 0;
}
}
if (isElement$6(endContainer) && endContainer.hasChildNodes()) {
endContainer = getNode$1(
endContainer,
rng.collapsed ? endOffset : endOffset - 1
);
if (isText$a(endContainer)) {
endOffset = endContainer.data.length;
}
}
startContainer = findParentContentEditable(dom, startContainer);
endContainer = findParentContentEditable(dom, endContainer);
if (isSelfOrParentBookmark(startContainer)) {
startContainer = isBookmarkNode(startContainer)
? startContainer
: startContainer.parentNode;
if (rng.collapsed) {
startContainer = startContainer.previousSibling || startContainer;
} else {
startContainer = startContainer.nextSibling || startContainer;
}
if (isText$a(startContainer)) {
startOffset = rng.collapsed ? startContainer.length : 0;
}
}
if (isSelfOrParentBookmark(endContainer)) {
endContainer = isBookmarkNode(endContainer)
? endContainer
: endContainer.parentNode;
if (rng.collapsed) {
endContainer = endContainer.nextSibling || endContainer;
} else {
endContainer = endContainer.previousSibling || endContainer;
}
if (isText$a(endContainer)) {
endOffset = rng.collapsed ? 0 : endContainer.length;
}
}
if (rng.collapsed) {
const startPoint = findWordEndPoint(
dom,
dom.getRoot(),
startContainer,
startOffset,
true,
includeTrailingSpace
);
startPoint.each(({ container, offset }) => {
startContainer = container;
startOffset = offset;
});
const endPoint = findWordEndPoint(
dom,
dom.getRoot(),
endContainer,
endOffset,
false,
includeTrailingSpace
);
endPoint.each(({ container, offset }) => {
endContainer = container;
endOffset = offset;
});
}
if (isInlineFormat(format) || format.block_expand) {
if (
!isInlineFormat(format) ||
!isText$a(startContainer) ||
startOffset === 0
) {
startContainer = findParentContainer(
dom,
formatList,
startContainer,
startOffset,
true
);
}
if (
!isInlineFormat(format) ||
!isText$a(endContainer) ||
endOffset === endContainer.data.length
) {
endContainer = findParentContainer(
dom,
formatList,
endContainer,
endOffset,
false
);
}
}
if (shouldExpandToSelector(format)) {
startContainer = findSelectorEndPoint(
dom,
formatList,
rng,
startContainer,
"previousSibling"
);
endContainer = findSelectorEndPoint(
dom,
formatList,
rng,
endContainer,
"nextSibling"
);
}
if (isBlockFormat(format) || isSelectorFormat(format)) {
startContainer = findBlockEndPoint(
dom,
formatList,
startContainer,
"previousSibling"
);
endContainer = findBlockEndPoint(
dom,
formatList,
endContainer,
"nextSibling"
);
if (isBlockFormat(format)) {
if (!dom.isBlock(startContainer)) {
startContainer = findParentContainer(
dom,
formatList,
startContainer,
startOffset,
true
);
}
if (!dom.isBlock(endContainer)) {
endContainer = findParentContainer(
dom,
formatList,
endContainer,
endOffset,
false
);
}
}
}
if (isElement$6(startContainer) && startContainer.parentNode) {
startOffset = dom.nodeIndex(startContainer);
startContainer = startContainer.parentNode;
}
if (isElement$6(endContainer) && endContainer.parentNode) {
endOffset = dom.nodeIndex(endContainer) + 1;
endContainer = endContainer.parentNode;
}
return {
startContainer,
startOffset,
endContainer,
endOffset,
};
};
const walk$3 = (dom, rng, callback) => {
var _a;
const startOffset = rng.startOffset;
const startContainer = getNode$1(rng.startContainer, startOffset);
const endOffset = rng.endOffset;
const endContainer = getNode$1(rng.endContainer, endOffset - 1);
const exclude = (nodes) => {
const firstNode = nodes[0];
if (
isText$a(firstNode) &&
firstNode === startContainer &&
startOffset >= firstNode.data.length
) {
nodes.splice(0, 1);
}
const lastNode = nodes[nodes.length - 1];
if (
endOffset === 0 &&
nodes.length > 0 &&
lastNode === endContainer &&
isText$a(lastNode)
) {
nodes.splice(nodes.length - 1, 1);
}
return nodes;
};
const collectSiblings = (node, name, endNode) => {
const siblings = [];
for (; node && node !== endNode; node = node[name]) {
siblings.push(node);
}
return siblings;
};
const findEndPoint = (node, root) =>
dom.getParent(node, (node) => node.parentNode === root, root);
const walkBoundary = (startNode, endNode, next) => {
const siblingName = next ? "nextSibling" : "previousSibling";
for (
let node = startNode, parent = node.parentNode;
node && node !== endNode;
node = parent
) {
parent = node.parentNode;
const siblings = collectSiblings(
node === startNode ? node : node[siblingName],
siblingName
);
if (siblings.length) {
if (!next) {
siblings.reverse();
}
callback(exclude(siblings));
}
}
};
if (startContainer === endContainer) {
return callback(exclude([startContainer]));
}
const ancestor =
(_a = dom.findCommonAncestor(startContainer, endContainer)) !== null &&
_a !== void 0
? _a
: dom.getRoot();
if (dom.isChildOf(startContainer, endContainer)) {
return walkBoundary(startContainer, ancestor, true);
}
if (dom.isChildOf(endContainer, startContainer)) {
return walkBoundary(endContainer, ancestor);
}
const startPoint = findEndPoint(startContainer, ancestor) || startContainer;
const endPoint = findEndPoint(endContainer, ancestor) || endContainer;
walkBoundary(startContainer, startPoint, true);
const siblings = collectSiblings(
startPoint === startContainer ? startPoint : startPoint.nextSibling,
"nextSibling",
endPoint === endContainer ? endPoint.nextSibling : endPoint
);
if (siblings.length) {
callback(exclude(siblings));
}
walkBoundary(endContainer, endPoint);
};
const validBlocks = [
'pre[class*=language-][contenteditable="false"]',
"figure.image",
"div[data-ephox-embed-iri]",
"div.tiny-pageembed",
"div.mce-toc",
"div[data-mce-toc]",
];
const isZeroWidth = (elem) => isText$b(elem) && get$3(elem) === ZWSP$1;
const context = (editor, elem, wrapName, nodeName) =>
parent(elem).fold(
() => "skipping",
(parent) => {
if (nodeName === "br" || isZeroWidth(elem)) {
return "valid";
} else if (isAnnotation(elem)) {
return "existing";
} else if (isCaretNode(elem.dom)) {
return "caret";
} else if (exists(validBlocks, (selector) => is$1(elem, selector))) {
return "valid-block";
} else if (
!isValid(editor, wrapName, nodeName) ||
!isValid(editor, name(parent), wrapName)
) {
return "invalid-child";
} else {
return "valid";
}
}
);
const applyWordGrab = (editor, rng) => {
const r = expandRng(editor.dom, rng, [{ inline: "span" }]);
rng.setStart(r.startContainer, r.startOffset);
rng.setEnd(r.endContainer, r.endOffset);
editor.selection.setRng(rng);
};
const applyAnnotation = (
elem,
masterUId,
data,
annotationName,
decorate,
directAnnotation
) => {
const { uid = masterUId, ...otherData } = data;
add$2(elem, annotation());
set$3(elem, `${dataAnnotationId()}`, uid);
set$3(elem, `${dataAnnotation()}`, annotationName);
const { attributes = {}, classes = [] } = decorate(uid, otherData);
setAll$1(elem, attributes);
add(elem, classes);
if (directAnnotation) {
if (classes.length > 0) {
set$3(elem, `${dataAnnotationClasses()}`, classes.join(","));
}
const attributeNames = keys(attributes);
if (attributeNames.length > 0) {
set$3(elem, `${dataAnnotationAttributes()}`, attributeNames.join(","));
}
}
};
const removeDirectAnnotation = (elem) => {
remove$7(elem, annotation());
remove$a(elem, `${dataAnnotationId()}`);
remove$a(elem, `${dataAnnotation()}`);
remove$a(elem, `${dataAnnotationActive()}`);
const customAttrNames = getOpt(elem, `${dataAnnotationAttributes()}`)
.map((names) => names.split(","))
.getOr([]);
const customClasses = getOpt(elem, `${dataAnnotationClasses()}`)
.map((names) => names.split(","))
.getOr([]);
each$e(customAttrNames, (name) => remove$a(elem, name));
remove$4(elem, customClasses);
remove$a(elem, `${dataAnnotationClasses()}`);
remove$a(elem, `${dataAnnotationAttributes()}`);
};
const makeAnnotation = (eDoc, uid, data, annotationName, decorate) => {
const master = SugarElement.fromTag("span", eDoc);
applyAnnotation(master, uid, data, annotationName, decorate, false);
return master;
};
const annotate = (editor, rng, uid, annotationName, decorate, data) => {
const newWrappers = [];
const master = makeAnnotation(
editor.getDoc(),
uid,
data,
annotationName,
decorate
);
const wrapper = value$2();
const finishWrapper = () => {
wrapper.clear();
};
const getOrOpenWrapper = () =>
wrapper.get().getOrThunk(() => {
const nu = shallow$1(master);
newWrappers.push(nu);
wrapper.set(nu);
return nu;
});
const processElements = (elems) => {
each$e(elems, processElement);
};
const processElement = (elem) => {
const ctx = context(editor, elem, "span", name(elem));
switch (ctx) {
case "invalid-child": {
finishWrapper();
const children = children$1(elem);
processElements(children);
finishWrapper();
break;
}
case "valid-block": {
finishWrapper();
applyAnnotation(elem, uid, data, annotationName, decorate, true);
break;
}
case "valid": {
const w = getOrOpenWrapper();
wrap$2(elem, w);
break;
}
}
};
const processNodes = (nodes) => {
const elems = map$3(nodes, SugarElement.fromDom);
processElements(elems);
};
walk$3(editor.dom, rng, (nodes) => {
finishWrapper();
processNodes(nodes);
});
return newWrappers;
};
const annotateWithBookmark = (editor, name, settings, data) => {
editor.undoManager.transact(() => {
const selection = editor.selection;
const initialRng = selection.getRng();
const hasFakeSelection = getCellsFromEditor(editor).length > 0;
const masterUid = generate$1("mce-annotation");
if (initialRng.collapsed && !hasFakeSelection) {
applyWordGrab(editor, initialRng);
}
if (selection.getRng().collapsed && !hasFakeSelection) {
const wrapper = makeAnnotation(
editor.getDoc(),
masterUid,
data,
name,
settings.decorate
);
set$1(wrapper, nbsp);
selection.getRng().insertNode(wrapper.dom);
selection.select(wrapper.dom);
} else {
preserve(selection, false, () => {
runOnRanges(editor, (selectionRng) => {
annotate(
editor,
selectionRng,
masterUid,
name,
settings.decorate,
data
);
});
});
}
});
};
const Annotator = (editor) => {
const registry = create$c();
setup$w(editor, registry);
const changes = setup$x(editor, registry);
const isSpan = isTag("span");
const removeAnnotations = (elements) => {
each$e(elements, (element) => {
if (isSpan(element)) {
unwrap(element);
} else {
removeDirectAnnotation(element);
}
});
};
return {
register: (name, settings) => {
registry.register(name, settings);
},
annotate: (name, data) => {
registry.lookup(name).each((settings) => {
annotateWithBookmark(editor, name, settings, data);
});
},
annotationChanged: (name, callback) => {
changes.addListener(name, callback);
},
remove: (name) => {
identify(editor, Optional.some(name)).each(({ elements }) => {
const bookmark = editor.selection.getBookmark();
removeAnnotations(elements);
editor.selection.moveToBookmark(bookmark);
});
},
removeAll: (name) => {
const bookmark = editor.selection.getBookmark();
each$d(findAll(editor, name), (elements, _) => {
removeAnnotations(elements);
});
editor.selection.moveToBookmark(bookmark);
},
getAll: (name) => {
const directory = findAll(editor, name);
return map$2(directory, (elems) => map$3(elems, (elem) => elem.dom));
},
};
};
const BookmarkManager = (selection) => {
return {
getBookmark: curry(getBookmark$1, selection),
moveToBookmark: curry(moveToBookmark, selection),
};
};
BookmarkManager.isBookmarkNode = isBookmarkNode$1;
const isXYWithinRange = (clientX, clientY, range) => {
if (range.collapsed) {
return false;
} else {
return exists(range.getClientRects(), (rect) =>
containsXY(rect, clientX, clientY)
);
}
};
const firePreProcess = (editor, args) => editor.dispatch("PreProcess", args);
const firePostProcess = (editor, args) =>
editor.dispatch("PostProcess", args);
const fireRemove = (editor) => {
editor.dispatch("remove");
};
const fireDetach = (editor) => {
editor.dispatch("detach");
};
const fireSwitchMode = (editor, mode) => {
editor.dispatch("SwitchMode", { mode });
};
const fireObjectResizeStart = (editor, target, width, height, origin) => {
editor.dispatch("ObjectResizeStart", {
target,
width,
height,
origin,
});
};
const fireObjectResized = (editor, target, width, height, origin) => {
editor.dispatch("ObjectResized", {
target,
width,
height,
origin,
});
};
const firePreInit = (editor) => {
editor.dispatch("PreInit");
};
const firePostRender = (editor) => {
editor.dispatch("PostRender");
};
const fireInit = (editor) => {
editor.dispatch("Init");
};
const firePlaceholderToggle = (editor, state) => {
editor.dispatch("PlaceholderToggle", { state });
};
const fireError = (editor, errorType, error) => {
editor.dispatch(errorType, error);
};
const fireFormatApply = (editor, format, node, vars) => {
editor.dispatch("FormatApply", {
format,
node,
vars,
});
};
const fireFormatRemove = (editor, format, node, vars) => {
editor.dispatch("FormatRemove", {
format,
node,
vars,
});
};
const fireBeforeSetContent = (editor, args) =>
editor.dispatch("BeforeSetContent", args);
const fireSetContent = (editor, args) => editor.dispatch("SetContent", args);
const fireBeforeGetContent = (editor, args) =>
editor.dispatch("BeforeGetContent", args);
const fireGetContent = (editor, args) => editor.dispatch("GetContent", args);
const fireAutocompleterStart = (editor, args) => {
editor.dispatch("AutocompleterStart", args);
};
const fireAutocompleterUpdate = (editor, args) => {
editor.dispatch("AutocompleterUpdate", args);
};
const fireAutocompleterEnd = (editor) => {
editor.dispatch("AutocompleterEnd");
};
const firePastePreProcess = (editor, html, internal) =>
editor.dispatch("PastePreProcess", {
content: html,
internal,
});
const firePastePostProcess = (editor, node, internal) =>
editor.dispatch("PastePostProcess", {
node,
internal,
});
const firePastePlainTextToggle = (editor, state) =>
editor.dispatch("PastePlainTextToggle", { state });
const fireEditableRootStateChange = (editor, state) =>
editor.dispatch("EditableRootStateChange", { state });
const VK = {
BACKSPACE: 8,
DELETE: 46,
DOWN: 40,
ENTER: 13,
ESC: 27,
LEFT: 37,
RIGHT: 39,
SPACEBAR: 32,
TAB: 9,
UP: 38,
PAGE_UP: 33,
PAGE_DOWN: 34,
END: 35,
HOME: 36,
modifierPressed: (e) => {
return e.shiftKey || e.ctrlKey || e.altKey || VK.metaKeyPressed(e);
},
metaKeyPressed: (e) => {
return Env.os.isMacOS() || Env.os.isiOS()
? e.metaKey
: e.ctrlKey && !e.altKey;
},
};
const elementSelectionAttr = "data-mce-selected";
const controlElmSelector =
"table,img,figure.image,hr,video,span.mce-preview-object,details";
const abs = Math.abs;
const round$1 = Math.round;
const resizeHandles = {
nw: [0, 0, -1, -1],
ne: [1, 0, 1, -1],
se: [1, 1, 1, 1],
sw: [0, 1, -1, 1],
};
const isTouchEvent = (evt) =>
evt.type === "longpress" || evt.type.indexOf("touch") === 0;
const ControlSelection = (selection, editor) => {
const dom = editor.dom;
const editableDoc = editor.getDoc();
const rootDocument = document;
const rootElement = editor.getBody();
let selectedElm,
selectedElmGhost,
resizeHelper,
selectedHandle,
resizeBackdrop;
let startX,
startY,
selectedElmX,
selectedElmY,
startW,
startH,
ratio,
resizeStarted;
let width;
let height;
let startScrollWidth;
let startScrollHeight;
const isImage = (elm) =>
isNonNullable(elm) && (isImg(elm) || dom.is(elm, "figure.image"));
const isMedia = (elm) =>
isMedia$2(elm) || dom.hasClass(elm, "mce-preview-object");
const isEventOnImageOutsideRange = (evt, range) => {
if (isTouchEvent(evt)) {
const touch = evt.touches[0];
return (
isImage(evt.target) &&
!isXYWithinRange(touch.clientX, touch.clientY, range)
);
} else {
return (
isImage(evt.target) &&
!isXYWithinRange(evt.clientX, evt.clientY, range)
);
}
};
const contextMenuSelectImage = (evt) => {
const target = evt.target;
if (
isEventOnImageOutsideRange(evt, editor.selection.getRng()) &&
!evt.isDefaultPrevented()
) {
editor.selection.select(target);
}
};
const getResizeTargets = (elm) => {
if (
dom.hasClass(elm, "mce-preview-object") &&
isNonNullable(elm.firstElementChild)
) {
return [elm, elm.firstElementChild];
} else if (dom.is(elm, "figure.image")) {
return [elm.querySelector("img")];
} else {
return [elm];
}
};
const isResizable = (elm) => {
const selector = getObjectResizing(editor);
if (!selector) {
return false;
}
if (elm.getAttribute("data-mce-resize") === "false") {
return false;
}
if (elm === editor.getBody()) {
return false;
}
if (
dom.hasClass(elm, "mce-preview-object") &&
isNonNullable(elm.firstElementChild)
) {
return is$1(SugarElement.fromDom(elm.firstElementChild), selector);
} else {
return is$1(SugarElement.fromDom(elm), selector);
}
};
const createGhostElement = (elm) => {
if (isMedia(elm)) {
return dom.create("img", { src: Env.transparentSrc });
} else {
return elm.cloneNode(true);
}
};
const setSizeProp = (element, name, value) => {
if (isNonNullable(value)) {
const targets = getResizeTargets(element);
each$e(targets, (target) => {
if (
target.style[name] ||
!editor.schema.isValid(target.nodeName.toLowerCase(), name)
) {
dom.setStyle(target, name, value);
} else {
dom.setAttrib(target, name, "" + value);
}
});
}
};
const setGhostElmSize = (ghostElm, width, height) => {
setSizeProp(ghostElm, "width", width);
setSizeProp(ghostElm, "height", height);
};
const resizeGhostElement = (e) => {
let deltaX, deltaY, proportional;
let resizeHelperX, resizeHelperY;
deltaX = e.screenX - startX;
deltaY = e.screenY - startY;
width = deltaX * selectedHandle[2] + startW;
height = deltaY * selectedHandle[3] + startH;
width = width < 5 ? 5 : width;
height = height < 5 ? 5 : height;
if (
(isImage(selectedElm) || isMedia(selectedElm)) &&
getResizeImgProportional(editor) !== false
) {
proportional = !VK.modifierPressed(e);
} else {
proportional = VK.modifierPressed(e);
}
if (proportional) {
if (abs(deltaX) > abs(deltaY)) {
height = round$1(width * ratio);
width = round$1(height / ratio);
} else {
width = round$1(height / ratio);
height = round$1(width * ratio);
}
}
setGhostElmSize(selectedElmGhost, width, height);
resizeHelperX = selectedHandle.startPos.x + deltaX;
resizeHelperY = selectedHandle.startPos.y + deltaY;
resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
dom.setStyles(resizeHelper, {
left: resizeHelperX,
top: resizeHelperY,
display: "block",
});
resizeHelper.innerHTML = width + " × " + height;
if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
dom.setStyle(selectedElmGhost, "left", selectedElmX + (startW - width));
}
if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
dom.setStyle(selectedElmGhost, "top", selectedElmY + (startH - height));
}
deltaX = rootElement.scrollWidth - startScrollWidth;
deltaY = rootElement.scrollHeight - startScrollHeight;
if (deltaX + deltaY !== 0) {
dom.setStyles(resizeHelper, {
left: resizeHelperX - deltaX,
top: resizeHelperY - deltaY,
});
}
if (!resizeStarted) {
fireObjectResizeStart(
editor,
selectedElm,
startW,
startH,
"corner-" + selectedHandle.name
);
resizeStarted = true;
}
};
const endGhostResize = () => {
const wasResizeStarted = resizeStarted;
resizeStarted = false;
if (wasResizeStarted) {
setSizeProp(selectedElm, "width", width);
setSizeProp(selectedElm, "height", height);
}
dom.unbind(editableDoc, "mousemove", resizeGhostElement);
dom.unbind(editableDoc, "mouseup", endGhostResize);
if (rootDocument !== editableDoc) {
dom.unbind(rootDocument, "mousemove", resizeGhostElement);
dom.unbind(rootDocument, "mouseup", endGhostResize);
}
dom.remove(selectedElmGhost);
dom.remove(resizeHelper);
dom.remove(resizeBackdrop);
showResizeRect(selectedElm);
if (wasResizeStarted) {
fireObjectResized(
editor,
selectedElm,
width,
height,
"corner-" + selectedHandle.name
);
dom.setAttrib(
selectedElm,
"style",
dom.getAttrib(selectedElm, "style")
);
}
editor.nodeChanged();
};
const showResizeRect = (targetElm) => {
unbindResizeHandleEvents();
const position = dom.getPos(targetElm, rootElement);
const selectedElmX = position.x;
const selectedElmY = position.y;
const rect = targetElm.getBoundingClientRect();
const targetWidth = rect.width || rect.right - rect.left;
const targetHeight = rect.height || rect.bottom - rect.top;
if (selectedElm !== targetElm) {
hideResizeRect();
selectedElm = targetElm;
width = height = 0;
}
const e = editor.dispatch("ObjectSelected", { target: targetElm });
if (isResizable(targetElm) && !e.isDefaultPrevented()) {
each$d(resizeHandles, (handle, name) => {
const startDrag = (e) => {
const target = getResizeTargets(selectedElm)[0];
startX = e.screenX;
startY = e.screenY;
startW = target.clientWidth;
startH = target.clientHeight;
ratio = startH / startW;
selectedHandle = handle;
selectedHandle.name = name;
selectedHandle.startPos = {
x: targetWidth * handle[0] + selectedElmX,
y: targetHeight * handle[1] + selectedElmY,
};
startScrollWidth = rootElement.scrollWidth;
startScrollHeight = rootElement.scrollHeight;
resizeBackdrop = dom.add(rootElement, "div", {
class: "mce-resize-backdrop",
"data-mce-bogus": "all",
});
dom.setStyles(resizeBackdrop, {
position: "fixed",
left: "0",
top: "0",
width: "100%",
height: "100%",
});
selectedElmGhost = createGhostElement(selectedElm);
dom.addClass(selectedElmGhost, "mce-clonedresizable");
dom.setAttrib(selectedElmGhost, "data-mce-bogus", "all");
selectedElmGhost.contentEditable = "false";
dom.setStyles(selectedElmGhost, {
left: selectedElmX,
top: selectedElmY,
margin: 0,
});
setGhostElmSize(selectedElmGhost, targetWidth, targetHeight);
selectedElmGhost.removeAttribute(elementSelectionAttr);
rootElement.appendChild(selectedElmGhost);
dom.bind(editableDoc, "mousemove", resizeGhostElement);
dom.bind(editableDoc, "mouseup", endGhostResize);
if (rootDocument !== editableDoc) {
dom.bind(rootDocument, "mousemove", resizeGhostElement);
dom.bind(rootDocument, "mouseup", endGhostResize);
}
resizeHelper = dom.add(
rootElement,
"div",
{
class: "mce-resize-helper",
"data-mce-bogus": "all",
},
startW + " × " + startH
);
};
let handleElm = dom.get("mceResizeHandle" + name);
if (handleElm) {
dom.remove(handleElm);
}
handleElm = dom.add(rootElement, "div", {
id: "mceResizeHandle" + name,
"data-mce-bogus": "all",
class: "mce-resizehandle",
unselectable: true,
style: "cursor:" + name + "-resize; margin:0; padding:0",
});
dom.bind(handleElm, "mousedown", (e) => {
e.stopImmediatePropagation();
e.preventDefault();
startDrag(e);
});
handle.elm = handleElm;
dom.setStyles(handleElm, {
left:
targetWidth * handle[0] +
selectedElmX -
handleElm.offsetWidth / 2,
top:
targetHeight * handle[1] +
selectedElmY -
handleElm.offsetHeight / 2,
});
});
} else {
hideResizeRect(false);
}
};
const throttledShowResizeRect = first$1(showResizeRect, 0);
const hideResizeRect = (removeSelected = true) => {
throttledShowResizeRect.cancel();
unbindResizeHandleEvents();
if (selectedElm && removeSelected) {
selectedElm.removeAttribute(elementSelectionAttr);
}
each$d(resizeHandles, (value, name) => {
const handleElm = dom.get("mceResizeHandle" + name);
if (handleElm) {
dom.unbind(handleElm);
dom.remove(handleElm);
}
});
};
const isChildOrEqual = (node, parent) => dom.isChildOf(node, parent);
const updateResizeRect = (e) => {
if (resizeStarted || editor.removed || editor.composing) {
return;
}
const targetElm = e.type === "mousedown" ? e.target : selection.getNode();
const controlElm = closest$3(
SugarElement.fromDom(targetElm),
controlElmSelector
)
.map((e) => e.dom)
.filter((e) => dom.isEditable(e.parentElement))
.getOrUndefined();
const selectedValue = isNonNullable(controlElm)
? dom.getAttrib(controlElm, elementSelectionAttr, "1")
: "1";
each$e(
dom.select(`img[${elementSelectionAttr}],hr[${elementSelectionAttr}]`),
(img) => {
img.removeAttribute(elementSelectionAttr);
}
);
if (
isNonNullable(controlElm) &&
isChildOrEqual(controlElm, rootElement) &&
editor.hasFocus()
) {
disableGeckoResize();
const startElm = selection.getStart(true);
if (
isChildOrEqual(startElm, controlElm) &&
isChildOrEqual(selection.getEnd(true), controlElm)
) {
dom.setAttrib(controlElm, elementSelectionAttr, selectedValue);
throttledShowResizeRect.throttle(controlElm);
return;
}
}
hideResizeRect();
};
const unbindResizeHandleEvents = () => {
each$d(resizeHandles, (handle) => {
if (handle.elm) {
dom.unbind(handle.elm);
delete handle.elm;
}
});
};
const disableGeckoResize = () => {
try {
editor.getDoc().execCommand("enableObjectResizing", false, "false");
} catch (ex) {}
};
editor.on("init", () => {
disableGeckoResize();
editor.on(
"NodeChange ResizeEditor ResizeWindow ResizeContent drop",
updateResizeRect
);
editor.on("keyup compositionend", (e) => {
if (selectedElm && selectedElm.nodeName === "TABLE") {
updateResizeRect(e);
}
});
editor.on("hide blur", hideResizeRect);
editor.on("contextmenu longpress", contextMenuSelectImage, true);
});
editor.on("remove", unbindResizeHandleEvents);
const destroy = () => {
throttledShowResizeRect.cancel();
selectedElm = selectedElmGhost = resizeBackdrop = null;
};
return {
isResizable,
showResizeRect,
hideResizeRect,
updateResizeRect,
destroy,
};
};
const setStart = (rng, situ) => {
situ.fold(
(e) => {
rng.setStartBefore(e.dom);
},
(e, o) => {
rng.setStart(e.dom, o);
},
(e) => {
rng.setStartAfter(e.dom);
}
);
};
const setFinish = (rng, situ) => {
situ.fold(
(e) => {
rng.setEndBefore(e.dom);
},
(e, o) => {
rng.setEnd(e.dom, o);
},
(e) => {
rng.setEndAfter(e.dom);
}
);
};
const relativeToNative = (win, startSitu, finishSitu) => {
const range = win.document.createRange();
setStart(range, startSitu);
setFinish(range, finishSitu);
return range;
};
const exactToNative = (win, start, soffset, finish, foffset) => {
const rng = win.document.createRange();
rng.setStart(start.dom, soffset);
rng.setEnd(finish.dom, foffset);
return rng;
};
const adt$3 = Adt.generate([
{
ltr: ["start", "soffset", "finish", "foffset"],
},
{
rtl: ["start", "soffset", "finish", "foffset"],
},
]);
const fromRange = (win, type, range) =>
type(
SugarElement.fromDom(range.startContainer),
range.startOffset,
SugarElement.fromDom(range.endContainer),
range.endOffset
);
const getRanges = (win, selection) =>
selection.match({
domRange: (rng) => {
return {
ltr: constant(rng),
rtl: Optional.none,
};
},
relative: (startSitu, finishSitu) => {
return {
ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
rtl: cached(() =>
Optional.some(relativeToNative(win, finishSitu, startSitu))
),
};
},
exact: (start, soffset, finish, foffset) => {
return {
ltr: cached(() =>
exactToNative(win, start, soffset, finish, foffset)
),
rtl: cached(() =>
Optional.some(exactToNative(win, finish, foffset, start, soffset))
),
};
},
});
const doDiagnose = (win, ranges) => {
const rng = ranges.ltr();
if (rng.collapsed) {
const reversed = ranges.rtl().filter((rev) => rev.collapsed === false);
return reversed
.map((rev) =>
adt$3.rtl(
SugarElement.fromDom(rev.endContainer),
rev.endOffset,
SugarElement.fromDom(rev.startContainer),
rev.startOffset
)
)
.getOrThunk(() => fromRange(win, adt$3.ltr, rng));
} else {
return fromRange(win, adt$3.ltr, rng);
}
};
const diagnose = (win, selection) => {
const ranges = getRanges(win, selection);
return doDiagnose(win, ranges);
};
adt$3.ltr;
adt$3.rtl;
const create$a = (start, soffset, finish, foffset) => ({
start,
soffset,
finish,
foffset,
});
const SimRange = { create: create$a };
const caretPositionFromPoint = (doc, x, y) => {
var _a, _b;
return Optional.from(
(_b = (_a = doc.dom).caretPositionFromPoint) === null || _b === void 0
? void 0
: _b.call(_a, x, y)
).bind((pos) => {
if (pos.offsetNode === null) {
return Optional.none();
}
const r = doc.dom.createRange();
r.setStart(pos.offsetNode, pos.offset);
r.collapse();
return Optional.some(r);
});
};
const caretRangeFromPoint = (doc, x, y) => {
var _a, _b;
return Optional.from(
(_b = (_a = doc.dom).caretRangeFromPoint) === null || _b === void 0
? void 0
: _b.call(_a, x, y)
);
};
const availableSearch = (() => {
if (document.caretPositionFromPoint) {
return caretPositionFromPoint;
} else if (document.caretRangeFromPoint) {
return caretRangeFromPoint;
} else {
return Optional.none;
}
})();
const fromPoint$1 = (win, x, y) => {
const doc = SugarElement.fromDom(win.document);
return availableSearch(doc, x, y).map((rng) =>
SimRange.create(
SugarElement.fromDom(rng.startContainer),
rng.startOffset,
SugarElement.fromDom(rng.endContainer),
rng.endOffset
)
);
};
const adt$2 = Adt.generate([
{ before: ["element"] },
{
on: ["element", "offset"],
},
{ after: ["element"] },
]);
const cata = (subject, onBefore, onOn, onAfter) =>
subject.fold(onBefore, onOn, onAfter);
const getStart$2 = (situ) => situ.fold(identity, identity, identity);
const before$1 = adt$2.before;
const on = adt$2.on;
const after$1 = adt$2.after;
const Situ = {
before: before$1,
on,
after: after$1,
cata,
getStart: getStart$2,
};
const adt$1 = Adt.generate([
{ domRange: ["rng"] },
{
relative: ["startSitu", "finishSitu"],
},
{
exact: ["start", "soffset", "finish", "foffset"],
},
]);
const exactFromRange = (simRange) =>
adt$1.exact(
simRange.start,
simRange.soffset,
simRange.finish,
simRange.foffset
);
const getStart$1 = (selection) =>
selection.match({
domRange: (rng) => SugarElement.fromDom(rng.startContainer),
relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
exact: (start, _soffset, _finish, _foffset) => start,
});
const domRange = adt$1.domRange;
const relative = adt$1.relative;
const exact = adt$1.exact;
const getWin = (selection) => {
const start = getStart$1(selection);
return defaultView(start);
};
const range = SimRange.create;
const SimSelection = {
domRange,
relative,
exact,
exactFromRange,
getWin,
range,
};
const beforeSpecial = (element, offset) => {
const name$1 = name(element);
if ("input" === name$1) {
return Situ.after(element);
} else if (!contains$2(["br", "img"], name$1)) {
return Situ.on(element, offset);
} else {
return offset === 0 ? Situ.before(element) : Situ.after(element);
}
};
const preprocessRelative = (startSitu, finishSitu) => {
const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
return SimSelection.relative(start, finish);
};
const preprocessExact = (start, soffset, finish, foffset) => {
const startSitu = beforeSpecial(start, soffset);
const finishSitu = beforeSpecial(finish, foffset);
return SimSelection.relative(startSitu, finishSitu);
};
const preprocess = (selection) =>
selection.match({
domRange: (rng) => {
const start = SugarElement.fromDom(rng.startContainer);
const finish = SugarElement.fromDom(rng.endContainer);
return preprocessExact(start, rng.startOffset, finish, rng.endOffset);
},
relative: preprocessRelative,
exact: preprocessExact,
});
const fromElements = (elements, scope) => {
const doc = scope || document;
const fragment = doc.createDocumentFragment();
each$e(elements, (element) => {
fragment.appendChild(element.dom);
});
return SugarElement.fromDom(fragment);
};
const toNative = (selection) => {
const win = SimSelection.getWin(selection).dom;
const getDomRange = (start, soffset, finish, foffset) =>
exactToNative(win, start, soffset, finish, foffset);
const filtered = preprocess(selection);
return diagnose(win, filtered).match({
ltr: getDomRange,
rtl: getDomRange,
});
};
const getAtPoint = (win, x, y) => fromPoint$1(win, x, y);
const fromPoint = (clientX, clientY, doc) => {
const win = defaultView(SugarElement.fromDom(doc));
return getAtPoint(win.dom, clientX, clientY)
.map((simRange) => {
const rng = doc.createRange();
rng.setStart(simRange.start.dom, simRange.soffset);
rng.setEnd(simRange.finish.dom, simRange.foffset);
return rng;
})
.getOrUndefined();
};
const isEq$4 = (rng1, rng2) => {
return (
isNonNullable(rng1) &&
isNonNullable(rng2) &&
rng1.startContainer === rng2.startContainer &&
rng1.startOffset === rng2.startOffset &&
rng1.endContainer === rng2.endContainer &&
rng1.endOffset === rng2.endOffset
);
};
const findParent = (node, rootNode, predicate) => {
let currentNode = node;
while (currentNode && currentNode !== rootNode) {
if (predicate(currentNode)) {
return currentNode;
}
currentNode = currentNode.parentNode;
}
return null;
};
const hasParent$1 = (node, rootNode, predicate) =>
findParent(node, rootNode, predicate) !== null;
const hasParentWithName = (node, rootNode, name) =>
hasParent$1(node, rootNode, (node) => node.nodeName === name);
const isCeFalseCaretContainer = (node, rootNode) =>
isCaretContainer$2(node) && !hasParent$1(node, rootNode, isCaretNode);
const hasBrBeforeAfter = (dom, node, left) => {
const parentNode = node.parentNode;
if (parentNode) {
const walker = new DomTreeWalker(
node,
dom.getParent(parentNode, dom.isBlock) || dom.getRoot()
);
let currentNode;
while ((currentNode = walker[left ? "prev" : "next"]())) {
if (isBr$6(currentNode)) {
return true;
}
}
}
return false;
};
const isPrevNode = (node, name) => {
var _a;
return (
((_a = node.previousSibling) === null || _a === void 0
? void 0
: _a.nodeName) === name
);
};
const hasContentEditableFalseParent = (root, node) => {
let currentNode = node;
while (currentNode && currentNode !== root) {
if (isContentEditableFalse$b(currentNode)) {
return true;
}
currentNode = currentNode.parentNode;
}
return false;
};
const findTextNodeRelative = (
dom,
isAfterNode,
collapsed,
left,
startNode
) => {
const body = dom.getRoot();
const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
const parentNode = startNode.parentNode;
let lastInlineElement;
let node;
if (!parentNode) {
return Optional.none();
}
const parentBlockContainer = dom.getParent(parentNode, dom.isBlock) || body;
if (
left &&
isBr$6(startNode) &&
isAfterNode &&
dom.isEmpty(parentBlockContainer)
) {
return Optional.some(CaretPosition(parentNode, dom.nodeIndex(startNode)));
}
const walker = new DomTreeWalker(startNode, parentBlockContainer);
while ((node = walker[left ? "prev" : "next"]())) {
if (
dom.getContentEditableParent(node) === "false" ||
isCeFalseCaretContainer(node, body)
) {
return Optional.none();
}
if (isText$a(node) && node.data.length > 0) {
if (!hasParentWithName(node, body, "A")) {
return Optional.some(
CaretPosition(node, left ? node.data.length : 0)
);
}
return Optional.none();
}
if (
dom.isBlock(node) ||
nonEmptyElementsMap[node.nodeName.toLowerCase()]
) {
return Optional.none();
}
lastInlineElement = node;
}
if (isComment(lastInlineElement)) {
return Optional.none();
}
if (collapsed && lastInlineElement) {
return Optional.some(CaretPosition(lastInlineElement, 0));
}
return Optional.none();
};
const normalizeEndPoint = (dom, collapsed, start, rng) => {
const body = dom.getRoot();
let node;
let normalized = false;
let container = start ? rng.startContainer : rng.endContainer;
let offset = start ? rng.startOffset : rng.endOffset;
const isAfterNode =
isElement$6(container) && offset === container.childNodes.length;
const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
let directionLeft = start;
if (isCaretContainer$2(container)) {
return Optional.none();
}
if (isElement$6(container) && offset > container.childNodes.length - 1) {
directionLeft = false;
}
if (isDocument$1(container)) {
container = body;
offset = 0;
}
if (container === body) {
if (directionLeft) {
node = container.childNodes[offset > 0 ? offset - 1 : 0];
if (node) {
if (isCaretContainer$2(node)) {
return Optional.none();
}
if (nonEmptyElementsMap[node.nodeName] || isTable$2(node)) {
return Optional.none();
}
}
}
if (container.hasChildNodes()) {
offset = Math.min(
!directionLeft && offset > 0 ? offset - 1 : offset,
container.childNodes.length - 1
);
container = container.childNodes[offset];
offset = isText$a(container) && isAfterNode ? container.data.length : 0;
if (
!collapsed &&
container === body.lastChild &&
isTable$2(container)
) {
return Optional.none();
}
if (
hasContentEditableFalseParent(body, container) ||
isCaretContainer$2(container)
) {
return Optional.none();
}
if (container.hasChildNodes() && !isTable$2(container)) {
node = container;
const walker = new DomTreeWalker(container, body);
do {
if (isContentEditableFalse$b(node) || isCaretContainer$2(node)) {
normalized = false;
break;
}
if (isText$a(node) && node.data.length > 0) {
offset = directionLeft ? 0 : node.data.length;
container = node;
normalized = true;
break;
}
if (
nonEmptyElementsMap[node.nodeName.toLowerCase()] &&
!isTableCellOrCaption(node)
) {
offset = dom.nodeIndex(node);
container = node.parentNode;
if (!directionLeft) {
offset++;
}
normalized = true;
break;
}
} while ((node = directionLeft ? walker.next() : walker.prev()));
}
}
}
if (collapsed) {
if (isText$a(container) && offset === 0) {
findTextNodeRelative(dom, isAfterNode, collapsed, true, container).each(
(pos) => {
container = pos.container();
offset = pos.offset();
normalized = true;
}
);
}
if (isElement$6(container)) {
node = container.childNodes[offset];
if (!node) {
node = container.childNodes[offset - 1];
}
if (
node &&
isBr$6(node) &&
!isPrevNode(node, "A") &&
!hasBrBeforeAfter(dom, node, false) &&
!hasBrBeforeAfter(dom, node, true)
) {
findTextNodeRelative(dom, isAfterNode, collapsed, true, node).each(
(pos) => {
container = pos.container();
offset = pos.offset();
normalized = true;
}
);
}
}
}
if (
directionLeft &&
!collapsed &&
isText$a(container) &&
offset === container.data.length
) {
findTextNodeRelative(dom, isAfterNode, collapsed, false, container).each(
(pos) => {
container = pos.container();
offset = pos.offset();
normalized = true;
}
);
}
return normalized && container
? Optional.some(CaretPosition(container, offset))
: Optional.none();
};
const normalize$2 = (dom, rng) => {
const collapsed = rng.collapsed,
normRng = rng.cloneRange();
const startPos = CaretPosition.fromRangeStart(rng);
normalizeEndPoint(dom, collapsed, true, normRng).each((pos) => {
if (!collapsed || !CaretPosition.isAbove(startPos, pos)) {
normRng.setStart(pos.container(), pos.offset());
}
});
if (!collapsed) {
normalizeEndPoint(dom, collapsed, false, normRng).each((pos) => {
normRng.setEnd(pos.container(), pos.offset());
});
}
if (collapsed) {
normRng.collapse(true);
}
return isEq$4(rng, normRng) ? Optional.none() : Optional.some(normRng);
};
const splitText = (node, offset) => {
return node.splitText(offset);
};
const split = (rng) => {
let startContainer = rng.startContainer,
startOffset = rng.startOffset,
endContainer = rng.endContainer,
endOffset = rng.endOffset;
if (startContainer === endContainer && isText$a(startContainer)) {
if (startOffset > 0 && startOffset < startContainer.data.length) {
endContainer = splitText(startContainer, startOffset);
startContainer = endContainer.previousSibling;
if (endOffset > startOffset) {
endOffset = endOffset - startOffset;
const newContainer = splitText(
endContainer,
endOffset
).previousSibling;
startContainer = endContainer = newContainer;
endOffset = newContainer.data.length;
startOffset = 0;
} else {
endOffset = 0;
}
}
} else {
if (
isText$a(startContainer) &&
startOffset > 0 &&
startOffset < startContainer.data.length
) {
startContainer = splitText(startContainer, startOffset);
startOffset = 0;
}
if (
isText$a(endContainer) &&
endOffset > 0 &&
endOffset < endContainer.data.length
) {
const newContainer = splitText(endContainer, endOffset).previousSibling;
endContainer = newContainer;
endOffset = newContainer.data.length;
}
}
return {
startContainer,
startOffset,
endContainer,
endOffset,
};
};
const RangeUtils = (dom) => {
const walk = (rng, callback) => {
return walk$3(dom, rng, callback);
};
const split$1 = split;
const normalize = (rng) => {
return normalize$2(dom, rng).fold(never, (normalizedRng) => {
rng.setStart(normalizedRng.startContainer, normalizedRng.startOffset);
rng.setEnd(normalizedRng.endContainer, normalizedRng.endOffset);
return true;
});
};
const expand = (rng, options = { type: "word" }) => {
if (options.type === "word") {
const rangeLike = expandRng(dom, rng, [{ inline: "span" }]);
const newRange = dom.createRng();
newRange.setStart(rangeLike.startContainer, rangeLike.startOffset);
newRange.setEnd(rangeLike.endContainer, rangeLike.endOffset);
return newRange;
}
return rng;
};
return {
walk,
split: split$1,
expand,
normalize,
};
};
RangeUtils.compareRanges = isEq$4;
RangeUtils.getCaretRangeFromPoint = fromPoint;
RangeUtils.getSelectedNode = getSelectedNode;
RangeUtils.getNode = getNode$1;
const Dimension = (name, getOffset) => {
const set = (element, h) => {
if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
throw new Error(
name + ".set accepts only positive integer values. Value was " + h
);
}
const dom = element.dom;
if (isSupported(dom)) {
dom.style[name] = h + "px";
}
};
const get = (element) => {
const r = getOffset(element);
if (r <= 0 || r === null) {
const css = get$7(element, name);
return parseFloat(css) || 0;
}
return r;
};
const getOuter = get;
const aggregate = (element, properties) =>
foldl(
properties,
(acc, property) => {
const val = get$7(element, property);
const value = val === undefined ? 0 : parseInt(val, 10);
return isNaN(value) ? acc : acc + value;
},
0
);
const max = (element, value, properties) => {
const cumulativeInclusions = aggregate(element, properties);
const absoluteMax =
value > cumulativeInclusions ? value - cumulativeInclusions : 0;
return absoluteMax;
};
return {
set,
get,
getOuter,
aggregate,
max,
};
};
const api = Dimension("height", (element) => {
const dom = element.dom;
return inBody(element)
? dom.getBoundingClientRect().height
: dom.offsetHeight;
});
const get$2 = (element) => api.get(element);
const getDocument = () => SugarElement.fromDom(document);
const walkUp = (navigation, doc) => {
const frame = navigation.view(doc);
return frame.fold(constant([]), (f) => {
const parent = navigation.owner(f);
const rest = walkUp(navigation, parent);
return [f].concat(rest);
});
};
const pathTo = (element, navigation) => {
const d = navigation.owner(element);
return walkUp(navigation, d);
};
const view = (doc) => {
var _a;
const element =
doc.dom === document
? Optional.none()
: Optional.from(
(_a = doc.dom.defaultView) === null || _a === void 0
? void 0
: _a.frameElement
);
return element.map(SugarElement.fromDom);
};
const owner = (element) => documentOrOwner(element);
var Navigation = /*#__PURE__*/ Object.freeze({
__proto__: null,
view: view,
owner: owner,
});
const find = (element) => {
const doc = getDocument();
const scroll = get$5(doc);
const frames = pathTo(element, Navigation);
const offset = viewport(element);
const r = foldr(
frames,
(b, a) => {
const loc = viewport(a);
return {
left: b.left + loc.left,
top: b.top + loc.top,
};
},
{
left: 0,
top: 0,
}
);
return SugarPosition(
r.left + offset.left + scroll.left,
r.top + offset.top + scroll.top
);
};
const excludeFromDescend = (element) => name(element) === "textarea";
const fireScrollIntoViewEvent = (editor, data) => {
const scrollEvent = editor.dispatch("ScrollIntoView", data);
return scrollEvent.isDefaultPrevented();
};
const fireAfterScrollIntoViewEvent = (editor, data) => {
editor.dispatch("AfterScrollIntoView", data);
};
const descend = (element, offset) => {
const children = children$1(element);
if (children.length === 0 || excludeFromDescend(element)) {
return {
element,
offset,
};
} else if (
offset < children.length &&
!excludeFromDescend(children[offset])
) {
return {
element: children[offset],
offset: 0,
};
} else {
const last = children[children.length - 1];
if (excludeFromDescend(last)) {
return {
element,
offset,
};
} else {
if (name(last) === "img") {
return {
element: last,
offset: 1,
};
} else if (isText$b(last)) {
return {
element: last,
offset: get$3(last).length,
};
} else {
return {
element: last,
offset: children$1(last).length,
};
}
}
}
};
const markerInfo = (element, cleanupFun) => {
const pos = absolute(element);
const height = get$2(element);
return {
element,
bottom: pos.top + height,
height,
pos,
cleanup: cleanupFun,
};
};
const createMarker$1 = (element, offset) => {
const startPoint = descend(element, offset);
const span = SugarElement.fromHtml(
'' +
ZWSP$1 +
""
);
before$3(startPoint.element, span);
return markerInfo(span, () => remove$5(span));
};
const elementMarker = (element) =>
markerInfo(SugarElement.fromDom(element), noop);
const withMarker = (editor, f, rng, alignToTop) => {
preserveWith(
editor,
(_s, _e) => applyWithMarker(editor, f, rng, alignToTop),
rng
);
};
const withScrollEvents = (editor, doc, f, marker, alignToTop) => {
const data = {
elm: marker.element.dom,
alignToTop,
};
if (fireScrollIntoViewEvent(editor, data)) {
return;
}
const scrollTop = get$5(doc).top;
f(editor, doc, scrollTop, marker, alignToTop);
fireAfterScrollIntoViewEvent(editor, data);
};
const applyWithMarker = (editor, f, rng, alignToTop) => {
const body = SugarElement.fromDom(editor.getBody());
const doc = SugarElement.fromDom(editor.getDoc());
reflow(body);
const marker = createMarker$1(
SugarElement.fromDom(rng.startContainer),
rng.startOffset
);
withScrollEvents(editor, doc, f, marker, alignToTop);
marker.cleanup();
};
const withElement = (editor, element, f, alignToTop) => {
const doc = SugarElement.fromDom(editor.getDoc());
withScrollEvents(editor, doc, f, elementMarker(element), alignToTop);
};
const preserveWith = (editor, f, rng) => {
const startElement = rng.startContainer;
const startOffset = rng.startOffset;
const endElement = rng.endContainer;
const endOffset = rng.endOffset;
f(SugarElement.fromDom(startElement), SugarElement.fromDom(endElement));
const newRng = editor.dom.createRng();
newRng.setStart(startElement, startOffset);
newRng.setEnd(endElement, endOffset);
editor.selection.setRng(rng);
};
const scrollToMarker = (editor, marker, viewHeight, alignToTop, doc) => {
const pos = marker.pos;
if (alignToTop) {
to(pos.left, pos.top, doc);
} else {
const y = pos.top - viewHeight + marker.height;
to(-editor.getBody().getBoundingClientRect().left, y, doc);
}
};
const intoWindowIfNeeded = (
editor,
doc,
scrollTop,
viewHeight,
marker,
alignToTop
) => {
const viewportBottom = viewHeight + scrollTop;
const markerTop = marker.pos.top;
const markerBottom = marker.bottom;
const largerThanViewport = markerBottom - markerTop >= viewHeight;
if (markerTop < scrollTop) {
scrollToMarker(editor, marker, viewHeight, alignToTop !== false, doc);
} else if (markerTop > viewportBottom) {
const align = largerThanViewport
? alignToTop !== false
: alignToTop === true;
scrollToMarker(editor, marker, viewHeight, align, doc);
} else if (markerBottom > viewportBottom && !largerThanViewport) {
scrollToMarker(editor, marker, viewHeight, alignToTop === true, doc);
}
};
const intoWindow = (editor, doc, scrollTop, marker, alignToTop) => {
const viewHeight = defaultView(doc).dom.innerHeight;
intoWindowIfNeeded(editor, doc, scrollTop, viewHeight, marker, alignToTop);
};
const intoFrame = (editor, doc, scrollTop, marker, alignToTop) => {
const frameViewHeight = defaultView(doc).dom.innerHeight;
intoWindowIfNeeded(
editor,
doc,
scrollTop,
frameViewHeight,
marker,
alignToTop
);
const op = find(marker.element);
const viewportBounds = getBounds(window);
if (op.top < viewportBounds.y) {
intoView(marker.element, alignToTop !== false);
} else if (op.top > viewportBounds.bottom) {
intoView(marker.element, alignToTop === true);
}
};
const rangeIntoWindow = (editor, rng, alignToTop) =>
withMarker(editor, intoWindow, rng, alignToTop);
const elementIntoWindow = (editor, element, alignToTop) =>
withElement(editor, element, intoWindow, alignToTop);
const rangeIntoFrame = (editor, rng, alignToTop) =>
withMarker(editor, intoFrame, rng, alignToTop);
const elementIntoFrame = (editor, element, alignToTop) =>
withElement(editor, element, intoFrame, alignToTop);
const scrollElementIntoView = (editor, element, alignToTop) => {
const scroller = editor.inline ? elementIntoWindow : elementIntoFrame;
scroller(editor, element, alignToTop);
};
const scrollRangeIntoView = (editor, rng, alignToTop) => {
const scroller = editor.inline ? rangeIntoWindow : rangeIntoFrame;
scroller(editor, rng, alignToTop);
};
const focus$1 = (element) => element.dom.focus();
const hasFocus$1 = (element) => {
const root = getRootNode(element).dom;
return element.dom === root.activeElement;
};
const active$1 = (root = getDocument()) =>
Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
const search = (element) =>
active$1(getRootNode(element)).filter((e) => element.dom.contains(e.dom));
const clamp$1 = (offset, element) => {
const max = isText$b(element)
? get$3(element).length
: children$1(element).length + 1;
if (offset > max) {
return max;
} else if (offset < 0) {
return 0;
}
return offset;
};
const normalizeRng = (rng) =>
SimSelection.range(
rng.start,
clamp$1(rng.soffset, rng.start),
rng.finish,
clamp$1(rng.foffset, rng.finish)
);
const isOrContains = (root, elm) =>
!isRestrictedNode(elm.dom) && (contains(root, elm) || eq(root, elm));
const isRngInRoot = (root) => (rng) =>
isOrContains(root, rng.start) && isOrContains(root, rng.finish);
const shouldStore = (editor) => editor.inline || Env.browser.isFirefox();
const nativeRangeToSelectionRange = (r) =>
SimSelection.range(
SugarElement.fromDom(r.startContainer),
r.startOffset,
SugarElement.fromDom(r.endContainer),
r.endOffset
);
const readRange = (win) => {
const selection = win.getSelection();
const rng =
!selection || selection.rangeCount === 0
? Optional.none()
: Optional.from(selection.getRangeAt(0));
return rng.map(nativeRangeToSelectionRange);
};
const getBookmark = (root) => {
const win = defaultView(root);
return readRange(win.dom).filter(isRngInRoot(root));
};
const validate = (root, bookmark) =>
Optional.from(bookmark).filter(isRngInRoot(root)).map(normalizeRng);
const bookmarkToNativeRng = (bookmark) => {
const rng = document.createRange();
try {
rng.setStart(bookmark.start.dom, bookmark.soffset);
rng.setEnd(bookmark.finish.dom, bookmark.foffset);
return Optional.some(rng);
} catch (_) {
return Optional.none();
}
};
const store = (editor) => {
const newBookmark = shouldStore(editor)
? getBookmark(SugarElement.fromDom(editor.getBody()))
: Optional.none();
editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
};
const getRng = (editor) => {
const bookmark = editor.bookmark ? editor.bookmark : Optional.none();
return bookmark
.bind((x) => validate(SugarElement.fromDom(editor.getBody()), x))
.bind(bookmarkToNativeRng);
};
const restore = (editor) => {
getRng(editor).each((rng) => editor.selection.setRng(rng));
};
const isEditorUIElement$1 = (elm) => {
const className = elm.className.toString();
return className.indexOf("tox-") !== -1 || className.indexOf("mce-") !== -1;
};
const FocusManager = { isEditorUIElement: isEditorUIElement$1 };
const wrappedSetTimeout = (callback, time) => {
if (!isNumber(time)) {
time = 0;
}
return setTimeout(callback, time);
};
const wrappedSetInterval = (callback, time) => {
if (!isNumber(time)) {
time = 0;
}
return setInterval(callback, time);
};
const Delay = {
setEditorTimeout: (editor, callback, time) => {
return wrappedSetTimeout(() => {
if (!editor.removed) {
callback();
}
}, time);
},
setEditorInterval: (editor, callback, time) => {
const timer = wrappedSetInterval(() => {
if (!editor.removed) {
callback();
} else {
clearInterval(timer);
}
}, time);
return timer;
},
};
const isManualNodeChange = (e) => {
return e.type === "nodechange" && e.selectionChange;
};
const registerPageMouseUp = (editor, throttledStore) => {
const mouseUpPage = () => {
throttledStore.throttle();
};
DOMUtils.DOM.bind(document, "mouseup", mouseUpPage);
editor.on("remove", () => {
DOMUtils.DOM.unbind(document, "mouseup", mouseUpPage);
});
};
const registerMouseUp = (editor, throttledStore) => {
editor.on("mouseup touchend", (_e) => {
throttledStore.throttle();
});
};
const registerEditorEvents = (editor, throttledStore) => {
registerMouseUp(editor, throttledStore);
editor.on("keyup NodeChange AfterSetSelectionRange", (e) => {
if (!isManualNodeChange(e)) {
store(editor);
}
});
};
const register$6 = (editor) => {
const throttledStore = first$1(() => {
store(editor);
}, 0);
editor.on("init", () => {
if (editor.inline) {
registerPageMouseUp(editor, throttledStore);
}
registerEditorEvents(editor, throttledStore);
});
editor.on("remove", () => {
throttledStore.cancel();
});
};
let documentFocusInHandler;
const DOM$9 = DOMUtils.DOM;
const isEditorUIElement = (elm) => {
return isElement$6(elm) && FocusManager.isEditorUIElement(elm);
};
const isEditorContentAreaElement = (elm) => {
const classList = elm.classList;
if (classList !== undefined) {
return (
classList.contains("tox-edit-area") ||
classList.contains("tox-edit-area__iframe") ||
classList.contains("mce-content-body")
);
} else {
return false;
}
};
const isUIElement = (editor, elm) => {
const customSelector = getCustomUiSelector(editor);
const parent = DOM$9.getParent(elm, (elm) => {
return (
isEditorUIElement(elm) ||
(customSelector ? editor.dom.is(elm, customSelector) : false)
);
});
return parent !== null;
};
const getActiveElement = (editor) => {
try {
const root = getRootNode(SugarElement.fromDom(editor.getElement()));
return active$1(root).fold(
() => document.body,
(x) => x.dom
);
} catch (ex) {
return document.body;
}
};
const registerEvents$1 = (editorManager, e) => {
const editor = e.editor;
register$6(editor);
const toggleContentAreaOnFocus = (editor, fn) => {
if (shouldHighlightOnFocus(editor) && editor.inline !== true) {
const contentArea = SugarElement.fromDom(editor.getContainer());
fn(contentArea, "tox-edit-focus");
}
};
editor.on("focusin", () => {
const focusedEditor = editorManager.focusedEditor;
if (isEditorContentAreaElement(getActiveElement(editor))) {
toggleContentAreaOnFocus(editor, add$2);
}
if (focusedEditor !== editor) {
if (focusedEditor) {
focusedEditor.dispatch("blur", { focusedEditor: editor });
}
editorManager.setActive(editor);
editorManager.focusedEditor = editor;
editor.dispatch("focus", { blurredEditor: focusedEditor });
editor.focus(true);
}
});
editor.on("focusout", () => {
Delay.setEditorTimeout(editor, () => {
const focusedEditor = editorManager.focusedEditor;
if (
!isEditorContentAreaElement(getActiveElement(editor)) ||
focusedEditor !== editor
) {
toggleContentAreaOnFocus(editor, remove$7);
}
if (
!isUIElement(editor, getActiveElement(editor)) &&
focusedEditor === editor
) {
editor.dispatch("blur", { focusedEditor: null });
editorManager.focusedEditor = null;
}
});
});
if (!documentFocusInHandler) {
documentFocusInHandler = (e) => {
const activeEditor = editorManager.activeEditor;
if (activeEditor) {
getOriginalEventTarget(e).each((target) => {
const elem = target;
if (elem.ownerDocument === document) {
if (
elem !== document.body &&
!isUIElement(activeEditor, elem) &&
editorManager.focusedEditor === activeEditor
) {
activeEditor.dispatch("blur", { focusedEditor: null });
editorManager.focusedEditor = null;
}
}
});
}
};
DOM$9.bind(document, "focusin", documentFocusInHandler);
}
};
const unregisterDocumentEvents = (editorManager, e) => {
if (editorManager.focusedEditor === e.editor) {
editorManager.focusedEditor = null;
}
if (!editorManager.activeEditor && documentFocusInHandler) {
DOM$9.unbind(document, "focusin", documentFocusInHandler);
documentFocusInHandler = null;
}
};
const setup$v = (editorManager) => {
editorManager.on("AddEditor", curry(registerEvents$1, editorManager));
editorManager.on(
"RemoveEditor",
curry(unregisterDocumentEvents, editorManager)
);
};
const getContentEditableHost = (editor, node) =>
editor.dom.getParent(
node,
(node) => editor.dom.getContentEditable(node) === "true"
);
const getCollapsedNode = (rng) =>
rng.collapsed
? Optional.from(getNode$1(rng.startContainer, rng.startOffset)).map(
SugarElement.fromDom
)
: Optional.none();
const getFocusInElement = (root, rng) =>
getCollapsedNode(rng).bind((node) => {
if (isTableSection(node)) {
return Optional.some(node);
} else if (!contains(root, node)) {
return Optional.some(root);
} else {
return Optional.none();
}
});
const normalizeSelection = (editor, rng) => {
getFocusInElement(SugarElement.fromDom(editor.getBody()), rng)
.bind((elm) => {
return firstPositionIn(elm.dom);
})
.fold(
() => {
editor.selection.normalize();
},
(caretPos) => editor.selection.setRng(caretPos.toRange())
);
};
const focusBody = (body) => {
if (body.setActive) {
try {
body.setActive();
} catch (ex) {
body.focus();
}
} else {
body.focus();
}
};
const hasElementFocus = (elm) => hasFocus$1(elm) || search(elm).isSome();
const hasIframeFocus = (editor) =>
isNonNullable(editor.iframeElement) &&
hasFocus$1(SugarElement.fromDom(editor.iframeElement));
const hasInlineFocus = (editor) => {
const rawBody = editor.getBody();
return rawBody && hasElementFocus(SugarElement.fromDom(rawBody));
};
const hasUiFocus = (editor) => {
const dos = getRootNode(SugarElement.fromDom(editor.getElement()));
return active$1(dos)
.filter(
(elem) =>
!isEditorContentAreaElement(elem.dom) && isUIElement(editor, elem.dom)
)
.isSome();
};
const hasFocus = (editor) =>
editor.inline ? hasInlineFocus(editor) : hasIframeFocus(editor);
const hasEditorOrUiFocus = (editor) => hasFocus(editor) || hasUiFocus(editor);
const focusEditor = (editor) => {
const selection = editor.selection;
const body = editor.getBody();
let rng = selection.getRng();
editor.quirks.refreshContentEditable();
if (isNonNullable(editor.bookmark) && !hasFocus(editor)) {
getRng(editor).each((bookmarkRng) => {
editor.selection.setRng(bookmarkRng);
rng = bookmarkRng;
});
}
const contentEditableHost = getContentEditableHost(
editor,
selection.getNode()
);
if (
contentEditableHost &&
editor.dom.isChildOf(contentEditableHost, body)
) {
focusBody(contentEditableHost);
normalizeSelection(editor, rng);
activateEditor(editor);
return;
}
if (!editor.inline) {
if (!Env.browser.isOpera()) {
focusBody(body);
}
editor.getWin().focus();
}
if (Env.browser.isFirefox() || editor.inline) {
focusBody(body);
normalizeSelection(editor, rng);
}
activateEditor(editor);
};
const activateEditor = (editor) => editor.editorManager.setActive(editor);
const focus = (editor, skipFocus) => {
if (editor.removed) {
return;
}
if (skipFocus) {
activateEditor(editor);
} else {
focusEditor(editor);
}
};
const getEndpointElement = (root, rng, start, real, resolve) => {
const container = start ? rng.startContainer : rng.endContainer;
const offset = start ? rng.startOffset : rng.endOffset;
return Optional.from(container)
.map(SugarElement.fromDom)
.map((elm) =>
!real || !rng.collapsed
? child$1(elm, resolve(elm, offset)).getOr(elm)
: elm
)
.bind((elm) =>
isElement$7(elm) ? Optional.some(elm) : parent(elm).filter(isElement$7)
)
.map((elm) => elm.dom)
.getOr(root);
};
const getStart = (root, rng, real = false) =>
getEndpointElement(root, rng, true, real, (elm, offset) =>
Math.min(childNodesCount(elm), offset)
);
const getEnd$1 = (root, rng, real = false) =>
getEndpointElement(root, rng, false, real, (elm, offset) =>
offset > 0 ? offset - 1 : offset
);
const skipEmptyTextNodes = (node, forwards) => {
const orig = node;
while (node && isText$a(node) && node.length === 0) {
node = forwards ? node.nextSibling : node.previousSibling;
}
return node || orig;
};
const getNode = (root, rng) => {
if (!rng) {
return root;
}
let startContainer = rng.startContainer;
let endContainer = rng.endContainer;
const startOffset = rng.startOffset;
const endOffset = rng.endOffset;
let node = rng.commonAncestorContainer;
if (!rng.collapsed) {
if (startContainer === endContainer) {
if (endOffset - startOffset < 2) {
if (startContainer.hasChildNodes()) {
node = startContainer.childNodes[startOffset];
}
}
}
if (isText$a(startContainer) && isText$a(endContainer)) {
if (startContainer.length === startOffset) {
startContainer = skipEmptyTextNodes(startContainer.nextSibling, true);
} else {
startContainer = startContainer.parentNode;
}
if (endOffset === 0) {
endContainer = skipEmptyTextNodes(
endContainer.previousSibling,
false
);
} else {
endContainer = endContainer.parentNode;
}
if (startContainer && startContainer === endContainer) {
node = startContainer;
}
}
}
const elm = isText$a(node) ? node.parentNode : node;
return isElement$6(elm) ? elm : root;
};
const getSelectedBlocks = (dom, rng, startElm, endElm) => {
const selectedBlocks = [];
const root = dom.getRoot();
const start = dom.getParent(
startElm || getStart(root, rng, rng.collapsed),
dom.isBlock
);
const end = dom.getParent(
endElm || getEnd$1(root, rng, rng.collapsed),
dom.isBlock
);
if (start && start !== root) {
selectedBlocks.push(start);
}
if (start && end && start !== end) {
let node;
const walker = new DomTreeWalker(start, root);
while ((node = walker.next()) && node !== end) {
if (dom.isBlock(node)) {
selectedBlocks.push(node);
}
}
}
if (end && start !== end && end !== root) {
selectedBlocks.push(end);
}
return selectedBlocks;
};
const select = (dom, node, content) =>
Optional.from(node).bind((node) =>
Optional.from(node.parentNode).map((parent) => {
const idx = dom.nodeIndex(node);
const rng = dom.createRng();
rng.setStart(parent, idx);
rng.setEnd(parent, idx + 1);
if (content) {
moveEndPoint(dom, rng, node, true);
moveEndPoint(dom, rng, node, false);
}
return rng;
})
);
const processRanges = (editor, ranges) =>
map$3(ranges, (range) => {
const evt = editor.dispatch("GetSelectionRange", { range });
return evt.range !== range ? evt.range : range;
});
const getEnd = (element) =>
name(element) === "img"
? 1
: getOption(element).fold(
() => children$1(element).length,
(v) => v.length
);
const isTextNodeWithCursorPosition = (el) =>
getOption(el)
.filter((text) => text.trim().length !== 0 || text.indexOf(nbsp) > -1)
.isSome();
const isContentEditableFalse$5 = (elem) =>
isHTMLElement(elem) && get$9(elem, "contenteditable") === "false";
const elementsWithCursorPosition = ["img", "br"];
const isCursorPosition = (elem) => {
const hasCursorPosition = isTextNodeWithCursorPosition(elem);
return (
hasCursorPosition ||
contains$2(elementsWithCursorPosition, name(elem)) ||
isContentEditableFalse$5(elem)
);
};
const first = (element) => descendant$1(element, isCursorPosition);
const last = (element) => descendantRtl(element, isCursorPosition);
const descendantRtl = (scope, predicate) => {
const descend = (element) => {
const children = children$1(element);
for (let i = children.length - 1; i >= 0; i--) {
const child = children[i];
if (predicate(child)) {
return Optional.some(child);
}
const res = descend(child);
if (res.isSome()) {
return res;
}
}
return Optional.none();
};
return descend(scope);
};
const autocompleteSelector = "[data-mce-autocompleter]";
const create$9 = (editor, range) => {
if (findIn(SugarElement.fromDom(editor.getBody())).isNone()) {
const wrapper = SugarElement.fromHtml(
'',
editor.getDoc()
);
append$1(wrapper, SugarElement.fromDom(range.extractContents()));
range.insertNode(wrapper.dom);
parent(wrapper).each((elm) => elm.dom.normalize());
last(wrapper).map((last) => {
editor.selection.setCursorLocation(last.dom, getEnd(last));
});
}
};
const detect$1 = (elm) => closest$3(elm, autocompleteSelector);
const findIn = (elm) => descendant(elm, autocompleteSelector);
const remove$2 = (editor, elm) =>
findIn(elm).each((wrapper) => {
const bookmark = editor.selection.getBookmark();
unwrap(wrapper);
editor.selection.moveToBookmark(bookmark);
});
const typeLookup = {
"#text": 3,
"#comment": 8,
"#cdata": 4,
"#pi": 7,
"#doctype": 10,
"#document-fragment": 11,
};
const walk$2 = (node, root, prev) => {
const startName = prev ? "lastChild" : "firstChild";
const siblingName = prev ? "prev" : "next";
if (node[startName]) {
return node[startName];
}
if (node !== root) {
let sibling = node[siblingName];
if (sibling) {
return sibling;
}
for (
let parent = node.parent;
parent && parent !== root;
parent = parent.parent
) {
sibling = parent[siblingName];
if (sibling) {
return sibling;
}
}
}
return undefined;
};
const isEmptyTextNode = (node) => {
var _a;
const text = (_a = node.value) !== null && _a !== void 0 ? _a : "";
if (!isWhitespaceText(text)) {
return false;
}
const parentNode = node.parent;
if (
parentNode &&
(parentNode.name !== "span" || parentNode.attr("style")) &&
/^[ ]+$/.test(text)
) {
return false;
}
return true;
};
const isNonEmptyElement = (node) => {
const isNamedAnchor =
node.name === "a" && !node.attr("href") && node.attr("id");
return (
node.attr("name") ||
(node.attr("id") && !node.firstChild) ||
node.attr("data-mce-bookmark") ||
isNamedAnchor
);
};
class AstNode {
static create(name, attrs) {
const node = new AstNode(name, typeLookup[name] || 1);
if (attrs) {
each$d(attrs, (value, attrName) => {
node.attr(attrName, value);
});
}
return node;
}
constructor(name, type) {
this.name = name;
this.type = type;
if (type === 1) {
this.attributes = [];
this.attributes.map = {};
}
}
replace(node) {
const self = this;
if (node.parent) {
node.remove();
}
self.insert(node, self);
self.remove();
return self;
}
attr(name, value) {
const self = this;
if (!isString(name)) {
if (isNonNullable(name)) {
each$d(name, (value, key) => {
self.attr(key, value);
});
}
return self;
}
const attrs = self.attributes;
if (attrs) {
if (value !== undefined) {
if (value === null) {
if (name in attrs.map) {
delete attrs.map[name];
let i = attrs.length;
while (i--) {
if (attrs[i].name === name) {
attrs.splice(i, 1);
return self;
}
}
}
return self;
}
if (name in attrs.map) {
let i = attrs.length;
while (i--) {
if (attrs[i].name === name) {
attrs[i].value = value;
break;
}
}
} else {
attrs.push({
name,
value,
});
}
attrs.map[name] = value;
return self;
}
return attrs.map[name];
}
return undefined;
}
clone() {
const self = this;
const clone = new AstNode(self.name, self.type);
const selfAttrs = self.attributes;
if (selfAttrs) {
const cloneAttrs = [];
cloneAttrs.map = {};
for (let i = 0, l = selfAttrs.length; i < l; i++) {
const selfAttr = selfAttrs[i];
if (selfAttr.name !== "id") {
cloneAttrs[cloneAttrs.length] = {
name: selfAttr.name,
value: selfAttr.value,
};
cloneAttrs.map[selfAttr.name] = selfAttr.value;
}
}
clone.attributes = cloneAttrs;
}
clone.value = self.value;
return clone;
}
wrap(wrapper) {
const self = this;
if (self.parent) {
self.parent.insert(wrapper, self);
wrapper.append(self);
}
return self;
}
unwrap() {
const self = this;
for (let node = self.firstChild; node; ) {
const next = node.next;
self.insert(node, self, true);
node = next;
}
self.remove();
}
remove() {
const self = this,
parent = self.parent,
next = self.next,
prev = self.prev;
if (parent) {
if (parent.firstChild === self) {
parent.firstChild = next;
if (next) {
next.prev = null;
}
} else if (prev) {
prev.next = next;
}
if (parent.lastChild === self) {
parent.lastChild = prev;
if (prev) {
prev.next = null;
}
} else if (next) {
next.prev = prev;
}
self.parent = self.next = self.prev = null;
}
return self;
}
append(node) {
const self = this;
if (node.parent) {
node.remove();
}
const last = self.lastChild;
if (last) {
last.next = node;
node.prev = last;
self.lastChild = node;
} else {
self.lastChild = self.firstChild = node;
}
node.parent = self;
return node;
}
insert(node, refNode, before) {
if (node.parent) {
node.remove();
}
const parent = refNode.parent || this;
if (before) {
if (refNode === parent.firstChild) {
parent.firstChild = node;
} else if (refNode.prev) {
refNode.prev.next = node;
}
node.prev = refNode.prev;
node.next = refNode;
refNode.prev = node;
} else {
if (refNode === parent.lastChild) {
parent.lastChild = node;
} else if (refNode.next) {
refNode.next.prev = node;
}
node.next = refNode.next;
node.prev = refNode;
refNode.next = node;
}
node.parent = parent;
return node;
}
getAll(name) {
const self = this;
const collection = [];
for (let node = self.firstChild; node; node = walk$2(node, self)) {
if (node.name === name) {
collection.push(node);
}
}
return collection;
}
children() {
const self = this;
const collection = [];
for (let node = self.firstChild; node; node = node.next) {
collection.push(node);
}
return collection;
}
empty() {
const self = this;
if (self.firstChild) {
const nodes = [];
for (let node = self.firstChild; node; node = walk$2(node, self)) {
nodes.push(node);
}
let i = nodes.length;
while (i--) {
const node = nodes[i];
node.parent =
node.firstChild =
node.lastChild =
node.next =
node.prev =
null;
}
}
self.firstChild = self.lastChild = null;
return self;
}
isEmpty(elements, whitespace = {}, predicate) {
var _a;
const self = this;
let node = self.firstChild;
if (isNonEmptyElement(self)) {
return false;
}
if (node) {
do {
if (node.type === 1) {
if (node.attr("data-mce-bogus")) {
continue;
}
if (elements[node.name]) {
return false;
}
if (isNonEmptyElement(node)) {
return false;
}
}
if (node.type === 8) {
return false;
}
if (node.type === 3 && !isEmptyTextNode(node)) {
return false;
}
if (
node.type === 3 &&
node.parent &&
whitespace[node.parent.name] &&
isWhitespaceText(
(_a = node.value) !== null && _a !== void 0 ? _a : ""
)
) {
return false;
}
if (predicate && predicate(node)) {
return false;
}
} while ((node = walk$2(node, self)));
}
return true;
}
walk(prev) {
return walk$2(this, null, prev);
}
}
const isConditionalComment = (html, startIndex) =>
/^\s*\[if [\w\W]+\]>.*/.test(html.substr(startIndex));
const findCommentEndIndex = (html, isBogus, startIndex = 0) => {
const lcHtml = html.toLowerCase();
if (
lcHtml.indexOf("[if ", startIndex) !== -1 &&
isConditionalComment(lcHtml, startIndex)
) {
const endIfIndex = lcHtml.indexOf("[endif]", startIndex);
return lcHtml.indexOf(">", endIfIndex);
} else {
if (isBogus) {
const endIndex = lcHtml.indexOf(">", startIndex);
return endIndex !== -1 ? endIndex : lcHtml.length;
} else {
const endCommentRegexp = /--!?>/g;
endCommentRegexp.lastIndex = startIndex;
const match = endCommentRegexp.exec(html);
return match ? match.index + match[0].length : lcHtml.length;
}
}
};
const findMatchingEndTagIndex = (schema, html, startIndex) => {
const startTagRegExp = /<([!?\/])?([A-Za-z0-9\-_:.]+)/g;
const endTagRegExp =
/(?:\s(?:[^'">]+(?:"[^"]*"|'[^']*'))*[^"'>]*(?:"[^">]*|'[^'>]*)?|\s*|\/)>/g;
const voidElements = schema.getVoidElements();
let count = 1,
index = startIndex;
while (count !== 0) {
startTagRegExp.lastIndex = index;
while (true) {
const startMatch = startTagRegExp.exec(html);
if (startMatch === null) {
return index;
} else if (startMatch[1] === "!") {
if (startsWith(startMatch[2], "--")) {
index = findCommentEndIndex(
html,
false,
startMatch.index + "!--".length
);
} else {
index = findCommentEndIndex(html, true, startMatch.index + 1);
}
break;
} else {
endTagRegExp.lastIndex = startTagRegExp.lastIndex;
const endMatch = endTagRegExp.exec(html);
if (isNull(endMatch) || endMatch.index !== startTagRegExp.lastIndex) {
continue;
}
if (startMatch[1] === "/") {
count -= 1;
} else if (!has$2(voidElements, startMatch[2])) {
count += 1;
}
index = startTagRegExp.lastIndex + endMatch[0].length;
break;
}
}
}
return index;
};
const trimHtml$1 = (tempAttrs, html) => {
const trimContentRegExp = new RegExp(
["\\s?(" + tempAttrs.join("|") + ')="[^"]+"'].join("|"),
"gi"
);
return html.replace(trimContentRegExp, "");
};
const trimInternal = (serializer, html) => {
const bogusAllRegExp = /<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g;
const schema = serializer.schema;
let content = trimHtml$1(serializer.getTempAttrs(), html);
const voidElements = schema.getVoidElements();
let matches;
while ((matches = bogusAllRegExp.exec(content))) {
const index = bogusAllRegExp.lastIndex;
const matchLength = matches[0].length;
let endTagIndex;
if (voidElements[matches[1]]) {
endTagIndex = index;
} else {
endTagIndex = findMatchingEndTagIndex(schema, content, index);
}
content =
content.substring(0, index - matchLength) +
content.substring(endTagIndex);
bogusAllRegExp.lastIndex = index - matchLength;
}
return trim$1(content);
};
const trimExternal = trimInternal;
const cleanupBogusElements = (parent) => {
const bogusElements = descendants(parent, "[data-mce-bogus]");
each$e(bogusElements, (elem) => {
const bogusValue = get$9(elem, "data-mce-bogus");
if (bogusValue === "all") {
remove$5(elem);
} else if (isBr$5(elem)) {
before$3(elem, SugarElement.fromText(zeroWidth));
remove$5(elem);
} else {
unwrap(elem);
}
});
};
const cleanupInputNames = (parent) => {
const inputs = descendants(parent, "input");
each$e(inputs, (input) => {
remove$a(input, "name");
});
};
const trimEmptyContents = (editor, html) => {
const blockName = getForcedRootBlock(editor);
const emptyRegExp = new RegExp(
`^(<${blockName}[^>]*>( | |\\s|\u00a0|
|)<\\/${blockName}>[\r\n]*|
[\r\n]*)$`
);
return html.replace(emptyRegExp, "");
};
const getPlainTextContent = (editor, body) => {
const doc = editor.getDoc();
const dos = getRootNode(SugarElement.fromDom(editor.getBody()));
const offscreenDiv = SugarElement.fromTag("div", doc);
set$3(offscreenDiv, "data-mce-bogus", "all");
setAll(offscreenDiv, {
position: "fixed",
left: "-9999999px",
top: "0",
});
set$1(offscreenDiv, body.innerHTML);
cleanupBogusElements(offscreenDiv);
cleanupInputNames(offscreenDiv);
const root = getContentContainer(dos);
append$1(root, offscreenDiv);
const content = trim$1(offscreenDiv.dom.innerText);
remove$5(offscreenDiv);
return content;
};
const getContentFromBody = (editor, args, body) => {
let content;
if (args.format === "raw") {
content = Tools.trim(trimExternal(editor.serializer, body.innerHTML));
} else if (args.format === "text") {
content = getPlainTextContent(editor, body);
} else if (args.format === "tree") {
content = editor.serializer.serialize(body, args);
} else {
content = trimEmptyContents(
editor,
editor.serializer.serialize(body, args)
);
}
const shouldTrim =
args.format !== "text" &&
!isWsPreserveElement(SugarElement.fromDom(body));
return shouldTrim && isString(content) ? Tools.trim(content) : content;
};
const getContentInternal = (editor, args) =>
Optional.from(editor.getBody()).fold(
constant(args.format === "tree" ? new AstNode("body", 11) : ""),
(body) => getContentFromBody(editor, args, body)
);
const makeMap$1 = Tools.makeMap;
const Writer = (settings) => {
const html = [];
settings = settings || {};
const indent = settings.indent;
const indentBefore = makeMap$1(settings.indent_before || "");
const indentAfter = makeMap$1(settings.indent_after || "");
const encode = Entities.getEncodeFunc(
settings.entity_encoding || "raw",
settings.entities
);
const htmlOutput = settings.element_format !== "xhtml";
return {
start: (name, attrs, empty) => {
if (indent && indentBefore[name] && html.length > 0) {
const value = html[html.length - 1];
if (value.length > 0 && value !== "\n") {
html.push("\n");
}
}
html.push("<", name);
if (attrs) {
for (let i = 0, l = attrs.length; i < l; i++) {
const attr = attrs[i];
html.push(" ", attr.name, '="', encode(attr.value, true), '"');
}
}
if (!empty || htmlOutput) {
html[html.length] = ">";
} else {
html[html.length] = " />";
}
if (empty && indent && indentAfter[name] && html.length > 0) {
const value = html[html.length - 1];
if (value.length > 0 && value !== "\n") {
html.push("\n");
}
}
},
end: (name) => {
let value;
html.push("", name, ">");
if (indent && indentAfter[name] && html.length > 0) {
value = html[html.length - 1];
if (value.length > 0 && value !== "\n") {
html.push("\n");
}
}
},
text: (text, raw) => {
if (text.length > 0) {
html[html.length] = raw ? text : encode(text);
}
},
cdata: (text) => {
html.push("");
},
comment: (text) => {
html.push("");
},
pi: (name, text) => {
if (text) {
html.push("", name, " ", encode(text), "?>");
} else {
html.push("", name, "?>");
}
if (indent) {
html.push("\n");
}
},
doctype: (text) => {
html.push("", indent ? "\n" : "");
},
reset: () => {
html.length = 0;
},
getContent: () => {
return html.join("").replace(/\n$/, "");
},
};
};
const HtmlSerializer = (settings = {}, schema = Schema()) => {
const writer = Writer(settings);
settings.validate = "validate" in settings ? settings.validate : true;
const serialize = (node) => {
const validate = settings.validate;
const handlers = {
3: (node) => {
var _a;
writer.text(
(_a = node.value) !== null && _a !== void 0 ? _a : "",
node.raw
);
},
8: (node) => {
var _a;
writer.comment((_a = node.value) !== null && _a !== void 0 ? _a : "");
},
7: (node) => {
writer.pi(node.name, node.value);
},
10: (node) => {
var _a;
writer.doctype((_a = node.value) !== null && _a !== void 0 ? _a : "");
},
4: (node) => {
var _a;
writer.cdata((_a = node.value) !== null && _a !== void 0 ? _a : "");
},
11: (node) => {
let tempNode = node;
if ((tempNode = tempNode.firstChild)) {
do {
walk(tempNode);
} while ((tempNode = tempNode.next));
}
},
};
writer.reset();
const walk = (node) => {
var _a;
const handler = handlers[node.type];
if (!handler) {
const name = node.name;
const isEmpty = name in schema.getVoidElements();
let attrs = node.attributes;
if (validate && attrs && attrs.length > 1) {
const sortedAttrs = [];
sortedAttrs.map = {};
const elementRule = schema.getElementRule(node.name);
if (elementRule) {
for (
let i = 0, l = elementRule.attributesOrder.length;
i < l;
i++
) {
const attrName = elementRule.attributesOrder[i];
if (attrName in attrs.map) {
const attrValue = attrs.map[attrName];
sortedAttrs.map[attrName] = attrValue;
sortedAttrs.push({
name: attrName,
value: attrValue,
});
}
}
for (let i = 0, l = attrs.length; i < l; i++) {
const attrName = attrs[i].name;
if (!(attrName in sortedAttrs.map)) {
const attrValue = attrs.map[attrName];
sortedAttrs.map[attrName] = attrValue;
sortedAttrs.push({
name: attrName,
value: attrValue,
});
}
}
attrs = sortedAttrs;
}
}
writer.start(name, attrs, isEmpty);
if (!isEmpty) {
let child = node.firstChild;
if (child) {
if (
(name === "pre" || name === "textarea") &&
child.type === 3 &&
((_a = child.value) === null || _a === void 0
? void 0
: _a[0]) === "\n"
) {
writer.text("\n", true);
}
do {
walk(child);
} while ((child = child.next));
}
writer.end(name);
}
} else {
handler(node);
}
};
if (node.type === 1 && !settings.inner) {
walk(node);
} else if (node.type === 3) {
handlers[3](node);
} else {
handlers[11](node);
}
return writer.getContent();
};
return { serialize };
};
const nonInheritableStyles = new Set();
(() => {
const nonInheritableStylesArr = [
"margin",
"margin-left",
"margin-right",
"margin-top",
"margin-bottom",
"padding",
"padding-left",
"padding-right",
"padding-top",
"padding-bottom",
"border",
"border-width",
"border-style",
"border-color",
"background",
"background-attachment",
"background-clip",
"background-color",
"background-image",
"background-origin",
"background-position",
"background-repeat",
"background-size",
"float",
"position",
"left",
"right",
"top",
"bottom",
"z-index",
"display",
"transform",
"width",
"max-width",
"min-width",
"height",
"max-height",
"min-height",
"overflow",
"overflow-x",
"overflow-y",
"text-overflow",
"vertical-align",
"transition",
"transition-delay",
"transition-duration",
"transition-property",
"transition-timing-function",
];
each$e(nonInheritableStylesArr, (style) => {
nonInheritableStyles.add(style);
});
})();
const shorthandStyleProps = ["font", "text-decoration", "text-emphasis"];
const getStyleProps = (dom, node) =>
keys(dom.parseStyle(dom.getAttrib(node, "style")));
const isNonInheritableStyle = (style) => nonInheritableStyles.has(style);
const hasInheritableStyles = (dom, node) =>
forall(getStyleProps(dom, node), (style) => !isNonInheritableStyle(style));
const getLonghandStyleProps = (styles) =>
filter$5(styles, (style) =>
exists(shorthandStyleProps, (prop) => startsWith(style, prop))
);
const hasStyleConflict = (dom, node, parentNode) => {
const nodeStyleProps = getStyleProps(dom, node);
const parentNodeStyleProps = getStyleProps(dom, parentNode);
const valueMismatch = (prop) => {
var _a, _b;
const nodeValue =
(_a = dom.getStyle(node, prop)) !== null && _a !== void 0 ? _a : "";
const parentValue =
(_b = dom.getStyle(parentNode, prop)) !== null && _b !== void 0
? _b
: "";
return (
isNotEmpty(nodeValue) &&
isNotEmpty(parentValue) &&
nodeValue !== parentValue
);
};
return exists(nodeStyleProps, (nodeStyleProp) => {
const propExists = (props) =>
exists(props, (prop) => prop === nodeStyleProp);
if (
!propExists(parentNodeStyleProps) &&
propExists(shorthandStyleProps)
) {
const longhandProps = getLonghandStyleProps(parentNodeStyleProps);
return exists(longhandProps, valueMismatch);
} else {
return valueMismatch(nodeStyleProp);
}
});
};
const isChar = (forward, predicate, pos) =>
Optional.from(pos.container())
.filter(isText$a)
.exists((text) => {
const delta = forward ? 0 : -1;
return predicate(text.data.charAt(pos.offset() + delta));
});
const isBeforeSpace = curry(isChar, true, isWhiteSpace);
const isAfterSpace = curry(isChar, false, isWhiteSpace);
const isEmptyText = (pos) => {
const container = pos.container();
return (
isText$a(container) &&
(container.data.length === 0 ||
(isZwsp$1(container.data) &&
BookmarkManager.isBookmarkNode(container.parentNode)))
);
};
const matchesElementPosition = (before, predicate) => (pos) =>
getChildNodeAtRelativeOffset(before ? 0 : -1, pos)
.filter(predicate)
.isSome();
const isImageBlock = (node) =>
isImg(node) && get$7(SugarElement.fromDom(node), "display") === "block";
const isCefNode = (node) =>
isContentEditableFalse$b(node) && !isBogusAll$1(node);
const isBeforeImageBlock = matchesElementPosition(true, isImageBlock);
const isAfterImageBlock = matchesElementPosition(false, isImageBlock);
const isBeforeMedia = matchesElementPosition(true, isMedia$2);
const isAfterMedia = matchesElementPosition(false, isMedia$2);
const isBeforeTable = matchesElementPosition(true, isTable$2);
const isAfterTable = matchesElementPosition(false, isTable$2);
const isBeforeContentEditableFalse = matchesElementPosition(true, isCefNode);
const isAfterContentEditableFalse = matchesElementPosition(false, isCefNode);
const dropLast = (xs) => xs.slice(0, -1);
const parentsUntil = (start, root, predicate) => {
if (contains(root, start)) {
return dropLast(
parents$1(start, (elm) => {
return predicate(elm) || eq(elm, root);
})
);
} else {
return [];
}
};
const parents = (start, root) => parentsUntil(start, root, never);
const parentsAndSelf = (start, root) => [start].concat(parents(start, root));
const navigateIgnoreEmptyTextNodes = (forward, root, from) =>
navigateIgnore(forward, root, from, isEmptyText);
const getClosestBlock$1 = (root, pos) =>
find$2(
parentsAndSelf(SugarElement.fromDom(pos.container()), root),
isBlock$2
);
const isAtBeforeAfterBlockBoundary = (forward, root, pos) =>
navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall((newPos) =>
getClosestBlock$1(root, pos).fold(
() => !isInSameBlock(newPos, pos, root.dom),
(fromBlock) =>
!isInSameBlock(newPos, pos, root.dom) &&
contains(fromBlock, SugarElement.fromDom(newPos.container()))
)
);
const isAtBlockBoundary = (forward, root, pos) =>
getClosestBlock$1(root, pos).fold(
() =>
navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall(
(newPos) => !isInSameBlock(newPos, pos, root.dom)
),
(parent) =>
navigateIgnoreEmptyTextNodes(forward, parent.dom, pos).isNone()
);
const isAtStartOfBlock = curry(isAtBlockBoundary, false);
const isAtEndOfBlock = curry(isAtBlockBoundary, true);
const isBeforeBlock = curry(isAtBeforeAfterBlockBoundary, false);
const isAfterBlock = curry(isAtBeforeAfterBlockBoundary, true);
const isBr$1 = (pos) => getElementFromPosition(pos).exists(isBr$5);
const findBr = (forward, root, pos) => {
const parentBlocks = filter$5(
parentsAndSelf(SugarElement.fromDom(pos.container()), root),
isBlock$2
);
const scope = head(parentBlocks).getOr(root);
return fromPosition(forward, scope.dom, pos).filter(isBr$1);
};
const isBeforeBr$1 = (root, pos) =>
getElementFromPosition(pos).exists(isBr$5) ||
findBr(true, root, pos).isSome();
const isAfterBr = (root, pos) =>
getElementFromPrevPosition(pos).exists(isBr$5) ||
findBr(false, root, pos).isSome();
const findPreviousBr = curry(findBr, false);
const findNextBr = curry(findBr, true);
const isInMiddleOfText = (pos) =>
CaretPosition.isTextPosition(pos) && !pos.isAtStart() && !pos.isAtEnd();
const getClosestBlock = (root, pos) => {
const parentBlocks = filter$5(
parentsAndSelf(SugarElement.fromDom(pos.container()), root),
isBlock$2
);
return head(parentBlocks).getOr(root);
};
const hasSpaceBefore = (root, pos) => {
if (isInMiddleOfText(pos)) {
return isAfterSpace(pos);
} else {
return (
isAfterSpace(pos) ||
prevPosition(getClosestBlock(root, pos).dom, pos).exists(isAfterSpace)
);
}
};
const hasSpaceAfter = (root, pos) => {
if (isInMiddleOfText(pos)) {
return isBeforeSpace(pos);
} else {
return (
isBeforeSpace(pos) ||
nextPosition(getClosestBlock(root, pos).dom, pos).exists(isBeforeSpace)
);
}
};
const isPreValue = (value) => contains$2(["pre", "pre-wrap"], value);
const isInPre = (pos) =>
getElementFromPosition(pos)
.bind((elm) => closest$4(elm, isElement$7))
.exists((elm) => isPreValue(get$7(elm, "white-space")));
const isAtBeginningOfBody = (root, pos) =>
prevPosition(root.dom, pos).isNone();
const isAtEndOfBody = (root, pos) => nextPosition(root.dom, pos).isNone();
const isAtLineBoundary = (root, pos) =>
isAtBeginningOfBody(root, pos) ||
isAtEndOfBody(root, pos) ||
isAtStartOfBlock(root, pos) ||
isAtEndOfBlock(root, pos) ||
isAfterBr(root, pos) ||
isBeforeBr$1(root, pos);
const isCefBlock = (node) =>
isNonNullable(node) && isContentEditableFalse$b(node) && isBlockLike(node);
const isSiblingCefBlock = (root, direction) => (container) => {
return isCefBlock(new DomTreeWalker(container, root)[direction]());
};
const isBeforeCefBlock = (root, pos) => {
const nextPos = nextPosition(root.dom, pos).getOr(pos);
const isNextCefBlock = isSiblingCefBlock(root.dom, "next");
return (
pos.isAtEnd() &&
(isNextCefBlock(pos.container()) || isNextCefBlock(nextPos.container()))
);
};
const isAfterCefBlock = (root, pos) => {
const prevPos = prevPosition(root.dom, pos).getOr(pos);
const isPrevCefBlock = isSiblingCefBlock(root.dom, "prev");
return (
pos.isAtStart() &&
(isPrevCefBlock(pos.container()) || isPrevCefBlock(prevPos.container()))
);
};
const needsToHaveNbsp = (root, pos) => {
if (isInPre(pos)) {
return false;
} else {
return (
isAtLineBoundary(root, pos) ||
hasSpaceBefore(root, pos) ||
hasSpaceAfter(root, pos)
);
}
};
const needsToBeNbspLeft = (root, pos) => {
if (isInPre(pos)) {
return false;
} else {
return (
isAtStartOfBlock(root, pos) ||
isBeforeBlock(root, pos) ||
isAfterBr(root, pos) ||
hasSpaceBefore(root, pos) ||
isAfterCefBlock(root, pos)
);
}
};
const leanRight = (pos) => {
const container = pos.container();
const offset = pos.offset();
if (isText$a(container) && offset < container.data.length) {
return CaretPosition(container, offset + 1);
} else {
return pos;
}
};
const needsToBeNbspRight = (root, pos) => {
if (isInPre(pos)) {
return false;
} else {
return (
isAtEndOfBlock(root, pos) ||
isAfterBlock(root, pos) ||
isBeforeBr$1(root, pos) ||
hasSpaceAfter(root, pos) ||
isBeforeCefBlock(root, pos)
);
}
};
const needsToBeNbsp = (root, pos) =>
needsToBeNbspLeft(root, pos) || needsToBeNbspRight(root, leanRight(pos));
const isNbspAt = (text, offset) => isNbsp(text.charAt(offset));
const isWhiteSpaceAt = (text, offset) => isWhiteSpace(text.charAt(offset));
const hasNbsp = (pos) => {
const container = pos.container();
return isText$a(container) && contains$1(container.data, nbsp);
};
const normalizeNbspMiddle = (text) => {
const chars = text.split("");
return map$3(chars, (chr, i) => {
if (
isNbsp(chr) &&
i > 0 &&
i < chars.length - 1 &&
isContent(chars[i - 1]) &&
isContent(chars[i + 1])
) {
return " ";
} else {
return chr;
}
}).join("");
};
const normalizeNbspAtStart = (root, node, makeNbsp) => {
const text = node.data;
const firstPos = CaretPosition(node, 0);
if (!makeNbsp && isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos)) {
node.data = " " + text.slice(1);
return true;
} else if (
makeNbsp &&
isWhiteSpaceAt(text, 0) &&
needsToBeNbspLeft(root, firstPos)
) {
node.data = nbsp + text.slice(1);
return true;
} else {
return false;
}
};
const normalizeNbspInMiddleOfTextNode = (node) => {
const text = node.data;
const newText = normalizeNbspMiddle(text);
if (newText !== text) {
node.data = newText;
return true;
} else {
return false;
}
};
const normalizeNbspAtEnd = (root, node, makeNbsp) => {
const text = node.data;
const lastPos = CaretPosition(node, text.length - 1);
if (
!makeNbsp &&
isNbspAt(text, text.length - 1) &&
!needsToBeNbsp(root, lastPos)
) {
node.data = text.slice(0, -1) + " ";
return true;
} else if (
makeNbsp &&
isWhiteSpaceAt(text, text.length - 1) &&
needsToBeNbspRight(root, lastPos)
) {
node.data = text.slice(0, -1) + nbsp;
return true;
} else {
return false;
}
};
const normalizeNbsps = (root, pos) => {
const container = pos.container();
if (!isText$a(container)) {
return Optional.none();
}
if (hasNbsp(pos)) {
const normalized =
normalizeNbspAtStart(root, container, false) ||
normalizeNbspInMiddleOfTextNode(container) ||
normalizeNbspAtEnd(root, container, false);
return someIf(normalized, pos);
} else if (needsToBeNbsp(root, pos)) {
const normalized =
normalizeNbspAtStart(root, container, true) ||
normalizeNbspAtEnd(root, container, true);
return someIf(normalized, pos);
} else {
return Optional.none();
}
};
const normalizeNbspsInEditor = (editor) => {
const root = SugarElement.fromDom(editor.getBody());
if (editor.selection.isCollapsed()) {
normalizeNbsps(
root,
CaretPosition.fromRangeStart(editor.selection.getRng())
).each((pos) => {
editor.selection.setRng(pos.toRange());
});
}
};
const normalize$1 = (node, offset, count) => {
if (count === 0) {
return;
}
const elm = SugarElement.fromDom(node);
const root = ancestor$4(elm, isBlock$2).getOr(elm);
const whitespace = node.data.slice(offset, offset + count);
const isEndOfContent =
offset + count >= node.data.length &&
needsToBeNbspRight(root, CaretPosition(node, node.data.length));
const isStartOfContent =
offset === 0 && needsToBeNbspLeft(root, CaretPosition(node, 0));
node.replaceData(
offset,
count,
normalize$4(whitespace, 4, isStartOfContent, isEndOfContent)
);
};
const normalizeWhitespaceAfter = (node, offset) => {
const content = node.data.slice(offset);
const whitespaceCount = content.length - lTrim(content).length;
normalize$1(node, offset, whitespaceCount);
};
const normalizeWhitespaceBefore = (node, offset) => {
const content = node.data.slice(0, offset);
const whitespaceCount = content.length - rTrim(content).length;
normalize$1(node, offset - whitespaceCount, whitespaceCount);
};
const mergeTextNodes = (
prevNode,
nextNode,
normalizeWhitespace,
mergeToPrev = true
) => {
const whitespaceOffset = rTrim(prevNode.data).length;
const newNode = mergeToPrev ? prevNode : nextNode;
const removeNode = mergeToPrev ? nextNode : prevNode;
if (mergeToPrev) {
newNode.appendData(removeNode.data);
} else {
newNode.insertData(0, removeNode.data);
}
remove$5(SugarElement.fromDom(removeNode));
if (normalizeWhitespace) {
normalizeWhitespaceAfter(newNode, whitespaceOffset);
}
return newNode;
};
const needsReposition = (pos, elm) => {
const container = pos.container();
const offset = pos.offset();
return (
!CaretPosition.isTextPosition(pos) &&
container === elm.parentNode &&
offset > CaretPosition.before(elm).offset()
);
};
const reposition = (elm, pos) =>
needsReposition(pos, elm)
? CaretPosition(pos.container(), pos.offset() - 1)
: pos;
const beforeOrStartOf = (node) =>
isText$a(node) ? CaretPosition(node, 0) : CaretPosition.before(node);
const afterOrEndOf = (node) =>
isText$a(node)
? CaretPosition(node, node.data.length)
: CaretPosition.after(node);
const getPreviousSiblingCaretPosition = (elm) => {
if (isCaretCandidate$3(elm.previousSibling)) {
return Optional.some(afterOrEndOf(elm.previousSibling));
} else {
return elm.previousSibling
? lastPositionIn(elm.previousSibling)
: Optional.none();
}
};
const getNextSiblingCaretPosition = (elm) => {
if (isCaretCandidate$3(elm.nextSibling)) {
return Optional.some(beforeOrStartOf(elm.nextSibling));
} else {
return elm.nextSibling
? firstPositionIn(elm.nextSibling)
: Optional.none();
}
};
const findCaretPositionBackwardsFromElm = (rootElement, elm) => {
return Optional.from(
elm.previousSibling ? elm.previousSibling : elm.parentNode
)
.bind((node) => prevPosition(rootElement, CaretPosition.before(node)))
.orThunk(() => nextPosition(rootElement, CaretPosition.after(elm)));
};
const findCaretPositionForwardsFromElm = (rootElement, elm) =>
nextPosition(rootElement, CaretPosition.after(elm)).orThunk(() =>
prevPosition(rootElement, CaretPosition.before(elm))
);
const findCaretPositionBackwards = (rootElement, elm) =>
getPreviousSiblingCaretPosition(elm)
.orThunk(() => getNextSiblingCaretPosition(elm))
.orThunk(() => findCaretPositionBackwardsFromElm(rootElement, elm));
const findCaretPositionForward = (rootElement, elm) =>
getNextSiblingCaretPosition(elm)
.orThunk(() => getPreviousSiblingCaretPosition(elm))
.orThunk(() => findCaretPositionForwardsFromElm(rootElement, elm));
const findCaretPosition = (forward, rootElement, elm) =>
forward
? findCaretPositionForward(rootElement, elm)
: findCaretPositionBackwards(rootElement, elm);
const findCaretPosOutsideElmAfterDelete = (forward, rootElement, elm) =>
findCaretPosition(forward, rootElement, elm).map(curry(reposition, elm));
const setSelection$1 = (editor, forward, pos) => {
pos.fold(
() => {
editor.focus();
},
(pos) => {
editor.selection.setRng(pos.toRange(), forward);
}
);
};
const eqRawNode = (rawNode) => (elm) => elm.dom === rawNode;
const isBlock = (editor, elm) =>
elm && has$2(editor.schema.getBlockElements(), name(elm));
const paddEmptyBlock = (elm) => {
if (isEmpty$2(elm)) {
const br = SugarElement.fromHtml('
');
empty(elm);
append$1(elm, br);
return Optional.some(CaretPosition.before(br.dom));
} else {
return Optional.none();
}
};
const deleteNormalized = (elm, afterDeletePosOpt, normalizeWhitespace) => {
const prevTextOpt = prevSibling(elm).filter(isText$b);
const nextTextOpt = nextSibling(elm).filter(isText$b);
remove$5(elm);
return lift3(
prevTextOpt,
nextTextOpt,
afterDeletePosOpt,
(prev, next, pos) => {
const prevNode = prev.dom,
nextNode = next.dom;
const offset = prevNode.data.length;
mergeTextNodes(prevNode, nextNode, normalizeWhitespace);
return pos.container() === nextNode
? CaretPosition(prevNode, offset)
: pos;
}
).orThunk(() => {
if (normalizeWhitespace) {
prevTextOpt.each((elm) =>
normalizeWhitespaceBefore(elm.dom, elm.dom.length)
);
nextTextOpt.each((elm) => normalizeWhitespaceAfter(elm.dom, 0));
}
return afterDeletePosOpt;
});
};
const isInlineElement = (editor, element) =>
has$2(editor.schema.getTextInlineElements(), name(element));
const deleteElement$2 = (editor, forward, elm, moveCaret = true) => {
const afterDeletePos = findCaretPosOutsideElmAfterDelete(
forward,
editor.getBody(),
elm.dom
);
const parentBlock = ancestor$4(
elm,
curry(isBlock, editor),
eqRawNode(editor.getBody())
);
const normalizedAfterDeletePos = deleteNormalized(
elm,
afterDeletePos,
isInlineElement(editor, elm)
);
if (editor.dom.isEmpty(editor.getBody())) {
editor.setContent("");
editor.selection.setCursorLocation();
} else {
parentBlock.bind(paddEmptyBlock).fold(
() => {
if (moveCaret) {
setSelection$1(editor, forward, normalizedAfterDeletePos);
}
},
(paddPos) => {
if (moveCaret) {
setSelection$1(editor, forward, Optional.some(paddPos));
}
}
);
}
};
const strongRtl = /[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/;
const hasStrongRtl = (text) => strongRtl.test(text);
const isInlineTarget = (editor, elm) =>
is$1(SugarElement.fromDom(elm), getInlineBoundarySelector(editor)) &&
!isTransparentBlock(editor.schema, elm) &&
editor.dom.isEditable(elm);
const isRtl = (element) => {
var _a;
return (
DOMUtils.DOM.getStyle(element, "direction", true) === "rtl" ||
hasStrongRtl(
(_a = element.textContent) !== null && _a !== void 0 ? _a : ""
)
);
};
const findInlineParents = (isInlineTarget, rootNode, pos) =>
filter$5(
DOMUtils.DOM.getParents(pos.container(), "*", rootNode),
isInlineTarget
);
const findRootInline = (isInlineTarget, rootNode, pos) => {
const parents = findInlineParents(isInlineTarget, rootNode, pos);
return Optional.from(parents[parents.length - 1]);
};
const hasSameParentBlock = (rootNode, node1, node2) => {
const block1 = getParentBlock$3(node1, rootNode);
const block2 = getParentBlock$3(node2, rootNode);
return isNonNullable(block1) && block1 === block2;
};
const isAtZwsp = (pos) => isBeforeInline(pos) || isAfterInline(pos);
const normalizePosition = (forward, pos) => {
const container = pos.container(),
offset = pos.offset();
if (forward) {
if (isCaretContainerInline(container)) {
if (isText$a(container.nextSibling)) {
return CaretPosition(container.nextSibling, 0);
} else {
return CaretPosition.after(container);
}
} else {
return isBeforeInline(pos) ? CaretPosition(container, offset + 1) : pos;
}
} else {
if (isCaretContainerInline(container)) {
if (isText$a(container.previousSibling)) {
return CaretPosition(
container.previousSibling,
container.previousSibling.data.length
);
} else {
return CaretPosition.before(container);
}
} else {
return isAfterInline(pos) ? CaretPosition(container, offset - 1) : pos;
}
}
};
const normalizeForwards = curry(normalizePosition, true);
const normalizeBackwards = curry(normalizePosition, false);
const execCommandIgnoreInputEvents = (editor, command) => {
const inputBlocker = (e) => e.stopImmediatePropagation();
editor.on("beforeinput input", inputBlocker, true);
editor.getDoc().execCommand(command);
editor.off("beforeinput input", inputBlocker);
};
const execEditorDeleteCommand = (editor) => {
editor.execCommand("delete");
};
const execNativeDeleteCommand = (editor) =>
execCommandIgnoreInputEvents(editor, "Delete");
const execNativeForwardDeleteCommand = (editor) =>
execCommandIgnoreInputEvents(editor, "ForwardDelete");
const isBeforeRoot = (rootNode) => (elm) => is$2(parent(elm), rootNode, eq);
const isTextBlockOrListItem = (element) =>
isTextBlock$2(element) || isListItem$1(element);
const getParentBlock$2 = (rootNode, elm) => {
if (contains(rootNode, elm)) {
return closest$4(elm, isTextBlockOrListItem, isBeforeRoot(rootNode));
} else {
return Optional.none();
}
};
const paddEmptyBody = (editor, moveSelection = true) => {
if (editor.dom.isEmpty(editor.getBody())) {
editor.setContent("", { no_selection: !moveSelection });
}
};
const willDeleteLastPositionInElement = (forward, fromPos, elm) =>
lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => {
const normalizedFirstPos = normalizePosition(true, firstPos);
const normalizedLastPos = normalizePosition(false, lastPos);
const normalizedFromPos = normalizePosition(false, fromPos);
if (forward) {
return nextPosition(elm, normalizedFromPos).exists(
(nextPos) =>
nextPos.isEqual(normalizedLastPos) &&
fromPos.isEqual(normalizedFirstPos)
);
} else {
return prevPosition(elm, normalizedFromPos).exists(
(prevPos) =>
prevPos.isEqual(normalizedFirstPos) &&
fromPos.isEqual(normalizedLastPos)
);
}
}).getOr(true);
const freefallRtl = (root) => {
const child = isComment$1(root) ? prevSibling(root) : lastChild(root);
return child.bind(freefallRtl).orThunk(() => Optional.some(root));
};
const deleteRangeContents = (editor, rng, root, moveSelection = true) => {
var _a;
rng.deleteContents();
const lastNode = freefallRtl(root).getOr(root);
const lastBlock = SugarElement.fromDom(
(_a = editor.dom.getParent(lastNode.dom, editor.dom.isBlock)) !== null &&
_a !== void 0
? _a
: root.dom
);
if (lastBlock.dom === editor.getBody()) {
paddEmptyBody(editor, moveSelection);
} else if (isEmpty$2(lastBlock)) {
fillWithPaddingBr(lastBlock);
if (moveSelection) {
editor.selection.setCursorLocation(lastBlock.dom, 0);
}
}
if (!eq(root, lastBlock)) {
const additionalCleanupNodes = is$2(parent(lastBlock), root)
? []
: siblings(lastBlock);
each$e(additionalCleanupNodes.concat(children$1(root)), (node) => {
if (
!eq(node, lastBlock) &&
!contains(node, lastBlock) &&
isEmpty$2(node)
) {
remove$5(node);
}
});
}
};
const isRootFromElement = (root) => (cur) => eq(root, cur);
const getTableCells = (table) => descendants(table, "td,th");
const getTableDetailsFromRange = (rng, isRoot) => {
const getTable = (node) =>
getClosestTable(SugarElement.fromDom(node), isRoot);
const startTable = getTable(rng.startContainer);
const endTable = getTable(rng.endContainer);
const isStartInTable = startTable.isSome();
const isEndInTable = endTable.isSome();
const isSameTable = lift2(startTable, endTable, eq).getOr(false);
const isMultiTable = !isSameTable && isStartInTable && isEndInTable;
return {
startTable,
endTable,
isStartInTable,
isEndInTable,
isSameTable,
isMultiTable,
};
};
const tableCellRng = (start, end) => ({
start,
end,
});
const tableSelection = (rng, table, cells) => ({
rng,
table,
cells,
});
const deleteAction = Adt.generate([
{
singleCellTable: ["rng", "cell"],
},
{ fullTable: ["table"] },
{
partialTable: ["cells", "outsideDetails"],
},
{
multiTable: ["startTableCells", "endTableCells", "betweenRng"],
},
]);
const getClosestCell$1 = (container, isRoot) =>
closest$3(SugarElement.fromDom(container), "td,th", isRoot);
const isExpandedCellRng = (cellRng) => !eq(cellRng.start, cellRng.end);
const getTableFromCellRng = (cellRng, isRoot) =>
getClosestTable(cellRng.start, isRoot).bind((startParentTable) =>
getClosestTable(cellRng.end, isRoot).bind((endParentTable) =>
someIf(eq(startParentTable, endParentTable), startParentTable)
)
);
const isSingleCellTable = (cellRng, isRoot) =>
!isExpandedCellRng(cellRng) &&
getTableFromCellRng(cellRng, isRoot).exists((table) => {
const rows = table.dom.rows;
return rows.length === 1 && rows[0].cells.length === 1;
});
const getCellRng = (rng, isRoot) => {
const startCell = getClosestCell$1(rng.startContainer, isRoot);
const endCell = getClosestCell$1(rng.endContainer, isRoot);
return lift2(startCell, endCell, tableCellRng);
};
const getCellRangeFromStartTable = (isRoot) => (startCell) =>
getClosestTable(startCell, isRoot).bind((table) =>
last$3(getTableCells(table)).map((endCell) =>
tableCellRng(startCell, endCell)
)
);
const getCellRangeFromEndTable = (isRoot) => (endCell) =>
getClosestTable(endCell, isRoot).bind((table) =>
head(getTableCells(table)).map((startCell) =>
tableCellRng(startCell, endCell)
)
);
const getTableSelectionFromCellRng = (isRoot) => (cellRng) =>
getTableFromCellRng(cellRng, isRoot).map((table) =>
tableSelection(cellRng, table, getTableCells(table))
);
const getTableSelections = (cellRng, selectionDetails, rng, isRoot) => {
if (rng.collapsed || !cellRng.forall(isExpandedCellRng)) {
return Optional.none();
} else if (selectionDetails.isSameTable) {
const sameTableSelection = cellRng.bind(
getTableSelectionFromCellRng(isRoot)
);
return Optional.some({
start: sameTableSelection,
end: sameTableSelection,
});
} else {
const startCell = getClosestCell$1(rng.startContainer, isRoot);
const endCell = getClosestCell$1(rng.endContainer, isRoot);
const startTableSelection = startCell
.bind(getCellRangeFromStartTable(isRoot))
.bind(getTableSelectionFromCellRng(isRoot));
const endTableSelection = endCell
.bind(getCellRangeFromEndTable(isRoot))
.bind(getTableSelectionFromCellRng(isRoot));
return Optional.some({
start: startTableSelection,
end: endTableSelection,
});
}
};
const getCellIndex = (cells, cell) => findIndex$2(cells, (x) => eq(x, cell));
const getSelectedCells = (tableSelection) =>
lift2(
getCellIndex(tableSelection.cells, tableSelection.rng.start),
getCellIndex(tableSelection.cells, tableSelection.rng.end),
(startIndex, endIndex) =>
tableSelection.cells.slice(startIndex, endIndex + 1)
);
const isSingleCellTableContentSelected = (optCellRng, rng, isRoot) =>
optCellRng.exists(
(cellRng) =>
isSingleCellTable(cellRng, isRoot) &&
hasAllContentsSelected(cellRng.start, rng)
);
const unselectCells = (rng, selectionDetails) => {
const { startTable, endTable } = selectionDetails;
const otherContentRng = rng.cloneRange();
startTable.each((table) => otherContentRng.setStartAfter(table.dom));
endTable.each((table) => otherContentRng.setEndBefore(table.dom));
return otherContentRng;
};
const handleSingleTable = (cellRng, selectionDetails, rng, isRoot) =>
getTableSelections(cellRng, selectionDetails, rng, isRoot)
.bind(({ start, end }) => start.or(end))
.bind((tableSelection) => {
const { isSameTable } = selectionDetails;
const selectedCells = getSelectedCells(tableSelection).getOr([]);
if (
isSameTable &&
tableSelection.cells.length === selectedCells.length
) {
return Optional.some(deleteAction.fullTable(tableSelection.table));
} else if (selectedCells.length > 0) {
if (isSameTable) {
return Optional.some(
deleteAction.partialTable(selectedCells, Optional.none())
);
} else {
const otherContentRng = unselectCells(rng, selectionDetails);
return Optional.some(
deleteAction.partialTable(
selectedCells,
Optional.some({
...selectionDetails,
rng: otherContentRng,
})
)
);
}
} else {
return Optional.none();
}
});
const handleMultiTable = (cellRng, selectionDetails, rng, isRoot) =>
getTableSelections(cellRng, selectionDetails, rng, isRoot).bind(
({ start, end }) => {
const startTableSelectedCells = start.bind(getSelectedCells).getOr([]);
const endTableSelectedCells = end.bind(getSelectedCells).getOr([]);
if (
startTableSelectedCells.length > 0 &&
endTableSelectedCells.length > 0
) {
const otherContentRng = unselectCells(rng, selectionDetails);
return Optional.some(
deleteAction.multiTable(
startTableSelectedCells,
endTableSelectedCells,
otherContentRng
)
);
} else {
return Optional.none();
}
}
);
const getActionFromRange = (root, rng) => {
const isRoot = isRootFromElement(root);
const optCellRng = getCellRng(rng, isRoot);
const selectionDetails = getTableDetailsFromRange(rng, isRoot);
if (isSingleCellTableContentSelected(optCellRng, rng, isRoot)) {
return optCellRng.map((cellRng) =>
deleteAction.singleCellTable(rng, cellRng.start)
);
} else if (selectionDetails.isMultiTable) {
return handleMultiTable(optCellRng, selectionDetails, rng, isRoot);
} else {
return handleSingleTable(optCellRng, selectionDetails, rng, isRoot);
}
};
const cleanCells = (cells) =>
each$e(cells, (cell) => {
remove$a(cell, "contenteditable");
fillWithPaddingBr(cell);
});
const getOutsideBlock = (editor, container) =>
Optional.from(editor.dom.getParent(container, editor.dom.isBlock)).map(
SugarElement.fromDom
);
const handleEmptyBlock = (editor, startInTable, emptyBlock) => {
emptyBlock.each((block) => {
if (startInTable) {
remove$5(block);
} else {
fillWithPaddingBr(block);
editor.selection.setCursorLocation(block.dom, 0);
}
});
};
const deleteContentInsideCell = (
editor,
cell,
rng,
isFirstCellInSelection
) => {
const insideTableRng = rng.cloneRange();
if (isFirstCellInSelection) {
insideTableRng.setStart(rng.startContainer, rng.startOffset);
insideTableRng.setEndAfter(cell.dom.lastChild);
} else {
insideTableRng.setStartBefore(cell.dom.firstChild);
insideTableRng.setEnd(rng.endContainer, rng.endOffset);
}
deleteCellContents(editor, insideTableRng, cell, false).each((action) =>
action()
);
};
const collapseAndRestoreCellSelection = (editor) => {
const selectedCells = getCellsFromEditor(editor);
const selectedNode = SugarElement.fromDom(editor.selection.getNode());
if (isTableCell$3(selectedNode.dom) && isEmpty$2(selectedNode)) {
editor.selection.setCursorLocation(selectedNode.dom, 0);
} else {
editor.selection.collapse(true);
}
if (
selectedCells.length > 1 &&
exists(selectedCells, (cell) => eq(cell, selectedNode))
) {
set$3(selectedNode, "data-mce-selected", "1");
}
};
const emptySingleTableCells = (editor, cells, outsideDetails) =>
Optional.some(() => {
const editorRng = editor.selection.getRng();
const cellsToClean = outsideDetails
.bind(({ rng, isStartInTable }) => {
const outsideBlock = getOutsideBlock(
editor,
isStartInTable ? rng.endContainer : rng.startContainer
);
rng.deleteContents();
handleEmptyBlock(
editor,
isStartInTable,
outsideBlock.filter(isEmpty$2)
);
const endPointCell = isStartInTable
? cells[0]
: cells[cells.length - 1];
deleteContentInsideCell(
editor,
endPointCell,
editorRng,
isStartInTable
);
if (!isEmpty$2(endPointCell)) {
return Optional.some(
isStartInTable ? cells.slice(1) : cells.slice(0, -1)
);
} else {
return Optional.none();
}
})
.getOr(cells);
cleanCells(cellsToClean);
collapseAndRestoreCellSelection(editor);
});
const emptyMultiTableCells = (
editor,
startTableCells,
endTableCells,
betweenRng
) =>
Optional.some(() => {
const rng = editor.selection.getRng();
const startCell = startTableCells[0];
const endCell = endTableCells[endTableCells.length - 1];
deleteContentInsideCell(editor, startCell, rng, true);
deleteContentInsideCell(editor, endCell, rng, false);
const startTableCellsToClean = isEmpty$2(startCell)
? startTableCells
: startTableCells.slice(1);
const endTableCellsToClean = isEmpty$2(endCell)
? endTableCells
: endTableCells.slice(0, -1);
cleanCells(startTableCellsToClean.concat(endTableCellsToClean));
betweenRng.deleteContents();
collapseAndRestoreCellSelection(editor);
});
const deleteCellContents = (editor, rng, cell, moveSelection = true) =>
Optional.some(() => {
deleteRangeContents(editor, rng, cell, moveSelection);
});
const deleteTableElement = (editor, table) =>
Optional.some(() => deleteElement$2(editor, false, table));
const deleteCellRange = (editor, rootElm, rng) =>
getActionFromRange(rootElm, rng).bind((action) =>
action.fold(
curry(deleteCellContents, editor),
curry(deleteTableElement, editor),
curry(emptySingleTableCells, editor),
curry(emptyMultiTableCells, editor)
)
);
const deleteCaptionRange = (editor, caption) => emptyElement(editor, caption);
const deleteTableRange = (editor, rootElm, rng, startElm) =>
getParentCaption(rootElm, startElm).fold(
() => deleteCellRange(editor, rootElm, rng),
(caption) => deleteCaptionRange(editor, caption)
);
const deleteRange$3 = (editor, startElm, selectedCells) => {
const rootNode = SugarElement.fromDom(editor.getBody());
const rng = editor.selection.getRng();
return selectedCells.length !== 0
? emptySingleTableCells(editor, selectedCells, Optional.none())
: deleteTableRange(editor, rootNode, rng, startElm);
};
const getParentCell = (rootElm, elm) =>
find$2(parentsAndSelf(elm, rootElm), isTableCell$2);
const getParentCaption = (rootElm, elm) =>
find$2(parentsAndSelf(elm, rootElm), isTag("caption"));
const deleteBetweenCells = (editor, rootElm, forward, fromCell, from) =>
navigate(forward, editor.getBody(), from).bind((to) =>
getParentCell(rootElm, SugarElement.fromDom(to.getNode())).bind(
(toCell) =>
eq(toCell, fromCell) ? Optional.none() : Optional.some(noop)
)
);
const emptyElement = (editor, elm) =>
Optional.some(() => {
fillWithPaddingBr(elm);
editor.selection.setCursorLocation(elm.dom, 0);
});
const isDeleteOfLastCharPos = (fromCaption, forward, from, to) =>
firstPositionIn(fromCaption.dom)
.bind((first) =>
lastPositionIn(fromCaption.dom).map((last) =>
forward
? from.isEqual(first) && to.isEqual(last)
: from.isEqual(last) && to.isEqual(first)
)
)
.getOr(true);
const emptyCaretCaption = (editor, elm) => emptyElement(editor, elm);
const validateCaretCaption = (rootElm, fromCaption, to) =>
getParentCaption(rootElm, SugarElement.fromDom(to.getNode())).fold(
() => Optional.some(noop),
(toCaption) => someIf(!eq(toCaption, fromCaption), noop)
);
const deleteCaretInsideCaption = (
editor,
rootElm,
forward,
fromCaption,
from
) =>
navigate(forward, editor.getBody(), from).fold(
() => Optional.some(noop),
(to) =>
isDeleteOfLastCharPos(fromCaption, forward, from, to)
? emptyCaretCaption(editor, fromCaption)
: validateCaretCaption(rootElm, fromCaption, to)
);
const deleteCaretCells = (editor, forward, rootElm, startElm) => {
const from = CaretPosition.fromRangeStart(editor.selection.getRng());
return getParentCell(rootElm, startElm).bind((fromCell) =>
isEmpty$2(fromCell)
? emptyElement(editor, fromCell)
: deleteBetweenCells(editor, rootElm, forward, fromCell, from)
);
};
const deleteCaretCaption = (editor, forward, rootElm, fromCaption) => {
const from = CaretPosition.fromRangeStart(editor.selection.getRng());
return isEmpty$2(fromCaption)
? emptyElement(editor, fromCaption)
: deleteCaretInsideCaption(editor, rootElm, forward, fromCaption, from);
};
const isNearTable = (forward, pos) =>
forward ? isBeforeTable(pos) : isAfterTable(pos);
const isBeforeOrAfterTable = (editor, forward) => {
const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
return (
isNearTable(forward, fromPos) ||
fromPosition(forward, editor.getBody(), fromPos).exists((pos) =>
isNearTable(forward, pos)
)
);
};
const deleteCaret$3 = (editor, forward, startElm) => {
const rootElm = SugarElement.fromDom(editor.getBody());
return getParentCaption(rootElm, startElm).fold(
() =>
deleteCaretCells(editor, forward, rootElm, startElm).orThunk(() =>
someIf(isBeforeOrAfterTable(editor, forward), noop)
),
(fromCaption) => deleteCaretCaption(editor, forward, rootElm, fromCaption)
);
};
const backspaceDelete$a = (editor, forward) => {
const startElm = SugarElement.fromDom(editor.selection.getStart(true));
const cells = getCellsFromEditor(editor);
return editor.selection.isCollapsed() && cells.length === 0
? deleteCaret$3(editor, forward, startElm)
: deleteRange$3(editor, startElm, cells);
};
const getContentEditableRoot$1 = (root, node) => {
let tempNode = node;
while (tempNode && tempNode !== root) {
if (
isContentEditableTrue$3(tempNode) ||
isContentEditableFalse$b(tempNode)
) {
return tempNode;
}
tempNode = tempNode.parentNode;
}
return null;
};
const internalAttributesPrefixes = [
"data-ephox-",
"data-mce-",
"data-alloy-",
"data-snooker-",
"_",
];
const each$9 = Tools.each;
const ElementUtils = (editor) => {
const dom = editor.dom;
const internalAttributes = new Set(editor.serializer.getTempAttrs());
const compare = (node1, node2) => {
if (
node1.nodeName !== node2.nodeName ||
node1.nodeType !== node2.nodeType
) {
return false;
}
const getAttribs = (node) => {
const attribs = {};
each$9(dom.getAttribs(node), (attr) => {
const name = attr.nodeName.toLowerCase();
if (name !== "style" && !isAttributeInternal(name)) {
attribs[name] = dom.getAttrib(node, name);
}
});
return attribs;
};
const compareObjects = (obj1, obj2) => {
for (const name in obj1) {
if (has$2(obj1, name)) {
const value = obj2[name];
if (isUndefined(value)) {
return false;
}
if (obj1[name] !== value) {
return false;
}
delete obj2[name];
}
}
for (const name in obj2) {
if (has$2(obj2, name)) {
return false;
}
}
return true;
};
if (isElement$6(node1) && isElement$6(node2)) {
if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
return false;
}
if (
!compareObjects(
dom.parseStyle(dom.getAttrib(node1, "style")),
dom.parseStyle(dom.getAttrib(node2, "style"))
)
) {
return false;
}
}
return !isBookmarkNode$1(node1) && !isBookmarkNode$1(node2);
};
const isAttributeInternal = (attributeName) =>
exists(internalAttributesPrefixes, (value) =>
startsWith(attributeName, value)
) || internalAttributes.has(attributeName);
return {
compare,
isAttributeInternal,
};
};
const traverse = (root, fn) => {
let node = root;
while ((node = node.walk())) {
fn(node);
}
};
const matchNode$1 = (nodeFilters, attributeFilters, node, matches) => {
const name = node.name;
for (let ni = 0, nl = nodeFilters.length; ni < nl; ni++) {
const filter = nodeFilters[ni];
if (filter.name === name) {
const match = matches.nodes[name];
if (match) {
match.nodes.push(node);
} else {
matches.nodes[name] = {
filter,
nodes: [node],
};
}
}
}
if (node.attributes) {
for (let ai = 0, al = attributeFilters.length; ai < al; ai++) {
const filter = attributeFilters[ai];
const attrName = filter.name;
if (attrName in node.attributes.map) {
const match = matches.attributes[attrName];
if (match) {
match.nodes.push(node);
} else {
matches.attributes[attrName] = {
filter,
nodes: [node],
};
}
}
}
}
};
const findMatchingNodes = (nodeFilters, attributeFilters, node) => {
const matches = {
nodes: {},
attributes: {},
};
if (node.firstChild) {
traverse(node, (childNode) => {
matchNode$1(nodeFilters, attributeFilters, childNode, matches);
});
}
return matches;
};
const runFilters = (matches, args) => {
const run = (matchRecord, filteringAttributes) => {
each$d(matchRecord, (match) => {
const nodes = from(match.nodes);
each$e(match.filter.callbacks, (callback) => {
for (let i = nodes.length - 1; i >= 0; i--) {
const node = nodes[i];
const valueMatches = filteringAttributes
? node.attr(match.filter.name) !== undefined
: node.name === match.filter.name;
if (!valueMatches || isNullable(node.parent)) {
nodes.splice(i, 1);
}
}
if (nodes.length > 0) {
callback(nodes, match.filter.name, args);
}
});
});
};
run(matches.nodes, false);
run(matches.attributes, true);
};
const filter$2 = (nodeFilters, attributeFilters, node, args = {}) => {
const matches = findMatchingNodes(nodeFilters, attributeFilters, node);
runFilters(matches, args);
};
const paddEmptyNode = (settings, args, isBlock, node) => {
const brPreferred = settings.pad_empty_with_br || args.insert;
if (brPreferred && isBlock(node)) {
const astNode = new AstNode("br", 1);
if (args.insert) {
astNode.attr("data-mce-bogus", "1");
}
node.empty().append(astNode);
} else {
node.empty().append(new AstNode("#text", 3)).value = nbsp;
}
};
const isPaddedWithNbsp = (node) => {
var _a;
return (
hasOnlyChild(node, "#text") &&
((_a = node === null || node === void 0 ? void 0 : node.firstChild) ===
null || _a === void 0
? void 0
: _a.value) === nbsp
);
};
const hasOnlyChild = (node, name) => {
const firstChild =
node === null || node === void 0 ? void 0 : node.firstChild;
return (
isNonNullable(firstChild) &&
firstChild === node.lastChild &&
firstChild.name === name
);
};
const isPadded = (schema, node) => {
const rule = schema.getElementRule(node.name);
return (
(rule === null || rule === void 0 ? void 0 : rule.paddEmpty) === true
);
};
const isEmpty = (schema, nonEmptyElements, whitespaceElements, node) =>
node.isEmpty(nonEmptyElements, whitespaceElements, (node) =>
isPadded(schema, node)
);
const isLineBreakNode = (node, isBlock) =>
isNonNullable(node) && (isBlock(node) || node.name === "br");
const findClosestEditingHost = (scope) => {
let editableNode;
for (let node = scope; node; node = node.parent) {
const contentEditable = node.attr("contenteditable");
if (contentEditable === "false") {
break;
} else if (contentEditable === "true") {
editableNode = node;
}
}
return Optional.from(editableNode);
};
const removeOrUnwrapInvalidNode = (
node,
schema,
originalNodeParent = node.parent
) => {
if (schema.getSpecialElements()[node.name]) {
node.empty().remove();
} else {
const children = node.children();
for (const childNode of children) {
if (
originalNodeParent &&
!schema.isValidChild(originalNodeParent.name, childNode.name)
) {
removeOrUnwrapInvalidNode(childNode, schema, originalNodeParent);
}
}
node.unwrap();
}
};
const cleanInvalidNodes = (nodes, schema, rootNode, onCreate = noop) => {
const textBlockElements = schema.getTextBlockElements();
const nonEmptyElements = schema.getNonEmptyElements();
const whitespaceElements = schema.getWhitespaceElements();
const nonSplittableElements = Tools.makeMap(
"tr,td,th,tbody,thead,tfoot,table,summary"
);
const fixed = new Set();
const isSplittableElement = (node) =>
node !== rootNode && !nonSplittableElements[node.name];
for (let ni = 0; ni < nodes.length; ni++) {
const node = nodes[ni];
let parent;
let newParent;
let tempNode;
if (!node.parent || fixed.has(node)) {
continue;
}
if (textBlockElements[node.name] && node.parent.name === "li") {
let sibling = node.next;
while (sibling) {
if (textBlockElements[sibling.name]) {
sibling.name = "li";
fixed.add(sibling);
node.parent.insert(sibling, node.parent);
} else {
break;
}
sibling = sibling.next;
}
node.unwrap();
continue;
}
const parents = [node];
for (
parent = node.parent;
parent &&
!schema.isValidChild(parent.name, node.name) &&
isSplittableElement(parent);
parent = parent.parent
) {
parents.push(parent);
}
if (parent && parents.length > 1) {
if (schema.isValidChild(parent.name, node.name)) {
parents.reverse();
newParent = parents[0].clone();
onCreate(newParent);
let currentNode = newParent;
for (let i = 0; i < parents.length - 1; i++) {
if (
schema.isValidChild(currentNode.name, parents[i].name) &&
i > 0
) {
tempNode = parents[i].clone();
onCreate(tempNode);
currentNode.append(tempNode);
} else {
tempNode = currentNode;
}
for (
let childNode = parents[i].firstChild;
childNode && childNode !== parents[i + 1];
) {
const nextNode = childNode.next;
tempNode.append(childNode);
childNode = nextNode;
}
currentNode = tempNode;
}
if (
!isEmpty(schema, nonEmptyElements, whitespaceElements, newParent)
) {
parent.insert(newParent, parents[0], true);
parent.insert(node, newParent);
} else {
parent.insert(node, parents[0], true);
}
parent = parents[0];
if (
isEmpty(schema, nonEmptyElements, whitespaceElements, parent) ||
hasOnlyChild(parent, "br")
) {
parent.empty().remove();
}
} else {
removeOrUnwrapInvalidNode(node, schema);
}
} else if (node.parent) {
if (node.name === "li") {
let sibling = node.prev;
if (sibling && (sibling.name === "ul" || sibling.name === "ol")) {
sibling.append(node);
continue;
}
sibling = node.next;
if (
sibling &&
(sibling.name === "ul" || sibling.name === "ol") &&
sibling.firstChild
) {
sibling.insert(node, sibling.firstChild, true);
continue;
}
const wrapper = new AstNode("ul", 1);
onCreate(wrapper);
node.wrap(wrapper);
continue;
}
if (
schema.isValidChild(node.parent.name, "div") &&
schema.isValidChild("div", node.name)
) {
const wrapper = new AstNode("div", 1);
onCreate(wrapper);
node.wrap(wrapper);
} else {
removeOrUnwrapInvalidNode(node, schema);
}
}
}
};
const hasClosest = (node, parentName) => {
let tempNode = node;
while (tempNode) {
if (tempNode.name === parentName) {
return true;
}
tempNode = tempNode.parent;
}
return false;
};
const isInvalid = (schema, node, parent = node.parent) => {
if (
parent &&
schema.children[node.name] &&
!schema.isValidChild(parent.name, node.name)
) {
return true;
} else if (parent && node.name === "a" && hasClosest(parent, "a")) {
return true;
} else {
return false;
}
};
const createRange = (sc, so, ec, eo) => {
const rng = document.createRange();
rng.setStart(sc, so);
rng.setEnd(ec, eo);
return rng;
};
const normalizeBlockSelectionRange = (rng) => {
const startPos = CaretPosition.fromRangeStart(rng);
const endPos = CaretPosition.fromRangeEnd(rng);
const rootNode = rng.commonAncestorContainer;
return fromPosition(false, rootNode, endPos)
.map((newEndPos) => {
if (
!isInSameBlock(startPos, endPos, rootNode) &&
isInSameBlock(startPos, newEndPos, rootNode)
) {
return createRange(
startPos.container(),
startPos.offset(),
newEndPos.container(),
newEndPos.offset()
);
} else {
return rng;
}
})
.getOr(rng);
};
const normalize = (rng) =>
rng.collapsed ? rng : normalizeBlockSelectionRange(rng);
const hasOnlyOneChild$1 = (node) => {
return isNonNullable(node.firstChild) && node.firstChild === node.lastChild;
};
const isPaddingNode = (node) => {
return node.name === "br" || node.value === nbsp;
};
const isPaddedEmptyBlock = (schema, node) => {
const blockElements = schema.getBlockElements();
return (
blockElements[node.name] &&
hasOnlyOneChild$1(node) &&
isPaddingNode(node.firstChild)
);
};
const isEmptyFragmentElement = (schema, node) => {
const nonEmptyElements = schema.getNonEmptyElements();
return (
isNonNullable(node) &&
(node.isEmpty(nonEmptyElements) || isPaddedEmptyBlock(schema, node))
);
};
const isListFragment = (schema, fragment) => {
let firstChild = fragment.firstChild;
let lastChild = fragment.lastChild;
if (firstChild && firstChild.name === "meta") {
firstChild = firstChild.next;
}
if (lastChild && lastChild.attr("id") === "mce_marker") {
lastChild = lastChild.prev;
}
if (isEmptyFragmentElement(schema, lastChild)) {
lastChild =
lastChild === null || lastChild === void 0 ? void 0 : lastChild.prev;
}
if (!firstChild || firstChild !== lastChild) {
return false;
}
return firstChild.name === "ul" || firstChild.name === "ol";
};
const cleanupDomFragment = (domFragment) => {
var _a, _b;
const firstChild = domFragment.firstChild;
const lastChild = domFragment.lastChild;
if (firstChild && firstChild.nodeName === "META") {
(_a = firstChild.parentNode) === null || _a === void 0
? void 0
: _a.removeChild(firstChild);
}
if (lastChild && lastChild.id === "mce_marker") {
(_b = lastChild.parentNode) === null || _b === void 0
? void 0
: _b.removeChild(lastChild);
}
return domFragment;
};
const toDomFragment = (dom, serializer, fragment) => {
const html = serializer.serialize(fragment);
const domFragment = dom.createFragment(html);
return cleanupDomFragment(domFragment);
};
const listItems = (elm) => {
var _a;
return filter$5(
(_a = elm === null || elm === void 0 ? void 0 : elm.childNodes) !==
null && _a !== void 0
? _a
: [],
(child) => {
return child.nodeName === "LI";
}
);
};
const isPadding = (node) => {
return node.data === nbsp || isBr$6(node);
};
const isListItemPadded = (node) => {
return (
isNonNullable(
node === null || node === void 0 ? void 0 : node.firstChild
) &&
node.firstChild === node.lastChild &&
isPadding(node.firstChild)
);
};
const isEmptyOrPadded = (elm) => {
return !elm.firstChild || isListItemPadded(elm);
};
const trimListItems = (elms) => {
return elms.length > 0 && isEmptyOrPadded(elms[elms.length - 1])
? elms.slice(0, -1)
: elms;
};
const getParentLi = (dom, node) => {
const parentBlock = dom.getParent(node, dom.isBlock);
return parentBlock && parentBlock.nodeName === "LI" ? parentBlock : null;
};
const isParentBlockLi = (dom, node) => {
return !!getParentLi(dom, node);
};
const getSplit = (parentNode, rng) => {
const beforeRng = rng.cloneRange();
const afterRng = rng.cloneRange();
beforeRng.setStartBefore(parentNode);
afterRng.setEndAfter(parentNode);
return [beforeRng.cloneContents(), afterRng.cloneContents()];
};
const findFirstIn = (node, rootNode) => {
const caretPos = CaretPosition.before(node);
const caretWalker = CaretWalker(rootNode);
const newCaretPos = caretWalker.next(caretPos);
return newCaretPos ? newCaretPos.toRange() : null;
};
const findLastOf = (node, rootNode) => {
const caretPos = CaretPosition.after(node);
const caretWalker = CaretWalker(rootNode);
const newCaretPos = caretWalker.prev(caretPos);
return newCaretPos ? newCaretPos.toRange() : null;
};
const insertMiddle = (target, elms, rootNode, rng) => {
const parts = getSplit(target, rng);
const parentElm = target.parentNode;
if (parentElm) {
parentElm.insertBefore(parts[0], target);
Tools.each(elms, (li) => {
parentElm.insertBefore(li, target);
});
parentElm.insertBefore(parts[1], target);
parentElm.removeChild(target);
}
return findLastOf(elms[elms.length - 1], rootNode);
};
const insertBefore$2 = (target, elms, rootNode) => {
const parentElm = target.parentNode;
if (parentElm) {
Tools.each(elms, (elm) => {
parentElm.insertBefore(elm, target);
});
}
return findFirstIn(target, rootNode);
};
const insertAfter$2 = (target, elms, rootNode, dom) => {
dom.insertAfter(elms.reverse(), target);
return findLastOf(elms[0], rootNode);
};
const insertAtCaret$1 = (serializer, dom, rng, fragment) => {
const domFragment = toDomFragment(dom, serializer, fragment);
const liTarget = getParentLi(dom, rng.startContainer);
const liElms = trimListItems(listItems(domFragment.firstChild));
const BEGINNING = 1,
END = 2;
const rootNode = dom.getRoot();
const isAt = (location) => {
const caretPos = CaretPosition.fromRangeStart(rng);
const caretWalker = CaretWalker(dom.getRoot());
const newPos =
location === BEGINNING
? caretWalker.prev(caretPos)
: caretWalker.next(caretPos);
const newPosNode =
newPos === null || newPos === void 0 ? void 0 : newPos.getNode();
return newPosNode ? getParentLi(dom, newPosNode) !== liTarget : true;
};
if (!liTarget) {
return null;
} else if (isAt(BEGINNING)) {
return insertBefore$2(liTarget, liElms, rootNode);
} else if (isAt(END)) {
return insertAfter$2(liTarget, liElms, rootNode, dom);
} else {
return insertMiddle(liTarget, liElms, rootNode, rng);
}
};
const mergeableWrappedElements = ["pre"];
const shouldPasteContentOnly = (dom, fragment, parentNode, root) => {
var _a;
const firstNode = fragment.firstChild;
const lastNode = fragment.lastChild;
const last =
lastNode.attr("data-mce-type") === "bookmark" ? lastNode.prev : lastNode;
const isPastingSingleElement = firstNode === last;
const isWrappedElement = contains$2(
mergeableWrappedElements,
firstNode.name
);
if (isPastingSingleElement && isWrappedElement) {
const isContentEditable = firstNode.attr("contenteditable") !== "false";
const isPastingInTheSameBlockTag =
((_a = dom.getParent(parentNode, dom.isBlock)) === null || _a === void 0
? void 0
: _a.nodeName.toLowerCase()) === firstNode.name;
const isPastingInContentEditable = Optional.from(
getContentEditableRoot$1(root, parentNode)
).forall(isContentEditableTrue$3);
return (
isContentEditable &&
isPastingInTheSameBlockTag &&
isPastingInContentEditable
);
} else {
return false;
}
};
const isTableCell = isTableCell$3;
const isTableCellContentSelected = (dom, rng, cell) => {
if (isNonNullable(cell)) {
const endCell = dom.getParent(rng.endContainer, isTableCell);
return (
cell === endCell &&
hasAllContentsSelected(SugarElement.fromDom(cell), rng)
);
} else {
return false;
}
};
const validInsertion = (editor, value, parentNode) => {
var _a;
if (parentNode.getAttribute("data-mce-bogus") === "all") {
(_a = parentNode.parentNode) === null || _a === void 0
? void 0
: _a.insertBefore(editor.dom.createFragment(value), parentNode);
} else {
const node = parentNode.firstChild;
const node2 = parentNode.lastChild;
if (!node || (node === node2 && node.nodeName === "BR")) {
editor.dom.setHTML(parentNode, value);
} else {
editor.selection.setContent(value, { no_events: true });
}
}
};
const trimBrsFromTableCell = (dom, elm) => {
Optional.from(dom.getParent(elm, "td,th"))
.map(SugarElement.fromDom)
.each(trimBlockTrailingBr);
};
const reduceInlineTextElements = (editor, merge) => {
const textInlineElements = editor.schema.getTextInlineElements();
const dom = editor.dom;
if (merge) {
const root = editor.getBody();
const elementUtils = ElementUtils(editor);
Tools.each(dom.select("*[data-mce-fragment]"), (node) => {
const isInline = isNonNullable(
textInlineElements[node.nodeName.toLowerCase()]
);
if (isInline && hasInheritableStyles(dom, node)) {
for (
let parentNode = node.parentElement;
isNonNullable(parentNode) && parentNode !== root;
parentNode = parentNode.parentElement
) {
const styleConflict = hasStyleConflict(dom, node, parentNode);
if (styleConflict) {
break;
}
if (elementUtils.compare(parentNode, node)) {
dom.remove(node, true);
break;
}
}
}
});
}
};
const markFragmentElements = (fragment) => {
let node = fragment;
while ((node = node.walk())) {
if (node.type === 1) {
node.attr("data-mce-fragment", "1");
}
}
};
const unmarkFragmentElements = (elm) => {
Tools.each(elm.getElementsByTagName("*"), (elm) => {
elm.removeAttribute("data-mce-fragment");
});
};
const isPartOfFragment = (node) => {
return !!node.getAttribute("data-mce-fragment");
};
const canHaveChildren = (editor, node) => {
return (
isNonNullable(node) && !editor.schema.getVoidElements()[node.nodeName]
);
};
const moveSelectionToMarker = (editor, marker) => {
var _a, _b, _c;
let nextRng;
const dom = editor.dom;
const selection = editor.selection;
if (!marker) {
return;
}
selection.scrollIntoView(marker);
const parentEditableElm = getContentEditableRoot$1(
editor.getBody(),
marker
);
if (
parentEditableElm &&
dom.getContentEditable(parentEditableElm) === "false"
) {
dom.remove(marker);
selection.select(parentEditableElm);
return;
}
let rng = dom.createRng();
const node = marker.previousSibling;
if (isText$a(node)) {
rng.setStart(
node,
(_b =
(_a = node.nodeValue) === null || _a === void 0
? void 0
: _a.length) !== null && _b !== void 0
? _b
: 0
);
const node2 = marker.nextSibling;
if (isText$a(node2)) {
node.appendData(node2.data);
(_c = node2.parentNode) === null || _c === void 0
? void 0
: _c.removeChild(node2);
}
} else {
rng.setStartBefore(marker);
rng.setEndBefore(marker);
}
const findNextCaretRng = (rng) => {
let caretPos = CaretPosition.fromRangeStart(rng);
const caretWalker = CaretWalker(editor.getBody());
caretPos = caretWalker.next(caretPos);
return caretPos === null || caretPos === void 0
? void 0
: caretPos.toRange();
};
const parentBlock = dom.getParent(marker, dom.isBlock);
dom.remove(marker);
if (parentBlock && dom.isEmpty(parentBlock)) {
const isCell = isTableCell(parentBlock);
empty(SugarElement.fromDom(parentBlock));
rng.setStart(parentBlock, 0);
rng.setEnd(parentBlock, 0);
if (
!isCell &&
!isPartOfFragment(parentBlock) &&
(nextRng = findNextCaretRng(rng))
) {
rng = nextRng;
dom.remove(parentBlock);
} else {
dom.add(
parentBlock,
dom.create("br", isCell ? {} : { "data-mce-bogus": "1" })
);
}
}
selection.setRng(rng);
};
const deleteSelectedContent = (editor) => {
const dom = editor.dom;
const rng = normalize(editor.selection.getRng());
editor.selection.setRng(rng);
const startCell = dom.getParent(rng.startContainer, isTableCell);
if (isTableCellContentSelected(dom, rng, startCell)) {
deleteCellContents(editor, rng, SugarElement.fromDom(startCell));
} else if (
rng.startContainer === rng.endContainer &&
rng.endOffset - rng.startOffset === 1 &&
isText$a(rng.startContainer.childNodes[rng.startOffset])
) {
rng.deleteContents();
} else {
editor.getDoc().execCommand("Delete", false);
}
};
const findMarkerNode = (scope) => {
for (let markerNode = scope; markerNode; markerNode = markerNode.walk()) {
if (markerNode.attr("id") === "mce_marker") {
return Optional.some(markerNode);
}
}
return Optional.none();
};
const insertHtmlAtCaret = (editor, value, details) => {
var _a, _b;
const selection = editor.selection;
const dom = editor.dom;
const parser = editor.parser;
const merge = details.merge;
const serializer = HtmlSerializer({ validate: true }, editor.schema);
const bookmarkHtml =
'';
if (value.indexOf("{$caret}") === -1) {
value += "{$caret}";
}
value = value.replace(/\{\$caret\}/, bookmarkHtml);
let rng = selection.getRng();
const caretElement = rng.startContainer;
const body = editor.getBody();
if (caretElement === body && selection.isCollapsed()) {
if (
dom.isBlock(body.firstChild) &&
canHaveChildren(editor, body.firstChild) &&
dom.isEmpty(body.firstChild)
) {
rng = dom.createRng();
rng.setStart(body.firstChild, 0);
rng.setEnd(body.firstChild, 0);
selection.setRng(rng);
}
}
if (!selection.isCollapsed()) {
deleteSelectedContent(editor);
}
const parentNode = selection.getNode();
const parserArgs = {
context: parentNode.nodeName.toLowerCase(),
data: details.data,
insert: true,
};
const fragment = parser.parse(value, parserArgs);
if (
details.paste === true &&
isListFragment(editor.schema, fragment) &&
isParentBlockLi(dom, parentNode)
) {
rng = insertAtCaret$1(serializer, dom, selection.getRng(), fragment);
if (rng) {
selection.setRng(rng);
}
return value;
}
if (
details.paste === true &&
shouldPasteContentOnly(dom, fragment, parentNode, editor.getBody())
) {
(_a = fragment.firstChild) === null || _a === void 0
? void 0
: _a.unwrap();
}
markFragmentElements(fragment);
let node = fragment.lastChild;
if (node && node.attr("id") === "mce_marker") {
const marker = node;
for (node = node.prev; node; node = node.walk(true)) {
if (node.type === 3 || !dom.isBlock(node.name)) {
if (
node.parent &&
editor.schema.isValidChild(node.parent.name, "span")
) {
node.parent.insert(marker, node, node.name === "br");
}
break;
}
}
}
editor._selectionOverrides.showBlockCaretContainer(parentNode);
if (!parserArgs.invalid) {
value = serializer.serialize(fragment);
validInsertion(editor, value, parentNode);
} else {
editor.selection.setContent(bookmarkHtml);
let parentNode = selection.getNode();
let tempNode;
const rootNode = editor.getBody();
if (isDocument$1(parentNode)) {
parentNode = tempNode = rootNode;
} else {
tempNode = parentNode;
}
while (tempNode && tempNode !== rootNode) {
parentNode = tempNode;
tempNode = tempNode.parentNode;
}
value =
parentNode === rootNode
? rootNode.innerHTML
: dom.getOuterHTML(parentNode);
const root = parser.parse(value);
const markerNode = findMarkerNode(root);
const editingHost = markerNode.bind(findClosestEditingHost).getOr(root);
markerNode.each((marker) => marker.replace(fragment));
const toExtract = fragment.children();
const parent =
(_b = fragment.parent) !== null && _b !== void 0 ? _b : root;
fragment.unwrap();
const invalidChildren = filter$5(toExtract, (node) =>
isInvalid(editor.schema, node, parent)
);
cleanInvalidNodes(invalidChildren, editor.schema, editingHost);
filter$2(parser.getNodeFilters(), parser.getAttributeFilters(), root);
value = serializer.serialize(root);
if (parentNode === rootNode) {
dom.setHTML(rootNode, value);
} else {
dom.setOuterHTML(parentNode, value);
}
}
reduceInlineTextElements(editor, merge);
moveSelectionToMarker(editor, dom.get("mce_marker"));
unmarkFragmentElements(editor.getBody());
trimBrsFromTableCell(dom, selection.getStart());
updateCaret(editor.schema, editor.getBody(), selection.getStart());
return value;
};
const isTreeNode = (content) => content instanceof AstNode;
const moveSelection = (editor) => {
if (hasFocus(editor)) {
firstPositionIn(editor.getBody()).each((pos) => {
const node = pos.getNode();
const caretPos = isTable$2(node)
? firstPositionIn(node).getOr(pos)
: pos;
editor.selection.setRng(caretPos.toRange());
});
}
};
const setEditorHtml = (editor, html, noSelection) => {
editor.dom.setHTML(editor.getBody(), html);
if (noSelection !== true) {
moveSelection(editor);
}
};
const setContentString = (editor, body, content, args) => {
if (content.length === 0 || /^\s+$/.test(content)) {
const padd = '
';
if (body.nodeName === "TABLE") {
content = "