1window.TinyMCERails = { 2 configuration: { 3 default: {} 4 }, 5 6 initialize: function(config, options) { 7 if (typeof tinyMCE != 'undefined') { 8 // Merge the custom options with the given configuration 9 var configuration = TinyMCERails.configuration[config || 'default']; 10 configuration = TinyMCERails._merge(configuration, options); 11 12 tinymce.init(configuration); 13 } else { 14 // Wait until TinyMCE is loaded 15 setTimeout(function() { 16 TinyMCERails.initialize(config, options); 17 }, 50); 18 } 19 }, 20 21 setupTurbolinks: function() { 22 // Remove all TinyMCE instances before rendering 23 document.addEventListener('turbolinks:before-render', function() { 24 tinymce.remove(); 25 }); 26 }, 27 28 _merge: function() { 29 var result = {}; 30 31 for (var i = 0; i < arguments.length; ++i) { 32 var source = arguments[i]; 33 34 for (var key in source) { 35 if (Object.prototype.hasOwnProperty.call(source, key)) { 36 if (Object.prototype.toString.call(source[key]) === '[object Object]') { 37 result[key] = TinyMCERails._merge(result[key], source[key]); 38 } else { 39 result[key] = source[key]; 40 } 41 } 42 } 43 } 44 45 return result; 46 } 47}; 48 49if (typeof Turbolinks != 'undefined' && Turbolinks.supported) { 50 TinyMCERails.setupTurbolinks(); 51}; 52window.tinymce = window.tinymce || { 53 base: 'https://static.shopmaker.com/assets/tinymce', 54 suffix: '' 55}; 56/** 57 * TinyMCE version 6.4.2 (2023-04-26) 58 */ 59 60(function () { 61 'use strict'; 62 63 var typeOf$1 = function (x) { 64 if (x === null) { 65 return 'null'; 66 } 67 if (x === undefined) { 68 return 'undefined'; 69 } 70 var t = typeof x; 71 if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { 72 return 'array'; 73 } 74 if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { 75 return 'string'; 76 } 77 return t; 78 }; 79 var isEquatableType = function (x) { 80 return [ 81 'undefined', 82 'boolean', 83 'number', 84 'string', 85 'function', 86 'xml', 87 'null' 88 ].indexOf(x) !== -1; 89 }; 90 91 var sort$1 = function (xs, compareFn) { 92 var clone = Array.prototype.slice.call(xs); 93 return clone.sort(compareFn); 94 }; 95 96 var contramap = function (eqa, f) { 97 return eq$2(function (x, y) { 98 return eqa.eq(f(x), f(y)); 99 }); 100 }; 101 var eq$2 = function (f) { 102 return { eq: f }; 103 }; 104 var tripleEq = eq$2(function (x, y) { 105 return x === y; 106 }); 107 var eqString = tripleEq; 108 var eqArray = function (eqa) { 109 return eq$2(function (x, y) { 110 if (x.length !== y.length) { 111 return false; 112 } 113 var len = x.length; 114 for (var i = 0; i < len; i++) { 115 if (!eqa.eq(x[i], y[i])) { 116 return false; 117 } 118 } 119 return true; 120 }); 121 }; 122 var eqSortedArray = function (eqa, compareFn) { 123 return contramap(eqArray(eqa), function (xs) { 124 return sort$1(xs, compareFn); 125 }); 126 }; 127 var eqRecord = function (eqa) { 128 return eq$2(function (x, y) { 129 var kx = Object.keys(x); 130 var ky = Object.keys(y); 131 if (!eqSortedArray(eqString).eq(kx, ky)) { 132 return false; 133 } 134 var len = kx.length; 135 for (var i = 0; i < len; i++) { 136 var q = kx[i]; 137 if (!eqa.eq(x[q], y[q])) { 138 return false; 139 } 140 } 141 return true; 142 }); 143 }; 144 var eqAny = eq$2(function (x, y) { 145 if (x === y) { 146 return true; 147 } 148 var tx = typeOf$1(x); 149 var ty = typeOf$1(y); 150 if (tx !== ty) { 151 return false; 152 } 153 if (isEquatableType(tx)) { 154 return x === y; 155 } else if (tx === 'array') { 156 return eqArray(eqAny).eq(x, y); 157 } else if (tx === 'object') { 158 return eqRecord(eqAny).eq(x, y); 159 } 160 return false; 161 }); 162 163 const getPrototypeOf$2 = Object.getPrototypeOf; 164 const hasProto = (v, constructor, predicate) => { 165 var _a; 166 if (predicate(v, constructor.prototype)) { 167 return true; 168 } else { 169 return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name; 170 } 171 }; 172 const typeOf = x => { 173 const t = typeof x; 174 if (x === null) { 175 return 'null';
vendor: 24,812 bytes, lines 176-1049
176 } else if (t === 'object' && Array.isArray(x)) { 177 return 'array'; 178 } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) { 179 return 'string'; 180 } else { 181 return t; 182 } 183 }; 184 const isType$1 = type => value => typeOf(value) === type; 185 const isSimpleType = type => value => typeof value === type; 186 const eq$1 = t => a => t === a; 187 const is$4 = (value, constructor) => isObject(value) && hasProto(value, constructor, (o, proto) => getPrototypeOf$2(o) === proto); 188 const isString = isType$1('string'); 189 const isObject = isType$1('object'); 190 const isPlainObject = value => is$4(value, Object); 191 const isArray$1 = isType$1('array'); 192 const isNull = eq$1(null); 193 const isBoolean = isSimpleType('boolean'); 194 const isUndefined = eq$1(undefined); 195 const isNullable = a => a === null || a === undefined; 196 const isNonNullable = a => !isNullable(a); 197 const isFunction = isSimpleType('function'); 198 const isNumber = isSimpleType('number'); 199 const isArrayOf = (value, pred) => { 200 if (isArray$1(value)) { 201 for (let i = 0, len = value.length; i < len; ++i) { 202 if (!pred(value[i])) { 203 return false; 204 } 205 } 206 return true; 207 } 208 return false; 209 }; 210 211 const noop = () => { 212 }; 213 const compose = (fa, fb) => { 214 return (...args) => { 215 return fa(fb.apply(null, args)); 216 }; 217 }; 218 const compose1 = (fbc, fab) => a => fbc(fab(a)); 219 const constant = value => { 220 return () => { 221 return value; 222 }; 223 }; 224 const identity = x => { 225 return x; 226 }; 227 const tripleEquals = (a, b) => { 228 return a === b; 229 }; 230 function curry(fn, ...initialArgs) { 231 return (...restArgs) => { 232 const all = initialArgs.concat(restArgs); 233 return fn.apply(null, all); 234 }; 235 } 236 const not = f => t => !f(t); 237 const die = msg => { 238 return () => { 239 throw new Error(msg); 240 }; 241 }; 242 const apply$1 = f => { 243 return f(); 244 }; 245 const call = f => { 246 f(); 247 }; 248 const never = constant(false); 249 const always = constant(true); 250 251 class Optional { 252 constructor(tag, value) { 253 this.tag = tag; 254 this.value = value; 255 } 256 static some(value) { 257 return new Optional(true, value); 258 } 259 static none() { 260 return Optional.singletonNone; 261 } 262 fold(onNone, onSome) { 263 if (this.tag) { 264 return onSome(this.value); 265 } else { 266 return onNone(); 267 } 268 } 269 isSome() { 270 return this.tag; 271 } 272 isNone() { 273 return !this.tag; 274 } 275 map(mapper) { 276 if (this.tag) { 277 return Optional.some(mapper(this.value)); 278 } else { 279 return Optional.none(); 280 } 281 } 282 bind(binder) { 283 if (this.tag) { 284 return binder(this.value); 285 } else { 286 return Optional.none(); 287 } 288 } 289 exists(predicate) { 290 return this.tag && predicate(this.value); 291 } 292 forall(predicate) { 293 return !this.tag || predicate(this.value); 294 } 295 filter(predicate) { 296 if (!this.tag || predicate(this.value)) { 297 return this; 298 } else { 299 return Optional.none(); 300 } 301 } 302 getOr(replacement) { 303 return this.tag ? this.value : replacement; 304 } 305 or(replacement) { 306 return this.tag ? this : replacement; 307 } 308 getOrThunk(thunk) { 309 return this.tag ? this.value : thunk(); 310 } 311 orThunk(thunk) { 312 return this.tag ? this : thunk(); 313 } 314 getOrDie(message) { 315 if (!this.tag) { 316 throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None'); 317 } else { 318 return this.value; 319 } 320 } 321 static from(value) { 322 return isNonNullable(value) ? Optional.some(value) : Optional.none(); 323 } 324 getOrNull() { 325 return this.tag ? this.value : null; 326 } 327 getOrUndefined() { 328 return this.value; 329 } 330 each(worker) { 331 if (this.tag) { 332 worker(this.value); 333 } 334 } 335 toArray() { 336 return this.tag ? [this.value] : []; 337 } 338 toString() { 339 return this.tag ? `some(${ this.value })` : 'none()'; 340 } 341 } 342 Optional.singletonNone = new Optional(false); 343 344 const nativeSlice = Array.prototype.slice; 345 const nativeIndexOf = Array.prototype.indexOf; 346 const nativePush = Array.prototype.push; 347 const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t); 348 const indexOf$1 = (xs, x) => { 349 const r = rawIndexOf(xs, x); 350 return r === -1 ? Optional.none() : Optional.some(r); 351 }; 352 const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1; 353 const exists = (xs, pred) => { 354 for (let i = 0, len = xs.length; i < len; i++) { 355 const x = xs[i]; 356 if (pred(x, i)) { 357 return true; 358 } 359 } 360 return false; 361 }; 362 const map$3 = (xs, f) => { 363 const len = xs.length; 364 const r = new Array(len); 365 for (let i = 0; i < len; i++) { 366 const x = xs[i]; 367 r[i] = f(x, i); 368 } 369 return r; 370 }; 371 const each$e = (xs, f) => { 372 for (let i = 0, len = xs.length; i < len; i++) { 373 const x = xs[i]; 374 f(x, i); 375 } 376 }; 377 const eachr = (xs, f) => { 378 for (let i = xs.length - 1; i >= 0; i--) { 379 const x = xs[i]; 380 f(x, i); 381 } 382 }; 383 const partition$2 = (xs, pred) => { 384 const pass = []; 385 const fail = []; 386 for (let i = 0, len = xs.length; i < len; i++) { 387 const x = xs[i]; 388 const arr = pred(x, i) ? pass : fail; 389 arr.push(x); 390 } 391 return { 392 pass, 393 fail 394 }; 395 }; 396 const filter$5 = (xs, pred) => { 397 const r = []; 398 for (let i = 0, len = xs.length; i < len; i++) { 399 const x = xs[i]; 400 if (pred(x, i)) { 401 r.push(x); 402 } 403 } 404 return r; 405 }; 406 const foldr = (xs, f, acc) => { 407 eachr(xs, (x, i) => { 408 acc = f(acc, x, i); 409 }); 410 return acc; 411 }; 412 const foldl = (xs, f, acc) => { 413 each$e(xs, (x, i) => { 414 acc = f(acc, x, i); 415 }); 416 return acc; 417 }; 418 const findUntil$1 = (xs, pred, until) => { 419 for (let i = 0, len = xs.length; i < len; i++) { 420 const x = xs[i]; 421 if (pred(x, i)) { 422 return Optional.some(x); 423 } else if (until(x, i)) { 424 break; 425 } 426 } 427 return Optional.none(); 428 }; 429 const find$2 = (xs, pred) => { 430 return findUntil$1(xs, pred, never); 431 }; 432 const findIndex$2 = (xs, pred) => { 433 for (let i = 0, len = xs.length; i < len; i++) { 434 const x = xs[i]; 435 if (pred(x, i)) { 436 return Optional.some(i); 437 } 438 } 439 return Optional.none(); 440 }; 441 const flatten = xs => { 442 const r = []; 443 for (let i = 0, len = xs.length; i < len; ++i) { 444 if (!isArray$1(xs[i])) { 445 throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs); 446 } 447 nativePush.apply(r, xs[i]); 448 } 449 return r; 450 }; 451 const bind$3 = (xs, f) => flatten(map$3(xs, f)); 452 const forall = (xs, pred) => { 453 for (let i = 0, len = xs.length; i < len; ++i) { 454 const x = xs[i]; 455 if (pred(x, i) !== true) { 456 return false; 457 } 458 } 459 return true; 460 }; 461 const reverse = xs => { 462 const r = nativeSlice.call(xs, 0); 463 r.reverse(); 464 return r; 465 }; 466 const difference = (a1, a2) => filter$5(a1, x => !contains$2(a2, x)); 467 const mapToObject = (xs, f) => { 468 const r = {}; 469 for (let i = 0, len = xs.length; i < len; i++) { 470 const x = xs[i]; 471 r[String(x)] = f(x, i); 472 } 473 return r; 474 }; 475 const sort = (xs, comparator) => { 476 const copy = nativeSlice.call(xs, 0); 477 copy.sort(comparator); 478 return copy; 479 }; 480 const get$b = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none(); 481 const head = xs => get$b(xs, 0); 482 const last$3 = xs => get$b(xs, xs.length - 1); 483 const from = isFunction(Array.from) ? Array.from : x => nativeSlice.call(x); 484 const findMap = (arr, f) => { 485 for (let i = 0; i < arr.length; i++) { 486 const r = f(arr[i], i); 487 if (r.isSome()) { 488 return r; 489 } 490 } 491 return Optional.none(); 492 }; 493 const unique$1 = (xs, comparator) => { 494 const r = []; 495 const isDuplicated = isFunction(comparator) ? x => exists(r, i => comparator(i, x)) : x => contains$2(r, x); 496 for (let i = 0, len = xs.length; i < len; i++) { 497 const x = xs[i]; 498 if (!isDuplicated(x)) { 499 r.push(x); 500 } 501 } 502 return r; 503 }; 504 505 const keys = Object.keys; 506 const hasOwnProperty$2 = Object.hasOwnProperty; 507 const each$d = (obj, f) => { 508 const props = keys(obj); 509 for (let k = 0, len = props.length; k < len; k++) { 510 const i = props[k]; 511 const x = obj[i]; 512 f(x, i); 513 } 514 }; 515 const map$2 = (obj, f) => { 516 return tupleMap(obj, (x, i) => ({ 517 k: i, 518 v: f(x, i) 519 })); 520 }; 521 const tupleMap = (obj, f) => { 522 const r = {}; 523 each$d(obj, (x, i) => { 524 const tuple = f(x, i); 525 r[tuple.k] = tuple.v; 526 }); 527 return r; 528 }; 529 const objAcc = r => (x, i) => { 530 r[i] = x; 531 }; 532 const internalFilter = (obj, pred, onTrue, onFalse) => { 533 each$d(obj, (x, i) => { 534 (pred(x, i) ? onTrue : onFalse)(x, i); 535 }); 536 }; 537 const bifilter = (obj, pred) => { 538 const t = {}; 539 const f = {}; 540 internalFilter(obj, pred, objAcc(t), objAcc(f)); 541 return { 542 t, 543 f 544 }; 545 }; 546 const filter$4 = (obj, pred) => { 547 const t = {}; 548 internalFilter(obj, pred, objAcc(t), noop); 549 return t; 550 }; 551 const mapToArray = (obj, f) => { 552 const r = []; 553 each$d(obj, (value, name) => { 554 r.push(f(value, name)); 555 }); 556 return r; 557 }; 558 const values = obj => { 559 return mapToArray(obj, identity); 560 }; 561 const get$a = (obj, key) => { 562 return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none(); 563 }; 564 const has$2 = (obj, key) => hasOwnProperty$2.call(obj, key); 565 const hasNonNullableKey = (obj, key) => has$2(obj, key) && obj[key] !== undefined && obj[key] !== null; 566 const equal$1 = (a1, a2, eq = eqAny) => eqRecord(eq).eq(a1, a2); 567 568 const stringArray = a => { 569 const all = {}; 570 each$e(a, key => { 571 all[key] = {}; 572 }); 573 return keys(all); 574 }; 575 576 const isArrayLike = o => o.length !== undefined; 577 const isArray = Array.isArray; 578 const toArray$1 = obj => { 579 if (!isArray(obj)) { 580 const array = []; 581 for (let i = 0, l = obj.length; i < l; i++) { 582 array[i] = obj[i]; 583 } 584 return array; 585 } else { 586 return obj; 587 } 588 }; 589 const each$c = (o, cb, s) => { 590 if (!o) { 591 return false; 592 } 593 s = s || o; 594 if (isArrayLike(o)) { 595 for (let n = 0, l = o.length; n < l; n++) { 596 if (cb.call(s, o[n], n, o) === false) { 597 return false; 598 } 599 } 600 } else { 601 for (const n in o) { 602 if (has$2(o, n)) { 603 if (cb.call(s, o[n], n, o) === false) { 604 return false; 605 } 606 } 607 } 608 } 609 return true; 610 }; 611 const map$1 = (array, callback) => { 612 const out = []; 613 each$c(array, (item, index) => { 614 out.push(callback(item, index, array)); 615 }); 616 return out; 617 }; 618 const filter$3 = (a, f) => { 619 const o = []; 620 each$c(a, (v, index) => { 621 if (!f || f(v, index, a)) { 622 o.push(v); 623 } 624 }); 625 return o; 626 }; 627 const indexOf = (a, v) => { 628 if (a) { 629 for (let i = 0, l = a.length; i < l; i++) { 630 if (a[i] === v) { 631 return i; 632 } 633 } 634 } 635 return -1; 636 }; 637 const reduce = (collection, iteratee, accumulator, thisArg) => { 638 let acc = isUndefined(accumulator) ? collection[0] : accumulator; 639 for (let i = 0; i < collection.length; i++) { 640 acc = iteratee.call(thisArg, acc, collection[i], i); 641 } 642 return acc; 643 }; 644 const findIndex$1 = (array, predicate, thisArg) => { 645 for (let i = 0, l = array.length; i < l; i++) { 646 if (predicate.call(thisArg, array[i], i, array)) { 647 return i; 648 } 649 } 650 return -1; 651 }; 652 const last$2 = collection => collection[collection.length - 1]; 653 654 const cached = f => { 655 let called = false; 656 let r; 657 return (...args) => { 658 if (!called) { 659 called = true; 660 r = f.apply(null, args); 661 } 662 return r; 663 }; 664 }; 665 666 const DeviceType = (os, browser, userAgent, mediaMatch) => { 667 const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true; 668 const isiPhone = os.isiOS() && !isiPad; 669 const isMobile = os.isiOS() || os.isAndroid(); 670 const isTouch = isMobile || mediaMatch('(pointer:coarse)'); 671 const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)'); 672 const isPhone = isiPhone || isMobile && !isTablet; 673 const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false; 674 const isDesktop = !isPhone && !isTablet && !iOSwebview; 675 return { 676 isiPad: constant(isiPad), 677 isiPhone: constant(isiPhone), 678 isTablet: constant(isTablet), 679 isPhone: constant(isPhone), 680 isTouch: constant(isTouch), 681 isAndroid: os.isAndroid, 682 isiOS: os.isiOS, 683 isWebView: constant(iOSwebview), 684 isDesktop: constant(isDesktop) 685 }; 686 }; 687 688 const firstMatch = (regexes, s) => { 689 for (let i = 0; i < regexes.length; i++) { 690 const x = regexes[i]; 691 if (x.test(s)) { 692 return x; 693 } 694 } 695 return undefined; 696 }; 697 const find$1 = (regexes, agent) => { 698 const r = firstMatch(regexes, agent); 699 if (!r) { 700 return { 701 major: 0, 702 minor: 0 703 }; 704 } 705 const group = i => { 706 return Number(agent.replace(r, '$' + i)); 707 }; 708 return nu$3(group(1), group(2)); 709 }; 710 const detect$5 = (versionRegexes, agent) => { 711 const cleanedAgent = String(agent).toLowerCase(); 712 if (versionRegexes.length === 0) { 713 return unknown$2(); 714 } 715 return find$1(versionRegexes, cleanedAgent); 716 }; 717 const unknown$2 = () => { 718 return nu$3(0, 0); 719 }; 720 const nu$3 = (major, minor) => { 721 return { 722 major, 723 minor 724 }; 725 }; 726 const Version = { 727 nu: nu$3, 728 detect: detect$5, 729 unknown: unknown$2 730 }; 731 732 const detectBrowser$1 = (browsers, userAgentData) => { 733 return findMap(userAgentData.brands, uaBrand => { 734 const lcBrand = uaBrand.brand.toLowerCase(); 735 return find$2(browsers, browser => { 736 var _a; 737 return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase()); 738 }).map(info => ({ 739 current: info.name, 740 version: Version.nu(parseInt(uaBrand.version, 10), 0) 741 })); 742 }); 743 }; 744 745 const detect$4 = (candidates, userAgent) => { 746 const agent = String(userAgent).toLowerCase(); 747 return find$2(candidates, candidate => { 748 return candidate.search(agent); 749 }); 750 }; 751 const detectBrowser = (browsers, userAgent) => { 752 return detect$4(browsers, userAgent).map(browser => { 753 const version = Version.detect(browser.versionRegexes, userAgent); 754 return { 755 current: browser.name, 756 version 757 }; 758 }); 759 }; 760 const detectOs = (oses, userAgent) => { 761 return detect$4(oses, userAgent).map(os => { 762 const version = Version.detect(os.versionRegexes, userAgent); 763 return { 764 current: os.name, 765 version 766 }; 767 }); 768 }; 769 770 const removeFromStart = (str, numChars) => { 771 return str.substring(numChars); 772 }; 773 774 const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr; 775 const removeLeading = (str, prefix) => { 776 return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str; 777 }; 778 const contains$1 = (str, substr, start = 0, end) => { 779 const idx = str.indexOf(substr, start); 780 if (idx !== -1) { 781 return isUndefined(end) ? true : idx + substr.length <= end; 782 } else { 783 return false; 784 } 785 }; 786 const startsWith = (str, prefix) => { 787 return checkRange(str, prefix, 0); 788 }; 789 const endsWith = (str, suffix) => { 790 return checkRange(str, suffix, str.length - suffix.length); 791 }; 792 const blank = r => s => s.replace(r, ''); 793 const trim$3 = blank(/^\s+|\s+$/g); 794 const lTrim = blank(/^\s+/g); 795 const rTrim = blank(/\s+$/g); 796 const isNotEmpty = s => s.length > 0; 797 const isEmpty$3 = s => !isNotEmpty(s); 798 const repeat = (s, count) => count <= 0 ? '' : new Array(count + 1).join(s); 799 const toInt = (value, radix = 10) => { 800 const num = parseInt(value, radix); 801 return isNaN(num) ? Optional.none() : Optional.some(num); 802 }; 803 804 const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/; 805 const checkContains = target => { 806 return uastring => { 807 return contains$1(uastring, target); 808 }; 809 }; 810 const browsers = [ 811 { 812 name: 'Edge', 813 versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/], 814 search: uastring => { 815 return contains$1(uastring, 'edge/') && contains$1(uastring, 'chrome') && contains$1(uastring, 'safari') && contains$1(uastring, 'applewebkit'); 816 } 817 }, 818 { 819 name: 'Chromium', 820 brand: 'Chromium', 821 versionRegexes: [ 822 /.*?chrome\/([0-9]+)\.([0-9]+).*/, 823 normalVersionRegex 824 ], 825 search: uastring => { 826 return contains$1(uastring, 'chrome') && !contains$1(uastring, 'chromeframe'); 827 } 828 }, 829 { 830 name: 'IE', 831 versionRegexes: [ 832 /.*?msie\ ?([0-9]+)\.([0-9]+).*/, 833 /.*?rv:([0-9]+)\.([0-9]+).*/ 834 ], 835 search: uastring => { 836 return contains$1(uastring, 'msie') || contains$1(uastring, 'trident'); 837 } 838 }, 839 { 840 name: 'Opera', 841 versionRegexes: [ 842 normalVersionRegex, 843 /.*?opera\/([0-9]+)\.([0-9]+).*/ 844 ], 845 search: checkContains('opera') 846 }, 847 { 848 name: 'Firefox', 849 versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/], 850 search: checkContains('firefox') 851 }, 852 { 853 name: 'Safari', 854 versionRegexes: [ 855 normalVersionRegex, 856 /.*?cpu os ([0-9]+)_([0-9]+).*/ 857 ], 858 search: uastring => { 859 return (contains$1(uastring, 'safari') || contains$1(uastring, 'mobile/')) && contains$1(uastring, 'applewebkit'); 860 } 861 } 862 ]; 863 const oses = [ 864 { 865 name: 'Windows', 866 search: checkContains('win'), 867 versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/] 868 }, 869 { 870 name: 'iOS', 871 search: uastring => { 872 return contains$1(uastring, 'iphone') || contains$1(uastring, 'ipad'); 873 }, 874 versionRegexes: [ 875 /.*?version\/\ ?([0-9]+)\.([0-9]+).*/, 876 /.*cpu os ([0-9]+)_([0-9]+).*/, 877 /.*cpu iphone os ([0-9]+)_([0-9]+).*/ 878 ] 879 }, 880 { 881 name: 'Android', 882 search: checkContains('android'), 883 versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/] 884 }, 885 { 886 name: 'macOS', 887 search: checkContains('mac os x'), 888 versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/] 889 }, 890 { 891 name: 'Linux', 892 search: checkContains('linux'), 893 versionRegexes: [] 894 }, 895 { 896 name: 'Solaris', 897 search: checkContains('sunos'), 898 versionRegexes: [] 899 }, 900 { 901 name: 'FreeBSD', 902 search: checkContains('freebsd'), 903 versionRegexes: [] 904 }, 905 { 906 name: 'ChromeOS', 907 search: checkContains('cros'), 908 versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/] 909 } 910 ]; 911 const PlatformInfo = { 912 browsers: constant(browsers), 913 oses: constant(oses) 914 }; 915 916 const edge = 'Edge'; 917 const chromium = 'Chromium'; 918 const ie = 'IE'; 919 const opera = 'Opera'; 920 const firefox = 'Firefox'; 921 const safari = 'Safari'; 922 const unknown$1 = () => { 923 return nu$2({ 924 current: undefined, 925 version: Version.unknown() 926 }); 927 }; 928 const nu$2 = info => { 929 const current = info.current; 930 const version = info.version; 931 const isBrowser = name => () => current === name; 932 return { 933 current, 934 version, 935 isEdge: isBrowser(edge), 936 isChromium: isBrowser(chromium), 937 isIE: isBrowser(ie), 938 isOpera: isBrowser(opera), 939 isFirefox: isBrowser(firefox), 940 isSafari: isBrowser(safari) 941 }; 942 }; 943 const Browser = { 944 unknown: unknown$1, 945 nu: nu$2, 946 edge: constant(edge), 947 chromium: constant(chromium), 948 ie: constant(ie), 949 opera: constant(opera), 950 firefox: constant(firefox), 951 safari: constant(safari) 952 }; 953 954 const windows = 'Windows'; 955 const ios = 'iOS'; 956 const android = 'Android'; 957 const linux = 'Linux'; 958 const macos = 'macOS'; 959 const solaris = 'Solaris'; 960 const freebsd = 'FreeBSD'; 961 const chromeos = 'ChromeOS'; 962 const unknown = () => { 963 return nu$1({ 964 current: undefined, 965 version: Version.unknown() 966 }); 967 }; 968 const nu$1 = info => { 969 const current = info.current; 970 const version = info.version; 971 const isOS = name => () => current === name; 972 return { 973 current, 974 version, 975 isWindows: isOS(windows), 976 isiOS: isOS(ios), 977 isAndroid: isOS(android), 978 isMacOS: isOS(macos), 979 isLinux: isOS(linux), 980 isSolaris: isOS(solaris), 981 isFreeBSD: isOS(freebsd), 982 isChromeOS: isOS(chromeos) 983 }; 984 }; 985 const OperatingSystem = { 986 unknown, 987 nu: nu$1, 988 windows: constant(windows), 989 ios: constant(ios), 990 android: constant(android), 991 linux: constant(linux), 992 macos: constant(macos), 993 solaris: constant(solaris), 994 freebsd: constant(freebsd), 995 chromeos: constant(chromeos) 996 }; 997 998 const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => { 999 const browsers = PlatformInfo.browsers(); 1000 const oses = PlatformInfo.oses(); 1001 const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu); 1002 const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu); 1003 const deviceType = DeviceType(os, browser, userAgent, mediaMatch); 1004 return { 1005 browser, 1006 os, 1007 deviceType 1008 }; 1009 }; 1010 const PlatformDetection = { detect: detect$3 }; 1011 1012 const mediaMatch = query => window.matchMedia(query).matches; 1013 let platform$2 = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch)); 1014 const detect$2 = () => platform$2(); 1015 1016 const userAgent = navigator.userAgent; 1017 const platform$1 = detect$2(); 1018 const browser$1 = platform$1.browser; 1019 const os = platform$1.os; 1020 const deviceType = platform$1.deviceType; 1021 const windowsPhone = userAgent.indexOf('Windows Phone') !== -1; 1022 const Env = { 1023 transparentSrc: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 1024 documentMode: browser$1.isIE() ? document.documentMode || 7 : 10, 1025 cacheSuffix: null, 1026 container: null, 1027 canHaveCSP: !browser$1.isIE(), 1028 windowsPhone, 1029 browser: { 1030 current: browser$1.current, 1031 version: browser$1.version, 1032 isChromium: browser$1.isChromium, 1033 isEdge: browser$1.isEdge, 1034 isFirefox: browser$1.isFirefox, 1035 isIE: browser$1.isIE, 1036 isOpera: browser$1.isOpera, 1037 isSafari: browser$1.isSafari 1038 }, 1039 os: { 1040 current: os.current, 1041 version: os.version, 1042 isAndroid: os.isAndroid, 1043 isChromeOS: os.isChromeOS, 1044 isFreeBSD: os.isFreeBSD, 1045 isiOS: os.isiOS, 1046 isLinux: os.isLinux, 1047 isMacOS: os.isMacOS, 1048 isSolaris: os.isSolaris, 1049 isWindows: os
vendor: 6,264 bytes, lines 1049-1253
1049.isWindows 1050 }, 1051 deviceType: { 1052 isDesktop: deviceType.isDesktop, 1053 isiPad: deviceType.isiPad, 1054 isiPhone: deviceType.isiPhone, 1055 isPhone: deviceType.isPhone, 1056 isTablet: deviceType.isTablet, 1057 isTouch: deviceType.isTouch, 1058 isWebView: deviceType.isWebView 1059 } 1060 }; 1061 1062 const whiteSpaceRegExp$1 = /^\s*|\s*$/g; 1063 const trim$2 = str => { 1064 return isNullable(str) ? '' : ('' + str).replace(whiteSpaceRegExp$1, ''); 1065 }; 1066 const is$3 = (obj, type) => { 1067 if (!type) { 1068 return obj !== undefined; 1069 } 1070 if (type === 'array' && isArray(obj)) { 1071 return true; 1072 } 1073 return typeof obj === type; 1074 }; 1075 const makeMap$4 = (items, delim, map = {}) => { 1076 const resolvedItems = isString(items) ? items.split(delim || ',') : items || []; 1077 let i = resolvedItems.length; 1078 while (i--) { 1079 map[resolvedItems[i]] = {}; 1080 } 1081 return map; 1082 }; 1083 const hasOwnProperty$1 = has$2; 1084 const extend$3 = (obj, ...exts) => { 1085 for (let i = 0; i < exts.length; i++) { 1086 const ext = exts[i]; 1087 for (const name in ext) { 1088 if (has$2(ext, name)) { 1089 const value = ext[name]; 1090 if (value !== undefined) { 1091 obj[name] = value; 1092 } 1093 } 1094 } 1095 } 1096 return obj; 1097 }; 1098 const walk$4 = function (o, f, n, s) { 1099 s = s || this; 1100 if (o) { 1101 if (n) { 1102 o = o[n]; 1103 } 1104 each$c(o, (o, i) => { 1105 if (f.call(s, o, i, n) === false) { 1106 return false; 1107 } else { 1108 walk$4(o, f, n, s); 1109 return true; 1110 } 1111 }); 1112 } 1113 }; 1114 const resolve$3 = (n, o = window) => { 1115 const path = n.split('.'); 1116 for (let i = 0, l = path.length; i < l; i++) { 1117 o = o[path[i]]; 1118 if (!o) { 1119 break; 1120 } 1121 } 1122 return o; 1123 }; 1124 const explode$3 = (s, d) => { 1125 if (isArray$1(s)) { 1126 return s; 1127 } else if (s === '') { 1128 return []; 1129 } else { 1130 return map$1(s.split(d || ','), trim$2); 1131 } 1132 }; 1133 const _addCacheSuffix = url => { 1134 const cacheSuffix = Env.cacheSuffix; 1135 if (cacheSuffix) { 1136 url += (url.indexOf('?') === -1 ? '?' : '&') + cacheSuffix; 1137 } 1138 return url; 1139 }; 1140 const Tools = { 1141 trim: trim$2, 1142 isArray: isArray, 1143 is: is$3, 1144 toArray: toArray$1, 1145 makeMap: makeMap$4, 1146 each: each$c, 1147 map: map$1, 1148 grep: filter$3, 1149 inArray: indexOf, 1150 hasOwn: hasOwnProperty$1, 1151 extend: extend$3, 1152 walk: walk$4, 1153 resolve: resolve$3, 1154 explode: explode$3, 1155 _addCacheSuffix 1156 }; 1157 1158 const is$2 = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs)); 1159 const cat = arr => { 1160 const r = []; 1161 const push = x => { 1162 r.push(x); 1163 }; 1164 for (let i = 0; i < arr.length; i++) { 1165 arr[i].each(push); 1166 } 1167 return r; 1168 }; 1169 const lift2 = (oa, ob, f) => oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none(); 1170 const lift3 = (oa, ob, oc, f) => oa.isSome() && ob.isSome() && oc.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie())) : Optional.none(); 1171 const someIf = (b, a) => b ? Optional.some(a) : Optional.none(); 1172 1173 const Global = typeof window !== 'undefined' ? window : Function('return this;')(); 1174 1175 const path = (parts, scope) => { 1176 let o = scope !== undefined && scope !== null ? scope : Global; 1177 for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) { 1178 o = o[parts[i]]; 1179 } 1180 return o; 1181 }; 1182 const resolve$2 = (p, scope) => { 1183 const parts = p.split('.'); 1184 return path(parts, scope); 1185 }; 1186 1187 const unsafe = (name, scope) => { 1188 return resolve$2(name, scope); 1189 }; 1190 const getOrDie = (name, scope) => { 1191 const actual = unsafe(name, scope); 1192 if (actual === undefined || actual === null) { 1193 throw new Error(name + ' not available on this browser'); 1194 } 1195 return actual; 1196 }; 1197 1198 const getPrototypeOf$1 = Object.getPrototypeOf; 1199 const sandHTMLElement = scope => { 1200 return getOrDie('HTMLElement', scope); 1201 }; 1202 const isPrototypeOf = x => { 1203 const scope = resolve$2('ownerDocument.defaultView', x); 1204 return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf$1(x).constructor.name)); 1205 }; 1206 1207 const COMMENT = 8; 1208 const DOCUMENT = 9; 1209 const DOCUMENT_FRAGMENT = 11; 1210 const ELEMENT = 1; 1211 const TEXT = 3; 1212 1213 const name = element => { 1214 const r = element.dom.nodeName; 1215 return r.toLowerCase(); 1216 }; 1217 const type$1 = element => element.dom.nodeType; 1218 const isType = t => element => type$1(element) === t; 1219 const isComment$1 = element => type$1(element) === COMMENT || name(element) === '#comment'; 1220 const isHTMLElement = element => isElement$7(element) && isPrototypeOf(element.dom); 1221 const isElement$7 = isType(ELEMENT); 1222 const isText$b = isType(TEXT); 1223 const isDocument$2 = isType(DOCUMENT); 1224 const isDocumentFragment$1 = isType(DOCUMENT_FRAGMENT); 1225 const isTag = tag => e => isElement$7(e) && name(e) === tag; 1226 1227 const rawSet = (dom, key, value) => { 1228 if (isString(value) || isBoolean(value) || isNumber(value)) { 1229 dom.setAttribute(key, value + ''); 1230 } else { 1231 console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom); 1232 throw new Error('Attribute value was not simple'); 1233 } 1234 }; 1235 const set$3 = (element, key, value) => { 1236 rawSet(element.dom, key, value); 1237 }; 1238 const setAll$1 = (element, attrs) => { 1239 const dom = element.dom; 1240 each$d(attrs, (v, k) => { 1241 rawSet(dom, k, v); 1242 }); 1243 }; 1244 const get$9 = (element, key) => { 1245 const v = element.dom.getAttribute(key); 1246 return v === null ? undefined : v; 1247 }; 1248 const getOpt = (element, key) => Optional.from(get$9(element, key)); 1249 const has$1 = (element, key) => { 1250 const dom = element.dom; 1251 return dom && dom.hasAttribute ? dom.hasAttribute(key) : false; 1252 }; 1253 const remove$
vendor: 15,634 bytes, lines 1253-1688
1253b = (element, key) => { 1254 element.dom.removeAttribute(key); 1255 }; 1256 const hasNone = element => { 1257 const attrs = element.dom.attributes; 1258 return attrs === undefined || attrs === null || attrs.length === 0; 1259 }; 1260 const clone$4 = element => foldl(element.dom.attributes, (acc, attr) => { 1261 acc[attr.name] = attr.value; 1262 return acc; 1263 }, {}); 1264 1265 const read$4 = (element, attr) => { 1266 const value = get$9(element, attr); 1267 return value === undefined || value === '' ? [] : value.split(' '); 1268 }; 1269 const add$4 = (element, attr, id) => { 1270 const old = read$4(element, attr); 1271 const nu = old.concat([id]); 1272 set$3(element, attr, nu.join(' ')); 1273 return true; 1274 }; 1275 const remove$a = (element, attr, id) => { 1276 const nu = filter$5(read$4(element, attr), v => v !== id); 1277 if (nu.length > 0) { 1278 set$3(element, attr, nu.join(' ')); 1279 } else { 1280 remove$b(element, attr); 1281 } 1282 return false; 1283 }; 1284 1285 const supports = element => element.dom.classList !== undefined; 1286 const get$8 = element => read$4(element, 'class'); 1287 const add$3 = (element, clazz) => add$4(element, 'class', clazz); 1288 const remove$9 = (element, clazz) => remove$a(element, 'class', clazz); 1289 const toggle$2 = (element, clazz) => { 1290 if (contains$2(get$8(element), clazz)) { 1291 return remove$9(element, clazz); 1292 } else { 1293 return add$3(element, clazz); 1294 } 1295 }; 1296 1297 const add$2 = (element, clazz) => { 1298 if (supports(element)) { 1299 element.dom.classList.add(clazz); 1300 } else { 1301 add$3(element, clazz); 1302 } 1303 }; 1304 const cleanClass = element => { 1305 const classList = supports(element) ? element.dom.classList : get$8(element); 1306 if (classList.length === 0) { 1307 remove$b(element, 'class'); 1308 } 1309 }; 1310 const remove$8 = (element, clazz) => { 1311 if (supports(element)) { 1312 const classList = element.dom.classList; 1313 classList.remove(clazz); 1314 } else { 1315 remove$9(element, clazz); 1316 } 1317 cleanClass(element); 1318 }; 1319 const toggle$1 = (element, clazz) => { 1320 const result = supports(element) ? element.dom.classList.toggle(clazz) : toggle$2(element, clazz); 1321 cleanClass(element); 1322 return result; 1323 }; 1324 const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz); 1325 1326 const fromHtml$1 = (html, scope) => { 1327 const doc = scope || document; 1328 const div = doc.createElement('div'); 1329 div.innerHTML = html; 1330 if (!div.hasChildNodes() || div.childNodes.length > 1) { 1331 const message = 'HTML does not have a single root node'; 1332 console.error(message, html); 1333 throw new Error(message); 1334 } 1335 return fromDom$2(div.childNodes[0]); 1336 }; 1337 const fromTag = (tag, scope) => { 1338 const doc = scope || document; 1339 const node = doc.createElement(tag); 1340 return fromDom$2(node); 1341 }; 1342 const fromText = (text, scope) => { 1343 const doc = scope || document; 1344 const node = doc.createTextNode(text); 1345 return fromDom$2(node); 1346 }; 1347 const fromDom$2 = node => { 1348 if (node === null || node === undefined) { 1349 throw new Error('Node cannot be null or undefined'); 1350 } 1351 return { dom: node }; 1352 }; 1353 const fromPoint$2 = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$2); 1354 const SugarElement = { 1355 fromHtml: fromHtml$1, 1356 fromTag, 1357 fromText, 1358 fromDom: fromDom$2, 1359 fromPoint: fromPoint$2 1360 }; 1361 1362 const toArray = (target, f) => { 1363 const r = []; 1364 const recurse = e => { 1365 r.push(e); 1366 return f(e); 1367 }; 1368 let cur = f(target); 1369 do { 1370 cur = cur.bind(recurse); 1371 } while (cur.isSome()); 1372 return r; 1373 }; 1374 1375 const is$1 = (element, selector) => { 1376 const dom = element.dom; 1377 if (dom.nodeType !== ELEMENT) { 1378 return false; 1379 } else { 1380 const elem = dom; 1381 if (elem.matches !== undefined) { 1382 return elem.matches(selector); 1383 } else if (elem.msMatchesSelector !== undefined) { 1384 return elem.msMatchesSelector(selector); 1385 } else if (elem.webkitMatchesSelector !== undefined) { 1386 return elem.webkitMatchesSelector(selector); 1387 } else if (elem.mozMatchesSelector !== undefined) { 1388 return elem.mozMatchesSelector(selector); 1389 } else { 1390 throw new Error('Browser lacks native selectors'); 1391 } 1392 } 1393 }; 1394 const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0; 1395 const all = (selector, scope) => { 1396 const base = scope === undefined ? document : scope.dom; 1397 return bypassSelector(base) ? [] : map$3(base.querySelectorAll(selector), SugarElement.fromDom); 1398 }; 1399 const one = (selector, scope) => { 1400 const base = scope === undefined ? document : scope.dom; 1401 return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom); 1402 }; 1403 1404 const eq = (e1, e2) => e1.dom === e2.dom; 1405 const contains = (e1, e2) => { 1406 const d1 = e1.dom; 1407 const d2 = e2.dom; 1408 return d1 === d2 ? false : d1.contains(d2); 1409 }; 1410 1411 const owner$1 = element => SugarElement.fromDom(element.dom.ownerDocument); 1412 const documentOrOwner = dos => isDocument$2(dos) ? dos : owner$1(dos); 1413 const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement); 1414 const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView); 1415 const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom); 1416 const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom); 1417 const parents$1 = (element, isRoot) => { 1418 const stop = isFunction(isRoot) ? isRoot : never; 1419 let dom = element.dom; 1420 const ret = []; 1421 while (dom.parentNode !== null && dom.parentNode !== undefined) { 1422 const rawParent = dom.parentNode; 1423 const p = SugarElement.fromDom(rawParent); 1424 ret.push(p); 1425 if (stop(p) === true) { 1426 break; 1427 } else { 1428 dom = rawParent; 1429 } 1430 } 1431 return ret; 1432 }; 1433 const siblings = element => { 1434 const filterSelf = elements => filter$5(elements, x => !eq(element, x)); 1435 return parent(element).map(children$1).map(filterSelf).getOr([]); 1436 }; 1437 const prevSibling = element => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom); 1438 const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom); 1439 const prevSiblings = element => reverse(toArray(element, prevSibling)); 1440 const nextSiblings = element => toArray(element, nextSibling); 1441 const children$1 = element => map$3(element.dom.childNodes, SugarElement.fromDom); 1442 const child$1 = (element, index) => { 1443 const cs = element.dom.childNodes; 1444 return Optional.from(cs[index]).map(SugarElement.fromDom); 1445 }; 1446 const firstChild = element => child$1(element, 0); 1447 const lastChild = element => child$1(element, element.dom.childNodes.length - 1); 1448 const childNodesCount = element => element.dom.childNodes.length; 1449 1450 const getHead = doc => { 1451 const b = doc.dom.head; 1452 if (b === null || b === undefined) { 1453 throw new Error('Head is not available yet'); 1454 } 1455 return SugarElement.fromDom(b); 1456 }; 1457 1458 const isShadowRoot = dos => isDocumentFragment$1(dos) && isNonNullable(dos.dom.host); 1459 const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode); 1460 const isSupported$1 = constant(supported); 1461 const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner; 1462 const getStyleContainer = dos => isShadowRoot(dos) ? dos : getHead(documentOrOwner(dos)); 1463 const getContentContainer = dos => isShadowRoot(dos) ? dos : SugarElement.fromDom(documentOrOwner(dos).dom.body); 1464 const getShadowRoot = e => { 1465 const r = getRootNode(e); 1466 return isShadowRoot(r) ? Optional.some(r) : Optional.none(); 1467 }; 1468 const getShadowHost = e => SugarElement.fromDom(e.dom.host); 1469 const getOriginalEventTarget = event => { 1470 if (isSupported$1() && isNonNullable(event.target)) { 1471 const el = SugarElement.fromDom(event.target); 1472 if (isElement$7(el) && isOpenShadowHost(el)) { 1473 if (event.composed && event.composedPath) { 1474 const composedPath = event.composedPath(); 1475 if (composedPath) { 1476 return head(composedPath); 1477 } 1478 } 1479 } 1480 } 1481 return Optional.from(event.target); 1482 }; 1483 const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot); 1484 1485 const inBody = element => { 1486 const dom = isText$b(element) ? element.dom.parentNode : element.dom; 1487 if (dom === undefined || dom === null || dom.ownerDocument === null) { 1488 return false; 1489 } 1490 const doc = dom.ownerDocument; 1491 return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost)); 1492 }; 1493 1494 var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => { 1495 if (is(scope, a)) { 1496 return Optional.some(scope); 1497 } else if (isFunction(isRoot) && isRoot(scope)) { 1498 return Optional.none(); 1499 } else { 1500 return ancestor(scope, a, isRoot); 1501 } 1502 }; 1503 1504 const ancestor$4 = (scope, predicate, isRoot) => { 1505 let element = scope.dom; 1506 const stop = isFunction(isRoot) ? isRoot : never; 1507 while (element.parentNode) { 1508 element = element.parentNode; 1509 const el = SugarElement.fromDom(element); 1510 if (predicate(el)) { 1511 return Optional.some(el); 1512 } else if (stop(el)) { 1513 break; 1514 } 1515 } 1516 return Optional.none(); 1517 }; 1518 const closest$4 = (scope, predicate, isRoot) => { 1519 const is = (s, test) => test(s); 1520 return ClosestOrAncestor(is, ancestor$4, scope, predicate, isRoot); 1521 }; 1522 const sibling$1 = (scope, predicate) => { 1523 const element = scope.dom; 1524 if (!element.parentNode) { 1525 return Optional.none(); 1526 } 1527 return child(SugarElement.fromDom(element.parentNode), x => !eq(scope, x) && predicate(x)); 1528 }; 1529 const child = (scope, predicate) => { 1530 const pred = node => predicate(SugarElement.fromDom(node)); 1531 const result = find$2(scope.dom.childNodes, pred); 1532 return result.map(SugarElement.fromDom); 1533 }; 1534 const descendant$1 = (scope, predicate) => { 1535 const descend = node => { 1536 for (let i = 0; i < node.childNodes.length; i++) { 1537 const child = SugarElement.fromDom(node.childNodes[i]); 1538 if (predicate(child)) { 1539 return Optional.some(child); 1540 } 1541 const res = descend(node.childNodes[i]); 1542 if (res.isSome()) { 1543 return res; 1544 } 1545 } 1546 return Optional.none(); 1547 }; 1548 return descend(scope.dom); 1549 }; 1550 1551 const ancestor$3 = (scope, selector, isRoot) => ancestor$4(scope, e => is$1(e, selector), isRoot); 1552 const descendant = (scope, selector) => one(selector, scope); 1553 const closest$3 = (scope, selector, isRoot) => { 1554 const is = (element, selector) => is$1(element, selector); 1555 return ClosestOrAncestor(is, ancestor$3, scope, selector, isRoot); 1556 }; 1557 1558 const closest$2 = target => closest$3(target, '[contenteditable]'); 1559 const isEditable$3 = (element, assumeEditable = false) => { 1560 if (inBody(element)) { 1561 return element.dom.isContentEditable; 1562 } else { 1563 return closest$2(element).fold(constant(assumeEditable), editable => getRaw$1(editable) === 'true'); 1564 } 1565 }; 1566 const getRaw$1 = element => element.dom.contentEditable; 1567 1568 const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue); 1569 1570 const internalSet = (dom, property, value) => { 1571 if (!isString(value)) { 1572 console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom); 1573 throw new Error('CSS value must be a string: ' + value); 1574 } 1575 if (isSupported(dom)) { 1576 dom.style.setProperty(property, value); 1577 } 1578 }; 1579 const internalRemove = (dom, property) => { 1580 if (isSupported(dom)) { 1581 dom.style.removeProperty(property); 1582 } 1583 }; 1584 const set$2 = (element, property, value) => { 1585 const dom = element.dom; 1586 internalSet(dom, property, value); 1587 }; 1588 const setAll = (element, css) => { 1589 const dom = element.dom; 1590 each$d(css, (v, k) => { 1591 internalSet(dom, k, v); 1592 }); 1593 }; 1594 const get$7 = (element, property) => { 1595 const dom = element.dom; 1596 const styles = window.getComputedStyle(dom); 1597 const r = styles.getPropertyValue(property); 1598 return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r; 1599 }; 1600 const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : ''; 1601 const getRaw = (element, property) => { 1602 const dom = element.dom; 1603 const raw = getUnsafeProperty(dom, property); 1604 return Optional.from(raw).filter(r => r.length > 0); 1605 }; 1606 const getAllRaw = element => { 1607 const css = {}; 1608 const dom = element.dom; 1609 if (isSupported(dom)) { 1610 for (let i = 0; i < dom.style.length; i++) { 1611 const ruleName = dom.style.item(i); 1612 css[ruleName] = dom.style[ruleName]; 1613 } 1614 } 1615 return css; 1616 }; 1617 const remove$7 = (element, property) => { 1618 const dom = element.dom; 1619 internalRemove(dom, property); 1620 if (is$2(getOpt(element, 'style').map(trim$3), '')) { 1621 remove$b(element, 'style'); 1622 } 1623 }; 1624 const reflow = e => e.dom.offsetWidth; 1625 1626 const before$3 = (marker, element) => { 1627 const parent$1 = parent(marker); 1628 parent$1.each(v => { 1629 v.dom.insertBefore(element.dom, marker.dom); 1630 }); 1631 }; 1632 const after$4 = (marker, element) => { 1633 const sibling = nextSibling(marker); 1634 sibling.fold(() => { 1635 const parent$1 = parent(marker); 1636 parent$1.each(v => { 1637 append$1(v, element); 1638 }); 1639 }, v => { 1640 before$3(v, element); 1641 }); 1642 }; 1643 const prepend = (parent, element) => { 1644 const firstChild$1 = firstChild(parent); 1645 firstChild$1.fold(() => { 1646 append$1(parent, element); 1647 }, v => { 1648 parent.dom.insertBefore(element.dom, v.dom); 1649 }); 1650 }; 1651 const append$1 = (parent, element) => { 1652 parent.dom.appendChild(element.dom); 1653 }; 1654 const wrap$2 = (element, wrapper) => { 1655 before$3(element, wrapper); 1656 append$1(wrapper, element); 1657 }; 1658 1659 const after$3 = (marker, elements) => { 1660 each$e(elements, (x, i) => { 1661 const e = i === 0 ? marker : elements[i - 1]; 1662 after$4(e, x); 1663 }); 1664 }; 1665 const append = (parent, elements) => { 1666 each$e(elements, x => { 1667 append$1(parent, x); 1668 }); 1669 }; 1670 1671 const empty = element => { 1672 element.dom.textContent = ''; 1673 each$e(children$1(element), rogue => { 1674 remove$6(rogue); 1675 }); 1676 }; 1677 const remove$6 = element => { 1678 const dom = element.dom; 1679 if (dom.parentNode !== null) { 1680 dom.parentNode.removeChild(dom); 1681 } 1682 }; 1683 const unwrap = wrapper => { 1684 const children = children$1(wrapper); 1685 if (children.length > 0) { 1686 after$3(wrapper, children); 1687 } 1688 remove$6
vendor: 11,043 bytes, lines 1688-2017
1688(wrapper); 1689 }; 1690 1691 const fromHtml = (html, scope) => { 1692 const doc = scope || document; 1693 const div = doc.createElement('div'); 1694 div.innerHTML = html; 1695 return children$1(SugarElement.fromDom(div)); 1696 }; 1697 const fromDom$1 = nodes => map$3(nodes, SugarElement.fromDom); 1698 1699 const get$6 = element => element.dom.innerHTML; 1700 const set$1 = (element, content) => { 1701 const owner = owner$1(element); 1702 const docDom = owner.dom; 1703 const fragment = SugarElement.fromDom(docDom.createDocumentFragment()); 1704 const contentElements = fromHtml(content, docDom); 1705 append(fragment, contentElements); 1706 empty(element); 1707 append$1(element, fragment); 1708 }; 1709 const getOuter = element => { 1710 const container = SugarElement.fromTag('div'); 1711 const clone = SugarElement.fromDom(element.dom.cloneNode(true)); 1712 append$1(container, clone); 1713 return get$6(container); 1714 }; 1715 1716 const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({ 1717 target, 1718 x, 1719 y, 1720 stop, 1721 prevent, 1722 kill, 1723 raw 1724 }); 1725 const fromRawEvent = rawEvent => { 1726 const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target)); 1727 const stop = () => rawEvent.stopPropagation(); 1728 const prevent = () => rawEvent.preventDefault(); 1729 const kill = compose(prevent, stop); 1730 return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent); 1731 }; 1732 const handle$1 = (filter, handler) => rawEvent => { 1733 if (filter(rawEvent)) { 1734 handler(fromRawEvent(rawEvent)); 1735 } 1736 }; 1737 const binder = (element, event, filter, handler, useCapture) => { 1738 const wrapped = handle$1(filter, handler); 1739 element.dom.addEventListener(event, wrapped, useCapture); 1740 return { unbind: curry(unbind, element, event, wrapped, useCapture) }; 1741 }; 1742 const bind$2 = (element, event, filter, handler) => binder(element, event, filter, handler, false); 1743 const unbind = (element, event, handler, useCapture) => { 1744 element.dom.removeEventListener(event, handler, useCapture); 1745 }; 1746 1747 const r = (left, top) => { 1748 const translate = (x, y) => r(left + x, top + y); 1749 return { 1750 left, 1751 top, 1752 translate 1753 }; 1754 }; 1755 const SugarPosition = r; 1756 1757 const boxPosition = dom => { 1758 const box = dom.getBoundingClientRect(); 1759 return SugarPosition(box.left, box.top); 1760 }; 1761 const firstDefinedOrZero = (a, b) => { 1762 if (a !== undefined) { 1763 return a; 1764 } else { 1765 return b !== undefined ? b : 0; 1766 } 1767 }; 1768 const absolute = element => { 1769 const doc = element.dom.ownerDocument; 1770 const body = doc.body; 1771 const win = doc.defaultView; 1772 const html = doc.documentElement; 1773 if (body === element.dom) { 1774 return SugarPosition(body.offsetLeft, body.offsetTop); 1775 } 1776 const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop); 1777 const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft); 1778 const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop); 1779 const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft); 1780 return viewport(element).translate(scrollLeft - clientLeft, scrollTop - clientTop); 1781 }; 1782 const viewport = element => { 1783 const dom = element.dom; 1784 const doc = dom.ownerDocument; 1785 const body = doc.body; 1786 if (body === dom) { 1787 return SugarPosition(body.offsetLeft, body.offsetTop); 1788 } 1789 if (!inBody(element)) { 1790 return SugarPosition(0, 0); 1791 } 1792 return boxPosition(dom); 1793 }; 1794 1795 const get$5 = _DOC => { 1796 const doc = _DOC !== undefined ? _DOC.dom : document; 1797 const x = doc.body.scrollLeft || doc.documentElement.scrollLeft; 1798 const y = doc.body.scrollTop || doc.documentElement.scrollTop; 1799 return SugarPosition(x, y); 1800 }; 1801 const intoView = (element, alignToTop) => { 1802 const isSafari = detect$2().browser.isSafari(); 1803 if (isSafari && isFunction(element.dom.scrollIntoViewIfNeeded)) { 1804 element.dom.scrollIntoViewIfNeeded(false); 1805 } else { 1806 element.dom.scrollIntoView(alignToTop); 1807 } 1808 }; 1809 1810 const get$4 = _win => { 1811 const win = _win === undefined ? window : _win; 1812 if (detect$2().browser.isFirefox()) { 1813 return Optional.none(); 1814 } else { 1815 return Optional.from(win.visualViewport); 1816 } 1817 }; 1818 const bounds = (x, y, width, height) => ({ 1819 x, 1820 y, 1821 width, 1822 height, 1823 right: x + width, 1824 bottom: y + height 1825 }); 1826 const getBounds = _win => { 1827 const win = _win === undefined ? window : _win; 1828 const doc = win.document; 1829 const scroll = get$5(SugarElement.fromDom(doc)); 1830 return get$4(win).fold(() => { 1831 const html = win.document.documentElement; 1832 const width = html.clientWidth; 1833 const height = html.clientHeight; 1834 return bounds(scroll.left, scroll.top, width, height); 1835 }, visualViewport => bounds(Math.max(visualViewport.pageLeft, scroll.left), Math.max(visualViewport.pageTop, scroll.top), visualViewport.width, visualViewport.height)); 1836 }; 1837 1838 const children = (scope, predicate) => filter$5(children$1(scope), predicate); 1839 const descendants$1 = (scope, predicate) => { 1840 let result = []; 1841 each$e(children$1(scope), x => { 1842 if (predicate(x)) { 1843 result = result.concat([x]); 1844 } 1845 result = result.concat(descendants$1(x, predicate)); 1846 }); 1847 return result; 1848 }; 1849 1850 const descendants = (scope, selector) => all(selector, scope); 1851 1852 const ancestor$2 = (scope, selector, isRoot) => ancestor$3(scope, selector, isRoot).isSome(); 1853 1854 class DomTreeWalker { 1855 constructor(startNode, rootNode) { 1856 this.node = startNode; 1857 this.rootNode = rootNode; 1858 this.current = this.current.bind(this); 1859 this.next = this.next.bind(this); 1860 this.prev = this.prev.bind(this); 1861 this.prev2 = this.prev2.bind(this); 1862 } 1863 current() { 1864 return this.node; 1865 } 1866 next(shallow) { 1867 this.node = this.findSibling(this.node, 'firstChild', 'nextSibling', shallow); 1868 return this.node; 1869 } 1870 prev(shallow) { 1871 this.node = this.findSibling(this.node, 'lastChild', 'previousSibling', shallow); 1872 return this.node; 1873 } 1874 prev2(shallow) { 1875 this.node = this.findPreviousNode(this.node, shallow); 1876 return this.node; 1877 } 1878 findSibling(node, startName, siblingName, shallow) { 1879 if (node) { 1880 if (!shallow && node[startName]) { 1881 return node[startName]; 1882 } 1883 if (node !== this.rootNode) { 1884 let sibling = node[siblingName]; 1885 if (sibling) { 1886 return sibling; 1887 } 1888 for (let parent = node.parentNode; parent && parent !== this.rootNode; parent = parent.parentNode) { 1889 sibling = parent[siblingName]; 1890 if (sibling) { 1891 return sibling; 1892 } 1893 } 1894 } 1895 } 1896 return undefined; 1897 } 1898 findPreviousNode(node, shallow) { 1899 if (node) { 1900 const sibling = node.previousSibling; 1901 if (this.rootNode && sibling === this.rootNode) { 1902 return; 1903 } 1904 if (sibling) { 1905 if (!shallow) { 1906 for (let child = sibling.lastChild; child; child = child.lastChild) { 1907 if (!child.lastChild) { 1908 return child; 1909 } 1910 } 1911 } 1912 return sibling; 1913 } 1914 const parent = node.parentNode; 1915 if (parent && parent !== this.rootNode) { 1916 return parent; 1917 } 1918 } 1919 return undefined; 1920 } 1921 } 1922 1923 const isNodeType = type => { 1924 return node => { 1925 return !!node && node.nodeType === type; 1926 }; 1927 }; 1928 const isRestrictedNode = node => !!node && !Object.getPrototypeOf(node); 1929 const isElement$6 = isNodeType(1); 1930 const matchNodeName = name => { 1931 const lowerCasedName = name.toLowerCase(); 1932 return node => isNonNullable(node) && node.nodeName.toLowerCase() === lowerCasedName; 1933 }; 1934 const matchNodeNames = names => { 1935 const lowerCasedNames = names.map(s => s.toLowerCase()); 1936 return node => { 1937 if (node && node.nodeName) { 1938 const nodeName = node.nodeName.toLowerCase(); 1939 return contains$2(lowerCasedNames, nodeName); 1940 } 1941 return false; 1942 }; 1943 }; 1944 const matchStyleValues = (name, values) => { 1945 const items = values.toLowerCase().split(' '); 1946 return node => { 1947 if (isElement$6(node)) { 1948 const win = node.ownerDocument.defaultView; 1949 if (win) { 1950 for (let i = 0; i < items.length; i++) { 1951 const computed = win.getComputedStyle(node, null); 1952 const cssValue = computed ? computed.getPropertyValue(name) : null; 1953 if (cssValue === items[i]) { 1954 return true; 1955 } 1956 } 1957 } 1958 } 1959 return false; 1960 }; 1961 }; 1962 const hasAttribute = attrName => { 1963 return node => { 1964 return isElement$6(node) && node.hasAttribute(attrName); 1965 }; 1966 }; 1967 const hasAttributeValue = (attrName, attrValue) => { 1968 return node => { 1969 return isElement$6(node) && node.getAttribute(attrName) === attrValue; 1970 }; 1971 }; 1972 const isBogus$2 = node => isElement$6(node) && node.hasAttribute('data-mce-bogus'); 1973 const isBogusAll$1 = node => isElement$6(node) && node.getAttribute('data-mce-bogus') === 'all'; 1974 const isTable$2 = node => isElement$6(node) && node.tagName === 'TABLE'; 1975 const hasContentEditableState = value => { 1976 return node => { 1977 if (isElement$6(node)) { 1978 if (node.contentEditable === value) { 1979 return true; 1980 } 1981 if (node.getAttribute('data-mce-contenteditable') === value) { 1982 return true; 1983 } 1984 } 1985 return false; 1986 }; 1987 }; 1988 const isTextareaOrInput = matchNodeNames([ 1989 'textarea', 1990 'input' 1991 ]); 1992 const isText$a = isNodeType(3); 1993 const isCData = isNodeType(4); 1994 const isPi = isNodeType(7); 1995 const isComment = isNodeType(8); 1996 const isDocument$1 = isNodeType(9); 1997 const isDocumentFragment = isNodeType(11); 1998 const isBr$6 = matchNodeName('br'); 1999 const isImg = matchNodeName('img'); 2000 const isContentEditableTrue$3 = hasContentEditableState('true'); 2001 const isContentEditableFalse$b = hasContentEditableState('false'); 2002 const isTableCell$3 = matchNodeNames([ 2003 'td', 2004 'th' 2005 ]); 2006 const isTableCellOrCaption = matchNodeNames([ 2007 'td', 2008 'th', 2009 'caption' 2010 ]); 2011 const isMedia$2 = matchNodeNames([ 2012 'video', 2013 'audio', 2014 'object', 2015 'embed' 2016 ]); 2017 const isListItem$2 = matchNodeName('li');
vendor: 4,970 bytes, lines 2018-2227
2018 2019 const zeroWidth = '\uFEFF'; 2020 const nbsp = '\xA0'; 2021 const isZwsp$1 = char => char === zeroWidth; 2022 const removeZwsp = s => s.replace(/\uFEFF/g, ''); 2023 2024 const NodeValue = (is, name) => { 2025 const get = element => { 2026 if (!is(element)) { 2027 throw new Error('Can only get ' + name + ' value of a ' + name + ' node'); 2028 } 2029 return getOption(element).getOr(''); 2030 }; 2031 const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none(); 2032 const set = (element, value) => { 2033 if (!is(element)) { 2034 throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node'); 2035 } 2036 element.dom.nodeValue = value; 2037 }; 2038 return { 2039 get, 2040 getOption, 2041 set 2042 }; 2043 }; 2044 2045 const api$1 = NodeValue(isText$b, 'text'); 2046 const get$3 = element => api$1.get(element); 2047 const getOption = element => api$1.getOption(element); 2048 const set = (element, value) => api$1.set(element, value); 2049 2050 const blocks = [ 2051 'article', 2052 'aside', 2053 'details', 2054 'div', 2055 'dt', 2056 'figcaption', 2057 'footer', 2058 'form', 2059 'fieldset', 2060 'header', 2061 'hgroup', 2062 'html', 2063 'main', 2064 'nav', 2065 'section', 2066 'summary', 2067 'body', 2068 'p', 2069 'dl', 2070 'multicol', 2071 'dd', 2072 'figure', 2073 'address', 2074 'center', 2075 'blockquote', 2076 'h1', 2077 'h2', 2078 'h3', 2079 'h4', 2080 'h5', 2081 'h6', 2082 'listing', 2083 'xmp', 2084 'pre', 2085 'plaintext', 2086 'menu', 2087 'dir', 2088 'ul', 2089 'ol', 2090 'li', 2091 'hr', 2092 'table', 2093 'tbody', 2094 'thead', 2095 'tfoot', 2096 'th', 2097 'tr', 2098 'td', 2099 'caption' 2100 ]; 2101 const tableCells = [ 2102 'td', 2103 'th' 2104 ]; 2105 const tableSections = [ 2106 'thead', 2107 'tbody', 2108 'tfoot' 2109 ]; 2110 const textBlocks = [ 2111 'h1', 2112 'h2', 2113 'h3', 2114 'h4', 2115 'h5', 2116 'h6', 2117 'p', 2118 'div', 2119 'address', 2120 'pre', 2121 'form', 2122 'blockquote', 2123 'center', 2124 'dir', 2125 'fieldset', 2126 'header', 2127 'footer', 2128 'article', 2129 'section', 2130 'hgroup', 2131 'aside', 2132 'nav', 2133 'figure' 2134 ]; 2135 const headings = [ 2136 'h1', 2137 'h2', 2138 'h3', 2139 'h4', 2140 'h5', 2141 'h6' 2142 ]; 2143 const listItems$1 = [ 2144 'li', 2145 'dd', 2146 'dt' 2147 ]; 2148 const lists = [ 2149 'ul', 2150 'ol', 2151 'dl' 2152 ]; 2153 const wsElements = [ 2154 'pre', 2155 'script', 2156 'textarea', 2157 'style' 2158 ]; 2159 const wrapBlockElements = ['pre'].concat(headings); 2160 const lazyLookup = items => { 2161 let lookup; 2162 return node => { 2163 lookup = lookup ? lookup : mapToObject(items, always); 2164 return has$2(lookup, name(node)); 2165 }; 2166 }; 2167 const isBlock$2 = lazyLookup(blocks); 2168 const isTable$1 = node => name(node) === 'table'; 2169 const isInline$1 = node => isElement$7(node) && !isBlock$2(node); 2170 const isBr$5 = node => isElement$7(node) && name(node) === 'br'; 2171 const isTextBlock$2 = lazyLookup(textBlocks); 2172 const isList = lazyLookup(lists); 2173 const isListItem$1 = lazyLookup(listItems$1); 2174 const isTableSection = lazyLookup(tableSections); 2175 const isTableCell$2 = lazyLookup(tableCells); 2176 const isWsPreserveElement = lazyLookup(wsElements); 2177 const isWrapBlockElement = lazyLookup(wrapBlockElements); 2178 const isWrapElement = node => isWrapBlockElement(node) || isInline$1(node); 2179 2180 const getLastChildren$1 = elm => { 2181 const children = []; 2182 let rawNode = elm.dom; 2183 while (rawNode) { 2184 children.push(SugarElement.fromDom(rawNode)); 2185 rawNode = rawNode.lastChild; 2186 } 2187 return children; 2188 }; 2189 const removeTrailingBr = elm => { 2190 const allBrs = descendants(elm, 'br'); 2191 const brs = filter$5(getLastChildren$1(elm).slice(-1), isBr$5); 2192 if (allBrs.length === brs.length) { 2193 each$e(brs, remove$6); 2194 } 2195 }; 2196 const createPaddingBr = () => { 2197 const br = SugarElement.fromTag('br'); 2198 set$3(br, 'data-mce-bogus', '1'); 2199 return br; 2200 }; 2201 const fillWithPaddingBr = elm => { 2202 empty(elm); 2203 append$1(elm, createPaddingBr()); 2204 }; 2205 const trimBlockTrailingBr = elm => { 2206 lastChild(elm).each(lastChild => { 2207 prevSibling(lastChild).each(lastChildPrevSibling => { 2208 if (isBlock$2(elm) && isBr$5(lastChild) && isBlock$2(lastChildPrevSibling)) { 2209 remove$6(lastChild); 2210 } 2211 }); 2212 }); 2213 }; 2214 2215 const ZWSP$1 = zeroWidth; 2216 const isZwsp = isZwsp$1; 2217 const trim$1 = removeZwsp; 2218 2219 const isElement$5 = isElement$6; 2220 const isText$9 = isText$a; 2221 const isCaretContainerBlock$1 = node => { 2222 if (isText$9(node)) { 2223 node = node.parentNode; 2224 } 2225 return isElement$5(node) && node.hasAttribute('data-mce-caret'); 2226 }; 2227 const isCaretContainerInline = node => isText$9(node) && isZwsp
vendor: 14,737 bytes, lines 2227-2572
2227(node.data); 2228 const isCaretContainer$2 = node => isCaretContainerBlock$1(node) || isCaretContainerInline(node); 2229 const hasContent = node => node.firstChild !== node.lastChild || !isBr$6(node.firstChild); 2230 const insertInline$1 = (node, before) => { 2231 var _a; 2232 const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document; 2233 const textNode = doc.createTextNode(ZWSP$1); 2234 const parentNode = node.parentNode; 2235 if (!before) { 2236 const sibling = node.nextSibling; 2237 if (isText$9(sibling)) { 2238 if (isCaretContainer$2(sibling)) { 2239 return sibling; 2240 } 2241 if (startsWithCaretContainer$1(sibling)) { 2242 sibling.splitText(1); 2243 return sibling; 2244 } 2245 } 2246 if (node.nextSibling) { 2247 parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(textNode, node.nextSibling); 2248 } else { 2249 parentNode === null || parentNode === void 0 ? void 0 : parentNode.appendChild(textNode); 2250 } 2251 } else { 2252 const sibling = node.previousSibling; 2253 if (isText$9(sibling)) { 2254 if (isCaretContainer$2(sibling)) { 2255 return sibling; 2256 } 2257 if (endsWithCaretContainer$1(sibling)) { 2258 return sibling.splitText(sibling.data.length - 1); 2259 } 2260 } 2261 parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(textNode, node); 2262 } 2263 return textNode; 2264 }; 2265 const isBeforeInline = pos => { 2266 const container = pos.container(); 2267 if (!isText$a(container)) { 2268 return false; 2269 } 2270 return container.data.charAt(pos.offset()) === ZWSP$1 || pos.isAtStart() && isCaretContainerInline(container.previousSibling); 2271 }; 2272 const isAfterInline = pos => { 2273 const container = pos.container(); 2274 if (!isText$a(container)) { 2275 return false; 2276 } 2277 return container.data.charAt(pos.offset() - 1) === ZWSP$1 || pos.isAtEnd() && isCaretContainerInline(container.nextSibling); 2278 }; 2279 const insertBlock = (blockName, node, before) => { 2280 var _a; 2281 const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document; 2282 const blockNode = doc.createElement(blockName); 2283 blockNode.setAttribute('data-mce-caret', before ? 'before' : 'after'); 2284 blockNode.setAttribute('data-mce-bogus', 'all'); 2285 blockNode.appendChild(createPaddingBr().dom); 2286 const parentNode = node.parentNode; 2287 if (!before) { 2288 if (node.nextSibling) { 2289 parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(blockNode, node.nextSibling); 2290 } else { 2291 parentNode === null || parentNode === void 0 ? void 0 : parentNode.appendChild(blockNode); 2292 } 2293 } else { 2294 parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(blockNode, node); 2295 } 2296 return blockNode; 2297 }; 2298 const startsWithCaretContainer$1 = node => isText$9(node) && node.data[0] === ZWSP$1; 2299 const endsWithCaretContainer$1 = node => isText$9(node) && node.data[node.data.length - 1] === ZWSP$1; 2300 const trimBogusBr = elm => { 2301 var _a; 2302 const brs = elm.getElementsByTagName('br'); 2303 const lastBr = brs[brs.length - 1]; 2304 if (isBogus$2(lastBr)) { 2305 (_a = lastBr.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(lastBr); 2306 } 2307 }; 2308 const showCaretContainerBlock = caretContainer => { 2309 if (caretContainer && caretContainer.hasAttribute('data-mce-caret')) { 2310 trimBogusBr(caretContainer); 2311 caretContainer.removeAttribute('data-mce-caret'); 2312 caretContainer.removeAttribute('data-mce-bogus'); 2313 caretContainer.removeAttribute('style'); 2314 caretContainer.removeAttribute('data-mce-style'); 2315 caretContainer.removeAttribute('_moz_abspos'); 2316 return caretContainer; 2317 } 2318 return null; 2319 }; 2320 const isRangeInCaretContainerBlock = range => isCaretContainerBlock$1(range.startContainer); 2321 2322 const isContentEditableTrue$2 = isContentEditableTrue$3; 2323 const isContentEditableFalse$a = isContentEditableFalse$b; 2324 const isBr$4 = isBr$6; 2325 const isText$8 = isText$a; 2326 const isInvalidTextElement = matchNodeNames([ 2327 'script', 2328 'style', 2329 'textarea' 2330 ]); 2331 const isAtomicInline = matchNodeNames([ 2332 'img', 2333 'input', 2334 'textarea', 2335 'hr', 2336 'iframe', 2337 'video', 2338 'audio', 2339 'object', 2340 'embed' 2341 ]); 2342 const isTable = matchNodeNames(['table']); 2343 const isCaretContainer$1 = isCaretContainer$2; 2344 const isCaretCandidate$3 = node => { 2345 if (isCaretContainer$1(node)) { 2346 return false; 2347 } 2348 if (isText$8(node)) { 2349 return !isInvalidTextElement(node.parentNode); 2350 } 2351 return isAtomicInline(node) || isBr$4(node) || isTable(node) || isNonUiContentEditableFalse(node); 2352 }; 2353 const isUnselectable = node => isElement$6(node) && node.getAttribute('unselectable') === 'true'; 2354 const isNonUiContentEditableFalse = node => !isUnselectable(node) && isContentEditableFalse$a(node); 2355 const isInEditable = (node, root) => { 2356 for (let tempNode = node.parentNode; tempNode && tempNode !== root; tempNode = tempNode.parentNode) { 2357 if (isNonUiContentEditableFalse(tempNode)) { 2358 return false; 2359 } 2360 if (isContentEditableTrue$2(tempNode)) { 2361 return true; 2362 } 2363 } 2364 return true; 2365 }; 2366 const isAtomicContentEditableFalse = node => { 2367 if (!isNonUiContentEditableFalse(node)) { 2368 return false; 2369 } 2370 return !foldl(from(node.getElementsByTagName('*')), (result, elm) => { 2371 return result || isContentEditableTrue$2(elm); 2372 }, false); 2373 }; 2374 const isAtomic$1 = node => isAtomicInline(node) || isAtomicContentEditableFalse(node); 2375 const isEditableCaretCandidate$1 = (node, root) => isCaretCandidate$3(node) && isInEditable(node, root); 2376 2377 const whiteSpaceRegExp = /^[ \t\r\n]*$/; 2378 const isWhitespaceText = text => whiteSpaceRegExp.test(text); 2379 const isCollapsibleWhitespace$1 = c => ' \f\t\x0B'.indexOf(c) !== -1; 2380 const isNewLineChar = c => c === '\n' || c === '\r'; 2381 const isNewline = (text, idx) => idx < text.length && idx >= 0 ? isNewLineChar(text[idx]) : false; 2382 const normalize$4 = (text, tabSpaces = 4, isStartOfContent = true, isEndOfContent = true) => { 2383 const tabSpace = repeat(' ', tabSpaces); 2384 const normalizedText = text.replace(/\t/g, tabSpace); 2385 const result = foldl(normalizedText, (acc, c) => { 2386 if (isCollapsibleWhitespace$1(c) || c === nbsp) { 2387 if (acc.pcIsSpace || acc.str === '' && isStartOfContent || acc.str.length === normalizedText.length - 1 && isEndOfContent || isNewline(normalizedText, acc.str.length + 1)) { 2388 return { 2389 pcIsSpace: false, 2390 str: acc.str + nbsp 2391 }; 2392 } else { 2393 return { 2394 pcIsSpace: true, 2395 str: acc.str + ' ' 2396 }; 2397 } 2398 } else { 2399 return { 2400 pcIsSpace: isNewLineChar(c), 2401 str: acc.str + c 2402 }; 2403 } 2404 }, { 2405 pcIsSpace: false, 2406 str: '' 2407 }); 2408 return result.str; 2409 }; 2410 2411 const hasWhitespacePreserveParent = (node, rootNode) => { 2412 const rootElement = SugarElement.fromDom(rootNode); 2413 const startNode = SugarElement.fromDom(node); 2414 return ancestor$2(startNode, 'pre,code', curry(eq, rootElement)); 2415 }; 2416 const isWhitespace$1 = (node, rootNode) => { 2417 return isText$a(node) && isWhitespaceText(node.data) && !hasWhitespacePreserveParent(node, rootNode); 2418 }; 2419 const isNamedAnchor = node => { 2420 return isElement$6(node) && node.nodeName === 'A' && !node.hasAttribute('href') && (node.hasAttribute('name') || node.hasAttribute('id')); 2421 }; 2422 const isContent$1 = (node, rootNode) => { 2423 return isCaretCandidate$3(node) && !isWhitespace$1(node, rootNode) || isNamedAnchor(node) || isBookmark(node); 2424 }; 2425 const isBookmark = hasAttribute('data-mce-bookmark'); 2426 const isBogus$1 = hasAttribute('data-mce-bogus'); 2427 const isBogusAll = hasAttributeValue('data-mce-bogus', 'all'); 2428 const isEmptyNode = (targetNode, skipBogus) => { 2429 let brCount = 0; 2430 if (isContent$1(targetNode, targetNode)) { 2431 return false; 2432 } else { 2433 let node = targetNode.firstChild; 2434 if (!node) { 2435 return true; 2436 } 2437 const walker = new DomTreeWalker(node, targetNode); 2438 do { 2439 if (skipBogus) { 2440 if (isBogusAll(node)) { 2441 node = walker.next(true); 2442 continue; 2443 } 2444 if (isBogus$1(node)) { 2445 node = walker.next(); 2446 continue; 2447 } 2448 } 2449 if (isBr$6(node)) { 2450 brCount++; 2451 node = walker.next(); 2452 continue; 2453 } 2454 if (isContent$1(node, targetNode)) { 2455 return false; 2456 } 2457 node = walker.next(); 2458 } while (node); 2459 return brCount <= 1; 2460 } 2461 }; 2462 const isEmpty$2 = (elm, skipBogus = true) => isEmptyNode(elm.dom, skipBogus); 2463 2464 const transparentBlockAttr = 'data-mce-block'; 2465 const elementNames = map => filter$5(keys(map), key => !/[A-Z]/.test(key)); 2466 const makeSelectorFromSchemaMap = map => elementNames(map).join(','); 2467 const updateTransparent = (blocksSelector, transparent) => { 2468 if (isNonNullable(transparent.querySelector(blocksSelector))) { 2469 transparent.setAttribute(transparentBlockAttr, 'true'); 2470 if (transparent.getAttribute('data-mce-selected') === 'inline-boundary') { 2471 transparent.removeAttribute('data-mce-selected'); 2472 } 2473 return true; 2474 } else { 2475 transparent.removeAttribute(transparentBlockAttr); 2476 return false; 2477 } 2478 }; 2479 const updateBlockStateOnChildren = (schema, scope) => { 2480 const transparentSelector = makeSelectorFromSchemaMap(schema.getTransparentElements()); 2481 const blocksSelector = makeSelectorFromSchemaMap(schema.getBlockElements()); 2482 return filter$5(scope.querySelectorAll(transparentSelector), transparent => updateTransparent(blocksSelector, transparent)); 2483 }; 2484 const trimEdge = (el, leftSide) => { 2485 var _a; 2486 const childPropertyName = leftSide ? 'lastChild' : 'firstChild'; 2487 for (let child = el[childPropertyName]; child; child = child[childPropertyName]) { 2488 if (isEmpty$2(SugarElement.fromDom(child))) { 2489 (_a = child.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(child); 2490 return; 2491 } 2492 } 2493 }; 2494 const split$2 = (parentElm, splitElm) => { 2495 const range = document.createRange(); 2496 const parentNode = parentElm.parentNode; 2497 if (parentNode) { 2498 range.setStartBefore(parentElm); 2499 range.setEndBefore(splitElm); 2500 const beforeFragment = range.extractContents(); 2501 trimEdge(beforeFragment, true); 2502 range.setStartAfter(splitElm); 2503 range.setEndAfter(parentElm); 2504 const afterFragment = range.extractContents(); 2505 trimEdge(afterFragment, false); 2506 if (!isEmpty$2(SugarElement.fromDom(beforeFragment))) { 2507 parentNode.insertBefore(beforeFragment, parentElm); 2508 } 2509 if (!isEmpty$2(SugarElement.fromDom(splitElm))) { 2510 parentNode.insertBefore(splitElm, parentElm); 2511 } 2512 if (!isEmpty$2(SugarElement.fromDom(afterFragment))) { 2513 parentNode.insertBefore(afterFragment, parentElm); 2514 } 2515 parentNode.removeChild(parentElm); 2516 } 2517 }; 2518 const splitInvalidChildren = (schema, scope, transparentBlocks) => { 2519 const blocksElements = schema.getBlockElements(); 2520 const rootNode = SugarElement.fromDom(scope); 2521 const isBlock = el => name(el) in blocksElements; 2522 const isRoot = el => eq(el, rootNode); 2523 each$e(fromDom$1(transparentBlocks), transparentBlock => { 2524 ancestor$4(transparentBlock, isBlock, isRoot).each(parentBlock => { 2525 const invalidChildren = children(transparentBlock, el => isBlock(el) && !schema.isValidChild(name(parentBlock), name(el))); 2526 if (invalidChildren.length > 0) { 2527 const stateScope = parentElement(parentBlock); 2528 each$e(invalidChildren, child => { 2529 ancestor$4(child, isBlock, isRoot).each(parentBlock => { 2530 split$2(parentBlock.dom, child.dom); 2531 }); 2532 }); 2533 stateScope.each(scope => updateBlockStateOnChildren(schema, scope.dom)); 2534 } 2535 }); 2536 }); 2537 }; 2538 const unwrapInvalidChildren = (schema, scope, transparentBlocks) => { 2539 each$e([ 2540 ...transparentBlocks, 2541 ...isTransparentBlock(schema, scope) ? [scope] : [] 2542 ], block => each$e(descendants(SugarElement.fromDom(block), block.nodeName.toLowerCase()), elm => { 2543 if (isTransparentInline(schema, elm.dom)) { 2544 unwrap(elm); 2545 } 2546 })); 2547 }; 2548 const updateChildren = (schema, scope) => { 2549 const transparentBlocks = updateBlockStateOnChildren(schema, scope); 2550 splitInvalidChildren(schema, scope, transparentBlocks); 2551 unwrapInvalidChildren(schema, scope, transparentBlocks); 2552 }; 2553 const updateElement = (schema, target) => { 2554 if (isTransparentElement(schema, target)) { 2555 const blocksSelector = makeSelectorFromSchemaMap(schema.getBlockElements()); 2556 updateTransparent(blocksSelector, target); 2557 } 2558 }; 2559 const updateCaret = (schema, root, caretParent) => { 2560 const isRoot = el => eq(el, SugarElement.fromDom(root)); 2561 const parents = parents$1(SugarElement.fromDom(caretParent), isRoot); 2562 get$b(parents, parents.length - 2).filter(isElement$7).fold(() => updateChildren(schema, root), scope => updateChildren(schema, scope.dom)); 2563 }; 2564 const hasBlockAttr = el => el.hasAttribute(transparentBlockAttr); 2565 const isTransparentElementName = (schema, name) => has$2(schema.getTransparentElements(), name); 2566 const isTransparentElement = (schema, node) => isElement$6(node) && isTransparentElementName(schema, node.nodeName); 2567 const isTransparentBlock = (schema, node) => isTransparentElement(schema, node) && hasBlockAttr(node); 2568 const isTransparentInline = (schema, node) => isTransparentElement(schema, node) && !hasBlockAttr(node); 2569 const isTransparentAstBlock = (schema, node) => node.type === 1 && isTransparentElementName(schema, node.name) && isString(node.attr(transparentBlockAttr)); 2570 const isTransparentAstInline = (schema, node) => node.type === 1 && isTransparentElementName(schema, node.name) && isUndefined(node.attr(transparentBlockAttr)); 2571 2572 const browser
vendor: 2,903 bytes, lines 2572-2642
2572 = detect$2().browser; 2573 const firstElement = nodes => find$2(nodes, isElement$7); 2574 const getTableCaptionDeltaY = elm => { 2575 if (browser.isFirefox() && name(elm) === 'table') { 2576 return firstElement(children$1(elm)).filter(elm => { 2577 return name(elm) === 'caption'; 2578 }).bind(caption => { 2579 return firstElement(nextSiblings(caption)).map(body => { 2580 const bodyTop = body.dom.offsetTop; 2581 const captionTop = caption.dom.offsetTop; 2582 const captionHeight = caption.dom.offsetHeight; 2583 return bodyTop <= captionTop ? -captionHeight : 0; 2584 }); 2585 }).getOr(0); 2586 } else { 2587 return 0; 2588 } 2589 }; 2590 const hasChild = (elm, child) => elm.children && contains$2(elm.children, child); 2591 const getPos = (body, elm, rootElm) => { 2592 let x = 0, y = 0; 2593 const doc = body.ownerDocument; 2594 rootElm = rootElm ? rootElm : body; 2595 if (elm) { 2596 if (rootElm === body && elm.getBoundingClientRect && get$7(SugarElement.fromDom(body), 'position') === 'static') { 2597 const pos = elm.getBoundingClientRect(); 2598 x = pos.left + (doc.documentElement.scrollLeft || body.scrollLeft) - doc.documentElement.clientLeft; 2599 y = pos.top + (doc.documentElement.scrollTop || body.scrollTop) - doc.documentElement.clientTop; 2600 return { 2601 x, 2602 y 2603 }; 2604 } 2605 let offsetParent = elm; 2606 while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType && !hasChild(offsetParent, rootElm)) { 2607 const castOffsetParent = offsetParent; 2608 x += castOffsetParent.offsetLeft || 0; 2609 y += castOffsetParent.offsetTop || 0; 2610 offsetParent = castOffsetParent.offsetParent; 2611 } 2612 offsetParent = elm.parentNode; 2613 while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType && !hasChild(offsetParent, rootElm)) { 2614 x -= offsetParent.scrollLeft || 0; 2615 y -= offsetParent.scrollTop || 0; 2616 offsetParent = offsetParent.parentNode; 2617 } 2618 y += getTableCaptionDeltaY(SugarElement.fromDom(elm)); 2619 } 2620 return { 2621 x, 2622 y 2623 }; 2624 }; 2625 2626 const StyleSheetLoader = (documentOrShadowRoot, settings = {}) => { 2627 let idCount = 0; 2628 const loadedStates = {}; 2629 const edos = SugarElement.fromDom(documentOrShadowRoot); 2630 const doc = documentOrOwner(edos); 2631 const _setReferrerPolicy = referrerPolicy => { 2632 settings.referrerPolicy = referrerPolicy; 2633 }; 2634 const _setContentCssCors = contentCssCors => { 2635 settings.contentCssCors = contentCssCors; 2636 }; 2637 const addStyle = element => { 2638 append$1(getStyleContainer(edos), element); 2639 }; 2640 const removeStyle = id => { 2641 const styleContainer = getStyleContainer(edos); 2642 descendant(styleContainer, '#' + id).each(remove$6
vendor: 16,522 bytes, lines 2642-3031
2642); 2643 }; 2644 const getOrCreateState = url => get$a(loadedStates, url).getOrThunk(() => ({ 2645 id: 'mce-u' + idCount++, 2646 passed: [], 2647 failed: [], 2648 count: 0 2649 })); 2650 const load = url => new Promise((success, failure) => { 2651 let link; 2652 const urlWithSuffix = Tools._addCacheSuffix(url); 2653 const state = getOrCreateState(urlWithSuffix); 2654 loadedStates[urlWithSuffix] = state; 2655 state.count++; 2656 const resolve = (callbacks, status) => { 2657 each$e(callbacks, call); 2658 state.status = status; 2659 state.passed = []; 2660 state.failed = []; 2661 if (link) { 2662 link.onload = null; 2663 link.onerror = null; 2664 link = null; 2665 } 2666 }; 2667 const passed = () => resolve(state.passed, 2); 2668 const failed = () => resolve(state.failed, 3); 2669 if (success) { 2670 state.passed.push(success); 2671 } 2672 if (failure) { 2673 state.failed.push(failure); 2674 } 2675 if (state.status === 1) { 2676 return; 2677 } 2678 if (state.status === 2) { 2679 passed(); 2680 return; 2681 } 2682 if (state.status === 3) { 2683 failed(); 2684 return; 2685 } 2686 state.status = 1; 2687 const linkElem = SugarElement.fromTag('link', doc.dom); 2688 setAll$1(linkElem, { 2689 rel: 'stylesheet', 2690 type: 'text/css', 2691 id: state.id 2692 }); 2693 if (settings.contentCssCors) { 2694 set$3(linkElem, 'crossOrigin', 'anonymous'); 2695 } 2696 if (settings.referrerPolicy) { 2697 set$3(linkElem, 'referrerpolicy', settings.referrerPolicy); 2698 } 2699 link = linkElem.dom; 2700 link.onload = passed; 2701 link.onerror = failed; 2702 addStyle(linkElem); 2703 set$3(linkElem, 'href', urlWithSuffix); 2704 }); 2705 const loadAll = urls => { 2706 const loadedUrls = Promise.allSettled(map$3(urls, url => load(url).then(constant(url)))); 2707 return loadedUrls.then(results => { 2708 const parts = partition$2(results, r => r.status === 'fulfilled'); 2709 if (parts.fail.length > 0) { 2710 return Promise.reject(map$3(parts.fail, result => result.reason)); 2711 } else { 2712 return map$3(parts.pass, result => result.value); 2713 } 2714 }); 2715 }; 2716 const unload = url => { 2717 const urlWithSuffix = Tools._addCacheSuffix(url); 2718 get$a(loadedStates, urlWithSuffix).each(state => { 2719 const count = --state.count; 2720 if (count === 0) { 2721 delete loadedStates[urlWithSuffix]; 2722 removeStyle(state.id); 2723 } 2724 }); 2725 }; 2726 const unloadAll = urls => { 2727 each$e(urls, url => { 2728 unload(url); 2729 }); 2730 }; 2731 return { 2732 load, 2733 loadAll, 2734 unload, 2735 unloadAll, 2736 _setReferrerPolicy, 2737 _setContentCssCors 2738 }; 2739 }; 2740 2741 const create$d = () => { 2742 const map = new WeakMap(); 2743 const forElement = (referenceElement, settings) => { 2744 const root = getRootNode(referenceElement); 2745 const rootDom = root.dom; 2746 return Optional.from(map.get(rootDom)).getOrThunk(() => { 2747 const sl = StyleSheetLoader(rootDom, settings); 2748 map.set(rootDom, sl); 2749 return sl; 2750 }); 2751 }; 2752 return { forElement }; 2753 }; 2754 const instance = create$d(); 2755 2756 const isSpan = node => node.nodeName.toLowerCase() === 'span'; 2757 const isInlineContent = (node, root) => isNonNullable(node) && (isContent$1(node, root) || isInline$1(SugarElement.fromDom(node))); 2758 const surroundedByInlineContent = (node, root) => { 2759 const prev = new DomTreeWalker(node, root).prev(false); 2760 const next = new DomTreeWalker(node, root).next(false); 2761 const prevIsInline = isUndefined(prev) || isInlineContent(prev, root); 2762 const nextIsInline = isUndefined(next) || isInlineContent(next, root); 2763 return prevIsInline && nextIsInline; 2764 }; 2765 const isBookmarkNode$2 = node => isSpan(node) && node.getAttribute('data-mce-type') === 'bookmark'; 2766 const isKeepTextNode = (node, root) => isText$a(node) && node.data.length > 0 && surroundedByInlineContent(node, root); 2767 const isKeepElement = node => isElement$6(node) ? node.childNodes.length > 0 : false; 2768 const isDocument = node => isDocumentFragment(node) || isDocument$1(node); 2769 const trimNode = (dom, node, root) => { 2770 var _a; 2771 const rootNode = root || node; 2772 if (isElement$6(node) && isBookmarkNode$2(node)) { 2773 return node; 2774 } 2775 const children = node.childNodes; 2776 for (let i = children.length - 1; i >= 0; i--) { 2777 trimNode(dom, children[i], rootNode); 2778 } 2779 if (isElement$6(node)) { 2780 const currentChildren = node.childNodes; 2781 if (currentChildren.length === 1 && isBookmarkNode$2(currentChildren[0])) { 2782 (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(currentChildren[0], node); 2783 } 2784 } 2785 if (!isDocument(node) && !isContent$1(node, rootNode) && !isKeepElement(node) && !isKeepTextNode(node, rootNode)) { 2786 dom.remove(node); 2787 } 2788 return node; 2789 }; 2790 2791 const makeMap$3 = Tools.makeMap; 2792 const attrsCharsRegExp = /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g; 2793 const textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g; 2794 const rawCharsRegExp = /[<>&\"\']/g; 2795 const entityRegExp = /&#([a-z0-9]+);?|&([a-z0-9]+);/gi; 2796 const asciiMap = { 2797 128: '\u20AC', 2798 130: '\u201A', 2799 131: '\u0192', 2800 132: '\u201E', 2801 133: '\u2026', 2802 134: '\u2020', 2803 135: '\u2021', 2804 136: '\u02c6', 2805 137: '\u2030', 2806 138: '\u0160', 2807 139: '\u2039', 2808 140: '\u0152', 2809 142: '\u017d', 2810 145: '\u2018', 2811 146: '\u2019', 2812 147: '\u201C', 2813 148: '\u201D', 2814 149: '\u2022', 2815 150: '\u2013', 2816 151: '\u2014', 2817 152: '\u02DC', 2818 153: '\u2122', 2819 154: '\u0161', 2820 155: '\u203A', 2821 156: '\u0153', 2822 158: '\u017e', 2823 159: '\u0178' 2824 }; 2825 const baseEntities = { 2826 '"': '"', 2827 '\'': ''', 2828 '<': '<', 2829 '>': '>', 2830 '&': '&', 2831 '`': '`' 2832 }; 2833 const reverseEntities = { 2834 '<': '<', 2835 '>': '>', 2836 '&': '&', 2837 '"': '"', 2838 ''': `'` 2839 }; 2840 const nativeDecode = text => { 2841 const elm = SugarElement.fromTag('div').dom; 2842 elm.innerHTML = text; 2843 return elm.textContent || elm.innerText || text; 2844 }; 2845 const buildEntitiesLookup = (items, radix) => { 2846 const lookup = {}; 2847 if (items) { 2848 const itemList = items.split(','); 2849 radix = radix || 10; 2850 for (let i = 0; i < itemList.length; i += 2) { 2851 const chr = String.fromCharCode(parseInt(itemList[i], radix)); 2852 if (!baseEntities[chr]) { 2853 const entity = '&' + itemList[i + 1] + ';'; 2854 lookup[chr] = entity; 2855 lookup[entity] = chr; 2856 } 2857 } 2858 return lookup; 2859 } else { 2860 return undefined; 2861 } 2862 }; 2863 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); 2864 const encodeRaw = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => { 2865 return baseEntities[chr] || chr; 2866 }); 2867 const encodeAllRaw = text => ('' + text).replace(rawCharsRegExp, chr => { 2868 return baseEntities[chr] || chr; 2869 }); 2870 const encodeNumeric = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => { 2871 if (chr.length > 1) { 2872 return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';'; 2873 } 2874 return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';'; 2875 }); 2876 const encodeNamed = (text, attr, entities) => { 2877 const resolveEntities = entities || namedEntities; 2878 return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => { 2879 return baseEntities[chr] || resolveEntities[chr] || chr; 2880 }); 2881 }; 2882 const getEncodeFunc = (name, entities) => { 2883 const entitiesMap = buildEntitiesLookup(entities) || namedEntities; 2884 const encodeNamedAndNumeric = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => { 2885 if (baseEntities[chr] !== undefined) { 2886 return baseEntities[chr]; 2887 } 2888 if (entitiesMap[chr] !== undefined) { 2889 return entitiesMap[chr]; 2890 } 2891 if (chr.length > 1) { 2892 return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';'; 2893 } 2894 return '&#' + chr.charCodeAt(0) + ';'; 2895 }); 2896 const encodeCustomNamed = (text, attr) => { 2897 return encodeNamed(text, attr, entitiesMap); 2898 }; 2899 const nameMap = makeMap$3(name.replace(/\+/g, ',')); 2900 if (nameMap.named && nameMap.numeric) { 2901 return encodeNamedAndNumeric; 2902 } 2903 if (nameMap.named) { 2904 if (entities) { 2905 return encodeCustomNamed; 2906 } 2907 return encodeNamed; 2908 } 2909 if (nameMap.numeric) { 2910 return encodeNumeric; 2911 } 2912 return encodeRaw; 2913 }; 2914 const decode = text => text.replace(entityRegExp, (all, numeric) => { 2915 if (numeric) { 2916 if (numeric.charAt(0).toLowerCase() === 'x') { 2917 numeric = parseInt(numeric.substr(1), 16); 2918 } else { 2919 numeric = parseInt(numeric, 10); 2920 } 2921 if (numeric > 65535) { 2922 numeric -= 65536; 2923 return String.fromCharCode(55296 + (numeric >> 10), 56320 + (numeric & 1023)); 2924 } 2925 return asciiMap[numeric] || String.fromCharCode(numeric); 2926 } 2927 return reverseEntities[all] || namedEntities[all] || nativeDecode(all); 2928 }); 2929 const Entities = { 2930 encodeRaw, 2931 encodeAllRaw, 2932 encodeNumeric, 2933 encodeNamed, 2934 getEncodeFunc, 2935 decode 2936 }; 2937 2938 const lookupCache = {}; 2939 const mapCache = {}; 2940 const dummyObj = {}; 2941 const makeMap$2 = Tools.makeMap, each$b = Tools.each, extend$2 = Tools.extend, explode$2 = Tools.explode, inArray = Tools.inArray; 2942 const split$1 = (items, delim) => { 2943 items = Tools.trim(items); 2944 return items ? items.split(delim || ' ') : []; 2945 }; 2946 const createMap = (defaultValue, extendWith = {}) => { 2947 const value = makeMap$2(defaultValue, ' ', makeMap$2(defaultValue.toUpperCase(), ' ')); 2948 return extend$2(value, extendWith); 2949 }; 2950 const getTextRootBlockElements = schema => createMap('td th li dt dd figcaption caption details summary', schema.getTextBlockElements()); 2951 const compileSchema = type => { 2952 const schema = {}; 2953 let globalAttributes, blockContent; 2954 let phrasingContent, flowContent; 2955 const add = (name, attributes = '', children = '') => { 2956 const childNames = split$1(children); 2957 const names = split$1(name); 2958 let ni = names.length; 2959 while (ni--) { 2960 const attributesOrder = split$1([ 2961 globalAttributes, 2962 attributes 2963 ].join(' ')); 2964 schema[names[ni]] = { 2965 attributes: mapToObject(attributesOrder, () => ({})), 2966 attributesOrder, 2967 children: mapToObject(childNames, constant(dummyObj)) 2968 }; 2969 } 2970 }; 2971 const addAttrs = (name, attributes) => { 2972 const names = split$1(name); 2973 const attrs = split$1(attributes); 2974 let ni = names.length; 2975 while (ni--) { 2976 const schemaItem = schema[names[ni]]; 2977 for (let i = 0, l = attrs.length; i < l; i++) { 2978 schemaItem.attributes[attrs[i]] = {}; 2979 schemaItem.attributesOrder.push(attrs[i]); 2980 } 2981 } 2982 }; 2983 if (lookupCache[type]) { 2984 return lookupCache[type]; 2985 } 2986 globalAttributes = 'id accesskey class dir lang style tabindex title role'; 2987 blockContent = 'address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul'; 2988 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'; 2989 if (type !== 'html4') { 2990 const transparentContent = 'a ins del canvas map'; 2991 globalAttributes += ' contenteditable contextmenu draggable dropzone ' + 'hidden spellcheck translate'; 2992 blockContent += ' article aside details dialog figure main header footer hgroup section nav ' + transparentContent; 2993 phrasingContent += ' audio canvas command datalist mark meter output picture ' + 'progress time wbr video ruby bdi keygen'; 2994 } 2995 if (type !== 'html5-strict') { 2996 globalAttributes += ' xml:lang'; 2997 const html4PhrasingContent = 'acronym applet basefont big font strike tt'; 2998 phrasingContent = [ 2999 phrasingContent, 3000 html4PhrasingContent 3001 ].join(' '); 3002 each$b(split$1(html4PhrasingContent), name => { 3003 add(name, '', phrasingContent); 3004 }); 3005 const html4BlockContent = 'center dir isindex noframes'; 3006 blockContent = [ 3007 blockContent, 3008 html4BlockContent 3009 ].join(' '); 3010 flowContent = [ 3011 blockContent, 3012 phrasingContent 3013 ].join(' '); 3014 each$b(split$1(html4BlockContent), name => { 3015 add(name, '', flowContent); 3016 }); 3017 } 3018 flowContent = flowContent || [ 3019 blockContent, 3020 phrasingContent 3021 ].join(' '); 3022 add('html', 'manifest', 'head body'); 3023 add('head', '', 'base command link meta noscript script style title'); 3024 add('title hr noscript br'); 3025 add('base', 'href target'); 3026 add('link', 'href rel media hreflang type sizes hreflang'); 3027 add('meta', 'name http-equiv content charset'); 3028 add('style', 'media type scoped'); 3029 add('script', 'src async defer type charset'); 3030 add('body', 'onafterprint onbeforeprint onbeforeunload onblur onerror onfocus ' + 'onhashchange onload onmessage onoffline ononline onpagehide onpageshow ' + 'onpopstate onresize onscroll onstorage onunload', flowContent); 3031 add('
3031address dt dd div caption', '', flowContent); 3032 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); 3033 add('blockquote', 'cite', flowContent); 3034 add('ol', 'reversed start type', 'li'); 3035 add('ul', '', 'li'); 3036 add('li', 'value', flowContent); 3037 add('dl', '', 'dt dd'); 3038 add('a', 'href target rel media hreflang type',
vendor: 19,399 bytes, lines 3038-3466
3038 flowContent); 3039 add('q', 'cite', phrasingContent); 3040 add('ins del', 'cite datetime', flowContent); 3041 add('img', 'src sizes srcset alt usemap ismap width height'); 3042 add('iframe', 'src name width height', flowContent); 3043 add('embed', 'src type width height'); 3044 add('object', 'data type typemustmatch name usemap form width height', [ 3045 flowContent, 3046 'param' 3047 ].join(' ')); 3048 add('param', 'name value'); 3049 add('map', 'name', [ 3050 flowContent, 3051 'area' 3052 ].join(' ')); 3053 add('area', 'alt coords shape href target rel media hreflang type'); 3054 add('table', 'border', 'caption colgroup thead tfoot tbody tr' + (type === 'html4' ? ' col' : '')); 3055 add('colgroup', 'span', 'col'); 3056 add('col', 'span'); 3057 add('tbody thead tfoot', '', 'tr'); 3058 add('tr', '', 'td th'); 3059 add('td', 'colspan rowspan headers', flowContent); 3060 add('th', 'colspan rowspan headers scope abbr', flowContent); 3061 add('form', 'accept-charset action autocomplete enctype method name novalidate target', flowContent); 3062 add('fieldset', 'disabled form name', [ 3063 flowContent, 3064 'legend' 3065 ].join(' ')); 3066 add('label', 'form for', phrasingContent); 3067 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'); 3068 add('button', 'disabled form formaction formenctype formmethod formnovalidate formtarget name type value', type === 'html4' ? flowContent : phrasingContent); 3069 add('select', 'disabled form multiple name required size', 'option optgroup'); 3070 add('optgroup', 'disabled label', 'option'); 3071 add('option', 'disabled label selected value'); 3072 add('textarea', 'cols dirname disabled form maxlength name readonly required rows wrap'); 3073 add('menu', 'type label', [ 3074 flowContent, 3075 'li' 3076 ].join(' ')); 3077 add('noscript', '', flowContent); 3078 if (type !== 'html4') { 3079 add('wbr'); 3080 add('ruby', '', [ 3081 phrasingContent, 3082 'rt rp' 3083 ].join(' ')); 3084 add('figcaption', '', flowContent); 3085 add('mark rt rp summary bdi', '', phrasingContent); 3086 add('canvas', 'width height', flowContent); 3087 add('video', 'src crossorigin poster preload autoplay mediagroup loop ' + 'muted controls width height buffered', [ 3088 flowContent, 3089 'track source' 3090 ].join(' ')); 3091 add('audio', 'src crossorigin preload autoplay mediagroup loop muted controls ' + 'buffered volume', [ 3092 flowContent, 3093 'track source' 3094 ].join(' ')); 3095 add('picture', '', 'img source'); 3096 add('source', 'src srcset type media sizes'); 3097 add('track', 'kind src srclang label default'); 3098 add('datalist', '', [ 3099 phrasingContent, 3100 'option' 3101 ].join(' ')); 3102 add('article section nav aside main header footer', '', flowContent); 3103 add('hgroup', '', 'h1 h2 h3 h4 h5 h6'); 3104 add('figure', '', [ 3105 flowContent, 3106 'figcaption' 3107 ].join(' ')); 3108 add('time', 'datetime', phrasingContent); 3109 add('dialog', 'open', flowContent); 3110 add('command', 'type label icon disabled checked radiogroup command'); 3111 add('output', 'for form name', phrasingContent); 3112 add('progress', 'value max', phrasingContent); 3113 add('meter', 'value min max low high optimum', phrasingContent); 3114 add('details', 'open', [ 3115 flowContent, 3116 'summary' 3117 ].join(' ')); 3118 add('keygen', 'autofocus challenge disabled form keytype name'); 3119 } 3120 if (type !== 'html5-strict') { 3121 addAttrs('script', 'language xml:space'); 3122 addAttrs('style', 'xml:space'); 3123 addAttrs('object', 'declare classid code codebase codetype archive standby align border hspace vspace'); 3124 addAttrs('embed', 'align name hspace vspace'); 3125 addAttrs('param', 'valuetype type'); 3126 addAttrs('a', 'charset name rev shape coords'); 3127 addAttrs('br', 'clear'); 3128 addAttrs('applet', 'codebase archive code object alt name width height align hspace vspace'); 3129 addAttrs('img', 'name longdesc align border hspace vspace'); 3130 addAttrs('iframe', 'longdesc frameborder marginwidth marginheight scrolling align'); 3131 addAttrs('font basefont', 'size color face'); 3132 addAttrs('input', 'usemap align'); 3133 addAttrs('select'); 3134 addAttrs('textarea'); 3135 addAttrs('h1 h2 h3 h4 h5 h6 div p legend caption', 'align'); 3136 addAttrs('ul', 'type compact'); 3137 addAttrs('li', 'type'); 3138 addAttrs('ol dl menu dir', 'compact'); 3139 addAttrs('pre', 'width xml:space'); 3140 addAttrs('hr', 'align noshade size width'); 3141 addAttrs('isindex', 'prompt'); 3142 addAttrs('table', 'summary width frame rules cellspacing cellpadding align bgcolor'); 3143 addAttrs('col', 'width align char charoff valign'); 3144 addAttrs('colgroup', 'width align char charoff valign'); 3145 addAttrs('thead', 'align char charoff valign'); 3146 addAttrs('tr', 'align char charoff valign bgcolor'); 3147 addAttrs('th', 'axis align char charoff valign nowrap bgcolor width height'); 3148 addAttrs('form', 'accept'); 3149 addAttrs('td', 'abbr axis scope align char charoff valign nowrap bgcolor width height'); 3150 addAttrs('tfoot', 'align char charoff valign'); 3151 addAttrs('tbody', 'align char charoff valign'); 3152 addAttrs('area', 'nohref'); 3153 addAttrs('body', 'background bgcolor text link vlink alink'); 3154 } 3155 if (type !== 'html4') { 3156 addAttrs('input button select textarea', 'autofocus'); 3157 addAttrs('input textarea', 'placeholder'); 3158 addAttrs('a', 'download'); 3159 addAttrs('link script img', 'crossorigin'); 3160 addAttrs('img', 'loading'); 3161 addAttrs('iframe', 'sandbox seamless allow allowfullscreen loading'); 3162 } 3163 if (type !== 'html4') { 3164 each$e([ 3165 schema.video, 3166 schema.audio 3167 ], item => { 3168 delete item.children.audio; 3169 delete item.children.video; 3170 }); 3171 } 3172 each$b(split$1('a form meter progress dfn'), name => { 3173 if (schema[name]) { 3174 delete schema[name].children[name]; 3175 } 3176 }); 3177 delete schema.caption.children.table; 3178 delete schema.script; 3179 lookupCache[type] = schema; 3180 return schema; 3181 }; 3182 const compileElementMap = (value, mode) => { 3183 if (value) { 3184 const styles = {}; 3185 if (isString(value)) { 3186 value = { '*': value }; 3187 } 3188 each$b(value, (value, key) => { 3189 styles[key] = styles[key.toUpperCase()] = mode === 'map' ? makeMap$2(value, /[, ]/) : explode$2(value, /[, ]/); 3190 }); 3191 return styles; 3192 } else { 3193 return undefined; 3194 } 3195 }; 3196 const Schema = (settings = {}) => { 3197 var _a; 3198 const elements = {}; 3199 const children = {}; 3200 let patternElements = []; 3201 const customElementsMap = {}; 3202 const specialElements = {}; 3203 const createLookupTable = (option, defaultValue, extendWith) => { 3204 const value = settings[option]; 3205 if (!value) { 3206 let newValue = mapCache[option]; 3207 if (!newValue) { 3208 newValue = createMap(defaultValue, extendWith); 3209 mapCache[option] = newValue; 3210 } 3211 return newValue; 3212 } else { 3213 return makeMap$2(value, /[, ]/, makeMap$2(value.toUpperCase(), /[, ]/)); 3214 } 3215 }; 3216 const schemaType = (_a = settings.schema) !== null && _a !== void 0 ? _a : 'html5'; 3217 const schemaItems = compileSchema(schemaType); 3218 if (settings.verify_html === false) { 3219 settings.valid_elements = '*[*]'; 3220 } 3221 const validStyles = compileElementMap(settings.valid_styles); 3222 const invalidStyles = compileElementMap(settings.invalid_styles, 'map'); 3223 const validClasses = compileElementMap(settings.valid_classes, 'map'); 3224 const whitespaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea video audio iframe object code'); 3225 const selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr'); 3226 const voidElementsMap = createLookupTable('void_elements', 'area base basefont br col frame hr img input isindex link ' + 'meta param embed source wbr track'); 3227 const boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize ' + 'noshade nowrap readonly selected autoplay loop controls allowfullscreen'); 3228 const nonEmptyOrMoveCaretBeforeOnEnter = 'td th iframe video audio object script code'; 3229 const nonEmptyElementsMap = createLookupTable('non_empty_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' pre', voidElementsMap); 3230 const moveCaretBeforeOnEnterElementsMap = createLookupTable('move_caret_before_on_enter_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' table', voidElementsMap); 3231 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'); 3232 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); 3233 const textInlineElementsMap = createLookupTable('text_inline_elements', 'span strong b em i font s strike u var cite ' + 'dfn code mark q sup sub samp'); 3234 const transparentElementsMap = createLookupTable('transparent_elements', 'a ins del canvas map'); 3235 each$b('script noscript iframe noframes noembed title style textarea xmp plaintext'.split(' '), name => { 3236 specialElements[name] = new RegExp('</' + name + '[^>]*>', 'gi'); 3237 }); 3238 const patternToRegExp = str => new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$'); 3239 const addValidElements = validElements => { 3240 const elementRuleRegExp = /^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)])?$/; 3241 const attrRuleRegExp = /^([!\-])?(\w+[\\:]:\w+|[^=~<]+)?(?:([=~<])(.*))?$/; 3242 const hasPatternsRegExp = /[*?+]/; 3243 if (validElements) { 3244 const validElementsArr = split$1(validElements, ','); 3245 let globalAttributes; 3246 let globalAttributesOrder; 3247 if (elements['@']) { 3248 globalAttributes = elements['@'].attributes; 3249 globalAttributesOrder = elements['@'].attributesOrder; 3250 } 3251 for (let ei = 0, el = validElementsArr.length; ei < el; ei++) { 3252 let matches = elementRuleRegExp.exec(validElementsArr[ei]); 3253 if (matches) { 3254 const prefix = matches[1]; 3255 const elementName = matches[2]; 3256 const outputName = matches[3]; 3257 const attrData = matches[5]; 3258 const attributes = {}; 3259 const attributesOrder = []; 3260 const element = { 3261 attributes, 3262 attributesOrder 3263 }; 3264 if (prefix === '#') { 3265 element.paddEmpty = true; 3266 } 3267 if (prefix === '-') { 3268 element.removeEmpty = true; 3269 } 3270 if (matches[4] === '!') { 3271 element.removeEmptyAttrs = true; 3272 } 3273 if (globalAttributes) { 3274 each$d(globalAttributes, (value, key) => { 3275 attributes[key] = value; 3276 }); 3277 if (globalAttributesOrder) { 3278 attributesOrder.push(...globalAttributesOrder); 3279 } 3280 } 3281 if (attrData) { 3282 const attrDatas = split$1(attrData, '|'); 3283 for (let ai = 0, al = attrDatas.length; ai < al; ai++) { 3284 matches = attrRuleRegExp.exec(attrDatas[ai]); 3285 if (matches) { 3286 const attr = {}; 3287 const attrType = matches[1]; 3288 const attrName = matches[2].replace(/[\\:]:/g, ':'); 3289 const attrPrefix = matches[3]; 3290 const value = matches[4]; 3291 if (attrType === '!') { 3292 element.attributesRequired = element.attributesRequired || []; 3293 element.attributesRequired.push(attrName); 3294 attr.required = true; 3295 } 3296 if (attrType === '-') { 3297 delete attributes[attrName]; 3298 attributesOrder.splice(inArray(attributesOrder, attrName), 1); 3299 continue; 3300 } 3301 if (attrPrefix) { 3302 if (attrPrefix === '=') { 3303 element.attributesDefault = element.attributesDefault || []; 3304 element.attributesDefault.push({ 3305 name: attrName, 3306 value 3307 }); 3308 attr.defaultValue = value; 3309 } 3310 if (attrPrefix === '~') { 3311 element.attributesForced = element.attributesForced || []; 3312 element.attributesForced.push({ 3313 name: attrName, 3314 value 3315 }); 3316 attr.forcedValue = value; 3317 } 3318 if (attrPrefix === '<') { 3319 attr.validValues = makeMap$2(value, '?'); 3320 } 3321 } 3322 if (hasPatternsRegExp.test(attrName)) { 3323 const attrPattern = attr; 3324 element.attributePatterns = element.attributePatterns || []; 3325 attrPattern.pattern = patternToRegExp(attrName); 3326 element.attributePatterns.push(attrPattern); 3327 } else { 3328 if (!attributes[attrName]) { 3329 attributesOrder.push(attrName); 3330 } 3331 attributes[attrName] = attr; 3332 } 3333 } 3334 } 3335 } 3336 if (!globalAttributes && elementName === '@') { 3337 globalAttributes = attributes; 3338 globalAttributesOrder = attributesOrder; 3339 } 3340 if (outputName) { 3341 element.outputName = elementName; 3342 elements[outputName] = element; 3343 } 3344 if (hasPatternsRegExp.test(elementName)) { 3345 const patternElement = element; 3346 patternElement.pattern = patternToRegExp(elementName); 3347 patternElements.push(patternElement); 3348 } else { 3349 elements[elementName] = element; 3350 } 3351 } 3352 } 3353 } 3354 }; 3355 const setValidElements = validElements => { 3356 patternElements = []; 3357 each$e(keys(elements), name => { 3358 delete elements[name]; 3359 }); 3360 addValidElements(validElements); 3361 each$b(schemaItems, (element, name) => { 3362 children[name] = element.children; 3363 }); 3364 }; 3365 const addCustomElements = customElements => { 3366 const customElementRegExp = /^(~)?(.+)$/; 3367 if (customElements) { 3368 delete mapCache.text_block_elements; 3369 delete mapCache.block_elements; 3370 each$b(split$1(customElements, ','), rule => { 3371 const matches = customElementRegExp.exec(rule); 3372 if (matches) { 3373 const inline = matches[1] === '~'; 3374 const cloneName = inline ? 'span' : 'div'; 3375 const name = matches[2]; 3376 children[name] = children[cloneName]; 3377 customElementsMap[name] = cloneName; 3378 nonEmptyElementsMap[name.toUpperCase()] = {}; 3379 nonEmptyElementsMap[name] = {}; 3380 if (!inline) { 3381 blockElementsMap[name.toUpperCase()] = {}; 3382 blockElementsMap[name] = {}; 3383 } 3384 if (!elements[name]) { 3385 let customRule = elements[cloneName]; 3386 customRule = extend$2({}, customRule); 3387 delete customRule.removeEmptyAttrs; 3388 delete customRule.removeEmpty; 3389 elements[name] = customRule; 3390 } 3391 each$b(children, (element, elmName) => { 3392 if (element[cloneName]) { 3393 children[elmName] = element = extend$2({}, children[elmName]); 3394 element[name] = element[cloneName]; 3395 } 3396 }); 3397 } 3398 }); 3399 } 3400 }; 3401 const addValidChildren = validChildren => { 3402 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]+)\[([^\]]+)]$/; 3403 delete lookupCache[schemaType]; 3404 if (validChildren) { 3405 each$b(split$1(validChildren, ','), rule => { 3406 const matches = childRuleRegExp.exec(rule); 3407 if (matches) { 3408 const prefix = matches[1]; 3409 let parent; 3410 if (prefix) { 3411 parent = children[matches[2]]; 3412 } else { 3413 parent = children[matches[2]] = { '#comment': {} }; 3414 } 3415 parent = children[matches[2]]; 3416 each$b(split$1(matches[3], '|'), child => { 3417 if (prefix === '-') { 3418 delete parent[child]; 3419 } else { 3420 parent[child] = {}; 3421 } 3422 }); 3423 } 3424 }); 3425 } 3426 }; 3427 const getElementRule = name => { 3428 const element = elements[name]; 3429 if (element) { 3430 return element; 3431 } 3432 let i = patternElements.length; 3433 while (i--) { 3434 const patternElement = patternElements[i]; 3435 if (patternElement.pattern.test(name)) { 3436 return patternElement; 3437 } 3438 } 3439 return undefined; 3440 }; 3441 if (!settings.valid_elements) { 3442 each$b(schemaItems, (element, name) => { 3443 elements[name] = { 3444 attributes: element.attributes, 3445 attributesOrder: element.attributesOrder 3446 }; 3447 children[name] = element.children; 3448 }); 3449 each$b(split$1('strong/b em/i'), item => { 3450 const items = split$1(item, '/'); 3451 elements[items[1]].outputName = items[0]; 3452 }); 3453 each$b(textInlineElementsMap, (_val, name) => { 3454 if (elements[name]) { 3455 if (settings.padd_empty_block_inline_children) { 3456 elements[name].paddInEmptyBlock = true; 3457 } 3458 elements[name].removeEmpty = true; 3459 } 3460 }); 3461 each$b(split$1('ol ul blockquote a table tbody'), name => { 3462 if (elements[name]) { 3463 elements[name].removeEmpty = true; 3464 } 3465 }); 3466 each$b(split$1('p h1 h2 h3 h4 h5 h6 th td pre div address caption li
3466'), name => { 3467 elements[name].paddEmpty = true;
vendor: 23,235 bytes, lines 3467-4113
3467 3468 }); 3469 each$b(split$1('span'), name => { 3470 elements[name].removeEmptyAttrs = true; 3471 }); 3472 } else { 3473 setValidElements(settings.valid_elements); 3474 } 3475 addCustomElements(settings.custom_elements); 3476 addValidChildren(settings.valid_children); 3477 addValidElements(settings.extended_valid_elements); 3478 addValidChildren('+ol[ul|ol],+ul[ul|ol]'); 3479 each$b({ 3480 dd: 'dl', 3481 dt: 'dl', 3482 li: 'ul ol', 3483 td: 'tr', 3484 th: 'tr', 3485 tr: 'tbody thead tfoot', 3486 tbody: 'table', 3487 thead: 'table', 3488 tfoot: 'table', 3489 legend: 'fieldset', 3490 area: 'map', 3491 param: 'video audio object' 3492 }, (parents, item) => { 3493 if (elements[item]) { 3494 elements[item].parentsRequired = split$1(parents); 3495 } 3496 }); 3497 if (settings.invalid_elements) { 3498 each$b(explode$2(settings.invalid_elements), item => { 3499 if (elements[item]) { 3500 delete elements[item]; 3501 } 3502 }); 3503 } 3504 if (!getElementRule('span')) { 3505 addValidElements('span[!data-mce-type|*]'); 3506 } 3507 const getValidStyles = constant(validStyles); 3508 const getInvalidStyles = constant(invalidStyles); 3509 const getValidClasses = constant(validClasses); 3510 const getBoolAttrs = constant(boolAttrMap); 3511 const getBlockElements = constant(blockElementsMap); 3512 const getTextBlockElements = constant(textBlockElementsMap); 3513 const getTextInlineElements = constant(textInlineElementsMap); 3514 const getVoidElements = constant(Object.seal(voidElementsMap)); 3515 const getSelfClosingElements = constant(selfClosingElementsMap); 3516 const getNonEmptyElements = constant(nonEmptyElementsMap); 3517 const getMoveCaretBeforeOnEnterElements = constant(moveCaretBeforeOnEnterElementsMap); 3518 const getWhitespaceElements = constant(whitespaceElementsMap); 3519 const getTransparentElements = constant(transparentElementsMap); 3520 const getSpecialElements = constant(Object.seal(specialElements)); 3521 const isValidChild = (name, child) => { 3522 const parent = children[name.toLowerCase()]; 3523 return !!(parent && parent[child.toLowerCase()]); 3524 }; 3525 const isValid = (name, attr) => { 3526 const rule = getElementRule(name); 3527 if (rule) { 3528 if (attr) { 3529 if (rule.attributes[attr]) { 3530 return true; 3531 } 3532 const attrPatterns = rule.attributePatterns; 3533 if (attrPatterns) { 3534 let i = attrPatterns.length; 3535 while (i--) { 3536 if (attrPatterns[i].pattern.test(attr)) { 3537 return true; 3538 } 3539 } 3540 } 3541 } else { 3542 return true; 3543 } 3544 } 3545 return false; 3546 }; 3547 const getCustomElements = constant(customElementsMap); 3548 return { 3549 type: schemaType, 3550 children, 3551 elements, 3552 getValidStyles, 3553 getValidClasses, 3554 getBlockElements, 3555 getInvalidStyles, 3556 getVoidElements, 3557 getTextBlockElements, 3558 getTextInlineElements, 3559 getBoolAttrs, 3560 getElementRule, 3561 getSelfClosingElements, 3562 getNonEmptyElements, 3563 getMoveCaretBeforeOnEnterElements, 3564 getWhitespaceElements, 3565 getTransparentElements, 3566 getSpecialElements, 3567 isValidChild, 3568 isValid, 3569 getCustomElements, 3570 addValidElements, 3571 setValidElements, 3572 addCustomElements, 3573 addValidChildren 3574 }; 3575 }; 3576 3577 const Styles = (settings = {}, schema) => { 3578 const urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi; 3579 const styleRegExp = /\s*([^:]+):\s*([^;]+);?/g; 3580 const trimRightRegExp = /\s+$/; 3581 const encodingLookup = {}; 3582 let validStyles; 3583 let invalidStyles; 3584 const invisibleChar = zeroWidth; 3585 if (schema) { 3586 validStyles = schema.getValidStyles(); 3587 invalidStyles = schema.getInvalidStyles(); 3588 } 3589 const encodingItems = (`\\" \\' \\; \\: ; : ` + invisibleChar).split(' '); 3590 for (let i = 0; i < encodingItems.length; i++) { 3591 encodingLookup[encodingItems[i]] = invisibleChar + i; 3592 encodingLookup[invisibleChar + i] = encodingItems[i]; 3593 } 3594 const self = { 3595 parse: css => { 3596 const styles = {}; 3597 let isEncoded = false; 3598 const urlConverter = settings.url_converter; 3599 const urlConverterScope = settings.url_converter_scope || self; 3600 const compress = (prefix, suffix, noJoin) => { 3601 const top = styles[prefix + '-top' + suffix]; 3602 if (!top) { 3603 return; 3604 } 3605 const right = styles[prefix + '-right' + suffix]; 3606 if (!right) { 3607 return; 3608 } 3609 const bottom = styles[prefix + '-bottom' + suffix]; 3610 if (!bottom) { 3611 return; 3612 } 3613 const left = styles[prefix + '-left' + suffix]; 3614 if (!left) { 3615 return; 3616 } 3617 const box = [ 3618 top, 3619 right, 3620 bottom, 3621 left 3622 ]; 3623 let i = box.length - 1; 3624 while (i--) { 3625 if (box[i] !== box[i + 1]) { 3626 break; 3627 } 3628 } 3629 if (i > -1 && noJoin) { 3630 return; 3631 } 3632 styles[prefix + suffix] = i === -1 ? box[0] : box.join(' '); 3633 delete styles[prefix + '-top' + suffix]; 3634 delete styles[prefix + '-right' + suffix]; 3635 delete styles[prefix + '-bottom' + suffix]; 3636 delete styles[prefix + '-left' + suffix]; 3637 }; 3638 const canCompress = key => { 3639 const value = styles[key]; 3640 if (!value) { 3641 return; 3642 } 3643 const values = value.split(' '); 3644 let i = values.length; 3645 while (i--) { 3646 if (values[i] !== values[0]) { 3647 return false; 3648 } 3649 } 3650 styles[key] = values[0]; 3651 return true; 3652 }; 3653 const compress2 = (target, a, b, c) => { 3654 if (!canCompress(a)) { 3655 return; 3656 } 3657 if (!canCompress(b)) { 3658 return; 3659 } 3660 if (!canCompress(c)) { 3661 return; 3662 } 3663 styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c]; 3664 delete styles[a]; 3665 delete styles[b]; 3666 delete styles[c]; 3667 }; 3668 const encode = str => { 3669 isEncoded = true; 3670 return encodingLookup[str]; 3671 }; 3672 const decode = (str, keepSlashes) => { 3673 if (isEncoded) { 3674 str = str.replace(/\uFEFF[0-9]/g, str => { 3675 return encodingLookup[str]; 3676 }); 3677 } 3678 if (!keepSlashes) { 3679 str = str.replace(/\\([\'\";:])/g, '$1'); 3680 } 3681 return str; 3682 }; 3683 const decodeSingleHexSequence = escSeq => { 3684 return String.fromCharCode(parseInt(escSeq.slice(1), 16)); 3685 }; 3686 const decodeHexSequences = value => { 3687 return value.replace(/\\[0-9a-f]+/gi, decodeSingleHexSequence); 3688 }; 3689 const processUrl = (match, url, url2, url3, str, str2) => { 3690 str = str || str2; 3691 if (str) { 3692 str = decode(str); 3693 return `'` + str.replace(/\'/g, `\\'`) + `'`; 3694 } 3695 url = decode(url || url2 || url3 || ''); 3696 if (!settings.allow_script_urls) { 3697 const scriptUrl = url.replace(/[\s\r\n]+/g, ''); 3698 if (/(java|vb)script:/i.test(scriptUrl)) { 3699 return ''; 3700 } 3701 if (!settings.allow_svg_data_urls && /^data:image\/svg/i.test(scriptUrl)) { 3702 return ''; 3703 } 3704 } 3705 if (urlConverter) { 3706 url = urlConverter.call(urlConverterScope, url, 'style'); 3707 } 3708 return `url('` + url.replace(/\'/g, `\\'`) + `')`; 3709 }; 3710 if (css) { 3711 css = css.replace(/[\u0000-\u001F]/g, ''); 3712 css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, str => { 3713 return str.replace(/[;:]/g, encode); 3714 }); 3715 let matches; 3716 while (matches = styleRegExp.exec(css)) { 3717 styleRegExp.lastIndex = matches.index + matches[0].length; 3718 let name = matches[1].replace(trimRightRegExp, '').toLowerCase(); 3719 let value = matches[2].replace(trimRightRegExp, ''); 3720 if (name && value) { 3721 name = decodeHexSequences(name); 3722 value = decodeHexSequences(value); 3723 if (name.indexOf(invisibleChar) !== -1 || name.indexOf('"') !== -1) { 3724 continue; 3725 } 3726 if (!settings.allow_script_urls && (name === 'behavior' || /expression\s*\(|\/\*|\*\//.test(value))) { 3727 continue; 3728 } 3729 if (name === 'font-weight' && value === '700') { 3730 value = 'bold'; 3731 } else if (name === 'color' || name === 'background-color') { 3732 value = value.toLowerCase(); 3733 } 3734 value = value.replace(urlOrStrRegExp, processUrl); 3735 styles[name] = isEncoded ? decode(value, true) : value; 3736 } 3737 } 3738 compress('border', '', true); 3739 compress('border', '-width'); 3740 compress('border', '-color'); 3741 compress('border', '-style'); 3742 compress('padding', ''); 3743 compress('margin', ''); 3744 compress2('border', 'border-width', 'border-style', 'border-color'); 3745 if (styles.border === 'medium none') { 3746 delete styles.border; 3747 } 3748 if (styles['border-image'] === 'none') { 3749 delete styles['border-image']; 3750 } 3751 } 3752 return styles; 3753 }, 3754 serialize: (styles, elementName) => { 3755 let css = ''; 3756 const serializeStyles = (elemName, validStyleList) => { 3757 const styleList = validStyleList[elemName]; 3758 if (styleList) { 3759 for (let i = 0, l = styleList.length; i < l; i++) { 3760 const name = styleList[i]; 3761 const value = styles[name]; 3762 if (value) { 3763 css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; 3764 } 3765 } 3766 } 3767 }; 3768 const isValid = (name, elemName) => { 3769 if (!invalidStyles || !elemName) { 3770 return true; 3771 } 3772 let styleMap = invalidStyles['*']; 3773 if (styleMap && styleMap[name]) { 3774 return false; 3775 } 3776 styleMap = invalidStyles[elemName]; 3777 return !(styleMap && styleMap[name]); 3778 }; 3779 if (elementName && validStyles) { 3780 serializeStyles('*', validStyles); 3781 serializeStyles(elementName, validStyles); 3782 } else { 3783 each$d(styles, (value, name) => { 3784 if (value && isValid(name, elementName)) { 3785 css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; 3786 } 3787 }); 3788 } 3789 return css; 3790 } 3791 }; 3792 return self; 3793 }; 3794 3795 const deprecated = { 3796 keyLocation: true, 3797 layerX: true, 3798 layerY: true, 3799 returnValue: true, 3800 webkitMovementX: true, 3801 webkitMovementY: true, 3802 keyIdentifier: true, 3803 mozPressure: true 3804 }; 3805 const isNativeEvent = event => event instanceof Event || isFunction(event.initEvent); 3806 const hasIsDefaultPrevented = event => event.isDefaultPrevented === always || event.isDefaultPrevented === never; 3807 const needsNormalizing = event => isNullable(event.preventDefault) || isNativeEvent(event); 3808 const clone$3 = (originalEvent, data) => { 3809 const event = data !== null && data !== void 0 ? data : {}; 3810 for (const name in originalEvent) { 3811 if (!has$2(deprecated, name)) { 3812 event[name] = originalEvent[name]; 3813 } 3814 } 3815 if (isNonNullable(originalEvent.composedPath)) { 3816 event.composedPath = () => originalEvent.composedPath(); 3817 } 3818 return event; 3819 }; 3820 const normalize$3 = (type, originalEvent, fallbackTarget, data) => { 3821 var _a; 3822 const event = clone$3(originalEvent, data); 3823 event.type = type; 3824 if (isNullable(event.target)) { 3825 event.target = (_a = event.srcElement) !== null && _a !== void 0 ? _a : fallbackTarget; 3826 } 3827 if (needsNormalizing(originalEvent)) { 3828 event.preventDefault = () => { 3829 event.defaultPrevented = true; 3830 event.isDefaultPrevented = always; 3831 if (isFunction(originalEvent.preventDefault)) { 3832 originalEvent.preventDefault(); 3833 } 3834 }; 3835 event.stopPropagation = () => { 3836 event.cancelBubble = true; 3837 event.isPropagationStopped = always; 3838 if (isFunction(originalEvent.stopPropagation)) { 3839 originalEvent.stopPropagation(); 3840 } 3841 }; 3842 event.stopImmediatePropagation = () => { 3843 event.isImmediatePropagationStopped = always; 3844 event.stopPropagation(); 3845 }; 3846 if (!hasIsDefaultPrevented(event)) { 3847 event.isDefaultPrevented = event.defaultPrevented === true ? always : never; 3848 event.isPropagationStopped = event.cancelBubble === true ? always : never; 3849 event.isImmediatePropagationStopped = never; 3850 } 3851 } 3852 return event; 3853 }; 3854 3855 const eventExpandoPrefix = 'mce-data-'; 3856 const mouseEventRe = /^(?:mouse|contextmenu)|click/; 3857 const addEvent = (target, name, callback, capture) => { 3858 target.addEventListener(name, callback, capture || false); 3859 }; 3860 const removeEvent = (target, name, callback, capture) => { 3861 target.removeEventListener(name, callback, capture || false); 3862 }; 3863 const isMouseEvent = event => isNonNullable(event) && mouseEventRe.test(event.type); 3864 const fix = (originalEvent, data) => { 3865 const event = normalize$3(originalEvent.type, originalEvent, document, data); 3866 if (isMouseEvent(originalEvent) && isUndefined(originalEvent.pageX) && !isUndefined(originalEvent.clientX)) { 3867 const eventDoc = event.target.ownerDocument || document; 3868 const doc = eventDoc.documentElement; 3869 const body = eventDoc.body; 3870 const mouseEvent = event; 3871 mouseEvent.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); 3872 mouseEvent.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); 3873 } 3874 return event; 3875 }; 3876 const bindOnReady = (win, callback, eventUtils) => { 3877 const doc = win.document, event = { type: 'ready' }; 3878 if (eventUtils.domLoaded) { 3879 callback(event); 3880 return; 3881 } 3882 const isDocReady = () => { 3883 return doc.readyState === 'complete' || doc.readyState === 'interactive' && doc.body; 3884 }; 3885 const readyHandler = () => { 3886 removeEvent(win, 'DOMContentLoaded', readyHandler); 3887 removeEvent(win, 'load', readyHandler); 3888 if (!eventUtils.domLoaded) { 3889 eventUtils.domLoaded = true; 3890 callback(event); 3891 } 3892 win = null; 3893 }; 3894 if (isDocReady()) { 3895 readyHandler(); 3896 } else { 3897 addEvent(win, 'DOMContentLoaded', readyHandler); 3898 } 3899 if (!eventUtils.domLoaded) { 3900 addEvent(win, 'load', readyHandler); 3901 } 3902 }; 3903 class EventUtils { 3904 constructor() { 3905 this.domLoaded = false; 3906 this.events = {}; 3907 this.count = 1; 3908 this.expando = eventExpandoPrefix + (+new Date()).toString(32); 3909 this.hasFocusIn = 'onfocusin' in document.documentElement; 3910 this.count = 1; 3911 } 3912 bind(target, names, callback, scope) { 3913 const self = this; 3914 let callbackList; 3915 const win = window; 3916 const defaultNativeHandler = evt => { 3917 self.executeHandlers(fix(evt || win.event), id); 3918 }; 3919 if (!target || isText$a(target) || isComment(target)) { 3920 return callback; 3921 } 3922 let id; 3923 if (!target[self.expando]) { 3924 id = self.count++; 3925 target[self.expando] = id; 3926 self.events[id] = {}; 3927 } else { 3928 id = target[self.expando]; 3929 } 3930 scope = scope || target; 3931 const namesList = names.split(' '); 3932 let i = namesList.length; 3933 while (i--) { 3934 let name = namesList[i]; 3935 let nativeHandler = defaultNativeHandler; 3936 let capture = false; 3937 let fakeName = false; 3938 if (name === 'DOMContentLoaded') { 3939 name = 'ready'; 3940 } 3941 if (self.domLoaded && name === 'ready' && target.readyState === 'complete') { 3942 callback.call(scope, fix({ type: name })); 3943 continue; 3944 } 3945 if (!self.hasFocusIn && (name === 'focusin' || name === 'focusout')) { 3946 capture = true; 3947 fakeName = name === 'focusin' ? 'focus' : 'blur'; 3948 nativeHandler = evt => { 3949 const event = fix(evt || win.event); 3950 event.type = event.type === 'focus' ? 'focusin' : 'focusout'; 3951 self.executeHandlers(event, id); 3952 }; 3953 } 3954 callbackList = self.events[id][name]; 3955 if (!callbackList) { 3956 self.events[id][name] = callbackList = [{ 3957 func: callback, 3958 scope 3959 }]; 3960 callbackList.fakeName = fakeName; 3961 callbackList.capture = capture; 3962 callbackList.nativeHandler = nativeHandler; 3963 if (name === 'ready') { 3964 bindOnReady(target, nativeHandler, self); 3965 } else { 3966 addEvent(target, fakeName || name, nativeHandler, capture); 3967 } 3968 } else { 3969 if (name === 'ready' && self.domLoaded) { 3970 callback(fix({ type: name })); 3971 } else { 3972 callbackList.push({ 3973 func: callback, 3974 scope 3975 }); 3976 } 3977 } 3978 } 3979 target = callbackList = null; 3980 return callback; 3981 } 3982 unbind(target, names, callback) { 3983 if (!target || isText$a(target) || isComment(target)) { 3984 return this; 3985 } 3986 const id = target[this.expando]; 3987 if (id) { 3988 let eventMap = this.events[id]; 3989 if (names) { 3990 const namesList = names.split(' '); 3991 let i = namesList.length; 3992 while (i--) { 3993 const name = namesList[i]; 3994 const callbackList = eventMap[name]; 3995 if (callbackList) { 3996 if (callback) { 3997 let ci = callbackList.length; 3998 while (ci--) { 3999 if (callbackList[ci].func === callback) { 4000 const nativeHandler = callbackList.nativeHandler; 4001 const fakeName = callbackList.fakeName, capture = callbackList.capture; 4002 const newCallbackList = callbackList.slice(0, ci).concat(callbackList.slice(ci + 1)); 4003 newCallbackList.nativeHandler = nativeHandler; 4004 newCallbackList.fakeName = fakeName; 4005 newCallbackList.capture = capture; 4006 eventMap[name] = newCallbackList; 4007 } 4008 } 4009 } 4010 if (!callback || callbackList.length === 0) { 4011 delete eventMap[name]; 4012 removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture); 4013 } 4014 } 4015 } 4016 } else { 4017 each$d(eventMap, (callbackList, name) => { 4018 removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture); 4019 }); 4020 eventMap = {}; 4021 } 4022 for (const name in eventMap) { 4023 if (has$2(eventMap, name)) { 4024 return this; 4025 } 4026 } 4027 delete this.events[id]; 4028 try { 4029 delete target[this.expando]; 4030 } catch (ex) { 4031 target[this.expando] = null; 4032 } 4033 } 4034 return this; 4035 } 4036 fire(target, name, args) { 4037 return this.dispatch(target, name, args); 4038 } 4039 dispatch(target, name, args) { 4040 if (!target || isText$a(target) || isComment(target)) { 4041 return this; 4042 } 4043 const event = fix({ 4044 type: name, 4045 target 4046 }, args); 4047 do { 4048 const id = target[this.expando]; 4049 if (id) { 4050 this.executeHandlers(event, id); 4051 } 4052 target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow; 4053 } while (target && !event.isPropagationStopped()); 4054 return this; 4055 } 4056 clean(target) { 4057 if (!target || isText$a(target) || isComment(target)) { 4058 return this; 4059 } 4060 if (target[this.expando]) { 4061 this.unbind(target); 4062 } 4063 if (!target.getElementsByTagName) { 4064 target = target.document; 4065 } 4066 if (target && target.getElementsByTagName) { 4067 this.unbind(target); 4068 const children = target.getElementsByTagName('*'); 4069 let i = children.length; 4070 while (i--) { 4071 target = children[i]; 4072 if (target[this.expando]) { 4073 this.unbind(target); 4074 } 4075 } 4076 } 4077 return this; 4078 } 4079 destroy() { 4080 this.events = {}; 4081 } 4082 cancel(e) { 4083 if (e) { 4084 e.preventDefault(); 4085 e.stopImmediatePropagation(); 4086 } 4087 return false; 4088 } 4089 executeHandlers(evt, id) { 4090 const container = this.events[id]; 4091 const callbackList = container && container[evt.type]; 4092 if (callbackList) { 4093 for (let i = 0, l = callbackList.length; i < l; i++) { 4094 const callback = callbackList[i]; 4095 if (callback && callback.func.call(callback.scope, evt) === false) { 4096 evt.preventDefault(); 4097 } 4098 if (evt.isImmediatePropagationStopped()) { 4099 return; 4100 } 4101 } 4102 } 4103 } 4104 } 4105 EventUtils.Event = new EventUtils(); 4106 4107 const each$a = Tools.each; 4108 const grep = Tools.grep; 4109 const internalStyleName = 'data-mce-style'; 4110 const numericalCssMap = Tools.makeMap('fill-opacity font-weight line-height opacity orphans widows z-index zoom', ' '); 4111 const legacySetAttribute = (elm, name, value) => { 4112 if (isNullable(value) || value === '') { 4113 remove$
vendor: 24,236 bytes, lines 4113-4804
4113b(elm, name); 4114 } else { 4115 set$3(elm, name, value); 4116 } 4117 }; 4118 const camelCaseToHyphens = name => name.replace(/[A-Z]/g, v => '-' + v.toLowerCase()); 4119 const findNodeIndex = (node, normalized) => { 4120 let idx = 0; 4121 if (node) { 4122 for (let lastNodeType = node.nodeType, tempNode = node.previousSibling; tempNode; tempNode = tempNode.previousSibling) { 4123 const nodeType = tempNode.nodeType; 4124 if (normalized && isText$a(tempNode)) { 4125 if (nodeType === lastNodeType || !tempNode.data.length) { 4126 continue; 4127 } 4128 } 4129 idx++; 4130 lastNodeType = nodeType; 4131 } 4132 } 4133 return idx; 4134 }; 4135 const updateInternalStyleAttr = (styles, elm) => { 4136 const rawValue = get$9(elm, 'style'); 4137 const value = styles.serialize(styles.parse(rawValue), name(elm)); 4138 legacySetAttribute(elm, internalStyleName, value); 4139 }; 4140 const convertStyleToString = (cssValue, cssName) => { 4141 if (isNumber(cssValue)) { 4142 return has$2(numericalCssMap, cssName) ? cssValue + '' : cssValue + 'px'; 4143 } else { 4144 return cssValue; 4145 } 4146 }; 4147 const applyStyle$1 = ($elm, cssName, cssValue) => { 4148 const normalizedName = camelCaseToHyphens(cssName); 4149 if (isNullable(cssValue) || cssValue === '') { 4150 remove$7($elm, normalizedName); 4151 } else { 4152 set$2($elm, normalizedName, convertStyleToString(cssValue, normalizedName)); 4153 } 4154 }; 4155 const setupAttrHooks = (styles, settings, getContext) => { 4156 const keepValues = settings.keep_values; 4157 const keepUrlHook = { 4158 set: (elm, value, name) => { 4159 const sugarElm = SugarElement.fromDom(elm); 4160 if (isFunction(settings.url_converter) && isNonNullable(value)) { 4161 value = settings.url_converter.call(settings.url_converter_scope || getContext(), String(value), name, elm); 4162 } 4163 const internalName = 'data-mce-' + name; 4164 legacySetAttribute(sugarElm, internalName, value); 4165 legacySetAttribute(sugarElm, name, value); 4166 }, 4167 get: (elm, name) => { 4168 const sugarElm = SugarElement.fromDom(elm); 4169 return get$9(sugarElm, 'data-mce-' + name) || get$9(sugarElm, name); 4170 } 4171 }; 4172 const attrHooks = { 4173 style: { 4174 set: (elm, value) => { 4175 const sugarElm = SugarElement.fromDom(elm); 4176 if (keepValues) { 4177 legacySetAttribute(sugarElm, internalStyleName, value); 4178 } 4179 remove$b(sugarElm, 'style'); 4180 if (isString(value)) { 4181 setAll(sugarElm, styles.parse(value)); 4182 } 4183 }, 4184 get: elm => { 4185 const sugarElm = SugarElement.fromDom(elm); 4186 const value = get$9(sugarElm, internalStyleName) || get$9(sugarElm, 'style'); 4187 return styles.serialize(styles.parse(value), name(sugarElm)); 4188 } 4189 } 4190 }; 4191 if (keepValues) { 4192 attrHooks.href = attrHooks.src = keepUrlHook; 4193 } 4194 return attrHooks; 4195 }; 4196 const DOMUtils = (doc, settings = {}) => { 4197 const addedStyles = {}; 4198 const win = window; 4199 const files = {}; 4200 let counter = 0; 4201 const stdMode = true; 4202 const boxModel = true; 4203 const styleSheetLoader = instance.forElement(SugarElement.fromDom(doc), { 4204 contentCssCors: settings.contentCssCors, 4205 referrerPolicy: settings.referrerPolicy 4206 }); 4207 const boundEvents = []; 4208 const schema = settings.schema ? settings.schema : Schema({}); 4209 const styles = Styles({ 4210 url_converter: settings.url_converter, 4211 url_converter_scope: settings.url_converter_scope 4212 }, settings.schema); 4213 const events = settings.ownEvents ? new EventUtils() : EventUtils.Event; 4214 const blockElementsMap = schema.getBlockElements(); 4215 const isBlock = node => { 4216 if (isString(node)) { 4217 return has$2(blockElementsMap, node); 4218 } else { 4219 return isElement$6(node) && (has$2(blockElementsMap, node.nodeName) || isTransparentBlock(schema, node)); 4220 } 4221 }; 4222 const get = elm => elm && doc && isString(elm) ? doc.getElementById(elm) : elm; 4223 const _get = elm => { 4224 const value = get(elm); 4225 return isNonNullable(value) ? SugarElement.fromDom(value) : null; 4226 }; 4227 const getAttrib = (elm, name, defaultVal = '') => { 4228 let value; 4229 const $elm = _get(elm); 4230 if (isNonNullable($elm) && isElement$7($elm)) { 4231 const hook = attrHooks[name]; 4232 if (hook && hook.get) { 4233 value = hook.get($elm.dom, name); 4234 } else { 4235 value = get$9($elm, name); 4236 } 4237 } 4238 return isNonNullable(value) ? value : defaultVal; 4239 }; 4240 const getAttribs = elm => { 4241 const node = get(elm); 4242 return isNullable(node) ? [] : node.attributes; 4243 }; 4244 const setAttrib = (elm, name, value) => { 4245 run(elm, e => { 4246 if (isElement$6(e)) { 4247 const $elm = SugarElement.fromDom(e); 4248 const val = value === '' ? null : value; 4249 const originalValue = get$9($elm, name); 4250 const hook = attrHooks[name]; 4251 if (hook && hook.set) { 4252 hook.set($elm.dom, val, name); 4253 } else { 4254 legacySetAttribute($elm, name, val); 4255 } 4256 if (originalValue !== val && settings.onSetAttrib) { 4257 settings.onSetAttrib({ 4258 attrElm: $elm.dom, 4259 attrName: name, 4260 attrValue: val 4261 }); 4262 } 4263 } 4264 }); 4265 }; 4266 const clone = (node, deep) => { 4267 return node.cloneNode(deep); 4268 }; 4269 const getRoot = () => settings.root_element || doc.body; 4270 const getViewPort = argWin => { 4271 const vp = getBounds(argWin); 4272 return { 4273 x: vp.x, 4274 y: vp.y, 4275 w: vp.width, 4276 h: vp.height 4277 }; 4278 }; 4279 const getPos$1 = (elm, rootElm) => getPos(doc.body, get(elm), rootElm); 4280 const setStyle = (elm, name, value) => { 4281 run(elm, e => { 4282 const $elm = SugarElement.fromDom(e); 4283 applyStyle$1($elm, name, value); 4284 if (settings.update_styles) { 4285 updateInternalStyleAttr(styles, $elm); 4286 } 4287 }); 4288 }; 4289 const setStyles = (elm, stylesArg) => { 4290 run(elm, e => { 4291 const $elm = SugarElement.fromDom(e); 4292 each$d(stylesArg, (v, n) => { 4293 applyStyle$1($elm, n, v); 4294 }); 4295 if (settings.update_styles) { 4296 updateInternalStyleAttr(styles, $elm); 4297 } 4298 }); 4299 }; 4300 const getStyle = (elm, name, computed) => { 4301 const $elm = get(elm); 4302 if (isNullable($elm) || !isElement$6($elm)) { 4303 return undefined; 4304 } 4305 if (computed) { 4306 return get$7(SugarElement.fromDom($elm), camelCaseToHyphens(name)); 4307 } else { 4308 name = name.replace(/-(\D)/g, (a, b) => b.toUpperCase()); 4309 if (name === 'float') { 4310 name = 'cssFloat'; 4311 } 4312 return $elm.style ? $elm.style[name] : undefined; 4313 } 4314 }; 4315 const getSize = elm => { 4316 const $elm = get(elm); 4317 if (!$elm) { 4318 return { 4319 w: 0, 4320 h: 0 4321 }; 4322 } 4323 let w = getStyle($elm, 'width'); 4324 let h = getStyle($elm, 'height'); 4325 if (!w || w.indexOf('px') === -1) { 4326 w = '0'; 4327 } 4328 if (!h || h.indexOf('px') === -1) { 4329 h = '0'; 4330 } 4331 return { 4332 w: parseInt(w, 10) || $elm.offsetWidth || $elm.clientWidth, 4333 h: parseInt(h, 10) || $elm.offsetHeight || $elm.clientHeight 4334 }; 4335 }; 4336 const getRect = elm => { 4337 const $elm = get(elm); 4338 const pos = getPos$1($elm); 4339 const size = getSize($elm); 4340 return { 4341 x: pos.x, 4342 y: pos.y, 4343 w: size.w, 4344 h: size.h 4345 }; 4346 }; 4347 const is = (elm, selector) => { 4348 if (!elm) { 4349 return false; 4350 } 4351 const elms = isArray$1(elm) ? elm : [elm]; 4352 return exists(elms, e => { 4353 return is$1(SugarElement.fromDom(e), selector); 4354 }); 4355 }; 4356 const getParents = (elm, selector, root, collect) => { 4357 const result = []; 4358 let node = get(elm); 4359 collect = collect === undefined; 4360 const resolvedRoot = root || (getRoot().nodeName !== 'BODY' ? getRoot().parentNode : null); 4361 if (isString(selector)) { 4362 if (selector === '*') { 4363 selector = isElement$6; 4364 } else { 4365 const selectorVal = selector; 4366 selector = node => is(node, selectorVal); 4367 } 4368 } 4369 while (node) { 4370 if (node === resolvedRoot || isNullable(node.nodeType) || isDocument$1(node) || isDocumentFragment(node)) { 4371 break; 4372 } 4373 if (!selector || selector(node)) { 4374 if (collect) { 4375 result.push(node); 4376 } else { 4377 return [node]; 4378 } 4379 } 4380 node = node.parentNode; 4381 } 4382 return collect ? result : null; 4383 }; 4384 const getParent = (node, selector, root) => { 4385 const parents = getParents(node, selector, root, false); 4386 return parents && parents.length > 0 ? parents[0] : null; 4387 }; 4388 const _findSib = (node, selector, name) => { 4389 let func = selector; 4390 if (node) { 4391 if (isString(selector)) { 4392 func = node => { 4393 return is(node, selector); 4394 }; 4395 } 4396 for (let tempNode = node[name]; tempNode; tempNode = tempNode[name]) { 4397 if (isFunction(func) && func(tempNode)) { 4398 return tempNode; 4399 } 4400 } 4401 } 4402 return null; 4403 }; 4404 const getNext = (node, selector) => _findSib(node, selector, 'nextSibling'); 4405 const getPrev = (node, selector) => _findSib(node, selector, 'previousSibling'); 4406 const isParentNode = node => isFunction(node.querySelectorAll); 4407 const select = (selector, scope) => { 4408 var _a, _b; 4409 const elm = (_b = (_a = get(scope)) !== null && _a !== void 0 ? _a : settings.root_element) !== null && _b !== void 0 ? _b : doc; 4410 return isParentNode(elm) ? from(elm.querySelectorAll(selector)) : []; 4411 }; 4412 const run = function (elm, func, scope) { 4413 const context = scope !== null && scope !== void 0 ? scope : this; 4414 if (isArray$1(elm)) { 4415 const result = []; 4416 each$a(elm, (e, i) => { 4417 const node = get(e); 4418 if (node) { 4419 result.push(func.call(context, node, i)); 4420 } 4421 }); 4422 return result; 4423 } else { 4424 const node = get(elm); 4425 return !node ? false : func.call(context, node); 4426 } 4427 }; 4428 const setAttribs = (elm, attrs) => { 4429 run(elm, $elm => { 4430 each$d(attrs, (value, name) => { 4431 setAttrib($elm, name, value); 4432 }); 4433 }); 4434 }; 4435 const setHTML = (elm, html) => { 4436 run(elm, e => { 4437 const $elm = SugarElement.fromDom(e); 4438 set$1($elm, html); 4439 }); 4440 }; 4441 const add = (parentElm, name, attrs, html, create) => run(parentElm, parentElm => { 4442 const newElm = isString(name) ? doc.createElement(name) : name; 4443 if (isNonNullable(attrs)) { 4444 setAttribs(newElm, attrs); 4445 } 4446 if (html) { 4447 if (!isString(html) && html.nodeType) { 4448 newElm.appendChild(html); 4449 } else if (isString(html)) { 4450 setHTML(newElm, html); 4451 } 4452 } 4453 return !create ? parentElm.appendChild(newElm) : newElm; 4454 }); 4455 const create = (name, attrs, html) => add(doc.createElement(name), name, attrs, html, true); 4456 const decode = Entities.decode; 4457 const encode = Entities.encodeAllRaw; 4458 const createHTML = (name, attrs, html = '') => { 4459 let outHtml = '<' + name; 4460 for (const key in attrs) { 4461 if (hasNonNullableKey(attrs, key)) { 4462 outHtml += ' ' + key + '="' + encode(attrs[key]) + '"'; 4463 } 4464 } 4465 if (isEmpty$3(html) && has$2(schema.getVoidElements(), name)) { 4466 return outHtml + ' />'; 4467 } else { 4468 return outHtml + '>' + html + '</' + name + '>'; 4469 } 4470 }; 4471 const createFragment = html => { 4472 const container = doc.createElement('div'); 4473 const frag = doc.createDocumentFragment(); 4474 frag.appendChild(container); 4475 if (html) { 4476 container.innerHTML = html; 4477 } 4478 let node; 4479 while (node = container.firstChild) { 4480 frag.appendChild(node); 4481 } 4482 frag.removeChild(container); 4483 return frag; 4484 }; 4485 const remove = (node, keepChildren) => { 4486 return run(node, n => { 4487 const $node = SugarElement.fromDom(n); 4488 if (keepChildren) { 4489 each$e(children$1($node), child => { 4490 if (isText$b(child) && child.dom.length === 0) { 4491 remove$6(child); 4492 } else { 4493 before$3($node, child); 4494 } 4495 }); 4496 } 4497 remove$6($node); 4498 return $node.dom; 4499 }); 4500 }; 4501 const removeAllAttribs = e => run(e, e => { 4502 const attrs = e.attributes; 4503 for (let i = attrs.length - 1; i >= 0; i--) { 4504 e.removeAttributeNode(attrs.item(i)); 4505 } 4506 }); 4507 const parseStyle = cssText => styles.parse(cssText); 4508 const serializeStyle = (stylesArg, name) => styles.serialize(stylesArg, name); 4509 const addStyle = cssText => { 4510 if (self !== DOMUtils.DOM && doc === document) { 4511 if (addedStyles[cssText]) { 4512 return; 4513 } 4514 addedStyles[cssText] = true; 4515 } 4516 let styleElm = doc.getElementById('mceDefaultStyles'); 4517 if (!styleElm) { 4518 styleElm = doc.createElement('style'); 4519 styleElm.id = 'mceDefaultStyles'; 4520 styleElm.type = 'text/css'; 4521 const head = doc.head; 4522 if (head.firstChild) { 4523 head.insertBefore(styleElm, head.firstChild); 4524 } else { 4525 head.appendChild(styleElm); 4526 } 4527 } 4528 if (styleElm.styleSheet) { 4529 styleElm.styleSheet.cssText += cssText; 4530 } else { 4531 styleElm.appendChild(doc.createTextNode(cssText)); 4532 } 4533 }; 4534 const loadCSS = urls => { 4535 if (!urls) { 4536 urls = ''; 4537 } 4538 each$e(urls.split(','), url => { 4539 files[url] = true; 4540 styleSheetLoader.load(url).catch(noop); 4541 }); 4542 }; 4543 const toggleClass = (elm, cls, state) => { 4544 run(elm, e => { 4545 if (isElement$6(e)) { 4546 const $elm = SugarElement.fromDom(e); 4547 const classes = cls.split(' '); 4548 each$e(classes, c => { 4549 if (isNonNullable(state)) { 4550 const fn = state ? add$2 : remove$8; 4551 fn($elm, c); 4552 } else { 4553 toggle$1($elm, c); 4554 } 4555 }); 4556 } 4557 }); 4558 }; 4559 const addClass = (elm, cls) => { 4560 toggleClass(elm, cls, true); 4561 }; 4562 const removeClass = (elm, cls) => { 4563 toggleClass(elm, cls, false); 4564 }; 4565 const hasClass = (elm, cls) => { 4566 const $elm = _get(elm); 4567 const classes = cls.split(' '); 4568 return isNonNullable($elm) && forall(classes, c => has($elm, c)); 4569 }; 4570 const show = elm => { 4571 run(elm, e => remove$7(SugarElement.fromDom(e), 'display')); 4572 }; 4573 const hide = elm => { 4574 run(elm, e => set$2(SugarElement.fromDom(e), 'display', 'none')); 4575 }; 4576 const isHidden = elm => { 4577 const $elm = _get(elm); 4578 return isNonNullable($elm) && is$2(getRaw($elm, 'display'), 'none'); 4579 }; 4580 const uniqueId = prefix => (!prefix ? 'mce_' : prefix) + counter++; 4581 const getOuterHTML = elm => { 4582 const $elm = _get(elm); 4583 if (isNonNullable($elm)) { 4584 return isElement$6($elm.dom) ? $elm.dom.outerHTML : getOuter($elm); 4585 } else { 4586 return ''; 4587 } 4588 }; 4589 const setOuterHTML = (elm, html) => { 4590 run(elm, $elm => { 4591 if (isElement$6($elm)) { 4592 $elm.outerHTML = html; 4593 } 4594 }); 4595 }; 4596 const insertAfter = (node, reference) => { 4597 const referenceNode = get(reference); 4598 return run(node, node => { 4599 const parent = referenceNode === null || referenceNode === void 0 ? void 0 : referenceNode.parentNode; 4600 const nextSibling = referenceNode === null || referenceNode === void 0 ? void 0 : referenceNode.nextSibling; 4601 if (parent) { 4602 if (nextSibling) { 4603 parent.insertBefore(node, nextSibling); 4604 } else { 4605 parent.appendChild(node); 4606 } 4607 } 4608 return node; 4609 }); 4610 }; 4611 const replace = (newElm, oldElm, keepChildren) => run(oldElm, elm => { 4612 var _a; 4613 const replacee = isArray$1(oldElm) ? newElm.cloneNode(true) : newElm; 4614 if (keepChildren) { 4615 each$a(grep(elm.childNodes), node => { 4616 replacee.appendChild(node); 4617 }); 4618 } 4619 (_a = elm.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(replacee, elm); 4620 return elm; 4621 }); 4622 const rename = (elm, name) => { 4623 if (elm.nodeName !== name.toUpperCase()) { 4624 const newElm = create(name); 4625 each$a(getAttribs(elm), attrNode => { 4626 setAttrib(newElm, attrNode.nodeName, getAttrib(elm, attrNode.nodeName)); 4627 }); 4628 replace(newElm, elm, true); 4629 return newElm; 4630 } else { 4631 return elm; 4632 } 4633 }; 4634 const findCommonAncestor = (a, b) => { 4635 let ps = a; 4636 while (ps) { 4637 let pe = b; 4638 while (pe && ps !== pe) { 4639 pe = pe.parentNode; 4640 } 4641 if (ps === pe) { 4642 break; 4643 } 4644 ps = ps.parentNode; 4645 } 4646 if (!ps && a.ownerDocument) { 4647 return a.ownerDocument.documentElement; 4648 } else { 4649 return ps; 4650 } 4651 }; 4652 const isNonEmptyElement = node => { 4653 if (isElement$6(node)) { 4654 const isNamedAnchor = node.nodeName.toLowerCase() === 'a' && !getAttrib(node, 'href') && getAttrib(node, 'id'); 4655 if (getAttrib(node, 'name') || getAttrib(node, 'data-mce-bookmark') || isNamedAnchor) { 4656 return true; 4657 } 4658 } 4659 return false; 4660 }; 4661 const isEmpty = (node, elements) => { 4662 let brCount = 0; 4663 if (isNonEmptyElement(node)) { 4664 return false; 4665 } 4666 const firstChild = node.firstChild; 4667 if (firstChild) { 4668 const walker = new DomTreeWalker(firstChild, node); 4669 const whitespaceElements = schema ? schema.getWhitespaceElements() : {}; 4670 const nonEmptyElements = elements || (schema ? schema.getNonEmptyElements() : null); 4671 let tempNode = firstChild; 4672 do { 4673 if (isElement$6(tempNode)) { 4674 const bogusVal = tempNode.getAttribute('data-mce-bogus'); 4675 if (bogusVal) { 4676 tempNode = walker.next(bogusVal === 'all'); 4677 continue; 4678 } 4679 const name = tempNode.nodeName.toLowerCase(); 4680 if (nonEmptyElements && nonEmptyElements[name]) { 4681 if (name === 'br') { 4682 brCount++; 4683 tempNode = walker.next(); 4684 continue; 4685 } 4686 return false; 4687 } 4688 if (isNonEmptyElement(tempNode)) { 4689 return false; 4690 } 4691 } 4692 if (isComment(tempNode)) { 4693 return false; 4694 } 4695 if (isText$a(tempNode) && !isWhitespaceText(tempNode.data)) { 4696 return false; 4697 } 4698 if (isText$a(tempNode) && tempNode.parentNode && whitespaceElements[tempNode.parentNode.nodeName] && isWhitespaceText(tempNode.data)) { 4699 return false; 4700 } 4701 tempNode = walker.next(); 4702 } while (tempNode); 4703 } 4704 return brCount <= 1; 4705 }; 4706 const createRng = () => doc.createRange(); 4707 const split = (parentElm, splitElm, replacementElm) => { 4708 let range = createRng(); 4709 let beforeFragment; 4710 let afterFragment; 4711 if (parentElm && splitElm && parentElm.parentNode && splitElm.parentNode) { 4712 const parentNode = parentElm.parentNode; 4713 range.setStart(parentNode, findNodeIndex(parentElm)); 4714 range.setEnd(splitElm.parentNode, findNodeIndex(splitElm)); 4715 beforeFragment = range.extractContents(); 4716 range = createRng(); 4717 range.setStart(splitElm.parentNode, findNodeIndex(splitElm) + 1); 4718 range.setEnd(parentNode, findNodeIndex(parentElm) + 1); 4719 afterFragment = range.extractContents(); 4720 parentNode.insertBefore(trimNode(self, beforeFragment), parentElm); 4721 if (replacementElm) { 4722 parentNode.insertBefore(replacementElm, parentElm); 4723 } else { 4724 parentNode.insertBefore(splitElm, parentElm); 4725 } 4726 parentNode.insertBefore(trimNode(self, afterFragment), parentElm); 4727 remove(parentElm); 4728 return replacementElm || splitElm; 4729 } else { 4730 return undefined; 4731 } 4732 }; 4733 const bind = (target, name, func, scope) => { 4734 if (isArray$1(target)) { 4735 let i = target.length; 4736 const rv = []; 4737 while (i--) { 4738 rv[i] = bind(target[i], name, func, scope); 4739 } 4740 return rv; 4741 } else { 4742 if (settings.collect && (target === doc || target === win)) { 4743 boundEvents.push([ 4744 target, 4745 name, 4746 func, 4747 scope 4748 ]); 4749 } 4750 return events.bind(target, name, func, scope || self); 4751 } 4752 }; 4753 const unbind = (target, name, func) => { 4754 if (isArray$1(target)) { 4755 let i = target.length; 4756 const rv = []; 4757 while (i--) { 4758 rv[i] = unbind(target[i], name, func); 4759 } 4760 return rv; 4761 } else { 4762 if (boundEvents.length > 0 && (target === doc || target === win)) { 4763 let i = boundEvents.length; 4764 while (i--) { 4765 const [boundTarget, boundName, boundFunc] = boundEvents[i]; 4766 if (target === boundTarget && (!name || name === boundName) && (!func || func === boundFunc)) { 4767 events.unbind(boundTarget, boundName, boundFunc); 4768 } 4769 } 4770 } 4771 return events.unbind(target, name, func); 4772 } 4773 }; 4774 const dispatch = (target, name, evt) => events.dispatch(target, name, evt); 4775 const fire = (target, name, evt) => events.dispatch(target, name, evt); 4776 const getContentEditable = node => { 4777 if (node && isElement$6(node)) { 4778 const contentEditable = node.getAttribute('data-mce-contenteditable'); 4779 if (contentEditable && contentEditable !== 'inherit') { 4780 return contentEditable; 4781 } 4782 return node.contentEditable !== 'inherit' ? node.contentEditable : null; 4783 } else { 4784 return null; 4785 } 4786 }; 4787 const getContentEditableParent = node => { 4788 const root = getRoot(); 4789 let state = null; 4790 for (let tempNode = node; tempNode && tempNode !== root; tempNode = tempNode.parentNode) { 4791 state = getContentEditable(tempNode); 4792 if (state !== null) { 4793 break; 4794 } 4795 } 4796 return state; 4797 }; 4798 const isEditable = node => { 4799 if (isNonNullable(node)) { 4800 const scope = isElement$6(node) ? node : node.parentElement; 4801 const isRootEditable = getContentEditable(getRoot()) === 'true'; 4802 return isNonNullable(scope) && isEditable$3(SugarElement.fromDom(scope), isRootEditable); 4803 } else { 4804 return false;
vendor: 6,561 bytes, lines 4805-5035
4805 } 4806 }; 4807 const destroy = () => { 4808 if (boundEvents.length > 0) { 4809 let i = boundEvents.length; 4810 while (i--) { 4811 const [boundTarget, boundName, boundFunc] = boundEvents[i]; 4812 events.unbind(boundTarget, boundName, boundFunc); 4813 } 4814 } 4815 each$d(files, (_, url) => { 4816 styleSheetLoader.unload(url); 4817 delete files[url]; 4818 }); 4819 }; 4820 const isChildOf = (node, parent) => { 4821 return node === parent || parent.contains(node); 4822 }; 4823 const dumpRng = r => 'startContainer: ' + r.startContainer.nodeName + ', startOffset: ' + r.startOffset + ', endContainer: ' + r.endContainer.nodeName + ', endOffset: ' + r.endOffset; 4824 const self = { 4825 doc, 4826 settings, 4827 win, 4828 files, 4829 stdMode, 4830 boxModel, 4831 styleSheetLoader, 4832 boundEvents, 4833 styles, 4834 schema, 4835 events, 4836 isBlock: isBlock, 4837 root: null, 4838 clone, 4839 getRoot, 4840 getViewPort, 4841 getRect, 4842 getSize, 4843 getParent, 4844 getParents: getParents, 4845 get, 4846 getNext, 4847 getPrev, 4848 select, 4849 is, 4850 add, 4851 create, 4852 createHTML, 4853 createFragment, 4854 remove, 4855 setStyle, 4856 getStyle: getStyle, 4857 setStyles, 4858 removeAllAttribs, 4859 setAttrib, 4860 setAttribs, 4861 getAttrib, 4862 getPos: getPos$1, 4863 parseStyle, 4864 serializeStyle, 4865 addStyle, 4866 loadCSS, 4867 addClass, 4868 removeClass, 4869 hasClass, 4870 toggleClass, 4871 show, 4872 hide, 4873 isHidden, 4874 uniqueId, 4875 setHTML, 4876 getOuterHTML, 4877 setOuterHTML, 4878 decode, 4879 encode, 4880 insertAfter, 4881 replace, 4882 rename, 4883 findCommonAncestor, 4884 run, 4885 getAttribs, 4886 isEmpty, 4887 createRng, 4888 nodeIndex: findNodeIndex, 4889 split, 4890 bind: bind, 4891 unbind: unbind, 4892 fire, 4893 dispatch, 4894 getContentEditable, 4895 getContentEditableParent, 4896 isEditable, 4897 destroy, 4898 isChildOf, 4899 dumpRng 4900 }; 4901 const attrHooks = setupAttrHooks(styles, settings, constant(self)); 4902 return self; 4903 }; 4904 DOMUtils.DOM = DOMUtils(document); 4905 DOMUtils.nodeIndex = findNodeIndex; 4906 4907 const DOM$b = DOMUtils.DOM; 4908 const QUEUED = 0; 4909 const LOADING = 1; 4910 const LOADED = 2; 4911 const FAILED = 3; 4912 class ScriptLoader { 4913 constructor(settings = {}) { 4914 this.states = {}; 4915 this.queue = []; 4916 this.scriptLoadedCallbacks = {}; 4917 this.queueLoadedCallbacks = []; 4918 this.loading = false; 4919 this.settings = settings; 4920 } 4921 _setReferrerPolicy(referrerPolicy) { 4922 this.settings.referrerPolicy = referrerPolicy; 4923 } 4924 loadScript(url) { 4925 return new Promise((resolve, reject) => { 4926 const dom = DOM$b; 4927 let elm; 4928 const cleanup = () => { 4929 dom.remove(id); 4930 if (elm) { 4931 elm.onerror = elm.onload = elm = null; 4932 } 4933 }; 4934 const done = () => { 4935 cleanup(); 4936 resolve(); 4937 }; 4938 const error = () => { 4939 cleanup(); 4940 reject('Failed to load script: ' + url); 4941 }; 4942 const id = dom.uniqueId(); 4943 elm = document.createElement('script'); 4944 elm.id = id; 4945 elm.type = 'text/javascript'; 4946 elm.src = Tools._addCacheSuffix(url); 4947 if (this.settings.referrerPolicy) { 4948 dom.setAttrib(elm, 'referrerpolicy', this.settings.referrerPolicy); 4949 } 4950 elm.onload = done; 4951 elm.onerror = error; 4952 (document.getElementsByTagName('head')[0] || document.body).appendChild(elm); 4953 }); 4954 } 4955 isDone(url) { 4956 return this.states[url] === LOADED; 4957 } 4958 markDone(url) { 4959 this.states[url] = LOADED; 4960 } 4961 add(url) { 4962 const self = this; 4963 self.queue.push(url); 4964 const state = self.states[url]; 4965 if (state === undefined) { 4966 self.states[url] = QUEUED; 4967 } 4968 return new Promise((resolve, reject) => { 4969 if (!self.scriptLoadedCallbacks[url]) { 4970 self.scriptLoadedCallbacks[url] = []; 4971 } 4972 self.scriptLoadedCallbacks[url].push({ 4973 resolve, 4974 reject 4975 }); 4976 }); 4977 } 4978 load(url) { 4979 return this.add(url); 4980 } 4981 remove(url) { 4982 delete this.states[url]; 4983 delete this.scriptLoadedCallbacks[url]; 4984 } 4985 loadQueue() { 4986 const queue = this.queue; 4987 this.queue = []; 4988 return this.loadScripts(queue); 4989 } 4990 loadScripts(scripts) { 4991 const self = this; 4992 const execCallbacks = (name, url) => { 4993 get$a(self.scriptLoadedCallbacks, url).each(callbacks => { 4994 each$e(callbacks, callback => callback[name](url)); 4995 }); 4996 delete self.scriptLoadedCallbacks[url]; 4997 }; 4998 const processResults = results => { 4999 const failures = filter$5(results, result => result.status === 'rejected'); 5000 if (failures.length > 0) { 5001 return Promise.reject(bind$3(failures, ({reason}) => isArray$1(reason) ? reason : [reason])); 5002 } else { 5003 return Promise.resolve(); 5004 } 5005 }; 5006 const load = urls => Promise.allSettled(map$3(urls, url => { 5007 if (self.states[url] === LOADED) { 5008 execCallbacks('resolve', url); 5009 return Promise.resolve(); 5010 } else if (self.states[url] === FAILED) { 5011 execCallbacks('reject', url); 5012 return Promise.reject(url); 5013 } else { 5014 self.states[url] = LOADING; 5015 return self.loadScript(url).then(() => { 5016 self.states[url] = LOADED; 5017 execCallbacks('resolve', url); 5018 const queue = self.queue; 5019 if (queue.length > 0) { 5020 self.queue = []; 5021 return load(queue).then(processResults); 5022 } else { 5023 return Promise.resolve(); 5024 } 5025 }, () => { 5026 self.states[url] = FAILED; 5027 execCallbacks('reject', url); 5028 return Promise.reject(url); 5029 }); 5030 } 5031 })); 5032 const processQueue = urls => { 5033 self.loading = true; 5034 return load(urls).then(results => { 5035 self.loading = false;
vendor: 4,081 bytes, lines 5036-5157
5036 const nextQueuedItem = self.queueLoadedCallbacks.shift(); 5037 Optional.from(nextQueuedItem).each(call); 5038 return processResults(results); 5039 }); 5040 }; 5041 const uniqueScripts = stringArray(scripts); 5042 if (self.loading) { 5043 return new Promise((resolve, reject) => { 5044 self.queueLoadedCallbacks.push(() => processQueue(uniqueScripts).then(resolve, reject)); 5045 }); 5046 } else { 5047 return processQueue(uniqueScripts); 5048 } 5049 } 5050 } 5051 ScriptLoader.ScriptLoader = new ScriptLoader(); 5052 5053 const Cell = initial => { 5054 let value = initial; 5055 const get = () => { 5056 return value; 5057 }; 5058 const set = v => { 5059 value = v; 5060 }; 5061 return { 5062 get, 5063 set 5064 }; 5065 }; 5066 5067 const isRaw = str => isObject(str) && has$2(str, 'raw'); 5068 const isTokenised = str => isArray$1(str) && str.length > 1; 5069 const data = {}; 5070 const currentCode = Cell('en'); 5071 const getLanguageData = () => get$a(data, currentCode.get()); 5072 const getData$1 = () => map$2(data, value => ({ ...value })); 5073 const setCode = newCode => { 5074 if (newCode) { 5075 currentCode.set(newCode); 5076 } 5077 }; 5078 const getCode = () => currentCode.get(); 5079 const add$1 = (code, items) => { 5080 let langData = data[code]; 5081 if (!langData) { 5082 data[code] = langData = {}; 5083 } 5084 each$d(items, (translation, name) => { 5085 langData[name.toLowerCase()] = translation; 5086 }); 5087 }; 5088 const translate = text => { 5089 const langData = getLanguageData().getOr({}); 5090 const toString = obj => { 5091 if (isFunction(obj)) { 5092 return Object.prototype.toString.call(obj); 5093 } 5094 return !isEmpty(obj) ? '' + obj : ''; 5095 }; 5096 const isEmpty = text => text === '' || text === null || text === undefined; 5097 const getLangData = text => { 5098 const textstr = toString(text); 5099 return get$a(langData, textstr.toLowerCase()).map(toString).getOr(textstr); 5100 }; 5101 const removeContext = str => str.replace(/{context:\w+}$/, ''); 5102 if (isEmpty(text)) { 5103 return ''; 5104 } 5105 if (isRaw(text)) { 5106 return toString(text.raw); 5107 } 5108 if (isTokenised(text)) { 5109 const values = text.slice(1); 5110 const substitued = getLangData(text[0]).replace(/\{([0-9]+)\}/g, ($1, $2) => has$2(values, $2) ? toString(values[$2]) : $1); 5111 return removeContext(substitued); 5112 } 5113 return removeContext(getLangData(text)); 5114 }; 5115 const isRtl$1 = () => getLanguageData().bind(items => get$a(items, '_dir')).exists(dir => dir === 'rtl'); 5116 const hasCode = code => has$2(data, code); 5117 const I18n = { 5118 getData: getData$1, 5119 setCode, 5120 getCode, 5121 add: add$1, 5122 translate, 5123 isRtl: isRtl$1, 5124 hasCode 5125 }; 5126 5127 const AddOnManager = () => { 5128 const items = []; 5129 const urls = {}; 5130 const lookup = {}; 5131 const _listeners = []; 5132 const runListeners = (name, state) => { 5133 const matchedListeners = filter$5(_listeners, listener => listener.name === name && listener.state === state); 5134 each$e(matchedListeners, listener => listener.resolve()); 5135 }; 5136 const isLoaded = name => has$2(urls, name); 5137 const isAdded = name => has$2(lookup, name); 5138 const get = name => { 5139 if (lookup[name]) { 5140 return lookup[name].instance; 5141 } 5142 return undefined; 5143 }; 5144 const loadLanguagePack = (name, languages) => { 5145 const language = I18n.getCode(); 5146 const wrappedLanguages = ',' + (languages || '') + ','; 5147 if (!language || languages && wrappedLanguages.indexOf(',' + language + ',') === -1) { 5148 return; 5149 } 5150 ScriptLoader.ScriptLoader.add(urls[name] + '/langs/' + language + '.js'); 5151 }; 5152 const requireLangPack = (name, languages) => { 5153 if (AddOnManager.languageLoad !== false) { 5154 if (isLoaded(name)) { 5155 loadLanguagePack(name, languages); 5156 } else { 5157 waitFor(name, 'loaded').then(() =>
vendor: 12,355 bytes, lines 5157-5541
5157 loadLanguagePack(name, languages)); 5158 } 5159 } 5160 }; 5161 const add = (id, addOn) => { 5162 items.push(addOn); 5163 lookup[id] = { instance: addOn }; 5164 runListeners(id, 'added'); 5165 return addOn; 5166 }; 5167 const remove = name => { 5168 delete urls[name]; 5169 delete lookup[name]; 5170 }; 5171 const createUrl = (baseUrl, dep) => { 5172 if (isString(dep)) { 5173 return isString(baseUrl) ? { 5174 prefix: '', 5175 resource: dep, 5176 suffix: '' 5177 } : { 5178 prefix: baseUrl.prefix, 5179 resource: dep, 5180 suffix: baseUrl.suffix 5181 }; 5182 } else { 5183 return dep; 5184 } 5185 }; 5186 const load = (name, addOnUrl) => { 5187 if (urls[name]) { 5188 return Promise.resolve(); 5189 } 5190 let urlString = isString(addOnUrl) ? addOnUrl : addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix; 5191 if (urlString.indexOf('/') !== 0 && urlString.indexOf('://') === -1) { 5192 urlString = AddOnManager.baseURL + '/' + urlString; 5193 } 5194 urls[name] = urlString.substring(0, urlString.lastIndexOf('/')); 5195 const done = () => { 5196 runListeners(name, 'loaded'); 5197 return Promise.resolve(); 5198 }; 5199 if (lookup[name]) { 5200 return done(); 5201 } else { 5202 return ScriptLoader.ScriptLoader.add(urlString).then(done); 5203 } 5204 }; 5205 const waitFor = (name, state = 'added') => { 5206 if (state === 'added' && isAdded(name)) { 5207 return Promise.resolve(); 5208 } else if (state === 'loaded' && isLoaded(name)) { 5209 return Promise.resolve(); 5210 } else { 5211 return new Promise(resolve => { 5212 _listeners.push({ 5213 name, 5214 state, 5215 resolve 5216 }); 5217 }); 5218 } 5219 }; 5220 return { 5221 items, 5222 urls, 5223 lookup, 5224 get, 5225 requireLangPack, 5226 add, 5227 remove, 5228 createUrl, 5229 load, 5230 waitFor 5231 }; 5232 }; 5233 AddOnManager.languageLoad = true; 5234 AddOnManager.baseURL = ''; 5235 AddOnManager.PluginManager = AddOnManager(); 5236 AddOnManager.ThemeManager = AddOnManager(); 5237 AddOnManager.ModelManager = AddOnManager(); 5238 5239 const singleton = doRevoke => { 5240 const subject = Cell(Optional.none()); 5241 const revoke = () => subject.get().each(doRevoke); 5242 const clear = () => { 5243 revoke(); 5244 subject.set(Optional.none()); 5245 }; 5246 const isSet = () => subject.get().isSome(); 5247 const get = () => subject.get(); 5248 const set = s => { 5249 revoke(); 5250 subject.set(Optional.some(s)); 5251 }; 5252 return { 5253 clear, 5254 isSet, 5255 get, 5256 set 5257 }; 5258 }; 5259 const repeatable = delay => { 5260 const intervalId = Cell(Optional.none()); 5261 const revoke = () => intervalId.get().each(id => clearInterval(id)); 5262 const clear = () => { 5263 revoke(); 5264 intervalId.set(Optional.none()); 5265 }; 5266 const isSet = () => intervalId.get().isSome(); 5267 const get = () => intervalId.get(); 5268 const set = functionToRepeat => { 5269 revoke(); 5270 intervalId.set(Optional.some(setInterval(functionToRepeat, delay))); 5271 }; 5272 return { 5273 clear, 5274 isSet, 5275 get, 5276 set 5277 }; 5278 }; 5279 const value$2 = () => { 5280 const subject = singleton(noop); 5281 const on = f => subject.get().each(f); 5282 return { 5283 ...subject, 5284 on 5285 }; 5286 }; 5287 5288 const first$1 = (fn, rate) => { 5289 let timer = null; 5290 const cancel = () => { 5291 if (!isNull(timer)) { 5292 clearTimeout(timer); 5293 timer = null; 5294 } 5295 }; 5296 const throttle = (...args) => { 5297 if (isNull(timer)) { 5298 timer = setTimeout(() => { 5299 timer = null; 5300 fn.apply(null, args); 5301 }, rate); 5302 } 5303 }; 5304 return { 5305 cancel, 5306 throttle 5307 }; 5308 }; 5309 const last$1 = (fn, rate) => { 5310 let timer = null; 5311 const cancel = () => { 5312 if (!isNull(timer)) { 5313 clearTimeout(timer); 5314 timer = null; 5315 } 5316 }; 5317 const throttle = (...args) => { 5318 cancel(); 5319 timer = setTimeout(() => { 5320 timer = null; 5321 fn.apply(null, args); 5322 }, rate); 5323 }; 5324 return { 5325 cancel, 5326 throttle 5327 }; 5328 }; 5329 5330 const annotation = constant('mce-annotation'); 5331 const dataAnnotation = constant('data-mce-annotation'); 5332 const dataAnnotationId = constant('data-mce-annotation-uid'); 5333 const dataAnnotationActive = constant('data-mce-annotation-active'); 5334 const dataAnnotationClasses = constant('data-mce-annotation-classes'); 5335 const dataAnnotationAttributes = constant('data-mce-annotation-attrs'); 5336 5337 const isRoot$1 = root => node => eq(node, root); 5338 const identify = (editor, annotationName) => { 5339 const rng = editor.selection.getRng(); 5340 const start = SugarElement.fromDom(rng.startContainer); 5341 const root = SugarElement.fromDom(editor.getBody()); 5342 const selector = annotationName.fold(() => '.' + annotation(), an => `[${ dataAnnotation() }="${ an }"]`); 5343 const newStart = child$1(start, rng.startOffset).getOr(start); 5344 const closest = closest$3(newStart, selector, isRoot$1(root)); 5345 return closest.bind(c => getOpt(c, `${ dataAnnotationId() }`).bind(uid => getOpt(c, `${ dataAnnotation() }`).map(name => { 5346 const elements = findMarkers(editor, uid); 5347 return { 5348 uid, 5349 name, 5350 elements 5351 }; 5352 }))); 5353 }; 5354 const isAnnotation = elem => isElement$7(elem) && has(elem, annotation()); 5355 const isBogusElement = (elem, root) => has$1(elem, 'data-mce-bogus') || ancestor$2(elem, '[data-mce-bogus="all"]', isRoot$1(root)); 5356 const findMarkers = (editor, uid) => { 5357 const body = SugarElement.fromDom(editor.getBody()); 5358 const descendants$1 = descendants(body, `[${ dataAnnotationId() }="${ uid }"]`); 5359 return filter$5(descendants$1, descendant => !isBogusElement(descendant, body)); 5360 }; 5361 const findAll = (editor, name) => { 5362 const body = SugarElement.fromDom(editor.getBody()); 5363 const markers = descendants(body, `[${ dataAnnotation() }="${ name }"]`); 5364 const directory = {}; 5365 each$e(markers, m => { 5366 if (!isBogusElement(m, body)) { 5367 const uid = get$9(m, dataAnnotationId()); 5368 const nodesAlready = get$a(directory, uid).getOr([]); 5369 directory[uid] = nodesAlready.concat([m]); 5370 } 5371 }); 5372 return directory; 5373 }; 5374 5375 const setup$x = (editor, registry) => { 5376 const changeCallbacks = Cell({}); 5377 const initData = () => ({ 5378 listeners: [], 5379 previous: value$2() 5380 }); 5381 const withCallbacks = (name, f) => { 5382 updateCallbacks(name, data => { 5383 f(data); 5384 return data; 5385 }); 5386 }; 5387 const updateCallbacks = (name, f) => { 5388 const callbackMap = changeCallbacks.get(); 5389 const data = get$a(callbackMap, name).getOrThunk(initData); 5390 const outputData = f(data); 5391 callbackMap[name] = outputData; 5392 changeCallbacks.set(callbackMap); 5393 }; 5394 const fireCallbacks = (name, uid, elements) => { 5395 withCallbacks(name, data => { 5396 each$e(data.listeners, f => f(true, name, { 5397 uid, 5398 nodes: map$3(elements, elem => elem.dom) 5399 })); 5400 }); 5401 }; 5402 const fireNoAnnotation = name => { 5403 withCallbacks(name, data => { 5404 each$e(data.listeners, f => f(false, name)); 5405 }); 5406 }; 5407 const toggleActiveAttr = (uid, state) => { 5408 each$e(findMarkers(editor, uid), elem => { 5409 if (state) { 5410 set$3(elem, dataAnnotationActive(), 'true'); 5411 } else { 5412 remove$b(elem, dataAnnotationActive()); 5413 } 5414 }); 5415 }; 5416 const onNodeChange = last$1(() => { 5417 const annotations = sort(registry.getNames()); 5418 each$e(annotations, name => { 5419 updateCallbacks(name, data => { 5420 const prev = data.previous.get(); 5421 identify(editor, Optional.some(name)).fold(() => { 5422 prev.each(uid => { 5423 fireNoAnnotation(name); 5424 data.previous.clear(); 5425 toggleActiveAttr(uid, false); 5426 }); 5427 }, ({uid, name, elements}) => { 5428 if (!is$2(prev, uid)) { 5429 prev.each(uid => toggleActiveAttr(uid, false)); 5430 fireCallbacks(name, uid, elements); 5431 data.previous.set(uid); 5432 toggleActiveAttr(uid, true); 5433 } 5434 }); 5435 return { 5436 previous: data.previous, 5437 listeners: data.listeners 5438 }; 5439 }); 5440 }); 5441 }, 30); 5442 editor.on('remove', () => { 5443 onNodeChange.cancel(); 5444 }); 5445 editor.on('NodeChange', () => { 5446 onNodeChange.throttle(); 5447 }); 5448 const addListener = (name, f) => { 5449 updateCallbacks(name, data => ({ 5450 previous: data.previous, 5451 listeners: data.listeners.concat([f]) 5452 })); 5453 }; 5454 return { addListener }; 5455 }; 5456 5457 const setup$w = (editor, registry) => { 5458 const dataAnnotation$1 = dataAnnotation(); 5459 const identifyParserNode = node => Optional.from(node.attr(dataAnnotation$1)).bind(registry.lookup); 5460 const removeDirectAnnotation = node => { 5461 var _a, _b; 5462 node.attr(dataAnnotationId(), null); 5463 node.attr(dataAnnotation(), null); 5464 node.attr(dataAnnotationActive(), null); 5465 const customAttrNames = Optional.from(node.attr(dataAnnotationAttributes())).map(names => names.split(',')).getOr([]); 5466 const customClasses = Optional.from(node.attr(dataAnnotationClasses())).map(names => names.split(',')).getOr([]); 5467 each$e(customAttrNames, name => node.attr(name, null)); 5468 const classList = (_b = (_a = node.attr('class')) === null || _a === void 0 ? void 0 : _a.split(' ')) !== null && _b !== void 0 ? _b : []; 5469 const newClassList = difference(classList, [annotation()].concat(customClasses)); 5470 node.attr('class', newClassList.length > 0 ? newClassList.join(' ') : null); 5471 node.attr(dataAnnotationClasses(), null); 5472 node.attr(dataAnnotationAttributes(), null); 5473 }; 5474 editor.serializer.addTempAttr(dataAnnotationActive()); 5475 editor.serializer.addAttributeFilter(dataAnnotation$1, nodes => { 5476 for (const node of nodes) { 5477 identifyParserNode(node).each(settings => { 5478 if (settings.persistent === false) { 5479 if (node.name === 'span') { 5480 node.unwrap(); 5481 } else { 5482 removeDirectAnnotation(node); 5483 } 5484 } 5485 }); 5486 } 5487 }); 5488 }; 5489 5490 const create$c = () => { 5491 const annotations = {}; 5492 const register = (name, settings) => { 5493 annotations[name] = { 5494 name, 5495 settings 5496 }; 5497 }; 5498 const lookup = name => get$a(annotations, name).map(a => a.settings); 5499 const getNames = () => keys(annotations); 5500 return { 5501 register, 5502 lookup, 5503 getNames 5504 }; 5505 }; 5506 5507 let unique = 0; 5508 const generate$1 = prefix => { 5509 const date = new Date(); 5510 const time = date.getTime(); 5511 const random = Math.floor(Math.random() * 1000000000); 5512 unique++; 5513 return prefix + '_' + random + unique + String(time); 5514 }; 5515 5516 const add = (element, classes) => { 5517 each$e(classes, x => { 5518 add$2(element, x); 5519 }); 5520 }; 5521 const remove$5 = (element, classes) => { 5522 each$e(classes, x => { 5523 remove$8(element, x); 5524 }); 5525 }; 5526 5527 const clone$2 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep)); 5528 const shallow$1 = original => clone$2(original, false); 5529 const deep$1 = original => clone$2(original, true); 5530 const shallowAs = (original, tag) => { 5531 const nu = SugarElement.fromTag(tag); 5532 const attributes = clone$4(original); 5533 setAll$1(nu, attributes); 5534 return nu; 5535 }; 5536 const mutate = (original, tag) => { 5537 const nu = shallowAs(original, tag); 5538 after$4(original, nu); 5539 const children = children$1(original); 5540 append(nu, children); 5541 remove$6
vendor: 45,163 bytes, lines 5541-6802
5541(original); 5542 return nu; 5543 }; 5544 5545 const TextWalker = (startNode, rootNode, isBoundary = never) => { 5546 const walker = new DomTreeWalker(startNode, rootNode); 5547 const walk = direction => { 5548 let next; 5549 do { 5550 next = walker[direction](); 5551 } while (next && !isText$a(next) && !isBoundary(next)); 5552 return Optional.from(next).filter(isText$a); 5553 }; 5554 return { 5555 current: () => Optional.from(walker.current()).filter(isText$a), 5556 next: () => walk('next'), 5557 prev: () => walk('prev'), 5558 prev2: () => walk('prev2') 5559 }; 5560 }; 5561 5562 const TextSeeker = (dom, isBoundary) => { 5563 const isBlockBoundary = isBoundary ? isBoundary : node => dom.isBlock(node) || isBr$6(node) || isContentEditableFalse$b(node); 5564 const walk = (node, offset, walker, process) => { 5565 if (isText$a(node)) { 5566 const newOffset = process(node, offset, node.data); 5567 if (newOffset !== -1) { 5568 return Optional.some({ 5569 container: node, 5570 offset: newOffset 5571 }); 5572 } 5573 } 5574 return walker().bind(next => walk(next.container, next.offset, walker, process)); 5575 }; 5576 const backwards = (node, offset, process, root) => { 5577 const walker = TextWalker(node, root !== null && root !== void 0 ? root : dom.getRoot(), isBlockBoundary); 5578 return walk(node, offset, () => walker.prev().map(prev => ({ 5579 container: prev, 5580 offset: prev.length 5581 })), process).getOrNull(); 5582 }; 5583 const forwards = (node, offset, process, root) => { 5584 const walker = TextWalker(node, root !== null && root !== void 0 ? root : dom.getRoot(), isBlockBoundary); 5585 return walk(node, offset, () => walker.next().map(next => ({ 5586 container: next, 5587 offset: 0 5588 })), process).getOrNull(); 5589 }; 5590 return { 5591 backwards, 5592 forwards 5593 }; 5594 }; 5595 5596 const round$2 = Math.round; 5597 const clone$1 = rect => { 5598 if (!rect) { 5599 return { 5600 left: 0, 5601 top: 0, 5602 bottom: 0, 5603 right: 0, 5604 width: 0, 5605 height: 0 5606 }; 5607 } 5608 return { 5609 left: round$2(rect.left), 5610 top: round$2(rect.top), 5611 bottom: round$2(rect.bottom), 5612 right: round$2(rect.right), 5613 width: round$2(rect.width), 5614 height: round$2(rect.height) 5615 }; 5616 }; 5617 const collapse = (rect, toStart) => { 5618 rect = clone$1(rect); 5619 if (toStart) { 5620 rect.right = rect.left; 5621 } else { 5622 rect.left = rect.left + rect.width; 5623 rect.right = rect.left; 5624 } 5625 rect.width = 0; 5626 return rect; 5627 }; 5628 const isEqual = (rect1, rect2) => rect1.left === rect2.left && rect1.top === rect2.top && rect1.bottom === rect2.bottom && rect1.right === rect2.right; 5629 const isValidOverflow = (overflowY, rect1, rect2) => overflowY >= 0 && overflowY <= Math.min(rect1.height, rect2.height) / 2; 5630 const isAbove$1 = (rect1, rect2) => { 5631 const halfHeight = Math.min(rect2.height / 2, rect1.height / 2); 5632 if (rect1.bottom - halfHeight < rect2.top) { 5633 return true; 5634 } 5635 if (rect1.top > rect2.bottom) { 5636 return false; 5637 } 5638 return isValidOverflow(rect2.top - rect1.bottom, rect1, rect2); 5639 }; 5640 const isBelow$1 = (rect1, rect2) => { 5641 if (rect1.top > rect2.bottom) { 5642 return true; 5643 } 5644 if (rect1.bottom < rect2.top) { 5645 return false; 5646 } 5647 return isValidOverflow(rect2.bottom - rect1.top, rect1, rect2); 5648 }; 5649 const containsXY = (rect, clientX, clientY) => clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom; 5650 const boundingClientRectFromRects = rects => { 5651 return foldl(rects, (acc, rect) => { 5652 return acc.fold(() => Optional.some(rect), prevRect => { 5653 const left = Math.min(rect.left, prevRect.left); 5654 const top = Math.min(rect.top, prevRect.top); 5655 const right = Math.max(rect.right, prevRect.right); 5656 const bottom = Math.max(rect.bottom, prevRect.bottom); 5657 return Optional.some({ 5658 top, 5659 right, 5660 bottom, 5661 left, 5662 width: right - left, 5663 height: bottom - top 5664 }); 5665 }); 5666 }, Optional.none()); 5667 }; 5668 const distanceToRectEdgeFromXY = (rect, x, y) => { 5669 const cx = Math.max(Math.min(x, rect.left + rect.width), rect.left); 5670 const cy = Math.max(Math.min(y, rect.top + rect.height), rect.top); 5671 return Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)); 5672 }; 5673 const overlapY = (r1, r2) => Math.max(0, Math.min(r1.bottom, r2.bottom) - Math.max(r1.top, r2.top)); 5674 5675 const clamp$2 = (value, min, max) => Math.min(Math.max(value, min), max); 5676 5677 const getSelectedNode = range => { 5678 const startContainer = range.startContainer, startOffset = range.startOffset; 5679 if (startContainer === range.endContainer && startContainer.hasChildNodes() && range.endOffset === startOffset + 1) { 5680 return startContainer.childNodes[startOffset]; 5681 } 5682 return null; 5683 }; 5684 const getNode$1 = (container, offset) => { 5685 if (isElement$6(container) && container.hasChildNodes()) { 5686 const childNodes = container.childNodes; 5687 const safeOffset = clamp$2(offset, 0, childNodes.length - 1); 5688 return childNodes[safeOffset]; 5689 } else { 5690 return container; 5691 } 5692 }; 5693 const getNodeUnsafe = (container, offset) => { 5694 if (offset < 0 && isElement$6(container) && container.hasChildNodes()) { 5695 return undefined; 5696 } else { 5697 return getNode$1(container, offset); 5698 } 5699 }; 5700 5701 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]'); 5702 const isExtendingChar = ch => isString(ch) && ch.charCodeAt(0) >= 768 && extendingChars.test(ch); 5703 5704 const or = (...args) => { 5705 return x => { 5706 for (let i = 0; i < args.length; i++) { 5707 if (args[i](x)) { 5708 return true; 5709 } 5710 } 5711 return false; 5712 }; 5713 }; 5714 const and = (...args) => { 5715 return x => { 5716 for (let i = 0; i < args.length; i++) { 5717 if (!args[i](x)) { 5718 return false; 5719 } 5720 } 5721 return true; 5722 }; 5723 }; 5724 5725 const isElement$4 = isElement$6; 5726 const isCaretCandidate$2 = isCaretCandidate$3; 5727 const isBlock$1 = matchStyleValues('display', 'block table'); 5728 const isFloated = matchStyleValues('float', 'left right'); 5729 const isValidElementCaretCandidate = and(isElement$4, isCaretCandidate$2, not(isFloated)); 5730 const isNotPre = not(matchStyleValues('white-space', 'pre pre-line pre-wrap')); 5731 const isText$7 = isText$a; 5732 const isBr$3 = isBr$6; 5733 const nodeIndex$1 = DOMUtils.nodeIndex; 5734 const resolveIndex$1 = getNodeUnsafe; 5735 const createRange$1 = doc => doc ? doc.createRange() : DOMUtils.DOM.createRng(); 5736 const isWhiteSpace$1 = chr => isString(chr) && /[\r\n\t ]/.test(chr); 5737 const isRange = rng => !!rng.setStart && !!rng.setEnd; 5738 const isHiddenWhiteSpaceRange = range => { 5739 const container = range.startContainer; 5740 const offset = range.startOffset; 5741 if (isWhiteSpace$1(range.toString()) && isNotPre(container.parentNode) && isText$a(container)) { 5742 const text = container.data; 5743 if (isWhiteSpace$1(text[offset - 1]) || isWhiteSpace$1(text[offset + 1])) { 5744 return true; 5745 } 5746 } 5747 return false; 5748 }; 5749 const getBrClientRect = brNode => { 5750 const doc = brNode.ownerDocument; 5751 const rng = createRange$1(doc); 5752 const nbsp$1 = doc.createTextNode(nbsp); 5753 const parentNode = brNode.parentNode; 5754 parentNode.insertBefore(nbsp$1, brNode); 5755 rng.setStart(nbsp$1, 0); 5756 rng.setEnd(nbsp$1, 1); 5757 const clientRect = clone$1(rng.getBoundingClientRect()); 5758 parentNode.removeChild(nbsp$1); 5759 return clientRect; 5760 }; 5761 const getBoundingClientRectWebKitText = rng => { 5762 const sc = rng.startContainer; 5763 const ec = rng.endContainer; 5764 const so = rng.startOffset; 5765 const eo = rng.endOffset; 5766 if (sc === ec && isText$a(ec) && so === 0 && eo === 1) { 5767 const newRng = rng.cloneRange(); 5768 newRng.setEndAfter(ec); 5769 return getBoundingClientRect$1(newRng); 5770 } else { 5771 return null; 5772 } 5773 }; 5774 const isZeroRect = r => r.left === 0 && r.right === 0 && r.top === 0 && r.bottom === 0; 5775 const getBoundingClientRect$1 = item => { 5776 var _a; 5777 let clientRect; 5778 const clientRects = item.getClientRects(); 5779 if (clientRects.length > 0) { 5780 clientRect = clone$1(clientRects[0]); 5781 } else { 5782 clientRect = clone$1(item.getBoundingClientRect()); 5783 } 5784 if (!isRange(item) && isBr$3(item) && isZeroRect(clientRect)) { 5785 return getBrClientRect(item); 5786 } 5787 if (isZeroRect(clientRect) && isRange(item)) { 5788 return (_a = getBoundingClientRectWebKitText(item)) !== null && _a !== void 0 ? _a : clientRect; 5789 } 5790 return clientRect; 5791 }; 5792 const collapseAndInflateWidth = (clientRect, toStart) => { 5793 const newClientRect = collapse(clientRect, toStart); 5794 newClientRect.width = 1; 5795 newClientRect.right = newClientRect.left + 1; 5796 return newClientRect; 5797 }; 5798 const getCaretPositionClientRects = caretPosition => { 5799 const clientRects = []; 5800 const addUniqueAndValidRect = clientRect => { 5801 if (clientRect.height === 0) { 5802 return; 5803 } 5804 if (clientRects.length > 0) { 5805 if (isEqual(clientRect, clientRects[clientRects.length - 1])) { 5806 return; 5807 } 5808 } 5809 clientRects.push(clientRect); 5810 }; 5811 const addCharacterOffset = (container, offset) => { 5812 const range = createRange$1(container.ownerDocument); 5813 if (offset < container.data.length) { 5814 if (isExtendingChar(container.data[offset])) { 5815 return; 5816 } 5817 if (isExtendingChar(container.data[offset - 1])) { 5818 range.setStart(container, offset); 5819 range.setEnd(container, offset + 1); 5820 if (!isHiddenWhiteSpaceRange(range)) { 5821 addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), false)); 5822 return; 5823 } 5824 } 5825 } 5826 if (offset > 0) { 5827 range.setStart(container, offset - 1); 5828 range.setEnd(container, offset); 5829 if (!isHiddenWhiteSpaceRange(range)) { 5830 addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), false)); 5831 } 5832 } 5833 if (offset < container.data.length) { 5834 range.setStart(container, offset); 5835 range.setEnd(container, offset + 1); 5836 if (!isHiddenWhiteSpaceRange(range)) { 5837 addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), true)); 5838 } 5839 } 5840 }; 5841 const container = caretPosition.container(); 5842 const offset = caretPosition.offset(); 5843 if (isText$7(container)) { 5844 addCharacterOffset(container, offset); 5845 return clientRects; 5846 } 5847 if (isElement$4(container)) { 5848 if (caretPosition.isAtEnd()) { 5849 const node = resolveIndex$1(container, offset); 5850 if (isText$7(node)) { 5851 addCharacterOffset(node, node.data.length); 5852 } 5853 if (isValidElementCaretCandidate(node) && !isBr$3(node)) { 5854 addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), false)); 5855 } 5856 } else { 5857 const node = resolveIndex$1(container, offset); 5858 if (isText$7(node)) { 5859 addCharacterOffset(node, 0); 5860 } 5861 if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) { 5862 addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), false)); 5863 return clientRects; 5864 } 5865 const beforeNode = resolveIndex$1(caretPosition.container(), caretPosition.offset() - 1); 5866 if (isValidElementCaretCandidate(beforeNode) && !isBr$3(beforeNode)) { 5867 if (isBlock$1(beforeNode) || isBlock$1(node) || !isValidElementCaretCandidate(node)) { 5868 addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(beforeNode), false)); 5869 } 5870 } 5871 if (isValidElementCaretCandidate(node)) { 5872 addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), true)); 5873 } 5874 } 5875 } 5876 return clientRects; 5877 }; 5878 const CaretPosition = (container, offset, clientRects) => { 5879 const isAtStart = () => { 5880 if (isText$7(container)) { 5881 return offset === 0; 5882 } 5883 return offset === 0; 5884 }; 5885 const isAtEnd = () => { 5886 if (isText$7(container)) { 5887 return offset >= container.data.length; 5888 } 5889 return offset >= container.childNodes.length; 5890 }; 5891 const toRange = () => { 5892 const range = createRange$1(container.ownerDocument); 5893 range.setStart(container, offset); 5894 range.setEnd(container, offset); 5895 return range; 5896 }; 5897 const getClientRects = () => { 5898 if (!clientRects) { 5899 clientRects = getCaretPositionClientRects(CaretPosition(container, offset)); 5900 } 5901 return clientRects; 5902 }; 5903 const isVisible = () => getClientRects().length > 0; 5904 const isEqual = caretPosition => caretPosition && container === caretPosition.container() && offset === caretPosition.offset(); 5905 const getNode = before => resolveIndex$1(container, before ? offset - 1 : offset); 5906 return { 5907 container: constant(container), 5908 offset: constant(offset), 5909 toRange, 5910 getClientRects, 5911 isVisible, 5912 isAtStart, 5913 isAtEnd, 5914 isEqual, 5915 getNode 5916 }; 5917 }; 5918 CaretPosition.fromRangeStart = range => CaretPosition(range.startContainer, range.startOffset); 5919 CaretPosition.fromRangeEnd = range => CaretPosition(range.endContainer, range.endOffset); 5920 CaretPosition.after = node => CaretPosition(node.parentNode, nodeIndex$1(node) + 1); 5921 CaretPosition.before = node => CaretPosition(node.parentNode, nodeIndex$1(node)); 5922 CaretPosition.isAbove = (pos1, pos2) => lift2(head(pos2.getClientRects()), last$3(pos1.getClientRects()), isAbove$1).getOr(false); 5923 CaretPosition.isBelow = (pos1, pos2) => lift2(last$3(pos2.getClientRects()), head(pos1.getClientRects()), isBelow$1).getOr(false); 5924 CaretPosition.isAtStart = pos => pos ? pos.isAtStart() : false; 5925 CaretPosition.isAtEnd = pos => pos ? pos.isAtEnd() : false; 5926 CaretPosition.isTextPosition = pos => pos ? isText$a(pos.container()) : false; 5927 CaretPosition.isElementPosition = pos => !CaretPosition.isTextPosition(pos); 5928 5929 const trimEmptyTextNode$1 = (dom, node) => { 5930 if (isText$a(node) && node.data.length === 0) { 5931 dom.remove(node); 5932 } 5933 }; 5934 const insertNode = (dom, rng, node) => { 5935 rng.insertNode(node); 5936 trimEmptyTextNode$1(dom, node.previousSibling); 5937 trimEmptyTextNode$1(dom, node.nextSibling); 5938 }; 5939 const insertFragment = (dom, rng, frag) => { 5940 const firstChild = Optional.from(frag.firstChild); 5941 const lastChild = Optional.from(frag.lastChild); 5942 rng.insertNode(frag); 5943 firstChild.each(child => trimEmptyTextNode$1(dom, child.previousSibling)); 5944 lastChild.each(child => trimEmptyTextNode$1(dom, child.nextSibling)); 5945 }; 5946 const rangeInsertNode = (dom, rng, node) => { 5947 if (isDocumentFragment(node)) { 5948 insertFragment(dom, rng, node); 5949 } else { 5950 insertNode(dom, rng, node); 5951 } 5952 }; 5953 5954 const isText$6 = isText$a; 5955 const isBogus = isBogus$2; 5956 const nodeIndex = DOMUtils.nodeIndex; 5957 const normalizedParent = node => { 5958 const parentNode = node.parentNode; 5959 if (isBogus(parentNode)) { 5960 return normalizedParent(parentNode); 5961 } 5962 return parentNode; 5963 }; 5964 const getChildNodes = node => { 5965 if (!node) { 5966 return []; 5967 } 5968 return reduce(node.childNodes, (result, node) => { 5969 if (isBogus(node) && node.nodeName !== 'BR') { 5970 result = result.concat(getChildNodes(node)); 5971 } else { 5972 result.push(node); 5973 } 5974 return result; 5975 }, []); 5976 }; 5977 const normalizedTextOffset = (node, offset) => { 5978 let tempNode = node; 5979 while (tempNode = tempNode.previousSibling) { 5980 if (!isText$6(tempNode)) { 5981 break; 5982 } 5983 offset += tempNode.data.length; 5984 } 5985 return offset; 5986 }; 5987 const equal = a => b => a === b; 5988 const normalizedNodeIndex = node => { 5989 let nodes, index; 5990 nodes = getChildNodes(normalizedParent(node)); 5991 index = findIndex$1(nodes, equal(node), node); 5992 nodes = nodes.slice(0, index + 1); 5993 const numTextFragments = reduce(nodes, (result, node, i) => { 5994 if (isText$6(node) && isText$6(nodes[i - 1])) { 5995 result++; 5996 } 5997 return result; 5998 }, 0); 5999 nodes = filter$3(nodes, matchNodeNames([node.nodeName])); 6000 index = findIndex$1(nodes, equal(node), node); 6001 return index - numTextFragments; 6002 }; 6003 const createPathItem = node => { 6004 const name = isText$6(node) ? 'text()' : node.nodeName.toLowerCase(); 6005 return name + '[' + normalizedNodeIndex(node) + ']'; 6006 }; 6007 const parentsUntil$1 = (root, node, predicate) => { 6008 const parents = []; 6009 for (let tempNode = node.parentNode; tempNode && tempNode !== root; tempNode = tempNode.parentNode) { 6010 if (predicate && predicate(tempNode)) { 6011 break; 6012 } 6013 parents.push(tempNode); 6014 } 6015 return parents; 6016 }; 6017 const create$b = (root, caretPosition) => { 6018 let path = []; 6019 let container = caretPosition.container(); 6020 let offset = caretPosition.offset(); 6021 let outputOffset; 6022 if (isText$6(container)) { 6023 outputOffset = normalizedTextOffset(container, offset); 6024 } else { 6025 const childNodes = container.childNodes; 6026 if (offset >= childNodes.length) { 6027 outputOffset = 'after'; 6028 offset = childNodes.length - 1; 6029 } else { 6030 outputOffset = 'before'; 6031 } 6032 container = childNodes[offset]; 6033 } 6034 path.push(createPathItem(container)); 6035 let parents = parentsUntil$1(root, container); 6036 parents = filter$3(parents, not(isBogus$2)); 6037 path = path.concat(map$1(parents, node => { 6038 return createPathItem(node); 6039 })); 6040 return path.reverse().join('/') + ',' + outputOffset; 6041 }; 6042 const resolvePathItem = (node, name, index) => { 6043 let nodes = getChildNodes(node); 6044 nodes = filter$3(nodes, (node, index) => { 6045 return !isText$6(node) || !isText$6(nodes[index - 1]); 6046 }); 6047 nodes = filter$3(nodes, matchNodeNames([name])); 6048 return nodes[index]; 6049 }; 6050 const findTextPosition = (container, offset) => { 6051 let node = container; 6052 let targetOffset = 0; 6053 while (isText$6(node)) { 6054 const dataLen = node.data.length; 6055 if (offset >= targetOffset && offset <= targetOffset + dataLen) { 6056 container = node; 6057 offset = offset - targetOffset; 6058 break; 6059 } 6060 if (!isText$6(node.nextSibling)) { 6061 container = node; 6062 offset = dataLen; 6063 break; 6064 } 6065 targetOffset += dataLen; 6066 node = node.nextSibling; 6067 } 6068 if (isText$6(container) && offset > container.data.length) { 6069 offset = container.data.length; 6070 } 6071 return CaretPosition(container, offset); 6072 }; 6073 const resolve$1 = (root, path) => { 6074 if (!path) { 6075 return null; 6076 } 6077 const parts = path.split(','); 6078 const paths = parts[0].split('/'); 6079 const offset = parts.length > 1 ? parts[1] : 'before'; 6080 const container = reduce(paths, (result, value) => { 6081 const match = /([\w\-\(\)]+)\[([0-9]+)\]/.exec(value); 6082 if (!match) { 6083 return null; 6084 } 6085 if (match[1] === 'text()') { 6086 match[1] = '#text'; 6087 } 6088 return resolvePathItem(result, match[1], parseInt(match[2], 10)); 6089 }, root); 6090 if (!container) { 6091 return null; 6092 } 6093 if (!isText$6(container) && container.parentNode) { 6094 let nodeOffset; 6095 if (offset === 'after') { 6096 nodeOffset = nodeIndex(container) + 1; 6097 } else { 6098 nodeOffset = nodeIndex(container); 6099 } 6100 return CaretPosition(container.parentNode, nodeOffset); 6101 } 6102 return findTextPosition(container, parseInt(offset, 10)); 6103 }; 6104 6105 const isContentEditableFalse$9 = isContentEditableFalse$b; 6106 const getNormalizedTextOffset$1 = (trim, container, offset) => { 6107 let trimmedOffset = trim(container.data.slice(0, offset)).length; 6108 for (let node = container.previousSibling; node && isText$a(node); node = node.previousSibling) { 6109 trimmedOffset += trim(node.data).length; 6110 } 6111 return trimmedOffset; 6112 }; 6113 const getPoint = (dom, trim, normalized, rng, start) => { 6114 const container = start ? rng.startContainer : rng.endContainer; 6115 let offset = start ? rng.startOffset : rng.endOffset; 6116 const point = []; 6117 const root = dom.getRoot(); 6118 if (isText$a(container)) { 6119 point.push(normalized ? getNormalizedTextOffset$1(trim, container, offset) : offset); 6120 } else { 6121 let after = 0; 6122 const childNodes = container.childNodes; 6123 if (offset >= childNodes.length && childNodes.length) { 6124 after = 1; 6125 offset = Math.max(0, childNodes.length - 1); 6126 } 6127 point.push(dom.nodeIndex(childNodes[offset], normalized) + after); 6128 } 6129 for (let node = container; node && node !== root; node = node.parentNode) { 6130 point.push(dom.nodeIndex(node, normalized)); 6131 } 6132 return point; 6133 }; 6134 const getLocation = (trim, selection, normalized, rng) => { 6135 const dom = selection.dom; 6136 const start = getPoint(dom, trim, normalized, rng, true); 6137 const forward = selection.isForward(); 6138 const fakeCaret = isRangeInCaretContainerBlock(rng) ? { isFakeCaret: true } : {}; 6139 if (!selection.isCollapsed()) { 6140 const end = getPoint(dom, trim, normalized, rng, false); 6141 return { 6142 start, 6143 end, 6144 forward, 6145 ...fakeCaret 6146 }; 6147 } else { 6148 return { 6149 start, 6150 forward, 6151 ...fakeCaret 6152 }; 6153 } 6154 }; 6155 const findIndex = (dom, name, element) => { 6156 let count = 0; 6157 Tools.each(dom.select(name), node => { 6158 if (node.getAttribute('data-mce-bogus') === 'all') { 6159 return; 6160 } else if (node === element) { 6161 return false; 6162 } else { 6163 count++; 6164 return; 6165 } 6166 }); 6167 return count; 6168 }; 6169 const moveEndPoint$1 = (rng, start) => { 6170 let container = start ? rng.startContainer : rng.endContainer; 6171 let offset = start ? rng.startOffset : rng.endOffset; 6172 if (isElement$6(container) && container.nodeName === 'TR') { 6173 const childNodes = container.childNodes; 6174 container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)]; 6175 if (container) { 6176 offset = start ? 0 : container.childNodes.length; 6177 if (start) { 6178 rng.setStart(container, offset); 6179 } else { 6180 rng.setEnd(container, offset); 6181 } 6182 } 6183 } 6184 }; 6185 const normalizeTableCellSelection = rng => { 6186 moveEndPoint$1(rng, true); 6187 moveEndPoint$1(rng, false); 6188 return rng; 6189 }; 6190 const findSibling = (node, offset) => { 6191 if (isElement$6(node)) { 6192 node = getNode$1(node, offset); 6193 if (isContentEditableFalse$9(node)) { 6194 return node; 6195 } 6196 } 6197 if (isCaretContainer$2(node)) { 6198 if (isText$a(node) && isCaretContainerBlock$1(node)) { 6199 node = node.parentNode; 6200 } 6201 let sibling = node.previousSibling; 6202 if (isContentEditableFalse$9(sibling)) { 6203 return sibling; 6204 } 6205 sibling = node.nextSibling; 6206 if (isContentEditableFalse$9(sibling)) { 6207 return sibling; 6208 } 6209 } 6210 return undefined; 6211 }; 6212 const findAdjacentContentEditableFalseElm = rng => { 6213 return findSibling(rng.startContainer, rng.startOffset) || findSibling(rng.endContainer, rng.endOffset); 6214 }; 6215 const getOffsetBookmark = (trim, normalized, selection) => { 6216 const element = selection.getNode(); 6217 const rng = selection.getRng(); 6218 if (element.nodeName === 'IMG' || isContentEditableFalse$9(element)) { 6219 const name = element.nodeName; 6220 return { 6221 name, 6222 index: findIndex(selection.dom, name, element) 6223 }; 6224 } 6225 const sibling = findAdjacentContentEditableFalseElm(rng); 6226 if (sibling) { 6227 const name = sibling.tagName; 6228 return { 6229 name, 6230 index: findIndex(selection.dom, name, sibling) 6231 }; 6232 } 6233 return getLocation(trim, selection, normalized, rng); 6234 }; 6235 const getCaretBookmark = selection => { 6236 const rng = selection.getRng(); 6237 return { 6238 start: create$b(selection.dom.getRoot(), CaretPosition.fromRangeStart(rng)), 6239 end: create$b(selection.dom.getRoot(), CaretPosition.fromRangeEnd(rng)), 6240 forward: selection.isForward() 6241 }; 6242 }; 6243 const getRangeBookmark = selection => { 6244 return { 6245 rng: selection.getRng(), 6246 forward: selection.isForward() 6247 }; 6248 }; 6249 const createBookmarkSpan = (dom, id, filled) => { 6250 const args = { 6251 'data-mce-type': 'bookmark', 6252 id, 6253 'style': 'overflow:hidden;line-height:0px' 6254 }; 6255 return filled ? dom.create('span', args, '') : dom.create('span', args); 6256 }; 6257 const getPersistentBookmark = (selection, filled) => { 6258 const dom = selection.dom; 6259 let rng = selection.getRng(); 6260 const id = dom.uniqueId(); 6261 const collapsed = selection.isCollapsed(); 6262 const element = selection.getNode(); 6263 const name = element.nodeName; 6264 const forward = selection.isForward(); 6265 if (name === 'IMG') { 6266 return { 6267 name, 6268 index: findIndex(dom, name, element) 6269 }; 6270 } 6271 const rng2 = normalizeTableCellSelection(rng.cloneRange()); 6272 if (!collapsed) { 6273 rng2.collapse(false); 6274 const endBookmarkNode = createBookmarkSpan(dom, id + '_end', filled); 6275 rangeInsertNode(dom, rng2, endBookmarkNode); 6276 } 6277 rng = normalizeTableCellSelection(rng); 6278 rng.collapse(true); 6279 const startBookmarkNode = createBookmarkSpan(dom, id + '_start', filled); 6280 rangeInsertNode(dom, rng, startBookmarkNode); 6281 selection.moveToBookmark({ 6282 id, 6283 keep: true, 6284 forward 6285 }); 6286 return { 6287 id, 6288 forward 6289 }; 6290 }; 6291 const getBookmark$2 = (selection, type, normalized = false) => { 6292 if (type === 2) { 6293 return getOffsetBookmark(trim$1, normalized, selection); 6294 } else if (type === 3) { 6295 return getCaretBookmark(selection); 6296 } else if (type) { 6297 return getRangeBookmark(selection); 6298 } else { 6299 return getPersistentBookmark(selection, false); 6300 } 6301 }; 6302 const getUndoBookmark = curry(getOffsetBookmark, identity, true); 6303 6304 const value$1 = value => { 6305 const applyHelper = fn => fn(value); 6306 const constHelper = constant(value); 6307 const outputHelper = () => output; 6308 const output = { 6309 tag: true, 6310 inner: value, 6311 fold: (_onError, onValue) => onValue(value), 6312 isValue: always, 6313 isError: never, 6314 map: mapper => Result.value(mapper(value)), 6315 mapError: outputHelper, 6316 bind: applyHelper, 6317 exists: applyHelper, 6318 forall: applyHelper, 6319 getOr: constHelper, 6320 or: outputHelper, 6321 getOrThunk: constHelper, 6322 orThunk: outputHelper, 6323 getOrDie: constHelper, 6324 each: fn => { 6325 fn(value); 6326 }, 6327 toOptional: () => Optional.some(value) 6328 }; 6329 return output; 6330 }; 6331 const error = error => { 6332 const outputHelper = () => output; 6333 const output = { 6334 tag: false, 6335 inner: error, 6336 fold: (onError, _onValue) => onError(error), 6337 isValue: never, 6338 isError: always, 6339 map: outputHelper, 6340 mapError: mapper => Result.error(mapper(error)), 6341 bind: outputHelper, 6342 exists: never, 6343 forall: always, 6344 getOr: identity, 6345 or: identity, 6346 getOrThunk: apply$1, 6347 orThunk: apply$1, 6348 getOrDie: die(String(error)), 6349 each: noop, 6350 toOptional: Optional.none 6351 }; 6352 return output; 6353 }; 6354 const fromOption = (optional, err) => optional.fold(() => error(err), value$1); 6355 const Result = { 6356 value: value$1, 6357 error, 6358 fromOption 6359 }; 6360 6361 const generate = cases => { 6362 if (!isArray$1(cases)) { 6363 throw new Error('cases must be an array'); 6364 } 6365 if (cases.length === 0) { 6366 throw new Error('there must be at least one case'); 6367 } 6368 const constructors = []; 6369 const adt = {}; 6370 each$e(cases, (acase, count) => { 6371 const keys$1 = keys(acase); 6372 if (keys$1.length !== 1) { 6373 throw new Error('one and only one name per case'); 6374 } 6375 const key = keys$1[0]; 6376 const value = acase[key]; 6377 if (adt[key] !== undefined) { 6378 throw new Error('duplicate key detected:' + key); 6379 } else if (key === 'cata') { 6380 throw new Error('cannot have a case named cata (sorry)'); 6381 } else if (!isArray$1(value)) { 6382 throw new Error('case arguments must be an array'); 6383 } 6384 constructors.push(key); 6385 adt[key] = (...args) => { 6386 const argLength = args.length; 6387 if (argLength !== value.length) { 6388 throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength); 6389 } 6390 const match = branches => { 6391 const branchKeys = keys(branches); 6392 if (constructors.length !== branchKeys.length) { 6393 throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(',')); 6394 } 6395 const allReqd = forall(constructors, reqKey => { 6396 return contains$2(branchKeys, reqKey); 6397 }); 6398 if (!allReqd) { 6399 throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', ')); 6400 } 6401 return branches[key].apply(null, args); 6402 }; 6403 return { 6404 fold: (...foldArgs) => { 6405 if (foldArgs.length !== cases.length) { 6406 throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length); 6407 } 6408 const target = foldArgs[count]; 6409 return target.apply(null, args); 6410 }, 6411 match, 6412 log: label => { 6413 console.log(label, { 6414 constructors, 6415 constructor: key, 6416 params: args 6417 }); 6418 } 6419 }; 6420 }; 6421 }); 6422 return adt; 6423 }; 6424 const Adt = { generate }; 6425 6426 Adt.generate([ 6427 { 6428 bothErrors: [ 6429 'error1', 6430 'error2' 6431 ] 6432 }, 6433 { 6434 firstError: [ 6435 'error1', 6436 'value2' 6437 ] 6438 }, 6439 { 6440 secondError: [ 6441 'value1', 6442 'error2' 6443 ] 6444 }, 6445 { 6446 bothValues: [ 6447 'value1', 6448 'value2' 6449 ] 6450 } 6451 ]); 6452 const partition$1 = results => { 6453 const errors = []; 6454 const values = []; 6455 each$e(results, result => { 6456 result.fold(err => { 6457 errors.push(err); 6458 }, value => { 6459 values.push(value); 6460 }); 6461 }); 6462 return { 6463 errors, 6464 values 6465 }; 6466 }; 6467 6468 const isInlinePattern = pattern => pattern.type === 'inline-command' || pattern.type === 'inline-format'; 6469 const isBlockPattern = pattern => pattern.type === 'block-command' || pattern.type === 'block-format'; 6470 const normalizePattern = pattern => { 6471 const err = message => Result.error({ 6472 message, 6473 pattern 6474 }); 6475 const formatOrCmd = (name, onFormat, onCommand) => { 6476 if (pattern.format !== undefined) { 6477 let formats; 6478 if (isArray$1(pattern.format)) { 6479 if (!forall(pattern.format, isString)) { 6480 return err(name + ' pattern has non-string items in the `format` array'); 6481 } 6482 formats = pattern.format; 6483 } else if (isString(pattern.format)) { 6484 formats = [pattern.format]; 6485 } else { 6486 return err(name + ' pattern has non-string `format` parameter'); 6487 } 6488 return Result.value(onFormat(formats)); 6489 } else if (pattern.cmd !== undefined) { 6490 if (!isString(pattern.cmd)) { 6491 return err(name + ' pattern has non-string `cmd` parameter'); 6492 } 6493 return Result.value(onCommand(pattern.cmd, pattern.value)); 6494 } else { 6495 return err(name + ' pattern is missing both `format` and `cmd` parameters'); 6496 } 6497 }; 6498 if (!isObject(pattern)) { 6499 return err('Raw pattern is not an object'); 6500 } 6501 if (!isString(pattern.start)) { 6502 return err('Raw pattern is missing `start` parameter'); 6503 } 6504 if (pattern.end !== undefined) { 6505 if (!isString(pattern.end)) { 6506 return err('Inline pattern has non-string `end` parameter'); 6507 } 6508 if (pattern.start.length === 0 && pattern.end.length === 0) { 6509 return err('Inline pattern has empty `start` and `end` parameters'); 6510 } 6511 let start = pattern.start; 6512 let end = pattern.end; 6513 if (end.length === 0) { 6514 end = start; 6515 start = ''; 6516 } 6517 return formatOrCmd('Inline', format => ({ 6518 type: 'inline-format', 6519 start, 6520 end, 6521 format 6522 }), (cmd, value) => ({ 6523 type: 'inline-command', 6524 start, 6525 end, 6526 cmd, 6527 value 6528 })); 6529 } else if (pattern.replacement !== undefined) { 6530 if (!isString(pattern.replacement)) { 6531 return err('Replacement pattern has non-string `replacement` parameter'); 6532 } 6533 if (pattern.start.length === 0) { 6534 return err('Replacement pattern has empty `start` parameter'); 6535 } 6536 return Result.value({ 6537 type: 'inline-command', 6538 start: '', 6539 end: pattern.start, 6540 cmd: 'mceInsertContent', 6541 value: pattern.replacement 6542 }); 6543 } else { 6544 if (pattern.start.length === 0) { 6545 return err('Block pattern has empty `start` parameter'); 6546 } 6547 return formatOrCmd('Block', formats => ({ 6548 type: 'block-format', 6549 start: pattern.start, 6550 format: formats[0] 6551 }), (command, commandValue) => ({ 6552 type: 'block-command', 6553 start: pattern.start, 6554 cmd: command, 6555 value: commandValue 6556 })); 6557 } 6558 }; 6559 const getBlockPatterns = patterns => filter$5(patterns, isBlockPattern); 6560 const getInlinePatterns = patterns => filter$5(patterns, isInlinePattern); 6561 const createPatternSet = (patterns, dynamicPatternsLookup) => ({ 6562 inlinePatterns: getInlinePatterns(patterns), 6563 blockPatterns: getBlockPatterns(patterns), 6564 dynamicPatternsLookup 6565 }); 6566 const fromRawPatterns = patterns => { 6567 const normalized = partition$1(map$3(patterns, normalizePattern)); 6568 each$e(normalized.errors, err => console.error(err.message, err.pattern)); 6569 return normalized.values; 6570 }; 6571 const fromRawPatternsLookup = lookupFn => { 6572 return ctx => { 6573 const rawPatterns = lookupFn(ctx); 6574 return fromRawPatterns(rawPatterns); 6575 }; 6576 }; 6577 6578 const deviceDetection$1 = detect$2().deviceType; 6579 const isTouch = deviceDetection$1.isTouch(); 6580 const DOM$a = DOMUtils.DOM; 6581 const getHash = value => { 6582 const items = value.indexOf('=') > 0 ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/) : value.split(','); 6583 return foldl(items, (output, item) => { 6584 const arr = item.split('='); 6585 const key = arr[0]; 6586 const val = arr.length > 1 ? arr[1] : key; 6587 output[trim$3(key)] = trim$3(val); 6588 return output; 6589 }, {}); 6590 }; 6591 const isRegExp = x => is$4(x, RegExp); 6592 const option = name => editor => editor.options.get(name); 6593 const stringOrObjectProcessor = value => isString(value) || isObject(value); 6594 const bodyOptionProcessor = (editor, defaultValue = '') => value => { 6595 const valid = isString(value); 6596 if (valid) { 6597 if (value.indexOf('=') !== -1) { 6598 const bodyObj = getHash(value); 6599 return { 6600 value: get$a(bodyObj, editor.id).getOr(defaultValue), 6601 valid 6602 }; 6603 } else { 6604 return { 6605 value, 6606 valid 6607 }; 6608 } 6609 } else { 6610 return { 6611 valid: false, 6612 message: 'Must be a string.' 6613 }; 6614 } 6615 }; 6616 const register$7 = editor => { 6617 const registerOption = editor.options.register; 6618 registerOption('id', { 6619 processor: 'string', 6620 default: editor.id 6621 }); 6622 registerOption('selector', { processor: 'string' }); 6623 registerOption('target', { processor: 'object' }); 6624 registerOption('suffix', { processor: 'string' }); 6625 registerOption('cache_suffix', { processor: 'string' }); 6626 registerOption('base_url', { processor: 'string' }); 6627 registerOption('referrer_policy', { 6628 processor: 'string', 6629 default: '' 6630 }); 6631 registerOption('language_load', { 6632 processor: 'boolean', 6633 default: true 6634 }); 6635 registerOption('inline', { 6636 processor: 'boolean', 6637 default: false 6638 }); 6639 registerOption('iframe_attrs', { 6640 processor: 'object', 6641 default: {} 6642 }); 6643 registerOption('doctype', { 6644 processor: 'string', 6645 default: '<!DOCTYPE html>' 6646 }); 6647 registerOption('document_base_url', { 6648 processor: 'string', 6649 default: editor.documentBaseUrl 6650 }); 6651 registerOption('body_id', { 6652 processor: bodyOptionProcessor(editor, 'tinymce'), 6653 default: 'tinymce' 6654 }); 6655 registerOption('body_class', { 6656 processor: bodyOptionProcessor(editor), 6657 default: '' 6658 }); 6659 registerOption('content_security_policy', { 6660 processor: 'string', 6661 default: '' 6662 }); 6663 registerOption('br_in_pre', { 6664 processor: 'boolean', 6665 default: true 6666 }); 6667 registerOption('forced_root_block', { 6668 processor: value => { 6669 const valid = isString(value) && isNotEmpty(value); 6670 if (valid) { 6671 return { 6672 value, 6673 valid 6674 }; 6675 } else { 6676 return { 6677 valid: false, 6678 message: 'Must be a non-empty string.' 6679 }; 6680 } 6681 }, 6682 default: 'p' 6683 }); 6684 registerOption('forced_root_block_attrs', { 6685 processor: 'object', 6686 default: {} 6687 }); 6688 registerOption('newline_behavior', { 6689 processor: value => { 6690 const valid = contains$2([ 6691 'block', 6692 'linebreak', 6693 'invert', 6694 'default' 6695 ], value); 6696 return valid ? { 6697 value, 6698 valid 6699 } : { 6700 valid: false, 6701 message: 'Must be one of: block, linebreak, invert or default.' 6702 }; 6703 }, 6704 default: 'default' 6705 }); 6706 registerOption('br_newline_selector', { 6707 processor: 'string', 6708 default: '.mce-toc h2,figcaption,caption' 6709 }); 6710 registerOption('no_newline_selector', { 6711 processor: 'string', 6712 default: '' 6713 }); 6714 registerOption('keep_styles', { 6715 processor: 'boolean', 6716 default: true 6717 }); 6718 registerOption('end_container_on_empty_block', { 6719 processor: value => { 6720 if (isBoolean(value)) { 6721 return { 6722 valid: true, 6723 value 6724 }; 6725 } else if (isString(value)) { 6726 return { 6727 valid: true, 6728 value 6729 }; 6730 } else { 6731 return { 6732 valid: false, 6733 message: 'Must be boolean or a string' 6734 }; 6735 } 6736 }, 6737 default: 'blockquote' 6738 }); 6739 registerOption('font_size_style_values', { 6740 processor: 'string', 6741 default: 'xx-small,x-small,small,medium,large,x-large,xx-large' 6742 }); 6743 registerOption('font_size_legacy_values', { 6744 processor: 'string', 6745 default: 'xx-small,small,medium,large,x-large,xx-large,300%' 6746 }); 6747 registerOption('font_size_classes', { 6748 processor: 'string', 6749 default: '' 6750 }); 6751 registerOption('automatic_uploads', { 6752 processor: 'boolean', 6753 default: true 6754 }); 6755 registerOption('images_reuse_filename', { 6756 processor: 'boolean', 6757 default: false 6758 }); 6759 registerOption('images_replace_blob_uris', { 6760 processor: 'boolean', 6761 default: true 6762 }); 6763 registerOption('icons', { 6764 processor: 'string', 6765 default: '' 6766 }); 6767 registerOption('icons_url', { 6768 processor: 'string', 6769 default: '' 6770 }); 6771 registerOption('images_upload_url', { 6772 processor: 'string', 6773 default: '' 6774 }); 6775 registerOption('images_upload_base_path', { 6776 processor: 'string', 6777 default: '' 6778 }); 6779 registerOption('images_upload_credentials', { 6780 processor: 'boolean', 6781 default: false 6782 }); 6783 registerOption('images_upload_handler', { processor: 'function' }); 6784 registerOption('language', { 6785 processor: 'string', 6786 default: 'en' 6787 }); 6788 registerOption('language_url', { 6789 processor: 'string', 6790 default: '' 6791 }); 6792 registerOption('entity_encoding', { 6793 processor: 'string', 6794 default: 'named' 6795 }); 6796 registerOption('indent', { 6797 processor: 'boolean', 6798 default: true 6799 }); 6800 registerOption('indent_before', { 6801 processor: 'string', 6802 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,
6802summary,article,hgroup,aside,f
vendor: 18,894 bytes, lines 6802-7354
6802igure,figcaption,option,optgroup,datalist' 6803 }); 6804 registerOption('indent_after', { 6805 processor: 'string', 6806 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,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist' 6807 }); 6808 registerOption('indent_use_margin', { 6809 processor: 'boolean', 6810 default: false 6811 }); 6812 registerOption('indentation', { 6813 processor: 'string', 6814 default: '40px' 6815 }); 6816 registerOption('content_css', { 6817 processor: value => { 6818 const valid = value === false || isString(value) || isArrayOf(value, isString); 6819 if (valid) { 6820 if (isString(value)) { 6821 return { 6822 value: map$3(value.split(','), trim$3), 6823 valid 6824 }; 6825 } else if (isArray$1(value)) { 6826 return { 6827 value, 6828 valid 6829 }; 6830 } else if (value === false) { 6831 return { 6832 value: [], 6833 valid 6834 }; 6835 } else { 6836 return { 6837 value, 6838 valid 6839 }; 6840 } 6841 } else { 6842 return { 6843 valid: false, 6844 message: 'Must be false, a string or an array of strings.' 6845 }; 6846 } 6847 }, 6848 default: isInline(editor) ? [] : ['default'] 6849 }); 6850 registerOption('content_style', { processor: 'string' }); 6851 registerOption('content_css_cors', { 6852 processor: 'boolean', 6853 default: false 6854 }); 6855 registerOption('font_css', { 6856 processor: value => { 6857 const valid = isString(value) || isArrayOf(value, isString); 6858 if (valid) { 6859 const newValue = isArray$1(value) ? value : map$3(value.split(','), trim$3); 6860 return { 6861 value: newValue, 6862 valid 6863 }; 6864 } else { 6865 return { 6866 valid: false, 6867 message: 'Must be a string or an array of strings.' 6868 }; 6869 } 6870 }, 6871 default: [] 6872 }); 6873 registerOption('inline_boundaries', { 6874 processor: 'boolean', 6875 default: true 6876 }); 6877 registerOption('inline_boundaries_selector', { 6878 processor: 'string', 6879 default: 'a[href],code,span.mce-annotation' 6880 }); 6881 registerOption('object_resizing', { 6882 processor: value => { 6883 const valid = isBoolean(value) || isString(value); 6884 if (valid) { 6885 if (value === false || deviceDetection$1.isiPhone() || deviceDetection$1.isiPad()) { 6886 return { 6887 value: '', 6888 valid 6889 }; 6890 } else { 6891 return { 6892 value: value === true ? 'table,img,figure.image,div,video,iframe' : value, 6893 valid 6894 }; 6895 } 6896 } else { 6897 return { 6898 valid: false, 6899 message: 'Must be boolean or a string' 6900 }; 6901 } 6902 }, 6903 default: !isTouch 6904 }); 6905 registerOption('resize_img_proportional', { 6906 processor: 'boolean', 6907 default: true 6908 }); 6909 registerOption('event_root', { processor: 'object' }); 6910 registerOption('service_message', { processor: 'string' }); 6911 registerOption('theme', { 6912 processor: value => value === false || isString(value) || isFunction(value), 6913 default: 'silver' 6914 }); 6915 registerOption('theme_url', { processor: 'string' }); 6916 registerOption('formats', { processor: 'object' }); 6917 registerOption('format_empty_lines', { 6918 processor: 'boolean', 6919 default: false 6920 }); 6921 registerOption('format_noneditable_selector', { 6922 processor: 'string', 6923 default: '' 6924 }); 6925 registerOption('preview_styles', { 6926 processor: value => { 6927 const valid = value === false || isString(value); 6928 if (valid) { 6929 return { 6930 value: value === false ? '' : value, 6931 valid 6932 }; 6933 } else { 6934 return { 6935 valid: false, 6936 message: 'Must be false or a string' 6937 }; 6938 } 6939 }, 6940 default: 'font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow' 6941 }); 6942 registerOption('custom_ui_selector', { 6943 processor: 'string', 6944 default: '' 6945 }); 6946 registerOption('hidden_input', { 6947 processor: 'boolean', 6948 default: true 6949 }); 6950 registerOption('submit_patch', { 6951 processor: 'boolean', 6952 default: true 6953 }); 6954 registerOption('encoding', { processor: 'string' }); 6955 registerOption('add_form_submit_trigger', { 6956 processor: 'boolean', 6957 default: true 6958 }); 6959 registerOption('add_unload_trigger', { 6960 processor: 'boolean', 6961 default: true 6962 }); 6963 registerOption('custom_undo_redo_levels', { 6964 processor: 'number', 6965 default: 0 6966 }); 6967 registerOption('disable_nodechange', { 6968 processor: 'boolean', 6969 default: false 6970 }); 6971 registerOption('readonly', { 6972 processor: 'boolean', 6973 default: false 6974 }); 6975 registerOption('plugins', { 6976 processor: 'string[]', 6977 default: [] 6978 }); 6979 registerOption('external_plugins', { processor: 'object' }); 6980 registerOption('forced_plugins', { processor: 'string[]' }); 6981 registerOption('model', { 6982 processor: 'string', 6983 default: editor.hasPlugin('rtc') ? 'plugin' : 'dom' 6984 }); 6985 registerOption('model_url', { processor: 'string' }); 6986 registerOption('block_unsupported_drop', { 6987 processor: 'boolean', 6988 default: true 6989 }); 6990 registerOption('visual', { 6991 processor: 'boolean', 6992 default: true 6993 }); 6994 registerOption('visual_table_class', { 6995 processor: 'string', 6996 default: 'mce-item-table' 6997 }); 6998 registerOption('visual_anchor_class', { 6999 processor: 'string', 7000 default: 'mce-item-anchor' 7001 }); 7002 registerOption('iframe_aria_text', { 7003 processor: 'string', 7004 default: 'Rich Text Area. Press ALT-0 for help.' 7005 }); 7006 registerOption('setup', { processor: 'function' }); 7007 registerOption('init_instance_callback', { processor: 'function' }); 7008 registerOption('url_converter', { 7009 processor: 'function', 7010 default: editor.convertURL 7011 }); 7012 registerOption('url_converter_scope', { 7013 processor: 'object', 7014 default: editor 7015 }); 7016 registerOption('urlconverter_callback', { processor: 'function' }); 7017 registerOption('allow_conditional_comments', { 7018 processor: 'boolean', 7019 default: false 7020 }); 7021 registerOption('allow_html_data_urls', { 7022 processor: 'boolean', 7023 default: false 7024 }); 7025 registerOption('allow_svg_data_urls', { processor: 'boolean' }); 7026 registerOption('allow_html_in_named_anchor', { 7027 processor: 'boolean', 7028 default: false 7029 }); 7030 registerOption('allow_script_urls', { 7031 processor: 'boolean', 7032 default: false 7033 }); 7034 registerOption('allow_unsafe_link_target', { 7035 processor: 'boolean', 7036 default: false 7037 }); 7038 registerOption('convert_fonts_to_spans', { 7039 processor: 'boolean', 7040 default: true, 7041 deprecated: true 7042 }); 7043 registerOption('fix_list_elements', { 7044 processor: 'boolean', 7045 default: false 7046 }); 7047 registerOption('preserve_cdata', { 7048 processor: 'boolean', 7049 default: false 7050 }); 7051 registerOption('remove_trailing_brs', { processor: 'boolean' }); 7052 registerOption('inline_styles', { 7053 processor: 'boolean', 7054 default: true, 7055 deprecated: true 7056 }); 7057 registerOption('element_format', { 7058 processor: 'string', 7059 default: 'html' 7060 }); 7061 registerOption('entities', { processor: 'string' }); 7062 registerOption('schema', { 7063 processor: 'string', 7064 default: 'html5' 7065 }); 7066 registerOption('convert_urls', { 7067 processor: 'boolean', 7068 default: true 7069 }); 7070 registerOption('relative_urls', { 7071 processor: 'boolean', 7072 default: true 7073 }); 7074 registerOption('remove_script_host', { 7075 processor: 'boolean', 7076 default: true 7077 }); 7078 registerOption('custom_elements', { processor: 'string' }); 7079 registerOption('extended_valid_elements', { processor: 'string' }); 7080 registerOption('invalid_elements', { processor: 'string' }); 7081 registerOption('invalid_styles', { processor: stringOrObjectProcessor }); 7082 registerOption('valid_children', { processor: 'string' }); 7083 registerOption('valid_classes', { processor: stringOrObjectProcessor }); 7084 registerOption('valid_elements', { processor: 'string' }); 7085 registerOption('valid_styles', { processor: stringOrObjectProcessor }); 7086 registerOption('verify_html', { 7087 processor: 'boolean', 7088 default: true 7089 }); 7090 registerOption('auto_focus', { processor: value => isString(value) || value === true }); 7091 registerOption('browser_spellcheck', { 7092 processor: 'boolean', 7093 default: false 7094 }); 7095 registerOption('protect', { processor: 'array' }); 7096 registerOption('images_file_types', { 7097 processor: 'string', 7098 default: 'jpeg,jpg,jpe,jfi,jif,jfif,png,gif,bmp,webp' 7099 }); 7100 registerOption('deprecation_warnings', { 7101 processor: 'boolean', 7102 default: true 7103 }); 7104 registerOption('a11y_advanced_options', { 7105 processor: 'boolean', 7106 default: false 7107 }); 7108 registerOption('api_key', { processor: 'string' }); 7109 registerOption('paste_block_drop', { 7110 processor: 'boolean', 7111 default: false 7112 }); 7113 registerOption('paste_data_images', { 7114 processor: 'boolean', 7115 default: true 7116 }); 7117 registerOption('paste_preprocess', { processor: 'function' }); 7118 registerOption('paste_postprocess', { processor: 'function' }); 7119 registerOption('paste_webkit_styles', { 7120 processor: 'string', 7121 default: 'none' 7122 }); 7123 registerOption('paste_remove_styles_if_webkit', { 7124 processor: 'boolean', 7125 default: true 7126 }); 7127 registerOption('paste_merge_formats', { 7128 processor: 'boolean', 7129 default: true 7130 }); 7131 registerOption('smart_paste', { 7132 processor: 'boolean', 7133 default: true 7134 }); 7135 registerOption('paste_as_text', { 7136 processor: 'boolean', 7137 default: false 7138 }); 7139 registerOption('paste_tab_spaces', { 7140 processor: 'number', 7141 default: 4 7142 }); 7143 registerOption('text_patterns', { 7144 processor: value => { 7145 if (isArrayOf(value, isObject) || value === false) { 7146 const patterns = value === false ? [] : value; 7147 return { 7148 value: fromRawPatterns(patterns), 7149 valid: true 7150 }; 7151 } else { 7152 return { 7153 valid: false, 7154 message: 'Must be an array of objects or false.' 7155 }; 7156 } 7157 }, 7158 default: [ 7159 { 7160 start: '*', 7161 end: '*', 7162 format: 'italic' 7163 }, 7164 { 7165 start: '**', 7166 end: '**', 7167 format: 'bold' 7168 }, 7169 { 7170 start: '#', 7171 format: 'h1' 7172 }, 7173 { 7174 start: '##', 7175 format: 'h2' 7176 }, 7177 { 7178 start: '###', 7179 format: 'h3' 7180 }, 7181 { 7182 start: '####', 7183 format: 'h4' 7184 }, 7185 { 7186 start: '#####', 7187 format: 'h5' 7188 }, 7189 { 7190 start: '######', 7191 format: 'h6' 7192 }, 7193 { 7194 start: '1. ', 7195 cmd: 'InsertOrderedList' 7196 }, 7197 { 7198 start: '* ', 7199 cmd: 'InsertUnorderedList' 7200 }, 7201 { 7202 start: '- ', 7203 cmd: 'InsertUnorderedList' 7204 } 7205 ] 7206 }); 7207 registerOption('text_patterns_lookup', { 7208 processor: value => { 7209 if (isFunction(value)) { 7210 return { 7211 value: fromRawPatternsLookup(value), 7212 valid: true 7213 }; 7214 } else { 7215 return { 7216 valid: false, 7217 message: 'Must be a single function' 7218 }; 7219 } 7220 }, 7221 default: _ctx => [] 7222 }); 7223 registerOption('noneditable_class', { 7224 processor: 'string', 7225 default: 'mceNonEditable' 7226 }); 7227 registerOption('editable_class', { 7228 processor: 'string', 7229 default: 'mceEditable' 7230 }); 7231 registerOption('noneditable_regexp', { 7232 processor: value => { 7233 if (isArrayOf(value, isRegExp)) { 7234 return { 7235 value, 7236 valid: true 7237 }; 7238 } else if (isRegExp(value)) { 7239 return { 7240 value: [value], 7241 valid: true 7242 }; 7243 } else { 7244 return { 7245 valid: false, 7246 message: 'Must be a RegExp or an array of RegExp.' 7247 }; 7248 } 7249 }, 7250 default: [] 7251 }); 7252 registerOption('table_tab_navigation', { 7253 processor: 'boolean', 7254 default: true 7255 }); 7256 registerOption('highlight_on_focus', { 7257 processor: 'boolean', 7258 default: false 7259 }); 7260 registerOption('xss_sanitization', { 7261 processor: 'boolean', 7262 default: true 7263 }); 7264 editor.on('ScriptsLoaded', () => { 7265 registerOption('directionality', { 7266 processor: 'string', 7267 default: I18n.isRtl() ? 'rtl' : undefined 7268 }); 7269 registerOption('placeholder', { 7270 processor: 'string', 7271 default: DOM$a.getAttrib(editor.getElement(), 'placeholder') 7272 }); 7273 }); 7274 }; 7275 const getIframeAttrs = option('iframe_attrs'); 7276 const getDocType = option('doctype'); 7277 const getDocumentBaseUrl = option('document_base_url'); 7278 const getBodyId = option('body_id'); 7279 const getBodyClass = option('body_class'); 7280 const getContentSecurityPolicy = option('content_security_policy'); 7281 const shouldPutBrInPre$1 = option('br_in_pre'); 7282 const getForcedRootBlock = option('forced_root_block'); 7283 const getForcedRootBlockAttrs = option('forced_root_block_attrs'); 7284 const getNewlineBehavior = option('newline_behavior'); 7285 const getBrNewLineSelector = option('br_newline_selector'); 7286 const getNoNewLineSelector = option('no_newline_selector'); 7287 const shouldKeepStyles = option('keep_styles'); 7288 const shouldEndContainerOnEmptyBlock = option('end_container_on_empty_block'); 7289 const isAutomaticUploadsEnabled = option('automatic_uploads'); 7290 const shouldReuseFileName = option('images_reuse_filename'); 7291 const shouldReplaceBlobUris = option('images_replace_blob_uris'); 7292 const getIconPackName = option('icons'); 7293 const getIconsUrl = option('icons_url'); 7294 const getImageUploadUrl = option('images_upload_url'); 7295 const getImageUploadBasePath = option('images_upload_base_path'); 7296 const getImagesUploadCredentials = option('images_upload_credentials'); 7297 const getImagesUploadHandler = option('images_upload_handler'); 7298 const shouldUseContentCssCors = option('content_css_cors'); 7299 const getReferrerPolicy = option('referrer_policy'); 7300 const getLanguageCode = option('language'); 7301 const getLanguageUrl = option('language_url'); 7302 const shouldIndentUseMargin = option('indent_use_margin'); 7303 const getIndentation = option('indentation'); 7304 const getContentCss = option('content_css'); 7305 const getContentStyle = option('content_style'); 7306 const getFontCss = option('font_css'); 7307 const getDirectionality = option('directionality'); 7308 const getInlineBoundarySelector = option('inline_boundaries_selector'); 7309 const getObjectResizing = option('object_resizing'); 7310 const getResizeImgProportional = option('resize_img_proportional'); 7311 const getPlaceholder = option('placeholder'); 7312 const getEventRoot = option('event_root'); 7313 const getServiceMessage = option('service_message'); 7314 const getTheme = option('theme'); 7315 const getThemeUrl = option('theme_url'); 7316 const getModel = option('model'); 7317 const getModelUrl = option('model_url'); 7318 const isInlineBoundariesEnabled = option('inline_boundaries'); 7319 const getFormats = option('formats'); 7320 const getPreviewStyles = option('preview_styles'); 7321 const canFormatEmptyLines = option('format_empty_lines'); 7322 const getFormatNoneditableSelector = option('format_noneditable_selector'); 7323 const getCustomUiSelector = option('custom_ui_selector'); 7324 const isInline = option('inline'); 7325 const hasHiddenInput = option('hidden_input'); 7326 const shouldPatchSubmit = option('submit_patch'); 7327 const shouldAddFormSubmitTrigger = option('add_form_submit_trigger'); 7328 const shouldAddUnloadTrigger = option('add_unload_trigger'); 7329 const getCustomUndoRedoLevels = option('custom_undo_redo_levels'); 7330 const shouldDisableNodeChange = option('disable_nodechange'); 7331 const isReadOnly$1 = option('readonly'); 7332 const hasContentCssCors = option('content_css_cors'); 7333 const getPlugins = option('plugins'); 7334 const getExternalPlugins$1 = option('external_plugins'); 7335 const shouldBlockUnsupportedDrop = option('block_unsupported_drop'); 7336 const isVisualAidsEnabled = option('visual'); 7337 const getVisualAidsTableClass = option('visual_table_class'); 7338 const getVisualAidsAnchorClass = option('visual_anchor_class'); 7339 const getIframeAriaText = option('iframe_aria_text'); 7340 const getSetupCallback = option('setup'); 7341 const getInitInstanceCallback = option('init_instance_callback'); 7342 const getUrlConverterCallback = option('urlconverter_callback'); 7343 const getAutoFocus = option('auto_focus'); 7344 const shouldBrowserSpellcheck = option('browser_spellcheck'); 7345 const getProtect = option('protect'); 7346 const shouldPasteBlockDrop = option('paste_block_drop'); 7347 const shouldPasteDataImages = option('paste_data_images'); 7348 const getPastePreProcess = option('paste_preprocess'); 7349 const getPastePostProcess = option('paste_postprocess'); 7350 const getPasteWebkitStyles = option('paste_webkit_styles'); 7351 const shouldPasteRemoveWebKitStyles = option('paste_remove_styles_if_webkit'); 7352 const shouldPasteMergeFormats = option('paste_merge_formats'); 7353 const isSmartPasteEnabled = option('smart_paste'); 7354 const isPasteAsTextEnabled = option('paste_as_text');
vendor: 7,864 bytes, lines 7355-7544
7355 const getPasteTabSpaces = option('paste_tab_spaces'); 7356 const shouldAllowHtmlDataUrls = option('allow_html_data_urls'); 7357 const getTextPatterns = option('text_patterns'); 7358 const getTextPatternsLookup = option('text_patterns_lookup'); 7359 const getNonEditableClass = option('noneditable_class'); 7360 const getEditableClass = option('editable_class'); 7361 const getNonEditableRegExps = option('noneditable_regexp'); 7362 const shouldPreserveCData = option('preserve_cdata'); 7363 const shouldHighlightOnFocus = option('highlight_on_focus'); 7364 const shouldSanitizeXss = option('xss_sanitization'); 7365 const hasTextPatternsLookup = editor => editor.options.isSet('text_patterns_lookup'); 7366 const getFontStyleValues = editor => Tools.explode(editor.options.get('font_size_style_values')); 7367 const getFontSizeClasses = editor => Tools.explode(editor.options.get('font_size_classes')); 7368 const isEncodingXml = editor => editor.options.get('encoding') === 'xml'; 7369 const getAllowedImageFileTypes = editor => Tools.explode(editor.options.get('images_file_types')); 7370 const hasTableTabNavigation = option('table_tab_navigation'); 7371 7372 const isElement$3 = isElement$6; 7373 const isText$5 = isText$a; 7374 const removeNode$1 = node => { 7375 const parentNode = node.parentNode; 7376 if (parentNode) { 7377 parentNode.removeChild(node); 7378 } 7379 }; 7380 const trimCount = text => { 7381 const trimmedText = trim$1(text); 7382 return { 7383 count: text.length - trimmedText.length, 7384 text: trimmedText 7385 }; 7386 }; 7387 const deleteZwspChars = caretContainer => { 7388 let idx; 7389 while ((idx = caretContainer.data.lastIndexOf(ZWSP$1)) !== -1) { 7390 caretContainer.deleteData(idx, 1); 7391 } 7392 }; 7393 const removeUnchanged = (caretContainer, pos) => { 7394 remove$4(caretContainer); 7395 return pos; 7396 }; 7397 const removeTextAndReposition = (caretContainer, pos) => { 7398 const before = trimCount(caretContainer.data.substr(0, pos.offset())); 7399 const after = trimCount(caretContainer.data.substr(pos.offset())); 7400 const text = before.text + after.text; 7401 if (text.length > 0) { 7402 deleteZwspChars(caretContainer); 7403 return CaretPosition(caretContainer, pos.offset() - before.count); 7404 } else { 7405 return pos; 7406 } 7407 }; 7408 const removeElementAndReposition = (caretContainer, pos) => { 7409 const parentNode = pos.container(); 7410 const newPosition = indexOf$1(from(parentNode.childNodes), caretContainer).map(index => { 7411 return index < pos.offset() ? CaretPosition(parentNode, pos.offset() - 1) : pos; 7412 }).getOr(pos); 7413 remove$4(caretContainer); 7414 return newPosition; 7415 }; 7416 const removeTextCaretContainer = (caretContainer, pos) => isText$5(caretContainer) && pos.container() === caretContainer ? removeTextAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos); 7417 const removeElementCaretContainer = (caretContainer, pos) => pos.container() === caretContainer.parentNode ? removeElementAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos); 7418 const removeAndReposition = (container, pos) => CaretPosition.isTextPosition(pos) ? removeTextCaretContainer(container, pos) : removeElementCaretContainer(container, pos); 7419 const remove$4 = caretContainerNode => { 7420 if (isElement$3(caretContainerNode) && isCaretContainer$2(caretContainerNode)) { 7421 if (hasContent(caretContainerNode)) { 7422 caretContainerNode.removeAttribute('data-mce-caret'); 7423 } else { 7424 removeNode$1(caretContainerNode); 7425 } 7426 } 7427 if (isText$5(caretContainerNode)) { 7428 deleteZwspChars(caretContainerNode); 7429 if (caretContainerNode.data.length === 0) { 7430 removeNode$1(caretContainerNode); 7431 } 7432 } 7433 }; 7434 7435 const isContentEditableFalse$8 = isContentEditableFalse$b; 7436 const isMedia$1 = isMedia$2; 7437 const isTableCell$1 = isTableCell$3; 7438 const inlineFakeCaretSelector = '*[contentEditable=false],video,audio,embed,object'; 7439 const getAbsoluteClientRect = (root, element, before) => { 7440 const clientRect = collapse(element.getBoundingClientRect(), before); 7441 let scrollX; 7442 let scrollY; 7443 if (root.tagName === 'BODY') { 7444 const docElm = root.ownerDocument.documentElement; 7445 scrollX = root.scrollLeft || docElm.scrollLeft; 7446 scrollY = root.scrollTop || docElm.scrollTop; 7447 } else { 7448 const rootRect = root.getBoundingClientRect(); 7449 scrollX = root.scrollLeft - rootRect.left; 7450 scrollY = root.scrollTop - rootRect.top; 7451 } 7452 clientRect.left += scrollX; 7453 clientRect.right += scrollX; 7454 clientRect.top += scrollY; 7455 clientRect.bottom += scrollY; 7456 clientRect.width = 1; 7457 let margin = element.offsetWidth - element.clientWidth; 7458 if (margin > 0) { 7459 if (before) { 7460 margin *= -1; 7461 } 7462 clientRect.left += margin; 7463 clientRect.right += margin; 7464 } 7465 return clientRect; 7466 }; 7467 const trimInlineCaretContainers = root => { 7468 var _a, _b; 7469 const fakeCaretTargetNodes = descendants(SugarElement.fromDom(root), inlineFakeCaretSelector); 7470 for (let i = 0; i < fakeCaretTargetNodes.length; i++) { 7471 const node = fakeCaretTargetNodes[i].dom; 7472 let sibling = node.previousSibling; 7473 if (endsWithCaretContainer$1(sibling)) { 7474 const data = sibling.data; 7475 if (data.length === 1) { 7476 (_a = sibling.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(sibling); 7477 } else { 7478 sibling.deleteData(data.length - 1, 1); 7479 } 7480 } 7481 sibling = node.nextSibling; 7482 if (startsWithCaretContainer$1(sibling)) { 7483 const data = sibling.data; 7484 if (data.length === 1) { 7485 (_b = sibling.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(sibling); 7486 } else { 7487 sibling.deleteData(0, 1); 7488 } 7489 } 7490 } 7491 }; 7492 const FakeCaret = (editor, root, isBlock, hasFocus) => { 7493 const lastVisualCaret = value$2(); 7494 let cursorInterval; 7495 let caretContainerNode; 7496 const caretBlock = getForcedRootBlock(editor); 7497 const dom = editor.dom; 7498 const show = (before, element) => { 7499 let rng; 7500 hide(); 7501 if (isTableCell$1(element)) { 7502 return null; 7503 } 7504 if (isBlock(element)) { 7505 const caretContainer = insertBlock(caretBlock, element, before); 7506 const clientRect = getAbsoluteClientRect(root, element, before); 7507 dom.setStyle(caretContainer, 'top', clientRect.top); 7508 caretContainerNode = caretContainer; 7509 const caret = dom.create('div', { 7510 'class': 'mce-visual-caret', 7511 'data-mce-bogus': 'all' 7512 }); 7513 dom.setStyles(caret, { ...clientRect }); 7514 dom.add(root, caret); 7515 lastVisualCaret.set({ 7516 caret, 7517 element, 7518 before 7519 }); 7520 if (before) { 7521 dom.addClass(caret, 'mce-visual-caret-before'); 7522 } 7523 startBlink(); 7524 rng = element.ownerDocument.createRange(); 7525 rng.setStart(caretContainer, 0); 7526 rng.setEnd(caretContainer, 0); 7527 } else { 7528 caretContainerNode = insertInline$1(element, before); 7529 rng = element.ownerDocument.createRange(); 7530 if (isInlineFakeCaretTarget(caretContainerNode.nextSibling)) { 7531 rng.setStart(caretContainerNode, 0); 7532 rng.setEnd(caretContainerNode, 0); 7533 } else { 7534 rng.setStart(caretContainerNode, 1); 7535 rng.setEnd(caretContainerNode, 1); 7536 } 7537 return rng; 7538 } 7539 return rng; 7540 }; 7541 const hide = () => { 7542 trimInlineCaretContainers(root); 7543 if (caretContainerNode) { 7544 remove$4
vendor: 27,224 bytes, lines 7544-8266
7544(caretContainerNode); 7545 caretContainerNode = null; 7546 } 7547 lastVisualCaret.on(caretState => { 7548 dom.remove(caretState.caret); 7549 lastVisualCaret.clear(); 7550 }); 7551 if (cursorInterval) { 7552 clearInterval(cursorInterval); 7553 cursorInterval = undefined; 7554 } 7555 }; 7556 const startBlink = () => { 7557 cursorInterval = setInterval(() => { 7558 lastVisualCaret.on(caretState => { 7559 if (hasFocus()) { 7560 dom.toggleClass(caretState.caret, 'mce-visual-caret-hidden'); 7561 } else { 7562 dom.addClass(caretState.caret, 'mce-visual-caret-hidden'); 7563 } 7564 }); 7565 }, 500); 7566 }; 7567 const reposition = () => { 7568 lastVisualCaret.on(caretState => { 7569 const clientRect = getAbsoluteClientRect(root, caretState.element, caretState.before); 7570 dom.setStyles(caretState.caret, { ...clientRect }); 7571 }); 7572 }; 7573 const destroy = () => clearInterval(cursorInterval); 7574 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;' + '}'; 7575 return { 7576 show, 7577 hide, 7578 getCss, 7579 reposition, 7580 destroy 7581 }; 7582 }; 7583 const isFakeCaretTableBrowser = () => Env.browser.isFirefox(); 7584 const isInlineFakeCaretTarget = node => isContentEditableFalse$8(node) || isMedia$1(node); 7585 const isFakeCaretTarget = node => { 7586 const isTarget = isInlineFakeCaretTarget(node) || isTable$2(node) && isFakeCaretTableBrowser(); 7587 return isTarget && parentElement(SugarElement.fromDom(node)).exists(isEditable$3); 7588 }; 7589 7590 const isContentEditableTrue$1 = isContentEditableTrue$3; 7591 const isContentEditableFalse$7 = isContentEditableFalse$b; 7592 const isMedia = isMedia$2; 7593 const isBlockLike = matchStyleValues('display', 'block table table-cell table-caption list-item'); 7594 const isCaretContainer = isCaretContainer$2; 7595 const isCaretContainerBlock = isCaretContainerBlock$1; 7596 const isElement$2 = isElement$6; 7597 const isText$4 = isText$a; 7598 const isCaretCandidate$1 = isCaretCandidate$3; 7599 const isForwards = direction => direction > 0; 7600 const isBackwards = direction => direction < 0; 7601 const skipCaretContainers = (walk, shallow) => { 7602 let node; 7603 while (node = walk(shallow)) { 7604 if (!isCaretContainerBlock(node)) { 7605 return node; 7606 } 7607 } 7608 return null; 7609 }; 7610 const findNode = (node, direction, predicateFn, rootNode, shallow) => { 7611 const walker = new DomTreeWalker(node, rootNode); 7612 const isCefOrCaretContainer = isContentEditableFalse$7(node) || isCaretContainerBlock(node); 7613 let tempNode; 7614 if (isBackwards(direction)) { 7615 if (isCefOrCaretContainer) { 7616 tempNode = skipCaretContainers(walker.prev.bind(walker), true); 7617 if (predicateFn(tempNode)) { 7618 return tempNode; 7619 } 7620 } 7621 while (tempNode = skipCaretContainers(walker.prev.bind(walker), shallow)) { 7622 if (predicateFn(tempNode)) { 7623 return tempNode; 7624 } 7625 } 7626 } 7627 if (isForwards(direction)) { 7628 if (isCefOrCaretContainer) { 7629 tempNode = skipCaretContainers(walker.next.bind(walker), true); 7630 if (predicateFn(tempNode)) { 7631 return tempNode; 7632 } 7633 } 7634 while (tempNode = skipCaretContainers(walker.next.bind(walker), shallow)) { 7635 if (predicateFn(tempNode)) { 7636 return tempNode; 7637 } 7638 } 7639 } 7640 return null; 7641 }; 7642 const getEditingHost = (node, rootNode) => { 7643 const isCETrue = node => isContentEditableTrue$1(node.dom); 7644 const isRoot = node => node.dom === rootNode; 7645 return ancestor$4(SugarElement.fromDom(node), isCETrue, isRoot).map(elm => elm.dom).getOr(rootNode); 7646 }; 7647 const getParentBlock$3 = (node, rootNode) => { 7648 while (node && node !== rootNode) { 7649 if (isBlockLike(node)) { 7650 return node; 7651 } 7652 node = node.parentNode; 7653 } 7654 return null; 7655 }; 7656 const isInSameBlock = (caretPosition1, caretPosition2, rootNode) => getParentBlock$3(caretPosition1.container(), rootNode) === getParentBlock$3(caretPosition2.container(), rootNode); 7657 const getChildNodeAtRelativeOffset = (relativeOffset, caretPosition) => { 7658 if (!caretPosition) { 7659 return Optional.none(); 7660 } 7661 const container = caretPosition.container(); 7662 const offset = caretPosition.offset(); 7663 if (!isElement$2(container)) { 7664 return Optional.none(); 7665 } 7666 return Optional.from(container.childNodes[offset + relativeOffset]); 7667 }; 7668 const beforeAfter = (before, node) => { 7669 var _a; 7670 const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document; 7671 const range = doc.createRange(); 7672 if (before) { 7673 range.setStartBefore(node); 7674 range.setEndBefore(node); 7675 } else { 7676 range.setStartAfter(node); 7677 range.setEndAfter(node); 7678 } 7679 return range; 7680 }; 7681 const isNodesInSameBlock = (root, node1, node2) => getParentBlock$3(node1, root) === getParentBlock$3(node2, root); 7682 const lean = (left, root, node) => { 7683 const siblingName = left ? 'previousSibling' : 'nextSibling'; 7684 let tempNode = node; 7685 while (tempNode && tempNode !== root) { 7686 let sibling = tempNode[siblingName]; 7687 if (sibling && isCaretContainer(sibling)) { 7688 sibling = sibling[siblingName]; 7689 } 7690 if (isContentEditableFalse$7(sibling) || isMedia(sibling)) { 7691 if (isNodesInSameBlock(root, sibling, tempNode)) { 7692 return sibling; 7693 } 7694 break; 7695 } 7696 if (isCaretCandidate$1(sibling)) { 7697 break; 7698 } 7699 tempNode = tempNode.parentNode; 7700 } 7701 return null; 7702 }; 7703 const before$2 = curry(beforeAfter, true); 7704 const after$2 = curry(beforeAfter, false); 7705 const normalizeRange = (direction, root, range) => { 7706 let node; 7707 const leanLeft = curry(lean, true, root); 7708 const leanRight = curry(lean, false, root); 7709 const container = range.startContainer; 7710 const offset = range.startOffset; 7711 if (isCaretContainerBlock$1(container)) { 7712 const block = isText$4(container) ? container.parentNode : container; 7713 const location = block.getAttribute('data-mce-caret'); 7714 if (location === 'before') { 7715 node = block.nextSibling; 7716 if (isFakeCaretTarget(node)) { 7717 return before$2(node); 7718 } 7719 } 7720 if (location === 'after') { 7721 node = block.previousSibling; 7722 if (isFakeCaretTarget(node)) { 7723 return after$2(node); 7724 } 7725 } 7726 } 7727 if (!range.collapsed) { 7728 return range; 7729 } 7730 if (isText$a(container)) { 7731 if (isCaretContainer(container)) { 7732 if (direction === 1) { 7733 node = leanRight(container); 7734 if (node) { 7735 return before$2(node); 7736 } 7737 node = leanLeft(container); 7738 if (node) { 7739 return after$2(node); 7740 } 7741 } 7742 if (direction === -1) { 7743 node = leanLeft(container); 7744 if (node) { 7745 return after$2(node); 7746 } 7747 node = leanRight(container); 7748 if (node) { 7749 return before$2(node); 7750 } 7751 } 7752 return range; 7753 } 7754 if (endsWithCaretContainer$1(container) && offset >= container.data.length - 1) { 7755 if (direction === 1) { 7756 node = leanRight(container); 7757 if (node) { 7758 return before$2(node); 7759 } 7760 } 7761 return range; 7762 } 7763 if (startsWithCaretContainer$1(container) && offset <= 1) { 7764 if (direction === -1) { 7765 node = leanLeft(container); 7766 if (node) { 7767 return after$2(node); 7768 } 7769 } 7770 return range; 7771 } 7772 if (offset === container.data.length) { 7773 node = leanRight(container); 7774 if (node) { 7775 return before$2(node); 7776 } 7777 return range; 7778 } 7779 if (offset === 0) { 7780 node = leanLeft(container); 7781 if (node) { 7782 return after$2(node); 7783 } 7784 return range; 7785 } 7786 } 7787 return range; 7788 }; 7789 const getRelativeCefElm = (forward, caretPosition) => getChildNodeAtRelativeOffset(forward ? 0 : -1, caretPosition).filter(isContentEditableFalse$7); 7790 const getNormalizedRangeEndPoint = (direction, root, range) => { 7791 const normalizedRange = normalizeRange(direction, root, range); 7792 return direction === -1 ? CaretPosition.fromRangeStart(normalizedRange) : CaretPosition.fromRangeEnd(normalizedRange); 7793 }; 7794 const getElementFromPosition = pos => Optional.from(pos.getNode()).map(SugarElement.fromDom); 7795 const getElementFromPrevPosition = pos => Optional.from(pos.getNode(true)).map(SugarElement.fromDom); 7796 const getVisualCaretPosition = (walkFn, caretPosition) => { 7797 let pos = caretPosition; 7798 while (pos = walkFn(pos)) { 7799 if (pos.isVisible()) { 7800 return pos; 7801 } 7802 } 7803 return pos; 7804 }; 7805 const isMoveInsideSameBlock = (from, to) => { 7806 const inSameBlock = isInSameBlock(from, to); 7807 if (!inSameBlock && isBr$6(from.getNode())) { 7808 return true; 7809 } 7810 return inSameBlock; 7811 }; 7812 7813 var HDirection; 7814 (function (HDirection) { 7815 HDirection[HDirection['Backwards'] = -1] = 'Backwards'; 7816 HDirection[HDirection['Forwards'] = 1] = 'Forwards'; 7817 }(HDirection || (HDirection = {}))); 7818 const isContentEditableFalse$6 = isContentEditableFalse$b; 7819 const isText$3 = isText$a; 7820 const isElement$1 = isElement$6; 7821 const isBr$2 = isBr$6; 7822 const isCaretCandidate = isCaretCandidate$3; 7823 const isAtomic = isAtomic$1; 7824 const isEditableCaretCandidate = isEditableCaretCandidate$1; 7825 const getParents$3 = (node, root) => { 7826 const parents = []; 7827 let tempNode = node; 7828 while (tempNode && tempNode !== root) { 7829 parents.push(tempNode); 7830 tempNode = tempNode.parentNode; 7831 } 7832 return parents; 7833 }; 7834 const nodeAtIndex = (container, offset) => { 7835 if (container.hasChildNodes() && offset < container.childNodes.length) { 7836 return container.childNodes[offset]; 7837 } 7838 return null; 7839 }; 7840 const getCaretCandidatePosition = (direction, node) => { 7841 if (isForwards(direction)) { 7842 if (isCaretCandidate(node.previousSibling) && !isText$3(node.previousSibling)) { 7843 return CaretPosition.before(node); 7844 } 7845 if (isText$3(node)) { 7846 return CaretPosition(node, 0); 7847 } 7848 } 7849 if (isBackwards(direction)) { 7850 if (isCaretCandidate(node.nextSibling) && !isText$3(node.nextSibling)) { 7851 return CaretPosition.after(node); 7852 } 7853 if (isText$3(node)) { 7854 return CaretPosition(node, node.data.length); 7855 } 7856 } 7857 if (isBackwards(direction)) { 7858 if (isBr$2(node)) { 7859 return CaretPosition.before(node); 7860 } 7861 return CaretPosition.after(node); 7862 } 7863 return CaretPosition.before(node); 7864 }; 7865 const moveForwardFromBr = (root, nextNode) => { 7866 const nextSibling = nextNode.nextSibling; 7867 if (nextSibling && isCaretCandidate(nextSibling)) { 7868 if (isText$3(nextSibling)) { 7869 return CaretPosition(nextSibling, 0); 7870 } else { 7871 return CaretPosition.before(nextSibling); 7872 } 7873 } else { 7874 return findCaretPosition$1(HDirection.Forwards, CaretPosition.after(nextNode), root); 7875 } 7876 }; 7877 const findCaretPosition$1 = (direction, startPos, root) => { 7878 let node; 7879 let nextNode; 7880 let innerNode; 7881 let caretPosition; 7882 if (!isElement$1(root) || !startPos) { 7883 return null; 7884 } 7885 if (startPos.isEqual(CaretPosition.after(root)) && root.lastChild) { 7886 caretPosition = CaretPosition.after(root.lastChild); 7887 if (isBackwards(direction) && isCaretCandidate(root.lastChild) && isElement$1(root.lastChild)) { 7888 return isBr$2(root.lastChild) ? CaretPosition.before(root.lastChild) : caretPosition; 7889 } 7890 } else { 7891 caretPosition = startPos; 7892 } 7893 const container = caretPosition.container(); 7894 let offset = caretPosition.offset(); 7895 if (isText$3(container)) { 7896 if (isBackwards(direction) && offset > 0) { 7897 return CaretPosition(container, --offset); 7898 } 7899 if (isForwards(direction) && offset < container.length) { 7900 return CaretPosition(container, ++offset); 7901 } 7902 node = container; 7903 } else { 7904 if (isBackwards(direction) && offset > 0) { 7905 nextNode = nodeAtIndex(container, offset - 1); 7906 if (isCaretCandidate(nextNode)) { 7907 if (!isAtomic(nextNode)) { 7908 innerNode = findNode(nextNode, direction, isEditableCaretCandidate, nextNode); 7909 if (innerNode) { 7910 if (isText$3(innerNode)) { 7911 return CaretPosition(innerNode, innerNode.data.length); 7912 } 7913 return CaretPosition.after(innerNode); 7914 } 7915 } 7916 if (isText$3(nextNode)) { 7917 return CaretPosition(nextNode, nextNode.data.length); 7918 } 7919 return CaretPosition.before(nextNode); 7920 } 7921 } 7922 if (isForwards(direction) && offset < container.childNodes.length) { 7923 nextNode = nodeAtIndex(container, offset); 7924 if (isCaretCandidate(nextNode)) { 7925 if (isBr$2(nextNode)) { 7926 return moveForwardFromBr(root, nextNode); 7927 } 7928 if (!isAtomic(nextNode)) { 7929 innerNode = findNode(nextNode, direction, isEditableCaretCandidate, nextNode); 7930 if (innerNode) { 7931 if (isText$3(innerNode)) { 7932 return CaretPosition(innerNode, 0); 7933 } 7934 return CaretPosition.before(innerNode); 7935 } 7936 } 7937 if (isText$3(nextNode)) { 7938 return CaretPosition(nextNode, 0); 7939 } 7940 return CaretPosition.after(nextNode); 7941 } 7942 } 7943 node = nextNode ? nextNode : caretPosition.getNode(); 7944 } 7945 if (node && (isForwards(direction) && caretPosition.isAtEnd() || isBackwards(direction) && caretPosition.isAtStart())) { 7946 node = findNode(node, direction, always, root, true); 7947 if (isEditableCaretCandidate(node, root)) { 7948 return getCaretCandidatePosition(direction, node); 7949 } 7950 } 7951 nextNode = node ? findNode(node, direction, isEditableCaretCandidate, root) : node; 7952 const rootContentEditableFalseElm = last$2(filter$5(getParents$3(container, root), isContentEditableFalse$6)); 7953 if (rootContentEditableFalseElm && (!nextNode || !rootContentEditableFalseElm.contains(nextNode))) { 7954 if (isForwards(direction)) { 7955 caretPosition = CaretPosition.after(rootContentEditableFalseElm); 7956 } else { 7957 caretPosition = CaretPosition.before(rootContentEditableFalseElm); 7958 } 7959 return caretPosition; 7960 } 7961 if (nextNode) { 7962 return getCaretCandidatePosition(direction, nextNode); 7963 } 7964 return null; 7965 }; 7966 const CaretWalker = root => ({ 7967 next: caretPosition => { 7968 return findCaretPosition$1(HDirection.Forwards, caretPosition, root); 7969 }, 7970 prev: caretPosition => { 7971 return findCaretPosition$1(HDirection.Backwards, caretPosition, root); 7972 } 7973 }); 7974 7975 const walkToPositionIn = (forward, root, start) => { 7976 const position = forward ? CaretPosition.before(start) : CaretPosition.after(start); 7977 return fromPosition(forward, root, position); 7978 }; 7979 const afterElement = node => isBr$6(node) ? CaretPosition.before(node) : CaretPosition.after(node); 7980 const isBeforeOrStart = position => { 7981 if (CaretPosition.isTextPosition(position)) { 7982 return position.offset() === 0; 7983 } else { 7984 return isCaretCandidate$3(position.getNode()); 7985 } 7986 }; 7987 const isAfterOrEnd = position => { 7988 if (CaretPosition.isTextPosition(position)) { 7989 const container = position.container(); 7990 return position.offset() === container.data.length; 7991 } else { 7992 return isCaretCandidate$3(position.getNode(true)); 7993 } 7994 }; 7995 const isBeforeAfterSameElement = (from, to) => !CaretPosition.isTextPosition(from) && !CaretPosition.isTextPosition(to) && from.getNode() === to.getNode(true); 7996 const isAtBr = position => !CaretPosition.isTextPosition(position) && isBr$6(position.getNode()); 7997 const shouldSkipPosition = (forward, from, to) => { 7998 if (forward) { 7999 return !isBeforeAfterSameElement(from, to) && !isAtBr(from) && isAfterOrEnd(from) && isBeforeOrStart(to); 8000 } else { 8001 return !isBeforeAfterSameElement(to, from) && isBeforeOrStart(from) && isAfterOrEnd(to); 8002 } 8003 }; 8004 const fromPosition = (forward, root, pos) => { 8005 const walker = CaretWalker(root); 8006 return Optional.from(forward ? walker.next(pos) : walker.prev(pos)); 8007 }; 8008 const navigate = (forward, root, from) => fromPosition(forward, root, from).bind(to => { 8009 if (isInSameBlock(from, to, root) && shouldSkipPosition(forward, from, to)) { 8010 return fromPosition(forward, root, to); 8011 } else { 8012 return Optional.some(to); 8013 } 8014 }); 8015 const navigateIgnore = (forward, root, from, ignoreFilter) => navigate(forward, root, from).bind(pos => ignoreFilter(pos) ? navigateIgnore(forward, root, pos, ignoreFilter) : Optional.some(pos)); 8016 const positionIn = (forward, element) => { 8017 const startNode = forward ? element.firstChild : element.lastChild; 8018 if (isText$a(startNode)) { 8019 return Optional.some(CaretPosition(startNode, forward ? 0 : startNode.data.length)); 8020 } else if (startNode) { 8021 if (isCaretCandidate$3(startNode)) { 8022 return Optional.some(forward ? CaretPosition.before(startNode) : afterElement(startNode)); 8023 } else { 8024 return walkToPositionIn(forward, element, startNode); 8025 } 8026 } else { 8027 return Optional.none(); 8028 } 8029 }; 8030 const nextPosition = curry(fromPosition, true); 8031 const prevPosition = curry(fromPosition, false); 8032 const firstPositionIn = curry(positionIn, true); 8033 const lastPositionIn = curry(positionIn, false); 8034 8035 const CARET_ID = '_mce_caret'; 8036 const isCaretNode = node => isElement$6(node) && node.id === CARET_ID; 8037 const getParentCaretContainer = (body, node) => { 8038 let currentNode = node; 8039 while (currentNode && currentNode !== body) { 8040 if (isCaretNode(currentNode)) { 8041 return currentNode; 8042 } 8043 currentNode = currentNode.parentNode; 8044 } 8045 return null; 8046 }; 8047 8048 const isStringPathBookmark = bookmark => isString(bookmark.start); 8049 const isRangeBookmark = bookmark => has$2(bookmark, 'rng'); 8050 const isIdBookmark = bookmark => has$2(bookmark, 'id'); 8051 const isIndexBookmark = bookmark => has$2(bookmark, 'name'); 8052 const isPathBookmark = bookmark => Tools.isArray(bookmark.start); 8053 8054 const isForwardBookmark = bookmark => !isIndexBookmark(bookmark) && isBoolean(bookmark.forward) ? bookmark.forward : true; 8055 const addBogus = (dom, node) => { 8056 if (isElement$6(node) && dom.isBlock(node) && !node.innerHTML) { 8057 node.innerHTML = '<br data-mce-bogus="1" />'; 8058 } 8059 return node; 8060 }; 8061 const resolveCaretPositionBookmark = (dom, bookmark) => { 8062 const startPos = Optional.from(resolve$1(dom.getRoot(), bookmark.start)); 8063 const endPos = Optional.from(resolve$1(dom.getRoot(), bookmark.end)); 8064 return lift2(startPos, endPos, (start, end) => { 8065 const range = dom.createRng(); 8066 range.setStart(start.container(), start.offset()); 8067 range.setEnd(end.container(), end.offset()); 8068 return { 8069 range, 8070 forward: isForwardBookmark(bookmark) 8071 }; 8072 }); 8073 }; 8074 const insertZwsp = (node, rng) => { 8075 var _a; 8076 const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document; 8077 const textNode = doc.createTextNode(ZWSP$1); 8078 node.appendChild(textNode); 8079 rng.setStart(textNode, 0); 8080 rng.setEnd(textNode, 0); 8081 }; 8082 const isEmpty$1 = node => !node.hasChildNodes(); 8083 const tryFindRangePosition = (node, rng) => lastPositionIn(node).fold(never, pos => { 8084 rng.setStart(pos.container(), pos.offset()); 8085 rng.setEnd(pos.container(), pos.offset()); 8086 return true; 8087 }); 8088 const padEmptyCaretContainer = (root, node, rng) => { 8089 if (isEmpty$1(node) && getParentCaretContainer(root, node)) { 8090 insertZwsp(node, rng); 8091 return true; 8092 } else { 8093 return false; 8094 } 8095 }; 8096 const setEndPoint = (dom, start, bookmark, rng) => { 8097 const point = bookmark[start ? 'start' : 'end']; 8098 const root = dom.getRoot(); 8099 if (point) { 8100 let node = root; 8101 let offset = point[0]; 8102 for (let i = point.length - 1; node && i >= 1; i--) { 8103 const children = node.childNodes; 8104 if (padEmptyCaretContainer(root, node, rng)) { 8105 return true; 8106 } 8107 if (point[i] > children.length - 1) { 8108 if (padEmptyCaretContainer(root, node, rng)) { 8109 return true; 8110 } 8111 return tryFindRangePosition(node, rng); 8112 } 8113 node = children[point[i]]; 8114 } 8115 if (isText$a(node)) { 8116 offset = Math.min(point[0], node.data.length); 8117 } 8118 if (isElement$6(node)) { 8119 offset = Math.min(point[0], node.childNodes.length); 8120 } 8121 if (start) { 8122 rng.setStart(node, offset); 8123 } else { 8124 rng.setEnd(node, offset); 8125 } 8126 } 8127 return true; 8128 }; 8129 const isValidTextNode = node => isText$a(node) && node.data.length > 0; 8130 const restoreEndPoint = (dom, suffix, bookmark) => { 8131 const marker = dom.get(bookmark.id + '_' + suffix); 8132 const markerParent = marker === null || marker === void 0 ? void 0 : marker.parentNode; 8133 const keep = bookmark.keep; 8134 if (marker && markerParent) { 8135 let container; 8136 let offset; 8137 if (suffix === 'start') { 8138 if (!keep) { 8139 container = markerParent; 8140 offset = dom.nodeIndex(marker); 8141 } else { 8142 if (marker.hasChildNodes()) { 8143 container = marker.firstChild; 8144 offset = 1; 8145 } else if (isValidTextNode(marker.nextSibling)) { 8146 container = marker.nextSibling; 8147 offset = 0; 8148 } else if (isValidTextNode(marker.previousSibling)) { 8149 container = marker.previousSibling; 8150 offset = marker.previousSibling.data.length; 8151 } else { 8152 container = markerParent; 8153 offset = dom.nodeIndex(marker) + 1; 8154 } 8155 } 8156 } else { 8157 if (!keep) { 8158 container = markerParent; 8159 offset = dom.nodeIndex(marker); 8160 } else { 8161 if (marker.hasChildNodes()) { 8162 container = marker.firstChild; 8163 offset = 1; 8164 } else if (isValidTextNode(marker.previousSibling)) { 8165 container = marker.previousSibling; 8166 offset = marker.previousSibling.data.length; 8167 } else { 8168 container = markerParent; 8169 offset = dom.nodeIndex(marker); 8170 } 8171 } 8172 } 8173 if (!keep) { 8174 const prev = marker.previousSibling; 8175 const next = marker.nextSibling; 8176 Tools.each(Tools.grep(marker.childNodes), node => { 8177 if (isText$a(node)) { 8178 node.data = node.data.replace(/\uFEFF/g, ''); 8179 } 8180 }); 8181 let otherMarker; 8182 while (otherMarker = dom.get(bookmark.id + '_' + suffix)) { 8183 dom.remove(otherMarker, true); 8184 } 8185 if (isText$a(next) && isText$a(prev) && !Env.browser.isOpera()) { 8186 const idx = prev.data.length; 8187 prev.appendData(next.data); 8188 dom.remove(next); 8189 container = prev; 8190 offset = idx; 8191 } 8192 } 8193 return Optional.some(CaretPosition(container, offset)); 8194 } else { 8195 return Optional.none(); 8196 } 8197 }; 8198 const resolvePaths = (dom, bookmark) => { 8199 const range = dom.createRng(); 8200 if (setEndPoint(dom, true, bookmark, range) && setEndPoint(dom, false, bookmark, range)) { 8201 return Optional.some({ 8202 range, 8203 forward: isForwardBookmark(bookmark) 8204 }); 8205 } else { 8206 return Optional.none(); 8207 } 8208 }; 8209 const resolveId = (dom, bookmark) => { 8210 const startPos = restoreEndPoint(dom, 'start', bookmark); 8211 const endPos = restoreEndPoint(dom, 'end', bookmark); 8212 return lift2(startPos, endPos.or(startPos), (spos, epos) => { 8213 const range = dom.createRng(); 8214 range.setStart(addBogus(dom, spos.container()), spos.offset()); 8215 range.setEnd(addBogus(dom, epos.container()), epos.offset()); 8216 return { 8217 range, 8218 forward: isForwardBookmark(bookmark) 8219 }; 8220 }); 8221 }; 8222 const resolveIndex = (dom, bookmark) => Optional.from(dom.select(bookmark.name)[bookmark.index]).map(elm => { 8223 const range = dom.createRng(); 8224 range.selectNode(elm); 8225 return { 8226 range, 8227 forward: true 8228 }; 8229 }); 8230 const resolve = (selection, bookmark) => { 8231 const dom = selection.dom; 8232 if (bookmark) { 8233 if (isPathBookmark(bookmark)) { 8234 return resolvePaths(dom, bookmark); 8235 } else if (isStringPathBookmark(bookmark)) { 8236 return resolveCaretPositionBookmark(dom, bookmark); 8237 } else if (isIdBookmark(bookmark)) { 8238 return resolveId(dom, bookmark); 8239 } else if (isIndexBookmark(bookmark)) { 8240 return resolveIndex(dom, bookmark); 8241 } else if (isRangeBookmark(bookmark)) { 8242 return Optional.some({ 8243 range: bookmark.rng, 8244 forward: isForwardBookmark(bookmark) 8245 }); 8246 } 8247 } 8248 return Optional.none(); 8249 }; 8250 8251 const getBookmark$1 = (selection, type, normalized) => { 8252 return getBookmark$2(selection, type, normalized); 8253 }; 8254 const moveToBookmark = (selection, bookmark) => { 8255 resolve(selection, bookmark).each(({range, forward}) => { 8256 selection.setRng(range, forward); 8257 }); 8258 }; 8259 const isBookmarkNode$1 = node => { 8260 return isElement$6(node) && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark'; 8261 }; 8262 8263 const is = expected => actual => expected === actual; 8264 const isNbsp = is(nbsp); 8265 const isWhiteSpace = chr => chr !== '' && ' \f\n\r\t\x0B'.indexOf(chr) !== -1; 8266 const isContent = chr => !isWhiteSpace(chr) && !isNbsp(chr) && !isZwsp$
82661
vendor: 28,894 bytes, lines 8266-8969
8266(chr); 8267 8268 const hexColour = value => ({ value: normalizeHex(value) }); 8269 const normalizeHex = hex => removeLeading(hex, '#').toUpperCase(); 8270 const toHex = component => { 8271 const hex = component.toString(16); 8272 return (hex.length === 1 ? '0' + hex : hex).toUpperCase(); 8273 }; 8274 const fromRgba = rgbaColour => { 8275 const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue); 8276 return hexColour(value); 8277 }; 8278 8279 const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i; 8280 const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i; 8281 const rgbaColour = (red, green, blue, alpha) => ({ 8282 red, 8283 green, 8284 blue, 8285 alpha 8286 }); 8287 const fromStringValues = (red, green, blue, alpha) => { 8288 const r = parseInt(red, 10); 8289 const g = parseInt(green, 10); 8290 const b = parseInt(blue, 10); 8291 const a = parseFloat(alpha); 8292 return rgbaColour(r, g, b, a); 8293 }; 8294 const fromString = rgbaString => { 8295 if (rgbaString === 'transparent') { 8296 return Optional.some(rgbaColour(0, 0, 0, 0)); 8297 } 8298 const rgbMatch = rgbRegex.exec(rgbaString); 8299 if (rgbMatch !== null) { 8300 return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1')); 8301 } 8302 const rgbaMatch = rgbaRegex.exec(rgbaString); 8303 if (rgbaMatch !== null) { 8304 return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4])); 8305 } 8306 return Optional.none(); 8307 }; 8308 8309 const rgbaToHexString = color => fromString(color).map(fromRgba).map(h => '#' + h.value).getOr(color); 8310 8311 const getRanges$1 = selection => { 8312 const ranges = []; 8313 if (selection) { 8314 for (let i = 0; i < selection.rangeCount; i++) { 8315 ranges.push(selection.getRangeAt(i)); 8316 } 8317 } 8318 return ranges; 8319 }; 8320 const getSelectedNodes = ranges => { 8321 return bind$3(ranges, range => { 8322 const node = getSelectedNode(range); 8323 return node ? [SugarElement.fromDom(node)] : []; 8324 }); 8325 }; 8326 const hasMultipleRanges = selection => { 8327 return getRanges$1(selection).length > 1; 8328 }; 8329 8330 const getCellsFromRanges = ranges => filter$5(getSelectedNodes(ranges), isTableCell$2); 8331 const getCellsFromElement = elm => descendants(elm, 'td[data-mce-selected],th[data-mce-selected]'); 8332 const getCellsFromElementOrRanges = (ranges, element) => { 8333 const selectedCells = getCellsFromElement(element); 8334 return selectedCells.length > 0 ? selectedCells : getCellsFromRanges(ranges); 8335 }; 8336 const getCellsFromEditor = editor => getCellsFromElementOrRanges(getRanges$1(editor.selection.getSel()), SugarElement.fromDom(editor.getBody())); 8337 const getClosestTable = (cell, isRoot) => ancestor$3(cell, 'table', isRoot); 8338 8339 const getStartNode = rng => { 8340 const sc = rng.startContainer, so = rng.startOffset; 8341 if (isText$a(sc)) { 8342 return so === 0 ? Optional.some(SugarElement.fromDom(sc)) : Optional.none(); 8343 } else { 8344 return Optional.from(sc.childNodes[so]).map(SugarElement.fromDom); 8345 } 8346 }; 8347 const getEndNode = rng => { 8348 const ec = rng.endContainer, eo = rng.endOffset; 8349 if (isText$a(ec)) { 8350 return eo === ec.data.length ? Optional.some(SugarElement.fromDom(ec)) : Optional.none(); 8351 } else { 8352 return Optional.from(ec.childNodes[eo - 1]).map(SugarElement.fromDom); 8353 } 8354 }; 8355 const getFirstChildren = node => { 8356 return firstChild(node).fold(constant([node]), child => { 8357 return [node].concat(getFirstChildren(child)); 8358 }); 8359 }; 8360 const getLastChildren = node => { 8361 return lastChild(node).fold(constant([node]), child => { 8362 if (name(child) === 'br') { 8363 return prevSibling(child).map(sibling => { 8364 return [node].concat(getLastChildren(sibling)); 8365 }).getOr([]); 8366 } else { 8367 return [node].concat(getLastChildren(child)); 8368 } 8369 }); 8370 }; 8371 const hasAllContentsSelected = (elm, rng) => { 8372 return lift2(getStartNode(rng), getEndNode(rng), (startNode, endNode) => { 8373 const start = find$2(getFirstChildren(elm), curry(eq, startNode)); 8374 const end = find$2(getLastChildren(elm), curry(eq, endNode)); 8375 return start.isSome() && end.isSome(); 8376 }).getOr(false); 8377 }; 8378 const moveEndPoint = (dom, rng, node, start) => { 8379 const root = node; 8380 const walker = new DomTreeWalker(node, root); 8381 const moveCaretBeforeOnEnterElementsMap = filter$4(dom.schema.getMoveCaretBeforeOnEnterElements(), (_, name) => !contains$2([ 8382 'td', 8383 'th', 8384 'table' 8385 ], name.toLowerCase())); 8386 let currentNode = node; 8387 do { 8388 if (isText$a(currentNode) && Tools.trim(currentNode.data).length !== 0) { 8389 if (start) { 8390 rng.setStart(currentNode, 0); 8391 } else { 8392 rng.setEnd(currentNode, currentNode.data.length); 8393 } 8394 return; 8395 } 8396 if (moveCaretBeforeOnEnterElementsMap[currentNode.nodeName]) { 8397 if (start) { 8398 rng.setStartBefore(currentNode); 8399 } else { 8400 if (currentNode.nodeName === 'BR') { 8401 rng.setEndBefore(currentNode); 8402 } else { 8403 rng.setEndAfter(currentNode); 8404 } 8405 } 8406 return; 8407 } 8408 } while (currentNode = start ? walker.next() : walker.prev()); 8409 if (root.nodeName === 'BODY') { 8410 if (start) { 8411 rng.setStart(root, 0); 8412 } else { 8413 rng.setEnd(root, root.childNodes.length); 8414 } 8415 } 8416 }; 8417 const hasAnyRanges = editor => { 8418 const sel = editor.selection.getSel(); 8419 return isNonNullable(sel) && sel.rangeCount > 0; 8420 }; 8421 const runOnRanges = (editor, executor) => { 8422 const fakeSelectionNodes = getCellsFromEditor(editor); 8423 if (fakeSelectionNodes.length > 0) { 8424 each$e(fakeSelectionNodes, elem => { 8425 const node = elem.dom; 8426 const fakeNodeRng = editor.dom.createRng(); 8427 fakeNodeRng.setStartBefore(node); 8428 fakeNodeRng.setEndAfter(node); 8429 executor(fakeNodeRng, true); 8430 }); 8431 } else { 8432 executor(editor.selection.getRng(), false); 8433 } 8434 }; 8435 const preserve = (selection, fillBookmark, executor) => { 8436 const bookmark = getPersistentBookmark(selection, fillBookmark); 8437 executor(bookmark); 8438 selection.moveToBookmark(bookmark); 8439 }; 8440 8441 const isNode = node => isNumber(node === null || node === void 0 ? void 0 : node.nodeType); 8442 const isElementNode$1 = node => isElement$6(node) && !isBookmarkNode$1(node) && !isCaretNode(node) && !isBogus$2(node); 8443 const isElementDirectlySelected = (dom, node) => { 8444 if (isElementNode$1(node) && !/^(TD|TH)$/.test(node.nodeName)) { 8445 const selectedAttr = dom.getAttrib(node, 'data-mce-selected'); 8446 const value = parseInt(selectedAttr, 10); 8447 return !isNaN(value) && value > 0; 8448 } else { 8449 return false; 8450 } 8451 }; 8452 const isEditable$2 = elm => elm.isContentEditable === true; 8453 const preserveSelection = (editor, action, shouldMoveStart) => { 8454 const {selection, dom} = editor; 8455 const selectedNodeBeforeAction = selection.getNode(); 8456 const isSelectedBeforeNodeNoneditable = isContentEditableFalse$b(selectedNodeBeforeAction); 8457 preserve(selection, true, () => { 8458 action(); 8459 }); 8460 const isBeforeNodeStillNoneditable = isSelectedBeforeNodeNoneditable && isContentEditableFalse$b(selectedNodeBeforeAction); 8461 if (isBeforeNodeStillNoneditable && dom.isChildOf(selectedNodeBeforeAction, editor.getBody())) { 8462 editor.selection.select(selectedNodeBeforeAction); 8463 } else if (shouldMoveStart(selection.getStart())) { 8464 moveStartToNearestText(dom, selection); 8465 } 8466 }; 8467 const moveStartToNearestText = (dom, selection) => { 8468 var _a, _b; 8469 const rng = selection.getRng(); 8470 const {startContainer, startOffset} = rng; 8471 const selectedNode = selection.getNode(); 8472 if (isElementDirectlySelected(dom, selectedNode)) { 8473 return; 8474 } 8475 if (isElement$6(startContainer)) { 8476 const nodes = startContainer.childNodes; 8477 const root = dom.getRoot(); 8478 let walker; 8479 if (startOffset < nodes.length) { 8480 const startNode = nodes[startOffset]; 8481 walker = new DomTreeWalker(startNode, (_a = dom.getParent(startNode, dom.isBlock)) !== null && _a !== void 0 ? _a : root); 8482 } else { 8483 const startNode = nodes[nodes.length - 1]; 8484 walker = new DomTreeWalker(startNode, (_b = dom.getParent(startNode, dom.isBlock)) !== null && _b !== void 0 ? _b : root); 8485 walker.next(true); 8486 } 8487 for (let node = walker.current(); node; node = walker.next()) { 8488 if (dom.getContentEditable(node) === 'false') { 8489 return; 8490 } else if (isText$a(node) && !isWhiteSpaceNode$1(node)) { 8491 rng.setStart(node, 0); 8492 selection.setRng(rng); 8493 return; 8494 } 8495 } 8496 } 8497 }; 8498 const getNonWhiteSpaceSibling = (node, next, inc) => { 8499 if (node) { 8500 const nextName = next ? 'nextSibling' : 'previousSibling'; 8501 for (node = inc ? node : node[nextName]; node; node = node[nextName]) { 8502 if (isElement$6(node) || !isWhiteSpaceNode$1(node)) { 8503 return node; 8504 } 8505 } 8506 } 8507 return undefined; 8508 }; 8509 const isTextBlock$1 = (schema, node) => !!schema.getTextBlockElements()[node.nodeName.toLowerCase()] || isTransparentBlock(schema, node); 8510 const isValid = (ed, parent, child) => { 8511 return ed.schema.isValidChild(parent, child); 8512 }; 8513 const isWhiteSpaceNode$1 = (node, allowSpaces = false) => { 8514 if (isNonNullable(node) && isText$a(node)) { 8515 const data = allowSpaces ? node.data.replace(/ /g, '\xA0') : node.data; 8516 return isWhitespaceText(data); 8517 } else { 8518 return false; 8519 } 8520 }; 8521 const isEmptyTextNode$1 = node => { 8522 return isNonNullable(node) && isText$a(node) && node.length === 0; 8523 }; 8524 const isWrapNoneditableTarget = (editor, node) => { 8525 const baseDataSelector = '[data-mce-cef-wrappable]'; 8526 const formatNoneditableSelector = getFormatNoneditableSelector(editor); 8527 const selector = isEmpty$3(formatNoneditableSelector) ? baseDataSelector : `${ baseDataSelector },${ formatNoneditableSelector }`; 8528 return is$1(SugarElement.fromDom(node), selector); 8529 }; 8530 const isWrappableNoneditable = (editor, node) => { 8531 const dom = editor.dom; 8532 return isElementNode$1(node) && dom.getContentEditable(node) === 'false' && isWrapNoneditableTarget(editor, node) && dom.select('[contenteditable="true"]', node).length === 0; 8533 }; 8534 const replaceVars = (value, vars) => { 8535 if (isFunction(value)) { 8536 return value(vars); 8537 } else if (isNonNullable(vars)) { 8538 value = value.replace(/%(\w+)/g, (str, name) => { 8539 return vars[name] || str; 8540 }); 8541 } 8542 return value; 8543 }; 8544 const isEq$5 = (str1, str2) => { 8545 str1 = str1 || ''; 8546 str2 = str2 || ''; 8547 str1 = '' + (str1.nodeName || str1); 8548 str2 = '' + (str2.nodeName || str2); 8549 return str1.toLowerCase() === str2.toLowerCase(); 8550 }; 8551 const normalizeStyleValue = (value, name) => { 8552 if (isNullable(value)) { 8553 return null; 8554 } else { 8555 let strValue = String(value); 8556 if (name === 'color' || name === 'backgroundColor') { 8557 strValue = rgbaToHexString(strValue); 8558 } 8559 if (name === 'fontWeight' && value === 700) { 8560 strValue = 'bold'; 8561 } 8562 if (name === 'fontFamily') { 8563 strValue = strValue.replace(/[\'\"]/g, '').replace(/,\s+/g, ','); 8564 } 8565 return strValue; 8566 } 8567 }; 8568 const getStyle = (dom, node, name) => { 8569 const style = dom.getStyle(node, name); 8570 return normalizeStyleValue(style, name); 8571 }; 8572 const getTextDecoration = (dom, node) => { 8573 let decoration; 8574 dom.getParent(node, n => { 8575 if (isElement$6(n)) { 8576 decoration = dom.getStyle(n, 'text-decoration'); 8577 return !!decoration && decoration !== 'none'; 8578 } else { 8579 return false; 8580 } 8581 }); 8582 return decoration; 8583 }; 8584 const getParents$2 = (dom, node, selector) => { 8585 return dom.getParents(node, selector, dom.getRoot()); 8586 }; 8587 const isFormatPredicate = (editor, formatName, predicate) => { 8588 const formats = editor.formatter.get(formatName); 8589 return isNonNullable(formats) && exists(formats, predicate); 8590 }; 8591 const isVariableFormatName = (editor, formatName) => { 8592 const hasVariableValues = format => { 8593 const isVariableValue = val => isFunction(val) || val.length > 1 && val.charAt(0) === '%'; 8594 return exists([ 8595 'styles', 8596 'attributes' 8597 ], key => get$a(format, key).exists(field => { 8598 const fieldValues = isArray$1(field) ? field : values(field); 8599 return exists(fieldValues, isVariableValue); 8600 })); 8601 }; 8602 return isFormatPredicate(editor, formatName, hasVariableValues); 8603 }; 8604 const areSimilarFormats = (editor, formatName, otherFormatName) => { 8605 const validKeys = [ 8606 'inline', 8607 'block', 8608 'selector', 8609 'attributes', 8610 'styles', 8611 'classes' 8612 ]; 8613 const filterObj = format => filter$4(format, (_, key) => exists(validKeys, validKey => validKey === key)); 8614 return isFormatPredicate(editor, formatName, fmt1 => { 8615 const filteredFmt1 = filterObj(fmt1); 8616 return isFormatPredicate(editor, otherFormatName, fmt2 => { 8617 const filteredFmt2 = filterObj(fmt2); 8618 return equal$1(filteredFmt1, filteredFmt2); 8619 }); 8620 }); 8621 }; 8622 const isBlockFormat = format => hasNonNullableKey(format, 'block'); 8623 const isWrappingBlockFormat = format => isBlockFormat(format) && format.wrapper === true; 8624 const isNonWrappingBlockFormat = format => isBlockFormat(format) && format.wrapper !== true; 8625 const isSelectorFormat = format => hasNonNullableKey(format, 'selector'); 8626 const isInlineFormat = format => hasNonNullableKey(format, 'inline'); 8627 const isMixedFormat = format => isSelectorFormat(format) && isInlineFormat(format) && is$2(get$a(format, 'mixed'), true); 8628 const shouldExpandToSelector = format => isSelectorFormat(format) && format.expand !== false && !isInlineFormat(format); 8629 8630 const isBookmarkNode = isBookmarkNode$1; 8631 const getParents$1 = getParents$2; 8632 const isWhiteSpaceNode = isWhiteSpaceNode$1; 8633 const isTextBlock = isTextBlock$1; 8634 const isBogusBr = node => { 8635 return isBr$6(node) && node.getAttribute('data-mce-bogus') && !node.nextSibling; 8636 }; 8637 const findParentContentEditable = (dom, node) => { 8638 let parent = node; 8639 while (parent) { 8640 if (isElement$6(parent) && dom.getContentEditable(parent)) { 8641 return dom.getContentEditable(parent) === 'false' ? parent : node; 8642 } 8643 parent = parent.parentNode; 8644 } 8645 return node; 8646 }; 8647 const walkText = (start, node, offset, predicate) => { 8648 const str = node.data; 8649 if (start) { 8650 for (let i = offset; i > 0; i--) { 8651 if (predicate(str.charAt(i - 1))) { 8652 return i; 8653 } 8654 } 8655 } else { 8656 for (let i = offset; i < str.length; i++) { 8657 if (predicate(str.charAt(i))) { 8658 return i; 8659 } 8660 } 8661 } 8662 return -1; 8663 }; 8664 const findSpace = (start, node, offset) => walkText(start, node, offset, c => isNbsp(c) || isWhiteSpace(c)); 8665 const findContent = (start, node, offset) => walkText(start, node, offset, isContent); 8666 const findWordEndPoint = (dom, body, container, offset, start, includeTrailingSpaces) => { 8667 let lastTextNode; 8668 const rootNode = dom.getParent(container, dom.isBlock) || body; 8669 const walk = (container, offset, pred) => { 8670 const textSeeker = TextSeeker(dom); 8671 const walker = start ? textSeeker.backwards : textSeeker.forwards; 8672 return Optional.from(walker(container, offset, (text, textOffset) => { 8673 if (isBookmarkNode(text.parentNode)) { 8674 return -1; 8675 } else { 8676 lastTextNode = text; 8677 return pred(start, text, textOffset); 8678 } 8679 }, rootNode)); 8680 }; 8681 const spaceResult = walk(container, offset, findSpace); 8682 return spaceResult.bind(result => includeTrailingSpaces ? walk(result.container, result.offset + (start ? -1 : 0), findContent) : Optional.some(result)).orThunk(() => lastTextNode ? Optional.some({ 8683 container: lastTextNode, 8684 offset: start ? 0 : lastTextNode.length 8685 }) : Optional.none()); 8686 }; 8687 const findSelectorEndPoint = (dom, formatList, rng, container, siblingName) => { 8688 const sibling = container[siblingName]; 8689 if (isText$a(container) && isEmpty$3(container.data) && sibling) { 8690 container = sibling; 8691 } 8692 const parents = getParents$1(dom, container); 8693 for (let i = 0; i < parents.length; i++) { 8694 for (let y = 0; y < formatList.length; y++) { 8695 const curFormat = formatList[y]; 8696 if (isNonNullable(curFormat.collapsed) && curFormat.collapsed !== rng.collapsed) { 8697 continue; 8698 } 8699 if (isSelectorFormat(curFormat) && dom.is(parents[i], curFormat.selector)) { 8700 return parents[i]; 8701 } 8702 } 8703 } 8704 return container; 8705 }; 8706 const findBlockEndPoint = (dom, formatList, container, siblingName) => { 8707 var _a; 8708 let node = container; 8709 const root = dom.getRoot(); 8710 const format = formatList[0]; 8711 if (isBlockFormat(format)) { 8712 node = format.wrapper ? null : dom.getParent(container, format.block, root); 8713 } 8714 if (!node) { 8715 const scopeRoot = (_a = dom.getParent(container, 'LI,TD,TH')) !== null && _a !== void 0 ? _a : root; 8716 node = dom.getParent(isText$a(container) ? container.parentNode : container, node => node !== root && isTextBlock(dom.schema, node), scopeRoot); 8717 } 8718 if (node && isBlockFormat(format) && format.wrapper) { 8719 node = getParents$1(dom, node, 'ul,ol').reverse()[0] || node; 8720 } 8721 if (!node) { 8722 node = container; 8723 while (node && node[siblingName] && !dom.isBlock(node[siblingName])) { 8724 node = node[siblingName]; 8725 if (isEq$5(node, 'br')) { 8726 break; 8727 } 8728 } 8729 } 8730 return node || container; 8731 }; 8732 const isAtBlockBoundary$1 = (dom, root, container, siblingName) => { 8733 const parent = container.parentNode; 8734 if (isNonNullable(container[siblingName])) { 8735 return false; 8736 } else if (parent === root || isNullable(parent) || dom.isBlock(parent)) { 8737 return true; 8738 } else { 8739 return isAtBlockBoundary$1(dom, root, parent, siblingName); 8740 } 8741 }; 8742 const findParentContainer = (dom, formatList, container, offset, start) => { 8743 let parent = container; 8744 const siblingName = start ? 'previousSibling' : 'nextSibling'; 8745 const root = dom.getRoot(); 8746 if (isText$a(container) && !isWhiteSpaceNode(container)) { 8747 if (start ? offset > 0 : offset < container.data.length) { 8748 return container; 8749 } 8750 } 8751 while (parent) { 8752 if (!formatList[0].block_expand && dom.isBlock(parent)) { 8753 return parent; 8754 } 8755 for (let sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) { 8756 const allowSpaces = isText$a(sibling) && !isAtBlockBoundary$1(dom, root, sibling, siblingName); 8757 if (!isBookmarkNode(sibling) && !isBogusBr(sibling) && !isWhiteSpaceNode(sibling, allowSpaces)) { 8758 return parent; 8759 } 8760 } 8761 if (parent === root || parent.parentNode === root) { 8762 container = parent; 8763 break; 8764 } 8765 parent = parent.parentNode; 8766 } 8767 return container; 8768 }; 8769 const isSelfOrParentBookmark = container => isBookmarkNode(container.parentNode) || isBookmarkNode(container); 8770 const expandRng = (dom, rng, formatList, includeTrailingSpace = false) => { 8771 let {startContainer, startOffset, endContainer, endOffset} = rng; 8772 const format = formatList[0]; 8773 if (isElement$6(startContainer) && startContainer.hasChildNodes()) { 8774 startContainer = getNode$1(startContainer, startOffset); 8775 if (isText$a(startContainer)) { 8776 startOffset = 0; 8777 } 8778 } 8779 if (isElement$6(endContainer) && endContainer.hasChildNodes()) { 8780 endContainer = getNode$1(endContainer, rng.collapsed ? endOffset : endOffset - 1); 8781 if (isText$a(endContainer)) { 8782 endOffset = endContainer.data.length; 8783 } 8784 } 8785 startContainer = findParentContentEditable(dom, startContainer); 8786 endContainer = findParentContentEditable(dom, endContainer); 8787 if (isSelfOrParentBookmark(startContainer)) { 8788 startContainer = isBookmarkNode(startContainer) ? startContainer : startContainer.parentNode; 8789 if (rng.collapsed) { 8790 startContainer = startContainer.previousSibling || startContainer; 8791 } else { 8792 startContainer = startContainer.nextSibling || startContainer; 8793 } 8794 if (isText$a(startContainer)) { 8795 startOffset = rng.collapsed ? startContainer.length : 0; 8796 } 8797 } 8798 if (isSelfOrParentBookmark(endContainer)) { 8799 endContainer = isBookmarkNode(endContainer) ? endContainer : endContainer.parentNode; 8800 if (rng.collapsed) { 8801 endContainer = endContainer.nextSibling || endContainer; 8802 } else { 8803 endContainer = endContainer.previousSibling || endContainer; 8804 } 8805 if (isText$a(endContainer)) { 8806 endOffset = rng.collapsed ? 0 : endContainer.length; 8807 } 8808 } 8809 if (rng.collapsed) { 8810 const startPoint = findWordEndPoint(dom, dom.getRoot(), startContainer, startOffset, true, includeTrailingSpace); 8811 startPoint.each(({container, offset}) => { 8812 startContainer = container; 8813 startOffset = offset; 8814 }); 8815 const endPoint = findWordEndPoint(dom, dom.getRoot(), endContainer, endOffset, false, includeTrailingSpace); 8816 endPoint.each(({container, offset}) => { 8817 endContainer = container; 8818 endOffset = offset; 8819 }); 8820 } 8821 if (isInlineFormat(format) || format.block_expand) { 8822 if (!isInlineFormat(format) || (!isText$a(startContainer) || startOffset === 0)) { 8823 startContainer = findParentContainer(dom, formatList, startContainer, startOffset, true); 8824 } 8825 if (!isInlineFormat(format) || (!isText$a(endContainer) || endOffset === endContainer.data.length)) { 8826 endContainer = findParentContainer(dom, formatList, endContainer, endOffset, false); 8827 } 8828 } 8829 if (shouldExpandToSelector(format)) { 8830 startContainer = findSelectorEndPoint(dom, formatList, rng, startContainer, 'previousSibling'); 8831 endContainer = findSelectorEndPoint(dom, formatList, rng, endContainer, 'nextSibling'); 8832 } 8833 if (isBlockFormat(format) || isSelectorFormat(format)) { 8834 startContainer = findBlockEndPoint(dom, formatList, startContainer, 'previousSibling'); 8835 endContainer = findBlockEndPoint(dom, formatList, endContainer, 'nextSibling'); 8836 if (isBlockFormat(format)) { 8837 if (!dom.isBlock(startContainer)) { 8838 startContainer = findParentContainer(dom, formatList, startContainer, startOffset, true); 8839 } 8840 if (!dom.isBlock(endContainer)) { 8841 endContainer = findParentContainer(dom, formatList, endContainer, endOffset, false); 8842 } 8843 } 8844 } 8845 if (isElement$6(startContainer) && startContainer.parentNode) { 8846 startOffset = dom.nodeIndex(startContainer); 8847 startContainer = startContainer.parentNode; 8848 } 8849 if (isElement$6(endContainer) && endContainer.parentNode) { 8850 endOffset = dom.nodeIndex(endContainer) + 1; 8851 endContainer = endContainer.parentNode; 8852 } 8853 return { 8854 startContainer, 8855 startOffset, 8856 endContainer, 8857 endOffset 8858 }; 8859 }; 8860 8861 const walk$3 = (dom, rng, callback) => { 8862 var _a; 8863 const startOffset = rng.startOffset; 8864 const startContainer = getNode$1(rng.startContainer, startOffset); 8865 const endOffset = rng.endOffset; 8866 const endContainer = getNode$1(rng.endContainer, endOffset - 1); 8867 const exclude = nodes => { 8868 const firstNode = nodes[0]; 8869 if (isText$a(firstNode) && firstNode === startContainer && startOffset >= firstNode.data.length) { 8870 nodes.splice(0, 1); 8871 } 8872 const lastNode = nodes[nodes.length - 1]; 8873 if (endOffset === 0 && nodes.length > 0 && lastNode === endContainer && isText$a(lastNode)) { 8874 nodes.splice(nodes.length - 1, 1); 8875 } 8876 return nodes; 8877 }; 8878 const collectSiblings = (node, name, endNode) => { 8879 const siblings = []; 8880 for (; node && node !== endNode; node = node[name]) { 8881 siblings.push(node); 8882 } 8883 return siblings; 8884 }; 8885 const findEndPoint = (node, root) => dom.getParent(node, node => node.parentNode === root, root); 8886 const walkBoundary = (startNode, endNode, next) => { 8887 const siblingName = next ? 'nextSibling' : 'previousSibling'; 8888 for (let node = startNode, parent = node.parentNode; node && node !== endNode; node = parent) { 8889 parent = node.parentNode; 8890 const siblings = collectSiblings(node === startNode ? node : node[siblingName], siblingName); 8891 if (siblings.length) { 8892 if (!next) { 8893 siblings.reverse(); 8894 } 8895 callback(exclude(siblings)); 8896 } 8897 } 8898 }; 8899 if (startContainer === endContainer) { 8900 return callback(exclude([startContainer])); 8901 } 8902 const ancestor = (_a = dom.findCommonAncestor(startContainer, endContainer)) !== null && _a !== void 0 ? _a : dom.getRoot(); 8903 if (dom.isChildOf(startContainer, endContainer)) { 8904 return walkBoundary(startContainer, ancestor, true); 8905 } 8906 if (dom.isChildOf(endContainer, startContainer)) { 8907 return walkBoundary(endContainer, ancestor); 8908 } 8909 const startPoint = findEndPoint(startContainer, ancestor) || startContainer; 8910 const endPoint = findEndPoint(endContainer, ancestor) || endContainer; 8911 walkBoundary(startContainer, startPoint, true); 8912 const siblings = collectSiblings(startPoint === startContainer ? startPoint : startPoint.nextSibling, 'nextSibling', endPoint === endContainer ? endPoint.nextSibling : endPoint); 8913 if (siblings.length) { 8914 callback(exclude(siblings)); 8915 } 8916 walkBoundary(endContainer, endPoint); 8917 }; 8918 8919 const validBlocks = [ 8920 'pre[class*=language-][contenteditable="false"]', 8921 'figure.image', 8922 'div[data-ephox-embed-iri]', 8923 'div.tiny-pageembed', 8924 'div.mce-toc', 8925 'div[data-mce-toc]' 8926 ]; 8927 const isZeroWidth = elem => isText$b(elem) && get$3(elem) === ZWSP$1; 8928 const context = (editor, elem, wrapName, nodeName) => parent(elem).fold(() => 'skipping', parent => { 8929 if (nodeName === 'br' || isZeroWidth(elem)) { 8930 return 'valid'; 8931 } else if (isAnnotation(elem)) { 8932 return 'existing'; 8933 } else if (isCaretNode(elem.dom)) { 8934 return 'caret'; 8935 } else if (exists(validBlocks, selector => is$1(elem, selector))) { 8936 return 'valid-block'; 8937 } else if (!isValid(editor, wrapName, nodeName) || !isValid(editor, name(parent), wrapName)) { 8938 return 'invalid-child'; 8939 } else { 8940 return 'valid'; 8941 } 8942 }); 8943 8944 const applyWordGrab = (editor, rng) => { 8945 const r = expandRng(editor.dom, rng, [{ inline: 'span' }]); 8946 rng.setStart(r.startContainer, r.startOffset); 8947 rng.setEnd(r.endContainer, r.endOffset); 8948 editor.selection.setRng(rng); 8949 }; 8950 const applyAnnotation = (elem, masterUId, data, annotationName, decorate, directAnnotation) => { 8951 const {uid = masterUId, ...otherData} = data; 8952 add$2(elem, annotation()); 8953 set$3(elem, `${ dataAnnotationId() }`, uid); 8954 set$3(elem, `${ dataAnnotation() }`, annotationName); 8955 const {attributes = {}, classes = []} = decorate(uid, otherData); 8956 setAll$1(elem, attributes); 8957 add(elem, classes); 8958 if (directAnnotation) { 8959 if (classes.length > 0) { 8960 set$3(elem, `${ dataAnnotationClasses() }`, classes.join(',')); 8961 } 8962 const attributeNames = keys(attributes); 8963 if (attributeNames.length > 0) { 8964 set$3(elem, `${ dataAnnotationAttributes() }`, attributeNames.join(',')); 8965 } 8966 } 8967 }; 8968 const removeDirectAnnotation = elem => { 8969 remove$
vendor: 8,668 bytes, lines 8969-9223
89698(elem, annotation()); 8970 remove$b(elem, `${ dataAnnotationId() }`); 8971 remove$b(elem, `${ dataAnnotation() }`); 8972 remove$b(elem, `${ dataAnnotationActive() }`); 8973 const customAttrNames = getOpt(elem, `${ dataAnnotationAttributes() }`).map(names => names.split(',')).getOr([]); 8974 const customClasses = getOpt(elem, `${ dataAnnotationClasses() }`).map(names => names.split(',')).getOr([]); 8975 each$e(customAttrNames, name => remove$b(elem, name)); 8976 remove$5(elem, customClasses); 8977 remove$b(elem, `${ dataAnnotationClasses() }`); 8978 remove$b(elem, `${ dataAnnotationAttributes() }`); 8979 }; 8980 const makeAnnotation = (eDoc, uid, data, annotationName, decorate) => { 8981 const master = SugarElement.fromTag('span', eDoc); 8982 applyAnnotation(master, uid, data, annotationName, decorate, false); 8983 return master; 8984 }; 8985 const annotate = (editor, rng, uid, annotationName, decorate, data) => { 8986 const newWrappers = []; 8987 const master = makeAnnotation(editor.getDoc(), uid, data, annotationName, decorate); 8988 const wrapper = value$2(); 8989 const finishWrapper = () => { 8990 wrapper.clear(); 8991 }; 8992 const getOrOpenWrapper = () => wrapper.get().getOrThunk(() => { 8993 const nu = shallow$1(master); 8994 newWrappers.push(nu); 8995 wrapper.set(nu); 8996 return nu; 8997 }); 8998 const processElements = elems => { 8999 each$e(elems, processElement); 9000 }; 9001 const processElement = elem => { 9002 const ctx = context(editor, elem, 'span', name(elem)); 9003 switch (ctx) { 9004 case 'invalid-child': { 9005 finishWrapper(); 9006 const children = children$1(elem); 9007 processElements(children); 9008 finishWrapper(); 9009 break; 9010 } 9011 case 'valid-block': { 9012 finishWrapper(); 9013 applyAnnotation(elem, uid, data, annotationName, decorate, true); 9014 break; 9015 } 9016 case 'valid': { 9017 const w = getOrOpenWrapper(); 9018 wrap$2(elem, w); 9019 break; 9020 } 9021 } 9022 }; 9023 const processNodes = nodes => { 9024 const elems = map$3(nodes, SugarElement.fromDom); 9025 processElements(elems); 9026 }; 9027 walk$3(editor.dom, rng, nodes => { 9028 finishWrapper(); 9029 processNodes(nodes); 9030 }); 9031 return newWrappers; 9032 }; 9033 const annotateWithBookmark = (editor, name, settings, data) => { 9034 editor.undoManager.transact(() => { 9035 const selection = editor.selection; 9036 const initialRng = selection.getRng(); 9037 const hasFakeSelection = getCellsFromEditor(editor).length > 0; 9038 const masterUid = generate$1('mce-annotation'); 9039 if (initialRng.collapsed && !hasFakeSelection) { 9040 applyWordGrab(editor, initialRng); 9041 } 9042 if (selection.getRng().collapsed && !hasFakeSelection) { 9043 const wrapper = makeAnnotation(editor.getDoc(), masterUid, data, name, settings.decorate); 9044 set$1(wrapper, nbsp); 9045 selection.getRng().insertNode(wrapper.dom); 9046 selection.select(wrapper.dom); 9047 } else { 9048 preserve(selection, false, () => { 9049 runOnRanges(editor, selectionRng => { 9050 annotate(editor, selectionRng, masterUid, name, settings.decorate, data); 9051 }); 9052 }); 9053 } 9054 }); 9055 }; 9056 9057 const Annotator = editor => { 9058 const registry = create$c(); 9059 setup$w(editor, registry); 9060 const changes = setup$x(editor, registry); 9061 const isSpan = isTag('span'); 9062 const removeAnnotations = elements => { 9063 each$e(elements, element => { 9064 if (isSpan(element)) { 9065 unwrap(element); 9066 } else { 9067 removeDirectAnnotation(element); 9068 } 9069 }); 9070 }; 9071 return { 9072 register: (name, settings) => { 9073 registry.register(name, settings); 9074 }, 9075 annotate: (name, data) => { 9076 registry.lookup(name).each(settings => { 9077 annotateWithBookmark(editor, name, settings, data); 9078 }); 9079 }, 9080 annotationChanged: (name, callback) => { 9081 changes.addListener(name, callback); 9082 }, 9083 remove: name => { 9084 identify(editor, Optional.some(name)).each(({elements}) => { 9085 const bookmark = editor.selection.getBookmark(); 9086 removeAnnotations(elements); 9087 editor.selection.moveToBookmark(bookmark); 9088 }); 9089 }, 9090 removeAll: name => { 9091 const bookmark = editor.selection.getBookmark(); 9092 each$d(findAll(editor, name), (elements, _) => { 9093 removeAnnotations(elements); 9094 }); 9095 editor.selection.moveToBookmark(bookmark); 9096 }, 9097 getAll: name => { 9098 const directory = findAll(editor, name); 9099 return map$2(directory, elems => map$3(elems, elem => elem.dom)); 9100 } 9101 }; 9102 }; 9103 9104 const BookmarkManager = selection => { 9105 return { 9106 getBookmark: curry(getBookmark$1, selection), 9107 moveToBookmark: curry(moveToBookmark, selection) 9108 }; 9109 }; 9110 BookmarkManager.isBookmarkNode = isBookmarkNode$1; 9111 9112 const isXYWithinRange = (clientX, clientY, range) => { 9113 if (range.collapsed) { 9114 return false; 9115 } else { 9116 return exists(range.getClientRects(), rect => containsXY(rect, clientX, clientY)); 9117 } 9118 }; 9119 9120 const firePreProcess = (editor, args) => editor.dispatch('PreProcess', args); 9121 const firePostProcess = (editor, args) => editor.dispatch('PostProcess', args); 9122 const fireRemove = editor => { 9123 editor.dispatch('remove'); 9124 }; 9125 const fireDetach = editor => { 9126 editor.dispatch('detach'); 9127 }; 9128 const fireSwitchMode = (editor, mode) => { 9129 editor.dispatch('SwitchMode', { mode }); 9130 }; 9131 const fireObjectResizeStart = (editor, target, width, height, origin) => { 9132 editor.dispatch('ObjectResizeStart', { 9133 target, 9134 width, 9135 height, 9136 origin 9137 }); 9138 }; 9139 const fireObjectResized = (editor, target, width, height, origin) => { 9140 editor.dispatch('ObjectResized', { 9141 target, 9142 width, 9143 height, 9144 origin 9145 }); 9146 }; 9147 const firePreInit = editor => { 9148 editor.dispatch('PreInit'); 9149 }; 9150 const firePostRender = editor => { 9151 editor.dispatch('PostRender'); 9152 }; 9153 const fireInit = editor => { 9154 editor.dispatch('Init'); 9155 }; 9156 const firePlaceholderToggle = (editor, state) => { 9157 editor.dispatch('PlaceholderToggle', { state }); 9158 }; 9159 const fireError = (editor, errorType, error) => { 9160 editor.dispatch(errorType, error); 9161 }; 9162 const fireFormatApply = (editor, format, node, vars) => { 9163 editor.dispatch('FormatApply', { 9164 format, 9165 node, 9166 vars 9167 }); 9168 }; 9169 const fireFormatRemove = (editor, format, node, vars) => { 9170 editor.dispatch('FormatRemove', { 9171 format, 9172 node, 9173 vars 9174 }); 9175 }; 9176 const fireBeforeSetContent = (editor, args) => editor.dispatch('BeforeSetContent', args); 9177 const fireSetContent = (editor, args) => editor.dispatch('SetContent', args); 9178 const fireBeforeGetContent = (editor, args) => editor.dispatch('BeforeGetContent', args); 9179 const fireGetContent = (editor, args) => editor.dispatch('GetContent', args); 9180 const fireAutocompleterStart = (editor, args) => { 9181 editor.dispatch('AutocompleterStart', args); 9182 }; 9183 const fireAutocompleterUpdate = (editor, args) => { 9184 editor.dispatch('AutocompleterUpdate', args); 9185 }; 9186 const fireAutocompleterEnd = editor => { 9187 editor.dispatch('AutocompleterEnd'); 9188 }; 9189 const firePastePreProcess = (editor, html, internal) => editor.dispatch('PastePreProcess', { 9190 content: html, 9191 internal 9192 }); 9193 const firePastePostProcess = (editor, node, internal) => editor.dispatch('PastePostProcess', { 9194 node, 9195 internal 9196 }); 9197 const firePastePlainTextToggle = (editor, state) => editor.dispatch('PastePlainTextToggle', { state }); 9198 9199 const VK = { 9200 BACKSPACE: 8, 9201 DELETE: 46, 9202 DOWN: 40, 9203 ENTER: 13, 9204 ESC: 27, 9205 LEFT: 37, 9206 RIGHT: 39, 9207 SPACEBAR: 32, 9208 TAB: 9, 9209 UP: 38, 9210 PAGE_UP: 33, 9211 PAGE_DOWN: 34, 9212 END: 35, 9213 HOME: 36, 9214 modifierPressed: e => { 9215 return e.shiftKey || e.ctrlKey || e.altKey || VK.metaKeyPressed(e); 9216 }, 9217 metaKeyPressed: e => { 9218 return Env.os.isMacOS() || Env.os.isiOS() ? e.metaKey : e.ctrlKey && !e.altKey; 9219 } 9220 }; 9221 9222 const elementSelectionAttr = 'data-mce-selected'; 9223 const controlElmSelector = 'table,img,figure.image,hr,video,span.mce-preview-object
vendor: 37,290 bytes, lines 9223-10248
9223'; 9224 const abs = Math.abs; 9225 const round$1 = Math.round; 9226 const resizeHandles = { 9227 nw: [ 9228 0, 9229 0, 9230 -1, 9231 -1 9232 ], 9233 ne: [ 9234 1, 9235 0, 9236 1, 9237 -1 9238 ], 9239 se: [ 9240 1, 9241 1, 9242 1, 9243 1 9244 ], 9245 sw: [ 9246 0, 9247 1, 9248 -1, 9249 1 9250 ] 9251 }; 9252 const isTouchEvent = evt => evt.type === 'longpress' || evt.type.indexOf('touch') === 0; 9253 const ControlSelection = (selection, editor) => { 9254 const dom = editor.dom; 9255 const editableDoc = editor.getDoc(); 9256 const rootDocument = document; 9257 const rootElement = editor.getBody(); 9258 let selectedElm, selectedElmGhost, resizeHelper, selectedHandle, resizeBackdrop; 9259 let startX, startY, selectedElmX, selectedElmY, startW, startH, ratio, resizeStarted; 9260 let width; 9261 let height; 9262 let startScrollWidth; 9263 let startScrollHeight; 9264 const isImage = elm => isNonNullable(elm) && (isImg(elm) || dom.is(elm, 'figure.image')); 9265 const isMedia = elm => isMedia$2(elm) || dom.hasClass(elm, 'mce-preview-object'); 9266 const isEventOnImageOutsideRange = (evt, range) => { 9267 if (isTouchEvent(evt)) { 9268 const touch = evt.touches[0]; 9269 return isImage(evt.target) && !isXYWithinRange(touch.clientX, touch.clientY, range); 9270 } else { 9271 return isImage(evt.target) && !isXYWithinRange(evt.clientX, evt.clientY, range); 9272 } 9273 }; 9274 const contextMenuSelectImage = evt => { 9275 const target = evt.target; 9276 if (isEventOnImageOutsideRange(evt, editor.selection.getRng()) && !evt.isDefaultPrevented()) { 9277 editor.selection.select(target); 9278 } 9279 }; 9280 const getResizeTargets = elm => { 9281 if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) { 9282 return [ 9283 elm, 9284 elm.firstElementChild 9285 ]; 9286 } else if (dom.is(elm, 'figure.image')) { 9287 return [elm.querySelector('img')]; 9288 } else { 9289 return [elm]; 9290 } 9291 }; 9292 const isResizable = elm => { 9293 const selector = getObjectResizing(editor); 9294 if (!selector) { 9295 return false; 9296 } 9297 if (elm.getAttribute('data-mce-resize') === 'false') { 9298 return false; 9299 } 9300 if (elm === editor.getBody()) { 9301 return false; 9302 } 9303 if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) { 9304 return is$1(SugarElement.fromDom(elm.firstElementChild), selector); 9305 } else { 9306 return is$1(SugarElement.fromDom(elm), selector); 9307 } 9308 }; 9309 const createGhostElement = elm => { 9310 if (isMedia(elm)) { 9311 return dom.create('img', { src: Env.transparentSrc }); 9312 } else { 9313 return elm.cloneNode(true); 9314 } 9315 }; 9316 const setSizeProp = (element, name, value) => { 9317 if (isNonNullable(value)) { 9318 const targets = getResizeTargets(element); 9319 each$e(targets, target => { 9320 if (target.style[name] || !editor.schema.isValid(target.nodeName.toLowerCase(), name)) { 9321 dom.setStyle(target, name, value); 9322 } else { 9323 dom.setAttrib(target, name, '' + value); 9324 } 9325 }); 9326 } 9327 }; 9328 const setGhostElmSize = (ghostElm, width, height) => { 9329 setSizeProp(ghostElm, 'width', width); 9330 setSizeProp(ghostElm, 'height', height); 9331 }; 9332 const resizeGhostElement = e => { 9333 let deltaX, deltaY, proportional; 9334 let resizeHelperX, resizeHelperY; 9335 deltaX = e.screenX - startX; 9336 deltaY = e.screenY - startY; 9337 width = deltaX * selectedHandle[2] + startW; 9338 height = deltaY * selectedHandle[3] + startH; 9339 width = width < 5 ? 5 : width; 9340 height = height < 5 ? 5 : height; 9341 if ((isImage(selectedElm) || isMedia(selectedElm)) && getResizeImgProportional(editor) !== false) { 9342 proportional = !VK.modifierPressed(e); 9343 } else { 9344 proportional = VK.modifierPressed(e); 9345 } 9346 if (proportional) { 9347 if (abs(deltaX) > abs(deltaY)) { 9348 height = round$1(width * ratio); 9349 width = round$1(height / ratio); 9350 } else { 9351 width = round$1(height / ratio); 9352 height = round$1(width * ratio); 9353 } 9354 } 9355 setGhostElmSize(selectedElmGhost, width, height); 9356 resizeHelperX = selectedHandle.startPos.x + deltaX; 9357 resizeHelperY = selectedHandle.startPos.y + deltaY; 9358 resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0; 9359 resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0; 9360 dom.setStyles(resizeHelper, { 9361 left: resizeHelperX, 9362 top: resizeHelperY, 9363 display: 'block' 9364 }); 9365 resizeHelper.innerHTML = width + ' × ' + height; 9366 if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) { 9367 dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width)); 9368 } 9369 if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) { 9370 dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height)); 9371 } 9372 deltaX = rootElement.scrollWidth - startScrollWidth; 9373 deltaY = rootElement.scrollHeight - startScrollHeight; 9374 if (deltaX + deltaY !== 0) { 9375 dom.setStyles(resizeHelper, { 9376 left: resizeHelperX - deltaX, 9377 top: resizeHelperY - deltaY 9378 }); 9379 } 9380 if (!resizeStarted) { 9381 fireObjectResizeStart(editor, selectedElm, startW, startH, 'corner-' + selectedHandle.name); 9382 resizeStarted = true; 9383 } 9384 }; 9385 const endGhostResize = () => { 9386 const wasResizeStarted = resizeStarted; 9387 resizeStarted = false; 9388 if (wasResizeStarted) { 9389 setSizeProp(selectedElm, 'width', width); 9390 setSizeProp(selectedElm, 'height', height); 9391 } 9392 dom.unbind(editableDoc, 'mousemove', resizeGhostElement); 9393 dom.unbind(editableDoc, 'mouseup', endGhostResize); 9394 if (rootDocument !== editableDoc) { 9395 dom.unbind(rootDocument, 'mousemove', resizeGhostElement); 9396 dom.unbind(rootDocument, 'mouseup', endGhostResize); 9397 } 9398 dom.remove(selectedElmGhost); 9399 dom.remove(resizeHelper); 9400 dom.remove(resizeBackdrop); 9401 showResizeRect(selectedElm); 9402 if (wasResizeStarted) { 9403 fireObjectResized(editor, selectedElm, width, height, 'corner-' + selectedHandle.name); 9404 dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style')); 9405 } 9406 editor.nodeChanged(); 9407 }; 9408 const showResizeRect = targetElm => { 9409 unbindResizeHandleEvents(); 9410 const position = dom.getPos(targetElm, rootElement); 9411 const selectedElmX = position.x; 9412 const selectedElmY = position.y; 9413 const rect = targetElm.getBoundingClientRect(); 9414 const targetWidth = rect.width || rect.right - rect.left; 9415 const targetHeight = rect.height || rect.bottom - rect.top; 9416 if (selectedElm !== targetElm) { 9417 hideResizeRect(); 9418 selectedElm = targetElm; 9419 width = height = 0; 9420 } 9421 const e = editor.dispatch('ObjectSelected', { target: targetElm }); 9422 if (isResizable(targetElm) && !e.isDefaultPrevented()) { 9423 each$d(resizeHandles, (handle, name) => { 9424 const startDrag = e => { 9425 const target = getResizeTargets(selectedElm)[0]; 9426 startX = e.screenX; 9427 startY = e.screenY; 9428 startW = target.clientWidth; 9429 startH = target.clientHeight; 9430 ratio = startH / startW; 9431 selectedHandle = handle; 9432 selectedHandle.name = name; 9433 selectedHandle.startPos = { 9434 x: targetWidth * handle[0] + selectedElmX, 9435 y: targetHeight * handle[1] + selectedElmY 9436 }; 9437 startScrollWidth = rootElement.scrollWidth; 9438 startScrollHeight = rootElement.scrollHeight; 9439 resizeBackdrop = dom.add(rootElement, 'div', { 9440 'class': 'mce-resize-backdrop', 9441 'data-mce-bogus': 'all' 9442 }); 9443 dom.setStyles(resizeBackdrop, { 9444 position: 'fixed', 9445 left: '0', 9446 top: '0', 9447 width: '100%', 9448 height: '100%' 9449 }); 9450 selectedElmGhost = createGhostElement(selectedElm); 9451 dom.addClass(selectedElmGhost, 'mce-clonedresizable'); 9452 dom.setAttrib(selectedElmGhost, 'data-mce-bogus', 'all'); 9453 selectedElmGhost.contentEditable = 'false'; 9454 dom.setStyles(selectedElmGhost, { 9455 left: selectedElmX, 9456 top: selectedElmY, 9457 margin: 0 9458 }); 9459 setGhostElmSize(selectedElmGhost, targetWidth, targetHeight); 9460 selectedElmGhost.removeAttribute(elementSelectionAttr); 9461 rootElement.appendChild(selectedElmGhost); 9462 dom.bind(editableDoc, 'mousemove', resizeGhostElement); 9463 dom.bind(editableDoc, 'mouseup', endGhostResize); 9464 if (rootDocument !== editableDoc) { 9465 dom.bind(rootDocument, 'mousemove', resizeGhostElement); 9466 dom.bind(rootDocument, 'mouseup', endGhostResize); 9467 } 9468 resizeHelper = dom.add(rootElement, 'div', { 9469 'class': 'mce-resize-helper', 9470 'data-mce-bogus': 'all' 9471 }, startW + ' × ' + startH); 9472 }; 9473 let handleElm = dom.get('mceResizeHandle' + name); 9474 if (handleElm) { 9475 dom.remove(handleElm); 9476 } 9477 handleElm = dom.add(rootElement, 'div', { 9478 'id': 'mceResizeHandle' + name, 9479 'data-mce-bogus': 'all', 9480 'class': 'mce-resizehandle', 9481 'unselectable': true, 9482 'style': 'cursor:' + name + '-resize; margin:0; padding:0' 9483 }); 9484 dom.bind(handleElm, 'mousedown', e => { 9485 e.stopImmediatePropagation(); 9486 e.preventDefault(); 9487 startDrag(e); 9488 }); 9489 handle.elm = handleElm; 9490 dom.setStyles(handleElm, { 9491 left: targetWidth * handle[0] + selectedElmX - handleElm.offsetWidth / 2, 9492 top: targetHeight * handle[1] + selectedElmY - handleElm.offsetHeight / 2 9493 }); 9494 }); 9495 } else { 9496 hideResizeRect(false); 9497 } 9498 }; 9499 const throttledShowResizeRect = first$1(showResizeRect, 0); 9500 const hideResizeRect = (removeSelected = true) => { 9501 throttledShowResizeRect.cancel(); 9502 unbindResizeHandleEvents(); 9503 if (selectedElm && removeSelected) { 9504 selectedElm.removeAttribute(elementSelectionAttr); 9505 } 9506 each$d(resizeHandles, (value, name) => { 9507 const handleElm = dom.get('mceResizeHandle' + name); 9508 if (handleElm) { 9509 dom.unbind(handleElm); 9510 dom.remove(handleElm); 9511 } 9512 }); 9513 }; 9514 const isChildOrEqual = (node, parent) => dom.isChildOf(node, parent); 9515 const updateResizeRect = e => { 9516 if (resizeStarted || editor.removed || editor.composing) { 9517 return; 9518 } 9519 const targetElm = e.type === 'mousedown' ? e.target : selection.getNode(); 9520 const controlElm = closest$3(SugarElement.fromDom(targetElm), controlElmSelector).map(e => e.dom).filter(e => dom.isEditable(e.parentElement)).getOrUndefined(); 9521 const selectedValue = isNonNullable(controlElm) ? dom.getAttrib(controlElm, elementSelectionAttr, '1') : '1'; 9522 each$e(dom.select(`img[${ elementSelectionAttr }],hr[${ elementSelectionAttr }]`), img => { 9523 img.removeAttribute(elementSelectionAttr); 9524 }); 9525 if (isNonNullable(controlElm) && isChildOrEqual(controlElm, rootElement)) { 9526 disableGeckoResize(); 9527 const startElm = selection.getStart(true); 9528 if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) { 9529 dom.setAttrib(controlElm, elementSelectionAttr, selectedValue); 9530 throttledShowResizeRect.throttle(controlElm); 9531 return; 9532 } 9533 } 9534 hideResizeRect(); 9535 }; 9536 const unbindResizeHandleEvents = () => { 9537 each$d(resizeHandles, handle => { 9538 if (handle.elm) { 9539 dom.unbind(handle.elm); 9540 delete handle.elm; 9541 } 9542 }); 9543 }; 9544 const disableGeckoResize = () => { 9545 try { 9546 editor.getDoc().execCommand('enableObjectResizing', false, 'false'); 9547 } catch (ex) { 9548 } 9549 }; 9550 editor.on('init', () => { 9551 disableGeckoResize(); 9552 editor.on('NodeChange ResizeEditor ResizeWindow ResizeContent drop', updateResizeRect); 9553 editor.on('keyup compositionend', e => { 9554 if (selectedElm && selectedElm.nodeName === 'TABLE') { 9555 updateResizeRect(e); 9556 } 9557 }); 9558 editor.on('hide blur', hideResizeRect); 9559 editor.on('contextmenu longpress', contextMenuSelectImage, true); 9560 }); 9561 editor.on('remove', unbindResizeHandleEvents); 9562 const destroy = () => { 9563 throttledShowResizeRect.cancel(); 9564 selectedElm = selectedElmGhost = resizeBackdrop = null; 9565 }; 9566 return { 9567 isResizable, 9568 showResizeRect, 9569 hideResizeRect, 9570 updateResizeRect, 9571 destroy 9572 }; 9573 }; 9574 9575 const setStart = (rng, situ) => { 9576 situ.fold(e => { 9577 rng.setStartBefore(e.dom); 9578 }, (e, o) => { 9579 rng.setStart(e.dom, o); 9580 }, e => { 9581 rng.setStartAfter(e.dom); 9582 }); 9583 }; 9584 const setFinish = (rng, situ) => { 9585 situ.fold(e => { 9586 rng.setEndBefore(e.dom); 9587 }, (e, o) => { 9588 rng.setEnd(e.dom, o); 9589 }, e => { 9590 rng.setEndAfter(e.dom); 9591 }); 9592 }; 9593 const relativeToNative = (win, startSitu, finishSitu) => { 9594 const range = win.document.createRange(); 9595 setStart(range, startSitu); 9596 setFinish(range, finishSitu); 9597 return range; 9598 }; 9599 const exactToNative = (win, start, soffset, finish, foffset) => { 9600 const rng = win.document.createRange(); 9601 rng.setStart(start.dom, soffset); 9602 rng.setEnd(finish.dom, foffset); 9603 return rng; 9604 }; 9605 9606 const adt$3 = Adt.generate([ 9607 { 9608 ltr: [ 9609 'start', 9610 'soffset', 9611 'finish', 9612 'foffset' 9613 ] 9614 }, 9615 { 9616 rtl: [ 9617 'start', 9618 'soffset', 9619 'finish', 9620 'foffset' 9621 ] 9622 } 9623 ]); 9624 const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset); 9625 const getRanges = (win, selection) => selection.match({ 9626 domRange: rng => { 9627 return { 9628 ltr: constant(rng), 9629 rtl: Optional.none 9630 }; 9631 }, 9632 relative: (startSitu, finishSitu) => { 9633 return { 9634 ltr: cached(() => relativeToNative(win, startSitu, finishSitu)), 9635 rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu))) 9636 }; 9637 }, 9638 exact: (start, soffset, finish, foffset) => { 9639 return { 9640 ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)), 9641 rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset))) 9642 }; 9643 } 9644 }); 9645 const doDiagnose = (win, ranges) => { 9646 const rng = ranges.ltr(); 9647 if (rng.collapsed) { 9648 const reversed = ranges.rtl().filter(rev => rev.collapsed === false); 9649 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)); 9650 } else { 9651 return fromRange(win, adt$3.ltr, rng); 9652 } 9653 }; 9654 const diagnose = (win, selection) => { 9655 const ranges = getRanges(win, selection); 9656 return doDiagnose(win, ranges); 9657 }; 9658 adt$3.ltr; 9659 adt$3.rtl; 9660 9661 const create$a = (start, soffset, finish, foffset) => ({ 9662 start, 9663 soffset, 9664 finish, 9665 foffset 9666 }); 9667 const SimRange = { create: create$a }; 9668 9669 const caretPositionFromPoint = (doc, x, y) => { 9670 var _a, _b; 9671 return Optional.from((_b = (_a = doc.dom).caretPositionFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y)).bind(pos => { 9672 if (pos.offsetNode === null) { 9673 return Optional.none(); 9674 } 9675 const r = doc.dom.createRange(); 9676 r.setStart(pos.offsetNode, pos.offset); 9677 r.collapse(); 9678 return Optional.some(r); 9679 }); 9680 }; 9681 const caretRangeFromPoint = (doc, x, y) => { 9682 var _a, _b; 9683 return Optional.from((_b = (_a = doc.dom).caretRangeFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y)); 9684 }; 9685 const availableSearch = (() => { 9686 if (document.caretPositionFromPoint) { 9687 return caretPositionFromPoint; 9688 } else if (document.caretRangeFromPoint) { 9689 return caretRangeFromPoint; 9690 } else { 9691 return Optional.none; 9692 } 9693 })(); 9694 const fromPoint$1 = (win, x, y) => { 9695 const doc = SugarElement.fromDom(win.document); 9696 return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset)); 9697 }; 9698 9699 const adt$2 = Adt.generate([ 9700 { before: ['element'] }, 9701 { 9702 on: [ 9703 'element', 9704 'offset' 9705 ] 9706 }, 9707 { after: ['element'] } 9708 ]); 9709 const cata = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter); 9710 const getStart$2 = situ => situ.fold(identity, identity, identity); 9711 const before$1 = adt$2.before; 9712 const on = adt$2.on; 9713 const after$1 = adt$2.after; 9714 const Situ = { 9715 before: before$1, 9716 on, 9717 after: after$1, 9718 cata, 9719 getStart: getStart$2 9720 }; 9721 9722 const adt$1 = Adt.generate([ 9723 { domRange: ['rng'] }, 9724 { 9725 relative: [ 9726 'startSitu', 9727 'finishSitu' 9728 ] 9729 }, 9730 { 9731 exact: [ 9732 'start', 9733 'soffset', 9734 'finish', 9735 'foffset' 9736 ] 9737 } 9738 ]); 9739 const exactFromRange = simRange => adt$1.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset); 9740 const getStart$1 = selection => selection.match({ 9741 domRange: rng => SugarElement.fromDom(rng.startContainer), 9742 relative: (startSitu, _finishSitu) => Situ.getStart(startSitu), 9743 exact: (start, _soffset, _finish, _foffset) => start 9744 }); 9745 const domRange = adt$1.domRange; 9746 const relative = adt$1.relative; 9747 const exact = adt$1.exact; 9748 const getWin = selection => { 9749 const start = getStart$1(selection); 9750 return defaultView(start); 9751 }; 9752 const range = SimRange.create; 9753 const SimSelection = { 9754 domRange, 9755 relative, 9756 exact, 9757 exactFromRange, 9758 getWin, 9759 range 9760 }; 9761 9762 const beforeSpecial = (element, offset) => { 9763 const name$1 = name(element); 9764 if ('input' === name$1) { 9765 return Situ.after(element); 9766 } else if (!contains$2([ 9767 'br', 9768 'img' 9769 ], name$1)) { 9770 return Situ.on(element, offset); 9771 } else { 9772 return offset === 0 ? Situ.before(element) : Situ.after(element); 9773 } 9774 }; 9775 const preprocessRelative = (startSitu, finishSitu) => { 9776 const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after); 9777 const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after); 9778 return SimSelection.relative(start, finish); 9779 }; 9780 const preprocessExact = (start, soffset, finish, foffset) => { 9781 const startSitu = beforeSpecial(start, soffset); 9782 const finishSitu = beforeSpecial(finish, foffset); 9783 return SimSelection.relative(startSitu, finishSitu); 9784 }; 9785 const preprocess = selection => selection.match({ 9786 domRange: rng => { 9787 const start = SugarElement.fromDom(rng.startContainer); 9788 const finish = SugarElement.fromDom(rng.endContainer); 9789 return preprocessExact(start, rng.startOffset, finish, rng.endOffset); 9790 }, 9791 relative: preprocessRelative, 9792 exact: preprocessExact 9793 }); 9794 9795 const fromElements = (elements, scope) => { 9796 const doc = scope || document; 9797 const fragment = doc.createDocumentFragment(); 9798 each$e(elements, element => { 9799 fragment.appendChild(element.dom); 9800 }); 9801 return SugarElement.fromDom(fragment); 9802 }; 9803 9804 const toNative = selection => { 9805 const win = SimSelection.getWin(selection).dom; 9806 const getDomRange = (start, soffset, finish, foffset) => exactToNative(win, start, soffset, finish, foffset); 9807 const filtered = preprocess(selection); 9808 return diagnose(win, filtered).match({ 9809 ltr: getDomRange, 9810 rtl: getDomRange 9811 }); 9812 }; 9813 const getAtPoint = (win, x, y) => fromPoint$1(win, x, y); 9814 9815 const fromPoint = (clientX, clientY, doc) => { 9816 const win = defaultView(SugarElement.fromDom(doc)); 9817 return getAtPoint(win.dom, clientX, clientY).map(simRange => { 9818 const rng = doc.createRange(); 9819 rng.setStart(simRange.start.dom, simRange.soffset); 9820 rng.setEnd(simRange.finish.dom, simRange.foffset); 9821 return rng; 9822 }).getOrUndefined(); 9823 }; 9824 9825 const isEq$4 = (rng1, rng2) => { 9826 return isNonNullable(rng1) && isNonNullable(rng2) && (rng1.startContainer === rng2.startContainer && rng1.startOffset === rng2.startOffset) && (rng1.endContainer === rng2.endContainer && rng1.endOffset === rng2.endOffset); 9827 }; 9828 9829 const findParent = (node, rootNode, predicate) => { 9830 let currentNode = node; 9831 while (currentNode && currentNode !== rootNode) { 9832 if (predicate(currentNode)) { 9833 return currentNode; 9834 } 9835 currentNode = currentNode.parentNode; 9836 } 9837 return null; 9838 }; 9839 const hasParent$1 = (node, rootNode, predicate) => findParent(node, rootNode, predicate) !== null; 9840 const hasParentWithName = (node, rootNode, name) => hasParent$1(node, rootNode, node => node.nodeName === name); 9841 const isCeFalseCaretContainer = (node, rootNode) => isCaretContainer$2(node) && !hasParent$1(node, rootNode, isCaretNode); 9842 const hasBrBeforeAfter = (dom, node, left) => { 9843 const parentNode = node.parentNode; 9844 if (parentNode) { 9845 const walker = new DomTreeWalker(node, dom.getParent(parentNode, dom.isBlock) || dom.getRoot()); 9846 let currentNode; 9847 while (currentNode = walker[left ? 'prev' : 'next']()) { 9848 if (isBr$6(currentNode)) { 9849 return true; 9850 } 9851 } 9852 } 9853 return false; 9854 }; 9855 const isPrevNode = (node, name) => { 9856 var _a; 9857 return ((_a = node.previousSibling) === null || _a === void 0 ? void 0 : _a.nodeName) === name; 9858 }; 9859 const hasContentEditableFalseParent = (root, node) => { 9860 let currentNode = node; 9861 while (currentNode && currentNode !== root) { 9862 if (isContentEditableFalse$b(currentNode)) { 9863 return true; 9864 } 9865 currentNode = currentNode.parentNode; 9866 } 9867 return false; 9868 }; 9869 const findTextNodeRelative = (dom, isAfterNode, collapsed, left, startNode) => { 9870 const body = dom.getRoot(); 9871 const nonEmptyElementsMap = dom.schema.getNonEmptyElements(); 9872 const parentNode = startNode.parentNode; 9873 let lastInlineElement; 9874 let node; 9875 if (!parentNode) { 9876 return Optional.none(); 9877 } 9878 const parentBlockContainer = dom.getParent(parentNode, dom.isBlock) || body; 9879 if (left && isBr$6(startNode) && isAfterNode && dom.isEmpty(parentBlockContainer)) { 9880 return Optional.some(CaretPosition(parentNode, dom.nodeIndex(startNode))); 9881 } 9882 const walker = new DomTreeWalker(startNode, parentBlockContainer); 9883 while (node = walker[left ? 'prev' : 'next']()) { 9884 if (dom.getContentEditableParent(node) === 'false' || isCeFalseCaretContainer(node, body)) { 9885 return Optional.none(); 9886 } 9887 if (isText$a(node) && node.data.length > 0) { 9888 if (!hasParentWithName(node, body, 'A')) { 9889 return Optional.some(CaretPosition(node, left ? node.data.length : 0)); 9890 } 9891 return Optional.none(); 9892 } 9893 if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) { 9894 return Optional.none(); 9895 } 9896 lastInlineElement = node; 9897 } 9898 if (isComment(lastInlineElement)) { 9899 return Optional.none(); 9900 } 9901 if (collapsed && lastInlineElement) { 9902 return Optional.some(CaretPosition(lastInlineElement, 0)); 9903 } 9904 return Optional.none(); 9905 }; 9906 const normalizeEndPoint = (dom, collapsed, start, rng) => { 9907 const body = dom.getRoot(); 9908 let node; 9909 let normalized = false; 9910 let container = start ? rng.startContainer : rng.endContainer; 9911 let offset = start ? rng.startOffset : rng.endOffset; 9912 const isAfterNode = isElement$6(container) && offset === container.childNodes.length; 9913 const nonEmptyElementsMap = dom.schema.getNonEmptyElements(); 9914 let directionLeft = start; 9915 if (isCaretContainer$2(container)) { 9916 return Optional.none(); 9917 } 9918 if (isElement$6(container) && offset > container.childNodes.length - 1) { 9919 directionLeft = false; 9920 } 9921 if (isDocument$1(container)) { 9922 container = body; 9923 offset = 0; 9924 } 9925 if (container === body) { 9926 if (directionLeft) { 9927 node = container.childNodes[offset > 0 ? offset - 1 : 0]; 9928 if (node) { 9929 if (isCaretContainer$2(node)) { 9930 return Optional.none(); 9931 } 9932 if (nonEmptyElementsMap[node.nodeName] || isTable$2(node)) { 9933 return Optional.none(); 9934 } 9935 } 9936 } 9937 if (container.hasChildNodes()) { 9938 offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1); 9939 container = container.childNodes[offset]; 9940 offset = isText$a(container) && isAfterNode ? container.data.length : 0; 9941 if (!collapsed && container === body.lastChild && isTable$2(container)) { 9942 return Optional.none(); 9943 } 9944 if (hasContentEditableFalseParent(body, container) || isCaretContainer$2(container)) { 9945 return Optional.none(); 9946 } 9947 if (container.hasChildNodes() && !isTable$2(container)) { 9948 node = container; 9949 const walker = new DomTreeWalker(container, body); 9950 do { 9951 if (isContentEditableFalse$b(node) || isCaretContainer$2(node)) { 9952 normalized = false; 9953 break; 9954 } 9955 if (isText$a(node) && node.data.length > 0) { 9956 offset = directionLeft ? 0 : node.data.length; 9957 container = node; 9958 normalized = true; 9959 break; 9960 } 9961 if (nonEmptyElementsMap[node.nodeName.toLowerCase()] && !isTableCellOrCaption(node)) { 9962 offset = dom.nodeIndex(node); 9963 container = node.parentNode; 9964 if (!directionLeft) { 9965 offset++; 9966 } 9967 normalized = true; 9968 break; 9969 } 9970 } while (node = directionLeft ? walker.next() : walker.prev()); 9971 } 9972 } 9973 } 9974 if (collapsed) { 9975 if (isText$a(container) && offset === 0) { 9976 findTextNodeRelative(dom, isAfterNode, collapsed, true, container).each(pos => { 9977 container = pos.container(); 9978 offset = pos.offset(); 9979 normalized = true; 9980 }); 9981 } 9982 if (isElement$6(container)) { 9983 node = container.childNodes[offset]; 9984 if (!node) { 9985 node = container.childNodes[offset - 1]; 9986 } 9987 if (node && isBr$6(node) && !isPrevNode(node, 'A') && !hasBrBeforeAfter(dom, node, false) && !hasBrBeforeAfter(dom, node, true)) { 9988 findTextNodeRelative(dom, isAfterNode, collapsed, true, node).each(pos => { 9989 container = pos.container(); 9990 offset = pos.offset(); 9991 normalized = true; 9992 }); 9993 } 9994 } 9995 } 9996 if (directionLeft && !collapsed && isText$a(container) && offset === container.data.length) { 9997 findTextNodeRelative(dom, isAfterNode, collapsed, false, container).each(pos => { 9998 container = pos.container(); 9999 offset = pos.offset(); 10000 normalized = true; 10001 }); 10002 } 10003 return normalized && container ? Optional.some(CaretPosition(container, offset)) : Optional.none(); 10004 }; 10005 const normalize$2 = (dom, rng) => { 10006 const collapsed = rng.collapsed, normRng = rng.cloneRange(); 10007 const startPos = CaretPosition.fromRangeStart(rng); 10008 normalizeEndPoint(dom, collapsed, true, normRng).each(pos => { 10009 if (!collapsed || !CaretPosition.isAbove(startPos, pos)) { 10010 normRng.setStart(pos.container(), pos.offset()); 10011 } 10012 }); 10013 if (!collapsed) { 10014 normalizeEndPoint(dom, collapsed, false, normRng).each(pos => { 10015 normRng.setEnd(pos.container(), pos.offset()); 10016 }); 10017 } 10018 if (collapsed) { 10019 normRng.collapse(true); 10020 } 10021 return isEq$4(rng, normRng) ? Optional.none() : Optional.some(normRng); 10022 }; 10023 10024 const splitText = (node, offset) => { 10025 return node.splitText(offset); 10026 }; 10027 const split = rng => { 10028 let startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset; 10029 if (startContainer === endContainer && isText$a(startContainer)) { 10030 if (startOffset > 0 && startOffset < startContainer.data.length) { 10031 endContainer = splitText(startContainer, startOffset); 10032 startContainer = endContainer.previousSibling; 10033 if (endOffset > startOffset) { 10034 endOffset = endOffset - startOffset; 10035 const newContainer = splitText(endContainer, endOffset).previousSibling; 10036 startContainer = endContainer = newContainer; 10037 endOffset = newContainer.data.length; 10038 startOffset = 0; 10039 } else { 10040 endOffset = 0; 10041 } 10042 } 10043 } else { 10044 if (isText$a(startContainer) && startOffset > 0 && startOffset < startContainer.data.length) { 10045 startContainer = splitText(startContainer, startOffset); 10046 startOffset = 0; 10047 } 10048 if (isText$a(endContainer) && endOffset > 0 && endOffset < endContainer.data.length) { 10049 const newContainer = splitText(endContainer, endOffset).previousSibling; 10050 endContainer = newContainer; 10051 endOffset = newContainer.data.length; 10052 } 10053 } 10054 return { 10055 startContainer, 10056 startOffset, 10057 endContainer, 10058 endOffset 10059 }; 10060 }; 10061 10062 const RangeUtils = dom => { 10063 const walk = (rng, callback) => { 10064 return walk$3(dom, rng, callback); 10065 }; 10066 const split$1 = split; 10067 const normalize = rng => { 10068 return normalize$2(dom, rng).fold(never, normalizedRng => { 10069 rng.setStart(normalizedRng.startContainer, normalizedRng.startOffset); 10070 rng.setEnd(normalizedRng.endContainer, normalizedRng.endOffset); 10071 return true; 10072 }); 10073 }; 10074 const expand = (rng, options = { type: 'word' }) => { 10075 if (options.type === 'word') { 10076 const rangeLike = expandRng(dom, rng, [{ inline: 'span' }]); 10077 const newRange = dom.createRng(); 10078 newRange.setStart(rangeLike.startContainer, rangeLike.startOffset); 10079 newRange.setEnd(rangeLike.endContainer, rangeLike.endOffset); 10080 return newRange; 10081 } 10082 return rng; 10083 }; 10084 return { 10085 walk, 10086 split: split$1, 10087 expand, 10088 normalize 10089 }; 10090 }; 10091 RangeUtils.compareRanges = isEq$4; 10092 RangeUtils.getCaretRangeFromPoint = fromPoint; 10093 RangeUtils.getSelectedNode = getSelectedNode; 10094 RangeUtils.getNode = getNode$1; 10095 10096 const Dimension = (name, getOffset) => { 10097 const set = (element, h) => { 10098 if (!isNumber(h) && !h.match(/^[0-9]+$/)) { 10099 throw new Error(name + '.set accepts only positive integer values. Value was ' + h); 10100 } 10101 const dom = element.dom; 10102 if (isSupported(dom)) { 10103 dom.style[name] = h + 'px'; 10104 } 10105 }; 10106 const get = element => { 10107 const r = getOffset(element); 10108 if (r <= 0 || r === null) { 10109 const css = get$7(element, name); 10110 return parseFloat(css) || 0; 10111 } 10112 return r; 10113 }; 10114 const getOuter = get; 10115 const aggregate = (element, properties) => foldl(properties, (acc, property) => { 10116 const val = get$7(element, property); 10117 const value = val === undefined ? 0 : parseInt(val, 10); 10118 return isNaN(value) ? acc : acc + value; 10119 }, 0); 10120 const max = (element, value, properties) => { 10121 const cumulativeInclusions = aggregate(element, properties); 10122 const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0; 10123 return absoluteMax; 10124 }; 10125 return { 10126 set, 10127 get, 10128 getOuter, 10129 aggregate, 10130 max 10131 }; 10132 }; 10133 10134 const api = Dimension('height', element => { 10135 const dom = element.dom; 10136 return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight; 10137 }); 10138 const get$2 = element => api.get(element); 10139 10140 const getDocument = () => SugarElement.fromDom(document); 10141 10142 const walkUp = (navigation, doc) => { 10143 const frame = navigation.view(doc); 10144 return frame.fold(constant([]), f => { 10145 const parent = navigation.owner(f); 10146 const rest = walkUp(navigation, parent); 10147 return [f].concat(rest); 10148 }); 10149 }; 10150 const pathTo = (element, navigation) => { 10151 const d = navigation.owner(element); 10152 return walkUp(navigation, d); 10153 }; 10154 10155 const view = doc => { 10156 var _a; 10157 const element = doc.dom === document ? Optional.none() : Optional.from((_a = doc.dom.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement); 10158 return element.map(SugarElement.fromDom); 10159 }; 10160 const owner = element => documentOrOwner(element); 10161 10162 var Navigation = /*#__PURE__*/Object.freeze({ 10163 __proto__: null, 10164 view: view, 10165 owner: owner 10166 }); 10167 10168 const find = element => { 10169 const doc = getDocument(); 10170 const scroll = get$5(doc); 10171 const frames = pathTo(element, Navigation); 10172 const offset = viewport(element); 10173 const r = foldr(frames, (b, a) => { 10174 const loc = viewport(a); 10175 return { 10176 left: b.left + loc.left, 10177 top: b.top + loc.top 10178 }; 10179 }, { 10180 left: 0, 10181 top: 0 10182 }); 10183 return SugarPosition(r.left + offset.left + scroll.left, r.top + offset.top + scroll.top); 10184 }; 10185 10186 const excludeFromDescend = element => name(element) === 'textarea'; 10187 const fireScrollIntoViewEvent = (editor, data) => { 10188 const scrollEvent = editor.dispatch('ScrollIntoView', data); 10189 return scrollEvent.isDefaultPrevented(); 10190 }; 10191 const fireAfterScrollIntoViewEvent = (editor, data) => { 10192 editor.dispatch('AfterScrollIntoView', data); 10193 }; 10194 const descend = (element, offset) => { 10195 const children = children$1(element); 10196 if (children.length === 0 || excludeFromDescend(element)) { 10197 return { 10198 element, 10199 offset 10200 }; 10201 } else if (offset < children.length && !excludeFromDescend(children[offset])) { 10202 return { 10203 element: children[offset], 10204 offset: 0 10205 }; 10206 } else { 10207 const last = children[children.length - 1]; 10208 if (excludeFromDescend(last)) { 10209 return { 10210 element, 10211 offset 10212 }; 10213 } else { 10214 if (name(last) === 'img') { 10215 return { 10216 element: last, 10217 offset: 1 10218 }; 10219 } else if (isText$b(last)) { 10220 return { 10221 element: last, 10222 offset: get$3(last).length 10223 }; 10224 } else { 10225 return { 10226 element: last, 10227 offset: children$1(last).length 10228 }; 10229 } 10230 } 10231 } 10232 }; 10233 const markerInfo = (element, cleanupFun) => { 10234 const pos = absolute(element); 10235 const height = get$2(element); 10236 return { 10237 element, 10238 bottom: pos.top + height, 10239 height, 10240 pos, 10241 cleanup: cleanupFun 10242 }; 10243 }; 10244 const createMarker$1 = (element, offset) => { 10245 const startPoint = descend(element, offset); 10246 const span = SugarElement.fromHtml('<span data-mce-bogus="all" style="display: inline-block;">' + ZWSP$1 + '</span>'); 10247 before$3(startPoint.element, span); 10248 return markerInfo(span, () => remove$
102486
vendor: 11,311 bytes, lines 10248-10520
10248(span)); 10249 }; 10250 const elementMarker = element => markerInfo(SugarElement.fromDom(element), noop); 10251 const withMarker = (editor, f, rng, alignToTop) => { 10252 preserveWith(editor, (_s, _e) => applyWithMarker(editor, f, rng, alignToTop), rng); 10253 }; 10254 const withScrollEvents = (editor, doc, f, marker, alignToTop) => { 10255 const data = { 10256 elm: marker.element.dom, 10257 alignToTop 10258 }; 10259 if (fireScrollIntoViewEvent(editor, data)) { 10260 return; 10261 } 10262 const scrollTop = get$5(doc).top; 10263 f(doc, scrollTop, marker, alignToTop); 10264 fireAfterScrollIntoViewEvent(editor, data); 10265 }; 10266 const applyWithMarker = (editor, f, rng, alignToTop) => { 10267 const body = SugarElement.fromDom(editor.getBody()); 10268 const doc = SugarElement.fromDom(editor.getDoc()); 10269 reflow(body); 10270 const marker = createMarker$1(SugarElement.fromDom(rng.startContainer), rng.startOffset); 10271 withScrollEvents(editor, doc, f, marker, alignToTop); 10272 marker.cleanup(); 10273 }; 10274 const withElement = (editor, element, f, alignToTop) => { 10275 const doc = SugarElement.fromDom(editor.getDoc()); 10276 withScrollEvents(editor, doc, f, elementMarker(element), alignToTop); 10277 }; 10278 const preserveWith = (editor, f, rng) => { 10279 const startElement = rng.startContainer; 10280 const startOffset = rng.startOffset; 10281 const endElement = rng.endContainer; 10282 const endOffset = rng.endOffset; 10283 f(SugarElement.fromDom(startElement), SugarElement.fromDom(endElement)); 10284 const newRng = editor.dom.createRng(); 10285 newRng.setStart(startElement, startOffset); 10286 newRng.setEnd(endElement, endOffset); 10287 editor.selection.setRng(rng); 10288 }; 10289 const scrollToMarker = (marker, alignToTop) => marker.element.dom.scrollIntoView({ block: alignToTop ? 'start' : 'end' }); 10290 const intoWindowIfNeeded = (scrollTop, viewHeight, marker, alignToTop) => { 10291 const viewportBottom = viewHeight + scrollTop; 10292 const markerTop = marker.pos.top; 10293 const markerBottom = marker.bottom; 10294 const largerThanViewport = markerBottom - markerTop >= viewHeight; 10295 if (markerTop < scrollTop) { 10296 scrollToMarker(marker, alignToTop !== false); 10297 } else if (markerTop > viewportBottom) { 10298 const align = largerThanViewport ? alignToTop !== false : alignToTop === true; 10299 scrollToMarker(marker, align); 10300 } else if (markerBottom > viewportBottom && !largerThanViewport) { 10301 scrollToMarker(marker, alignToTop === true); 10302 } 10303 }; 10304 const intoWindow = (doc, scrollTop, marker, alignToTop) => { 10305 const viewHeight = defaultView(doc).dom.innerHeight; 10306 intoWindowIfNeeded(scrollTop, viewHeight, marker, alignToTop); 10307 }; 10308 const intoFrame = (doc, scrollTop, marker, alignToTop) => { 10309 const frameViewHeight = defaultView(doc).dom.innerHeight; 10310 intoWindowIfNeeded(scrollTop, frameViewHeight, marker, alignToTop); 10311 const op = find(marker.element); 10312 const viewportBounds = getBounds(window); 10313 if (op.top < viewportBounds.y) { 10314 intoView(marker.element, alignToTop !== false); 10315 } else if (op.top > viewportBounds.bottom) { 10316 intoView(marker.element, alignToTop === true); 10317 } 10318 }; 10319 const rangeIntoWindow = (editor, rng, alignToTop) => withMarker(editor, intoWindow, rng, alignToTop); 10320 const elementIntoWindow = (editor, element, alignToTop) => withElement(editor, element, intoWindow, alignToTop); 10321 const rangeIntoFrame = (editor, rng, alignToTop) => withMarker(editor, intoFrame, rng, alignToTop); 10322 const elementIntoFrame = (editor, element, alignToTop) => withElement(editor, element, intoFrame, alignToTop); 10323 const scrollElementIntoView = (editor, element, alignToTop) => { 10324 const scroller = editor.inline ? elementIntoWindow : elementIntoFrame; 10325 scroller(editor, element, alignToTop); 10326 }; 10327 const scrollRangeIntoView = (editor, rng, alignToTop) => { 10328 const scroller = editor.inline ? rangeIntoWindow : rangeIntoFrame; 10329 scroller(editor, rng, alignToTop); 10330 }; 10331 10332 const focus$1 = element => element.dom.focus(); 10333 const hasFocus$1 = element => { 10334 const root = getRootNode(element).dom; 10335 return element.dom === root.activeElement; 10336 }; 10337 const active$1 = (root = getDocument()) => Optional.from(root.dom.activeElement).map(SugarElement.fromDom); 10338 const search = element => active$1(getRootNode(element)).filter(e => element.dom.contains(e.dom)); 10339 10340 const clamp$1 = (offset, element) => { 10341 const max = isText$b(element) ? get$3(element).length : children$1(element).length + 1; 10342 if (offset > max) { 10343 return max; 10344 } else if (offset < 0) { 10345 return 0; 10346 } 10347 return offset; 10348 }; 10349 const normalizeRng = rng => SimSelection.range(rng.start, clamp$1(rng.soffset, rng.start), rng.finish, clamp$1(rng.foffset, rng.finish)); 10350 const isOrContains = (root, elm) => !isRestrictedNode(elm.dom) && (contains(root, elm) || eq(root, elm)); 10351 const isRngInRoot = root => rng => isOrContains(root, rng.start) && isOrContains(root, rng.finish); 10352 const shouldStore = editor => editor.inline || Env.browser.isFirefox(); 10353 const nativeRangeToSelectionRange = r => SimSelection.range(SugarElement.fromDom(r.startContainer), r.startOffset, SugarElement.fromDom(r.endContainer), r.endOffset); 10354 const readRange = win => { 10355 const selection = win.getSelection(); 10356 const rng = !selection || selection.rangeCount === 0 ? Optional.none() : Optional.from(selection.getRangeAt(0)); 10357 return rng.map(nativeRangeToSelectionRange); 10358 }; 10359 const getBookmark = root => { 10360 const win = defaultView(root); 10361 return readRange(win.dom).filter(isRngInRoot(root)); 10362 }; 10363 const validate = (root, bookmark) => Optional.from(bookmark).filter(isRngInRoot(root)).map(normalizeRng); 10364 const bookmarkToNativeRng = bookmark => { 10365 const rng = document.createRange(); 10366 try { 10367 rng.setStart(bookmark.start.dom, bookmark.soffset); 10368 rng.setEnd(bookmark.finish.dom, bookmark.foffset); 10369 return Optional.some(rng); 10370 } catch (_) { 10371 return Optional.none(); 10372 } 10373 }; 10374 const store = editor => { 10375 const newBookmark = shouldStore(editor) ? getBookmark(SugarElement.fromDom(editor.getBody())) : Optional.none(); 10376 editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark; 10377 }; 10378 const getRng = editor => { 10379 const bookmark = editor.bookmark ? editor.bookmark : Optional.none(); 10380 return bookmark.bind(x => validate(SugarElement.fromDom(editor.getBody()), x)).bind(bookmarkToNativeRng); 10381 }; 10382 const restore = editor => { 10383 getRng(editor).each(rng => editor.selection.setRng(rng)); 10384 }; 10385 10386 const isEditorUIElement$1 = elm => { 10387 const className = elm.className.toString(); 10388 return className.indexOf('tox-') !== -1 || className.indexOf('mce-') !== -1; 10389 }; 10390 const FocusManager = { isEditorUIElement: isEditorUIElement$1 }; 10391 10392 const wrappedSetTimeout = (callback, time) => { 10393 if (!isNumber(time)) { 10394 time = 0; 10395 } 10396 return setTimeout(callback, time); 10397 }; 10398 const wrappedSetInterval = (callback, time) => { 10399 if (!isNumber(time)) { 10400 time = 0; 10401 } 10402 return setInterval(callback, time); 10403 }; 10404 const Delay = { 10405 setEditorTimeout: (editor, callback, time) => { 10406 return wrappedSetTimeout(() => { 10407 if (!editor.removed) { 10408 callback(); 10409 } 10410 }, time); 10411 }, 10412 setEditorInterval: (editor, callback, time) => { 10413 const timer = wrappedSetInterval(() => { 10414 if (!editor.removed) { 10415 callback(); 10416 } else { 10417 clearInterval(timer); 10418 } 10419 }, time); 10420 return timer; 10421 } 10422 }; 10423 10424 const isManualNodeChange = e => { 10425 return e.type === 'nodechange' && e.selectionChange; 10426 }; 10427 const registerPageMouseUp = (editor, throttledStore) => { 10428 const mouseUpPage = () => { 10429 throttledStore.throttle(); 10430 }; 10431 DOMUtils.DOM.bind(document, 'mouseup', mouseUpPage); 10432 editor.on('remove', () => { 10433 DOMUtils.DOM.unbind(document, 'mouseup', mouseUpPage); 10434 }); 10435 }; 10436 const registerMouseUp = (editor, throttledStore) => { 10437 editor.on('mouseup touchend', _e => { 10438 throttledStore.throttle(); 10439 }); 10440 }; 10441 const registerEditorEvents = (editor, throttledStore) => { 10442 registerMouseUp(editor, throttledStore); 10443 editor.on('keyup NodeChange AfterSetSelectionRange', e => { 10444 if (!isManualNodeChange(e)) { 10445 store(editor); 10446 } 10447 }); 10448 }; 10449 const register$6 = editor => { 10450 const throttledStore = first$1(() => { 10451 store(editor); 10452 }, 0); 10453 editor.on('init', () => { 10454 if (editor.inline) { 10455 registerPageMouseUp(editor, throttledStore); 10456 } 10457 registerEditorEvents(editor, throttledStore); 10458 }); 10459 editor.on('remove', () => { 10460 throttledStore.cancel(); 10461 }); 10462 }; 10463 10464 let documentFocusInHandler; 10465 const DOM$9 = DOMUtils.DOM; 10466 const isEditorUIElement = elm => { 10467 return isElement$6(elm) && FocusManager.isEditorUIElement(elm); 10468 }; 10469 const isEditorContentAreaElement = elm => { 10470 const classList = elm.classList; 10471 if (classList !== undefined) { 10472 return classList.contains('tox-edit-area') || classList.contains('tox-edit-area__iframe') || classList.contains('mce-content-body'); 10473 } else { 10474 return false; 10475 } 10476 }; 10477 const isUIElement = (editor, elm) => { 10478 const customSelector = getCustomUiSelector(editor); 10479 const parent = DOM$9.getParent(elm, elm => { 10480 return isEditorUIElement(elm) || (customSelector ? editor.dom.is(elm, customSelector) : false); 10481 }); 10482 return parent !== null; 10483 }; 10484 const getActiveElement = editor => { 10485 try { 10486 const root = getRootNode(SugarElement.fromDom(editor.getElement())); 10487 return active$1(root).fold(() => document.body, x => x.dom); 10488 } catch (ex) { 10489 return document.body; 10490 } 10491 }; 10492 const registerEvents$1 = (editorManager, e) => { 10493 const editor = e.editor; 10494 register$6(editor); 10495 const toggleContentAreaOnFocus = (editor, fn) => { 10496 if (shouldHighlightOnFocus(editor) && editor.inline !== true) { 10497 const contentArea = SugarElement.fromDom(editor.getContainer()); 10498 fn(contentArea, 'tox-edit-focus'); 10499 } 10500 }; 10501 editor.on('focusin', () => { 10502 const focusedEditor = editorManager.focusedEditor; 10503 if (isEditorContentAreaElement(getActiveElement(editor))) { 10504 toggleContentAreaOnFocus(editor, add$2); 10505 } 10506 if (focusedEditor !== editor) { 10507 if (focusedEditor) { 10508 focusedEditor.dispatch('blur', { focusedEditor: editor }); 10509 } 10510 editorManager.setActive(editor); 10511 editorManager.focusedEditor = editor; 10512 editor.dispatch('focus', { blurredEditor: focusedEditor }); 10513 editor.focus(true); 10514 } 10515 }); 10516 editor.on('focusout', () => { 10517 Delay.setEditorTimeout(editor, () => { 10518 const focusedEditor = editorManager.focusedEditor; 10519 if (!isEditorContentAreaElement(getActiveElement(editor)) || focusedEditor !== editor) { 10520 toggleContentAreaOnFocus(editor, remove$
105208
vendor: 10,567 bytes, lines 10520-10778
10520); 10521 } 10522 if (!isUIElement(editor, getActiveElement(editor)) && focusedEditor === editor) { 10523 editor.dispatch('blur', { focusedEditor: null }); 10524 editorManager.focusedEditor = null; 10525 } 10526 }); 10527 }); 10528 if (!documentFocusInHandler) { 10529 documentFocusInHandler = e => { 10530 const activeEditor = editorManager.activeEditor; 10531 if (activeEditor) { 10532 getOriginalEventTarget(e).each(target => { 10533 const elem = target; 10534 if (elem.ownerDocument === document) { 10535 if (elem !== document.body && !isUIElement(activeEditor, elem) && editorManager.focusedEditor === activeEditor) { 10536 activeEditor.dispatch('blur', { focusedEditor: null }); 10537 editorManager.focusedEditor = null; 10538 } 10539 } 10540 }); 10541 } 10542 }; 10543 DOM$9.bind(document, 'focusin', documentFocusInHandler); 10544 } 10545 }; 10546 const unregisterDocumentEvents = (editorManager, e) => { 10547 if (editorManager.focusedEditor === e.editor) { 10548 editorManager.focusedEditor = null; 10549 } 10550 if (!editorManager.activeEditor && documentFocusInHandler) { 10551 DOM$9.unbind(document, 'focusin', documentFocusInHandler); 10552 documentFocusInHandler = null; 10553 } 10554 }; 10555 const setup$v = editorManager => { 10556 editorManager.on('AddEditor', curry(registerEvents$1, editorManager)); 10557 editorManager.on('RemoveEditor', curry(unregisterDocumentEvents, editorManager)); 10558 }; 10559 10560 const getContentEditableHost = (editor, node) => editor.dom.getParent(node, node => editor.dom.getContentEditable(node) === 'true'); 10561 const getCollapsedNode = rng => rng.collapsed ? Optional.from(getNode$1(rng.startContainer, rng.startOffset)).map(SugarElement.fromDom) : Optional.none(); 10562 const getFocusInElement = (root, rng) => getCollapsedNode(rng).bind(node => { 10563 if (isTableSection(node)) { 10564 return Optional.some(node); 10565 } else if (!contains(root, node)) { 10566 return Optional.some(root); 10567 } else { 10568 return Optional.none(); 10569 } 10570 }); 10571 const normalizeSelection = (editor, rng) => { 10572 getFocusInElement(SugarElement.fromDom(editor.getBody()), rng).bind(elm => { 10573 return firstPositionIn(elm.dom); 10574 }).fold(() => { 10575 editor.selection.normalize(); 10576 }, caretPos => editor.selection.setRng(caretPos.toRange())); 10577 }; 10578 const focusBody = body => { 10579 if (body.setActive) { 10580 try { 10581 body.setActive(); 10582 } catch (ex) { 10583 body.focus(); 10584 } 10585 } else { 10586 body.focus(); 10587 } 10588 }; 10589 const hasElementFocus = elm => hasFocus$1(elm) || search(elm).isSome(); 10590 const hasIframeFocus = editor => isNonNullable(editor.iframeElement) && hasFocus$1(SugarElement.fromDom(editor.iframeElement)); 10591 const hasInlineFocus = editor => { 10592 const rawBody = editor.getBody(); 10593 return rawBody && hasElementFocus(SugarElement.fromDom(rawBody)); 10594 }; 10595 const hasUiFocus = editor => { 10596 const dos = getRootNode(SugarElement.fromDom(editor.getElement())); 10597 return active$1(dos).filter(elem => !isEditorContentAreaElement(elem.dom) && isUIElement(editor, elem.dom)).isSome(); 10598 }; 10599 const hasFocus = editor => editor.inline ? hasInlineFocus(editor) : hasIframeFocus(editor); 10600 const hasEditorOrUiFocus = editor => hasFocus(editor) || hasUiFocus(editor); 10601 const focusEditor = editor => { 10602 const selection = editor.selection; 10603 const body = editor.getBody(); 10604 let rng = selection.getRng(); 10605 editor.quirks.refreshContentEditable(); 10606 if (isNonNullable(editor.bookmark) && !hasFocus(editor)) { 10607 getRng(editor).each(bookmarkRng => { 10608 editor.selection.setRng(bookmarkRng); 10609 rng = bookmarkRng; 10610 }); 10611 } 10612 const contentEditableHost = getContentEditableHost(editor, selection.getNode()); 10613 if (contentEditableHost && editor.dom.isChildOf(contentEditableHost, body)) { 10614 focusBody(contentEditableHost); 10615 normalizeSelection(editor, rng); 10616 activateEditor(editor); 10617 return; 10618 } 10619 if (!editor.inline) { 10620 if (!Env.browser.isOpera()) { 10621 focusBody(body); 10622 } 10623 editor.getWin().focus(); 10624 } 10625 if (Env.browser.isFirefox() || editor.inline) { 10626 focusBody(body); 10627 normalizeSelection(editor, rng); 10628 } 10629 activateEditor(editor); 10630 }; 10631 const activateEditor = editor => editor.editorManager.setActive(editor); 10632 const focus = (editor, skipFocus) => { 10633 if (editor.removed) { 10634 return; 10635 } 10636 if (skipFocus) { 10637 activateEditor(editor); 10638 } else { 10639 focusEditor(editor); 10640 } 10641 }; 10642 10643 const getEndpointElement = (root, rng, start, real, resolve) => { 10644 const container = start ? rng.startContainer : rng.endContainer; 10645 const offset = start ? rng.startOffset : rng.endOffset; 10646 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); 10647 }; 10648 const getStart = (root, rng, real = false) => getEndpointElement(root, rng, true, real, (elm, offset) => Math.min(childNodesCount(elm), offset)); 10649 const getEnd$1 = (root, rng, real = false) => getEndpointElement(root, rng, false, real, (elm, offset) => offset > 0 ? offset - 1 : offset); 10650 const skipEmptyTextNodes = (node, forwards) => { 10651 const orig = node; 10652 while (node && isText$a(node) && node.length === 0) { 10653 node = forwards ? node.nextSibling : node.previousSibling; 10654 } 10655 return node || orig; 10656 }; 10657 const getNode = (root, rng) => { 10658 if (!rng) { 10659 return root; 10660 } 10661 let startContainer = rng.startContainer; 10662 let endContainer = rng.endContainer; 10663 const startOffset = rng.startOffset; 10664 const endOffset = rng.endOffset; 10665 let node = rng.commonAncestorContainer; 10666 if (!rng.collapsed) { 10667 if (startContainer === endContainer) { 10668 if (endOffset - startOffset < 2) { 10669 if (startContainer.hasChildNodes()) { 10670 node = startContainer.childNodes[startOffset]; 10671 } 10672 } 10673 } 10674 if (isText$a(startContainer) && isText$a(endContainer)) { 10675 if (startContainer.length === startOffset) { 10676 startContainer = skipEmptyTextNodes(startContainer.nextSibling, true); 10677 } else { 10678 startContainer = startContainer.parentNode; 10679 } 10680 if (endOffset === 0) { 10681 endContainer = skipEmptyTextNodes(endContainer.previousSibling, false); 10682 } else { 10683 endContainer = endContainer.parentNode; 10684 } 10685 if (startContainer && startContainer === endContainer) { 10686 node = startContainer; 10687 } 10688 } 10689 } 10690 const elm = isText$a(node) ? node.parentNode : node; 10691 return isElement$6(elm) ? elm : root; 10692 }; 10693 const getSelectedBlocks = (dom, rng, startElm, endElm) => { 10694 const selectedBlocks = []; 10695 const root = dom.getRoot(); 10696 const start = dom.getParent(startElm || getStart(root, rng, rng.collapsed), dom.isBlock); 10697 const end = dom.getParent(endElm || getEnd$1(root, rng, rng.collapsed), dom.isBlock); 10698 if (start && start !== root) { 10699 selectedBlocks.push(start); 10700 } 10701 if (start && end && start !== end) { 10702 let node; 10703 const walker = new DomTreeWalker(start, root); 10704 while ((node = walker.next()) && node !== end) { 10705 if (dom.isBlock(node)) { 10706 selectedBlocks.push(node); 10707 } 10708 } 10709 } 10710 if (end && start !== end && end !== root) { 10711 selectedBlocks.push(end); 10712 } 10713 return selectedBlocks; 10714 }; 10715 const select = (dom, node, content) => Optional.from(node).bind(node => Optional.from(node.parentNode).map(parent => { 10716 const idx = dom.nodeIndex(node); 10717 const rng = dom.createRng(); 10718 rng.setStart(parent, idx); 10719 rng.setEnd(parent, idx + 1); 10720 if (content) { 10721 moveEndPoint(dom, rng, node, true); 10722 moveEndPoint(dom, rng, node, false); 10723 } 10724 return rng; 10725 })); 10726 10727 const processRanges = (editor, ranges) => map$3(ranges, range => { 10728 const evt = editor.dispatch('GetSelectionRange', { range }); 10729 return evt.range !== range ? evt.range : range; 10730 }); 10731 10732 const getEnd = element => name(element) === 'img' ? 1 : getOption(element).fold(() => children$1(element).length, v => v.length); 10733 const isTextNodeWithCursorPosition = el => getOption(el).filter(text => text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome(); 10734 const isContentEditableFalse$5 = elem => isHTMLElement(elem) && get$9(elem, 'contenteditable') === 'false'; 10735 const elementsWithCursorPosition = [ 10736 'img', 10737 'br' 10738 ]; 10739 const isCursorPosition = elem => { 10740 const hasCursorPosition = isTextNodeWithCursorPosition(elem); 10741 return hasCursorPosition || contains$2(elementsWithCursorPosition, name(elem)) || isContentEditableFalse$5(elem); 10742 }; 10743 10744 const first = element => descendant$1(element, isCursorPosition); 10745 const last = element => descendantRtl(element, isCursorPosition); 10746 const descendantRtl = (scope, predicate) => { 10747 const descend = element => { 10748 const children = children$1(element); 10749 for (let i = children.length - 1; i >= 0; i--) { 10750 const child = children[i]; 10751 if (predicate(child)) { 10752 return Optional.some(child); 10753 } 10754 const res = descend(child); 10755 if (res.isSome()) { 10756 return res; 10757 } 10758 } 10759 return Optional.none(); 10760 }; 10761 return descend(scope); 10762 }; 10763 10764 const autocompleteSelector = '[data-mce-autocompleter]'; 10765 const create$9 = (editor, range) => { 10766 if (findIn(SugarElement.fromDom(editor.getBody())).isNone()) { 10767 const wrapper = SugarElement.fromHtml('<span data-mce-autocompleter="1" data-mce-bogus="1"></span>', editor.getDoc()); 10768 append$1(wrapper, SugarElement.fromDom(range.extractContents())); 10769 range.insertNode(wrapper.dom); 10770 parent(wrapper).each(elm => elm.dom.normalize()); 10771 last(wrapper).map(last => { 10772 editor.selection.setCursorLocation(last.dom, getEnd(last)); 10773 }); 10774 } 10775 }; 10776 const detect$1 = elm => closest$3(elm, autocompleteSelector); 10777 const findIn = elm => descendant(elm, autocompleteSelector); 10778 const remove$
vendor: 24,116 bytes, lines 10778-11496
107783 = (editor, elm) => findIn(elm).each(wrapper => { 10779 const bookmark = editor.selection.getBookmark(); 10780 unwrap(wrapper); 10781 editor.selection.moveToBookmark(bookmark); 10782 }); 10783 10784 const typeLookup = { 10785 '#text': 3, 10786 '#comment': 8, 10787 '#cdata': 4, 10788 '#pi': 7, 10789 '#doctype': 10, 10790 '#document-fragment': 11 10791 }; 10792 const walk$2 = (node, root, prev) => { 10793 const startName = prev ? 'lastChild' : 'firstChild'; 10794 const siblingName = prev ? 'prev' : 'next'; 10795 if (node[startName]) { 10796 return node[startName]; 10797 } 10798 if (node !== root) { 10799 let sibling = node[siblingName]; 10800 if (sibling) { 10801 return sibling; 10802 } 10803 for (let parent = node.parent; parent && parent !== root; parent = parent.parent) { 10804 sibling = parent[siblingName]; 10805 if (sibling) { 10806 return sibling; 10807 } 10808 } 10809 } 10810 return undefined; 10811 }; 10812 const isEmptyTextNode = node => { 10813 var _a; 10814 const text = (_a = node.value) !== null && _a !== void 0 ? _a : ''; 10815 if (!isWhitespaceText(text)) { 10816 return false; 10817 } 10818 const parentNode = node.parent; 10819 if (parentNode && (parentNode.name !== 'span' || parentNode.attr('style')) && /^[ ]+$/.test(text)) { 10820 return false; 10821 } 10822 return true; 10823 }; 10824 const isNonEmptyElement = node => { 10825 const isNamedAnchor = node.name === 'a' && !node.attr('href') && node.attr('id'); 10826 return node.attr('name') || node.attr('id') && !node.firstChild || node.attr('data-mce-bookmark') || isNamedAnchor; 10827 }; 10828 class AstNode { 10829 constructor(name, type) { 10830 this.name = name; 10831 this.type = type; 10832 if (type === 1) { 10833 this.attributes = []; 10834 this.attributes.map = {}; 10835 } 10836 } 10837 static create(name, attrs) { 10838 const node = new AstNode(name, typeLookup[name] || 1); 10839 if (attrs) { 10840 each$d(attrs, (value, attrName) => { 10841 node.attr(attrName, value); 10842 }); 10843 } 10844 return node; 10845 } 10846 replace(node) { 10847 const self = this; 10848 if (node.parent) { 10849 node.remove(); 10850 } 10851 self.insert(node, self); 10852 self.remove(); 10853 return self; 10854 } 10855 attr(name, value) { 10856 const self = this; 10857 if (!isString(name)) { 10858 if (isNonNullable(name)) { 10859 each$d(name, (value, key) => { 10860 self.attr(key, value); 10861 }); 10862 } 10863 return self; 10864 } 10865 const attrs = self.attributes; 10866 if (attrs) { 10867 if (value !== undefined) { 10868 if (value === null) { 10869 if (name in attrs.map) { 10870 delete attrs.map[name]; 10871 let i = attrs.length; 10872 while (i--) { 10873 if (attrs[i].name === name) { 10874 attrs.splice(i, 1); 10875 return self; 10876 } 10877 } 10878 } 10879 return self; 10880 } 10881 if (name in attrs.map) { 10882 let i = attrs.length; 10883 while (i--) { 10884 if (attrs[i].name === name) { 10885 attrs[i].value = value; 10886 break; 10887 } 10888 } 10889 } else { 10890 attrs.push({ 10891 name, 10892 value 10893 }); 10894 } 10895 attrs.map[name] = value; 10896 return self; 10897 } 10898 return attrs.map[name]; 10899 } 10900 return undefined; 10901 } 10902 clone() { 10903 const self = this; 10904 const clone = new AstNode(self.name, self.type); 10905 const selfAttrs = self.attributes; 10906 if (selfAttrs) { 10907 const cloneAttrs = []; 10908 cloneAttrs.map = {}; 10909 for (let i = 0, l = selfAttrs.length; i < l; i++) { 10910 const selfAttr = selfAttrs[i]; 10911 if (selfAttr.name !== 'id') { 10912 cloneAttrs[cloneAttrs.length] = { 10913 name: selfAttr.name, 10914 value: selfAttr.value 10915 }; 10916 cloneAttrs.map[selfAttr.name] = selfAttr.value; 10917 } 10918 } 10919 clone.attributes = cloneAttrs; 10920 } 10921 clone.value = self.value; 10922 return clone; 10923 } 10924 wrap(wrapper) { 10925 const self = this; 10926 if (self.parent) { 10927 self.parent.insert(wrapper, self); 10928 wrapper.append(self); 10929 } 10930 return self; 10931 } 10932 unwrap() { 10933 const self = this; 10934 for (let node = self.firstChild; node;) { 10935 const next = node.next; 10936 self.insert(node, self, true); 10937 node = next; 10938 } 10939 self.remove(); 10940 } 10941 remove() { 10942 const self = this, parent = self.parent, next = self.next, prev = self.prev; 10943 if (parent) { 10944 if (parent.firstChild === self) { 10945 parent.firstChild = next; 10946 if (next) { 10947 next.prev = null; 10948 } 10949 } else if (prev) { 10950 prev.next = next; 10951 } 10952 if (parent.lastChild === self) { 10953 parent.lastChild = prev; 10954 if (prev) { 10955 prev.next = null; 10956 } 10957 } else if (next) { 10958 next.prev = prev; 10959 } 10960 self.parent = self.next = self.prev = null; 10961 } 10962 return self; 10963 } 10964 append(node) { 10965 const self = this; 10966 if (node.parent) { 10967 node.remove(); 10968 } 10969 const last = self.lastChild; 10970 if (last) { 10971 last.next = node; 10972 node.prev = last; 10973 self.lastChild = node; 10974 } else { 10975 self.lastChild = self.firstChild = node; 10976 } 10977 node.parent = self; 10978 return node; 10979 } 10980 insert(node, refNode, before) { 10981 if (node.parent) { 10982 node.remove(); 10983 } 10984 const parent = refNode.parent || this; 10985 if (before) { 10986 if (refNode === parent.firstChild) { 10987 parent.firstChild = node; 10988 } else if (refNode.prev) { 10989 refNode.prev.next = node; 10990 } 10991 node.prev = refNode.prev; 10992 node.next = refNode; 10993 refNode.prev = node; 10994 } else { 10995 if (refNode === parent.lastChild) { 10996 parent.lastChild = node; 10997 } else if (refNode.next) { 10998 refNode.next.prev = node; 10999 } 11000 node.next = refNode.next; 11001 node.prev = refNode; 11002 refNode.next = node; 11003 } 11004 node.parent = parent; 11005 return node; 11006 } 11007 getAll(name) { 11008 const self = this; 11009 const collection = []; 11010 for (let node = self.firstChild; node; node = walk$2(node, self)) { 11011 if (node.name === name) { 11012 collection.push(node); 11013 } 11014 } 11015 return collection; 11016 } 11017 children() { 11018 const self = this; 11019 const collection = []; 11020 for (let node = self.firstChild; node; node = node.next) { 11021 collection.push(node); 11022 } 11023 return collection; 11024 } 11025 empty() { 11026 const self = this; 11027 if (self.firstChild) { 11028 const nodes = []; 11029 for (let node = self.firstChild; node; node = walk$2(node, self)) { 11030 nodes.push(node); 11031 } 11032 let i = nodes.length; 11033 while (i--) { 11034 const node = nodes[i]; 11035 node.parent = node.firstChild = node.lastChild = node.next = node.prev = null; 11036 } 11037 } 11038 self.firstChild = self.lastChild = null; 11039 return self; 11040 } 11041 isEmpty(elements, whitespace = {}, predicate) { 11042 var _a; 11043 const self = this; 11044 let node = self.firstChild; 11045 if (isNonEmptyElement(self)) { 11046 return false; 11047 } 11048 if (node) { 11049 do { 11050 if (node.type === 1) { 11051 if (node.attr('data-mce-bogus')) { 11052 continue; 11053 } 11054 if (elements[node.name]) { 11055 return false; 11056 } 11057 if (isNonEmptyElement(node)) { 11058 return false; 11059 } 11060 } 11061 if (node.type === 8) { 11062 return false; 11063 } 11064 if (node.type === 3 && !isEmptyTextNode(node)) { 11065 return false; 11066 } 11067 if (node.type === 3 && node.parent && whitespace[node.parent.name] && isWhitespaceText((_a = node.value) !== null && _a !== void 0 ? _a : '')) { 11068 return false; 11069 } 11070 if (predicate && predicate(node)) { 11071 return false; 11072 } 11073 } while (node = walk$2(node, self)); 11074 } 11075 return true; 11076 } 11077 walk(prev) { 11078 return walk$2(this, null, prev); 11079 } 11080 } 11081 11082 const isConditionalComment = (html, startIndex) => /^\s*\[if [\w\W]+\]>.*<!\[endif\](--!?)?>/.test(html.substr(startIndex)); 11083 const findCommentEndIndex = (html, isBogus, startIndex = 0) => { 11084 const lcHtml = html.toLowerCase(); 11085 if (lcHtml.indexOf('[if ', startIndex) !== -1 && isConditionalComment(lcHtml, startIndex)) { 11086 const endIfIndex = lcHtml.indexOf('[endif]', startIndex); 11087 return lcHtml.indexOf('>', endIfIndex); 11088 } else { 11089 if (isBogus) { 11090 const endIndex = lcHtml.indexOf('>', startIndex); 11091 return endIndex !== -1 ? endIndex : lcHtml.length; 11092 } else { 11093 const endCommentRegexp = /--!?>/g; 11094 endCommentRegexp.lastIndex = startIndex; 11095 const match = endCommentRegexp.exec(html); 11096 return match ? match.index + match[0].length : lcHtml.length; 11097 } 11098 } 11099 }; 11100 const findMatchingEndTagIndex = (schema, html, startIndex) => { 11101 const startTagRegExp = /<([!?\/])?([A-Za-z0-9\-_:.]+)/g; 11102 const endTagRegExp = /(?:\s(?:[^'">]+(?:"[^"]*"|'[^']*'))*[^"'>]*(?:"[^">]*|'[^'>]*)?|\s*|\/)>/g; 11103 const voidElements = schema.getVoidElements(); 11104 let count = 1, index = startIndex; 11105 while (count !== 0) { 11106 startTagRegExp.lastIndex = index; 11107 while (true) { 11108 const startMatch = startTagRegExp.exec(html); 11109 if (startMatch === null) { 11110 return index; 11111 } else if (startMatch[1] === '!') { 11112 if (startsWith(startMatch[2], '--')) { 11113 index = findCommentEndIndex(html, false, startMatch.index + '!--'.length); 11114 } else { 11115 index = findCommentEndIndex(html, true, startMatch.index + 1); 11116 } 11117 break; 11118 } else { 11119 endTagRegExp.lastIndex = startTagRegExp.lastIndex; 11120 const endMatch = endTagRegExp.exec(html); 11121 if (isNull(endMatch) || endMatch.index !== startTagRegExp.lastIndex) { 11122 continue; 11123 } 11124 if (startMatch[1] === '/') { 11125 count -= 1; 11126 } else if (!has$2(voidElements, startMatch[2])) { 11127 count += 1; 11128 } 11129 index = startTagRegExp.lastIndex + endMatch[0].length; 11130 break; 11131 } 11132 } 11133 } 11134 return index; 11135 }; 11136 const trimHtml$1 = (tempAttrs, html) => { 11137 const trimContentRegExp = new RegExp(['\\s?(' + tempAttrs.join('|') + ')="[^"]+"'].join('|'), 'gi'); 11138 return html.replace(trimContentRegExp, ''); 11139 }; 11140 const trimInternal = (serializer, html) => { 11141 const bogusAllRegExp = /<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g; 11142 const schema = serializer.schema; 11143 let content = trimHtml$1(serializer.getTempAttrs(), html); 11144 const voidElements = schema.getVoidElements(); 11145 let matches; 11146 while (matches = bogusAllRegExp.exec(content)) { 11147 const index = bogusAllRegExp.lastIndex; 11148 const matchLength = matches[0].length; 11149 let endTagIndex; 11150 if (voidElements[matches[1]]) { 11151 endTagIndex = index; 11152 } else { 11153 endTagIndex = findMatchingEndTagIndex(schema, content, index); 11154 } 11155 content = content.substring(0, index - matchLength) + content.substring(endTagIndex); 11156 bogusAllRegExp.lastIndex = index - matchLength; 11157 } 11158 return trim$1(content); 11159 }; 11160 const trimExternal = trimInternal; 11161 11162 const cleanupBogusElements = parent => { 11163 const bogusElements = descendants(parent, '[data-mce-bogus]'); 11164 each$e(bogusElements, elem => { 11165 const bogusValue = get$9(elem, 'data-mce-bogus'); 11166 if (bogusValue === 'all') { 11167 remove$6(elem); 11168 } else if (isBr$5(elem)) { 11169 before$3(elem, SugarElement.fromText(zeroWidth)); 11170 remove$6(elem); 11171 } else { 11172 unwrap(elem); 11173 } 11174 }); 11175 }; 11176 const cleanupInputNames = parent => { 11177 const inputs = descendants(parent, 'input'); 11178 each$e(inputs, input => { 11179 remove$b(input, 'name'); 11180 }); 11181 }; 11182 11183 const trimEmptyContents = (editor, html) => { 11184 const blockName = getForcedRootBlock(editor); 11185 const emptyRegExp = new RegExp(`^(<${ blockName }[^>]*>( | |\\s|\u00a0|<br \\/>|)<\\/${ blockName }>[\r\n]*|<br \\/>[\r\n]*)$`); 11186 return html.replace(emptyRegExp, ''); 11187 }; 11188 const getPlainTextContent = (editor, body) => { 11189 const doc = editor.getDoc(); 11190 const dos = getRootNode(SugarElement.fromDom(editor.getBody())); 11191 const offscreenDiv = SugarElement.fromTag('div', doc); 11192 set$3(offscreenDiv, 'data-mce-bogus', 'all'); 11193 setAll(offscreenDiv, { 11194 position: 'fixed', 11195 left: '-9999999px', 11196 top: '0' 11197 }); 11198 set$1(offscreenDiv, body.innerHTML); 11199 cleanupBogusElements(offscreenDiv); 11200 cleanupInputNames(offscreenDiv); 11201 const root = getContentContainer(dos); 11202 append$1(root, offscreenDiv); 11203 const content = trim$1(offscreenDiv.dom.innerText); 11204 remove$6(offscreenDiv); 11205 return content; 11206 }; 11207 const getContentFromBody = (editor, args, body) => { 11208 let content; 11209 if (args.format === 'raw') { 11210 content = Tools.trim(trimExternal(editor.serializer, body.innerHTML)); 11211 } else if (args.format === 'text') { 11212 content = getPlainTextContent(editor, body); 11213 } else if (args.format === 'tree') { 11214 content = editor.serializer.serialize(body, args); 11215 } else { 11216 content = trimEmptyContents(editor, editor.serializer.serialize(body, args)); 11217 } 11218 const shouldTrim = args.format !== 'text' && !isWsPreserveElement(SugarElement.fromDom(body)); 11219 return shouldTrim && isString(content) ? Tools.trim(content) : content; 11220 }; 11221 const getContentInternal = (editor, args) => Optional.from(editor.getBody()).fold(constant(args.format === 'tree' ? new AstNode('body', 11) : ''), body => getContentFromBody(editor, args, body)); 11222 11223 const makeMap$1 = Tools.makeMap; 11224 const Writer = settings => { 11225 const html = []; 11226 settings = settings || {}; 11227 const indent = settings.indent; 11228 const indentBefore = makeMap$1(settings.indent_before || ''); 11229 const indentAfter = makeMap$1(settings.indent_after || ''); 11230 const encode = Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities); 11231 const htmlOutput = settings.element_format !== 'xhtml'; 11232 return { 11233 start: (name, attrs, empty) => { 11234 if (indent && indentBefore[name] && html.length > 0) { 11235 const value = html[html.length - 1]; 11236 if (value.length > 0 && value !== '\n') { 11237 html.push('\n'); 11238 } 11239 } 11240 html.push('<', name); 11241 if (attrs) { 11242 for (let i = 0, l = attrs.length; i < l; i++) { 11243 const attr = attrs[i]; 11244 html.push(' ', attr.name, '="', encode(attr.value, true), '"'); 11245 } 11246 } 11247 if (!empty || htmlOutput) { 11248 html[html.length] = '>'; 11249 } else { 11250 html[html.length] = ' />'; 11251 } 11252 if (empty && indent && indentAfter[name] && html.length > 0) { 11253 const value = html[html.length - 1]; 11254 if (value.length > 0 && value !== '\n') { 11255 html.push('\n'); 11256 } 11257 } 11258 }, 11259 end: name => { 11260 let value; 11261 html.push('</', name, '>'); 11262 if (indent && indentAfter[name] && html.length > 0) { 11263 value = html[html.length - 1]; 11264 if (value.length > 0 && value !== '\n') { 11265 html.push('\n'); 11266 } 11267 } 11268 }, 11269 text: (text, raw) => { 11270 if (text.length > 0) { 11271 html[html.length] = raw ? text : encode(text); 11272 } 11273 }, 11274 cdata: text => { 11275 html.push('<![CDATA[', text, ']]>'); 11276 }, 11277 comment: text => { 11278 html.push('<!--', text, '-->'); 11279 }, 11280 pi: (name, text) => { 11281 if (text) { 11282 html.push('<?', name, ' ', encode(text), '?>'); 11283 } else { 11284 html.push('<?', name, '?>'); 11285 } 11286 if (indent) { 11287 html.push('\n'); 11288 } 11289 }, 11290 doctype: text => { 11291 html.push('<!DOCTYPE', text, '>', indent ? '\n' : ''); 11292 }, 11293 reset: () => { 11294 html.length = 0; 11295 }, 11296 getContent: () => { 11297 return html.join('').replace(/\n$/, ''); 11298 } 11299 }; 11300 }; 11301 11302 const HtmlSerializer = (settings = {}, schema = Schema()) => { 11303 const writer = Writer(settings); 11304 settings.validate = 'validate' in settings ? settings.validate : true; 11305 const serialize = node => { 11306 const validate = settings.validate; 11307 const handlers = { 11308 3: node => { 11309 var _a; 11310 writer.text((_a = node.value) !== null && _a !== void 0 ? _a : '', node.raw); 11311 }, 11312 8: node => { 11313 var _a; 11314 writer.comment((_a = node.value) !== null && _a !== void 0 ? _a : ''); 11315 }, 11316 7: node => { 11317 writer.pi(node.name, node.value); 11318 }, 11319 10: node => { 11320 var _a; 11321 writer.doctype((_a = node.value) !== null && _a !== void 0 ? _a : ''); 11322 }, 11323 4: node => { 11324 var _a; 11325 writer.cdata((_a = node.value) !== null && _a !== void 0 ? _a : ''); 11326 }, 11327 11: node => { 11328 let tempNode = node; 11329 if (tempNode = tempNode.firstChild) { 11330 do { 11331 walk(tempNode); 11332 } while (tempNode = tempNode.next); 11333 } 11334 } 11335 }; 11336 writer.reset(); 11337 const walk = node => { 11338 var _a; 11339 const handler = handlers[node.type]; 11340 if (!handler) { 11341 const name = node.name; 11342 const isEmpty = name in schema.getVoidElements(); 11343 let attrs = node.attributes; 11344 if (validate && attrs && attrs.length > 1) { 11345 const sortedAttrs = []; 11346 sortedAttrs.map = {}; 11347 const elementRule = schema.getElementRule(node.name); 11348 if (elementRule) { 11349 for (let i = 0, l = elementRule.attributesOrder.length; i < l; i++) { 11350 const attrName = elementRule.attributesOrder[i]; 11351 if (attrName in attrs.map) { 11352 const attrValue = attrs.map[attrName]; 11353 sortedAttrs.map[attrName] = attrValue; 11354 sortedAttrs.push({ 11355 name: attrName, 11356 value: attrValue 11357 }); 11358 } 11359 } 11360 for (let i = 0, l = attrs.length; i < l; i++) { 11361 const attrName = attrs[i].name; 11362 if (!(attrName in sortedAttrs.map)) { 11363 const attrValue = attrs.map[attrName]; 11364 sortedAttrs.map[attrName] = attrValue; 11365 sortedAttrs.push({ 11366 name: attrName, 11367 value: attrValue 11368 }); 11369 } 11370 } 11371 attrs = sortedAttrs; 11372 } 11373 } 11374 writer.start(name, attrs, isEmpty); 11375 if (!isEmpty) { 11376 let child = node.firstChild; 11377 if (child) { 11378 if ((name === 'pre' || name === 'textarea') && child.type === 3 && ((_a = child.value) === null || _a === void 0 ? void 0 : _a[0]) === '\n') { 11379 writer.text('\n', true); 11380 } 11381 do { 11382 walk(child); 11383 } while (child = child.next); 11384 } 11385 writer.end(name); 11386 } 11387 } else { 11388 handler(node); 11389 } 11390 }; 11391 if (node.type === 1 && !settings.inner) { 11392 walk(node); 11393 } else if (node.type === 3) { 11394 handlers[3](node); 11395 } else { 11396 handlers[11](node); 11397 } 11398 return writer.getContent(); 11399 }; 11400 return { serialize }; 11401 }; 11402 11403 const nonInheritableStyles = new Set(); 11404 (() => { 11405 const nonInheritableStylesArr = [ 11406 'margin', 11407 'margin-left', 11408 'margin-right', 11409 'margin-top', 11410 'margin-bottom', 11411 'padding', 11412 'padding-left', 11413 'padding-right', 11414 'padding-top', 11415 'padding-bottom', 11416 'border', 11417 'border-width', 11418 'border-style', 11419 'border-color', 11420 'background', 11421 'background-attachment', 11422 'background-clip', 11423 'background-color', 11424 'background-image', 11425 'background-origin', 11426 'background-position', 11427 'background-repeat', 11428 'background-size', 11429 'float', 11430 'position', 11431 'left', 11432 'right', 11433 'top', 11434 'bottom', 11435 'z-index', 11436 'display', 11437 'transform', 11438 'width', 11439 'max-width', 11440 'min-width', 11441 'height', 11442 'max-height', 11443 'min-height', 11444 'overflow', 11445 'overflow-x', 11446 'overflow-y', 11447 'text-overflow', 11448 'vertical-align', 11449 'transition', 11450 'transition-delay', 11451 'transition-duration', 11452 'transition-property', 11453 'transition-timing-function' 11454 ]; 11455 each$e(nonInheritableStylesArr, style => { 11456 nonInheritableStyles.add(style); 11457 }); 11458 })(); 11459 const shorthandStyleProps = [ 11460 'font', 11461 'text-decoration', 11462 'text-emphasis' 11463 ]; 11464 const getStyleProps = (dom, node) => keys(dom.parseStyle(dom.getAttrib(node, 'style'))); 11465 const isNonInheritableStyle = style => nonInheritableStyles.has(style); 11466 const hasInheritableStyles = (dom, node) => forall(getStyleProps(dom, node), style => !isNonInheritableStyle(style)); 11467 const getLonghandStyleProps = styles => filter$5(styles, style => exists(shorthandStyleProps, prop => startsWith(style, prop))); 11468 const hasStyleConflict = (dom, node, parentNode) => { 11469 const nodeStyleProps = getStyleProps(dom, node); 11470 const parentNodeStyleProps = getStyleProps(dom, parentNode); 11471 const valueMismatch = prop => { 11472 var _a, _b; 11473 const nodeValue = (_a = dom.getStyle(node, prop)) !== null && _a !== void 0 ? _a : ''; 11474 const parentValue = (_b = dom.getStyle(parentNode, prop)) !== null && _b !== void 0 ? _b : ''; 11475 return isNotEmpty(nodeValue) && isNotEmpty(parentValue) && nodeValue !== parentValue; 11476 }; 11477 return exists(nodeStyleProps, nodeStyleProp => { 11478 const propExists = props => exists(props, prop => prop === nodeStyleProp); 11479 if (!propExists(parentNodeStyleProps) && propExists(shorthandStyleProps)) { 11480 const longhandProps = getLonghandStyleProps(parentNodeStyleProps); 11481 return exists(longhandProps, valueMismatch); 11482 } else { 11483 return valueMismatch(nodeStyleProp); 11484 } 11485 }); 11486 }; 11487 11488 const isChar = (forward, predicate, pos) => Optional.from(pos.container()).filter(isText$a).exists(text => { 11489 const delta = forward ? 0 : -1; 11490 return predicate(text.data.charAt(pos.offset() + delta)); 11491 }); 11492 const isBeforeSpace = curry(isChar, true, isWhiteSpace); 11493 const isAfterSpace = curry(isChar, false, isWhiteSpace); 11494 const isEmptyText = pos => { 11495 const container = pos.container(); 11496 return isText$a(container) && (container.data.length === 0 || isZwsp
vendor: 11,094 bytes, lines 11496-11721
11496(container.data) && BookmarkManager.isBookmarkNode(container.parentNode)); 11497 }; 11498 const matchesElementPosition = (before, predicate) => pos => getChildNodeAtRelativeOffset(before ? 0 : -1, pos).filter(predicate).isSome(); 11499 const isImageBlock = node => isImg(node) && get$7(SugarElement.fromDom(node), 'display') === 'block'; 11500 const isCefNode = node => isContentEditableFalse$b(node) && !isBogusAll$1(node); 11501 const isBeforeImageBlock = matchesElementPosition(true, isImageBlock); 11502 const isAfterImageBlock = matchesElementPosition(false, isImageBlock); 11503 const isBeforeMedia = matchesElementPosition(true, isMedia$2); 11504 const isAfterMedia = matchesElementPosition(false, isMedia$2); 11505 const isBeforeTable = matchesElementPosition(true, isTable$2); 11506 const isAfterTable = matchesElementPosition(false, isTable$2); 11507 const isBeforeContentEditableFalse = matchesElementPosition(true, isCefNode); 11508 const isAfterContentEditableFalse = matchesElementPosition(false, isCefNode); 11509 11510 const dropLast = xs => xs.slice(0, -1); 11511 const parentsUntil = (start, root, predicate) => { 11512 if (contains(root, start)) { 11513 return dropLast(parents$1(start, elm => { 11514 return predicate(elm) || eq(elm, root); 11515 })); 11516 } else { 11517 return []; 11518 } 11519 }; 11520 const parents = (start, root) => parentsUntil(start, root, never); 11521 const parentsAndSelf = (start, root) => [start].concat(parents(start, root)); 11522 11523 const navigateIgnoreEmptyTextNodes = (forward, root, from) => navigateIgnore(forward, root, from, isEmptyText); 11524 const getClosestBlock$1 = (root, pos) => find$2(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$2); 11525 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())))); 11526 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()); 11527 const isAtStartOfBlock = curry(isAtBlockBoundary, false); 11528 const isAtEndOfBlock = curry(isAtBlockBoundary, true); 11529 const isBeforeBlock = curry(isAtBeforeAfterBlockBoundary, false); 11530 const isAfterBlock = curry(isAtBeforeAfterBlockBoundary, true); 11531 11532 const isBr$1 = pos => getElementFromPosition(pos).exists(isBr$5); 11533 const findBr = (forward, root, pos) => { 11534 const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$2); 11535 const scope = head(parentBlocks).getOr(root); 11536 return fromPosition(forward, scope.dom, pos).filter(isBr$1); 11537 }; 11538 const isBeforeBr$1 = (root, pos) => getElementFromPosition(pos).exists(isBr$5) || findBr(true, root, pos).isSome(); 11539 const isAfterBr = (root, pos) => getElementFromPrevPosition(pos).exists(isBr$5) || findBr(false, root, pos).isSome(); 11540 const findPreviousBr = curry(findBr, false); 11541 const findNextBr = curry(findBr, true); 11542 11543 const isInMiddleOfText = pos => CaretPosition.isTextPosition(pos) && !pos.isAtStart() && !pos.isAtEnd(); 11544 const getClosestBlock = (root, pos) => { 11545 const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$2); 11546 return head(parentBlocks).getOr(root); 11547 }; 11548 const hasSpaceBefore = (root, pos) => { 11549 if (isInMiddleOfText(pos)) { 11550 return isAfterSpace(pos); 11551 } else { 11552 return isAfterSpace(pos) || prevPosition(getClosestBlock(root, pos).dom, pos).exists(isAfterSpace); 11553 } 11554 }; 11555 const hasSpaceAfter = (root, pos) => { 11556 if (isInMiddleOfText(pos)) { 11557 return isBeforeSpace(pos); 11558 } else { 11559 return isBeforeSpace(pos) || nextPosition(getClosestBlock(root, pos).dom, pos).exists(isBeforeSpace); 11560 } 11561 }; 11562 const isPreValue = value => contains$2([ 11563 'pre', 11564 'pre-wrap' 11565 ], value); 11566 const isInPre = pos => getElementFromPosition(pos).bind(elm => closest$4(elm, isElement$7)).exists(elm => isPreValue(get$7(elm, 'white-space'))); 11567 const isAtBeginningOfBody = (root, pos) => prevPosition(root.dom, pos).isNone(); 11568 const isAtEndOfBody = (root, pos) => nextPosition(root.dom, pos).isNone(); 11569 const isAtLineBoundary = (root, pos) => isAtBeginningOfBody(root, pos) || isAtEndOfBody(root, pos) || isAtStartOfBlock(root, pos) || isAtEndOfBlock(root, pos) || isAfterBr(root, pos) || isBeforeBr$1(root, pos); 11570 const isCefBlock = node => isNonNullable(node) && isContentEditableFalse$b(node) && isBlockLike(node); 11571 const isSiblingCefBlock = (root, direction) => container => { 11572 return isCefBlock(new DomTreeWalker(container, root)[direction]()); 11573 }; 11574 const isBeforeCefBlock = (root, pos) => { 11575 const nextPos = nextPosition(root.dom, pos).getOr(pos); 11576 const isNextCefBlock = isSiblingCefBlock(root.dom, 'next'); 11577 return pos.isAtEnd() && (isNextCefBlock(pos.container()) || isNextCefBlock(nextPos.container())); 11578 }; 11579 const isAfterCefBlock = (root, pos) => { 11580 const prevPos = prevPosition(root.dom, pos).getOr(pos); 11581 const isPrevCefBlock = isSiblingCefBlock(root.dom, 'prev'); 11582 return pos.isAtStart() && (isPrevCefBlock(pos.container()) || isPrevCefBlock(prevPos.container())); 11583 }; 11584 const needsToHaveNbsp = (root, pos) => { 11585 if (isInPre(pos)) { 11586 return false; 11587 } else { 11588 return isAtLineBoundary(root, pos) || hasSpaceBefore(root, pos) || hasSpaceAfter(root, pos); 11589 } 11590 }; 11591 const needsToBeNbspLeft = (root, pos) => { 11592 if (isInPre(pos)) { 11593 return false; 11594 } else { 11595 return isAtStartOfBlock(root, pos) || isBeforeBlock(root, pos) || isAfterBr(root, pos) || hasSpaceBefore(root, pos) || isAfterCefBlock(root, pos); 11596 } 11597 }; 11598 const leanRight = pos => { 11599 const container = pos.container(); 11600 const offset = pos.offset(); 11601 if (isText$a(container) && offset < container.data.length) { 11602 return CaretPosition(container, offset + 1); 11603 } else { 11604 return pos; 11605 } 11606 }; 11607 const needsToBeNbspRight = (root, pos) => { 11608 if (isInPre(pos)) { 11609 return false; 11610 } else { 11611 return isAtEndOfBlock(root, pos) || isAfterBlock(root, pos) || isBeforeBr$1(root, pos) || hasSpaceAfter(root, pos) || isBeforeCefBlock(root, pos); 11612 } 11613 }; 11614 const needsToBeNbsp = (root, pos) => needsToBeNbspLeft(root, pos) || needsToBeNbspRight(root, leanRight(pos)); 11615 const isNbspAt = (text, offset) => isNbsp(text.charAt(offset)); 11616 const isWhiteSpaceAt = (text, offset) => isWhiteSpace(text.charAt(offset)); 11617 const hasNbsp = pos => { 11618 const container = pos.container(); 11619 return isText$a(container) && contains$1(container.data, nbsp); 11620 }; 11621 const normalizeNbspMiddle = text => { 11622 const chars = text.split(''); 11623 return map$3(chars, (chr, i) => { 11624 if (isNbsp(chr) && i > 0 && i < chars.length - 1 && isContent(chars[i - 1]) && isContent(chars[i + 1])) { 11625 return ' '; 11626 } else { 11627 return chr; 11628 } 11629 }).join(''); 11630 }; 11631 const normalizeNbspAtStart = (root, node, makeNbsp) => { 11632 const text = node.data; 11633 const firstPos = CaretPosition(node, 0); 11634 if (!makeNbsp && isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos)) { 11635 node.data = ' ' + text.slice(1); 11636 return true; 11637 } else if (makeNbsp && isWhiteSpaceAt(text, 0) && needsToBeNbspLeft(root, firstPos)) { 11638 node.data = nbsp + text.slice(1); 11639 return true; 11640 } else { 11641 return false; 11642 } 11643 }; 11644 const normalizeNbspInMiddleOfTextNode = node => { 11645 const text = node.data; 11646 const newText = normalizeNbspMiddle(text); 11647 if (newText !== text) { 11648 node.data = newText; 11649 return true; 11650 } else { 11651 return false; 11652 } 11653 }; 11654 const normalizeNbspAtEnd = (root, node, makeNbsp) => { 11655 const text = node.data; 11656 const lastPos = CaretPosition(node, text.length - 1); 11657 if (!makeNbsp && isNbspAt(text, text.length - 1) && !needsToBeNbsp(root, lastPos)) { 11658 node.data = text.slice(0, -1) + ' '; 11659 return true; 11660 } else if (makeNbsp && isWhiteSpaceAt(text, text.length - 1) && needsToBeNbspRight(root, lastPos)) { 11661 node.data = text.slice(0, -1) + nbsp; 11662 return true; 11663 } else { 11664 return false; 11665 } 11666 }; 11667 const normalizeNbsps = (root, pos) => { 11668 const container = pos.container(); 11669 if (!isText$a(container)) { 11670 return Optional.none(); 11671 } 11672 if (hasNbsp(pos)) { 11673 const normalized = normalizeNbspAtStart(root, container, false) || normalizeNbspInMiddleOfTextNode(container) || normalizeNbspAtEnd(root, container, false); 11674 return someIf(normalized, pos); 11675 } else if (needsToBeNbsp(root, pos)) { 11676 const normalized = normalizeNbspAtStart(root, container, true) || normalizeNbspAtEnd(root, container, true); 11677 return someIf(normalized, pos); 11678 } else { 11679 return Optional.none(); 11680 } 11681 }; 11682 const normalizeNbspsInEditor = editor => { 11683 const root = SugarElement.fromDom(editor.getBody()); 11684 if (editor.selection.isCollapsed()) { 11685 normalizeNbsps(root, CaretPosition.fromRangeStart(editor.selection.getRng())).each(pos => { 11686 editor.selection.setRng(pos.toRange()); 11687 }); 11688 } 11689 }; 11690 11691 const normalize$1 = (node, offset, count) => { 11692 if (count === 0) { 11693 return; 11694 } 11695 const elm = SugarElement.fromDom(node); 11696 const root = ancestor$4(elm, isBlock$2).getOr(elm); 11697 const whitespace = node.data.slice(offset, offset + count); 11698 const isEndOfContent = offset + count >= node.data.length && needsToBeNbspRight(root, CaretPosition(node, node.data.length)); 11699 const isStartOfContent = offset === 0 && needsToBeNbspLeft(root, CaretPosition(node, 0)); 11700 node.replaceData(offset, count, normalize$4(whitespace, 4, isStartOfContent, isEndOfContent)); 11701 }; 11702 const normalizeWhitespaceAfter = (node, offset) => { 11703 const content = node.data.slice(offset); 11704 const whitespaceCount = content.length - lTrim(content).length; 11705 normalize$1(node, offset, whitespaceCount); 11706 }; 11707 const normalizeWhitespaceBefore = (node, offset) => { 11708 const content = node.data.slice(0, offset); 11709 const whitespaceCount = content.length - rTrim(content).length; 11710 normalize$1(node, offset - whitespaceCount, whitespaceCount); 11711 }; 11712 const mergeTextNodes = (prevNode, nextNode, normalizeWhitespace, mergeToPrev = true) => { 11713 const whitespaceOffset = rTrim(prevNode.data).length; 11714 const newNode = mergeToPrev ? prevNode : nextNode; 11715 const removeNode = mergeToPrev ? nextNode : prevNode; 11716 if (mergeToPrev) { 11717 newNode.appendData(removeNode.data); 11718 } else { 11719 newNode.insertData(0, removeNode.data); 11720 } 11721 remove$
vendor: 2,489 bytes, lines 11721-11757
117216(SugarElement.fromDom(removeNode)); 11722 if (normalizeWhitespace) { 11723 normalizeWhitespaceAfter(newNode, whitespaceOffset); 11724 } 11725 return newNode; 11726 }; 11727 11728 const needsReposition = (pos, elm) => { 11729 const container = pos.container(); 11730 const offset = pos.offset(); 11731 return !CaretPosition.isTextPosition(pos) && container === elm.parentNode && offset > CaretPosition.before(elm).offset(); 11732 }; 11733 const reposition = (elm, pos) => needsReposition(pos, elm) ? CaretPosition(pos.container(), pos.offset() - 1) : pos; 11734 const beforeOrStartOf = node => isText$a(node) ? CaretPosition(node, 0) : CaretPosition.before(node); 11735 const afterOrEndOf = node => isText$a(node) ? CaretPosition(node, node.data.length) : CaretPosition.after(node); 11736 const getPreviousSiblingCaretPosition = elm => { 11737 if (isCaretCandidate$3(elm.previousSibling)) { 11738 return Optional.some(afterOrEndOf(elm.previousSibling)); 11739 } else { 11740 return elm.previousSibling ? lastPositionIn(elm.previousSibling) : Optional.none(); 11741 } 11742 }; 11743 const getNextSiblingCaretPosition = elm => { 11744 if (isCaretCandidate$3(elm.nextSibling)) { 11745 return Optional.some(beforeOrStartOf(elm.nextSibling)); 11746 } else { 11747 return elm.nextSibling ? firstPositionIn(elm.nextSibling) : Optional.none(); 11748 } 11749 }; 11750 const findCaretPositionBackwardsFromElm = (rootElement, elm) => { 11751 return Optional.from(elm.previousSibling ? elm.previousSibling : elm.parentNode).bind(node => prevPosition(rootElement, CaretPosition.before(node))).orThunk(() => nextPosition(rootElement, CaretPosition.after(elm))); 11752 }; 11753 const findCaretPositionForwardsFromElm = (rootElement, elm) => nextPosition(rootElement, CaretPosition.after(elm)).orThunk(() => prevPosition(rootElement, CaretPosition.before(elm))); 11754 const findCaretPositionBackwards = (rootElement, elm) => getPreviousSiblingCaretPosition(elm).orThunk(() => getNextSiblingCaretPosition(elm)).orThunk(() => findCaretPositionBackwardsFromElm(rootElement, elm)); 11755 const findCaretPositionForward = (rootElement, elm) => getNextSiblingCaretPosition(elm).orThunk(() => getPreviousSiblingCaretPosition(elm)).orThunk(() => findCaretPositionForwardsFromElm(rootElement, elm)); 11756 const findCaretPosition = (forward, rootElement, elm) => forward ? findCaretPositionForward(rootElement, elm) : findCaretPositionBackwards(rootElement, elm); 11757 const findCaretPosOutsideElmAfterDelete = (forward, rootElement, elm) =>
vendor: 6,336 bytes, lines 11757-11891
11757 findCaretPosition(forward, rootElement, elm).map(curry(reposition, elm)); 11758 const setSelection$1 = (editor, forward, pos) => { 11759 pos.fold(() => { 11760 editor.focus(); 11761 }, pos => { 11762 editor.selection.setRng(pos.toRange(), forward); 11763 }); 11764 }; 11765 const eqRawNode = rawNode => elm => elm.dom === rawNode; 11766 const isBlock = (editor, elm) => elm && has$2(editor.schema.getBlockElements(), name(elm)); 11767 const paddEmptyBlock = elm => { 11768 if (isEmpty$2(elm)) { 11769 const br = SugarElement.fromHtml('<br data-mce-bogus="1">'); 11770 empty(elm); 11771 append$1(elm, br); 11772 return Optional.some(CaretPosition.before(br.dom)); 11773 } else { 11774 return Optional.none(); 11775 } 11776 }; 11777 const deleteNormalized = (elm, afterDeletePosOpt, normalizeWhitespace) => { 11778 const prevTextOpt = prevSibling(elm).filter(isText$b); 11779 const nextTextOpt = nextSibling(elm).filter(isText$b); 11780 remove$6(elm); 11781 return lift3(prevTextOpt, nextTextOpt, afterDeletePosOpt, (prev, next, pos) => { 11782 const prevNode = prev.dom, nextNode = next.dom; 11783 const offset = prevNode.data.length; 11784 mergeTextNodes(prevNode, nextNode, normalizeWhitespace); 11785 return pos.container() === nextNode ? CaretPosition(prevNode, offset) : pos; 11786 }).orThunk(() => { 11787 if (normalizeWhitespace) { 11788 prevTextOpt.each(elm => normalizeWhitespaceBefore(elm.dom, elm.dom.length)); 11789 nextTextOpt.each(elm => normalizeWhitespaceAfter(elm.dom, 0)); 11790 } 11791 return afterDeletePosOpt; 11792 }); 11793 }; 11794 const isInlineElement = (editor, element) => has$2(editor.schema.getTextInlineElements(), name(element)); 11795 const deleteElement$2 = (editor, forward, elm, moveCaret = true) => { 11796 const afterDeletePos = findCaretPosOutsideElmAfterDelete(forward, editor.getBody(), elm.dom); 11797 const parentBlock = ancestor$4(elm, curry(isBlock, editor), eqRawNode(editor.getBody())); 11798 const normalizedAfterDeletePos = deleteNormalized(elm, afterDeletePos, isInlineElement(editor, elm)); 11799 if (editor.dom.isEmpty(editor.getBody())) { 11800 editor.setContent(''); 11801 editor.selection.setCursorLocation(); 11802 } else { 11803 parentBlock.bind(paddEmptyBlock).fold(() => { 11804 if (moveCaret) { 11805 setSelection$1(editor, forward, normalizedAfterDeletePos); 11806 } 11807 }, paddPos => { 11808 if (moveCaret) { 11809 setSelection$1(editor, forward, Optional.some(paddPos)); 11810 } 11811 }); 11812 } 11813 }; 11814 11815 const strongRtl = /[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/; 11816 const hasStrongRtl = text => strongRtl.test(text); 11817 11818 const isInlineTarget = (editor, elm) => is$1(SugarElement.fromDom(elm), getInlineBoundarySelector(editor)) && !isTransparentBlock(editor.schema, elm) && editor.dom.isEditable(elm); 11819 const isRtl = element => { 11820 var _a; 11821 return DOMUtils.DOM.getStyle(element, 'direction', true) === 'rtl' || hasStrongRtl((_a = element.textContent) !== null && _a !== void 0 ? _a : ''); 11822 }; 11823 const findInlineParents = (isInlineTarget, rootNode, pos) => filter$5(DOMUtils.DOM.getParents(pos.container(), '*', rootNode), isInlineTarget); 11824 const findRootInline = (isInlineTarget, rootNode, pos) => { 11825 const parents = findInlineParents(isInlineTarget, rootNode, pos); 11826 return Optional.from(parents[parents.length - 1]); 11827 }; 11828 const hasSameParentBlock = (rootNode, node1, node2) => { 11829 const block1 = getParentBlock$3(node1, rootNode); 11830 const block2 = getParentBlock$3(node2, rootNode); 11831 return isNonNullable(block1) && block1 === block2; 11832 }; 11833 const isAtZwsp = pos => isBeforeInline(pos) || isAfterInline(pos); 11834 const normalizePosition = (forward, pos) => { 11835 const container = pos.container(), offset = pos.offset(); 11836 if (forward) { 11837 if (isCaretContainerInline(container)) { 11838 if (isText$a(container.nextSibling)) { 11839 return CaretPosition(container.nextSibling, 0); 11840 } else { 11841 return CaretPosition.after(container); 11842 } 11843 } else { 11844 return isBeforeInline(pos) ? CaretPosition(container, offset + 1) : pos; 11845 } 11846 } else { 11847 if (isCaretContainerInline(container)) { 11848 if (isText$a(container.previousSibling)) { 11849 return CaretPosition(container.previousSibling, container.previousSibling.data.length); 11850 } else { 11851 return CaretPosition.before(container); 11852 } 11853 } else { 11854 return isAfterInline(pos) ? CaretPosition(container, offset - 1) : pos; 11855 } 11856 } 11857 }; 11858 const normalizeForwards = curry(normalizePosition, true); 11859 const normalizeBackwards = curry(normalizePosition, false); 11860 11861 const execCommandIgnoreInputEvents = (editor, command) => { 11862 const inputBlocker = e => e.stopImmediatePropagation(); 11863 editor.on('beforeinput input', inputBlocker, true); 11864 editor.getDoc().execCommand(command); 11865 editor.off('beforeinput input', inputBlocker); 11866 }; 11867 const execEditorDeleteCommand = editor => { 11868 editor.execCommand('delete'); 11869 }; 11870 const execNativeDeleteCommand = editor => execCommandIgnoreInputEvents(editor, 'Delete'); 11871 const execNativeForwardDeleteCommand = editor => execCommandIgnoreInputEvents(editor, 'ForwardDelete'); 11872 const isBeforeRoot = rootNode => elm => is$2(parent(elm), rootNode, eq); 11873 const isTextBlockOrListItem = element => isTextBlock$2(element) || isListItem$1(element); 11874 const getParentBlock$2 = (rootNode, elm) => { 11875 if (contains(rootNode, elm)) { 11876 return closest$4(elm, isTextBlockOrListItem, isBeforeRoot(rootNode)); 11877 } else { 11878 return Optional.none(); 11879 } 11880 }; 11881 const paddEmptyBody = (editor, moveSelection = true) => { 11882 if (editor.dom.isEmpty(editor.getBody())) { 11883 editor.setContent('', { no_selection: !moveSelection }); 11884 } 11885 }; 11886 const willDeleteLastPositionInElement = (forward, fromPos, elm) => lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => { 11887 const normalizedFirstPos = normalizePosition(true, firstPos); 11888 const normalizedLastPos = normalizePosition(false, lastPos); 11889 const normalizedFromPos = normalizePosition(false, fromPos); 11890 if (forward) { 11891 return nextPosition(elm, normalizedFromPos).exists(nextPos
vendor: 1,381 bytes, lines 11891-11917
11891=> nextPos.isEqual(normalizedLastPos) && fromPos.isEqual(normalizedFirstPos)); 11892 } else { 11893 return prevPosition(elm, normalizedFromPos).exists(prevPos => prevPos.isEqual(normalizedFirstPos) && fromPos.isEqual(normalizedLastPos)); 11894 } 11895 }).getOr(true); 11896 const freefallRtl = root => { 11897 const child = isComment$1(root) ? prevSibling(root) : lastChild(root); 11898 return child.bind(freefallRtl).orThunk(() => Optional.some(root)); 11899 }; 11900 const deleteRangeContents = (editor, rng, root, moveSelection = true) => { 11901 var _a; 11902 rng.deleteContents(); 11903 const lastNode = freefallRtl(root).getOr(root); 11904 const lastBlock = SugarElement.fromDom((_a = editor.dom.getParent(lastNode.dom, editor.dom.isBlock)) !== null && _a !== void 0 ? _a : root.dom); 11905 if (lastBlock.dom === editor.getBody()) { 11906 paddEmptyBody(editor, moveSelection); 11907 } else if (isEmpty$2(lastBlock)) { 11908 fillWithPaddingBr(lastBlock); 11909 if (moveSelection) { 11910 editor.selection.setCursorLocation(lastBlock.dom, 0); 11911 } 11912 } 11913 if (!eq(root, lastBlock)) { 11914 const additionalCleanupNodes = is$2(parent(lastBlock), root) ? [] : siblings(lastBlock); 11915 each$e(additionalCleanupNodes.concat(children$1(root)), node => { 11916 if (!eq(node, lastBlock) && !contains(node, lastBlock) && isEmpty$2(node)) { 11917 remove$6
vendor: 6,955 bytes, lines 11917-12062
11917(node); 11918 } 11919 }); 11920 } 11921 }; 11922 11923 const isRootFromElement = root => cur => eq(root, cur); 11924 const getTableCells = table => descendants(table, 'td,th'); 11925 const getTableDetailsFromRange = (rng, isRoot) => { 11926 const getTable = node => getClosestTable(SugarElement.fromDom(node), isRoot); 11927 const startTable = getTable(rng.startContainer); 11928 const endTable = getTable(rng.endContainer); 11929 const isStartInTable = startTable.isSome(); 11930 const isEndInTable = endTable.isSome(); 11931 const isSameTable = lift2(startTable, endTable, eq).getOr(false); 11932 const isMultiTable = !isSameTable && isStartInTable && isEndInTable; 11933 return { 11934 startTable, 11935 endTable, 11936 isStartInTable, 11937 isEndInTable, 11938 isSameTable, 11939 isMultiTable 11940 }; 11941 }; 11942 11943 const tableCellRng = (start, end) => ({ 11944 start, 11945 end 11946 }); 11947 const tableSelection = (rng, table, cells) => ({ 11948 rng, 11949 table, 11950 cells 11951 }); 11952 const deleteAction = Adt.generate([ 11953 { 11954 singleCellTable: [ 11955 'rng', 11956 'cell' 11957 ] 11958 }, 11959 { fullTable: ['table'] }, 11960 { 11961 partialTable: [ 11962 'cells', 11963 'outsideDetails' 11964 ] 11965 }, 11966 { 11967 multiTable: [ 11968 'startTableCells', 11969 'endTableCells', 11970 'betweenRng' 11971 ] 11972 } 11973 ]); 11974 const getClosestCell$1 = (container, isRoot) => closest$3(SugarElement.fromDom(container), 'td,th', isRoot); 11975 const isExpandedCellRng = cellRng => !eq(cellRng.start, cellRng.end); 11976 const getTableFromCellRng = (cellRng, isRoot) => getClosestTable(cellRng.start, isRoot).bind(startParentTable => getClosestTable(cellRng.end, isRoot).bind(endParentTable => someIf(eq(startParentTable, endParentTable), startParentTable))); 11977 const isSingleCellTable = (cellRng, isRoot) => !isExpandedCellRng(cellRng) && getTableFromCellRng(cellRng, isRoot).exists(table => { 11978 const rows = table.dom.rows; 11979 return rows.length === 1 && rows[0].cells.length === 1; 11980 }); 11981 const getCellRng = (rng, isRoot) => { 11982 const startCell = getClosestCell$1(rng.startContainer, isRoot); 11983 const endCell = getClosestCell$1(rng.endContainer, isRoot); 11984 return lift2(startCell, endCell, tableCellRng); 11985 }; 11986 const getCellRangeFromStartTable = isRoot => startCell => getClosestTable(startCell, isRoot).bind(table => last$3(getTableCells(table)).map(endCell => tableCellRng(startCell, endCell))); 11987 const getCellRangeFromEndTable = isRoot => endCell => getClosestTable(endCell, isRoot).bind(table => head(getTableCells(table)).map(startCell => tableCellRng(startCell, endCell))); 11988 const getTableSelectionFromCellRng = isRoot => cellRng => getTableFromCellRng(cellRng, isRoot).map(table => tableSelection(cellRng, table, getTableCells(table))); 11989 const getTableSelections = (cellRng, selectionDetails, rng, isRoot) => { 11990 if (rng.collapsed || !cellRng.forall(isExpandedCellRng)) { 11991 return Optional.none(); 11992 } else if (selectionDetails.isSameTable) { 11993 const sameTableSelection = cellRng.bind(getTableSelectionFromCellRng(isRoot)); 11994 return Optional.some({ 11995 start: sameTableSelection, 11996 end: sameTableSelection 11997 }); 11998 } else { 11999 const startCell = getClosestCell$1(rng.startContainer, isRoot); 12000 const endCell = getClosestCell$1(rng.endContainer, isRoot); 12001 const startTableSelection = startCell.bind(getCellRangeFromStartTable(isRoot)).bind(getTableSelectionFromCellRng(isRoot)); 12002 const endTableSelection = endCell.bind(getCellRangeFromEndTable(isRoot)).bind(getTableSelectionFromCellRng(isRoot)); 12003 return Optional.some({ 12004 start: startTableSelection, 12005 end: endTableSelection 12006 }); 12007 } 12008 }; 12009 const getCellIndex = (cells, cell) => findIndex$2(cells, x => eq(x, cell)); 12010 const getSelectedCells = tableSelection => lift2(getCellIndex(tableSelection.cells, tableSelection.rng.start), getCellIndex(tableSelection.cells, tableSelection.rng.end), (startIndex, endIndex) => tableSelection.cells.slice(startIndex, endIndex + 1)); 12011 const isSingleCellTableContentSelected = (optCellRng, rng, isRoot) => optCellRng.exists(cellRng => isSingleCellTable(cellRng, isRoot) && hasAllContentsSelected(cellRng.start, rng)); 12012 const unselectCells = (rng, selectionDetails) => { 12013 const {startTable, endTable} = selectionDetails; 12014 const otherContentRng = rng.cloneRange(); 12015 startTable.each(table => otherContentRng.setStartAfter(table.dom)); 12016 endTable.each(table => otherContentRng.setEndBefore(table.dom)); 12017 return otherContentRng; 12018 }; 12019 const handleSingleTable = (cellRng, selectionDetails, rng, isRoot) => getTableSelections(cellRng, selectionDetails, rng, isRoot).bind(({start, end}) => start.or(end)).bind(tableSelection => { 12020 const {isSameTable} = selectionDetails; 12021 const selectedCells = getSelectedCells(tableSelection).getOr([]); 12022 if (isSameTable && tableSelection.cells.length === selectedCells.length) { 12023 return Optional.some(deleteAction.fullTable(tableSelection.table)); 12024 } else if (selectedCells.length > 0) { 12025 if (isSameTable) { 12026 return Optional.some(deleteAction.partialTable(selectedCells, Optional.none())); 12027 } else { 12028 const otherContentRng = unselectCells(rng, selectionDetails); 12029 return Optional.some(deleteAction.partialTable(selectedCells, Optional.some({ 12030 ...selectionDetails, 12031 rng: otherContentRng 12032 }))); 12033 } 12034 } else { 12035 return Optional.none(); 12036 } 12037 }); 12038 const handleMultiTable = (cellRng, selectionDetails, rng, isRoot) => getTableSelections(cellRng, selectionDetails, rng, isRoot).bind(({start, end}) => { 12039 const startTableSelectedCells = start.bind(getSelectedCells).getOr([]); 12040 const endTableSelectedCells = end.bind(getSelectedCells).getOr([]); 12041 if (startTableSelectedCells.length > 0 && endTableSelectedCells.length > 0) { 12042 const otherContentRng = unselectCells(rng, selectionDetails); 12043 return Optional.some(deleteAction.multiTable(startTableSelectedCells, endTableSelectedCells, otherContentRng)); 12044 } else { 12045 return Optional.none(); 12046 } 12047 }); 12048 const getActionFromRange = (root, rng) => { 12049 const isRoot = isRootFromElement(root); 12050 const optCellRng = getCellRng(rng, isRoot); 12051 const selectionDetails = getTableDetailsFromRange(rng, isRoot); 12052 if (isSingleCellTableContentSelected(optCellRng, rng, isRoot)) { 12053 return optCellRng.map(cellRng => deleteAction.singleCellTable(rng, cellRng.start)); 12054 } else if (selectionDetails.isMultiTable) { 12055 return handleMultiTable(optCellRng, selectionDetails, rng, isRoot); 12056 } else { 12057 return handleSingleTable(optCellRng, selectionDetails, rng, isRoot); 12058 } 12059 }; 12060 12061 const cleanCells = cells => each$e(cells, cell => { 12062 remove$
12062b(cell, 'contenteditable'); 12063 fillWithPaddingBr(cell); 12064 }); 12065 const getOutsideBlock = (editor, container) => Optional.from(editor.dom.getParent(container, editor.dom.isBlock)).map(SugarElement.fromDom); 12066 const handleEmptyBlock = (editor, startInTable, emptyBlock) => { 12067 emptyBlock.each(block => { 12068 if (startInTable) { 12069 remove$6
vendor: 19,607 bytes, lines 12069-12509
12069(block); 12070 } else { 12071 fillWithPaddingBr(block); 12072 editor.selection.setCursorLocation(block.dom, 0); 12073 } 12074 }); 12075 }; 12076 const deleteContentInsideCell = (editor, cell, rng, isFirstCellInSelection) => { 12077 const insideTableRng = rng.cloneRange(); 12078 if (isFirstCellInSelection) { 12079 insideTableRng.setStart(rng.startContainer, rng.startOffset); 12080 insideTableRng.setEndAfter(cell.dom.lastChild); 12081 } else { 12082 insideTableRng.setStartBefore(cell.dom.firstChild); 12083 insideTableRng.setEnd(rng.endContainer, rng.endOffset); 12084 } 12085 deleteCellContents(editor, insideTableRng, cell, false).each(action => action()); 12086 }; 12087 const collapseAndRestoreCellSelection = editor => { 12088 const selectedCells = getCellsFromEditor(editor); 12089 const selectedNode = SugarElement.fromDom(editor.selection.getNode()); 12090 if (isTableCell$3(selectedNode.dom) && isEmpty$2(selectedNode)) { 12091 editor.selection.setCursorLocation(selectedNode.dom, 0); 12092 } else { 12093 editor.selection.collapse(true); 12094 } 12095 if (selectedCells.length > 1 && exists(selectedCells, cell => eq(cell, selectedNode))) { 12096 set$3(selectedNode, 'data-mce-selected', '1'); 12097 } 12098 }; 12099 const emptySingleTableCells = (editor, cells, outsideDetails) => Optional.some(() => { 12100 const editorRng = editor.selection.getRng(); 12101 const cellsToClean = outsideDetails.bind(({rng, isStartInTable}) => { 12102 const outsideBlock = getOutsideBlock(editor, isStartInTable ? rng.endContainer : rng.startContainer); 12103 rng.deleteContents(); 12104 handleEmptyBlock(editor, isStartInTable, outsideBlock.filter(isEmpty$2)); 12105 const endPointCell = isStartInTable ? cells[0] : cells[cells.length - 1]; 12106 deleteContentInsideCell(editor, endPointCell, editorRng, isStartInTable); 12107 if (!isEmpty$2(endPointCell)) { 12108 return Optional.some(isStartInTable ? cells.slice(1) : cells.slice(0, -1)); 12109 } else { 12110 return Optional.none(); 12111 } 12112 }).getOr(cells); 12113 cleanCells(cellsToClean); 12114 collapseAndRestoreCellSelection(editor); 12115 }); 12116 const emptyMultiTableCells = (editor, startTableCells, endTableCells, betweenRng) => Optional.some(() => { 12117 const rng = editor.selection.getRng(); 12118 const startCell = startTableCells[0]; 12119 const endCell = endTableCells[endTableCells.length - 1]; 12120 deleteContentInsideCell(editor, startCell, rng, true); 12121 deleteContentInsideCell(editor, endCell, rng, false); 12122 const startTableCellsToClean = isEmpty$2(startCell) ? startTableCells : startTableCells.slice(1); 12123 const endTableCellsToClean = isEmpty$2(endCell) ? endTableCells : endTableCells.slice(0, -1); 12124 cleanCells(startTableCellsToClean.concat(endTableCellsToClean)); 12125 betweenRng.deleteContents(); 12126 collapseAndRestoreCellSelection(editor); 12127 }); 12128 const deleteCellContents = (editor, rng, cell, moveSelection = true) => Optional.some(() => { 12129 deleteRangeContents(editor, rng, cell, moveSelection); 12130 }); 12131 const deleteTableElement = (editor, table) => Optional.some(() => deleteElement$2(editor, false, table)); 12132 const deleteCellRange = (editor, rootElm, rng) => getActionFromRange(rootElm, rng).bind(action => action.fold(curry(deleteCellContents, editor), curry(deleteTableElement, editor), curry(emptySingleTableCells, editor), curry(emptyMultiTableCells, editor))); 12133 const deleteCaptionRange = (editor, caption) => emptyElement(editor, caption); 12134 const deleteTableRange = (editor, rootElm, rng, startElm) => getParentCaption(rootElm, startElm).fold(() => deleteCellRange(editor, rootElm, rng), caption => deleteCaptionRange(editor, caption)); 12135 const deleteRange$3 = (editor, startElm, selectedCells) => { 12136 const rootNode = SugarElement.fromDom(editor.getBody()); 12137 const rng = editor.selection.getRng(); 12138 return selectedCells.length !== 0 ? emptySingleTableCells(editor, selectedCells, Optional.none()) : deleteTableRange(editor, rootNode, rng, startElm); 12139 }; 12140 const getParentCell = (rootElm, elm) => find$2(parentsAndSelf(elm, rootElm), isTableCell$2); 12141 const getParentCaption = (rootElm, elm) => find$2(parentsAndSelf(elm, rootElm), isTag('caption')); 12142 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))); 12143 const emptyElement = (editor, elm) => Optional.some(() => { 12144 fillWithPaddingBr(elm); 12145 editor.selection.setCursorLocation(elm.dom, 0); 12146 }); 12147 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); 12148 const emptyCaretCaption = (editor, elm) => emptyElement(editor, elm); 12149 const validateCaretCaption = (rootElm, fromCaption, to) => getParentCaption(rootElm, SugarElement.fromDom(to.getNode())).fold(() => Optional.some(noop), toCaption => someIf(!eq(toCaption, fromCaption), noop)); 12150 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)); 12151 const deleteCaretCells = (editor, forward, rootElm, startElm) => { 12152 const from = CaretPosition.fromRangeStart(editor.selection.getRng()); 12153 return getParentCell(rootElm, startElm).bind(fromCell => isEmpty$2(fromCell) ? emptyElement(editor, fromCell) : deleteBetweenCells(editor, rootElm, forward, fromCell, from)); 12154 }; 12155 const deleteCaretCaption = (editor, forward, rootElm, fromCaption) => { 12156 const from = CaretPosition.fromRangeStart(editor.selection.getRng()); 12157 return isEmpty$2(fromCaption) ? emptyElement(editor, fromCaption) : deleteCaretInsideCaption(editor, rootElm, forward, fromCaption, from); 12158 }; 12159 const isNearTable = (forward, pos) => forward ? isBeforeTable(pos) : isAfterTable(pos); 12160 const isBeforeOrAfterTable = (editor, forward) => { 12161 const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng()); 12162 return isNearTable(forward, fromPos) || fromPosition(forward, editor.getBody(), fromPos).exists(pos => isNearTable(forward, pos)); 12163 }; 12164 const deleteCaret$3 = (editor, forward, startElm) => { 12165 const rootElm = SugarElement.fromDom(editor.getBody()); 12166 return getParentCaption(rootElm, startElm).fold(() => deleteCaretCells(editor, forward, rootElm, startElm).orThunk(() => someIf(isBeforeOrAfterTable(editor, forward), noop)), fromCaption => deleteCaretCaption(editor, forward, rootElm, fromCaption)); 12167 }; 12168 const backspaceDelete$9 = (editor, forward) => { 12169 const startElm = SugarElement.fromDom(editor.selection.getStart(true)); 12170 const cells = getCellsFromEditor(editor); 12171 return editor.selection.isCollapsed() && cells.length === 0 ? deleteCaret$3(editor, forward, startElm) : deleteRange$3(editor, startElm, cells); 12172 }; 12173 12174 const getContentEditableRoot$1 = (root, node) => { 12175 let tempNode = node; 12176 while (tempNode && tempNode !== root) { 12177 if (isContentEditableTrue$3(tempNode) || isContentEditableFalse$b(tempNode)) { 12178 return tempNode; 12179 } 12180 tempNode = tempNode.parentNode; 12181 } 12182 return null; 12183 }; 12184 12185 const internalAttributesPrefixes = [ 12186 'data-ephox-', 12187 'data-mce-', 12188 'data-alloy-', 12189 'data-snooker-', 12190 '_' 12191 ]; 12192 const each$9 = Tools.each; 12193 const ElementUtils = editor => { 12194 const dom = editor.dom; 12195 const internalAttributes = new Set(editor.serializer.getTempAttrs()); 12196 const compare = (node1, node2) => { 12197 if (node1.nodeName !== node2.nodeName || node1.nodeType !== node2.nodeType) { 12198 return false; 12199 } 12200 const getAttribs = node => { 12201 const attribs = {}; 12202 each$9(dom.getAttribs(node), attr => { 12203 const name = attr.nodeName.toLowerCase(); 12204 if (name !== 'style' && !isAttributeInternal(name)) { 12205 attribs[name] = dom.getAttrib(node, name); 12206 } 12207 }); 12208 return attribs; 12209 }; 12210 const compareObjects = (obj1, obj2) => { 12211 for (const name in obj1) { 12212 if (has$2(obj1, name)) { 12213 const value = obj2[name]; 12214 if (isUndefined(value)) { 12215 return false; 12216 } 12217 if (obj1[name] !== value) { 12218 return false; 12219 } 12220 delete obj2[name]; 12221 } 12222 } 12223 for (const name in obj2) { 12224 if (has$2(obj2, name)) { 12225 return false; 12226 } 12227 } 12228 return true; 12229 }; 12230 if (isElement$6(node1) && isElement$6(node2)) { 12231 if (!compareObjects(getAttribs(node1), getAttribs(node2))) { 12232 return false; 12233 } 12234 if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) { 12235 return false; 12236 } 12237 } 12238 return !isBookmarkNode$1(node1) && !isBookmarkNode$1(node2); 12239 }; 12240 const isAttributeInternal = attributeName => exists(internalAttributesPrefixes, value => startsWith(attributeName, value)) || internalAttributes.has(attributeName); 12241 return { 12242 compare, 12243 isAttributeInternal 12244 }; 12245 }; 12246 12247 const traverse = (root, fn) => { 12248 let node = root; 12249 while (node = node.walk()) { 12250 fn(node); 12251 } 12252 }; 12253 const matchNode$1 = (nodeFilters, attributeFilters, node, matches) => { 12254 const name = node.name; 12255 for (let ni = 0, nl = nodeFilters.length; ni < nl; ni++) { 12256 const filter = nodeFilters[ni]; 12257 if (filter.name === name) { 12258 const match = matches.nodes[name]; 12259 if (match) { 12260 match.nodes.push(node); 12261 } else { 12262 matches.nodes[name] = { 12263 filter, 12264 nodes: [node] 12265 }; 12266 } 12267 } 12268 } 12269 if (node.attributes) { 12270 for (let ai = 0, al = attributeFilters.length; ai < al; ai++) { 12271 const filter = attributeFilters[ai]; 12272 const attrName = filter.name; 12273 if (attrName in node.attributes.map) { 12274 const match = matches.attributes[attrName]; 12275 if (match) { 12276 match.nodes.push(node); 12277 } else { 12278 matches.attributes[attrName] = { 12279 filter, 12280 nodes: [node] 12281 }; 12282 } 12283 } 12284 } 12285 } 12286 }; 12287 const findMatchingNodes = (nodeFilters, attributeFilters, node) => { 12288 const matches = { 12289 nodes: {}, 12290 attributes: {} 12291 }; 12292 if (node.firstChild) { 12293 traverse(node, childNode => { 12294 matchNode$1(nodeFilters, attributeFilters, childNode, matches); 12295 }); 12296 } 12297 return matches; 12298 }; 12299 const runFilters = (matches, args) => { 12300 const run = (matchRecord, filteringAttributes) => { 12301 each$d(matchRecord, match => { 12302 const nodes = from(match.nodes); 12303 each$e(match.filter.callbacks, callback => { 12304 for (let i = nodes.length - 1; i >= 0; i--) { 12305 const node = nodes[i]; 12306 const valueMatches = filteringAttributes ? node.attr(match.filter.name) !== undefined : node.name === match.filter.name; 12307 if (!valueMatches || isNullable(node.parent)) { 12308 nodes.splice(i, 1); 12309 } 12310 } 12311 if (nodes.length > 0) { 12312 callback(nodes, match.filter.name, args); 12313 } 12314 }); 12315 }); 12316 }; 12317 run(matches.nodes, false); 12318 run(matches.attributes, true); 12319 }; 12320 const filter$2 = (nodeFilters, attributeFilters, node, args = {}) => { 12321 const matches = findMatchingNodes(nodeFilters, attributeFilters, node); 12322 runFilters(matches, args); 12323 }; 12324 12325 const paddEmptyNode = (args, isBlock, node) => { 12326 if (args.insert && isBlock(node)) { 12327 const astNode = new AstNode('br', 1); 12328 astNode.attr('data-mce-bogus', '1'); 12329 node.empty().append(astNode); 12330 } else { 12331 node.empty().append(new AstNode('#text', 3)).value = nbsp; 12332 } 12333 }; 12334 const isPaddedWithNbsp = node => { 12335 var _a; 12336 return hasOnlyChild(node, '#text') && ((_a = node === null || node === void 0 ? void 0 : node.firstChild) === null || _a === void 0 ? void 0 : _a.value) === nbsp; 12337 }; 12338 const hasOnlyChild = (node, name) => { 12339 const firstChild = node === null || node === void 0 ? void 0 : node.firstChild; 12340 return isNonNullable(firstChild) && firstChild === node.lastChild && firstChild.name === name; 12341 }; 12342 const isPadded = (schema, node) => { 12343 const rule = schema.getElementRule(node.name); 12344 return (rule === null || rule === void 0 ? void 0 : rule.paddEmpty) === true; 12345 }; 12346 const isEmpty = (schema, nonEmptyElements, whitespaceElements, node) => node.isEmpty(nonEmptyElements, whitespaceElements, node => isPadded(schema, node)); 12347 const isLineBreakNode = (node, isBlock) => isNonNullable(node) && (isBlock(node) || node.name === 'br'); 12348 const findClosestEditingHost = scope => { 12349 let editableNode; 12350 for (let node = scope; node; node = node.parent) { 12351 const contentEditable = node.attr('contenteditable'); 12352 if (contentEditable === 'false') { 12353 break; 12354 } else if (contentEditable === 'true') { 12355 editableNode = node; 12356 } 12357 } 12358 return Optional.from(editableNode); 12359 }; 12360 12361 const removeOrUnwrapInvalidNode = (node, schema, originalNodeParent = node.parent) => { 12362 if (schema.getSpecialElements()[node.name]) { 12363 node.empty().remove(); 12364 } else { 12365 const children = node.children(); 12366 for (const childNode of children) { 12367 if (originalNodeParent && !schema.isValidChild(originalNodeParent.name, childNode.name)) { 12368 removeOrUnwrapInvalidNode(childNode, schema, originalNodeParent); 12369 } 12370 } 12371 node.unwrap(); 12372 } 12373 }; 12374 const cleanInvalidNodes = (nodes, schema, rootNode, onCreate = noop) => { 12375 const textBlockElements = schema.getTextBlockElements(); 12376 const nonEmptyElements = schema.getNonEmptyElements(); 12377 const whitespaceElements = schema.getWhitespaceElements(); 12378 const nonSplittableElements = Tools.makeMap('tr,td,th,tbody,thead,tfoot,table'); 12379 const fixed = new Set(); 12380 const isSplittableElement = node => node !== rootNode && !nonSplittableElements[node.name]; 12381 for (let ni = 0; ni < nodes.length; ni++) { 12382 const node = nodes[ni]; 12383 let parent; 12384 let newParent; 12385 let tempNode; 12386 if (!node.parent || fixed.has(node)) { 12387 continue; 12388 } 12389 if (textBlockElements[node.name] && node.parent.name === 'li') { 12390 let sibling = node.next; 12391 while (sibling) { 12392 if (textBlockElements[sibling.name]) { 12393 sibling.name = 'li'; 12394 fixed.add(sibling); 12395 node.parent.insert(sibling, node.parent); 12396 } else { 12397 break; 12398 } 12399 sibling = sibling.next; 12400 } 12401 node.unwrap(); 12402 continue; 12403 } 12404 const parents = [node]; 12405 for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && isSplittableElement(parent); parent = parent.parent) { 12406 parents.push(parent); 12407 } 12408 if (parent && parents.length > 1) { 12409 if (schema.isValidChild(parent.name, node.name)) { 12410 parents.reverse(); 12411 newParent = parents[0].clone(); 12412 onCreate(newParent); 12413 let currentNode = newParent; 12414 for (let i = 0; i < parents.length - 1; i++) { 12415 if (schema.isValidChild(currentNode.name, parents[i].name) && i > 0) { 12416 tempNode = parents[i].clone(); 12417 onCreate(tempNode); 12418 currentNode.append(tempNode); 12419 } else { 12420 tempNode = currentNode; 12421 } 12422 for (let childNode = parents[i].firstChild; childNode && childNode !== parents[i + 1];) { 12423 const nextNode = childNode.next; 12424 tempNode.append(childNode); 12425 childNode = nextNode; 12426 } 12427 currentNode = tempNode; 12428 } 12429 if (!isEmpty(schema, nonEmptyElements, whitespaceElements, newParent)) { 12430 parent.insert(newParent, parents[0], true); 12431 parent.insert(node, newParent); 12432 } else { 12433 parent.insert(node, parents[0], true); 12434 } 12435 parent = parents[0]; 12436 if (isEmpty(schema, nonEmptyElements, whitespaceElements, parent) || hasOnlyChild(parent, 'br')) { 12437 parent.empty().remove(); 12438 } 12439 } else { 12440 removeOrUnwrapInvalidNode(node, schema); 12441 } 12442 } else if (node.parent) { 12443 if (node.name === 'li') { 12444 let sibling = node.prev; 12445 if (sibling && (sibling.name === 'ul' || sibling.name === 'ol')) { 12446 sibling.append(node); 12447 continue; 12448 } 12449 sibling = node.next; 12450 if (sibling && (sibling.name === 'ul' || sibling.name === 'ol') && sibling.firstChild) { 12451 sibling.insert(node, sibling.firstChild, true); 12452 continue; 12453 } 12454 const wrapper = new AstNode('ul', 1); 12455 onCreate(wrapper); 12456 node.wrap(wrapper); 12457 continue; 12458 } 12459 if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) { 12460 const wrapper = new AstNode('div', 1); 12461 onCreate(wrapper); 12462 node.wrap(wrapper); 12463 } else { 12464 removeOrUnwrapInvalidNode(node, schema); 12465 } 12466 } 12467 } 12468 }; 12469 const hasClosest = (node, parentName) => { 12470 let tempNode = node; 12471 while (tempNode) { 12472 if (tempNode.name === parentName) { 12473 return true; 12474 } 12475 tempNode = tempNode.parent; 12476 } 12477 return false; 12478 }; 12479 const isInvalid = (schema, node, parent = node.parent) => { 12480 if (parent && schema.children[node.name] && !schema.isValidChild(parent.name, node.name)) { 12481 return true; 12482 } else if (parent && node.name === 'a' && hasClosest(parent, 'a')) { 12483 return true; 12484 } else { 12485 return false; 12486 } 12487 }; 12488 12489 const createRange = (sc, so, ec, eo) => { 12490 const rng = document.createRange(); 12491 rng.setStart(sc, so); 12492 rng.setEnd(ec, eo); 12493 return rng; 12494 }; 12495 const normalizeBlockSelectionRange = rng => { 12496 const startPos = CaretPosition.fromRangeStart(rng); 12497 const endPos = CaretPosition.fromRangeEnd(rng); 12498 const rootNode = rng.commonAncestorContainer; 12499 return fromPosition(false, rootNode, endPos).map(newEndPos => { 12500 if (!isInSameBlock(startPos, endPos, rootNode) && isInSameBlock(startPos, newEndPos, rootNode)) { 12501 return createRange(startPos.container(), startPos.offset(), newEndPos.container(), newEndPos.offset()); 12502 } else { 12503 return rng; 12504 } 12505 }).getOr(rng); 12506 }; 12507 const normalize = rng => rng.collapsed ? rng : normalizeBlockSelectionRange(rng); 12508 12509 const hasOnlyOneChild
12509 = node => { 12510 return isNonNullable(node.firstChild) && node.firstChild === node.lastChild; 12511 }; 12512 const isPaddingNode = node => { 12513 return node.name === 'br' || node.value === nbsp; 12514 }; 12515 const isPaddedEmptyBlock = (schema, node) => { 12516 const blockElements = schema.getBlockElements(); 12517 return blockElements[node.name] && hasOnlyOneChild
vendor: 12,206 bytes, lines 12517-12809
12517(node) && isPaddingNode(node.firstChild); 12518 }; 12519 const isEmptyFragmentElement = (schema, node) => { 12520 const nonEmptyElements = schema.getNonEmptyElements(); 12521 return isNonNullable(node) && (node.isEmpty(nonEmptyElements) || isPaddedEmptyBlock(schema, node)); 12522 }; 12523 const isListFragment = (schema, fragment) => { 12524 let firstChild = fragment.firstChild; 12525 let lastChild = fragment.lastChild; 12526 if (firstChild && firstChild.name === 'meta') { 12527 firstChild = firstChild.next; 12528 } 12529 if (lastChild && lastChild.attr('id') === 'mce_marker') { 12530 lastChild = lastChild.prev; 12531 } 12532 if (isEmptyFragmentElement(schema, lastChild)) { 12533 lastChild = lastChild === null || lastChild === void 0 ? void 0 : lastChild.prev; 12534 } 12535 if (!firstChild || firstChild !== lastChild) { 12536 return false; 12537 } 12538 return firstChild.name === 'ul' || firstChild.name === 'ol'; 12539 }; 12540 const cleanupDomFragment = domFragment => { 12541 var _a, _b; 12542 const firstChild = domFragment.firstChild; 12543 const lastChild = domFragment.lastChild; 12544 if (firstChild && firstChild.nodeName === 'META') { 12545 (_a = firstChild.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(firstChild); 12546 } 12547 if (lastChild && lastChild.id === 'mce_marker') { 12548 (_b = lastChild.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(lastChild); 12549 } 12550 return domFragment; 12551 }; 12552 const toDomFragment = (dom, serializer, fragment) => { 12553 const html = serializer.serialize(fragment); 12554 const domFragment = dom.createFragment(html); 12555 return cleanupDomFragment(domFragment); 12556 }; 12557 const listItems = elm => { 12558 var _a; 12559 return filter$5((_a = elm === null || elm === void 0 ? void 0 : elm.childNodes) !== null && _a !== void 0 ? _a : [], child => { 12560 return child.nodeName === 'LI'; 12561 }); 12562 }; 12563 const isPadding = node => { 12564 return node.data === nbsp || isBr$6(node); 12565 }; 12566 const isListItemPadded = node => { 12567 return isNonNullable(node === null || node === void 0 ? void 0 : node.firstChild) && node.firstChild === node.lastChild && isPadding(node.firstChild); 12568 }; 12569 const isEmptyOrPadded = elm => { 12570 return !elm.firstChild || isListItemPadded(elm); 12571 }; 12572 const trimListItems = elms => { 12573 return elms.length > 0 && isEmptyOrPadded(elms[elms.length - 1]) ? elms.slice(0, -1) : elms; 12574 }; 12575 const getParentLi = (dom, node) => { 12576 const parentBlock = dom.getParent(node, dom.isBlock); 12577 return parentBlock && parentBlock.nodeName === 'LI' ? parentBlock : null; 12578 }; 12579 const isParentBlockLi = (dom, node) => { 12580 return !!getParentLi(dom, node); 12581 }; 12582 const getSplit = (parentNode, rng) => { 12583 const beforeRng = rng.cloneRange(); 12584 const afterRng = rng.cloneRange(); 12585 beforeRng.setStartBefore(parentNode); 12586 afterRng.setEndAfter(parentNode); 12587 return [ 12588 beforeRng.cloneContents(), 12589 afterRng.cloneContents() 12590 ]; 12591 }; 12592 const findFirstIn = (node, rootNode) => { 12593 const caretPos = CaretPosition.before(node); 12594 const caretWalker = CaretWalker(rootNode); 12595 const newCaretPos = caretWalker.next(caretPos); 12596 return newCaretPos ? newCaretPos.toRange() : null; 12597 }; 12598 const findLastOf = (node, rootNode) => { 12599 const caretPos = CaretPosition.after(node); 12600 const caretWalker = CaretWalker(rootNode); 12601 const newCaretPos = caretWalker.prev(caretPos); 12602 return newCaretPos ? newCaretPos.toRange() : null; 12603 }; 12604 const insertMiddle = (target, elms, rootNode, rng) => { 12605 const parts = getSplit(target, rng); 12606 const parentElm = target.parentNode; 12607 if (parentElm) { 12608 parentElm.insertBefore(parts[0], target); 12609 Tools.each(elms, li => { 12610 parentElm.insertBefore(li, target); 12611 }); 12612 parentElm.insertBefore(parts[1], target); 12613 parentElm.removeChild(target); 12614 } 12615 return findLastOf(elms[elms.length - 1], rootNode); 12616 }; 12617 const insertBefore$1 = (target, elms, rootNode) => { 12618 const parentElm = target.parentNode; 12619 if (parentElm) { 12620 Tools.each(elms, elm => { 12621 parentElm.insertBefore(elm, target); 12622 }); 12623 } 12624 return findFirstIn(target, rootNode); 12625 }; 12626 const insertAfter$1 = (target, elms, rootNode, dom) => { 12627 dom.insertAfter(elms.reverse(), target); 12628 return findLastOf(elms[0], rootNode); 12629 }; 12630 const insertAtCaret$1 = (serializer, dom, rng, fragment) => { 12631 const domFragment = toDomFragment(dom, serializer, fragment); 12632 const liTarget = getParentLi(dom, rng.startContainer); 12633 const liElms = trimListItems(listItems(domFragment.firstChild)); 12634 const BEGINNING = 1, END = 2; 12635 const rootNode = dom.getRoot(); 12636 const isAt = location => { 12637 const caretPos = CaretPosition.fromRangeStart(rng); 12638 const caretWalker = CaretWalker(dom.getRoot()); 12639 const newPos = location === BEGINNING ? caretWalker.prev(caretPos) : caretWalker.next(caretPos); 12640 const newPosNode = newPos === null || newPos === void 0 ? void 0 : newPos.getNode(); 12641 return newPosNode ? getParentLi(dom, newPosNode) !== liTarget : true; 12642 }; 12643 if (!liTarget) { 12644 return null; 12645 } else if (isAt(BEGINNING)) { 12646 return insertBefore$1(liTarget, liElms, rootNode); 12647 } else if (isAt(END)) { 12648 return insertAfter$1(liTarget, liElms, rootNode, dom); 12649 } else { 12650 return insertMiddle(liTarget, liElms, rootNode, rng); 12651 } 12652 }; 12653 12654 const mergeableWrappedElements = ['pre']; 12655 const shouldPasteContentOnly = (dom, fragment, parentNode, root) => { 12656 var _a; 12657 const firstNode = fragment.firstChild; 12658 const lastNode = fragment.lastChild; 12659 const last = lastNode.attr('data-mce-type') === 'bookmark' ? lastNode.prev : lastNode; 12660 const isPastingSingleElement = firstNode === last; 12661 const isWrappedElement = contains$2(mergeableWrappedElements, firstNode.name); 12662 if (isPastingSingleElement && isWrappedElement) { 12663 const isContentEditable = firstNode.attr('contenteditable') !== 'false'; 12664 const isPastingInTheSameBlockTag = ((_a = dom.getParent(parentNode, dom.isBlock)) === null || _a === void 0 ? void 0 : _a.nodeName.toLowerCase()) === firstNode.name; 12665 const isPastingInContentEditable = Optional.from(getContentEditableRoot$1(root, parentNode)).forall(isContentEditableTrue$3); 12666 return isContentEditable && isPastingInTheSameBlockTag && isPastingInContentEditable; 12667 } else { 12668 return false; 12669 } 12670 }; 12671 const isTableCell = isTableCell$3; 12672 const isTableCellContentSelected = (dom, rng, cell) => { 12673 if (isNonNullable(cell)) { 12674 const endCell = dom.getParent(rng.endContainer, isTableCell); 12675 return cell === endCell && hasAllContentsSelected(SugarElement.fromDom(cell), rng); 12676 } else { 12677 return false; 12678 } 12679 }; 12680 const validInsertion = (editor, value, parentNode) => { 12681 var _a; 12682 if (parentNode.getAttribute('data-mce-bogus') === 'all') { 12683 (_a = parentNode.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(editor.dom.createFragment(value), parentNode); 12684 } else { 12685 const node = parentNode.firstChild; 12686 const node2 = parentNode.lastChild; 12687 if (!node || node === node2 && node.nodeName === 'BR') { 12688 editor.dom.setHTML(parentNode, value); 12689 } else { 12690 editor.selection.setContent(value, { no_events: true }); 12691 } 12692 } 12693 }; 12694 const trimBrsFromTableCell = (dom, elm) => { 12695 Optional.from(dom.getParent(elm, 'td,th')).map(SugarElement.fromDom).each(trimBlockTrailingBr); 12696 }; 12697 const reduceInlineTextElements = (editor, merge) => { 12698 const textInlineElements = editor.schema.getTextInlineElements(); 12699 const dom = editor.dom; 12700 if (merge) { 12701 const root = editor.getBody(); 12702 const elementUtils = ElementUtils(editor); 12703 Tools.each(dom.select('*[data-mce-fragment]'), node => { 12704 const isInline = isNonNullable(textInlineElements[node.nodeName.toLowerCase()]); 12705 if (isInline && hasInheritableStyles(dom, node)) { 12706 for (let parentNode = node.parentElement; isNonNullable(parentNode) && parentNode !== root; parentNode = parentNode.parentElement) { 12707 const styleConflict = hasStyleConflict(dom, node, parentNode); 12708 if (styleConflict) { 12709 break; 12710 } 12711 if (elementUtils.compare(parentNode, node)) { 12712 dom.remove(node, true); 12713 break; 12714 } 12715 } 12716 } 12717 }); 12718 } 12719 }; 12720 const markFragmentElements = fragment => { 12721 let node = fragment; 12722 while (node = node.walk()) { 12723 if (node.type === 1) { 12724 node.attr('data-mce-fragment', '1'); 12725 } 12726 } 12727 }; 12728 const unmarkFragmentElements = elm => { 12729 Tools.each(elm.getElementsByTagName('*'), elm => { 12730 elm.removeAttribute('data-mce-fragment'); 12731 }); 12732 }; 12733 const isPartOfFragment = node => { 12734 return !!node.getAttribute('data-mce-fragment'); 12735 }; 12736 const canHaveChildren = (editor, node) => { 12737 return isNonNullable(node) && !editor.schema.getVoidElements()[node.nodeName]; 12738 }; 12739 const moveSelectionToMarker = (editor, marker) => { 12740 var _a, _b, _c; 12741 let nextRng; 12742 const dom = editor.dom; 12743 const selection = editor.selection; 12744 if (!marker) { 12745 return; 12746 } 12747 selection.scrollIntoView(marker); 12748 const parentEditableElm = getContentEditableRoot$1(editor.getBody(), marker); 12749 if (parentEditableElm && dom.getContentEditable(parentEditableElm) === 'false') { 12750 dom.remove(marker); 12751 selection.select(parentEditableElm); 12752 return; 12753 } 12754 let rng = dom.createRng(); 12755 const node = marker.previousSibling; 12756 if (isText$a(node)) { 12757 rng.setStart(node, (_b = (_a = node.nodeValue) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0); 12758 const node2 = marker.nextSibling; 12759 if (isText$a(node2)) { 12760 node.appendData(node2.data); 12761 (_c = node2.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(node2); 12762 } 12763 } else { 12764 rng.setStartBefore(marker); 12765 rng.setEndBefore(marker); 12766 } 12767 const findNextCaretRng = rng => { 12768 let caretPos = CaretPosition.fromRangeStart(rng); 12769 const caretWalker = CaretWalker(editor.getBody()); 12770 caretPos = caretWalker.next(caretPos); 12771 return caretPos === null || caretPos === void 0 ? void 0 : caretPos.toRange(); 12772 }; 12773 const parentBlock = dom.getParent(marker, dom.isBlock); 12774 dom.remove(marker); 12775 if (parentBlock && dom.isEmpty(parentBlock)) { 12776 empty(SugarElement.fromDom(parentBlock)); 12777 rng.setStart(parentBlock, 0); 12778 rng.setEnd(parentBlock, 0); 12779 if (!isTableCell(parentBlock) && !isPartOfFragment(parentBlock) && (nextRng = findNextCaretRng(rng))) { 12780 rng = nextRng; 12781 dom.remove(parentBlock); 12782 } else { 12783 dom.add(parentBlock, dom.create('br', { 'data-mce-bogus': '1' })); 12784 } 12785 } 12786 selection.setRng(rng); 12787 }; 12788 const deleteSelectedContent = editor => { 12789 const dom = editor.dom; 12790 const rng = normalize(editor.selection.getRng()); 12791 editor.selection.setRng(rng); 12792 const startCell = dom.getParent(rng.startContainer, isTableCell); 12793 if (isTableCellContentSelected(dom, rng, startCell)) { 12794 deleteCellContents(editor, rng, SugarElement.fromDom(startCell)); 12795 } else if (rng.startContainer === rng.endContainer && rng.endOffset - rng.startOffset === 1 && isText$a(rng.startContainer.childNodes[rng.startOffset])) { 12796 rng.deleteContents(); 12797 } else { 12798 editor.getDoc().execCommand('Delete', false); 12799 } 12800 }; 12801 const findMarkerNode = scope => { 12802 for (let markerNode = scope; markerNode; markerNode = markerNode.walk()) { 12803 if (markerNode.attr('id') === 'mce_marker') { 12804 return Optional.some(markerNode); 12805 } 12806 } 12807 return Optional.none(); 12808 }; 12809 const
12809insertHtmlAtCaret = (editor, value, details) => { 12810 var _a, _b; 12811 const selection = editor.selection; 12812 const dom = editor.dom; 12813 const parser = editor.parser; 12814 const merge = details.merge; 12815 const serializer = HtmlSerializer({ validate: true }, editor.schema); 12816 const bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">
vendor: 7,676 bytes, lines 12816-13006
12816</span>'; 12817 if (value.indexOf('{$caret}') === -1) { 12818 value += '{$caret}'; 12819 } 12820 value = value.replace(/\{\$caret\}/, bookmarkHtml); 12821 let rng = selection.getRng(); 12822 const caretElement = rng.startContainer; 12823 const body = editor.getBody(); 12824 if (caretElement === body && selection.isCollapsed()) { 12825 if (dom.isBlock(body.firstChild) && canHaveChildren(editor, body.firstChild) && dom.isEmpty(body.firstChild)) { 12826 rng = dom.createRng(); 12827 rng.setStart(body.firstChild, 0); 12828 rng.setEnd(body.firstChild, 0); 12829 selection.setRng(rng); 12830 } 12831 } 12832 if (!selection.isCollapsed()) { 12833 deleteSelectedContent(editor); 12834 } 12835 const parentNode = selection.getNode(); 12836 const parserArgs = { 12837 context: parentNode.nodeName.toLowerCase(), 12838 data: details.data, 12839 insert: true 12840 }; 12841 const fragment = parser.parse(value, parserArgs); 12842 if (details.paste === true && isListFragment(editor.schema, fragment) && isParentBlockLi(dom, parentNode)) { 12843 rng = insertAtCaret$1(serializer, dom, selection.getRng(), fragment); 12844 if (rng) { 12845 selection.setRng(rng); 12846 } 12847 return value; 12848 } 12849 if (details.paste === true && shouldPasteContentOnly(dom, fragment, parentNode, editor.getBody())) { 12850 (_a = fragment.firstChild) === null || _a === void 0 ? void 0 : _a.unwrap(); 12851 } 12852 markFragmentElements(fragment); 12853 let node = fragment.lastChild; 12854 if (node && node.attr('id') === 'mce_marker') { 12855 const marker = node; 12856 for (node = node.prev; node; node = node.walk(true)) { 12857 if (node.type === 3 || !dom.isBlock(node.name)) { 12858 if (node.parent && editor.schema.isValidChild(node.parent.name, 'span')) { 12859 node.parent.insert(marker, node, node.name === 'br'); 12860 } 12861 break; 12862 } 12863 } 12864 } 12865 editor._selectionOverrides.showBlockCaretContainer(parentNode); 12866 if (!parserArgs.invalid) { 12867 value = serializer.serialize(fragment); 12868 validInsertion(editor, value, parentNode); 12869 } else { 12870 editor.selection.setContent(bookmarkHtml); 12871 let parentNode = selection.getNode(); 12872 let tempNode; 12873 const rootNode = editor.getBody(); 12874 if (isDocument$1(parentNode)) { 12875 parentNode = tempNode = rootNode; 12876 } else { 12877 tempNode = parentNode; 12878 } 12879 while (tempNode && tempNode !== rootNode) { 12880 parentNode = tempNode; 12881 tempNode = tempNode.parentNode; 12882 } 12883 value = parentNode === rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode); 12884 const root = parser.parse(value); 12885 const markerNode = findMarkerNode(root); 12886 const editingHost = markerNode.bind(findClosestEditingHost).getOr(root); 12887 markerNode.each(marker => marker.replace(fragment)); 12888 const toExtract = fragment.children(); 12889 const parent = (_b = fragment.parent) !== null && _b !== void 0 ? _b : root; 12890 fragment.unwrap(); 12891 const invalidChildren = filter$5(toExtract, node => isInvalid(editor.schema, node, parent)); 12892 cleanInvalidNodes(invalidChildren, editor.schema, editingHost); 12893 filter$2(parser.getNodeFilters(), parser.getAttributeFilters(), root); 12894 value = serializer.serialize(root); 12895 if (parentNode === rootNode) { 12896 dom.setHTML(rootNode, value); 12897 } else { 12898 dom.setOuterHTML(parentNode, value); 12899 } 12900 } 12901 reduceInlineTextElements(editor, merge); 12902 moveSelectionToMarker(editor, dom.get('mce_marker')); 12903 unmarkFragmentElements(editor.getBody()); 12904 trimBrsFromTableCell(dom, selection.getStart()); 12905 updateCaret(editor.schema, editor.getBody(), selection.getStart()); 12906 return value; 12907 }; 12908 12909 const isTreeNode = content => content instanceof AstNode; 12910 12911 const moveSelection = editor => { 12912 if (hasFocus(editor)) { 12913 firstPositionIn(editor.getBody()).each(pos => { 12914 const node = pos.getNode(); 12915 const caretPos = isTable$2(node) ? firstPositionIn(node).getOr(pos) : pos; 12916 editor.selection.setRng(caretPos.toRange()); 12917 }); 12918 } 12919 }; 12920 const setEditorHtml = (editor, html, noSelection) => { 12921 editor.dom.setHTML(editor.getBody(), html); 12922 if (noSelection !== true) { 12923 moveSelection(editor); 12924 } 12925 }; 12926 const setContentString = (editor, body, content, args) => { 12927 if (content.length === 0 || /^\s+$/.test(content)) { 12928 const padd = '<br data-mce-bogus="1">'; 12929 if (body.nodeName === 'TABLE') { 12930 content = '<tr><td>' + padd + '</td></tr>'; 12931 } else if (/^(UL|OL)$/.test(body.nodeName)) { 12932 content = '<li>' + padd + '</li>'; 12933 } 12934 const forcedRootBlockName = getForcedRootBlock(editor); 12935 if (editor.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) { 12936 content = padd; 12937 content = editor.dom.createHTML(forcedRootBlockName, getForcedRootBlockAttrs(editor), content); 12938 } else if (!content) { 12939 content = padd; 12940 } 12941 setEditorHtml(editor, content, args.no_selection); 12942 return { 12943 content, 12944 html: content 12945 }; 12946 } else { 12947 if (args.format !== 'raw') { 12948 content = HtmlSerializer({ validate: false }, editor.schema).serialize(editor.parser.parse(content, { 12949 isRootContent: true, 12950 insert: true 12951 })); 12952 } 12953 const trimmedHtml = isWsPreserveElement(SugarElement.fromDom(body)) ? content : Tools.trim(content); 12954 setEditorHtml(editor, trimmedHtml, args.no_selection); 12955 return { 12956 content: trimmedHtml, 12957 html: trimmedHtml 12958 }; 12959 } 12960 }; 12961 const setContentTree = (editor, body, content, args) => { 12962 filter$2(editor.parser.getNodeFilters(), editor.parser.getAttributeFilters(), content); 12963 const html = HtmlSerializer({ validate: false }, editor.schema).serialize(content); 12964 const trimmedHtml = isWsPreserveElement(SugarElement.fromDom(body)) ? html : Tools.trim(html); 12965 setEditorHtml(editor, trimmedHtml, args.no_selection); 12966 return { 12967 content, 12968 html: trimmedHtml 12969 }; 12970 }; 12971 const setContentInternal = (editor, content, args) => { 12972 return Optional.from(editor.getBody()).map(body => { 12973 if (isTreeNode(content)) { 12974 return setContentTree(editor, body, content, args); 12975 } else { 12976 return setContentString(editor, body, content, args); 12977 } 12978 }).getOr({ 12979 content, 12980 html: isTreeNode(args.content) ? '' : args.content 12981 }); 12982 }; 12983 12984 const ancestor$1 = (scope, predicate, isRoot) => ancestor$4(scope, predicate, isRoot).isSome(); 12985 const sibling = (scope, predicate) => sibling$1(scope, predicate).isSome(); 12986 12987 const ensureIsRoot = isRoot => isFunction(isRoot) ? isRoot : never; 12988 const ancestor = (scope, transform, isRoot) => { 12989 let element = scope.dom; 12990 const stop = ensureIsRoot(isRoot); 12991 while (element.parentNode) { 12992 element = element.parentNode; 12993 const el = SugarElement.fromDom(element); 12994 const transformed = transform(el); 12995 if (transformed.isSome()) { 12996 return transformed; 12997 } else if (stop(el)) { 12998 break; 12999 } 13000 } 13001 return Optional.none(); 13002 }; 13003 const closest$1 = (scope, transform, isRoot) => { 13004 const current = transform(scope); 13005 const stop = ensureIsRoot(isRoot); 13006 return current.orThunk(() => stop(scope) ? Optional.none() : ancestor(scope, transform, stop
vendor: 5,553 bytes, lines 13006-13156
13006)); 13007 }; 13008 13009 const isEq$3 = isEq$5; 13010 const matchesUnInheritedFormatSelector = (ed, node, name) => { 13011 const formatList = ed.formatter.get(name); 13012 if (formatList) { 13013 for (let i = 0; i < formatList.length; i++) { 13014 const format = formatList[i]; 13015 if (isSelectorFormat(format) && format.inherit === false && ed.dom.is(node, format.selector)) { 13016 return true; 13017 } 13018 } 13019 } 13020 return false; 13021 }; 13022 const matchParents = (editor, node, name, vars, similar) => { 13023 const root = editor.dom.getRoot(); 13024 if (node === root) { 13025 return false; 13026 } 13027 const matchedNode = editor.dom.getParent(node, elm => { 13028 if (matchesUnInheritedFormatSelector(editor, elm, name)) { 13029 return true; 13030 } 13031 return elm.parentNode === root || !!matchNode(editor, elm, name, vars, true); 13032 }); 13033 return !!matchNode(editor, matchedNode, name, vars, similar); 13034 }; 13035 const matchName = (dom, node, format) => { 13036 if (isInlineFormat(format) && isEq$3(node, format.inline)) { 13037 return true; 13038 } 13039 if (isBlockFormat(format) && isEq$3(node, format.block)) { 13040 return true; 13041 } 13042 if (isSelectorFormat(format)) { 13043 return isElement$6(node) && dom.is(node, format.selector); 13044 } 13045 return false; 13046 }; 13047 const matchItems = (dom, node, format, itemName, similar, vars) => { 13048 const items = format[itemName]; 13049 const matchAttributes = itemName === 'attributes'; 13050 if (isFunction(format.onmatch)) { 13051 return format.onmatch(node, format, itemName); 13052 } 13053 if (items) { 13054 if (!isArrayLike(items)) { 13055 for (const key in items) { 13056 if (has$2(items, key)) { 13057 const value = matchAttributes ? dom.getAttrib(node, key) : getStyle(dom, node, key); 13058 const expectedValue = replaceVars(items[key], vars); 13059 const isEmptyValue = isNullable(value) || isEmpty$3(value); 13060 if (isEmptyValue && isNullable(expectedValue)) { 13061 continue; 13062 } 13063 if (similar && isEmptyValue && !format.exact) { 13064 return false; 13065 } 13066 if ((!similar || format.exact) && !isEq$3(value, normalizeStyleValue(expectedValue, key))) { 13067 return false; 13068 } 13069 } 13070 } 13071 } else { 13072 for (let i = 0; i < items.length; i++) { 13073 if (matchAttributes ? dom.getAttrib(node, items[i]) : getStyle(dom, node, items[i])) { 13074 return true; 13075 } 13076 } 13077 } 13078 } 13079 return true; 13080 }; 13081 const matchNode = (ed, node, name, vars, similar) => { 13082 const formatList = ed.formatter.get(name); 13083 const dom = ed.dom; 13084 if (formatList && isElement$6(node)) { 13085 for (let i = 0; i < formatList.length; i++) { 13086 const format = formatList[i]; 13087 if (matchName(ed.dom, node, format) && matchItems(dom, node, format, 'attributes', similar, vars) && matchItems(dom, node, format, 'styles', similar, vars)) { 13088 const classes = format.classes; 13089 if (classes) { 13090 for (let x = 0; x < classes.length; x++) { 13091 if (!ed.dom.hasClass(node, replaceVars(classes[x], vars))) { 13092 return; 13093 } 13094 } 13095 } 13096 return format; 13097 } 13098 } 13099 } 13100 return undefined; 13101 }; 13102 const match$2 = (editor, name, vars, node, similar) => { 13103 if (node) { 13104 return matchParents(editor, node, name, vars, similar); 13105 } 13106 node = editor.selection.getNode(); 13107 if (matchParents(editor, node, name, vars, similar)) { 13108 return true; 13109 } 13110 const startNode = editor.selection.getStart(); 13111 if (startNode !== node) { 13112 if (matchParents(editor, startNode, name, vars, similar)) { 13113 return true; 13114 } 13115 } 13116 return false; 13117 }; 13118 const matchAll = (editor, names, vars) => { 13119 const matchedFormatNames = []; 13120 const checkedMap = {}; 13121 const startElement = editor.selection.getStart(); 13122 editor.dom.getParent(startElement, node => { 13123 for (let i = 0; i < names.length; i++) { 13124 const name = names[i]; 13125 if (!checkedMap[name] && matchNode(editor, node, name, vars)) { 13126 checkedMap[name] = true; 13127 matchedFormatNames.push(name); 13128 } 13129 } 13130 }, editor.dom.getRoot()); 13131 return matchedFormatNames; 13132 }; 13133 const closest = (editor, names) => { 13134 const isRoot = elm => eq(elm, SugarElement.fromDom(editor.getBody())); 13135 const match = (elm, name) => matchNode(editor, elm.dom, name) ? Optional.some(name) : Optional.none(); 13136 return Optional.from(editor.selection.getStart(true)).bind(rawElm => closest$1(SugarElement.fromDom(rawElm), elm => findMap(names, name => match(elm, name)), isRoot)).getOrNull(); 13137 }; 13138 const canApply = (editor, name) => { 13139 const formatList = editor.formatter.get(name); 13140 const dom = editor.dom; 13141 if (formatList) { 13142 const startNode = editor.selection.getStart(); 13143 const parents = getParents$2(dom, startNode); 13144 for (let x = formatList.length - 1; x >= 0; x--) { 13145 const format = formatList[x]; 13146 if (!isSelectorFormat(format)) { 13147 return true; 13148 } 13149 for (let i = parents.length - 1; i >= 0; i--) { 13150 if (dom.is(parents[i], format.selector)) { 13151 return true; 13152 } 13153 } 13154 } 13155 } 13156 return false;
vendor: 39,730 bytes, lines 13157-14130
13157 }; 13158 const matchAllOnNode = (editor, node, formatNames) => foldl(formatNames, (acc, name) => { 13159 const matchSimilar = isVariableFormatName(editor, name); 13160 if (editor.formatter.matchNode(node, name, {}, matchSimilar)) { 13161 return acc.concat([name]); 13162 } else { 13163 return acc; 13164 } 13165 }, []); 13166 13167 const ZWSP = ZWSP$1; 13168 const importNode = (ownerDocument, node) => { 13169 return ownerDocument.importNode(node, true); 13170 }; 13171 const getEmptyCaretContainers = node => { 13172 const nodes = []; 13173 let tempNode = node; 13174 while (tempNode) { 13175 if (isText$a(tempNode) && tempNode.data !== ZWSP || tempNode.childNodes.length > 1) { 13176 return []; 13177 } 13178 if (isElement$6(tempNode)) { 13179 nodes.push(tempNode); 13180 } 13181 tempNode = tempNode.firstChild; 13182 } 13183 return nodes; 13184 }; 13185 const isCaretContainerEmpty = node => { 13186 return getEmptyCaretContainers(node).length > 0; 13187 }; 13188 const findFirstTextNode = node => { 13189 if (node) { 13190 const walker = new DomTreeWalker(node, node); 13191 for (let tempNode = walker.current(); tempNode; tempNode = walker.next()) { 13192 if (isText$a(tempNode)) { 13193 return tempNode; 13194 } 13195 } 13196 } 13197 return null; 13198 }; 13199 const createCaretContainer = fill => { 13200 const caretContainer = SugarElement.fromTag('span'); 13201 setAll$1(caretContainer, { 13202 'id': CARET_ID, 13203 'data-mce-bogus': '1', 13204 'data-mce-type': 'format-caret' 13205 }); 13206 if (fill) { 13207 append$1(caretContainer, SugarElement.fromText(ZWSP)); 13208 } 13209 return caretContainer; 13210 }; 13211 const trimZwspFromCaretContainer = caretContainerNode => { 13212 const textNode = findFirstTextNode(caretContainerNode); 13213 if (textNode && textNode.data.charAt(0) === ZWSP) { 13214 textNode.deleteData(0, 1); 13215 } 13216 return textNode; 13217 }; 13218 const removeCaretContainerNode = (editor, node, moveCaret = true) => { 13219 const dom = editor.dom, selection = editor.selection; 13220 if (isCaretContainerEmpty(node)) { 13221 deleteElement$2(editor, false, SugarElement.fromDom(node), moveCaret); 13222 } else { 13223 const rng = selection.getRng(); 13224 const block = dom.getParent(node, dom.isBlock); 13225 const startContainer = rng.startContainer; 13226 const startOffset = rng.startOffset; 13227 const endContainer = rng.endContainer; 13228 const endOffset = rng.endOffset; 13229 const textNode = trimZwspFromCaretContainer(node); 13230 dom.remove(node, true); 13231 if (startContainer === textNode && startOffset > 0) { 13232 rng.setStart(textNode, startOffset - 1); 13233 } 13234 if (endContainer === textNode && endOffset > 0) { 13235 rng.setEnd(textNode, endOffset - 1); 13236 } 13237 if (block && dom.isEmpty(block)) { 13238 fillWithPaddingBr(SugarElement.fromDom(block)); 13239 } 13240 selection.setRng(rng); 13241 } 13242 }; 13243 const removeCaretContainer = (editor, node, moveCaret = true) => { 13244 const dom = editor.dom, selection = editor.selection; 13245 if (!node) { 13246 node = getParentCaretContainer(editor.getBody(), selection.getStart()); 13247 if (!node) { 13248 while (node = dom.get(CARET_ID)) { 13249 removeCaretContainerNode(editor, node, false); 13250 } 13251 } 13252 } else { 13253 removeCaretContainerNode(editor, node, moveCaret); 13254 } 13255 }; 13256 const insertCaretContainerNode = (editor, caretContainer, formatNode) => { 13257 var _a, _b; 13258 const dom = editor.dom; 13259 const block = dom.getParent(formatNode, curry(isTextBlock$1, editor.schema)); 13260 if (block && dom.isEmpty(block)) { 13261 (_a = formatNode.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(caretContainer, formatNode); 13262 } else { 13263 removeTrailingBr(SugarElement.fromDom(formatNode)); 13264 if (dom.isEmpty(formatNode)) { 13265 (_b = formatNode.parentNode) === null || _b === void 0 ? void 0 : _b.replaceChild(caretContainer, formatNode); 13266 } else { 13267 dom.insertAfter(caretContainer, formatNode); 13268 } 13269 } 13270 }; 13271 const appendNode = (parentNode, node) => { 13272 parentNode.appendChild(node); 13273 return node; 13274 }; 13275 const insertFormatNodesIntoCaretContainer = (formatNodes, caretContainer) => { 13276 var _a; 13277 const innerMostFormatNode = foldr(formatNodes, (parentNode, formatNode) => { 13278 return appendNode(parentNode, formatNode.cloneNode(false)); 13279 }, caretContainer); 13280 const doc = (_a = innerMostFormatNode.ownerDocument) !== null && _a !== void 0 ? _a : document; 13281 return appendNode(innerMostFormatNode, doc.createTextNode(ZWSP)); 13282 }; 13283 const cleanFormatNode = (editor, caretContainer, formatNode, name, vars, similar) => { 13284 const formatter = editor.formatter; 13285 const dom = editor.dom; 13286 const validFormats = filter$5(keys(formatter.get()), formatName => formatName !== name && !contains$1(formatName, 'removeformat')); 13287 const matchedFormats = matchAllOnNode(editor, formatNode, validFormats); 13288 const uniqueFormats = filter$5(matchedFormats, fmtName => !areSimilarFormats(editor, fmtName, name)); 13289 if (uniqueFormats.length > 0) { 13290 const clonedFormatNode = formatNode.cloneNode(false); 13291 dom.add(caretContainer, clonedFormatNode); 13292 formatter.remove(name, vars, clonedFormatNode, similar); 13293 dom.remove(clonedFormatNode); 13294 return Optional.some(clonedFormatNode); 13295 } else { 13296 return Optional.none(); 13297 } 13298 }; 13299 const applyCaretFormat = (editor, name, vars) => { 13300 let caretContainer; 13301 const selection = editor.selection; 13302 const formatList = editor.formatter.get(name); 13303 if (!formatList) { 13304 return; 13305 } 13306 const selectionRng = selection.getRng(); 13307 let offset = selectionRng.startOffset; 13308 const container = selectionRng.startContainer; 13309 const text = container.nodeValue; 13310 caretContainer = getParentCaretContainer(editor.getBody(), selection.getStart()); 13311 const wordcharRegex = /[^\s\u00a0\u00ad\u200b\ufeff]/; 13312 if (text && offset > 0 && offset < text.length && wordcharRegex.test(text.charAt(offset)) && wordcharRegex.test(text.charAt(offset - 1))) { 13313 const bookmark = selection.getBookmark(); 13314 selectionRng.collapse(true); 13315 let rng = expandRng(editor.dom, selectionRng, formatList); 13316 rng = split(rng); 13317 editor.formatter.apply(name, vars, rng); 13318 selection.moveToBookmark(bookmark); 13319 } else { 13320 let textNode = caretContainer ? findFirstTextNode(caretContainer) : null; 13321 if (!caretContainer || (textNode === null || textNode === void 0 ? void 0 : textNode.data) !== ZWSP) { 13322 caretContainer = importNode(editor.getDoc(), createCaretContainer(true).dom); 13323 textNode = caretContainer.firstChild; 13324 selectionRng.insertNode(caretContainer); 13325 offset = 1; 13326 editor.formatter.apply(name, vars, caretContainer); 13327 } else { 13328 editor.formatter.apply(name, vars, caretContainer); 13329 } 13330 selection.setCursorLocation(textNode, offset); 13331 } 13332 }; 13333 const removeCaretFormat = (editor, name, vars, similar) => { 13334 const dom = editor.dom; 13335 const selection = editor.selection; 13336 let hasContentAfter = false; 13337 const formatList = editor.formatter.get(name); 13338 if (!formatList) { 13339 return; 13340 } 13341 const rng = selection.getRng(); 13342 const container = rng.startContainer; 13343 const offset = rng.startOffset; 13344 let node = container; 13345 if (isText$a(container)) { 13346 if (offset !== container.data.length) { 13347 hasContentAfter = true; 13348 } 13349 node = node.parentNode; 13350 } 13351 const parents = []; 13352 let formatNode; 13353 while (node) { 13354 if (matchNode(editor, node, name, vars, similar)) { 13355 formatNode = node; 13356 break; 13357 } 13358 if (node.nextSibling) { 13359 hasContentAfter = true; 13360 } 13361 parents.push(node); 13362 node = node.parentNode; 13363 } 13364 if (!formatNode) { 13365 return; 13366 } 13367 if (hasContentAfter) { 13368 const bookmark = selection.getBookmark(); 13369 rng.collapse(true); 13370 let expandedRng = expandRng(dom, rng, formatList, true); 13371 expandedRng = split(expandedRng); 13372 editor.formatter.remove(name, vars, expandedRng, similar); 13373 selection.moveToBookmark(bookmark); 13374 } else { 13375 const caretContainer = getParentCaretContainer(editor.getBody(), formatNode); 13376 const newCaretContainer = createCaretContainer(false).dom; 13377 insertCaretContainerNode(editor, newCaretContainer, caretContainer !== null && caretContainer !== void 0 ? caretContainer : formatNode); 13378 const cleanedFormatNode = cleanFormatNode(editor, newCaretContainer, formatNode, name, vars, similar); 13379 const caretTextNode = insertFormatNodesIntoCaretContainer(parents.concat(cleanedFormatNode.toArray()), newCaretContainer); 13380 if (caretContainer) { 13381 removeCaretContainerNode(editor, caretContainer, false); 13382 } 13383 selection.setCursorLocation(caretTextNode, 1); 13384 if (dom.isEmpty(formatNode)) { 13385 dom.remove(formatNode); 13386 } 13387 } 13388 }; 13389 const disableCaretContainer = (editor, keyCode) => { 13390 const selection = editor.selection, body = editor.getBody(); 13391 removeCaretContainer(editor, null, false); 13392 if ((keyCode === 8 || keyCode === 46) && selection.isCollapsed() && selection.getStart().innerHTML === ZWSP) { 13393 removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart())); 13394 } 13395 if (keyCode === 37 || keyCode === 39) { 13396 removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart())); 13397 } 13398 }; 13399 const setup$u = editor => { 13400 editor.on('mouseup keydown', e => { 13401 disableCaretContainer(editor, e.keyCode); 13402 }); 13403 }; 13404 const createCaretFormat = formatNodes => { 13405 const caretContainer = createCaretContainer(false); 13406 const innerMost = insertFormatNodesIntoCaretContainer(formatNodes, caretContainer.dom); 13407 return { 13408 caretContainer, 13409 caretPosition: CaretPosition(innerMost, 0) 13410 }; 13411 }; 13412 const replaceWithCaretFormat = (targetNode, formatNodes) => { 13413 const {caretContainer, caretPosition} = createCaretFormat(formatNodes); 13414 before$3(SugarElement.fromDom(targetNode), caretContainer); 13415 remove$6(SugarElement.fromDom(targetNode)); 13416 return caretPosition; 13417 }; 13418 const createCaretFormatAtStart$1 = (editor, formatNodes) => { 13419 const {caretContainer, caretPosition} = createCaretFormat(formatNodes); 13420 editor.selection.getRng().insertNode(caretContainer.dom); 13421 return caretPosition; 13422 }; 13423 const isFormatElement = (editor, element) => { 13424 const inlineElements = editor.schema.getTextInlineElements(); 13425 return has$2(inlineElements, name(element)) && !isCaretNode(element.dom) && !isBogus$2(element.dom); 13426 }; 13427 const isEmptyCaretFormatElement = element => { 13428 return isCaretNode(element.dom) && isCaretContainerEmpty(element.dom); 13429 }; 13430 13431 const postProcessHooks = {}; 13432 const isPre = matchNodeNames(['pre']); 13433 const addPostProcessHook = (name, hook) => { 13434 const hooks = postProcessHooks[name]; 13435 if (!hooks) { 13436 postProcessHooks[name] = []; 13437 } 13438 postProcessHooks[name].push(hook); 13439 }; 13440 const postProcess$1 = (name, editor) => { 13441 if (has$2(postProcessHooks, name)) { 13442 each$e(postProcessHooks[name], hook => { 13443 hook(editor); 13444 }); 13445 } 13446 }; 13447 addPostProcessHook('pre', editor => { 13448 const rng = editor.selection.getRng(); 13449 const hasPreSibling = blocks => pre => { 13450 const prev = pre.previousSibling; 13451 return isPre(prev) && contains$2(blocks, prev); 13452 }; 13453 const joinPre = (pre1, pre2) => { 13454 const sPre2 = SugarElement.fromDom(pre2); 13455 const doc = documentOrOwner(sPre2).dom; 13456 remove$6(sPre2); 13457 append(SugarElement.fromDom(pre1), [ 13458 SugarElement.fromTag('br', doc), 13459 SugarElement.fromTag('br', doc), 13460 ...children$1(sPre2) 13461 ]); 13462 }; 13463 if (!rng.collapsed) { 13464 const blocks = editor.selection.getSelectedBlocks(); 13465 const preBlocks = filter$5(filter$5(blocks, isPre), hasPreSibling(blocks)); 13466 each$e(preBlocks, pre => { 13467 joinPre(pre.previousSibling, pre); 13468 }); 13469 } 13470 }); 13471 13472 const listItemStyles = [ 13473 'fontWeight', 13474 'fontStyle', 13475 'color', 13476 'fontSize', 13477 'fontFamily' 13478 ]; 13479 const hasListStyles = fmt => isObject(fmt.styles) && exists(keys(fmt.styles), name => contains$2(listItemStyles, name)); 13480 const findExpandedListItemFormat = formats => find$2(formats, fmt => isInlineFormat(fmt) && fmt.inline === 'span' && hasListStyles(fmt)); 13481 const getExpandedListItemFormat = (formatter, format) => { 13482 const formatList = formatter.get(format); 13483 return isArray$1(formatList) ? findExpandedListItemFormat(formatList) : Optional.none(); 13484 }; 13485 const isRngStartAtStartOfElement = (rng, elm) => prevPosition(elm, CaretPosition.fromRangeStart(rng)).isNone(); 13486 const isRngEndAtEndOfElement = (rng, elm) => { 13487 return nextPosition(elm, CaretPosition.fromRangeEnd(rng)).exists(pos => !isBr$6(pos.getNode()) || nextPosition(elm, pos).isSome()) === false; 13488 }; 13489 const isEditableListItem = dom => elm => isListItem$2(elm) && dom.isEditable(elm); 13490 const getFullySelectedBlocks = selection => { 13491 const blocks = selection.getSelectedBlocks(); 13492 const rng = selection.getRng(); 13493 if (selection.isCollapsed()) { 13494 return []; 13495 } 13496 if (blocks.length === 1) { 13497 return isRngStartAtStartOfElement(rng, blocks[0]) && isRngEndAtEndOfElement(rng, blocks[0]) ? blocks : []; 13498 } else { 13499 const first = head(blocks).filter(elm => isRngStartAtStartOfElement(rng, elm)).toArray(); 13500 const last = last$3(blocks).filter(elm => isRngEndAtEndOfElement(rng, elm)).toArray(); 13501 const middle = blocks.slice(1, -1); 13502 return first.concat(middle).concat(last); 13503 } 13504 }; 13505 const getFullySelectedListItems = selection => filter$5(getFullySelectedBlocks(selection), isEditableListItem(selection.dom)); 13506 const getPartiallySelectedListItems = selection => filter$5(selection.getSelectedBlocks(), isEditableListItem(selection.dom)); 13507 13508 const each$8 = Tools.each; 13509 const isElementNode = node => isElement$6(node) && !isBookmarkNode$1(node) && !isCaretNode(node) && !isBogus$2(node); 13510 const findElementSibling = (node, siblingName) => { 13511 for (let sibling = node; sibling; sibling = sibling[siblingName]) { 13512 if (isText$a(sibling) && isNotEmpty(sibling.data)) { 13513 return node; 13514 } 13515 if (isElement$6(sibling) && !isBookmarkNode$1(sibling)) { 13516 return sibling; 13517 } 13518 } 13519 return node; 13520 }; 13521 const mergeSiblingsNodes = (editor, prev, next) => { 13522 const elementUtils = ElementUtils(editor); 13523 const isPrevEditable = isElement$6(prev) && isEditable$2(prev); 13524 const isNextEditable = isElement$6(next) && isEditable$2(next); 13525 if (isPrevEditable && isNextEditable) { 13526 const prevSibling = findElementSibling(prev, 'previousSibling'); 13527 const nextSibling = findElementSibling(next, 'nextSibling'); 13528 if (elementUtils.compare(prevSibling, nextSibling)) { 13529 for (let sibling = prevSibling.nextSibling; sibling && sibling !== nextSibling;) { 13530 const tmpSibling = sibling; 13531 sibling = sibling.nextSibling; 13532 prevSibling.appendChild(tmpSibling); 13533 } 13534 editor.dom.remove(nextSibling); 13535 Tools.each(Tools.grep(nextSibling.childNodes), node => { 13536 prevSibling.appendChild(node); 13537 }); 13538 return prevSibling; 13539 } 13540 } 13541 return next; 13542 }; 13543 const mergeSiblings = (editor, format, vars, node) => { 13544 var _a; 13545 if (node && format.merge_siblings !== false) { 13546 const newNode = (_a = mergeSiblingsNodes(editor, getNonWhiteSpaceSibling(node), node)) !== null && _a !== void 0 ? _a : node; 13547 mergeSiblingsNodes(editor, newNode, getNonWhiteSpaceSibling(newNode, true)); 13548 } 13549 }; 13550 const clearChildStyles = (dom, format, node) => { 13551 if (format.clear_child_styles) { 13552 const selector = format.links ? '*:not(a)' : '*'; 13553 each$8(dom.select(selector, node), childNode => { 13554 if (isElementNode(childNode) && isEditable$2(childNode)) { 13555 each$8(format.styles, (_value, name) => { 13556 dom.setStyle(childNode, name, ''); 13557 }); 13558 } 13559 }); 13560 } 13561 }; 13562 const processChildElements = (node, filter, process) => { 13563 each$8(node.childNodes, node => { 13564 if (isElementNode(node)) { 13565 if (filter(node)) { 13566 process(node); 13567 } 13568 if (node.hasChildNodes()) { 13569 processChildElements(node, filter, process); 13570 } 13571 } 13572 }); 13573 }; 13574 const unwrapEmptySpan = (dom, node) => { 13575 if (node.nodeName === 'SPAN' && dom.getAttribs(node).length === 0) { 13576 dom.remove(node, true); 13577 } 13578 }; 13579 const hasStyle = (dom, name) => node => !!(node && getStyle(dom, node, name)); 13580 const applyStyle = (dom, name, value) => node => { 13581 dom.setStyle(node, name, value); 13582 if (node.getAttribute('style') === '') { 13583 node.removeAttribute('style'); 13584 } 13585 unwrapEmptySpan(dom, node); 13586 }; 13587 13588 const removeResult = Adt.generate([ 13589 { keep: [] }, 13590 { rename: ['name'] }, 13591 { removed: [] } 13592 ]); 13593 const MCE_ATTR_RE = /^(src|href|style)$/; 13594 const each$7 = Tools.each; 13595 const isEq$2 = isEq$5; 13596 const isTableCellOrRow = node => /^(TR|TH|TD)$/.test(node.nodeName); 13597 const isChildOfInlineParent = (dom, node, parent) => dom.isChildOf(node, parent) && node !== parent && !dom.isBlock(parent); 13598 const getContainer = (ed, rng, start) => { 13599 let container = rng[start ? 'startContainer' : 'endContainer']; 13600 let offset = rng[start ? 'startOffset' : 'endOffset']; 13601 if (isElement$6(container)) { 13602 const lastIdx = container.childNodes.length - 1; 13603 if (!start && offset) { 13604 offset--; 13605 } 13606 container = container.childNodes[offset > lastIdx ? lastIdx : offset]; 13607 } 13608 if (isText$a(container) && start && offset >= container.data.length) { 13609 container = new DomTreeWalker(container, ed.getBody()).next() || container; 13610 } 13611 if (isText$a(container) && !start && offset === 0) { 13612 container = new DomTreeWalker(container, ed.getBody()).prev() || container; 13613 } 13614 return container; 13615 }; 13616 const normalizeTableSelection = (node, start) => { 13617 const prop = start ? 'firstChild' : 'lastChild'; 13618 const childNode = node[prop]; 13619 if (isTableCellOrRow(node) && childNode) { 13620 if (node.nodeName === 'TR') { 13621 return childNode[prop] || childNode; 13622 } else { 13623 return childNode; 13624 } 13625 } 13626 return node; 13627 }; 13628 const wrap$1 = (dom, node, name, attrs) => { 13629 var _a; 13630 const wrapper = dom.create(name, attrs); 13631 (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(wrapper, node); 13632 wrapper.appendChild(node); 13633 return wrapper; 13634 }; 13635 const wrapWithSiblings = (dom, node, next, name, attrs) => { 13636 const start = SugarElement.fromDom(node); 13637 const wrapper = SugarElement.fromDom(dom.create(name, attrs)); 13638 const siblings = next ? nextSiblings(start) : prevSiblings(start); 13639 append(wrapper, siblings); 13640 if (next) { 13641 before$3(start, wrapper); 13642 prepend(wrapper, start); 13643 } else { 13644 after$4(start, wrapper); 13645 append$1(wrapper, start); 13646 } 13647 return wrapper.dom; 13648 }; 13649 const isColorFormatAndAnchor = (node, format) => format.links && node.nodeName === 'A'; 13650 const removeNode = (ed, node, format) => { 13651 const parentNode = node.parentNode; 13652 let rootBlockElm; 13653 const dom = ed.dom; 13654 const forcedRootBlock = getForcedRootBlock(ed); 13655 if (isBlockFormat(format)) { 13656 if (parentNode === dom.getRoot()) { 13657 if (!format.list_block || !isEq$2(node, format.list_block)) { 13658 each$e(from(node.childNodes), node => { 13659 if (isValid(ed, forcedRootBlock, node.nodeName.toLowerCase())) { 13660 if (!rootBlockElm) { 13661 rootBlockElm = wrap$1(dom, node, forcedRootBlock); 13662 dom.setAttribs(rootBlockElm, getForcedRootBlockAttrs(ed)); 13663 } else { 13664 rootBlockElm.appendChild(node); 13665 } 13666 } else { 13667 rootBlockElm = null; 13668 } 13669 }); 13670 } 13671 } 13672 } 13673 if (isMixedFormat(format) && !isEq$2(format.inline, node)) { 13674 return; 13675 } 13676 dom.remove(node, true); 13677 }; 13678 const processFormatAttrOrStyle = (name, value, vars) => { 13679 if (isNumber(name)) { 13680 return { 13681 name: value, 13682 value: null 13683 }; 13684 } else { 13685 return { 13686 name, 13687 value: replaceVars(value, vars) 13688 }; 13689 } 13690 }; 13691 const removeEmptyStyleAttributeIfNeeded = (dom, elm) => { 13692 if (dom.getAttrib(elm, 'style') === '') { 13693 elm.removeAttribute('style'); 13694 elm.removeAttribute('data-mce-style'); 13695 } 13696 }; 13697 const removeStyles = (dom, elm, format, vars, compareNode) => { 13698 let stylesModified = false; 13699 each$7(format.styles, (value, name) => { 13700 const { 13701 name: styleName, 13702 value: styleValue 13703 } = processFormatAttrOrStyle(name, value, vars); 13704 const normalizedStyleValue = normalizeStyleValue(styleValue, styleName); 13705 if (format.remove_similar || isNull(styleValue) || !isElement$6(compareNode) || isEq$2(getStyle(dom, compareNode, styleName), normalizedStyleValue)) { 13706 dom.setStyle(elm, styleName, ''); 13707 } 13708 stylesModified = true; 13709 }); 13710 if (stylesModified) { 13711 removeEmptyStyleAttributeIfNeeded(dom, elm); 13712 } 13713 }; 13714 const removeListStyleFormats = (editor, name, vars) => { 13715 if (name === 'removeformat') { 13716 each$e(getPartiallySelectedListItems(editor.selection), li => { 13717 each$e(listItemStyles, name => editor.dom.setStyle(li, name, '')); 13718 removeEmptyStyleAttributeIfNeeded(editor.dom, li); 13719 }); 13720 } else { 13721 getExpandedListItemFormat(editor.formatter, name).each(liFmt => { 13722 each$e(getPartiallySelectedListItems(editor.selection), li => removeStyles(editor.dom, li, liFmt, vars, null)); 13723 }); 13724 } 13725 }; 13726 const removeFormatInternal = (ed, format, vars, node, compareNode) => { 13727 const dom = ed.dom; 13728 const elementUtils = ElementUtils(ed); 13729 const schema = ed.schema; 13730 if (isInlineFormat(format) && isTransparentElementName(schema, format.inline) && isTransparentBlock(schema, node) && node.parentElement === ed.getBody()) { 13731 removeNode(ed, node, format); 13732 return removeResult.removed(); 13733 } 13734 if (!format.ceFalseOverride && node && dom.getContentEditableParent(node) === 'false') { 13735 return removeResult.keep(); 13736 } 13737 if (node && !matchName(dom, node, format) && !isColorFormatAndAnchor(node, format)) { 13738 return removeResult.keep(); 13739 } 13740 const elm = node; 13741 const preserveAttributes = format.preserve_attributes; 13742 if (isInlineFormat(format) && format.remove === 'all' && isArray$1(preserveAttributes)) { 13743 const attrsToPreserve = filter$5(dom.getAttribs(elm), attr => contains$2(preserveAttributes, attr.name.toLowerCase())); 13744 dom.removeAllAttribs(elm); 13745 each$e(attrsToPreserve, attr => dom.setAttrib(elm, attr.name, attr.value)); 13746 if (attrsToPreserve.length > 0) { 13747 return removeResult.rename('span'); 13748 } 13749 } 13750 if (format.remove !== 'all') { 13751 removeStyles(dom, elm, format, vars, compareNode); 13752 each$7(format.attributes, (value, name) => { 13753 const { 13754 name: attrName, 13755 value: attrValue 13756 } = processFormatAttrOrStyle(name, value, vars); 13757 if (format.remove_similar || isNull(attrValue) || !isElement$6(compareNode) || isEq$2(dom.getAttrib(compareNode, attrName), attrValue)) { 13758 if (attrName === 'class') { 13759 const currentValue = dom.getAttrib(elm, attrName); 13760 if (currentValue) { 13761 let valueOut = ''; 13762 each$e(currentValue.split(/\s+/), cls => { 13763 if (/mce\-\w+/.test(cls)) { 13764 valueOut += (valueOut ? ' ' : '') + cls; 13765 } 13766 }); 13767 if (valueOut) { 13768 dom.setAttrib(elm, attrName, valueOut); 13769 return; 13770 } 13771 } 13772 } 13773 if (MCE_ATTR_RE.test(attrName)) { 13774 elm.removeAttribute('data-mce-' + attrName); 13775 } 13776 if (attrName === 'style' && matchNodeNames(['li'])(elm) && dom.getStyle(elm, 'list-style-type') === 'none') { 13777 elm.removeAttribute(attrName); 13778 dom.setStyle(elm, 'list-style-type', 'none'); 13779 return; 13780 } 13781 if (attrName === 'class') { 13782 elm.removeAttribute('className'); 13783 } 13784 elm.removeAttribute(attrName); 13785 } 13786 }); 13787 each$7(format.classes, value => { 13788 value = replaceVars(value, vars); 13789 if (!isElement$6(compareNode) || dom.hasClass(compareNode, value)) { 13790 dom.removeClass(elm, value); 13791 } 13792 }); 13793 const attrs = dom.getAttribs(elm); 13794 for (let i = 0; i < attrs.length; i++) { 13795 const attrName = attrs[i].nodeName; 13796 if (!elementUtils.isAttributeInternal(attrName)) { 13797 return removeResult.keep(); 13798 } 13799 } 13800 } 13801 if (format.remove !== 'none') { 13802 removeNode(ed, elm, format); 13803 return removeResult.removed(); 13804 } 13805 return removeResult.keep(); 13806 }; 13807 const removeFormat$1 = (ed, format, vars, node, compareNode) => removeFormatInternal(ed, format, vars, node, compareNode).fold(never, newName => { 13808 ed.dom.rename(node, newName); 13809 return true; 13810 }, always); 13811 const findFormatRoot = (editor, container, name, vars, similar) => { 13812 let formatRoot; 13813 if (container.parentNode) { 13814 each$e(getParents$2(editor.dom, container.parentNode).reverse(), parent => { 13815 if (!formatRoot && isElement$6(parent) && parent.id !== '_start' && parent.id !== '_end') { 13816 const format = matchNode(editor, parent, name, vars, similar); 13817 if (format && format.split !== false) { 13818 formatRoot = parent; 13819 } 13820 } 13821 }); 13822 } 13823 return formatRoot; 13824 }; 13825 const removeFormatFromClone = (editor, format, vars, clone) => removeFormatInternal(editor, format, vars, clone, clone).fold(constant(clone), newName => { 13826 const fragment = editor.dom.createFragment(); 13827 fragment.appendChild(clone); 13828 return editor.dom.rename(clone, newName); 13829 }, constant(null)); 13830 const wrapAndSplit = (editor, formatList, formatRoot, container, target, split, format, vars) => { 13831 var _a, _b; 13832 let lastClone; 13833 let firstClone; 13834 const dom = editor.dom; 13835 if (formatRoot) { 13836 const formatRootParent = formatRoot.parentNode; 13837 for (let parent = container.parentNode; parent && parent !== formatRootParent; parent = parent.parentNode) { 13838 let clone = dom.clone(parent, false); 13839 for (let i = 0; i < formatList.length; i++) { 13840 clone = removeFormatFromClone(editor, formatList[i], vars, clone); 13841 if (clone === null) { 13842 break; 13843 } 13844 } 13845 if (clone) { 13846 if (lastClone) { 13847 clone.appendChild(lastClone); 13848 } 13849 if (!firstClone) { 13850 firstClone = clone; 13851 } 13852 lastClone = clone; 13853 } 13854 } 13855 if (split && (!format.mixed || !dom.isBlock(formatRoot))) { 13856 container = (_a = dom.split(formatRoot, container)) !== null && _a !== void 0 ? _a : container; 13857 } 13858 if (lastClone && firstClone) { 13859 (_b = target.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(lastClone, target); 13860 firstClone.appendChild(target); 13861 if (isInlineFormat(format)) { 13862 mergeSiblings(editor, format, vars, lastClone); 13863 } 13864 } 13865 } 13866 return container; 13867 }; 13868 const remove$2 = (ed, name, vars, node, similar) => { 13869 const formatList = ed.formatter.get(name); 13870 const format = formatList[0]; 13871 const dom = ed.dom; 13872 const selection = ed.selection; 13873 const splitToFormatRoot = container => { 13874 const formatRoot = findFormatRoot(ed, container, name, vars, similar); 13875 return wrapAndSplit(ed, formatList, formatRoot, container, container, true, format, vars); 13876 }; 13877 const isRemoveBookmarkNode = node => isBookmarkNode$1(node) && isElement$6(node) && (node.id === '_start' || node.id === '_end'); 13878 const removeNodeFormat = node => exists(formatList, fmt => removeFormat$1(ed, fmt, vars, node, node)); 13879 const process = node => { 13880 const children = from(node.childNodes); 13881 const removed = removeNodeFormat(node); 13882 const currentNodeMatches = removed || exists(formatList, f => matchName(dom, node, f)); 13883 const parentNode = node.parentNode; 13884 if (!currentNodeMatches && isNonNullable(parentNode) && shouldExpandToSelector(format)) { 13885 removeNodeFormat(parentNode); 13886 } 13887 if (format.deep) { 13888 if (children.length) { 13889 for (let i = 0; i < children.length; i++) { 13890 process(children[i]); 13891 } 13892 } 13893 } 13894 const textDecorations = [ 13895 'underline', 13896 'line-through', 13897 'overline' 13898 ]; 13899 each$e(textDecorations, decoration => { 13900 if (isElement$6(node) && ed.dom.getStyle(node, 'text-decoration') === decoration && node.parentNode && getTextDecoration(dom, node.parentNode) === decoration) { 13901 removeFormat$1(ed, { 13902 deep: false, 13903 exact: true, 13904 inline: 'span', 13905 styles: { textDecoration: decoration } 13906 }, undefined, node); 13907 } 13908 }); 13909 }; 13910 const unwrap = start => { 13911 const node = dom.get(start ? '_start' : '_end'); 13912 if (node) { 13913 let out = node[start ? 'firstChild' : 'lastChild']; 13914 if (isRemoveBookmarkNode(out)) { 13915 out = out[start ? 'firstChild' : 'lastChild']; 13916 } 13917 if (isText$a(out) && out.data.length === 0) { 13918 out = start ? node.previousSibling || node.nextSibling : node.nextSibling || node.previousSibling; 13919 } 13920 dom.remove(node, true); 13921 return out; 13922 } else { 13923 return null; 13924 } 13925 }; 13926 const removeRngStyle = rng => { 13927 let startContainer; 13928 let endContainer; 13929 let expandedRng = expandRng(dom, rng, formatList, rng.collapsed); 13930 if (format.split) { 13931 expandedRng = split(expandedRng); 13932 startContainer = getContainer(ed, expandedRng, true); 13933 endContainer = getContainer(ed, expandedRng); 13934 if (startContainer !== endContainer) { 13935 startContainer = normalizeTableSelection(startContainer, true); 13936 endContainer = normalizeTableSelection(endContainer, false); 13937 if (isChildOfInlineParent(dom, startContainer, endContainer)) { 13938 const marker = Optional.from(startContainer.firstChild).getOr(startContainer); 13939 splitToFormatRoot(wrapWithSiblings(dom, marker, true, 'span', { 13940 'id': '_start', 13941 'data-mce-type': 'bookmark' 13942 })); 13943 unwrap(true); 13944 return; 13945 } 13946 if (isChildOfInlineParent(dom, endContainer, startContainer)) { 13947 const marker = Optional.from(endContainer.lastChild).getOr(endContainer); 13948 splitToFormatRoot(wrapWithSiblings(dom, marker, false, 'span', { 13949 'id': '_end', 13950 'data-mce-type': 'bookmark' 13951 })); 13952 unwrap(false); 13953 return; 13954 } 13955 startContainer = wrap$1(dom, startContainer, 'span', { 13956 'id': '_start', 13957 'data-mce-type': 'bookmark' 13958 }); 13959 endContainer = wrap$1(dom, endContainer, 'span', { 13960 'id': '_end', 13961 'data-mce-type': 'bookmark' 13962 }); 13963 const newRng = dom.createRng(); 13964 newRng.setStartAfter(startContainer); 13965 newRng.setEndBefore(endContainer); 13966 walk$3(dom, newRng, nodes => { 13967 each$e(nodes, n => { 13968 if (!isBookmarkNode$1(n) && !isBookmarkNode$1(n.parentNode)) { 13969 splitToFormatRoot(n); 13970 } 13971 }); 13972 }); 13973 splitToFormatRoot(startContainer); 13974 splitToFormatRoot(endContainer); 13975 startContainer = unwrap(true); 13976 endContainer = unwrap(); 13977 } else { 13978 startContainer = endContainer = splitToFormatRoot(startContainer); 13979 } 13980 expandedRng.startContainer = startContainer.parentNode ? startContainer.parentNode : startContainer; 13981 expandedRng.startOffset = dom.nodeIndex(startContainer); 13982 expandedRng.endContainer = endContainer.parentNode ? endContainer.parentNode : endContainer; 13983 expandedRng.endOffset = dom.nodeIndex(endContainer) + 1; 13984 } 13985 walk$3(dom, expandedRng, nodes => { 13986 each$e(nodes, process); 13987 }); 13988 }; 13989 if (node) { 13990 if (isNode(node)) { 13991 const rng = dom.createRng(); 13992 rng.setStartBefore(node); 13993 rng.setEndAfter(node); 13994 removeRngStyle(rng); 13995 } else { 13996 removeRngStyle(node); 13997 } 13998 fireFormatRemove(ed, name, node, vars); 13999 return; 14000 } 14001 if (!selection.isCollapsed() || !isInlineFormat(format) || getCellsFromEditor(ed).length) { 14002 preserveSelection(ed, () => runOnRanges(ed, removeRngStyle), startNode => isInlineFormat(format) && match$2(ed, name, vars, startNode)); 14003 ed.nodeChanged(); 14004 } else { 14005 removeCaretFormat(ed, name, vars, similar); 14006 } 14007 removeListStyleFormats(ed, name, vars); 14008 fireFormatRemove(ed, name, node, vars); 14009 }; 14010 14011 const each$6 = Tools.each; 14012 const mergeTextDecorationsAndColor = (dom, format, vars, node) => { 14013 const processTextDecorationsAndColor = n => { 14014 if (isElement$6(n) && isElement$6(n.parentNode) && isEditable$2(n)) { 14015 const parentTextDecoration = getTextDecoration(dom, n.parentNode); 14016 if (dom.getStyle(n, 'color') && parentTextDecoration) { 14017 dom.setStyle(n, 'text-decoration', parentTextDecoration); 14018 } else if (dom.getStyle(n, 'text-decoration') === parentTextDecoration) { 14019 dom.setStyle(n, 'text-decoration', null); 14020 } 14021 } 14022 }; 14023 if (format.styles && (format.styles.color || format.styles.textDecoration)) { 14024 Tools.walk(node, processTextDecorationsAndColor, 'childNodes'); 14025 processTextDecorationsAndColor(node); 14026 } 14027 }; 14028 const mergeBackgroundColorAndFontSize = (dom, format, vars, node) => { 14029 if (format.styles && format.styles.backgroundColor) { 14030 const hasFontSize = hasStyle(dom, 'fontSize'); 14031 processChildElements(node, elm => hasFontSize(elm) && isEditable$2(elm), applyStyle(dom, 'backgroundColor', replaceVars(format.styles.backgroundColor, vars))); 14032 } 14033 }; 14034 const mergeSubSup = (dom, format, vars, node) => { 14035 if (isInlineFormat(format) && (format.inline === 'sub' || format.inline === 'sup')) { 14036 const hasFontSize = hasStyle(dom, 'fontSize'); 14037 processChildElements(node, elm => hasFontSize(elm) && isEditable$2(elm), applyStyle(dom, 'fontSize', '')); 14038 const inverseTagDescendants = filter$5(dom.select(format.inline === 'sup' ? 'sub' : 'sup', node), isEditable$2); 14039 dom.remove(inverseTagDescendants, true); 14040 } 14041 }; 14042 const mergeWithChildren = (editor, formatList, vars, node) => { 14043 each$6(formatList, format => { 14044 if (isInlineFormat(format)) { 14045 each$6(editor.dom.select(format.inline, node), child => { 14046 if (isElementNode(child)) { 14047 removeFormat$1(editor, format, vars, child, format.exact ? child : null); 14048 } 14049 }); 14050 } 14051 clearChildStyles(editor.dom, format, node); 14052 }); 14053 }; 14054 const mergeWithParents = (editor, format, name, vars, node) => { 14055 const parentNode = node.parentNode; 14056 if (matchNode(editor, parentNode, name, vars)) { 14057 if (removeFormat$1(editor, format, vars, node)) { 14058 return; 14059 } 14060 } 14061 if (format.merge_with_parents && parentNode) { 14062 editor.dom.getParent(parentNode, parent => { 14063 if (matchNode(editor, parent, name, vars)) { 14064 removeFormat$1(editor, format, vars, node); 14065 return true; 14066 } else { 14067 return false; 14068 } 14069 }); 14070 } 14071 }; 14072 14073 const each$5 = Tools.each; 14074 const canFormatBR = (editor, format, node, parentName) => { 14075 if (canFormatEmptyLines(editor) && isInlineFormat(format) && node.parentNode) { 14076 const validBRParentElements = getTextRootBlockElements(editor.schema); 14077 const hasCaretNodeSibling = sibling(SugarElement.fromDom(node), sibling => isCaretNode(sibling.dom)); 14078 return hasNonNullableKey(validBRParentElements, parentName) && isEmpty$2(SugarElement.fromDom(node.parentNode), false) && !hasCaretNodeSibling; 14079 } else { 14080 return false; 14081 } 14082 }; 14083 const applyStyles = (dom, elm, format, vars) => { 14084 each$5(format.styles, (value, name) => { 14085 dom.setStyle(elm, name, replaceVars(value, vars)); 14086 }); 14087 if (format.styles) { 14088 const styleVal = dom.getAttrib(elm, 'style'); 14089 if (styleVal) { 14090 dom.setAttrib(elm, 'data-mce-style', styleVal); 14091 } 14092 } 14093 }; 14094 const applyFormat$1 = (ed, name, vars, node) => { 14095 const formatList = ed.formatter.get(name); 14096 const format = formatList[0]; 14097 const isCollapsed = !node && ed.selection.isCollapsed(); 14098 const dom = ed.dom; 14099 const selection = ed.selection; 14100 const setElementFormat = (elm, fmt = format) => { 14101 if (isFunction(fmt.onformat)) { 14102 fmt.onformat(elm, fmt, vars, node); 14103 } 14104 applyStyles(dom, elm, fmt, vars); 14105 each$5(fmt.attributes, (value, name) => { 14106 dom.setAttrib(elm, name, replaceVars(value, vars)); 14107 }); 14108 each$5(fmt.classes, value => { 14109 const newValue = replaceVars(value, vars); 14110 if (!dom.hasClass(elm, newValue)) { 14111 dom.addClass(elm, newValue); 14112 } 14113 }); 14114 }; 14115 const applyNodeStyle = (formatList, node) => { 14116 let found = false; 14117 each$5(formatList, format => { 14118 if (!isSelectorFormat(format)) { 14119 return false; 14120 } 14121 if (dom.getContentEditable(node) === 'false' && !format.ceFalseOverride) { 14122 return true; 14123 } 14124 if (isNonNullable(format.collapsed) && format.collapsed !== isCollapsed) { 14125 return true; 14126 } 14127 if (dom.is(node, format.selector) && !isCaretNode(node)) { 14128 setElementFormat(node, format); 14129 found = true; 14130 return false;
vendor: 18,703 bytes, lines 14131-14618
14131 } 14132 return true; 14133 }); 14134 return found; 14135 }; 14136 const createWrapElement = wrapName => { 14137 if (isString(wrapName)) { 14138 const wrapElm = dom.create(wrapName); 14139 setElementFormat(wrapElm); 14140 return wrapElm; 14141 } else { 14142 return null; 14143 } 14144 }; 14145 const applyRngStyle = (dom, rng, nodeSpecific) => { 14146 const newWrappers = []; 14147 let contentEditable = true; 14148 const wrapName = format.inline || format.block; 14149 const wrapElm = createWrapElement(wrapName); 14150 const isMatchingWrappingBlock = node => isWrappingBlockFormat(format) && matchNode(ed, node, name, vars); 14151 const canRenameBlock = (node, parentName, isEditableDescendant) => { 14152 const isValidBlockFormatForNode = isNonWrappingBlockFormat(format) && isTextBlock$1(ed.schema, node) && isValid(ed, parentName, wrapName); 14153 return isEditableDescendant && isValidBlockFormatForNode; 14154 }; 14155 const canWrapNode = (node, parentName, isEditableDescendant, isWrappableNoneditableElm) => { 14156 const nodeName = node.nodeName.toLowerCase(); 14157 const isValidWrapNode = isValid(ed, wrapName, nodeName) && isValid(ed, parentName, wrapName); 14158 const isZwsp$1 = !nodeSpecific && isText$a(node) && isZwsp(node.data); 14159 const isCaret = isCaretNode(node); 14160 const isCorrectFormatForNode = !isInlineFormat(format) || !dom.isBlock(node); 14161 return (isEditableDescendant || isWrappableNoneditableElm) && isValidWrapNode && !isZwsp$1 && !isCaret && isCorrectFormatForNode; 14162 }; 14163 walk$3(dom, rng, nodes => { 14164 let currentWrapElm; 14165 const process = node => { 14166 let hasContentEditableState = false; 14167 let lastContentEditable = contentEditable; 14168 let isWrappableNoneditableElm = false; 14169 const parentNode = node.parentNode; 14170 const parentName = parentNode.nodeName.toLowerCase(); 14171 const contentEditableValue = dom.getContentEditable(node); 14172 if (isNonNullable(contentEditableValue)) { 14173 lastContentEditable = contentEditable; 14174 contentEditable = contentEditableValue === 'true'; 14175 hasContentEditableState = true; 14176 isWrappableNoneditableElm = isWrappableNoneditable(ed, node); 14177 } 14178 const isEditableDescendant = contentEditable && !hasContentEditableState; 14179 if (isBr$6(node) && !canFormatBR(ed, format, node, parentName)) { 14180 currentWrapElm = null; 14181 if (isBlockFormat(format)) { 14182 dom.remove(node); 14183 } 14184 return; 14185 } 14186 if (isMatchingWrappingBlock(node)) { 14187 currentWrapElm = null; 14188 return; 14189 } 14190 if (canRenameBlock(node, parentName, isEditableDescendant)) { 14191 const elm = dom.rename(node, wrapName); 14192 setElementFormat(elm); 14193 newWrappers.push(elm); 14194 currentWrapElm = null; 14195 return; 14196 } 14197 if (isSelectorFormat(format)) { 14198 let found = applyNodeStyle(formatList, node); 14199 if (!found && isNonNullable(parentNode) && shouldExpandToSelector(format)) { 14200 found = applyNodeStyle(formatList, parentNode); 14201 } 14202 if (!isInlineFormat(format) || found) { 14203 currentWrapElm = null; 14204 return; 14205 } 14206 } 14207 if (isNonNullable(wrapElm) && canWrapNode(node, parentName, isEditableDescendant, isWrappableNoneditableElm)) { 14208 if (!currentWrapElm) { 14209 currentWrapElm = dom.clone(wrapElm, false); 14210 parentNode.insertBefore(currentWrapElm, node); 14211 newWrappers.push(currentWrapElm); 14212 } 14213 if (isWrappableNoneditableElm && hasContentEditableState) { 14214 contentEditable = lastContentEditable; 14215 } 14216 currentWrapElm.appendChild(node); 14217 } else { 14218 currentWrapElm = null; 14219 each$e(from(node.childNodes), process); 14220 if (hasContentEditableState) { 14221 contentEditable = lastContentEditable; 14222 } 14223 currentWrapElm = null; 14224 } 14225 }; 14226 each$e(nodes, process); 14227 }); 14228 if (format.links === true) { 14229 each$e(newWrappers, node => { 14230 const process = node => { 14231 if (node.nodeName === 'A') { 14232 setElementFormat(node, format); 14233 } 14234 each$e(from(node.childNodes), process); 14235 }; 14236 process(node); 14237 }); 14238 } 14239 each$e(newWrappers, node => { 14240 const getChildCount = node => { 14241 let count = 0; 14242 each$e(node.childNodes, node => { 14243 if (!isEmptyTextNode$1(node) && !isBookmarkNode$1(node)) { 14244 count++; 14245 } 14246 }); 14247 return count; 14248 }; 14249 const mergeStyles = node => { 14250 const childElement = find$2(node.childNodes, isElementNode$1).filter(child => dom.getContentEditable(child) !== 'false' && matchName(dom, child, format)); 14251 return childElement.map(child => { 14252 const clone = dom.clone(child, false); 14253 setElementFormat(clone); 14254 dom.replace(clone, node, true); 14255 dom.remove(child, true); 14256 return clone; 14257 }).getOr(node); 14258 }; 14259 const childCount = getChildCount(node); 14260 if ((newWrappers.length > 1 || !dom.isBlock(node)) && childCount === 0) { 14261 dom.remove(node, true); 14262 return; 14263 } 14264 if (isInlineFormat(format) || isBlockFormat(format) && format.wrapper) { 14265 if (!format.exact && childCount === 1) { 14266 node = mergeStyles(node); 14267 } 14268 mergeWithChildren(ed, formatList, vars, node); 14269 mergeWithParents(ed, format, name, vars, node); 14270 mergeBackgroundColorAndFontSize(dom, format, vars, node); 14271 mergeTextDecorationsAndColor(dom, format, vars, node); 14272 mergeSubSup(dom, format, vars, node); 14273 mergeSiblings(ed, format, vars, node); 14274 } 14275 }); 14276 }; 14277 const targetNode = isNode(node) ? node : selection.getNode(); 14278 if (dom.getContentEditable(targetNode) === 'false' && !isWrappableNoneditable(ed, targetNode)) { 14279 node = targetNode; 14280 applyNodeStyle(formatList, node); 14281 fireFormatApply(ed, name, node, vars); 14282 return; 14283 } 14284 if (format) { 14285 if (node) { 14286 if (isNode(node)) { 14287 if (!applyNodeStyle(formatList, node)) { 14288 const rng = dom.createRng(); 14289 rng.setStartBefore(node); 14290 rng.setEndAfter(node); 14291 applyRngStyle(dom, expandRng(dom, rng, formatList), true); 14292 } 14293 } else { 14294 applyRngStyle(dom, node, true); 14295 } 14296 } else { 14297 if (!isCollapsed || !isInlineFormat(format) || getCellsFromEditor(ed).length) { 14298 selection.setRng(normalize(selection.getRng())); 14299 preserveSelection(ed, () => { 14300 runOnRanges(ed, (selectionRng, fake) => { 14301 const expandedRng = fake ? selectionRng : expandRng(dom, selectionRng, formatList); 14302 applyRngStyle(dom, expandedRng, false); 14303 }); 14304 }, always); 14305 ed.nodeChanged(); 14306 } else { 14307 applyCaretFormat(ed, name, vars); 14308 } 14309 getExpandedListItemFormat(ed.formatter, name).each(liFmt => { 14310 each$e(getFullySelectedListItems(ed.selection), li => applyStyles(dom, li, liFmt, vars)); 14311 }); 14312 } 14313 postProcess$1(name, ed); 14314 } 14315 fireFormatApply(ed, name, node, vars); 14316 }; 14317 14318 const hasVars = value => has$2(value, 'vars'); 14319 const setup$t = (registeredFormatListeners, editor) => { 14320 registeredFormatListeners.set({}); 14321 editor.on('NodeChange', e => { 14322 updateAndFireChangeCallbacks(editor, e.element, registeredFormatListeners.get()); 14323 }); 14324 editor.on('FormatApply FormatRemove', e => { 14325 const element = Optional.from(e.node).map(nodeOrRange => isNode(nodeOrRange) ? nodeOrRange : nodeOrRange.startContainer).bind(node => isElement$6(node) ? Optional.some(node) : Optional.from(node.parentElement)).getOrThunk(() => fallbackElement(editor)); 14326 updateAndFireChangeCallbacks(editor, element, registeredFormatListeners.get()); 14327 }); 14328 }; 14329 const fallbackElement = editor => editor.selection.getStart(); 14330 const matchingNode = (editor, parents, format, similar, vars) => { 14331 const isMatchingNode = node => { 14332 const matchingFormat = editor.formatter.matchNode(node, format, vars !== null && vars !== void 0 ? vars : {}, similar); 14333 return !isUndefined(matchingFormat); 14334 }; 14335 const isUnableToMatch = node => { 14336 if (matchesUnInheritedFormatSelector(editor, node, format)) { 14337 return true; 14338 } else { 14339 if (!similar) { 14340 return isNonNullable(editor.formatter.matchNode(node, format, vars, true)); 14341 } else { 14342 return false; 14343 } 14344 } 14345 }; 14346 return findUntil$1(parents, isMatchingNode, isUnableToMatch); 14347 }; 14348 const getParents = (editor, elm) => { 14349 const element = elm !== null && elm !== void 0 ? elm : fallbackElement(editor); 14350 return filter$5(getParents$2(editor.dom, element), node => isElement$6(node) && !isBogus$2(node)); 14351 }; 14352 const updateAndFireChangeCallbacks = (editor, elm, registeredCallbacks) => { 14353 const parents = getParents(editor, elm); 14354 each$d(registeredCallbacks, (data, format) => { 14355 const runIfChanged = spec => { 14356 const match = matchingNode(editor, parents, format, spec.similar, hasVars(spec) ? spec.vars : undefined); 14357 const isSet = match.isSome(); 14358 if (spec.state.get() !== isSet) { 14359 spec.state.set(isSet); 14360 const node = match.getOr(elm); 14361 if (hasVars(spec)) { 14362 spec.callback(isSet, { 14363 node, 14364 format, 14365 parents 14366 }); 14367 } else { 14368 each$e(spec.callbacks, callback => callback(isSet, { 14369 node, 14370 format, 14371 parents 14372 })); 14373 } 14374 } 14375 }; 14376 each$e([ 14377 data.withSimilar, 14378 data.withoutSimilar 14379 ], runIfChanged); 14380 each$e(data.withVars, runIfChanged); 14381 }); 14382 }; 14383 const addListeners = (editor, registeredFormatListeners, formats, callback, similar, vars) => { 14384 const formatChangeItems = registeredFormatListeners.get(); 14385 each$e(formats.split(','), format => { 14386 const group = get$a(formatChangeItems, format).getOrThunk(() => { 14387 const base = { 14388 withSimilar: { 14389 state: Cell(false), 14390 similar: true, 14391 callbacks: [] 14392 }, 14393 withoutSimilar: { 14394 state: Cell(false), 14395 similar: false, 14396 callbacks: [] 14397 }, 14398 withVars: [] 14399 }; 14400 formatChangeItems[format] = base; 14401 return base; 14402 }); 14403 const getCurrent = () => { 14404 const parents = getParents(editor); 14405 return matchingNode(editor, parents, format, similar, vars).isSome(); 14406 }; 14407 if (isUndefined(vars)) { 14408 const toAppendTo = similar ? group.withSimilar : group.withoutSimilar; 14409 toAppendTo.callbacks.push(callback); 14410 if (toAppendTo.callbacks.length === 1) { 14411 toAppendTo.state.set(getCurrent()); 14412 } 14413 } else { 14414 group.withVars.push({ 14415 state: Cell(getCurrent()), 14416 similar, 14417 vars, 14418 callback 14419 }); 14420 } 14421 }); 14422 registeredFormatListeners.set(formatChangeItems); 14423 }; 14424 const removeListeners = (registeredFormatListeners, formats, callback) => { 14425 const formatChangeItems = registeredFormatListeners.get(); 14426 each$e(formats.split(','), format => get$a(formatChangeItems, format).each(group => { 14427 formatChangeItems[format] = { 14428 withSimilar: { 14429 ...group.withSimilar, 14430 callbacks: filter$5(group.withSimilar.callbacks, cb => cb !== callback) 14431 }, 14432 withoutSimilar: { 14433 ...group.withoutSimilar, 14434 callbacks: filter$5(group.withoutSimilar.callbacks, cb => cb !== callback) 14435 }, 14436 withVars: filter$5(group.withVars, item => item.callback !== callback) 14437 }; 14438 })); 14439 registeredFormatListeners.set(formatChangeItems); 14440 }; 14441 const formatChangedInternal = (editor, registeredFormatListeners, formats, callback, similar, vars) => { 14442 addListeners(editor, registeredFormatListeners, formats, callback, similar, vars); 14443 return { unbind: () => removeListeners(registeredFormatListeners, formats, callback) }; 14444 }; 14445 14446 const toggle = (editor, name, vars, node) => { 14447 const fmt = editor.formatter.get(name); 14448 if (fmt) { 14449 if (match$2(editor, name, vars, node) && (!('toggle' in fmt[0]) || fmt[0].toggle)) { 14450 remove$2(editor, name, vars, node); 14451 } else { 14452 applyFormat$1(editor, name, vars, node); 14453 } 14454 } 14455 }; 14456 14457 const explode$1 = Tools.explode; 14458 const create$8 = () => { 14459 const filters = {}; 14460 const addFilter = (name, callback) => { 14461 each$e(explode$1(name), name => { 14462 if (!has$2(filters, name)) { 14463 filters[name] = { 14464 name, 14465 callbacks: [] 14466 }; 14467 } 14468 filters[name].callbacks.push(callback); 14469 }); 14470 }; 14471 const getFilters = () => values(filters); 14472 const removeFilter = (name, callback) => { 14473 each$e(explode$1(name), name => { 14474 if (has$2(filters, name)) { 14475 if (isNonNullable(callback)) { 14476 const filter = filters[name]; 14477 const newCallbacks = filter$5(filter.callbacks, c => c !== callback); 14478 if (newCallbacks.length > 0) { 14479 filter.callbacks = newCallbacks; 14480 } else { 14481 delete filters[name]; 14482 } 14483 } else { 14484 delete filters[name]; 14485 } 14486 } 14487 }); 14488 }; 14489 return { 14490 addFilter, 14491 getFilters, 14492 removeFilter 14493 }; 14494 }; 14495 14496 const removeAttrs = (node, names) => { 14497 each$e(names, name => { 14498 node.attr(name, null); 14499 }); 14500 }; 14501 const addFontToSpansFilter = (domParser, styles, fontSizes) => { 14502 domParser.addNodeFilter('font', nodes => { 14503 each$e(nodes, node => { 14504 const props = styles.parse(node.attr('style')); 14505 const color = node.attr('color'); 14506 const face = node.attr('face'); 14507 const size = node.attr('size'); 14508 if (color) { 14509 props.color = color; 14510 } 14511 if (face) { 14512 props['font-family'] = face; 14513 } 14514 if (size) { 14515 toInt(size).each(num => { 14516 props['font-size'] = fontSizes[num - 1]; 14517 }); 14518 } 14519 node.name = 'span'; 14520 node.attr('style', styles.serialize(props)); 14521 removeAttrs(node, [ 14522 'color', 14523 'face', 14524 'size' 14525 ]); 14526 }); 14527 }); 14528 }; 14529 const addStrikeFilter = (domParser, schema, styles) => { 14530 domParser.addNodeFilter('strike', nodes => { 14531 const convertToSTag = schema.type !== 'html4'; 14532 each$e(nodes, node => { 14533 if (convertToSTag) { 14534 node.name = 's'; 14535 } else { 14536 const props = styles.parse(node.attr('style')); 14537 props['text-decoration'] = 'line-through'; 14538 node.name = 'span'; 14539 node.attr('style', styles.serialize(props)); 14540 } 14541 }); 14542 }); 14543 }; 14544 const addFilters = (domParser, settings, schema) => { 14545 var _a; 14546 const styles = Styles(); 14547 if (settings.convert_fonts_to_spans) { 14548 addFontToSpansFilter(domParser, styles, Tools.explode((_a = settings.font_size_legacy_values) !== null && _a !== void 0 ? _a : '')); 14549 } 14550 addStrikeFilter(domParser, schema, styles); 14551 }; 14552 const register$5 = (domParser, settings, schema) => { 14553 if (settings.inline_styles) { 14554 addFilters(domParser, settings, schema); 14555 } 14556 }; 14557 14558 const blobUriToBlob = url => fetch(url).then(res => res.ok ? res.blob() : Promise.reject()).catch(() => Promise.reject({ 14559 message: `Cannot convert ${ url } to Blob. Resource might not exist or is inaccessible.`, 14560 uriType: 'blob' 14561 })); 14562 const extractBase64Data = data => { 14563 const matches = /([a-z0-9+\/=\s]+)/i.exec(data); 14564 return matches ? matches[1] : ''; 14565 }; 14566 const parseDataUri = uri => { 14567 const [type, ...rest] = uri.split(','); 14568 const data = rest.join(','); 14569 const matches = /data:([^/]+\/[^;]+)(;.+)?/.exec(type); 14570 if (matches) { 14571 const base64Encoded = matches[2] === ';base64'; 14572 const extractedData = base64Encoded ? extractBase64Data(data) : decodeURIComponent(data); 14573 return Optional.some({ 14574 type: matches[1], 14575 data: extractedData, 14576 base64Encoded 14577 }); 14578 } else { 14579 return Optional.none(); 14580 } 14581 }; 14582 const buildBlob = (type, data, base64Encoded = true) => { 14583 let str = data; 14584 if (base64Encoded) { 14585 try { 14586 str = atob(data); 14587 } catch (e) { 14588 return Optional.none(); 14589 } 14590 } 14591 const arr = new Uint8Array(str.length); 14592 for (let i = 0; i < arr.length; i++) { 14593 arr[i] = str.charCodeAt(i); 14594 } 14595 return Optional.some(new Blob([arr], { type })); 14596 }; 14597 const dataUriToBlob = uri => { 14598 return new Promise((resolve, reject) => { 14599 parseDataUri(uri).bind(({type, data, base64Encoded}) => buildBlob(type, data, base64Encoded)).fold(() => reject('Invalid data URI'), resolve); 14600 }); 14601 }; 14602 const uriToBlob = url => { 14603 if (startsWith(url, 'blob:')) { 14604 return blobUriToBlob(url); 14605 } else if (startsWith(url, 'data:')) { 14606 return dataUriToBlob(url); 14607 } else { 14608 return Promise.reject('Unknown URI format'); 14609 } 14610 }; 14611 const blobToDataUri = blob => { 14612 return new Promise((resolve, reject) => { 14613 const reader = new FileReader(); 14614 reader.onloadend = () => { 14615 resolve(reader.result); 14616 }; 14617 reader.onerror = () => { 14618 var _a;
vendor: 5,071 bytes, lines 14619-14739
14619 reject((_a = reader.error) === null || _a === void 0 ? void 0 : _a.message); 14620 }; 14621 reader.readAsDataURL(blob); 14622 }); 14623 }; 14624 14625 let count$1 = 0; 14626 const uniqueId$1 = prefix => { 14627 return (prefix || 'blobid') + count$1++; 14628 }; 14629 const processDataUri = (dataUri, base64Only, generateBlobInfo) => { 14630 return parseDataUri(dataUri).bind(({data, type, base64Encoded}) => { 14631 if (base64Only && !base64Encoded) { 14632 return Optional.none(); 14633 } else { 14634 const base64 = base64Encoded ? data : btoa(data); 14635 return generateBlobInfo(base64, type); 14636 } 14637 }); 14638 }; 14639 const createBlobInfo$1 = (blobCache, blob, base64) => { 14640 const blobInfo = blobCache.create(uniqueId$1(), blob, base64); 14641 blobCache.add(blobInfo); 14642 return blobInfo; 14643 }; 14644 const dataUriToBlobInfo = (blobCache, dataUri, base64Only = false) => { 14645 return processDataUri(dataUri, base64Only, (base64, type) => Optional.from(blobCache.getByData(base64, type)).orThunk(() => buildBlob(type, base64).map(blob => createBlobInfo$1(blobCache, blob, base64)))); 14646 }; 14647 const imageToBlobInfo = (blobCache, imageSrc) => { 14648 const invalidDataUri = () => Promise.reject('Invalid data URI'); 14649 if (startsWith(imageSrc, 'blob:')) { 14650 const blobInfo = blobCache.getByUri(imageSrc); 14651 if (isNonNullable(blobInfo)) { 14652 return Promise.resolve(blobInfo); 14653 } else { 14654 return uriToBlob(imageSrc).then(blob => { 14655 return blobToDataUri(blob).then(dataUri => { 14656 return processDataUri(dataUri, false, base64 => { 14657 return Optional.some(createBlobInfo$1(blobCache, blob, base64)); 14658 }).getOrThunk(invalidDataUri); 14659 }); 14660 }); 14661 } 14662 } else if (startsWith(imageSrc, 'data:')) { 14663 return dataUriToBlobInfo(blobCache, imageSrc).fold(invalidDataUri, blobInfo => Promise.resolve(blobInfo)); 14664 } else { 14665 return Promise.reject('Unknown image data format'); 14666 } 14667 }; 14668 14669 const isBogusImage = img => isNonNullable(img.attr('data-mce-bogus')); 14670 const isInternalImageSource = img => img.attr('src') === Env.transparentSrc || isNonNullable(img.attr('data-mce-placeholder')); 14671 const registerBase64ImageFilter = (parser, settings) => { 14672 const {blob_cache: blobCache} = settings; 14673 if (blobCache) { 14674 const processImage = img => { 14675 const inputSrc = img.attr('src'); 14676 if (isInternalImageSource(img) || isBogusImage(img) || isNullable(inputSrc)) { 14677 return; 14678 } 14679 dataUriToBlobInfo(blobCache, inputSrc, true).each(blobInfo => { 14680 img.attr('src', blobInfo.blobUri()); 14681 }); 14682 }; 14683 parser.addAttributeFilter('src', nodes => each$e(nodes, processImage)); 14684 } 14685 }; 14686 const register$4 = (parser, settings) => { 14687 const schema = parser.schema; 14688 if (settings.remove_trailing_brs) { 14689 parser.addNodeFilter('br', (nodes, _, args) => { 14690 const blockElements = Tools.extend({}, schema.getBlockElements()); 14691 const nonEmptyElements = schema.getNonEmptyElements(); 14692 const whitespaceElements = schema.getWhitespaceElements(); 14693 blockElements.body = 1; 14694 const isBlock = node => node.name in blockElements && isTransparentAstInline(schema, node); 14695 for (let i = 0, l = nodes.length; i < l; i++) { 14696 let node = nodes[i]; 14697 let parent = node.parent; 14698 if (parent && blockElements[parent.name] && node === parent.lastChild) { 14699 let prev = node.prev; 14700 while (prev) { 14701 const prevName = prev.name; 14702 if (prevName !== 'span' || prev.attr('data-mce-type') !== 'bookmark') { 14703 if (prevName === 'br') { 14704 node = null; 14705 } 14706 break; 14707 } 14708 prev = prev.prev; 14709 } 14710 if (node) { 14711 node.remove(); 14712 if (isEmpty(schema, nonEmptyElements, whitespaceElements, parent)) { 14713 const elementRule = schema.getElementRule(parent.name); 14714 if (elementRule) { 14715 if (elementRule.removeEmpty) { 14716 parent.remove(); 14717 } else if (elementRule.paddEmpty) { 14718 paddEmptyNode(args, isBlock, parent); 14719 } 14720 } 14721 } 14722 } 14723 } else { 14724 let lastParent = node; 14725 while (parent && parent.firstChild === lastParent && parent.lastChild === lastParent) { 14726 lastParent = parent; 14727 if (blockElements[parent.name]) { 14728 break; 14729 } 14730 parent = parent.parent; 14731 } 14732 if (lastParent === parent) { 14733 const textNode = new AstNode('#text', 3); 14734 textNode.value = nbsp; 14735 node.replace(textNode); 14736 } 14737 } 14738 } 14739 }
vendor: 14,430 bytes, lines 14739-15302
14739); 14740 } 14741 parser.addAttributeFilter('href', nodes => { 14742 let i = nodes.length; 14743 const appendRel = rel => { 14744 const parts = rel.split(' ').filter(p => p.length > 0); 14745 return parts.concat(['noopener']).sort().join(' '); 14746 }; 14747 const addNoOpener = rel => { 14748 const newRel = rel ? Tools.trim(rel) : ''; 14749 if (!/\b(noopener)\b/g.test(newRel)) { 14750 return appendRel(newRel); 14751 } else { 14752 return newRel; 14753 } 14754 }; 14755 if (!settings.allow_unsafe_link_target) { 14756 while (i--) { 14757 const node = nodes[i]; 14758 if (node.name === 'a' && node.attr('target') === '_blank') { 14759 node.attr('rel', addNoOpener(node.attr('rel'))); 14760 } 14761 } 14762 } 14763 }); 14764 if (!settings.allow_html_in_named_anchor) { 14765 parser.addAttributeFilter('id,name', nodes => { 14766 let i = nodes.length, sibling, prevSibling, parent, node; 14767 while (i--) { 14768 node = nodes[i]; 14769 if (node.name === 'a' && node.firstChild && !node.attr('href')) { 14770 parent = node.parent; 14771 sibling = node.lastChild; 14772 while (sibling && parent) { 14773 prevSibling = sibling.prev; 14774 parent.insert(sibling, node); 14775 sibling = prevSibling; 14776 } 14777 } 14778 } 14779 }); 14780 } 14781 if (settings.fix_list_elements) { 14782 parser.addNodeFilter('ul,ol', nodes => { 14783 let i = nodes.length, node, parentNode; 14784 while (i--) { 14785 node = nodes[i]; 14786 parentNode = node.parent; 14787 if (parentNode && (parentNode.name === 'ul' || parentNode.name === 'ol')) { 14788 if (node.prev && node.prev.name === 'li') { 14789 node.prev.append(node); 14790 } else { 14791 const li = new AstNode('li', 1); 14792 li.attr('style', 'list-style-type: none'); 14793 node.wrap(li); 14794 } 14795 } 14796 } 14797 }); 14798 } 14799 const validClasses = schema.getValidClasses(); 14800 if (settings.validate && validClasses) { 14801 parser.addAttributeFilter('class', nodes => { 14802 var _a; 14803 let i = nodes.length; 14804 while (i--) { 14805 const node = nodes[i]; 14806 const clazz = (_a = node.attr('class')) !== null && _a !== void 0 ? _a : ''; 14807 const classList = Tools.explode(clazz, ' '); 14808 let classValue = ''; 14809 for (let ci = 0; ci < classList.length; ci++) { 14810 const className = classList[ci]; 14811 let valid = false; 14812 let validClassesMap = validClasses['*']; 14813 if (validClassesMap && validClassesMap[className]) { 14814 valid = true; 14815 } 14816 validClassesMap = validClasses[node.name]; 14817 if (!valid && validClassesMap && validClassesMap[className]) { 14818 valid = true; 14819 } 14820 if (valid) { 14821 if (classValue) { 14822 classValue += ' '; 14823 } 14824 classValue += className; 14825 } 14826 } 14827 if (!classValue.length) { 14828 classValue = null; 14829 } 14830 node.attr('class', classValue); 14831 } 14832 }); 14833 } 14834 registerBase64ImageFilter(parser, settings); 14835 }; 14836 14837 function _typeof(obj) { 14838 '@babel/helpers - typeof'; 14839 return _typeof = 'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator ? function (obj) { 14840 return typeof obj; 14841 } : function (obj) { 14842 return obj && 'function' == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj; 14843 }, _typeof(obj); 14844 } 14845 function _setPrototypeOf(o, p) { 14846 _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { 14847 o.__proto__ = p; 14848 return o; 14849 }; 14850 return _setPrototypeOf(o, p); 14851 } 14852 function _isNativeReflectConstruct() { 14853 if (typeof Reflect === 'undefined' || !Reflect.construct) 14854 return false; 14855 if (Reflect.construct.sham) 14856 return false; 14857 if (typeof Proxy === 'function') 14858 return true; 14859 try { 14860 Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () { 14861 })); 14862 return true; 14863 } catch (e) { 14864 return false; 14865 } 14866 } 14867 function _construct(Parent, args, Class) { 14868 if (_isNativeReflectConstruct()) { 14869 _construct = Reflect.construct; 14870 } else { 14871 _construct = function _construct(Parent, args, Class) { 14872 var a = [null]; 14873 a.push.apply(a, args); 14874 var Constructor = Function.bind.apply(Parent, a); 14875 var instance = new Constructor(); 14876 if (Class) 14877 _setPrototypeOf(instance, Class.prototype); 14878 return instance; 14879 }; 14880 } 14881 return _construct.apply(null, arguments); 14882 } 14883 function _toConsumableArray(arr) { 14884 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); 14885 } 14886 function _arrayWithoutHoles(arr) { 14887 if (Array.isArray(arr)) 14888 return _arrayLikeToArray(arr); 14889 } 14890 function _iterableToArray(iter) { 14891 if (typeof Symbol !== 'undefined' && iter[Symbol.iterator] != null || iter['@@iterator'] != null) 14892 return Array.from(iter); 14893 } 14894 function _unsupportedIterableToArray(o, minLen) { 14895 if (!o) 14896 return; 14897 if (typeof o === 'string') 14898 return _arrayLikeToArray(o, minLen); 14899 var n = Object.prototype.toString.call(o).slice(8, -1); 14900 if (n === 'Object' && o.constructor) 14901 n = o.constructor.name; 14902 if (n === 'Map' || n === 'Set') 14903 return Array.from(o); 14904 if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) 14905 return _arrayLikeToArray(o, minLen); 14906 } 14907 function _arrayLikeToArray(arr, len) { 14908 if (len == null || len > arr.length) 14909 len = arr.length; 14910 for (var i = 0, arr2 = new Array(len); i < len; i++) 14911 arr2[i] = arr[i]; 14912 return arr2; 14913 } 14914 function _nonIterableSpread() { 14915 throw new TypeError('Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.'); 14916 } 14917 var hasOwnProperty = Object.hasOwnProperty, setPrototypeOf = Object.setPrototypeOf, isFrozen = Object.isFrozen, getPrototypeOf = Object.getPrototypeOf, getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; 14918 var freeze = Object.freeze, seal = Object.seal, create$7 = Object.create; 14919 var _ref = typeof Reflect !== 'undefined' && Reflect, apply = _ref.apply, construct = _ref.construct; 14920 if (!apply) { 14921 apply = function apply(fun, thisValue, args) { 14922 return fun.apply(thisValue, args); 14923 }; 14924 } 14925 if (!freeze) { 14926 freeze = function freeze(x) { 14927 return x; 14928 }; 14929 } 14930 if (!seal) { 14931 seal = function seal(x) { 14932 return x; 14933 }; 14934 } 14935 if (!construct) { 14936 construct = function construct(Func, args) { 14937 return _construct(Func, _toConsumableArray(args)); 14938 }; 14939 } 14940 var arrayForEach = unapply(Array.prototype.forEach); 14941 var arrayPop = unapply(Array.prototype.pop); 14942 var arrayPush = unapply(Array.prototype.push); 14943 var stringToLowerCase = unapply(String.prototype.toLowerCase); 14944 var stringMatch = unapply(String.prototype.match); 14945 var stringReplace = unapply(String.prototype.replace); 14946 var stringIndexOf = unapply(String.prototype.indexOf); 14947 var stringTrim = unapply(String.prototype.trim); 14948 var regExpTest = unapply(RegExp.prototype.test); 14949 var typeErrorCreate = unconstruct(TypeError); 14950 function unapply(func) { 14951 return function (thisArg) { 14952 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 14953 args[_key - 1] = arguments[_key]; 14954 } 14955 return apply(func, thisArg, args); 14956 }; 14957 } 14958 function unconstruct(func) { 14959 return function () { 14960 for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 14961 args[_key2] = arguments[_key2]; 14962 } 14963 return construct(func, args); 14964 }; 14965 } 14966 function addToSet(set, array) { 14967 if (setPrototypeOf) { 14968 setPrototypeOf(set, null); 14969 } 14970 var l = array.length; 14971 while (l--) { 14972 var element = array[l]; 14973 if (typeof element === 'string') { 14974 var lcElement = stringToLowerCase(element); 14975 if (lcElement !== element) { 14976 if (!isFrozen(array)) { 14977 array[l] = lcElement; 14978 } 14979 element = lcElement; 14980 } 14981 } 14982 set[element] = true; 14983 } 14984 return set; 14985 } 14986 function clone(object) { 14987 var newObject = create$7(null); 14988 var property; 14989 for (property in object) { 14990 if (apply(hasOwnProperty, object, [property])) { 14991 newObject[property] = object[property]; 14992 } 14993 } 14994 return newObject; 14995 } 14996 function lookupGetter(object, prop) { 14997 while (object !== null) { 14998 var desc = getOwnPropertyDescriptor(object, prop); 14999 if (desc) { 15000 if (desc.get) { 15001 return unapply(desc.get); 15002 } 15003 if (typeof desc.value === 'function') { 15004 return unapply(desc.value); 15005 } 15006 } 15007 object = getPrototypeOf(object); 15008 } 15009 function fallbackValue(element) { 15010 console.warn('fallback value for', element); 15011 return null; 15012 } 15013 return fallbackValue; 15014 } 15015 var html$1 = freeze([ 15016 'a', 15017 'abbr', 15018 'acronym', 15019 'address', 15020 'area', 15021 'article', 15022 'aside', 15023 'audio', 15024 'b', 15025 'bdi', 15026 'bdo', 15027 'big', 15028 'blink', 15029 'blockquote', 15030 'body', 15031 'br', 15032 'button', 15033 'canvas', 15034 'caption', 15035 'center', 15036 'cite', 15037 'code', 15038 'col', 15039 'colgroup', 15040 'content', 15041 'data', 15042 'datalist', 15043 'dd', 15044 'decorator', 15045 'del', 15046 'details', 15047 'dfn', 15048 'dialog', 15049 'dir', 15050 'div', 15051 'dl', 15052 'dt', 15053 'element', 15054 'em', 15055 'fieldset', 15056 'figcaption', 15057 'figure', 15058 'font', 15059 'footer', 15060 'form', 15061 'h1', 15062 'h2', 15063 'h3', 15064 'h4', 15065 'h5', 15066 'h6', 15067 'head', 15068 'header', 15069 'hgroup', 15070 'hr', 15071 'html', 15072 'i', 15073 'img', 15074 'input', 15075 'ins', 15076 'kbd', 15077 'label', 15078 'legend', 15079 'li', 15080 'main', 15081 'map', 15082 'mark', 15083 'marquee', 15084 'menu', 15085 'menuitem', 15086 'meter', 15087 'nav', 15088 'nobr', 15089 'ol', 15090 'optgroup', 15091 'option', 15092 'output', 15093 'p', 15094 'picture', 15095 'pre', 15096 'progress', 15097 'q', 15098 'rp', 15099 'rt', 15100 'ruby', 15101 's', 15102 'samp', 15103 'section', 15104 'select', 15105 'shadow', 15106 'small', 15107 'source', 15108 'spacer', 15109 'span', 15110 'strike', 15111 'strong', 15112 'style', 15113 'sub', 15114 'summary', 15115 'sup', 15116 'table', 15117 'tbody', 15118 'td', 15119 'template', 15120 'textarea', 15121 'tfoot', 15122 'th', 15123 'thead', 15124 'time', 15125 'tr', 15126 'track', 15127 'tt', 15128 'u', 15129 'ul', 15130 'var', 15131 'video', 15132 'wbr' 15133 ]); 15134 var svg$1 = freeze([ 15135 'svg', 15136 'a', 15137 'altglyph', 15138 'altglyphdef', 15139 'altglyphitem', 15140 'animatecolor', 15141 'animatemotion', 15142 'animatetransform', 15143 'circle', 15144 'clippath', 15145 'defs', 15146 'desc', 15147 'ellipse', 15148 'filter', 15149 'font', 15150 'g', 15151 'glyph', 15152 'glyphref', 15153 'hkern', 15154 'image', 15155 'line', 15156 'lineargradient', 15157 'marker', 15158 'mask', 15159 'metadata', 15160 'mpath', 15161 'path', 15162 'pattern', 15163 'polygon', 15164 'polyline', 15165 'radialgradient', 15166 'rect', 15167 'stop', 15168 'style', 15169 'switch', 15170 'symbol', 15171 'text', 15172 'textpath', 15173 'title', 15174 'tref', 15175 'tspan', 15176 'view', 15177 'vkern' 15178 ]); 15179 var svgFilters = freeze([ 15180 'feBlend', 15181 'feColorMatrix', 15182 'feComponentTransfer', 15183 'feComposite', 15184 'feConvolveMatrix', 15185 'feDiffuseLighting', 15186 'feDisplacementMap', 15187 'feDistantLight', 15188 'feFlood', 15189 'feFuncA', 15190 'feFuncB', 15191 'feFuncG', 15192 'feFuncR', 15193 'feGaussianBlur', 15194 'feImage', 15195 'feMerge', 15196 'feMergeNode', 15197 'feMorphology', 15198 'feOffset', 15199 'fePointLight', 15200 'feSpecularLighting', 15201 'feSpotLight', 15202 'feTile', 15203 'feTurbulence' 15204 ]); 15205 var svgDisallowed = freeze([ 15206 'animate', 15207 'color-profile', 15208 'cursor', 15209 'discard', 15210 'fedropshadow', 15211 'font-face', 15212 'font-face-format', 15213 'font-face-name', 15214 'font-face-src', 15215 'font-face-uri', 15216 'foreignobject', 15217 'hatch', 15218 'hatchpath', 15219 'mesh', 15220 'meshgradient', 15221 'meshpatch', 15222 'meshrow', 15223 'missing-glyph', 15224 'script', 15225 'set', 15226 'solidcolor', 15227 'unknown', 15228 'use' 15229 ]); 15230 var mathMl$1 = freeze([ 15231 'math', 15232 'menclose', 15233 'merror', 15234 'mfenced', 15235 'mfrac', 15236 'mglyph', 15237 'mi', 15238 'mlabeledtr', 15239 'mmultiscripts', 15240 'mn', 15241 'mo', 15242 'mover', 15243 'mpadded', 15244 'mphantom', 15245 'mroot', 15246 'mrow', 15247 'ms', 15248 'mspace', 15249 'msqrt', 15250 'mstyle', 15251 'msub', 15252 'msup', 15253 'msubsup', 15254 'mtable', 15255 'mtd', 15256 'mtext', 15257 'mtr', 15258 'munder', 15259 'munderover' 15260 ]); 15261 var mathMlDisallowed = freeze([ 15262 'maction', 15263 'maligngroup', 15264 'malignmark', 15265 'mlongdiv', 15266 'mscarries', 15267 'mscarry', 15268 'msgroup', 15269 'mstack', 15270 'msline', 15271 'msrow', 15272 'semantics', 15273 'annotation', 15274 'annotation-xml', 15275 'mprescripts', 15276 'none' 15277 ]); 15278 var text = freeze(['#text']); 15279 var html = freeze([ 15280 'accept', 15281 'action', 15282 'align', 15283 'alt', 15284 'autocapitalize', 15285 'autocomplete', 15286 'autopictureinpicture', 15287 'autoplay', 15288 'background', 15289 'bgcolor', 15290 'border', 15291 'capture', 15292 'cellpadding', 15293 'cellspacing', 15294 'checked', 15295 'cite', 15296 'class', 15297 'clear', 15298 'color', 15299 'cols', 15300 'colspan', 15301 'controls', 15302 'controlslist',
vendor: 37,839 bytes, lines 15303-16400
15303 'coords', 15304 'crossorigin', 15305 'datetime', 15306 'decoding', 15307 'default', 15308 'dir', 15309 'disabled', 15310 'disablepictureinpicture', 15311 'disableremoteplayback', 15312 'download', 15313 'draggable', 15314 'enctype', 15315 'enterkeyhint', 15316 'face', 15317 'for', 15318 'headers', 15319 'height', 15320 'hidden', 15321 'high', 15322 'href', 15323 'hreflang', 15324 'id', 15325 'inputmode', 15326 'integrity', 15327 'ismap', 15328 'kind', 15329 'label', 15330 'lang', 15331 'list', 15332 'loading', 15333 'loop', 15334 'low', 15335 'max', 15336 'maxlength', 15337 'media', 15338 'method', 15339 'min', 15340 'minlength', 15341 'multiple', 15342 'muted', 15343 'name', 15344 'nonce', 15345 'noshade', 15346 'novalidate', 15347 'nowrap', 15348 'open', 15349 'optimum', 15350 'pattern', 15351 'placeholder', 15352 'playsinline', 15353 'poster', 15354 'preload', 15355 'pubdate', 15356 'radiogroup', 15357 'readonly', 15358 'rel', 15359 'required', 15360 'rev', 15361 'reversed', 15362 'role', 15363 'rows', 15364 'rowspan', 15365 'spellcheck', 15366 'scope', 15367 'selected', 15368 'shape', 15369 'size', 15370 'sizes', 15371 'span', 15372 'srclang', 15373 'start', 15374 'src', 15375 'srcset', 15376 'step', 15377 'style', 15378 'summary', 15379 'tabindex', 15380 'title', 15381 'translate', 15382 'type', 15383 'usemap', 15384 'valign', 15385 'value', 15386 'width', 15387 'xmlns', 15388 'slot' 15389 ]); 15390 var svg = freeze([ 15391 'accent-height', 15392 'accumulate', 15393 'additive', 15394 'alignment-baseline', 15395 'ascent', 15396 'attributename', 15397 'attributetype', 15398 'azimuth', 15399 'basefrequency', 15400 'baseline-shift', 15401 'begin', 15402 'bias', 15403 'by', 15404 'class', 15405 'clip', 15406 'clippathunits', 15407 'clip-path', 15408 'clip-rule', 15409 'color', 15410 'color-interpolation', 15411 'color-interpolation-filters', 15412 'color-profile', 15413 'color-rendering', 15414 'cx', 15415 'cy', 15416 'd', 15417 'dx', 15418 'dy', 15419 'diffuseconstant', 15420 'direction', 15421 'display', 15422 'divisor', 15423 'dur', 15424 'edgemode', 15425 'elevation', 15426 'end', 15427 'fill', 15428 'fill-opacity', 15429 'fill-rule', 15430 'filter', 15431 'filterunits', 15432 'flood-color', 15433 'flood-opacity', 15434 'font-family', 15435 'font-size', 15436 'font-size-adjust', 15437 'font-stretch', 15438 'font-style', 15439 'font-variant', 15440 'font-weight', 15441 'fx', 15442 'fy', 15443 'g1', 15444 'g2', 15445 'glyph-name', 15446 'glyphref', 15447 'gradientunits', 15448 'gradienttransform', 15449 'height', 15450 'href', 15451 'id', 15452 'image-rendering', 15453 'in', 15454 'in2', 15455 'k', 15456 'k1', 15457 'k2', 15458 'k3', 15459 'k4', 15460 'kerning', 15461 'keypoints', 15462 'keysplines', 15463 'keytimes', 15464 'lang', 15465 'lengthadjust', 15466 'letter-spacing', 15467 'kernelmatrix', 15468 'kernelunitlength', 15469 'lighting-color', 15470 'local', 15471 'marker-end', 15472 'marker-mid', 15473 'marker-start', 15474 'markerheight', 15475 'markerunits', 15476 'markerwidth', 15477 'maskcontentunits', 15478 'maskunits', 15479 'max', 15480 'mask', 15481 'media', 15482 'method', 15483 'mode', 15484 'min', 15485 'name', 15486 'numoctaves', 15487 'offset', 15488 'operator', 15489 'opacity', 15490 'order', 15491 'orient', 15492 'orientation', 15493 'origin', 15494 'overflow', 15495 'paint-order', 15496 'path', 15497 'pathlength', 15498 'patterncontentunits', 15499 'patterntransform', 15500 'patternunits', 15501 'points', 15502 'preservealpha', 15503 'preserveaspectratio', 15504 'primitiveunits', 15505 'r', 15506 'rx', 15507 'ry', 15508 'radius', 15509 'refx', 15510 'refy', 15511 'repeatcount', 15512 'repeatdur', 15513 'restart', 15514 'result', 15515 'rotate', 15516 'scale', 15517 'seed', 15518 'shape-rendering', 15519 'specularconstant', 15520 'specularexponent', 15521 'spreadmethod', 15522 'startoffset', 15523 'stddeviation', 15524 'stitchtiles', 15525 'stop-color', 15526 'stop-opacity', 15527 'stroke-dasharray', 15528 'stroke-dashoffset', 15529 'stroke-linecap', 15530 'stroke-linejoin', 15531 'stroke-miterlimit', 15532 'stroke-opacity', 15533 'stroke', 15534 'stroke-width', 15535 'style', 15536 'surfacescale', 15537 'systemlanguage', 15538 'tabindex', 15539 'targetx', 15540 'targety', 15541 'transform', 15542 'transform-origin', 15543 'text-anchor', 15544 'text-decoration', 15545 'text-rendering', 15546 'textlength', 15547 'type', 15548 'u1', 15549 'u2', 15550 'unicode', 15551 'values', 15552 'viewbox', 15553 'visibility', 15554 'version', 15555 'vert-adv-y', 15556 'vert-origin-x', 15557 'vert-origin-y', 15558 'width', 15559 'word-spacing', 15560 'wrap', 15561 'writing-mode', 15562 'xchannelselector', 15563 'ychannelselector', 15564 'x', 15565 'x1', 15566 'x2', 15567 'xmlns', 15568 'y', 15569 'y1', 15570 'y2', 15571 'z', 15572 'zoomandpan' 15573 ]); 15574 var mathMl = freeze([ 15575 'accent', 15576 'accentunder', 15577 'align', 15578 'bevelled', 15579 'close', 15580 'columnsalign', 15581 'columnlines', 15582 'columnspan', 15583 'denomalign', 15584 'depth', 15585 'dir', 15586 'display', 15587 'displaystyle', 15588 'encoding', 15589 'fence', 15590 'frame', 15591 'height', 15592 'href', 15593 'id', 15594 'largeop', 15595 'length', 15596 'linethickness', 15597 'lspace', 15598 'lquote', 15599 'mathbackground', 15600 'mathcolor', 15601 'mathsize', 15602 'mathvariant', 15603 'maxsize', 15604 'minsize', 15605 'movablelimits', 15606 'notation', 15607 'numalign', 15608 'open', 15609 'rowalign', 15610 'rowlines', 15611 'rowspacing', 15612 'rowspan', 15613 'rspace', 15614 'rquote', 15615 'scriptlevel', 15616 'scriptminsize', 15617 'scriptsizemultiplier', 15618 'selection', 15619 'separator', 15620 'separators', 15621 'stretchy', 15622 'subscriptshift', 15623 'supscriptshift', 15624 'symmetric', 15625 'voffset', 15626 'width', 15627 'xmlns' 15628 ]); 15629 var xml = freeze([ 15630 'xlink:href', 15631 'xml:id', 15632 'xlink:title', 15633 'xml:space', 15634 'xmlns:xlink' 15635 ]); 15636 var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); 15637 var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm); 15638 var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); 15639 var ARIA_ATTR = seal(/^aria-[\-\w]+$/); 15640 var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i); 15641 var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); 15642 var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g); 15643 var DOCTYPE_NAME = seal(/^html$/i); 15644 var getGlobal = function getGlobal() { 15645 return typeof window === 'undefined' ? null : window; 15646 }; 15647 var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) { 15648 if (_typeof(trustedTypes) !== 'object' || typeof trustedTypes.createPolicy !== 'function') { 15649 return null; 15650 } 15651 var suffix = null; 15652 var ATTR_NAME = 'data-tt-policy-suffix'; 15653 if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) { 15654 suffix = document.currentScript.getAttribute(ATTR_NAME); 15655 } 15656 var policyName = 'dompurify' + (suffix ? '#' + suffix : ''); 15657 try { 15658 return trustedTypes.createPolicy(policyName, { 15659 createHTML: function createHTML(html) { 15660 return html; 15661 } 15662 }); 15663 } catch (_) { 15664 console.warn('TrustedTypes policy ' + policyName + ' could not be created.'); 15665 return null; 15666 } 15667 }; 15668 function createDOMPurify() { 15669 var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal(); 15670 var DOMPurify = function DOMPurify(root) { 15671 return createDOMPurify(root); 15672 }; 15673 DOMPurify.version = '2.3.8'; 15674 DOMPurify.removed = []; 15675 if (!window || !window.document || window.document.nodeType !== 9) { 15676 DOMPurify.isSupported = false; 15677 return DOMPurify; 15678 } 15679 var originalDocument = window.document; 15680 var document = window.document; 15681 var DocumentFragment = window.DocumentFragment, HTMLTemplateElement = window.HTMLTemplateElement, Node = window.Node, Element = window.Element, NodeFilter = window.NodeFilter, _window$NamedNodeMap = window.NamedNodeMap, NamedNodeMap = _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap, HTMLFormElement = window.HTMLFormElement, DOMParser = window.DOMParser, trustedTypes = window.trustedTypes; 15682 var ElementPrototype = Element.prototype; 15683 var cloneNode = lookupGetter(ElementPrototype, 'cloneNode'); 15684 var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling'); 15685 var getChildNodes = lookupGetter(ElementPrototype, 'childNodes'); 15686 var getParentNode = lookupGetter(ElementPrototype, 'parentNode'); 15687 if (typeof HTMLTemplateElement === 'function') { 15688 var template = document.createElement('template'); 15689 if (template.content && template.content.ownerDocument) { 15690 document = template.content.ownerDocument; 15691 } 15692 } 15693 var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument); 15694 var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : ''; 15695 var _document = document, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName; 15696 var importNode = originalDocument.importNode; 15697 var documentMode = {}; 15698 try { 15699 documentMode = clone(document).documentMode ? document.documentMode : {}; 15700 } catch (_) { 15701 } 15702 var hooks = {}; 15703 DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9; 15704 var MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE; 15705 var IS_ALLOWED_URI$1 = IS_ALLOWED_URI; 15706 var ALLOWED_TAGS = null; 15707 var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text))); 15708 var ALLOWED_ATTR = null; 15709 var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml))); 15710 var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, { 15711 tagNameCheck: { 15712 writable: true, 15713 configurable: false, 15714 enumerable: true, 15715 value: null 15716 }, 15717 attributeNameCheck: { 15718 writable: true, 15719 configurable: false, 15720 enumerable: true, 15721 value: null 15722 }, 15723 allowCustomizedBuiltInElements: { 15724 writable: true, 15725 configurable: false, 15726 enumerable: true, 15727 value: false 15728 } 15729 })); 15730 var FORBID_TAGS = null; 15731 var FORBID_ATTR = null; 15732 var ALLOW_ARIA_ATTR = true; 15733 var ALLOW_DATA_ATTR = true; 15734 var ALLOW_UNKNOWN_PROTOCOLS = false; 15735 var SAFE_FOR_TEMPLATES = false; 15736 var WHOLE_DOCUMENT = false; 15737 var SET_CONFIG = false; 15738 var FORCE_BODY = false; 15739 var RETURN_DOM = false; 15740 var RETURN_DOM_FRAGMENT = false; 15741 var RETURN_TRUSTED_TYPE = false; 15742 var SANITIZE_DOM = true; 15743 var KEEP_CONTENT = true; 15744 var IN_PLACE = false; 15745 var USE_PROFILES = {}; 15746 var FORBID_CONTENTS = null; 15747 var DEFAULT_FORBID_CONTENTS = addToSet({}, [ 15748 'annotation-xml', 15749 'audio', 15750 'colgroup', 15751 'desc', 15752 'foreignobject', 15753 'head', 15754 'iframe', 15755 'math', 15756 'mi', 15757 'mn', 15758 'mo', 15759 'ms', 15760 'mtext', 15761 'noembed', 15762 'noframes', 15763 'noscript', 15764 'plaintext', 15765 'script', 15766 'style', 15767 'svg', 15768 'template', 15769 'thead', 15770 'title', 15771 'video', 15772 'xmp' 15773 ]); 15774 var DATA_URI_TAGS = null; 15775 var DEFAULT_DATA_URI_TAGS = addToSet({}, [ 15776 'audio', 15777 'video', 15778 'img', 15779 'source', 15780 'image', 15781 'track' 15782 ]); 15783 var URI_SAFE_ATTRIBUTES = null; 15784 var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [ 15785 'alt', 15786 'class', 15787 'for', 15788 'id', 15789 'label', 15790 'name', 15791 'pattern', 15792 'placeholder', 15793 'role', 15794 'summary', 15795 'title', 15796 'value', 15797 'style', 15798 'xmlns' 15799 ]); 15800 var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML'; 15801 var SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; 15802 var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'; 15803 var NAMESPACE = HTML_NAMESPACE; 15804 var IS_EMPTY_INPUT = false; 15805 var PARSER_MEDIA_TYPE; 15806 var SUPPORTED_PARSER_MEDIA_TYPES = [ 15807 'application/xhtml+xml', 15808 'text/html' 15809 ]; 15810 var DEFAULT_PARSER_MEDIA_TYPE = 'text/html'; 15811 var transformCaseFunc; 15812 var CONFIG = null; 15813 var formElement = document.createElement('form'); 15814 var isRegexOrFunction = function isRegexOrFunction(testValue) { 15815 return testValue instanceof RegExp || testValue instanceof Function; 15816 }; 15817 var _parseConfig = function _parseConfig(cfg) { 15818 if (CONFIG && CONFIG === cfg) { 15819 return; 15820 } 15821 if (!cfg || _typeof(cfg) !== 'object') { 15822 cfg = {}; 15823 } 15824 cfg = clone(cfg); 15825 ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS; 15826 ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR; 15827 URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES; 15828 DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS; 15829 FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS; 15830 FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {}; 15831 FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {}; 15832 USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false; 15833 ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; 15834 ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; 15835 ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; 15836 SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; 15837 WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; 15838 RETURN_DOM = cfg.RETURN_DOM || false; 15839 RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; 15840 RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; 15841 FORCE_BODY = cfg.FORCE_BODY || false; 15842 SANITIZE_DOM = cfg.SANITIZE_DOM !== false; 15843 KEEP_CONTENT = cfg.KEEP_CONTENT !== false; 15844 IN_PLACE = cfg.IN_PLACE || false; 15845 IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1; 15846 NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE; 15847 if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) { 15848 CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck; 15849 } 15850 if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) { 15851 CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck; 15852 } 15853 if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') { 15854 CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements; 15855 } 15856 PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE; 15857 transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) { 15858 return x; 15859 } : stringToLowerCase; 15860 if (SAFE_FOR_TEMPLATES) { 15861 ALLOW_DATA_ATTR = false; 15862 } 15863 if (RETURN_DOM_FRAGMENT) { 15864 RETURN_DOM = true; 15865 } 15866 if (USE_PROFILES) { 15867 ALLOWED_TAGS = addToSet({}, _toConsumableArray(text)); 15868 ALLOWED_ATTR = []; 15869 if (USE_PROFILES.html === true) { 15870 addToSet(ALLOWED_TAGS, html$1); 15871 addToSet(ALLOWED_ATTR, html); 15872 } 15873 if (USE_PROFILES.svg === true) { 15874 addToSet(ALLOWED_TAGS, svg$1); 15875 addToSet(ALLOWED_ATTR, svg); 15876 addToSet(ALLOWED_ATTR, xml); 15877 } 15878 if (USE_PROFILES.svgFilters === true) { 15879 addToSet(ALLOWED_TAGS, svgFilters); 15880 addToSet(ALLOWED_ATTR, svg); 15881 addToSet(ALLOWED_ATTR, xml); 15882 } 15883 if (USE_PROFILES.mathMl === true) { 15884 addToSet(ALLOWED_TAGS, mathMl$1); 15885 addToSet(ALLOWED_ATTR, mathMl); 15886 addToSet(ALLOWED_ATTR, xml); 15887 } 15888 } 15889 if (cfg.ADD_TAGS) { 15890 if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) { 15891 ALLOWED_TAGS = clone(ALLOWED_TAGS); 15892 } 15893 addToSet(ALLOWED_TAGS, cfg.ADD_TAGS); 15894 } 15895 if (cfg.ADD_ATTR) { 15896 if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) { 15897 ALLOWED_ATTR = clone(ALLOWED_ATTR); 15898 } 15899 addToSet(ALLOWED_ATTR, cfg.ADD_ATTR); 15900 } 15901 if (cfg.ADD_URI_SAFE_ATTR) { 15902 addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR); 15903 } 15904 if (cfg.FORBID_CONTENTS) { 15905 if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) { 15906 FORBID_CONTENTS = clone(FORBID_CONTENTS); 15907 } 15908 addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS); 15909 } 15910 if (KEEP_CONTENT) { 15911 ALLOWED_TAGS['#text'] = true; 15912 } 15913 if (WHOLE_DOCUMENT) { 15914 addToSet(ALLOWED_TAGS, [ 15915 'html', 15916 'head', 15917 'body' 15918 ]); 15919 } 15920 if (ALLOWED_TAGS.table) { 15921 addToSet(ALLOWED_TAGS, ['tbody']); 15922 delete FORBID_TAGS.tbody; 15923 } 15924 if (freeze) { 15925 freeze(cfg); 15926 } 15927 CONFIG = cfg; 15928 }; 15929 var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [ 15930 'mi', 15931 'mo', 15932 'mn', 15933 'ms', 15934 'mtext' 15935 ]); 15936 var HTML_INTEGRATION_POINTS = addToSet({}, [ 15937 'foreignobject', 15938 'desc', 15939 'title', 15940 'annotation-xml' 15941 ]); 15942 var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [ 15943 'title', 15944 'style', 15945 'font', 15946 'a', 15947 'script' 15948 ]); 15949 var ALL_SVG_TAGS = addToSet({}, svg$1); 15950 addToSet(ALL_SVG_TAGS, svgFilters); 15951 addToSet(ALL_SVG_TAGS, svgDisallowed); 15952 var ALL_MATHML_TAGS = addToSet({}, mathMl$1); 15953 addToSet(ALL_MATHML_TAGS, mathMlDisallowed); 15954 var _checkValidNamespace = function _checkValidNamespace(element) { 15955 var parent = getParentNode(element); 15956 if (!parent || !parent.tagName) { 15957 parent = { 15958 namespaceURI: HTML_NAMESPACE, 15959 tagName: 'template' 15960 }; 15961 } 15962 var tagName = stringToLowerCase(element.tagName); 15963 var parentTagName = stringToLowerCase(parent.tagName); 15964 if (element.namespaceURI === SVG_NAMESPACE) { 15965 if (parent.namespaceURI === HTML_NAMESPACE) { 15966 return tagName === 'svg'; 15967 } 15968 if (parent.namespaceURI === MATHML_NAMESPACE) { 15969 return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]); 15970 } 15971 return Boolean(ALL_SVG_TAGS[tagName]); 15972 } 15973 if (element.namespaceURI === MATHML_NAMESPACE) { 15974 if (parent.namespaceURI === HTML_NAMESPACE) { 15975 return tagName === 'math'; 15976 } 15977 if (parent.namespaceURI === SVG_NAMESPACE) { 15978 return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName]; 15979 } 15980 return Boolean(ALL_MATHML_TAGS[tagName]); 15981 } 15982 if (element.namespaceURI === HTML_NAMESPACE) { 15983 if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) { 15984 return false; 15985 } 15986 if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) { 15987 return false; 15988 } 15989 return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]); 15990 } 15991 return false; 15992 }; 15993 var _forceRemove = function _forceRemove(node) { 15994 arrayPush(DOMPurify.removed, { element: node }); 15995 try { 15996 node.parentNode.removeChild(node); 15997 } catch (_) { 15998 try { 15999 node.outerHTML = emptyHTML; 16000 } catch (_) { 16001 node.remove(); 16002 } 16003 } 16004 }; 16005 var _removeAttribute = function _removeAttribute(name, node) { 16006 try { 16007 arrayPush(DOMPurify.removed, { 16008 attribute: node.getAttributeNode(name), 16009 from: node 16010 }); 16011 } catch (_) { 16012 arrayPush(DOMPurify.removed, { 16013 attribute: null, 16014 from: node 16015 }); 16016 } 16017 node.removeAttribute(name); 16018 if (name === 'is' && !ALLOWED_ATTR[name]) { 16019 if (RETURN_DOM || RETURN_DOM_FRAGMENT) { 16020 try { 16021 _forceRemove(node); 16022 } catch (_) { 16023 } 16024 } else { 16025 try { 16026 node.setAttribute(name, ''); 16027 } catch (_) { 16028 } 16029 } 16030 } 16031 }; 16032 var _initDocument = function _initDocument(dirty) { 16033 var doc; 16034 var leadingWhitespace; 16035 if (FORCE_BODY) { 16036 dirty = '<remove></remove>' + dirty; 16037 } else { 16038 var matches = stringMatch(dirty, /^[\r\n\t ]+/); 16039 leadingWhitespace = matches && matches[0]; 16040 } 16041 if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') { 16042 dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>'; 16043 } 16044 var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty; 16045 if (NAMESPACE === HTML_NAMESPACE) { 16046 try { 16047 doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE); 16048 } catch (_) { 16049 } 16050 } 16051 if (!doc || !doc.documentElement) { 16052 doc = implementation.createDocument(NAMESPACE, 'template', null); 16053 try { 16054 doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload; 16055 } catch (_) { 16056 } 16057 } 16058 var body = doc.body || doc.documentElement; 16059 if (dirty && leadingWhitespace) { 16060 body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null); 16061 } 16062 if (NAMESPACE === HTML_NAMESPACE) { 16063 return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0]; 16064 } 16065 return WHOLE_DOCUMENT ? doc.documentElement : body; 16066 }; 16067 var _createIterator = function _createIterator(root) { 16068 return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false); 16069 }; 16070 var _isClobbered = function _isClobbered(elm) { 16071 return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function'); 16072 }; 16073 var _isNode = function _isNode(object) { 16074 return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'; 16075 }; 16076 var _executeHook = function _executeHook(entryPoint, currentNode, data) { 16077 if (!hooks[entryPoint]) { 16078 return; 16079 } 16080 arrayForEach(hooks[entryPoint], function (hook) { 16081 hook.call(DOMPurify, currentNode, data, CONFIG); 16082 }); 16083 }; 16084 var _sanitizeElements = function _sanitizeElements(currentNode) { 16085 var content; 16086 _executeHook('beforeSanitizeElements', currentNode, null); 16087 if (_isClobbered(currentNode)) { 16088 _forceRemove(currentNode); 16089 return true; 16090 } 16091 if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) { 16092 _forceRemove(currentNode); 16093 return true; 16094 } 16095 var tagName = transformCaseFunc(currentNode.nodeName); 16096 _executeHook('uponSanitizeElement', currentNode, { 16097 tagName: tagName, 16098 allowedTags: ALLOWED_TAGS 16099 }); 16100 if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) { 16101 _forceRemove(currentNode); 16102 return true; 16103 } 16104 if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) { 16105 _forceRemove(currentNode); 16106 return true; 16107 } 16108 if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) { 16109 if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) { 16110 if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) 16111 return false; 16112 if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) 16113 return false; 16114 } 16115 if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) { 16116 var parentNode = getParentNode(currentNode) || currentNode.parentNode; 16117 var childNodes = getChildNodes(currentNode) || currentNode.childNodes; 16118 if (childNodes && parentNode) { 16119 var childCount = childNodes.length; 16120 for (var i = childCount - 1; i >= 0; --i) { 16121 parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode)); 16122 } 16123 } 16124 } 16125 _forceRemove(currentNode); 16126 return true; 16127 } 16128 if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) { 16129 _forceRemove(currentNode); 16130 return true; 16131 } 16132 if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) { 16133 _forceRemove(currentNode); 16134 return true; 16135 } 16136 if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) { 16137 content = currentNode.textContent; 16138 content = stringReplace(content, MUSTACHE_EXPR$1, ' '); 16139 content = stringReplace(content, ERB_EXPR$1, ' '); 16140 if (currentNode.textContent !== content) { 16141 arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() }); 16142 currentNode.textContent = content; 16143 } 16144 } 16145 _executeHook('afterSanitizeElements', currentNode, null); 16146 return false; 16147 }; 16148 var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) { 16149 if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) { 16150 return false; 16151 } 16152 if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)); 16153 else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)); 16154 else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) { 16155 if (_basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) || lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))); 16156 else { 16157 return false; 16158 } 16159 } else if (URI_SAFE_ATTRIBUTES[lcName]); 16160 else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ''))); 16161 else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]); 16162 else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ''))); 16163 else if (!value); 16164 else { 16165 return false; 16166 } 16167 return true; 16168 }; 16169 var _basicCustomElementTest = function _basicCustomElementTest(tagName) { 16170 return tagName.indexOf('-') > 0; 16171 }; 16172 var _sanitizeAttributes = function _sanitizeAttributes(currentNode) { 16173 var attr; 16174 var value; 16175 var lcName; 16176 var l; 16177 _executeHook('beforeSanitizeAttributes', currentNode, null); 16178 var attributes = currentNode.attributes; 16179 if (!attributes) { 16180 return; 16181 } 16182 var hookEvent = { 16183 attrName: '', 16184 attrValue: '', 16185 keepAttr: true, 16186 allowedAttributes: ALLOWED_ATTR 16187 }; 16188 l = attributes.length; 16189 while (l--) { 16190 attr = attributes[l]; 16191 var _attr = attr, name = _attr.name, namespaceURI = _attr.namespaceURI; 16192 value = name === 'value' ? attr.value : stringTrim(attr.value); 16193 lcName = transformCaseFunc(name); 16194 var initValue = value; 16195 hookEvent.attrName = lcName; 16196 hookEvent.attrValue = value; 16197 hookEvent.keepAttr = true; 16198 hookEvent.forceKeepAttr = undefined; 16199 _executeHook('uponSanitizeAttribute', currentNode, hookEvent); 16200 value = hookEvent.attrValue; 16201 if (hookEvent.forceKeepAttr) { 16202 continue; 16203 } 16204 if (!hookEvent.keepAttr) { 16205 _removeAttribute(name, currentNode); 16206 continue; 16207 } 16208 if (regExpTest(/\/>/i, value)) { 16209 _removeAttribute(name, currentNode); 16210 continue; 16211 } 16212 if (SAFE_FOR_TEMPLATES) { 16213 value = stringReplace(value, MUSTACHE_EXPR$1, ' '); 16214 value = stringReplace(value, ERB_EXPR$1, ' '); 16215 } 16216 var lcTag = transformCaseFunc(currentNode.nodeName); 16217 if (!_isValidAttribute(lcTag, lcName, value)) { 16218 _removeAttribute(name, currentNode); 16219 continue; 16220 } 16221 if (value !== initValue) { 16222 try { 16223 if (namespaceURI) { 16224 currentNode.setAttributeNS(namespaceURI, name, value); 16225 } else { 16226 currentNode.setAttribute(name, value); 16227 } 16228 } catch (_) { 16229 _removeAttribute(name, currentNode); 16230 } 16231 } 16232 } 16233 _executeHook('afterSanitizeAttributes', currentNode, null); 16234 }; 16235 var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) { 16236 var shadowNode; 16237 var shadowIterator = _createIterator(fragment); 16238 _executeHook('beforeSanitizeShadowDOM', fragment, null); 16239 while (shadowNode = shadowIterator.nextNode()) { 16240 _executeHook('uponSanitizeShadowNode', shadowNode, null); 16241 if (_sanitizeElements(shadowNode)) { 16242 continue; 16243 } 16244 if (shadowNode.content instanceof DocumentFragment) { 16245 _sanitizeShadowDOM(shadowNode.content); 16246 } 16247 _sanitizeAttributes(shadowNode); 16248 } 16249 _executeHook('afterSanitizeShadowDOM', fragment, null); 16250 }; 16251 DOMPurify.sanitize = function (dirty, cfg) { 16252 var body; 16253 var importedNode; 16254 var currentNode; 16255 var oldNode; 16256 var returnNode; 16257 IS_EMPTY_INPUT = !dirty; 16258 if (IS_EMPTY_INPUT) { 16259 dirty = '<!-->'; 16260 } 16261 if (typeof dirty !== 'string' && !_isNode(dirty)) { 16262 if (typeof dirty.toString !== 'function') { 16263 throw typeErrorCreate('toString is not a function'); 16264 } else { 16265 dirty = dirty.toString(); 16266 if (typeof dirty !== 'string') { 16267 throw typeErrorCreate('dirty is not a string, aborting'); 16268 } 16269 } 16270 } 16271 if (!DOMPurify.isSupported) { 16272 if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') { 16273 if (typeof dirty === 'string') { 16274 return window.toStaticHTML(dirty); 16275 } 16276 if (_isNode(dirty)) { 16277 return window.toStaticHTML(dirty.outerHTML); 16278 } 16279 } 16280 return dirty; 16281 } 16282 if (!SET_CONFIG) { 16283 _parseConfig(cfg); 16284 } 16285 DOMPurify.removed = []; 16286 if (typeof dirty === 'string') { 16287 IN_PLACE = false; 16288 } 16289 if (IN_PLACE) { 16290 if (dirty.nodeName) { 16291 var tagName = transformCaseFunc(dirty.nodeName); 16292 if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) { 16293 throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place'); 16294 } 16295 } 16296 } else if (dirty instanceof Node) { 16297 body = _initDocument('<!---->'); 16298 importedNode = body.ownerDocument.importNode(dirty, true); 16299 if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') { 16300 body = importedNode; 16301 } else if (importedNode.nodeName === 'HTML') { 16302 body = importedNode; 16303 } else { 16304 body.appendChild(importedNode); 16305 } 16306 } else { 16307 if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) { 16308 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty; 16309 } 16310 body = _initDocument(dirty); 16311 if (!body) { 16312 return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : ''; 16313 } 16314 } 16315 if (body && FORCE_BODY) { 16316 _forceRemove(body.firstChild); 16317 } 16318 var nodeIterator = _createIterator(IN_PLACE ? dirty : body); 16319 while (currentNode = nodeIterator.nextNode()) { 16320 if (currentNode.nodeType === 3 && currentNode === oldNode) { 16321 continue; 16322 } 16323 if (_sanitizeElements(currentNode)) { 16324 continue; 16325 } 16326 if (currentNode.content instanceof DocumentFragment) { 16327 _sanitizeShadowDOM(currentNode.content); 16328 } 16329 _sanitizeAttributes(currentNode); 16330 oldNode = currentNode; 16331 } 16332 oldNode = null; 16333 if (IN_PLACE) { 16334 return dirty; 16335 } 16336 if (RETURN_DOM) { 16337 if (RETURN_DOM_FRAGMENT) { 16338 returnNode = createDocumentFragment.call(body.ownerDocument); 16339 while (body.firstChild) { 16340 returnNode.appendChild(body.firstChild); 16341 } 16342 } else { 16343 returnNode = body; 16344 } 16345 if (ALLOWED_ATTR.shadowroot) { 16346 returnNode = importNode.call(originalDocument, returnNode, true); 16347 } 16348 return returnNode; 16349 } 16350 var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML; 16351 if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) { 16352 serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML; 16353 } 16354 if (SAFE_FOR_TEMPLATES) { 16355 serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' '); 16356 serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' '); 16357 } 16358 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML; 16359 }; 16360 DOMPurify.setConfig = function (cfg) { 16361 _parseConfig(cfg); 16362 SET_CONFIG = true; 16363 }; 16364 DOMPurify.clearConfig = function () { 16365 CONFIG = null; 16366 SET_CONFIG = false; 16367 }; 16368 DOMPurify.isValidAttribute = function (tag, attr, value) { 16369 if (!CONFIG) { 16370 _parseConfig({}); 16371 } 16372 var lcTag = transformCaseFunc(tag); 16373 var lcName = transformCaseFunc(attr); 16374 return _isValidAttribute(lcTag, lcName, value); 16375 }; 16376 DOMPurify.addHook = function (entryPoint, hookFunction) { 16377 if (typeof hookFunction !== 'function') { 16378 return; 16379 } 16380 hooks[entryPoint] = hooks[entryPoint] || []; 16381 arrayPush(hooks[entryPoint], hookFunction); 16382 }; 16383 DOMPurify.removeHook = function (entryPoint) { 16384 if (hooks[entryPoint]) { 16385 return arrayPop(hooks[entryPoint]); 16386 } 16387 }; 16388 DOMPurify.removeHooks = function (entryPoint) { 16389 if (hooks[entryPoint]) { 16390 hooks[entryPoint] = []; 16391 } 16392 }; 16393 DOMPurify.removeAllHooks = function () { 16394 hooks = {}; 16395 }; 16396 return DOMPurify; 16397 } 16398 var purify = createDOMPurify(); 16399 16400 const
vendor: 3,141 bytes, lines 16400-16490
16400each$4 = Tools.each, trim = Tools.trim; 16401 const queryParts = [ 16402 'source', 16403 'protocol', 16404 'authority', 16405 'userInfo', 16406 'user', 16407 'password', 16408 'host', 16409 'port', 16410 'relative', 16411 'path', 16412 'directory', 16413 'file', 16414 'query', 16415 'anchor' 16416 ]; 16417 const DEFAULT_PORTS = { 16418 ftp: 21, 16419 http: 80, 16420 https: 443, 16421 mailto: 25 16422 }; 16423 const safeSvgDataUrlElements = [ 16424 'img', 16425 'video' 16426 ]; 16427 const blockSvgDataUris = (allowSvgDataUrls, tagName) => { 16428 if (isNonNullable(allowSvgDataUrls)) { 16429 return !allowSvgDataUrls; 16430 } else { 16431 return isNonNullable(tagName) ? !contains$2(safeSvgDataUrlElements, tagName) : true; 16432 } 16433 }; 16434 const decodeUri = encodedUri => { 16435 try { 16436 return decodeURIComponent(encodedUri); 16437 } catch (ex) { 16438 return unescape(encodedUri); 16439 } 16440 }; 16441 const isInvalidUri = (settings, uri, tagName) => { 16442 const decodedUri = decodeUri(uri).replace(/\s/g, ''); 16443 if (settings.allow_script_urls) { 16444 return false; 16445 } else if (/((java|vb)script|mhtml):/i.test(decodedUri)) { 16446 return true; 16447 } else if (settings.allow_html_data_urls) { 16448 return false; 16449 } else if (/^data:image\//i.test(decodedUri)) { 16450 return blockSvgDataUris(settings.allow_svg_data_urls, tagName) && /^data:image\/svg\+xml/i.test(decodedUri); 16451 } else { 16452 return /^data:/i.test(decodedUri); 16453 } 16454 }; 16455 class URI { 16456 constructor(url, settings = {}) { 16457 this.path = ''; 16458 this.directory = ''; 16459 url = trim(url); 16460 this.settings = settings; 16461 const baseUri = settings.base_uri; 16462 const self = this; 16463 if (/^([\w\-]+):([^\/]{2})/i.test(url) || /^\s*#/.test(url)) { 16464 self.source = url; 16465 return; 16466 } 16467 const isProtocolRelative = url.indexOf('//') === 0; 16468 if (url.indexOf('/') === 0 && !isProtocolRelative) { 16469 url = (baseUri ? baseUri.protocol || 'http' : 'http') + '://mce_host' + url; 16470 } 16471 if (!/^[\w\-]*:?\/\//.test(url)) { 16472 const baseUrl = baseUri ? baseUri.path : new URI(document.location.href).directory; 16473 if ((baseUri === null || baseUri === void 0 ? void 0 : baseUri.protocol) === '') { 16474 url = '//mce_host' + self.toAbsPath(baseUrl, url); 16475 } else { 16476 const match = /([^#?]*)([#?]?.*)/.exec(url); 16477 if (match) { 16478 url = (baseUri && baseUri.protocol || 'http') + '://mce_host' + self.toAbsPath(baseUrl, match[1]) + match[2]; 16479 } 16480 } 16481 } 16482 url = url.replace(/@@/g, '(mce_at)'); 16483 const urlMatch = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?(\[[a-zA-Z0-9:.%]+\]|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(url); 16484 if (urlMatch) { 16485 each$4(queryParts, (v, i) => { 16486 let part = urlMatch[i]; 16487 if (part) { 16488 part = part.replace(/\(mce_at\)/g, '@@'); 16489 } 16490 self[v] = part;
vendor: 15,763 bytes, lines 16491-16919
16491 }); 16492 } 16493 if (baseUri) { 16494 if (!self.protocol) { 16495 self.protocol = baseUri.protocol; 16496 } 16497 if (!self.userInfo) { 16498 self.userInfo = baseUri.userInfo; 16499 } 16500 if (!self.port && self.host === 'mce_host') { 16501 self.port = baseUri.port; 16502 } 16503 if (!self.host || self.host === 'mce_host') { 16504 self.host = baseUri.host; 16505 } 16506 self.source = ''; 16507 } 16508 if (isProtocolRelative) { 16509 self.protocol = ''; 16510 } 16511 } 16512 static parseDataUri(uri) { 16513 let type; 16514 const uriComponents = decodeURIComponent(uri).split(','); 16515 const matches = /data:([^;]+)/.exec(uriComponents[0]); 16516 if (matches) { 16517 type = matches[1]; 16518 } 16519 return { 16520 type, 16521 data: uriComponents[1] 16522 }; 16523 } 16524 static isDomSafe(uri, context, options = {}) { 16525 if (options.allow_script_urls) { 16526 return true; 16527 } else { 16528 const decodedUri = Entities.decode(uri).replace(/[\s\u0000-\u001F]+/g, ''); 16529 return !isInvalidUri(options, decodedUri, context); 16530 } 16531 } 16532 static getDocumentBaseUrl(loc) { 16533 var _a; 16534 let baseUrl; 16535 if (loc.protocol.indexOf('http') !== 0 && loc.protocol !== 'file:') { 16536 baseUrl = (_a = loc.href) !== null && _a !== void 0 ? _a : ''; 16537 } else { 16538 baseUrl = loc.protocol + '//' + loc.host + loc.pathname; 16539 } 16540 if (/^[^:]+:\/\/\/?[^\/]+\//.test(baseUrl)) { 16541 baseUrl = baseUrl.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, ''); 16542 if (!/[\/\\]$/.test(baseUrl)) { 16543 baseUrl += '/'; 16544 } 16545 } 16546 return baseUrl; 16547 } 16548 setPath(path) { 16549 const pathMatch = /^(.*?)\/?(\w+)?$/.exec(path); 16550 if (pathMatch) { 16551 this.path = pathMatch[0]; 16552 this.directory = pathMatch[1]; 16553 this.file = pathMatch[2]; 16554 } 16555 this.source = ''; 16556 this.getURI(); 16557 } 16558 toRelative(uri) { 16559 if (uri === './') { 16560 return uri; 16561 } 16562 const relativeUri = new URI(uri, { base_uri: this }); 16563 if (relativeUri.host !== 'mce_host' && this.host !== relativeUri.host && relativeUri.host || this.port !== relativeUri.port || this.protocol !== relativeUri.protocol && relativeUri.protocol !== '') { 16564 return relativeUri.getURI(); 16565 } 16566 const tu = this.getURI(), uu = relativeUri.getURI(); 16567 if (tu === uu || tu.charAt(tu.length - 1) === '/' && tu.substr(0, tu.length - 1) === uu) { 16568 return tu; 16569 } 16570 let output = this.toRelPath(this.path, relativeUri.path); 16571 if (relativeUri.query) { 16572 output += '?' + relativeUri.query; 16573 } 16574 if (relativeUri.anchor) { 16575 output += '#' + relativeUri.anchor; 16576 } 16577 return output; 16578 } 16579 toAbsolute(uri, noHost) { 16580 const absoluteUri = new URI(uri, { base_uri: this }); 16581 return absoluteUri.getURI(noHost && this.isSameOrigin(absoluteUri)); 16582 } 16583 isSameOrigin(uri) { 16584 if (this.host == uri.host && this.protocol == uri.protocol) { 16585 if (this.port == uri.port) { 16586 return true; 16587 } 16588 const defaultPort = this.protocol ? DEFAULT_PORTS[this.protocol] : null; 16589 if (defaultPort && (this.port || defaultPort) == (uri.port || defaultPort)) { 16590 return true; 16591 } 16592 } 16593 return false; 16594 } 16595 toRelPath(base, path) { 16596 let breakPoint = 0, out = '', i, l; 16597 const normalizedBase = base.substring(0, base.lastIndexOf('/')).split('/'); 16598 const items = path.split('/'); 16599 if (normalizedBase.length >= items.length) { 16600 for (i = 0, l = normalizedBase.length; i < l; i++) { 16601 if (i >= items.length || normalizedBase[i] !== items[i]) { 16602 breakPoint = i + 1; 16603 break; 16604 } 16605 } 16606 } 16607 if (normalizedBase.length < items.length) { 16608 for (i = 0, l = items.length; i < l; i++) { 16609 if (i >= normalizedBase.length || normalizedBase[i] !== items[i]) { 16610 breakPoint = i + 1; 16611 break; 16612 } 16613 } 16614 } 16615 if (breakPoint === 1) { 16616 return path; 16617 } 16618 for (i = 0, l = normalizedBase.length - (breakPoint - 1); i < l; i++) { 16619 out += '../'; 16620 } 16621 for (i = breakPoint - 1, l = items.length; i < l; i++) { 16622 if (i !== breakPoint - 1) { 16623 out += '/' + items[i]; 16624 } else { 16625 out += items[i]; 16626 } 16627 } 16628 return out; 16629 } 16630 toAbsPath(base, path) { 16631 let nb = 0; 16632 const tr = /\/$/.test(path) ? '/' : ''; 16633 const normalizedBase = base.split('/'); 16634 const normalizedPath = path.split('/'); 16635 const baseParts = []; 16636 each$4(normalizedBase, k => { 16637 if (k) { 16638 baseParts.push(k); 16639 } 16640 }); 16641 const pathParts = []; 16642 for (let i = normalizedPath.length - 1; i >= 0; i--) { 16643 if (normalizedPath[i].length === 0 || normalizedPath[i] === '.') { 16644 continue; 16645 } 16646 if (normalizedPath[i] === '..') { 16647 nb++; 16648 continue; 16649 } 16650 if (nb > 0) { 16651 nb--; 16652 continue; 16653 } 16654 pathParts.push(normalizedPath[i]); 16655 } 16656 const i = baseParts.length - nb; 16657 let outPath; 16658 if (i <= 0) { 16659 outPath = reverse(pathParts).join('/'); 16660 } else { 16661 outPath = baseParts.slice(0, i).join('/') + '/' + reverse(pathParts).join('/'); 16662 } 16663 if (outPath.indexOf('/') !== 0) { 16664 outPath = '/' + outPath; 16665 } 16666 if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) { 16667 outPath += tr; 16668 } 16669 return outPath; 16670 } 16671 getURI(noProtoHost = false) { 16672 let s; 16673 if (!this.source || noProtoHost) { 16674 s = ''; 16675 if (!noProtoHost) { 16676 if (this.protocol) { 16677 s += this.protocol + '://'; 16678 } else { 16679 s += '//'; 16680 } 16681 if (this.userInfo) { 16682 s += this.userInfo + '@'; 16683 } 16684 if (this.host) { 16685 s += this.host; 16686 } 16687 if (this.port) { 16688 s += ':' + this.port; 16689 } 16690 } 16691 if (this.path) { 16692 s += this.path; 16693 } 16694 if (this.query) { 16695 s += '?' + this.query; 16696 } 16697 if (this.anchor) { 16698 s += '#' + this.anchor; 16699 } 16700 this.source = s; 16701 } 16702 return this.source; 16703 } 16704 } 16705 16706 const filteredUrlAttrs = Tools.makeMap('src,href,data,background,action,formaction,poster,xlink:href'); 16707 const internalElementAttr = 'data-mce-type'; 16708 let uid = 0; 16709 const processNode = (node, settings, schema, evt) => { 16710 var _a, _b, _c, _d; 16711 const validate = settings.validate; 16712 const specialElements = schema.getSpecialElements(); 16713 if (node.nodeType === COMMENT && !settings.allow_conditional_comments && /^\[if/i.test((_a = node.nodeValue) !== null && _a !== void 0 ? _a : '')) { 16714 node.nodeValue = ' ' + node.nodeValue; 16715 } 16716 const lcTagName = (_b = evt === null || evt === void 0 ? void 0 : evt.tagName) !== null && _b !== void 0 ? _b : node.nodeName.toLowerCase(); 16717 if (node.nodeType !== ELEMENT || lcTagName === 'body') { 16718 return; 16719 } 16720 const element = SugarElement.fromDom(node); 16721 const isInternalElement = has$1(element, internalElementAttr); 16722 const bogus = get$9(element, 'data-mce-bogus'); 16723 if (!isInternalElement && isString(bogus)) { 16724 if (bogus === 'all') { 16725 remove$6(element); 16726 } else { 16727 unwrap(element); 16728 } 16729 return; 16730 } 16731 const rule = schema.getElementRule(lcTagName); 16732 if (validate && !rule) { 16733 if (has$2(specialElements, lcTagName)) { 16734 remove$6(element); 16735 } else { 16736 unwrap(element); 16737 } 16738 return; 16739 } else { 16740 if (isNonNullable(evt)) { 16741 evt.allowedTags[lcTagName] = true; 16742 } 16743 } 16744 if (validate && rule && !isInternalElement) { 16745 each$e((_c = rule.attributesForced) !== null && _c !== void 0 ? _c : [], attr => { 16746 set$3(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value); 16747 }); 16748 each$e((_d = rule.attributesDefault) !== null && _d !== void 0 ? _d : [], attr => { 16749 if (!has$1(element, attr.name)) { 16750 set$3(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value); 16751 } 16752 }); 16753 if (rule.attributesRequired && !exists(rule.attributesRequired, attr => has$1(element, attr))) { 16754 unwrap(element); 16755 return; 16756 } 16757 if (rule.removeEmptyAttrs && hasNone(element)) { 16758 unwrap(element); 16759 return; 16760 } 16761 if (rule.outputName && rule.outputName !== lcTagName) { 16762 mutate(element, rule.outputName); 16763 } 16764 } 16765 }; 16766 const shouldKeepAttribute = (settings, schema, tagName, attrName, attrValue) => !(attrName in filteredUrlAttrs && isInvalidUri(settings, attrValue, tagName)) && (!settings.validate || schema.isValid(tagName, attrName) || startsWith(attrName, 'data-') || startsWith(attrName, 'aria-')); 16767 const isRequiredAttributeOfInternalElement = (ele, attrName) => ele.hasAttribute(internalElementAttr) && (attrName === 'id' || attrName === 'class' || attrName === 'style'); 16768 const isBooleanAttribute = (attrName, schema) => attrName in schema.getBoolAttrs(); 16769 const filterAttributes = (ele, settings, schema) => { 16770 const {attributes} = ele; 16771 for (let i = attributes.length - 1; i >= 0; i--) { 16772 const attr = attributes[i]; 16773 const attrName = attr.name; 16774 const attrValue = attr.value; 16775 if (!shouldKeepAttribute(settings, schema, ele.tagName.toLowerCase(), attrName, attrValue) && !isRequiredAttributeOfInternalElement(ele, attrName)) { 16776 ele.removeAttribute(attrName); 16777 } else if (isBooleanAttribute(attrName, schema)) { 16778 ele.setAttribute(attrName, attrName); 16779 } 16780 } 16781 }; 16782 const setupPurify = (settings, schema) => { 16783 const purify$1 = purify(); 16784 purify$1.addHook('uponSanitizeElement', (ele, evt) => { 16785 processNode(ele, settings, schema, evt); 16786 }); 16787 purify$1.addHook('uponSanitizeAttribute', (ele, evt) => { 16788 const tagName = ele.tagName.toLowerCase(); 16789 const {attrName, attrValue} = evt; 16790 evt.keepAttr = shouldKeepAttribute(settings, schema, tagName, attrName, attrValue); 16791 if (evt.keepAttr) { 16792 evt.allowedAttributes[attrName] = true; 16793 if (isBooleanAttribute(attrName, schema)) { 16794 evt.attrValue = attrName; 16795 } 16796 if (settings.allow_svg_data_urls && startsWith(attrValue, 'data:image/svg+xml')) { 16797 evt.forceKeepAttr = true; 16798 } 16799 } else if (isRequiredAttributeOfInternalElement(ele, attrName)) { 16800 evt.forceKeepAttr = true; 16801 } 16802 }); 16803 return purify$1; 16804 }; 16805 const getPurifyConfig = (settings, mimeType) => { 16806 const basePurifyConfig = { 16807 IN_PLACE: true, 16808 ALLOW_UNKNOWN_PROTOCOLS: true, 16809 ALLOWED_TAGS: [ 16810 '#comment', 16811 '#cdata-section', 16812 'body' 16813 ], 16814 ALLOWED_ATTR: [] 16815 }; 16816 const config = { ...basePurifyConfig }; 16817 config.PARSER_MEDIA_TYPE = mimeType; 16818 if (settings.allow_script_urls) { 16819 config.ALLOWED_URI_REGEXP = /.*/; 16820 } else if (settings.allow_html_data_urls) { 16821 config.ALLOWED_URI_REGEXP = /^(?!(\w+script|mhtml):)/i; 16822 } 16823 return config; 16824 }; 16825 const getSanitizer = (settings, schema) => { 16826 if (settings.sanitize) { 16827 const purify = setupPurify(settings, schema); 16828 return (body, mimeType) => { 16829 purify.sanitize(body, getPurifyConfig(settings, mimeType)); 16830 purify.removed = []; 16831 }; 16832 } else { 16833 return (body, _) => { 16834 const nodeIterator = document.createNodeIterator(body, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT); 16835 let node; 16836 while (node = nodeIterator.nextNode()) { 16837 processNode(node, settings, schema); 16838 if (isElement$6(node)) { 16839 filterAttributes(node, settings, schema); 16840 } 16841 } 16842 }; 16843 } 16844 }; 16845 16846 const makeMap = Tools.makeMap, extend$1 = Tools.extend; 16847 const transferChildren = (parent, nativeParent, specialElements) => { 16848 const parentName = parent.name; 16849 const isSpecial = parentName in specialElements && parentName !== 'title' && parentName !== 'textarea'; 16850 const childNodes = nativeParent.childNodes; 16851 for (let ni = 0, nl = childNodes.length; ni < nl; ni++) { 16852 const nativeChild = childNodes[ni]; 16853 const child = new AstNode(nativeChild.nodeName.toLowerCase(), nativeChild.nodeType); 16854 if (isElement$6(nativeChild)) { 16855 const attributes = nativeChild.attributes; 16856 for (let ai = 0, al = attributes.length; ai < al; ai++) { 16857 const attr = attributes[ai]; 16858 child.attr(attr.name, attr.value); 16859 } 16860 } else if (isText$a(nativeChild)) { 16861 child.value = nativeChild.data; 16862 if (isSpecial) { 16863 child.raw = true; 16864 } 16865 } else if (isComment(nativeChild) || isCData(nativeChild) || isPi(nativeChild)) { 16866 child.value = nativeChild.data; 16867 } 16868 transferChildren(child, nativeChild, specialElements); 16869 parent.append(child); 16870 } 16871 }; 16872 const walkTree = (root, preprocessors, postprocessors) => { 16873 const traverseOrder = []; 16874 for (let node = root, lastNode = node; node; lastNode = node, node = node.walk()) { 16875 const tempNode = node; 16876 each$e(preprocessors, preprocess => preprocess(tempNode)); 16877 if (isNullable(tempNode.parent) && tempNode !== root) { 16878 node = lastNode; 16879 } else { 16880 traverseOrder.push(tempNode); 16881 } 16882 } 16883 for (let i = traverseOrder.length - 1; i >= 0; i--) { 16884 const node = traverseOrder[i]; 16885 each$e(postprocessors, postprocess => postprocess(node)); 16886 } 16887 }; 16888 const whitespaceCleaner = (root, schema, settings, args) => { 16889 const validate = settings.validate; 16890 const nonEmptyElements = schema.getNonEmptyElements(); 16891 const whitespaceElements = schema.getWhitespaceElements(); 16892 const blockElements = extend$1(makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements()); 16893 const textRootBlockElements = getTextRootBlockElements(schema); 16894 const allWhiteSpaceRegExp = /[ \t\r\n]+/g; 16895 const startWhiteSpaceRegExp = /^[ \t\r\n]+/; 16896 const endWhiteSpaceRegExp = /[ \t\r\n]+$/; 16897 const hasWhitespaceParent = node => { 16898 let tempNode = node.parent; 16899 while (isNonNullable(tempNode)) { 16900 if (tempNode.name in whitespaceElements) { 16901 return true; 16902 } else { 16903 tempNode = tempNode.parent; 16904 } 16905 } 16906 return false; 16907 }; 16908 const isTextRootBlockEmpty = node => { 16909 let tempNode = node; 16910 while (isNonNullable(tempNode)) { 16911 if (tempNode.name in textRootBlockElements) { 16912 return isEmpty(schema, nonEmptyElements, whitespaceElements, tempNode); 16913 } else { 16914 tempNode = tempNode.parent; 16915 } 16916 } 16917 return false; 16918 }; 16919 const isBlock = node => node.name in blockElements && !isTransparentAstInline
vendor: 13,742 bytes, lines 16919-17292
16919(schema, node); 16920 const isAtEdgeOfBlock = (node, start) => { 16921 const neighbour = start ? node.prev : node.next; 16922 if (isNonNullable(neighbour) || isNullable(node.parent)) { 16923 return false; 16924 } 16925 return isBlock(node.parent) && (node.parent !== root || args.isRootContent === true); 16926 }; 16927 const preprocess = node => { 16928 var _a; 16929 if (node.type === 3) { 16930 if (!hasWhitespaceParent(node)) { 16931 let text = (_a = node.value) !== null && _a !== void 0 ? _a : ''; 16932 text = text.replace(allWhiteSpaceRegExp, ' '); 16933 if (isLineBreakNode(node.prev, isBlock) || isAtEdgeOfBlock(node, true)) { 16934 text = text.replace(startWhiteSpaceRegExp, ''); 16935 } 16936 if (text.length === 0) { 16937 node.remove(); 16938 } else { 16939 node.value = text; 16940 } 16941 } 16942 } 16943 }; 16944 const postprocess = node => { 16945 var _a; 16946 if (node.type === 1) { 16947 const elementRule = schema.getElementRule(node.name); 16948 if (validate && elementRule) { 16949 const isNodeEmpty = isEmpty(schema, nonEmptyElements, whitespaceElements, node); 16950 if (elementRule.paddInEmptyBlock && isNodeEmpty && isTextRootBlockEmpty(node)) { 16951 paddEmptyNode(args, isBlock, node); 16952 } else if (elementRule.removeEmpty && isNodeEmpty) { 16953 if (isBlock(node)) { 16954 node.remove(); 16955 } else { 16956 node.unwrap(); 16957 } 16958 } else if (elementRule.paddEmpty && (isNodeEmpty || isPaddedWithNbsp(node))) { 16959 paddEmptyNode(args, isBlock, node); 16960 } 16961 } 16962 } else if (node.type === 3) { 16963 if (!hasWhitespaceParent(node)) { 16964 let text = (_a = node.value) !== null && _a !== void 0 ? _a : ''; 16965 if (node.next && isBlock(node.next) || isAtEdgeOfBlock(node, false)) { 16966 text = text.replace(endWhiteSpaceRegExp, ''); 16967 } 16968 if (text.length === 0) { 16969 node.remove(); 16970 } else { 16971 node.value = text; 16972 } 16973 } 16974 } 16975 }; 16976 return [ 16977 preprocess, 16978 postprocess 16979 ]; 16980 }; 16981 const getRootBlockName = (settings, args) => { 16982 var _a; 16983 const name = (_a = args.forced_root_block) !== null && _a !== void 0 ? _a : settings.forced_root_block; 16984 if (name === false) { 16985 return ''; 16986 } else if (name === true) { 16987 return 'p'; 16988 } else { 16989 return name; 16990 } 16991 }; 16992 const DomParser = (settings = {}, schema = Schema()) => { 16993 const nodeFilterRegistry = create$8(); 16994 const attributeFilterRegistry = create$8(); 16995 const defaultedSettings = { 16996 validate: true, 16997 root_name: 'body', 16998 sanitize: true, 16999 ...settings 17000 }; 17001 const parser = new DOMParser(); 17002 const sanitize = getSanitizer(defaultedSettings, schema); 17003 const parseAndSanitizeWithContext = (html, rootName, format = 'html') => { 17004 const mimeType = format === 'xhtml' ? 'application/xhtml+xml' : 'text/html'; 17005 const isSpecialRoot = has$2(schema.getSpecialElements(), rootName.toLowerCase()); 17006 const content = isSpecialRoot ? `<${ rootName }>${ html }</${ rootName }>` : html; 17007 const wrappedHtml = format === 'xhtml' ? `<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>${ content }</body></html>` : `<body>${ content }</body>`; 17008 const body = parser.parseFromString(wrappedHtml, mimeType).body; 17009 sanitize(body, mimeType); 17010 return isSpecialRoot ? body.firstChild : body; 17011 }; 17012 const addNodeFilter = nodeFilterRegistry.addFilter; 17013 const getNodeFilters = nodeFilterRegistry.getFilters; 17014 const removeNodeFilter = nodeFilterRegistry.removeFilter; 17015 const addAttributeFilter = attributeFilterRegistry.addFilter; 17016 const getAttributeFilters = attributeFilterRegistry.getFilters; 17017 const removeAttributeFilter = attributeFilterRegistry.removeFilter; 17018 const findInvalidChildren = (node, invalidChildren) => { 17019 if (isInvalid(schema, node)) { 17020 invalidChildren.push(node); 17021 } 17022 }; 17023 const isWrappableNode = (blockElements, node) => { 17024 const isInternalElement = isString(node.attr(internalElementAttr)); 17025 const isInlineElement = node.type === 1 && (!has$2(blockElements, node.name) && !isTransparentAstBlock(schema, node)); 17026 return node.type === 3 || isInlineElement && !isInternalElement; 17027 }; 17028 const addRootBlocks = (rootNode, rootBlockName) => { 17029 const blockElements = extend$1(makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements()); 17030 const startWhiteSpaceRegExp = /^[ \t\r\n]+/; 17031 const endWhiteSpaceRegExp = /[ \t\r\n]+$/; 17032 let node = rootNode.firstChild, rootBlockNode = null; 17033 const trim = rootBlock => { 17034 var _a, _b; 17035 if (rootBlock) { 17036 node = rootBlock.firstChild; 17037 if (node && node.type === 3) { 17038 node.value = (_a = node.value) === null || _a === void 0 ? void 0 : _a.replace(startWhiteSpaceRegExp, ''); 17039 } 17040 node = rootBlock.lastChild; 17041 if (node && node.type === 3) { 17042 node.value = (_b = node.value) === null || _b === void 0 ? void 0 : _b.replace(endWhiteSpaceRegExp, ''); 17043 } 17044 } 17045 }; 17046 if (!schema.isValidChild(rootNode.name, rootBlockName.toLowerCase())) { 17047 return; 17048 } 17049 while (node) { 17050 const next = node.next; 17051 if (isWrappableNode(blockElements, node)) { 17052 if (!rootBlockNode) { 17053 rootBlockNode = new AstNode(rootBlockName, 1); 17054 rootBlockNode.attr(defaultedSettings.forced_root_block_attrs); 17055 rootNode.insert(rootBlockNode, node); 17056 rootBlockNode.append(node); 17057 } else { 17058 rootBlockNode.append(node); 17059 } 17060 } else { 17061 trim(rootBlockNode); 17062 rootBlockNode = null; 17063 } 17064 node = next; 17065 } 17066 trim(rootBlockNode); 17067 }; 17068 const parse = (html, args = {}) => { 17069 var _a; 17070 const validate = defaultedSettings.validate; 17071 const rootName = (_a = args.context) !== null && _a !== void 0 ? _a : defaultedSettings.root_name; 17072 const element = parseAndSanitizeWithContext(html, rootName, args.format); 17073 updateChildren(schema, element); 17074 const rootNode = new AstNode(rootName, 11); 17075 transferChildren(rootNode, element, schema.getSpecialElements()); 17076 element.innerHTML = ''; 17077 const [whitespacePre, whitespacePost] = whitespaceCleaner(rootNode, schema, defaultedSettings, args); 17078 const invalidChildren = []; 17079 const invalidFinder = validate ? node => findInvalidChildren(node, invalidChildren) : noop; 17080 const matches = { 17081 nodes: {}, 17082 attributes: {} 17083 }; 17084 const matchFinder = node => matchNode$1(getNodeFilters(), getAttributeFilters(), node, matches); 17085 walkTree(rootNode, [ 17086 whitespacePre, 17087 matchFinder 17088 ], [ 17089 whitespacePost, 17090 invalidFinder 17091 ]); 17092 invalidChildren.reverse(); 17093 if (validate && invalidChildren.length > 0) { 17094 if (args.context) { 17095 const { 17096 pass: topLevelChildren, 17097 fail: otherChildren 17098 } = partition$2(invalidChildren, child => child.parent === rootNode); 17099 cleanInvalidNodes(otherChildren, schema, rootNode, matchFinder); 17100 args.invalid = topLevelChildren.length > 0; 17101 } else { 17102 cleanInvalidNodes(invalidChildren, schema, rootNode, matchFinder); 17103 } 17104 } 17105 const rootBlockName = getRootBlockName(defaultedSettings, args); 17106 if (rootBlockName && (rootNode.name === 'body' || args.isRootContent)) { 17107 addRootBlocks(rootNode, rootBlockName); 17108 } 17109 if (!args.invalid) { 17110 runFilters(matches, args); 17111 } 17112 return rootNode; 17113 }; 17114 const exports = { 17115 schema, 17116 addAttributeFilter, 17117 getAttributeFilters, 17118 removeAttributeFilter, 17119 addNodeFilter, 17120 getNodeFilters, 17121 removeNodeFilter, 17122 parse 17123 }; 17124 register$4(exports, defaultedSettings); 17125 register$5(exports, defaultedSettings, schema); 17126 return exports; 17127 }; 17128 17129 const serializeContent = content => isTreeNode(content) ? HtmlSerializer({ validate: false }).serialize(content) : content; 17130 const withSerializedContent = (content, fireEvent, sanitize) => { 17131 const serializedContent = serializeContent(content); 17132 const eventArgs = fireEvent(serializedContent); 17133 if (eventArgs.isDefaultPrevented()) { 17134 return eventArgs; 17135 } else if (isTreeNode(content)) { 17136 if (eventArgs.content !== serializedContent) { 17137 const rootNode = DomParser({ 17138 validate: false, 17139 forced_root_block: false, 17140 sanitize 17141 }).parse(eventArgs.content, { context: content.name }); 17142 return { 17143 ...eventArgs, 17144 content: rootNode 17145 }; 17146 } else { 17147 return { 17148 ...eventArgs, 17149 content 17150 }; 17151 } 17152 } else { 17153 return eventArgs; 17154 } 17155 }; 17156 const preProcessGetContent = (editor, args) => { 17157 if (args.no_events) { 17158 return Result.value(args); 17159 } else { 17160 const eventArgs = fireBeforeGetContent(editor, args); 17161 if (eventArgs.isDefaultPrevented()) { 17162 return Result.error(fireGetContent(editor, { 17163 content: '', 17164 ...eventArgs 17165 }).content); 17166 } else { 17167 return Result.value(eventArgs); 17168 } 17169 } 17170 }; 17171 const postProcessGetContent = (editor, content, args) => { 17172 if (args.no_events) { 17173 return content; 17174 } else { 17175 const processedEventArgs = withSerializedContent(content, content => fireGetContent(editor, { 17176 ...args, 17177 content 17178 }), shouldSanitizeXss(editor)); 17179 return processedEventArgs.content; 17180 } 17181 }; 17182 const preProcessSetContent = (editor, args) => { 17183 if (args.no_events) { 17184 return Result.value(args); 17185 } else { 17186 const processedEventArgs = withSerializedContent(args.content, content => fireBeforeSetContent(editor, { 17187 ...args, 17188 content 17189 }), shouldSanitizeXss(editor)); 17190 if (processedEventArgs.isDefaultPrevented()) { 17191 fireSetContent(editor, processedEventArgs); 17192 return Result.error(undefined); 17193 } else { 17194 return Result.value(processedEventArgs); 17195 } 17196 } 17197 }; 17198 const postProcessSetContent = (editor, content, args) => { 17199 if (!args.no_events) { 17200 fireSetContent(editor, { 17201 ...args, 17202 content 17203 }); 17204 } 17205 }; 17206 17207 const tableModel = (element, width, rows) => ({ 17208 element, 17209 width, 17210 rows 17211 }); 17212 const tableRow = (element, cells) => ({ 17213 element, 17214 cells 17215 }); 17216 const cellPosition = (x, y) => ({ 17217 x, 17218 y 17219 }); 17220 const getSpan = (td, key) => { 17221 return getOpt(td, key).bind(toInt).getOr(1); 17222 }; 17223 const fillout = (table, x, y, tr, td) => { 17224 const rowspan = getSpan(td, 'rowspan'); 17225 const colspan = getSpan(td, 'colspan'); 17226 const rows = table.rows; 17227 for (let y2 = y; y2 < y + rowspan; y2++) { 17228 if (!rows[y2]) { 17229 rows[y2] = tableRow(deep$1(tr), []); 17230 } 17231 for (let x2 = x; x2 < x + colspan; x2++) { 17232 const cells = rows[y2].cells; 17233 cells[x2] = y2 === y && x2 === x ? td : shallow$1(td); 17234 } 17235 } 17236 }; 17237 const cellExists = (table, x, y) => { 17238 const rows = table.rows; 17239 const cells = rows[y] ? rows[y].cells : []; 17240 return !!cells[x]; 17241 }; 17242 const skipCellsX = (table, x, y) => { 17243 while (cellExists(table, x, y)) { 17244 x++; 17245 } 17246 return x; 17247 }; 17248 const getWidth = rows => { 17249 return foldl(rows, (acc, row) => { 17250 return row.cells.length > acc ? row.cells.length : acc; 17251 }, 0); 17252 }; 17253 const findElementPos = (table, element) => { 17254 const rows = table.rows; 17255 for (let y = 0; y < rows.length; y++) { 17256 const cells = rows[y].cells; 17257 for (let x = 0; x < cells.length; x++) { 17258 if (eq(cells[x], element)) { 17259 return Optional.some(cellPosition(x, y)); 17260 } 17261 } 17262 } 17263 return Optional.none(); 17264 }; 17265 const extractRows = (table, sx, sy, ex, ey) => { 17266 const newRows = []; 17267 const rows = table.rows; 17268 for (let y = sy; y <= ey; y++) { 17269 const cells = rows[y].cells; 17270 const slice = sx < ex ? cells.slice(sx, ex + 1) : cells.slice(ex, sx + 1); 17271 newRows.push(tableRow(rows[y].element, slice)); 17272 } 17273 return newRows; 17274 }; 17275 const subTable = (table, startPos, endPos) => { 17276 const sx = startPos.x, sy = startPos.y; 17277 const ex = endPos.x, ey = endPos.y; 17278 const newRows = sy < ey ? extractRows(table, sx, sy, ex, ey) : extractRows(table, sx, ey, ex, sy); 17279 return tableModel(table.element, getWidth(newRows), newRows); 17280 }; 17281 const createDomTable = (table, rows) => { 17282 const tableElement = shallow$1(table.element); 17283 const tableBody = SugarElement.fromTag('tbody'); 17284 append(tableBody, rows); 17285 append$1(tableElement, tableBody); 17286 return tableElement; 17287 }; 17288 const modelRowsToDomRows = table => { 17289 return map$3(table.rows, row => { 17290 const cells = map$3(row.cells, cell => { 17291 const td = deep$1(cell); 17292 remove$
17292b(td, 'colspan'); 17293 remove$b
vendor: 22,612 bytes, lines 17293-17885
17293(td, 'rowspan'); 17294 return td; 17295 }); 17296 const tr = shallow$1(row.element); 17297 append(tr, cells); 17298 return tr; 17299 }); 17300 }; 17301 const fromDom = tableElm => { 17302 const table = tableModel(shallow$1(tableElm), 0, []); 17303 each$e(descendants(tableElm, 'tr'), (tr, y) => { 17304 each$e(descendants(tr, 'td,th'), (td, x) => { 17305 fillout(table, skipCellsX(table, x, y), y, tr, td); 17306 }); 17307 }); 17308 return tableModel(table.element, getWidth(table.rows), table.rows); 17309 }; 17310 const toDom = table => { 17311 return createDomTable(table, modelRowsToDomRows(table)); 17312 }; 17313 const subsection = (table, startElement, endElement) => { 17314 return findElementPos(table, startElement).bind(startPos => { 17315 return findElementPos(table, endElement).map(endPos => { 17316 return subTable(table, startPos, endPos); 17317 }); 17318 }); 17319 }; 17320 17321 const findParentListContainer = parents => find$2(parents, elm => name(elm) === 'ul' || name(elm) === 'ol'); 17322 const getFullySelectedListWrappers = (parents, rng) => find$2(parents, elm => name(elm) === 'li' && hasAllContentsSelected(elm, rng)).fold(constant([]), _li => findParentListContainer(parents).map(listCont => { 17323 const listElm = SugarElement.fromTag(name(listCont)); 17324 const listStyles = filter$4(getAllRaw(listCont), (_style, name) => startsWith(name, 'list-style')); 17325 setAll(listElm, listStyles); 17326 return [ 17327 SugarElement.fromTag('li'), 17328 listElm 17329 ]; 17330 }).getOr([])); 17331 const wrap = (innerElm, elms) => { 17332 const wrapped = foldl(elms, (acc, elm) => { 17333 append$1(elm, acc); 17334 return elm; 17335 }, innerElm); 17336 return elms.length > 0 ? fromElements([wrapped]) : wrapped; 17337 }; 17338 const directListWrappers = commonAnchorContainer => { 17339 if (isListItem$1(commonAnchorContainer)) { 17340 return parent(commonAnchorContainer).filter(isList).fold(constant([]), listElm => [ 17341 commonAnchorContainer, 17342 listElm 17343 ]); 17344 } else { 17345 return isList(commonAnchorContainer) ? [commonAnchorContainer] : []; 17346 } 17347 }; 17348 const getWrapElements = (rootNode, rng) => { 17349 const commonAnchorContainer = SugarElement.fromDom(rng.commonAncestorContainer); 17350 const parents = parentsAndSelf(commonAnchorContainer, rootNode); 17351 const wrapElements = filter$5(parents, isWrapElement); 17352 const listWrappers = getFullySelectedListWrappers(parents, rng); 17353 const allWrappers = wrapElements.concat(listWrappers.length ? listWrappers : directListWrappers(commonAnchorContainer)); 17354 return map$3(allWrappers, shallow$1); 17355 }; 17356 const emptyFragment = () => fromElements([]); 17357 const getFragmentFromRange = (rootNode, rng) => wrap(SugarElement.fromDom(rng.cloneContents()), getWrapElements(rootNode, rng)); 17358 const getParentTable = (rootElm, cell) => ancestor$3(cell, 'table', curry(eq, rootElm)); 17359 const getTableFragment = (rootNode, selectedTableCells) => getParentTable(rootNode, selectedTableCells[0]).bind(tableElm => { 17360 const firstCell = selectedTableCells[0]; 17361 const lastCell = selectedTableCells[selectedTableCells.length - 1]; 17362 const fullTableModel = fromDom(tableElm); 17363 return subsection(fullTableModel, firstCell, lastCell).map(sectionedTableModel => fromElements([toDom(sectionedTableModel)])); 17364 }).getOrThunk(emptyFragment); 17365 const getSelectionFragment = (rootNode, ranges) => ranges.length > 0 && ranges[0].collapsed ? emptyFragment() : getFragmentFromRange(rootNode, ranges[0]); 17366 const read$3 = (rootNode, ranges) => { 17367 const selectedCells = getCellsFromElementOrRanges(ranges, rootNode); 17368 return selectedCells.length > 0 ? getTableFragment(rootNode, selectedCells) : getSelectionFragment(rootNode, ranges); 17369 }; 17370 17371 const isCollapsibleWhitespace = (text, index) => index >= 0 && index < text.length && isWhiteSpace(text.charAt(index)); 17372 const getInnerText = bin => { 17373 return trim$1(bin.innerText); 17374 }; 17375 const getContextNodeName = parentBlockOpt => parentBlockOpt.map(block => block.nodeName).getOr('div').toLowerCase(); 17376 const getTextContent = editor => Optional.from(editor.selection.getRng()).map(rng => { 17377 var _a; 17378 const parentBlockOpt = Optional.from(editor.dom.getParent(rng.commonAncestorContainer, editor.dom.isBlock)); 17379 const body = editor.getBody(); 17380 const contextNodeName = getContextNodeName(parentBlockOpt); 17381 const rangeContentClone = SugarElement.fromDom(rng.cloneContents()); 17382 cleanupBogusElements(rangeContentClone); 17383 cleanupInputNames(rangeContentClone); 17384 const bin = editor.dom.add(body, contextNodeName, { 17385 'data-mce-bogus': 'all', 17386 'style': 'overflow: hidden; opacity: 0;' 17387 }, rangeContentClone.dom); 17388 const text = getInnerText(bin); 17389 const nonRenderedText = trim$1((_a = bin.textContent) !== null && _a !== void 0 ? _a : ''); 17390 editor.dom.remove(bin); 17391 if (isCollapsibleWhitespace(nonRenderedText, 0) || isCollapsibleWhitespace(nonRenderedText, nonRenderedText.length - 1)) { 17392 const parentBlock = parentBlockOpt.getOr(body); 17393 const parentBlockText = getInnerText(parentBlock); 17394 const textIndex = parentBlockText.indexOf(text); 17395 if (textIndex === -1) { 17396 return text; 17397 } else { 17398 const hasProceedingSpace = isCollapsibleWhitespace(parentBlockText, textIndex - 1); 17399 const hasTrailingSpace = isCollapsibleWhitespace(parentBlockText, textIndex + text.length); 17400 return (hasProceedingSpace ? ' ' : '') + text + (hasTrailingSpace ? ' ' : ''); 17401 } 17402 } else { 17403 return text; 17404 } 17405 }).getOr(''); 17406 const getSerializedContent = (editor, args) => { 17407 const rng = editor.selection.getRng(), tmpElm = editor.dom.create('body'); 17408 const sel = editor.selection.getSel(); 17409 const ranges = processRanges(editor, getRanges$1(sel)); 17410 const fragment = args.contextual ? read$3(SugarElement.fromDom(editor.getBody()), ranges).dom : rng.cloneContents(); 17411 if (fragment) { 17412 tmpElm.appendChild(fragment); 17413 } 17414 return editor.selection.serializer.serialize(tmpElm, args); 17415 }; 17416 const extractSelectedContent = (editor, args) => { 17417 if (args.format === 'text') { 17418 return getTextContent(editor); 17419 } else { 17420 const content = getSerializedContent(editor, args); 17421 if (args.format === 'tree') { 17422 return content; 17423 } else { 17424 return editor.selection.isCollapsed() ? '' : content; 17425 } 17426 } 17427 }; 17428 const setupArgs$3 = (args, format) => ({ 17429 ...args, 17430 format, 17431 get: true, 17432 selection: true, 17433 getInner: true 17434 }); 17435 const getSelectedContentInternal = (editor, format, args = {}) => { 17436 const defaultedArgs = setupArgs$3(args, format); 17437 return preProcessGetContent(editor, defaultedArgs).fold(identity, updatedArgs => { 17438 const content = extractSelectedContent(editor, updatedArgs); 17439 return postProcessGetContent(editor, content, updatedArgs); 17440 }); 17441 }; 17442 17443 const KEEP = 0, INSERT = 1, DELETE = 2; 17444 const diff = (left, right) => { 17445 const size = left.length + right.length + 2; 17446 const vDown = new Array(size); 17447 const vUp = new Array(size); 17448 const snake = (start, end, diag) => { 17449 return { 17450 start, 17451 end, 17452 diag 17453 }; 17454 }; 17455 const buildScript = (start1, end1, start2, end2, script) => { 17456 const middle = getMiddleSnake(start1, end1, start2, end2); 17457 if (middle === null || middle.start === end1 && middle.diag === end1 - end2 || middle.end === start1 && middle.diag === start1 - start2) { 17458 let i = start1; 17459 let j = start2; 17460 while (i < end1 || j < end2) { 17461 if (i < end1 && j < end2 && left[i] === right[j]) { 17462 script.push([ 17463 KEEP, 17464 left[i] 17465 ]); 17466 ++i; 17467 ++j; 17468 } else { 17469 if (end1 - start1 > end2 - start2) { 17470 script.push([ 17471 DELETE, 17472 left[i] 17473 ]); 17474 ++i; 17475 } else { 17476 script.push([ 17477 INSERT, 17478 right[j] 17479 ]); 17480 ++j; 17481 } 17482 } 17483 } 17484 } else { 17485 buildScript(start1, middle.start, start2, middle.start - middle.diag, script); 17486 for (let i2 = middle.start; i2 < middle.end; ++i2) { 17487 script.push([ 17488 KEEP, 17489 left[i2] 17490 ]); 17491 } 17492 buildScript(middle.end, end1, middle.end - middle.diag, end2, script); 17493 } 17494 }; 17495 const buildSnake = (start, diag, end1, end2) => { 17496 let end = start; 17497 while (end - diag < end2 && end < end1 && left[end] === right[end - diag]) { 17498 ++end; 17499 } 17500 return snake(start, end, diag); 17501 }; 17502 const getMiddleSnake = (start1, end1, start2, end2) => { 17503 const m = end1 - start1; 17504 const n = end2 - start2; 17505 if (m === 0 || n === 0) { 17506 return null; 17507 } 17508 const delta = m - n; 17509 const sum = n + m; 17510 const offset = (sum % 2 === 0 ? sum : sum + 1) / 2; 17511 vDown[1 + offset] = start1; 17512 vUp[1 + offset] = end1 + 1; 17513 let d, k, i, x, y; 17514 for (d = 0; d <= offset; ++d) { 17515 for (k = -d; k <= d; k += 2) { 17516 i = k + offset; 17517 if (k === -d || k !== d && vDown[i - 1] < vDown[i + 1]) { 17518 vDown[i] = vDown[i + 1]; 17519 } else { 17520 vDown[i] = vDown[i - 1] + 1; 17521 } 17522 x = vDown[i]; 17523 y = x - start1 + start2 - k; 17524 while (x < end1 && y < end2 && left[x] === right[y]) { 17525 vDown[i] = ++x; 17526 ++y; 17527 } 17528 if (delta % 2 !== 0 && delta - d <= k && k <= delta + d) { 17529 if (vUp[i - delta] <= vDown[i]) { 17530 return buildSnake(vUp[i - delta], k + start1 - start2, end1, end2); 17531 } 17532 } 17533 } 17534 for (k = delta - d; k <= delta + d; k += 2) { 17535 i = k + offset - delta; 17536 if (k === delta - d || k !== delta + d && vUp[i + 1] <= vUp[i - 1]) { 17537 vUp[i] = vUp[i + 1] - 1; 17538 } else { 17539 vUp[i] = vUp[i - 1]; 17540 } 17541 x = vUp[i] - 1; 17542 y = x - start1 + start2 - k; 17543 while (x >= start1 && y >= start2 && left[x] === right[y]) { 17544 vUp[i] = x--; 17545 y--; 17546 } 17547 if (delta % 2 === 0 && -d <= k && k <= d) { 17548 if (vUp[i] <= vDown[i + delta]) { 17549 return buildSnake(vUp[i], k + start1 - start2, end1, end2); 17550 } 17551 } 17552 } 17553 } 17554 return null; 17555 }; 17556 const script = []; 17557 buildScript(0, left.length, 0, right.length, script); 17558 return script; 17559 }; 17560 17561 const getOuterHtml = elm => { 17562 if (isElement$6(elm)) { 17563 return elm.outerHTML; 17564 } else if (isText$a(elm)) { 17565 return Entities.encodeRaw(elm.data, false); 17566 } else if (isComment(elm)) { 17567 return '<!--' + elm.data + '-->'; 17568 } 17569 return ''; 17570 }; 17571 const createFragment = html => { 17572 let node; 17573 const container = document.createElement('div'); 17574 const frag = document.createDocumentFragment(); 17575 if (html) { 17576 container.innerHTML = html; 17577 } 17578 while (node = container.firstChild) { 17579 frag.appendChild(node); 17580 } 17581 return frag; 17582 }; 17583 const insertAt = (elm, html, index) => { 17584 const fragment = createFragment(html); 17585 if (elm.hasChildNodes() && index < elm.childNodes.length) { 17586 const target = elm.childNodes[index]; 17587 elm.insertBefore(fragment, target); 17588 } else { 17589 elm.appendChild(fragment); 17590 } 17591 }; 17592 const removeAt = (elm, index) => { 17593 if (elm.hasChildNodes() && index < elm.childNodes.length) { 17594 const target = elm.childNodes[index]; 17595 elm.removeChild(target); 17596 } 17597 }; 17598 const applyDiff = (diff, elm) => { 17599 let index = 0; 17600 each$e(diff, action => { 17601 if (action[0] === KEEP) { 17602 index++; 17603 } else if (action[0] === INSERT) { 17604 insertAt(elm, action[1], index); 17605 index++; 17606 } else if (action[0] === DELETE) { 17607 removeAt(elm, index); 17608 } 17609 }); 17610 }; 17611 const read$2 = elm => { 17612 return filter$5(map$3(from(elm.childNodes), getOuterHtml), item => { 17613 return item.length > 0; 17614 }); 17615 }; 17616 const write = (fragments, elm) => { 17617 const currentFragments = map$3(from(elm.childNodes), getOuterHtml); 17618 applyDiff(diff(currentFragments, fragments), elm); 17619 return elm; 17620 }; 17621 17622 const lazyTempDocument = cached(() => document.implementation.createHTMLDocument('undo')); 17623 const hasIframes = html => { 17624 return html.indexOf('</iframe>') !== -1; 17625 }; 17626 const createFragmentedLevel = fragments => { 17627 return { 17628 type: 'fragmented', 17629 fragments, 17630 content: '', 17631 bookmark: null, 17632 beforeBookmark: null 17633 }; 17634 }; 17635 const createCompleteLevel = content => { 17636 return { 17637 type: 'complete', 17638 fragments: null, 17639 content, 17640 bookmark: null, 17641 beforeBookmark: null 17642 }; 17643 }; 17644 const createFromEditor = editor => { 17645 const fragments = read$2(editor.getBody()); 17646 const trimmedFragments = bind$3(fragments, html => { 17647 const trimmed = trimInternal(editor.serializer, html); 17648 return trimmed.length > 0 ? [trimmed] : []; 17649 }); 17650 const content = trimmedFragments.join(''); 17651 return hasIframes(content) ? createFragmentedLevel(trimmedFragments) : createCompleteLevel(content); 17652 }; 17653 const applyToEditor = (editor, level, before) => { 17654 const bookmark = before ? level.beforeBookmark : level.bookmark; 17655 if (level.type === 'fragmented') { 17656 write(level.fragments, editor.getBody()); 17657 } else { 17658 editor.setContent(level.content, { 17659 format: 'raw', 17660 no_selection: isNonNullable(bookmark) && isPathBookmark(bookmark) ? !bookmark.isFakeCaret : true 17661 }); 17662 } 17663 if (bookmark) { 17664 editor.selection.moveToBookmark(bookmark); 17665 editor.selection.scrollIntoView(); 17666 } 17667 }; 17668 const getLevelContent = level => { 17669 return level.type === 'fragmented' ? level.fragments.join('') : level.content; 17670 }; 17671 const getCleanLevelContent = level => { 17672 const elm = SugarElement.fromTag('body', lazyTempDocument()); 17673 set$1(elm, getLevelContent(level)); 17674 each$e(descendants(elm, '*[data-mce-bogus]'), unwrap); 17675 return get$6(elm); 17676 }; 17677 const hasEqualContent = (level1, level2) => getLevelContent(level1) === getLevelContent(level2); 17678 const hasEqualCleanedContent = (level1, level2) => getCleanLevelContent(level1) === getCleanLevelContent(level2); 17679 const isEq$1 = (level1, level2) => { 17680 if (!level1 || !level2) { 17681 return false; 17682 } else if (hasEqualContent(level1, level2)) { 17683 return true; 17684 } else { 17685 return hasEqualCleanedContent(level1, level2); 17686 } 17687 }; 17688 17689 const isUnlocked = locks => locks.get() === 0; 17690 17691 const setTyping = (undoManager, typing, locks) => { 17692 if (isUnlocked(locks)) { 17693 undoManager.typing = typing; 17694 } 17695 }; 17696 const endTyping = (undoManager, locks) => { 17697 if (undoManager.typing) { 17698 setTyping(undoManager, false, locks); 17699 undoManager.add(); 17700 } 17701 }; 17702 const endTypingLevelIgnoreLocks = undoManager => { 17703 if (undoManager.typing) { 17704 undoManager.typing = false; 17705 undoManager.add(); 17706 } 17707 }; 17708 17709 const beforeChange$1 = (editor, locks, beforeBookmark) => { 17710 if (isUnlocked(locks)) { 17711 beforeBookmark.set(getUndoBookmark(editor.selection)); 17712 } 17713 }; 17714 const addUndoLevel$1 = (editor, undoManager, index, locks, beforeBookmark, level, event) => { 17715 const currentLevel = createFromEditor(editor); 17716 const newLevel = Tools.extend(level || {}, currentLevel); 17717 if (!isUnlocked(locks) || editor.removed) { 17718 return null; 17719 } 17720 const lastLevel = undoManager.data[index.get()]; 17721 if (editor.dispatch('BeforeAddUndo', { 17722 level: newLevel, 17723 lastLevel, 17724 originalEvent: event 17725 }).isDefaultPrevented()) { 17726 return null; 17727 } 17728 if (lastLevel && isEq$1(lastLevel, newLevel)) { 17729 return null; 17730 } 17731 if (undoManager.data[index.get()]) { 17732 beforeBookmark.get().each(bm => { 17733 undoManager.data[index.get()].beforeBookmark = bm; 17734 }); 17735 } 17736 const customUndoRedoLevels = getCustomUndoRedoLevels(editor); 17737 if (customUndoRedoLevels) { 17738 if (undoManager.data.length > customUndoRedoLevels) { 17739 for (let i = 0; i < undoManager.data.length - 1; i++) { 17740 undoManager.data[i] = undoManager.data[i + 1]; 17741 } 17742 undoManager.data.length--; 17743 index.set(undoManager.data.length); 17744 } 17745 } 17746 newLevel.bookmark = getUndoBookmark(editor.selection); 17747 if (index.get() < undoManager.data.length - 1) { 17748 undoManager.data.length = index.get() + 1; 17749 } 17750 undoManager.data.push(newLevel); 17751 index.set(undoManager.data.length - 1); 17752 const args = { 17753 level: newLevel, 17754 lastLevel, 17755 originalEvent: event 17756 }; 17757 if (index.get() > 0) { 17758 editor.setDirty(true); 17759 editor.dispatch('AddUndo', args); 17760 editor.dispatch('change', args); 17761 } else { 17762 editor.dispatch('AddUndo', args); 17763 } 17764 return newLevel; 17765 }; 17766 const clear$1 = (editor, undoManager, index) => { 17767 undoManager.data = []; 17768 index.set(0); 17769 undoManager.typing = false; 17770 editor.dispatch('ClearUndos'); 17771 }; 17772 const extra$1 = (editor, undoManager, index, callback1, callback2) => { 17773 if (undoManager.transact(callback1)) { 17774 const bookmark = undoManager.data[index.get()].bookmark; 17775 const lastLevel = undoManager.data[index.get() - 1]; 17776 applyToEditor(editor, lastLevel, true); 17777 if (undoManager.transact(callback2)) { 17778 undoManager.data[index.get() - 1].beforeBookmark = bookmark; 17779 } 17780 } 17781 }; 17782 const redo$1 = (editor, index, data) => { 17783 let level; 17784 if (index.get() < data.length - 1) { 17785 index.set(index.get() + 1); 17786 level = data[index.get()]; 17787 applyToEditor(editor, level, false); 17788 editor.setDirty(true); 17789 editor.dispatch('Redo', { level }); 17790 } 17791 return level; 17792 }; 17793 const undo$1 = (editor, undoManager, locks, index) => { 17794 let level; 17795 if (undoManager.typing) { 17796 undoManager.add(); 17797 undoManager.typing = false; 17798 setTyping(undoManager, false, locks); 17799 } 17800 if (index.get() > 0) { 17801 index.set(index.get() - 1); 17802 level = undoManager.data[index.get()]; 17803 applyToEditor(editor, level, true); 17804 editor.setDirty(true); 17805 editor.dispatch('Undo', { level }); 17806 } 17807 return level; 17808 }; 17809 const reset$1 = undoManager => { 17810 undoManager.clear(); 17811 undoManager.add(); 17812 }; 17813 const hasUndo$1 = (editor, undoManager, index) => index.get() > 0 || undoManager.typing && undoManager.data[0] && !isEq$1(createFromEditor(editor), undoManager.data[0]); 17814 const hasRedo$1 = (undoManager, index) => index.get() < undoManager.data.length - 1 && !undoManager.typing; 17815 const transact$1 = (undoManager, locks, callback) => { 17816 endTyping(undoManager, locks); 17817 undoManager.beforeChange(); 17818 undoManager.ignore(callback); 17819 return undoManager.add(); 17820 }; 17821 const ignore$1 = (locks, callback) => { 17822 try { 17823 locks.set(locks.get() + 1); 17824 callback(); 17825 } finally { 17826 locks.set(locks.get() - 1); 17827 } 17828 }; 17829 17830 const addVisualInternal = (editor, elm) => { 17831 const dom = editor.dom; 17832 const scope = isNonNullable(elm) ? elm : editor.getBody(); 17833 each$e(dom.select('table,a', scope), matchedElm => { 17834 switch (matchedElm.nodeName) { 17835 case 'TABLE': 17836 const cls = getVisualAidsTableClass(editor); 17837 const value = dom.getAttrib(matchedElm, 'border'); 17838 if ((!value || value === '0') && editor.hasVisual) { 17839 dom.addClass(matchedElm, cls); 17840 } else { 17841 dom.removeClass(matchedElm, cls); 17842 } 17843 break; 17844 case 'A': 17845 if (!dom.getAttrib(matchedElm, 'href')) { 17846 const value = dom.getAttrib(matchedElm, 'name') || matchedElm.id; 17847 const cls = getVisualAidsAnchorClass(editor); 17848 if (value && editor.hasVisual) { 17849 dom.addClass(matchedElm, cls); 17850 } else { 17851 dom.removeClass(matchedElm, cls); 17852 } 17853 } 17854 break; 17855 } 17856 }); 17857 editor.dispatch('VisualAid', { 17858 element: elm, 17859 hasVisual: editor.hasVisual 17860 }); 17861 }; 17862 17863 const makePlainAdaptor = editor => ({ 17864 init: { bindEvents: noop }, 17865 undoManager: { 17866 beforeChange: (locks, beforeBookmark) => beforeChange$1(editor, locks, beforeBookmark), 17867 add: (undoManager, index, locks, beforeBookmark, level, event) => addUndoLevel$1(editor, undoManager, index, locks, beforeBookmark, level, event), 17868 undo: (undoManager, locks, index) => undo$1(editor, undoManager, locks, index), 17869 redo: (index, data) => redo$1(editor, index, data), 17870 clear: (undoManager, index) => clear$1(editor, undoManager, index), 17871 reset: undoManager => reset$1(undoManager), 17872 hasUndo: (undoManager, index) => hasUndo$1(editor, undoManager, index), 17873 hasRedo: (undoManager, index) => hasRedo$1(undoManager, index), 17874 transact: (undoManager, locks, callback) => transact$1(undoManager, locks, callback), 17875 ignore: (locks, callback) => ignore$1(locks, callback), 17876 extra: (undoManager, index, callback1, callback2) => extra$1(editor, undoManager, index, callback1, callback2) 17877 }, 17878 formatter: { 17879 match: (name, vars, node, similar) => match$2(editor, name, vars, node, similar), 17880 matchAll: (names, vars) => matchAll(editor, names, vars), 17881 matchNode: (node, name, vars, similar) => matchNode(editor, node, name, vars, similar), 17882 canApply: name => canApply(editor, name), 17883 closest: names => closest(editor, names), 17884 apply: (name, vars, node) => applyFormat$1(editor, name, vars, node), 17885 remove: (name, vars, node, similar) => remove
17885$2(editor, name, vars, node, similar), 17886 toggle: (name, vars, node) => toggle(editor, name, vars, node), 17887 formatChanged: (registeredFormatListeners, formats, callback, similar, vars) => formatChangedInternal(editor, registeredFormatListeners, formats, callback, similar, vars) 17888 }, 17889 editor: { 17890 getContent: args => getContentInternal(editor, args), 17891 setContent: (content, args) => setContentInternal(editor, content, args), 17892 insertContent: (value, details) => insertHtmlAtCaret(editor, value, details), 17893 addVisual: elm => addVisualInternal(editor, elm) 17894 }, 17895 selection: { getContent: (format, args) => getSelectedContentInternal(editor, format, args) }, 17896 autocompleter: { 17897 addDecoration: range => create$9(editor, range), 17898 removeDecoration: () => remove$3
vendor: 8,579 bytes, lines 17898-18075
17898(editor, SugarElement.fromDom(editor.getBody())) 17899 }, 17900 raw: { getModel: () => Optional.none() } 17901 }); 17902 const makeRtcAdaptor = rtcEditor => { 17903 const defaultVars = vars => isObject(vars) ? vars : {}; 17904 const {init, undoManager, formatter, editor, selection, autocompleter, raw} = rtcEditor; 17905 return { 17906 init: { bindEvents: init.bindEvents }, 17907 undoManager: { 17908 beforeChange: undoManager.beforeChange, 17909 add: undoManager.add, 17910 undo: undoManager.undo, 17911 redo: undoManager.redo, 17912 clear: undoManager.clear, 17913 reset: undoManager.reset, 17914 hasUndo: undoManager.hasUndo, 17915 hasRedo: undoManager.hasRedo, 17916 transact: (_undoManager, _locks, fn) => undoManager.transact(fn), 17917 ignore: (_locks, callback) => undoManager.ignore(callback), 17918 extra: (_undoManager, _index, callback1, callback2) => undoManager.extra(callback1, callback2) 17919 }, 17920 formatter: { 17921 match: (name, vars, _node, similar) => formatter.match(name, defaultVars(vars), similar), 17922 matchAll: formatter.matchAll, 17923 matchNode: formatter.matchNode, 17924 canApply: name => formatter.canApply(name), 17925 closest: names => formatter.closest(names), 17926 apply: (name, vars, _node) => formatter.apply(name, defaultVars(vars)), 17927 remove: (name, vars, _node, _similar) => formatter.remove(name, defaultVars(vars)), 17928 toggle: (name, vars, _node) => formatter.toggle(name, defaultVars(vars)), 17929 formatChanged: (_rfl, formats, callback, similar, vars) => formatter.formatChanged(formats, callback, similar, vars) 17930 }, 17931 editor: { 17932 getContent: args => editor.getContent(args), 17933 setContent: (content, args) => { 17934 return { 17935 content: editor.setContent(content, args), 17936 html: '' 17937 }; 17938 }, 17939 insertContent: (content, _details) => { 17940 editor.insertContent(content); 17941 return ''; 17942 }, 17943 addVisual: editor.addVisual 17944 }, 17945 selection: { getContent: (_format, args) => selection.getContent(args) }, 17946 autocompleter: { 17947 addDecoration: autocompleter.addDecoration, 17948 removeDecoration: autocompleter.removeDecoration 17949 }, 17950 raw: { getModel: () => Optional.some(raw.getRawModel()) } 17951 }; 17952 }; 17953 const makeNoopAdaptor = () => { 17954 const nul = constant(null); 17955 const empty = constant(''); 17956 return { 17957 init: { bindEvents: noop }, 17958 undoManager: { 17959 beforeChange: noop, 17960 add: nul, 17961 undo: nul, 17962 redo: nul, 17963 clear: noop, 17964 reset: noop, 17965 hasUndo: never, 17966 hasRedo: never, 17967 transact: nul, 17968 ignore: noop, 17969 extra: noop 17970 }, 17971 formatter: { 17972 match: never, 17973 matchAll: constant([]), 17974 matchNode: constant(undefined), 17975 canApply: never, 17976 closest: empty, 17977 apply: noop, 17978 remove: noop, 17979 toggle: noop, 17980 formatChanged: constant({ unbind: noop }) 17981 }, 17982 editor: { 17983 getContent: empty, 17984 setContent: constant({ 17985 content: '', 17986 html: '' 17987 }), 17988 insertContent: constant(''), 17989 addVisual: noop 17990 }, 17991 selection: { getContent: empty }, 17992 autocompleter: { 17993 addDecoration: noop, 17994 removeDecoration: noop 17995 }, 17996 raw: { getModel: constant(Optional.none()) } 17997 }; 17998 }; 17999 const isRtc = editor => has$2(editor.plugins, 'rtc'); 18000 const getRtcSetup = editor => get$a(editor.plugins, 'rtc').bind(rtcPlugin => Optional.from(rtcPlugin.setup)); 18001 const setup$s = editor => { 18002 const editorCast = editor; 18003 return getRtcSetup(editor).fold(() => { 18004 editorCast.rtcInstance = makePlainAdaptor(editor); 18005 return Optional.none(); 18006 }, setup => { 18007 editorCast.rtcInstance = makeNoopAdaptor(); 18008 return Optional.some(() => setup().then(rtcEditor => { 18009 editorCast.rtcInstance = makeRtcAdaptor(rtcEditor); 18010 return rtcEditor.rtc.isRemote; 18011 })); 18012 }); 18013 }; 18014 const getRtcInstanceWithFallback = editor => editor.rtcInstance ? editor.rtcInstance : makePlainAdaptor(editor); 18015 const getRtcInstanceWithError = editor => { 18016 const rtcInstance = editor.rtcInstance; 18017 if (!rtcInstance) { 18018 throw new Error('Failed to get RTC instance not yet initialized.'); 18019 } else { 18020 return rtcInstance; 18021 } 18022 }; 18023 const beforeChange = (editor, locks, beforeBookmark) => { 18024 getRtcInstanceWithError(editor).undoManager.beforeChange(locks, beforeBookmark); 18025 }; 18026 const addUndoLevel = (editor, undoManager, index, locks, beforeBookmark, level, event) => getRtcInstanceWithError(editor).undoManager.add(undoManager, index, locks, beforeBookmark, level, event); 18027 const undo = (editor, undoManager, locks, index) => getRtcInstanceWithError(editor).undoManager.undo(undoManager, locks, index); 18028 const redo = (editor, index, data) => getRtcInstanceWithError(editor).undoManager.redo(index, data); 18029 const clear = (editor, undoManager, index) => { 18030 getRtcInstanceWithError(editor).undoManager.clear(undoManager, index); 18031 }; 18032 const reset = (editor, undoManager) => { 18033 getRtcInstanceWithError(editor).undoManager.reset(undoManager); 18034 }; 18035 const hasUndo = (editor, undoManager, index) => getRtcInstanceWithError(editor).undoManager.hasUndo(undoManager, index); 18036 const hasRedo = (editor, undoManager, index) => getRtcInstanceWithError(editor).undoManager.hasRedo(undoManager, index); 18037 const transact = (editor, undoManager, locks, callback) => getRtcInstanceWithError(editor).undoManager.transact(undoManager, locks, callback); 18038 const ignore = (editor, locks, callback) => { 18039 getRtcInstanceWithError(editor).undoManager.ignore(locks, callback); 18040 }; 18041 const extra = (editor, undoManager, index, callback1, callback2) => { 18042 getRtcInstanceWithError(editor).undoManager.extra(undoManager, index, callback1, callback2); 18043 }; 18044 const matchFormat = (editor, name, vars, node, similar) => getRtcInstanceWithError(editor).formatter.match(name, vars, node, similar); 18045 const matchAllFormats = (editor, names, vars) => getRtcInstanceWithError(editor).formatter.matchAll(names, vars); 18046 const matchNodeFormat = (editor, node, name, vars, similar) => getRtcInstanceWithError(editor).formatter.matchNode(node, name, vars, similar); 18047 const canApplyFormat = (editor, name) => getRtcInstanceWithError(editor).formatter.canApply(name); 18048 const closestFormat = (editor, names) => getRtcInstanceWithError(editor).formatter.closest(names); 18049 const applyFormat = (editor, name, vars, node) => { 18050 getRtcInstanceWithError(editor).formatter.apply(name, vars, node); 18051 }; 18052 const removeFormat = (editor, name, vars, node, similar) => { 18053 getRtcInstanceWithError(editor).formatter.remove(name, vars, node, similar); 18054 }; 18055 const toggleFormat = (editor, name, vars, node) => { 18056 getRtcInstanceWithError(editor).formatter.toggle(name, vars, node); 18057 }; 18058 const formatChanged = (editor, registeredFormatListeners, formats, callback, similar, vars) => getRtcInstanceWithError(editor).formatter.formatChanged(registeredFormatListeners, formats, callback, similar, vars); 18059 const getContent$2 = (editor, args) => getRtcInstanceWithFallback(editor).editor.getContent(args); 18060 const setContent$2 = (editor, content, args) => getRtcInstanceWithFallback(editor).editor.setContent(content, args); 18061 const insertContent$1 = (editor, value, details) => getRtcInstanceWithFallback(editor).editor.insertContent(value, details); 18062 const getSelectedContent = (editor, format, args) => getRtcInstanceWithError(editor).selection.getContent(format, args); 18063 const addVisual$1 = (editor, elm) => getRtcInstanceWithError(editor).editor.addVisual(elm); 18064 const bindEvents = editor => getRtcInstanceWithError(editor).init.bindEvents(); 18065 const addAutocompleterDecoration = (editor, range) => getRtcInstanceWithError(editor).autocompleter.addDecoration(range); 18066 const removeAutocompleterDecoration = editor => getRtcInstanceWithError(editor).autocompleter.removeDecoration(); 18067 18068 const getContent$1 = (editor, args = {}) => { 18069 const format = args.format ? args.format : 'html'; 18070 return getSelectedContent(editor, format, args); 18071 }; 18072 18073 const removeEmpty = text => { 18074 if (text.dom.length === 0) { 18075 remove$
180756
vendor: 17,637 bytes, lines 18075-18541
18075(text); 18076 return Optional.none(); 18077 } else { 18078 return Optional.some(text); 18079 } 18080 }; 18081 const walkPastBookmark = (node, start) => node.filter(elm => BookmarkManager.isBookmarkNode(elm.dom)).bind(start ? nextSibling : prevSibling); 18082 const merge$1 = (outer, inner, rng, start) => { 18083 const outerElm = outer.dom; 18084 const innerElm = inner.dom; 18085 const oldLength = start ? outerElm.length : innerElm.length; 18086 if (start) { 18087 mergeTextNodes(outerElm, innerElm, false, !start); 18088 rng.setStart(innerElm, oldLength); 18089 } else { 18090 mergeTextNodes(innerElm, outerElm, false, !start); 18091 rng.setEnd(innerElm, oldLength); 18092 } 18093 }; 18094 const normalizeTextIfRequired = (inner, start) => { 18095 parent(inner).each(root => { 18096 const text = inner.dom; 18097 if (start && needsToBeNbspLeft(root, CaretPosition(text, 0))) { 18098 normalizeWhitespaceAfter(text, 0); 18099 } else if (!start && needsToBeNbspRight(root, CaretPosition(text, text.length))) { 18100 normalizeWhitespaceBefore(text, text.length); 18101 } 18102 }); 18103 }; 18104 const mergeAndNormalizeText = (outerNode, innerNode, rng, start) => { 18105 outerNode.bind(outer => { 18106 const normalizer = start ? normalizeWhitespaceBefore : normalizeWhitespaceAfter; 18107 normalizer(outer.dom, start ? outer.dom.length : 0); 18108 return innerNode.filter(isText$b).map(inner => merge$1(outer, inner, rng, start)); 18109 }).orThunk(() => { 18110 const innerTextNode = walkPastBookmark(innerNode, start).or(innerNode).filter(isText$b); 18111 return innerTextNode.map(inner => normalizeTextIfRequired(inner, start)); 18112 }); 18113 }; 18114 const rngSetContent = (rng, fragment) => { 18115 const firstChild = Optional.from(fragment.firstChild).map(SugarElement.fromDom); 18116 const lastChild = Optional.from(fragment.lastChild).map(SugarElement.fromDom); 18117 rng.deleteContents(); 18118 rng.insertNode(fragment); 18119 const prevText = firstChild.bind(prevSibling).filter(isText$b).bind(removeEmpty); 18120 const nextText = lastChild.bind(nextSibling).filter(isText$b).bind(removeEmpty); 18121 mergeAndNormalizeText(prevText, firstChild, rng, true); 18122 mergeAndNormalizeText(nextText, lastChild, rng, false); 18123 rng.collapse(false); 18124 }; 18125 const setupArgs$2 = (args, content) => ({ 18126 format: 'html', 18127 ...args, 18128 set: true, 18129 selection: true, 18130 content 18131 }); 18132 const cleanContent = (editor, args) => { 18133 if (args.format !== 'raw') { 18134 const rng = editor.selection.getRng(); 18135 const contextBlock = editor.dom.getParent(rng.commonAncestorContainer, editor.dom.isBlock); 18136 const contextArgs = contextBlock ? { context: contextBlock.nodeName.toLowerCase() } : {}; 18137 const node = editor.parser.parse(args.content, { 18138 forced_root_block: false, 18139 ...contextArgs, 18140 ...args 18141 }); 18142 return HtmlSerializer({ validate: false }, editor.schema).serialize(node); 18143 } else { 18144 return args.content; 18145 } 18146 }; 18147 const setContent$1 = (editor, content, args = {}) => { 18148 const defaultedArgs = setupArgs$2(args, content); 18149 preProcessSetContent(editor, defaultedArgs).each(updatedArgs => { 18150 const cleanedContent = cleanContent(editor, updatedArgs); 18151 const rng = editor.selection.getRng(); 18152 rngSetContent(rng, rng.createContextualFragment(cleanedContent)); 18153 editor.selection.setRng(rng); 18154 scrollRangeIntoView(editor, rng); 18155 postProcessSetContent(editor, cleanedContent, updatedArgs); 18156 }); 18157 }; 18158 18159 const deleteFromCallbackMap = (callbackMap, selector, callback) => { 18160 if (has$2(callbackMap, selector)) { 18161 const newCallbacks = filter$5(callbackMap[selector], cb => cb !== callback); 18162 if (newCallbacks.length === 0) { 18163 delete callbackMap[selector]; 18164 } else { 18165 callbackMap[selector] = newCallbacks; 18166 } 18167 } 18168 }; 18169 var SelectorChanged = (dom, editor) => { 18170 let selectorChangedData; 18171 let currentSelectors; 18172 const findMatchingNode = (selector, nodes) => find$2(nodes, node => dom.is(node, selector)); 18173 const getParents = elem => dom.getParents(elem, undefined, dom.getRoot()); 18174 const setup = () => { 18175 selectorChangedData = {}; 18176 currentSelectors = {}; 18177 editor.on('NodeChange', e => { 18178 const node = e.element; 18179 const parents = getParents(node); 18180 const matchedSelectors = {}; 18181 each$d(selectorChangedData, (callbacks, selector) => { 18182 findMatchingNode(selector, parents).each(node => { 18183 if (!currentSelectors[selector]) { 18184 each$e(callbacks, callback => { 18185 callback(true, { 18186 node, 18187 selector, 18188 parents 18189 }); 18190 }); 18191 currentSelectors[selector] = callbacks; 18192 } 18193 matchedSelectors[selector] = callbacks; 18194 }); 18195 }); 18196 each$d(currentSelectors, (callbacks, selector) => { 18197 if (!matchedSelectors[selector]) { 18198 delete currentSelectors[selector]; 18199 each$e(callbacks, callback => { 18200 callback(false, { 18201 node, 18202 selector, 18203 parents 18204 }); 18205 }); 18206 } 18207 }); 18208 }); 18209 }; 18210 return { 18211 selectorChangedWithUnbind: (selector, callback) => { 18212 if (!selectorChangedData) { 18213 setup(); 18214 } 18215 if (!selectorChangedData[selector]) { 18216 selectorChangedData[selector] = []; 18217 } 18218 selectorChangedData[selector].push(callback); 18219 findMatchingNode(selector, getParents(editor.selection.getStart())).each(() => { 18220 currentSelectors[selector] = selectorChangedData[selector]; 18221 }); 18222 return { 18223 unbind: () => { 18224 deleteFromCallbackMap(selectorChangedData, selector, callback); 18225 deleteFromCallbackMap(currentSelectors, selector, callback); 18226 } 18227 }; 18228 } 18229 }; 18230 }; 18231 18232 const isAttachedToDom = node => { 18233 return !!(node && node.ownerDocument) && contains(SugarElement.fromDom(node.ownerDocument), SugarElement.fromDom(node)); 18234 }; 18235 const isValidRange = rng => { 18236 if (!rng) { 18237 return false; 18238 } else { 18239 return isAttachedToDom(rng.startContainer) && isAttachedToDom(rng.endContainer); 18240 } 18241 }; 18242 const EditorSelection = (dom, win, serializer, editor) => { 18243 let selectedRange; 18244 let explicitRange; 18245 const {selectorChangedWithUnbind} = SelectorChanged(dom, editor); 18246 const setCursorLocation = (node, offset) => { 18247 const rng = dom.createRng(); 18248 if (isNonNullable(node) && isNonNullable(offset)) { 18249 rng.setStart(node, offset); 18250 rng.setEnd(node, offset); 18251 setRng(rng); 18252 collapse(false); 18253 } else { 18254 moveEndPoint(dom, rng, editor.getBody(), true); 18255 setRng(rng); 18256 } 18257 }; 18258 const getContent = args => getContent$1(editor, args); 18259 const setContent = (content, args) => setContent$1(editor, content, args); 18260 const getStart$1 = real => getStart(editor.getBody(), getRng$1(), real); 18261 const getEnd = real => getEnd$1(editor.getBody(), getRng$1(), real); 18262 const getBookmark = (type, normalized) => bookmarkManager.getBookmark(type, normalized); 18263 const moveToBookmark = bookmark => bookmarkManager.moveToBookmark(bookmark); 18264 const select$1 = (node, content) => { 18265 select(dom, node, content).each(setRng); 18266 return node; 18267 }; 18268 const isCollapsed = () => { 18269 const rng = getRng$1(), sel = getSel(); 18270 if (!rng || rng.item) { 18271 return false; 18272 } 18273 if (rng.compareEndPoints) { 18274 return rng.compareEndPoints('StartToEnd', rng) === 0; 18275 } 18276 return !sel || rng.collapsed; 18277 }; 18278 const isEditable = () => { 18279 const rng = getRng$1(); 18280 const fakeSelectedElements = editor.getBody().querySelectorAll('[data-mce-selected="1"]'); 18281 if (fakeSelectedElements.length > 0) { 18282 return forall(fakeSelectedElements, el => dom.isEditable(el.parentElement)); 18283 } else if (rng.startContainer === rng.endContainer) { 18284 return dom.isEditable(rng.startContainer); 18285 } else { 18286 return dom.isEditable(rng.startContainer) && dom.isEditable(rng.endContainer); 18287 } 18288 }; 18289 const collapse = toStart => { 18290 const rng = getRng$1(); 18291 rng.collapse(!!toStart); 18292 setRng(rng); 18293 }; 18294 const getSel = () => win.getSelection ? win.getSelection() : win.document.selection; 18295 const getRng$1 = () => { 18296 let rng; 18297 const tryCompareBoundaryPoints = (how, sourceRange, destinationRange) => { 18298 try { 18299 return sourceRange.compareBoundaryPoints(how, destinationRange); 18300 } catch (ex) { 18301 return -1; 18302 } 18303 }; 18304 const doc = win.document; 18305 if (isNonNullable(editor.bookmark) && !hasFocus(editor)) { 18306 const bookmark = getRng(editor); 18307 if (bookmark.isSome()) { 18308 return bookmark.map(r => processRanges(editor, [r])[0]).getOr(doc.createRange()); 18309 } 18310 } 18311 try { 18312 const selection = getSel(); 18313 if (selection && !isRestrictedNode(selection.anchorNode)) { 18314 if (selection.rangeCount > 0) { 18315 rng = selection.getRangeAt(0); 18316 } else { 18317 rng = doc.createRange(); 18318 } 18319 rng = processRanges(editor, [rng])[0]; 18320 } 18321 } catch (ex) { 18322 } 18323 if (!rng) { 18324 rng = doc.createRange(); 18325 } 18326 if (isDocument$1(rng.startContainer) && rng.collapsed) { 18327 const elm = dom.getRoot(); 18328 rng.setStart(elm, 0); 18329 rng.setEnd(elm, 0); 18330 } 18331 if (selectedRange && explicitRange) { 18332 if (tryCompareBoundaryPoints(rng.START_TO_START, rng, selectedRange) === 0 && tryCompareBoundaryPoints(rng.END_TO_END, rng, selectedRange) === 0) { 18333 rng = explicitRange; 18334 } else { 18335 selectedRange = null; 18336 explicitRange = null; 18337 } 18338 } 18339 return rng; 18340 }; 18341 const setRng = (rng, forward) => { 18342 if (!isValidRange(rng)) { 18343 return; 18344 } 18345 const sel = getSel(); 18346 const evt = editor.dispatch('SetSelectionRange', { 18347 range: rng, 18348 forward 18349 }); 18350 rng = evt.range; 18351 if (sel) { 18352 explicitRange = rng; 18353 try { 18354 sel.removeAllRanges(); 18355 sel.addRange(rng); 18356 } catch (ex) { 18357 } 18358 if (forward === false && sel.extend) { 18359 sel.collapse(rng.endContainer, rng.endOffset); 18360 sel.extend(rng.startContainer, rng.startOffset); 18361 } 18362 selectedRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null; 18363 } 18364 if (!rng.collapsed && rng.startContainer === rng.endContainer && (sel === null || sel === void 0 ? void 0 : sel.setBaseAndExtent)) { 18365 if (rng.endOffset - rng.startOffset < 2) { 18366 if (rng.startContainer.hasChildNodes()) { 18367 const node = rng.startContainer.childNodes[rng.startOffset]; 18368 if (node && node.nodeName === 'IMG') { 18369 sel.setBaseAndExtent(rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset); 18370 if (sel.anchorNode !== rng.startContainer || sel.focusNode !== rng.endContainer) { 18371 sel.setBaseAndExtent(node, 0, node, 1); 18372 } 18373 } 18374 } 18375 } 18376 } 18377 editor.dispatch('AfterSetSelectionRange', { 18378 range: rng, 18379 forward 18380 }); 18381 }; 18382 const setNode = elm => { 18383 setContent(dom.getOuterHTML(elm)); 18384 return elm; 18385 }; 18386 const getNode$1 = () => getNode(editor.getBody(), getRng$1()); 18387 const getSelectedBlocks$1 = (startElm, endElm) => getSelectedBlocks(dom, getRng$1(), startElm, endElm); 18388 const isForward = () => { 18389 const sel = getSel(); 18390 const anchorNode = sel === null || sel === void 0 ? void 0 : sel.anchorNode; 18391 const focusNode = sel === null || sel === void 0 ? void 0 : sel.focusNode; 18392 if (!sel || !anchorNode || !focusNode || isRestrictedNode(anchorNode) || isRestrictedNode(focusNode)) { 18393 return true; 18394 } 18395 const anchorRange = dom.createRng(); 18396 const focusRange = dom.createRng(); 18397 try { 18398 anchorRange.setStart(anchorNode, sel.anchorOffset); 18399 anchorRange.collapse(true); 18400 focusRange.setStart(focusNode, sel.focusOffset); 18401 focusRange.collapse(true); 18402 } catch (e) { 18403 return true; 18404 } 18405 return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0; 18406 }; 18407 const normalize = () => { 18408 const rng = getRng$1(); 18409 const sel = getSel(); 18410 if (!hasMultipleRanges(sel) && hasAnyRanges(editor)) { 18411 const normRng = normalize$2(dom, rng); 18412 normRng.each(normRng => { 18413 setRng(normRng, isForward()); 18414 }); 18415 return normRng.getOr(rng); 18416 } 18417 return rng; 18418 }; 18419 const selectorChanged = (selector, callback) => { 18420 selectorChangedWithUnbind(selector, callback); 18421 return exports; 18422 }; 18423 const getScrollContainer = () => { 18424 let scrollContainer; 18425 let node = dom.getRoot(); 18426 while (node && node.nodeName !== 'BODY') { 18427 if (node.scrollHeight > node.clientHeight) { 18428 scrollContainer = node; 18429 break; 18430 } 18431 node = node.parentNode; 18432 } 18433 return scrollContainer; 18434 }; 18435 const scrollIntoView = (elm, alignToTop) => { 18436 if (isNonNullable(elm)) { 18437 scrollElementIntoView(editor, elm, alignToTop); 18438 } else { 18439 scrollRangeIntoView(editor, getRng$1(), alignToTop); 18440 } 18441 }; 18442 const placeCaretAt = (clientX, clientY) => setRng(fromPoint(clientX, clientY, editor.getDoc())); 18443 const getBoundingClientRect = () => { 18444 const rng = getRng$1(); 18445 return rng.collapsed ? CaretPosition.fromRangeStart(rng).getClientRects()[0] : rng.getBoundingClientRect(); 18446 }; 18447 const destroy = () => { 18448 win = selectedRange = explicitRange = null; 18449 controlSelection.destroy(); 18450 }; 18451 const expand = (options = { type: 'word' }) => setRng(RangeUtils(dom).expand(getRng$1(), options)); 18452 const exports = { 18453 dom, 18454 win, 18455 serializer, 18456 editor, 18457 expand, 18458 collapse, 18459 setCursorLocation, 18460 getContent, 18461 setContent, 18462 getBookmark, 18463 moveToBookmark, 18464 select: select$1, 18465 isCollapsed, 18466 isEditable, 18467 isForward, 18468 setNode, 18469 getNode: getNode$1, 18470 getSel, 18471 setRng, 18472 getRng: getRng$1, 18473 getStart: getStart$1, 18474 getEnd, 18475 getSelectedBlocks: getSelectedBlocks$1, 18476 normalize, 18477 selectorChanged, 18478 selectorChangedWithUnbind, 18479 getScrollContainer, 18480 scrollIntoView, 18481 placeCaretAt, 18482 getBoundingClientRect, 18483 destroy 18484 }; 18485 const bookmarkManager = BookmarkManager(exports); 18486 const controlSelection = ControlSelection(exports, editor); 18487 exports.bookmarkManager = bookmarkManager; 18488 exports.controlSelection = controlSelection; 18489 return exports; 18490 }; 18491 18492 const register$3 = (htmlParser, settings, dom) => { 18493 htmlParser.addAttributeFilter('data-mce-tabindex', (nodes, name) => { 18494 let i = nodes.length; 18495 while (i--) { 18496 const node = nodes[i]; 18497 node.attr('tabindex', node.attr('data-mce-tabindex')); 18498 node.attr(name, null); 18499 } 18500 }); 18501 htmlParser.addAttributeFilter('src,href,style', (nodes, name) => { 18502 const internalName = 'data-mce-' + name; 18503 const urlConverter = settings.url_converter; 18504 const urlConverterScope = settings.url_converter_scope; 18505 let i = nodes.length; 18506 while (i--) { 18507 const node = nodes[i]; 18508 let value = node.attr(internalName); 18509 if (value !== undefined) { 18510 node.attr(name, value.length > 0 ? value : null); 18511 node.attr(internalName, null); 18512 } else { 18513 value = node.attr(name); 18514 if (name === 'style') { 18515 value = dom.serializeStyle(dom.parseStyle(value), node.name); 18516 } else if (urlConverter) { 18517 value = urlConverter.call(urlConverterScope, value, name, node.name); 18518 } 18519 node.attr(name, value.length > 0 ? value : null); 18520 } 18521 } 18522 }); 18523 htmlParser.addAttributeFilter('class', nodes => { 18524 let i = nodes.length; 18525 while (i--) { 18526 const node = nodes[i]; 18527 let value = node.attr('class'); 18528 if (value) { 18529 value = value.replace(/(?:^|\s)mce-item-\w+(?!\S)/g, ''); 18530 node.attr('class', value.length > 0 ? value : null); 18531 } 18532 } 18533 }); 18534 htmlParser.addAttributeFilter('data-mce-type', (nodes, name, args) => { 18535 let i = nodes.length; 18536 while (i--) { 18537 const node = nodes[i]; 18538 if (node.attr('data-mce-type') === 'bookmark' && !args.cleanup) { 18539 const hasChildren = Optional.from(node.firstChild).exists(firstChild => { 18540 var _a; 18541 return !isZwsp
vendor: 6,082 bytes, lines 18541-18707
18541((_a = firstChild.value) !== null && _a !== void 0 ? _a : ''); 18542 }); 18543 if (hasChildren) { 18544 node.unwrap(); 18545 } else { 18546 node.remove(); 18547 } 18548 } 18549 } 18550 }); 18551 htmlParser.addNodeFilter('noscript', nodes => { 18552 var _a; 18553 let i = nodes.length; 18554 while (i--) { 18555 const node = nodes[i].firstChild; 18556 if (node) { 18557 node.value = Entities.decode((_a = node.value) !== null && _a !== void 0 ? _a : ''); 18558 } 18559 } 18560 }); 18561 htmlParser.addNodeFilter('script,style', (nodes, name) => { 18562 var _a; 18563 const trim = value => { 18564 return value.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n').replace(/^[\r\n]*|[\r\n]*$/g, '').replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi, '').replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, ''); 18565 }; 18566 let i = nodes.length; 18567 while (i--) { 18568 const node = nodes[i]; 18569 const firstChild = node.firstChild; 18570 const value = (_a = firstChild === null || firstChild === void 0 ? void 0 : firstChild.value) !== null && _a !== void 0 ? _a : ''; 18571 if (name === 'script') { 18572 const type = node.attr('type'); 18573 if (type) { 18574 node.attr('type', type === 'mce-no/type' ? null : type.replace(/^mce\-/, '')); 18575 } 18576 if (settings.element_format === 'xhtml' && firstChild && value.length > 0) { 18577 firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>'; 18578 } 18579 } else { 18580 if (settings.element_format === 'xhtml' && firstChild && value.length > 0) { 18581 firstChild.value = '<!--\n' + trim(value) + '\n-->'; 18582 } 18583 } 18584 } 18585 }); 18586 htmlParser.addNodeFilter('#comment', nodes => { 18587 let i = nodes.length; 18588 while (i--) { 18589 const node = nodes[i]; 18590 const value = node.value; 18591 if (settings.preserve_cdata && (value === null || value === void 0 ? void 0 : value.indexOf('[CDATA[')) === 0) { 18592 node.name = '#cdata'; 18593 node.type = 4; 18594 node.value = dom.decode(value.replace(/^\[CDATA\[|\]\]$/g, '')); 18595 } else if ((value === null || value === void 0 ? void 0 : value.indexOf('mce:protected ')) === 0) { 18596 node.name = '#text'; 18597 node.type = 3; 18598 node.raw = true; 18599 node.value = unescape(value).substr(14); 18600 } 18601 } 18602 }); 18603 htmlParser.addNodeFilter('xml:namespace,input', (nodes, name) => { 18604 let i = nodes.length; 18605 while (i--) { 18606 const node = nodes[i]; 18607 if (node.type === 7) { 18608 node.remove(); 18609 } else if (node.type === 1) { 18610 if (name === 'input' && !node.attr('type')) { 18611 node.attr('type', 'text'); 18612 } 18613 } 18614 } 18615 }); 18616 htmlParser.addAttributeFilter('data-mce-type', nodes => { 18617 each$e(nodes, node => { 18618 if (node.attr('data-mce-type') === 'format-caret') { 18619 if (node.isEmpty(htmlParser.schema.getNonEmptyElements())) { 18620 node.remove(); 18621 } else { 18622 node.unwrap(); 18623 } 18624 } 18625 }); 18626 }); 18627 htmlParser.addAttributeFilter('data-mce-src,data-mce-href,data-mce-style,' + 'data-mce-selected,data-mce-expando,data-mce-block,' + 'data-mce-type,data-mce-resize,data-mce-placeholder', (nodes, name) => { 18628 let i = nodes.length; 18629 while (i--) { 18630 nodes[i].attr(name, null); 18631 } 18632 }); 18633 }; 18634 const trimTrailingBr = rootNode => { 18635 const isBr = node => { 18636 return (node === null || node === void 0 ? void 0 : node.name) === 'br'; 18637 }; 18638 const brNode1 = rootNode.lastChild; 18639 if (isBr(brNode1)) { 18640 const brNode2 = brNode1.prev; 18641 if (isBr(brNode2)) { 18642 brNode1.remove(); 18643 brNode2.remove(); 18644 } 18645 } 18646 }; 18647 18648 const preProcess$1 = (editor, node, args) => { 18649 let oldDoc; 18650 const dom = editor.dom; 18651 let clonedNode = node.cloneNode(true); 18652 const impl = document.implementation; 18653 if (impl.createHTMLDocument) { 18654 const doc = impl.createHTMLDocument(''); 18655 Tools.each(clonedNode.nodeName === 'BODY' ? clonedNode.childNodes : [clonedNode], node => { 18656 doc.body.appendChild(doc.importNode(node, true)); 18657 }); 18658 if (clonedNode.nodeName !== 'BODY') { 18659 clonedNode = doc.body.firstChild; 18660 } else { 18661 clonedNode = doc.body; 18662 } 18663 oldDoc = dom.doc; 18664 dom.doc = doc; 18665 } 18666 firePreProcess(editor, { 18667 ...args, 18668 node: clonedNode 18669 }); 18670 if (oldDoc) { 18671 dom.doc = oldDoc; 18672 } 18673 return clonedNode; 18674 }; 18675 const shouldFireEvent = (editor, args) => { 18676 return isNonNullable(editor) && editor.hasEventListeners('PreProcess') && !args.no_events; 18677 }; 18678 const process$1 = (editor, node, args) => { 18679 return shouldFireEvent(editor, args) ? preProcess$1(editor, node, args) : node; 18680 }; 18681 18682 const addTempAttr = (htmlParser, tempAttrs, name) => { 18683 if (Tools.inArray(tempAttrs, name) === -1) { 18684 htmlParser.addAttributeFilter(name, (nodes, name) => { 18685 let i = nodes.length; 18686 while (i--) { 18687 nodes[i].attr(name, null); 18688 } 18689 }); 18690 tempAttrs.push(name); 18691 } 18692 }; 18693 const postProcess = (editor, args, content) => { 18694 if (!args.no_events && editor) { 18695 const outArgs = firePostProcess(editor, { 18696 ...args, 18697 content 18698 }); 18699 return outArgs.content; 18700 } else { 18701 return content; 18702 } 18703 }; 18704 const getHtmlFromNode = (dom, node, args) => { 18705 const html = trim$1(args.getInner ? node.innerHTML : dom.getOuterHTML(node)); 18706 return args.selection || isWsPreserveElement(SugarElement.fromDom(node)) ? html : Tools.trim(html); 18707 };
vendor: 7,820 bytes, lines 18708-18851
18708 const parseHtml = (htmlParser, html, args) => { 18709 const parserArgs = args.selection ? { 18710 forced_root_block: false, 18711 ...args 18712 } : args; 18713 const rootNode = htmlParser.parse(html, parserArgs); 18714 trimTrailingBr(rootNode); 18715 return rootNode; 18716 }; 18717 const serializeNode = (settings, schema, node) => { 18718 const htmlSerializer = HtmlSerializer(settings, schema); 18719 return htmlSerializer.serialize(node); 18720 }; 18721 const toHtml = (editor, settings, schema, rootNode, args) => { 18722 const content = serializeNode(settings, schema, rootNode); 18723 return postProcess(editor, args, content); 18724 }; 18725 const DomSerializerImpl = (settings, editor) => { 18726 const tempAttrs = ['data-mce-selected']; 18727 const dom = editor && editor.dom ? editor.dom : DOMUtils.DOM; 18728 const schema = editor && editor.schema ? editor.schema : Schema(settings); 18729 settings.entity_encoding = settings.entity_encoding || 'named'; 18730 settings.remove_trailing_brs = 'remove_trailing_brs' in settings ? settings.remove_trailing_brs : true; 18731 const htmlParser = DomParser(settings, schema); 18732 register$3(htmlParser, settings, dom); 18733 const serialize = (node, parserArgs = {}) => { 18734 const args = { 18735 format: 'html', 18736 ...parserArgs 18737 }; 18738 const targetNode = process$1(editor, node, args); 18739 const html = getHtmlFromNode(dom, targetNode, args); 18740 const rootNode = parseHtml(htmlParser, html, args); 18741 return args.format === 'tree' ? rootNode : toHtml(editor, settings, schema, rootNode, args); 18742 }; 18743 return { 18744 schema, 18745 addNodeFilter: htmlParser.addNodeFilter, 18746 addAttributeFilter: htmlParser.addAttributeFilter, 18747 serialize: serialize, 18748 addRules: schema.addValidElements, 18749 setRules: schema.setValidElements, 18750 addTempAttr: curry(addTempAttr, htmlParser, tempAttrs), 18751 getTempAttrs: constant(tempAttrs), 18752 getNodeFilters: htmlParser.getNodeFilters, 18753 getAttributeFilters: htmlParser.getAttributeFilters, 18754 removeNodeFilter: htmlParser.removeNodeFilter, 18755 removeAttributeFilter: htmlParser.removeAttributeFilter 18756 }; 18757 }; 18758 18759 const DomSerializer = (settings, editor) => { 18760 const domSerializer = DomSerializerImpl(settings, editor); 18761 return { 18762 schema: domSerializer.schema, 18763 addNodeFilter: domSerializer.addNodeFilter, 18764 addAttributeFilter: domSerializer.addAttributeFilter, 18765 serialize: domSerializer.serialize, 18766 addRules: domSerializer.addRules, 18767 setRules: domSerializer.setRules, 18768 addTempAttr: domSerializer.addTempAttr, 18769 getTempAttrs: domSerializer.getTempAttrs, 18770 getNodeFilters: domSerializer.getNodeFilters, 18771 getAttributeFilters: domSerializer.getAttributeFilters, 18772 removeNodeFilter: domSerializer.removeNodeFilter, 18773 removeAttributeFilter: domSerializer.removeAttributeFilter 18774 }; 18775 }; 18776 18777 const defaultFormat$1 = 'html'; 18778 const setupArgs$1 = (args, format) => ({ 18779 ...args, 18780 format, 18781 get: true, 18782 getInner: true 18783 }); 18784 const getContent = (editor, args = {}) => { 18785 const format = args.format ? args.format : defaultFormat$1; 18786 const defaultedArgs = setupArgs$1(args, format); 18787 return preProcessGetContent(editor, defaultedArgs).fold(identity, updatedArgs => { 18788 const content = getContent$2(editor, updatedArgs); 18789 return postProcessGetContent(editor, content, updatedArgs); 18790 }); 18791 }; 18792 18793 const defaultFormat = 'html'; 18794 const setupArgs = (args, content) => ({ 18795 format: defaultFormat, 18796 ...args, 18797 set: true, 18798 content 18799 }); 18800 const setContent = (editor, content, args = {}) => { 18801 const defaultedArgs = setupArgs(args, content); 18802 return preProcessSetContent(editor, defaultedArgs).map(updatedArgs => { 18803 const result = setContent$2(editor, updatedArgs.content, updatedArgs); 18804 postProcessSetContent(editor, result.html, updatedArgs); 18805 return result.content; 18806 }).getOr(content); 18807 }; 18808 18809 const removedOptions = ('autoresize_on_init,content_editable_state,padd_empty_with_br,block_elements,' + 'boolean_attributes,editor_deselector,editor_selector,elements,file_browser_callback_types,filepicker_validator_handler,' + 'force_hex_style_colors,force_p_newlines,gecko_spellcheck,images_dataimg_filter,media_scripts,mode,move_caret_before_on_enter_elements,' + 'non_empty_elements,self_closing_elements,short_ended_elements,special,spellchecker_select_languages,spellchecker_whitelist,' + 'tab_focus,tabfocus_elements,table_responsive_width,text_block_elements,text_inline_elements,toolbar_drawer,types,validate,whitespace_elements,' + 'paste_enable_default_filters,paste_filter_drop,paste_word_valid_elements,paste_retain_style_properties,paste_convert_word_fake_lists').split(','); 18810 const deprecatedOptions = 'template_cdate_classes,template_mdate_classes,template_selected_content_classes,template_preview_replace_values,template_replace_values,templates,template_cdate_format,template_mdate_format'.split(','); 18811 const removedPlugins = 'bbcode,colorpicker,contextmenu,fullpage,legacyoutput,spellchecker,textcolor'.split(','); 18812 const deprecatedPlugins = [{ 18813 name: 'template', 18814 replacedWith: 'Advanced Template' 18815 }]; 18816 const getMatchingOptions = (options, searchingFor) => { 18817 const settingNames = filter$5(searchingFor, setting => has$2(options, setting)); 18818 return sort(settingNames); 18819 }; 18820 const getRemovedOptions = options => { 18821 const settingNames = getMatchingOptions(options, removedOptions); 18822 const forcedRootBlock = options.forced_root_block; 18823 if (forcedRootBlock === false || forcedRootBlock === '') { 18824 settingNames.push('forced_root_block (false only)'); 18825 } 18826 return sort(settingNames); 18827 }; 18828 const getDeprecatedOptions = options => getMatchingOptions(options, deprecatedOptions); 18829 const getMatchingPlugins = (options, searchingFor) => { 18830 const plugins = Tools.makeMap(options.plugins, ' '); 18831 const hasPlugin = plugin => has$2(plugins, plugin); 18832 const pluginNames = filter$5(searchingFor, hasPlugin); 18833 return sort(pluginNames); 18834 }; 18835 const getRemovedPlugins = options => getMatchingPlugins(options, removedPlugins); 18836 const getDeprecatedPlugins = options => getMatchingPlugins(options, deprecatedPlugins.map(entry => entry.name)); 18837 const logRemovedWarnings = (rawOptions, normalizedOptions) => { 18838 const removedOptions = getRemovedOptions(rawOptions); 18839 const removedPlugins = getRemovedPlugins(normalizedOptions); 18840 const hasRemovedPlugins = removedPlugins.length > 0; 18841 const hasRemovedOptions = removedOptions.length > 0; 18842 const isLegacyMobileTheme = normalizedOptions.theme === 'mobile'; 18843 if (hasRemovedPlugins || hasRemovedOptions || isLegacyMobileTheme) { 18844 const listJoiner = '\n- '; 18845 const themesMessage = isLegacyMobileTheme ? `\n\nThemes:${ listJoiner }mobile` : ''; 18846 const pluginsMessage = hasRemovedPlugins ? `\n\nPlugins:${ listJoiner }${ removedPlugins.join(listJoiner) }` : ''; 18847 const optionsMessage = hasRemovedOptions ? `\n\nOptions:${ listJoiner }${ removedOptions.join(listJoiner) }` : ''; 18848 console.warn('The following deprecated features are currently enabled and have been removed in TinyMCE 6.0. These features will no longer work and should be removed from the TinyMCE configuration. ' + 'See https://www.tiny.cloud/docs/tinymce/6/migration-from-5x/ for more information.' + themesMessage + pluginsMessage + optionsMessage); 18849 } 18850 }; 18851 const getPluginDescription = name => find$2(deprecatedPlugins, entry => entry.name === name).fold(() => name, entry => `${ name }, replaced by ${ entry.replacedWith }`
vendor: 26,591 bytes, lines 18851-19608
18851); 18852 const logDeprecatedWarnings = (rawOptions, normalizedOptions) => { 18853 const deprecatedOptions = getDeprecatedOptions(rawOptions); 18854 const deprecatedPlugins = getDeprecatedPlugins(normalizedOptions); 18855 const hasDeprecatedPlugins = deprecatedPlugins.length > 0; 18856 const hasDeprecatedOptions = deprecatedOptions.length > 0; 18857 if (hasDeprecatedPlugins || hasDeprecatedOptions) { 18858 const listJoiner = '\n- '; 18859 const pluginsMessage = hasDeprecatedPlugins ? `\n\nPlugins:${ listJoiner }${ deprecatedPlugins.map(getPluginDescription).join(listJoiner) }` : ''; 18860 const optionsMessage = hasDeprecatedOptions ? `\n\nOptions:${ listJoiner }${ deprecatedOptions.join(listJoiner) }` : ''; 18861 console.warn('The following deprecated features are currently enabled but will be removed soon.' + pluginsMessage + optionsMessage); 18862 } 18863 }; 18864 const logWarnings = (rawOptions, normalizedOptions) => { 18865 logRemovedWarnings(rawOptions, normalizedOptions); 18866 logDeprecatedWarnings(rawOptions, normalizedOptions); 18867 }; 18868 18869 const DOM$8 = DOMUtils.DOM; 18870 const restoreOriginalStyles = editor => { 18871 DOM$8.setStyle(editor.id, 'display', editor.orgDisplay); 18872 }; 18873 const safeDestroy = x => Optional.from(x).each(x => x.destroy()); 18874 const clearDomReferences = editor => { 18875 const ed = editor; 18876 ed.contentAreaContainer = ed.formElement = ed.container = ed.editorContainer = null; 18877 ed.bodyElement = ed.contentDocument = ed.contentWindow = null; 18878 ed.iframeElement = ed.targetElm = null; 18879 const selection = editor.selection; 18880 if (selection) { 18881 const dom = selection.dom; 18882 ed.selection = selection.win = selection.dom = dom.doc = null; 18883 } 18884 }; 18885 const restoreForm = editor => { 18886 const form = editor.formElement; 18887 if (form) { 18888 if (form._mceOldSubmit) { 18889 form.submit = form._mceOldSubmit; 18890 delete form._mceOldSubmit; 18891 } 18892 DOM$8.unbind(form, 'submit reset', editor.formEventDelegate); 18893 } 18894 }; 18895 const remove$1 = editor => { 18896 if (!editor.removed) { 18897 const {_selectionOverrides, editorUpload} = editor; 18898 const body = editor.getBody(); 18899 const element = editor.getElement(); 18900 if (body) { 18901 editor.save({ is_removing: true }); 18902 } 18903 editor.removed = true; 18904 editor.unbindAllNativeEvents(); 18905 if (editor.hasHiddenInput && isNonNullable(element === null || element === void 0 ? void 0 : element.nextSibling)) { 18906 DOM$8.remove(element.nextSibling); 18907 } 18908 fireRemove(editor); 18909 editor.editorManager.remove(editor); 18910 if (!editor.inline && body) { 18911 restoreOriginalStyles(editor); 18912 } 18913 fireDetach(editor); 18914 DOM$8.remove(editor.getContainer()); 18915 safeDestroy(_selectionOverrides); 18916 safeDestroy(editorUpload); 18917 editor.destroy(); 18918 } 18919 }; 18920 const destroy = (editor, automatic) => { 18921 const {selection, dom} = editor; 18922 if (editor.destroyed) { 18923 return; 18924 } 18925 if (!automatic && !editor.removed) { 18926 editor.remove(); 18927 return; 18928 } 18929 if (!automatic) { 18930 editor.editorManager.off('beforeunload', editor._beforeUnload); 18931 if (editor.theme && editor.theme.destroy) { 18932 editor.theme.destroy(); 18933 } 18934 safeDestroy(selection); 18935 safeDestroy(dom); 18936 } 18937 restoreForm(editor); 18938 clearDomReferences(editor); 18939 editor.destroyed = true; 18940 }; 18941 18942 const CreateIconManager = () => { 18943 const lookup = {}; 18944 const add = (id, iconPack) => { 18945 lookup[id] = iconPack; 18946 }; 18947 const get = id => { 18948 if (lookup[id]) { 18949 return lookup[id]; 18950 } else { 18951 return { icons: {} }; 18952 } 18953 }; 18954 const has = id => has$2(lookup, id); 18955 return { 18956 add, 18957 get, 18958 has 18959 }; 18960 }; 18961 const IconManager = CreateIconManager(); 18962 18963 const ModelManager = AddOnManager.ModelManager; 18964 18965 const getProp = (propName, elm) => { 18966 const rawElm = elm.dom; 18967 return rawElm[propName]; 18968 }; 18969 const getComputedSizeProp = (propName, elm) => parseInt(get$7(elm, propName), 10); 18970 const getClientWidth = curry(getProp, 'clientWidth'); 18971 const getClientHeight = curry(getProp, 'clientHeight'); 18972 const getMarginTop = curry(getComputedSizeProp, 'margin-top'); 18973 const getMarginLeft = curry(getComputedSizeProp, 'margin-left'); 18974 const getBoundingClientRect = elm => elm.dom.getBoundingClientRect(); 18975 const isInsideElementContentArea = (bodyElm, clientX, clientY) => { 18976 const clientWidth = getClientWidth(bodyElm); 18977 const clientHeight = getClientHeight(bodyElm); 18978 return clientX >= 0 && clientY >= 0 && clientX <= clientWidth && clientY <= clientHeight; 18979 }; 18980 const transpose = (inline, elm, clientX, clientY) => { 18981 const clientRect = getBoundingClientRect(elm); 18982 const deltaX = inline ? clientRect.left + elm.dom.clientLeft + getMarginLeft(elm) : 0; 18983 const deltaY = inline ? clientRect.top + elm.dom.clientTop + getMarginTop(elm) : 0; 18984 const x = clientX - deltaX; 18985 const y = clientY - deltaY; 18986 return { 18987 x, 18988 y 18989 }; 18990 }; 18991 const isXYInContentArea = (editor, clientX, clientY) => { 18992 const bodyElm = SugarElement.fromDom(editor.getBody()); 18993 const targetElm = editor.inline ? bodyElm : documentElement(bodyElm); 18994 const transposedPoint = transpose(editor.inline, targetElm, clientX, clientY); 18995 return isInsideElementContentArea(targetElm, transposedPoint.x, transposedPoint.y); 18996 }; 18997 const fromDomSafe = node => Optional.from(node).map(SugarElement.fromDom); 18998 const isEditorAttachedToDom = editor => { 18999 const rawContainer = editor.inline ? editor.getBody() : editor.getContentAreaContainer(); 19000 return fromDomSafe(rawContainer).map(inBody).getOr(false); 19001 }; 19002 19003 var NotificationManagerImpl = () => { 19004 const unimplemented = () => { 19005 throw new Error('Theme did not provide a NotificationManager implementation.'); 19006 }; 19007 return { 19008 open: unimplemented, 19009 close: unimplemented, 19010 getArgs: unimplemented 19011 }; 19012 }; 19013 19014 const NotificationManager = editor => { 19015 const notifications = []; 19016 const getImplementation = () => { 19017 const theme = editor.theme; 19018 return theme && theme.getNotificationManagerImpl ? theme.getNotificationManagerImpl() : NotificationManagerImpl(); 19019 }; 19020 const getTopNotification = () => { 19021 return Optional.from(notifications[0]); 19022 }; 19023 const isEqual = (a, b) => { 19024 return a.type === b.type && a.text === b.text && !a.progressBar && !a.timeout && !b.progressBar && !b.timeout; 19025 }; 19026 const reposition = () => { 19027 each$e(notifications, notification => { 19028 notification.reposition(); 19029 }); 19030 }; 19031 const addNotification = notification => { 19032 notifications.push(notification); 19033 }; 19034 const closeNotification = notification => { 19035 findIndex$2(notifications, otherNotification => { 19036 return otherNotification === notification; 19037 }).each(index => { 19038 notifications.splice(index, 1); 19039 }); 19040 }; 19041 const open = (spec, fireEvent = true) => { 19042 if (editor.removed || !isEditorAttachedToDom(editor)) { 19043 return {}; 19044 } 19045 if (fireEvent) { 19046 editor.dispatch('BeforeOpenNotification', { notification: spec }); 19047 } 19048 return find$2(notifications, notification => { 19049 return isEqual(getImplementation().getArgs(notification), spec); 19050 }).getOrThunk(() => { 19051 editor.editorManager.setActive(editor); 19052 const notification = getImplementation().open(spec, () => { 19053 closeNotification(notification); 19054 reposition(); 19055 getTopNotification().fold(() => editor.focus(), top => focus$1(SugarElement.fromDom(top.getEl()))); 19056 }); 19057 addNotification(notification); 19058 reposition(); 19059 editor.dispatch('OpenNotification', { notification: { ...notification } }); 19060 return notification; 19061 }); 19062 }; 19063 const close = () => { 19064 getTopNotification().each(notification => { 19065 getImplementation().close(notification); 19066 closeNotification(notification); 19067 reposition(); 19068 }); 19069 }; 19070 const getNotifications = constant(notifications); 19071 const registerEvents = editor => { 19072 editor.on('SkinLoaded', () => { 19073 const serviceMessage = getServiceMessage(editor); 19074 if (serviceMessage) { 19075 open({ 19076 text: serviceMessage, 19077 type: 'warning', 19078 timeout: 0 19079 }, false); 19080 } 19081 reposition(); 19082 }); 19083 editor.on('show ResizeEditor ResizeWindow NodeChange', () => { 19084 requestAnimationFrame(reposition); 19085 }); 19086 editor.on('remove', () => { 19087 each$e(notifications.slice(), notification => { 19088 getImplementation().close(notification); 19089 }); 19090 }); 19091 }; 19092 registerEvents(editor); 19093 return { 19094 open, 19095 close, 19096 getNotifications 19097 }; 19098 }; 19099 19100 const PluginManager = AddOnManager.PluginManager; 19101 19102 const ThemeManager = AddOnManager.ThemeManager; 19103 19104 var WindowManagerImpl = () => { 19105 const unimplemented = () => { 19106 throw new Error('Theme did not provide a WindowManager implementation.'); 19107 }; 19108 return { 19109 open: unimplemented, 19110 openUrl: unimplemented, 19111 alert: unimplemented, 19112 confirm: unimplemented, 19113 close: unimplemented 19114 }; 19115 }; 19116 19117 const WindowManager = editor => { 19118 let dialogs = []; 19119 const getImplementation = () => { 19120 const theme = editor.theme; 19121 return theme && theme.getWindowManagerImpl ? theme.getWindowManagerImpl() : WindowManagerImpl(); 19122 }; 19123 const funcBind = (scope, f) => { 19124 return (...args) => { 19125 return f ? f.apply(scope, args) : undefined; 19126 }; 19127 }; 19128 const fireOpenEvent = dialog => { 19129 editor.dispatch('OpenWindow', { dialog }); 19130 }; 19131 const fireCloseEvent = dialog => { 19132 editor.dispatch('CloseWindow', { dialog }); 19133 }; 19134 const addDialog = dialog => { 19135 dialogs.push(dialog); 19136 fireOpenEvent(dialog); 19137 }; 19138 const closeDialog = dialog => { 19139 fireCloseEvent(dialog); 19140 dialogs = filter$5(dialogs, otherDialog => { 19141 return otherDialog !== dialog; 19142 }); 19143 if (dialogs.length === 0) { 19144 editor.focus(); 19145 } 19146 }; 19147 const getTopDialog = () => { 19148 return Optional.from(dialogs[dialogs.length - 1]); 19149 }; 19150 const storeSelectionAndOpenDialog = openDialog => { 19151 editor.editorManager.setActive(editor); 19152 store(editor); 19153 editor.ui.show(); 19154 const dialog = openDialog(); 19155 addDialog(dialog); 19156 return dialog; 19157 }; 19158 const open = (args, params) => { 19159 return storeSelectionAndOpenDialog(() => getImplementation().open(args, params, closeDialog)); 19160 }; 19161 const openUrl = args => { 19162 return storeSelectionAndOpenDialog(() => getImplementation().openUrl(args, closeDialog)); 19163 }; 19164 const alert = (message, callback, scope) => { 19165 const windowManagerImpl = getImplementation(); 19166 windowManagerImpl.alert(message, funcBind(scope ? scope : windowManagerImpl, callback)); 19167 }; 19168 const confirm = (message, callback, scope) => { 19169 const windowManagerImpl = getImplementation(); 19170 windowManagerImpl.confirm(message, funcBind(scope ? scope : windowManagerImpl, callback)); 19171 }; 19172 const close = () => { 19173 getTopDialog().each(dialog => { 19174 getImplementation().close(dialog); 19175 closeDialog(dialog); 19176 }); 19177 }; 19178 editor.on('remove', () => { 19179 each$e(dialogs, dialog => { 19180 getImplementation().close(dialog); 19181 }); 19182 }); 19183 return { 19184 open, 19185 openUrl, 19186 alert, 19187 confirm, 19188 close 19189 }; 19190 }; 19191 19192 const displayNotification = (editor, message) => { 19193 editor.notificationManager.open({ 19194 type: 'error', 19195 text: message 19196 }); 19197 }; 19198 const displayError = (editor, message) => { 19199 if (editor._skinLoaded) { 19200 displayNotification(editor, message); 19201 } else { 19202 editor.on('SkinLoaded', () => { 19203 displayNotification(editor, message); 19204 }); 19205 } 19206 }; 19207 const uploadError = (editor, message) => { 19208 displayError(editor, I18n.translate([ 19209 'Failed to upload image: {0}', 19210 message 19211 ])); 19212 }; 19213 const logError = (editor, errorType, msg) => { 19214 fireError(editor, errorType, { message: msg }); 19215 console.error(msg); 19216 }; 19217 const createLoadError = (type, url, name) => name ? `Failed to load ${ type }: ${ name } from url ${ url }` : `Failed to load ${ type } url: ${ url }`; 19218 const pluginLoadError = (editor, url, name) => { 19219 logError(editor, 'PluginLoadError', createLoadError('plugin', url, name)); 19220 }; 19221 const iconsLoadError = (editor, url, name) => { 19222 logError(editor, 'IconsLoadError', createLoadError('icons', url, name)); 19223 }; 19224 const languageLoadError = (editor, url, name) => { 19225 logError(editor, 'LanguageLoadError', createLoadError('language', url, name)); 19226 }; 19227 const themeLoadError = (editor, url, name) => { 19228 logError(editor, 'ThemeLoadError', createLoadError('theme', url, name)); 19229 }; 19230 const modelLoadError = (editor, url, name) => { 19231 logError(editor, 'ModelLoadError', createLoadError('model', url, name)); 19232 }; 19233 const pluginInitError = (editor, name, err) => { 19234 const message = I18n.translate([ 19235 'Failed to initialize plugin: {0}', 19236 name 19237 ]); 19238 fireError(editor, 'PluginLoadError', { message }); 19239 initError(message, err); 19240 displayError(editor, message); 19241 }; 19242 const initError = (message, ...x) => { 19243 const console = window.console; 19244 if (console) { 19245 if (console.error) { 19246 console.error(message, ...x); 19247 } else { 19248 console.log(message, ...x); 19249 } 19250 } 19251 }; 19252 19253 const isContentCssSkinName = url => /^[a-z0-9\-]+$/i.test(url); 19254 const getContentCssUrls = editor => { 19255 return transformToUrls(editor, getContentCss(editor)); 19256 }; 19257 const getFontCssUrls = editor => { 19258 return transformToUrls(editor, getFontCss(editor)); 19259 }; 19260 const transformToUrls = (editor, cssLinks) => { 19261 const skinUrl = editor.editorManager.baseURL + '/skins/content'; 19262 const suffix = editor.editorManager.suffix; 19263 const contentCssFile = `content${ suffix }.css`; 19264 return map$3(cssLinks, url => { 19265 if (isContentCssSkinName(url) && !editor.inline) { 19266 return `${ skinUrl }/${ url }/${ contentCssFile }`; 19267 } else { 19268 return editor.documentBaseURI.toAbsolute(url); 19269 } 19270 }); 19271 }; 19272 const appendContentCssFromSettings = editor => { 19273 editor.contentCSS = editor.contentCSS.concat(getContentCssUrls(editor), getFontCssUrls(editor)); 19274 }; 19275 19276 const getAllImages = elm => { 19277 return elm ? from(elm.getElementsByTagName('img')) : []; 19278 }; 19279 const ImageScanner = (uploadStatus, blobCache) => { 19280 const cachedPromises = {}; 19281 const findAll = (elm, predicate = always) => { 19282 const images = filter$5(getAllImages(elm), img => { 19283 const src = img.src; 19284 if (img.hasAttribute('data-mce-bogus')) { 19285 return false; 19286 } 19287 if (img.hasAttribute('data-mce-placeholder')) { 19288 return false; 19289 } 19290 if (!src || src === Env.transparentSrc) { 19291 return false; 19292 } 19293 if (startsWith(src, 'blob:')) { 19294 return !uploadStatus.isUploaded(src) && predicate(img); 19295 } 19296 if (startsWith(src, 'data:')) { 19297 return predicate(img); 19298 } 19299 return false; 19300 }); 19301 const promises = map$3(images, img => { 19302 const imageSrc = img.src; 19303 if (has$2(cachedPromises, imageSrc)) { 19304 return cachedPromises[imageSrc].then(imageInfo => { 19305 if (isString(imageInfo)) { 19306 return imageInfo; 19307 } else { 19308 return { 19309 image: img, 19310 blobInfo: imageInfo.blobInfo 19311 }; 19312 } 19313 }); 19314 } else { 19315 const newPromise = imageToBlobInfo(blobCache, imageSrc).then(blobInfo => { 19316 delete cachedPromises[imageSrc]; 19317 return { 19318 image: img, 19319 blobInfo 19320 }; 19321 }).catch(error => { 19322 delete cachedPromises[imageSrc]; 19323 return error; 19324 }); 19325 cachedPromises[imageSrc] = newPromise; 19326 return newPromise; 19327 } 19328 }); 19329 return Promise.all(promises); 19330 }; 19331 return { findAll }; 19332 }; 19333 19334 const UploadStatus = () => { 19335 const PENDING = 1, UPLOADED = 2; 19336 let blobUriStatuses = {}; 19337 const createStatus = (status, resultUri) => { 19338 return { 19339 status, 19340 resultUri 19341 }; 19342 }; 19343 const hasBlobUri = blobUri => { 19344 return blobUri in blobUriStatuses; 19345 }; 19346 const getResultUri = blobUri => { 19347 const result = blobUriStatuses[blobUri]; 19348 return result ? result.resultUri : null; 19349 }; 19350 const isPending = blobUri => { 19351 return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === PENDING : false; 19352 }; 19353 const isUploaded = blobUri => { 19354 return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === UPLOADED : false; 19355 }; 19356 const markPending = blobUri => { 19357 blobUriStatuses[blobUri] = createStatus(PENDING, null); 19358 }; 19359 const markUploaded = (blobUri, resultUri) => { 19360 blobUriStatuses[blobUri] = createStatus(UPLOADED, resultUri); 19361 }; 19362 const removeFailed = blobUri => { 19363 delete blobUriStatuses[blobUri]; 19364 }; 19365 const destroy = () => { 19366 blobUriStatuses = {}; 19367 }; 19368 return { 19369 hasBlobUri, 19370 getResultUri, 19371 isPending, 19372 isUploaded, 19373 markPending, 19374 markUploaded, 19375 removeFailed, 19376 destroy 19377 }; 19378 }; 19379 19380 let count = 0; 19381 const seed = () => { 19382 const rnd = () => { 19383 return Math.round(Math.random() * 4294967295).toString(36); 19384 }; 19385 const now = new Date().getTime(); 19386 return 's' + now.toString(36) + rnd() + rnd() + rnd(); 19387 }; 19388 const uuid = prefix => { 19389 return prefix + count++ + seed(); 19390 }; 19391 19392 const BlobCache = () => { 19393 let cache = []; 19394 const mimeToExt = mime => { 19395 const mimes = { 19396 'image/jpeg': 'jpg', 19397 'image/jpg': 'jpg', 19398 'image/gif': 'gif', 19399 'image/png': 'png', 19400 'image/apng': 'apng', 19401 'image/avif': 'avif', 19402 'image/svg+xml': 'svg', 19403 'image/webp': 'webp', 19404 'image/bmp': 'bmp', 19405 'image/tiff': 'tiff' 19406 }; 19407 return mimes[mime.toLowerCase()] || 'dat'; 19408 }; 19409 const create = (o, blob, base64, name, filename) => { 19410 if (isString(o)) { 19411 const id = o; 19412 return toBlobInfo({ 19413 id, 19414 name, 19415 filename, 19416 blob: blob, 19417 base64: base64 19418 }); 19419 } else if (isObject(o)) { 19420 return toBlobInfo(o); 19421 } else { 19422 throw new Error('Unknown input type'); 19423 } 19424 }; 19425 const toBlobInfo = o => { 19426 if (!o.blob || !o.base64) { 19427 throw new Error('blob and base64 representations of the image are required for BlobInfo to be created'); 19428 } 19429 const id = o.id || uuid('blobid'); 19430 const name = o.name || id; 19431 const blob = o.blob; 19432 return { 19433 id: constant(id), 19434 name: constant(name), 19435 filename: constant(o.filename || name + '.' + mimeToExt(blob.type)), 19436 blob: constant(blob), 19437 base64: constant(o.base64), 19438 blobUri: constant(o.blobUri || URL.createObjectURL(blob)), 19439 uri: constant(o.uri) 19440 }; 19441 }; 19442 const add = blobInfo => { 19443 if (!get(blobInfo.id())) { 19444 cache.push(blobInfo); 19445 } 19446 }; 19447 const findFirst = predicate => find$2(cache, predicate).getOrUndefined(); 19448 const get = id => findFirst(cachedBlobInfo => cachedBlobInfo.id() === id); 19449 const getByUri = blobUri => findFirst(blobInfo => blobInfo.blobUri() === blobUri); 19450 const getByData = (base64, type) => findFirst(blobInfo => blobInfo.base64() === base64 && blobInfo.blob().type === type); 19451 const removeByUri = blobUri => { 19452 cache = filter$5(cache, blobInfo => { 19453 if (blobInfo.blobUri() === blobUri) { 19454 URL.revokeObjectURL(blobInfo.blobUri()); 19455 return false; 19456 } 19457 return true; 19458 }); 19459 }; 19460 const destroy = () => { 19461 each$e(cache, cachedBlobInfo => { 19462 URL.revokeObjectURL(cachedBlobInfo.blobUri()); 19463 }); 19464 cache = []; 19465 }; 19466 return { 19467 create, 19468 add, 19469 get, 19470 getByUri, 19471 getByData, 19472 findFirst, 19473 removeByUri, 19474 destroy 19475 }; 19476 }; 19477 19478 const Uploader = (uploadStatus, settings) => { 19479 const pendingPromises = {}; 19480 const pathJoin = (path1, path2) => { 19481 if (path1) { 19482 return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, ''); 19483 } 19484 return path2; 19485 }; 19486 const defaultHandler = (blobInfo, progress) => new Promise((success, failure) => { 19487 const xhr = new XMLHttpRequest(); 19488 xhr.open('POST', settings.url); 19489 xhr.withCredentials = settings.credentials; 19490 xhr.upload.onprogress = e => { 19491 progress(e.loaded / e.total * 100); 19492 }; 19493 xhr.onerror = () => { 19494 failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status); 19495 }; 19496 xhr.onload = () => { 19497 if (xhr.status < 200 || xhr.status >= 300) { 19498 failure('HTTP Error: ' + xhr.status); 19499 return; 19500 } 19501 const json = JSON.parse(xhr.responseText); 19502 if (!json || !isString(json.location)) { 19503 failure('Invalid JSON: ' + xhr.responseText); 19504 return; 19505 } 19506 success(pathJoin(settings.basePath, json.location)); 19507 }; 19508 const formData = new FormData(); 19509 formData.append('file', blobInfo.blob(), blobInfo.filename()); 19510 xhr.send(formData); 19511 }); 19512 const uploadHandler = isFunction(settings.handler) ? settings.handler : defaultHandler; 19513 const noUpload = () => new Promise(resolve => { 19514 resolve([]); 19515 }); 19516 const handlerSuccess = (blobInfo, url) => ({ 19517 url, 19518 blobInfo, 19519 status: true 19520 }); 19521 const handlerFailure = (blobInfo, error) => ({ 19522 url: '', 19523 blobInfo, 19524 status: false, 19525 error 19526 }); 19527 const resolvePending = (blobUri, result) => { 19528 Tools.each(pendingPromises[blobUri], resolve => { 19529 resolve(result); 19530 }); 19531 delete pendingPromises[blobUri]; 19532 }; 19533 const uploadBlobInfo = (blobInfo, handler, openNotification) => { 19534 uploadStatus.markPending(blobInfo.blobUri()); 19535 return new Promise(resolve => { 19536 let notification; 19537 let progress; 19538 try { 19539 const closeNotification = () => { 19540 if (notification) { 19541 notification.close(); 19542 progress = noop; 19543 } 19544 }; 19545 const success = url => { 19546 closeNotification(); 19547 uploadStatus.markUploaded(blobInfo.blobUri(), url); 19548 resolvePending(blobInfo.blobUri(), handlerSuccess(blobInfo, url)); 19549 resolve(handlerSuccess(blobInfo, url)); 19550 }; 19551 const failure = error => { 19552 closeNotification(); 19553 uploadStatus.removeFailed(blobInfo.blobUri()); 19554 resolvePending(blobInfo.blobUri(), handlerFailure(blobInfo, error)); 19555 resolve(handlerFailure(blobInfo, error)); 19556 }; 19557 progress = percent => { 19558 if (percent < 0 || percent > 100) { 19559 return; 19560 } 19561 Optional.from(notification).orThunk(() => Optional.from(openNotification).map(apply$1)).each(n => { 19562 notification = n; 19563 n.progressBar.value(percent); 19564 }); 19565 }; 19566 handler(blobInfo, progress).then(success, err => { 19567 failure(isString(err) ? { message: err } : err); 19568 }); 19569 } catch (ex) { 19570 resolve(handlerFailure(blobInfo, ex)); 19571 } 19572 }); 19573 }; 19574 const isDefaultHandler = handler => handler === defaultHandler; 19575 const pendingUploadBlobInfo = blobInfo => { 19576 const blobUri = blobInfo.blobUri(); 19577 return new Promise(resolve => { 19578 pendingPromises[blobUri] = pendingPromises[blobUri] || []; 19579 pendingPromises[blobUri].push(resolve); 19580 }); 19581 }; 19582 const uploadBlobs = (blobInfos, openNotification) => { 19583 blobInfos = Tools.grep(blobInfos, blobInfo => !uploadStatus.isUploaded(blobInfo.blobUri())); 19584 return Promise.all(Tools.map(blobInfos, blobInfo => uploadStatus.isPending(blobInfo.blobUri()) ? pendingUploadBlobInfo(blobInfo) : uploadBlobInfo(blobInfo, uploadHandler, openNotification))); 19585 }; 19586 const upload = (blobInfos, openNotification) => !settings.url && isDefaultHandler(uploadHandler) ? noUpload() : uploadBlobs(blobInfos, openNotification); 19587 return { upload }; 19588 }; 19589 19590 const openNotification = editor => () => editor.notificationManager.open({ 19591 text: editor.translate('Image uploading...'), 19592 type: 'info', 19593 timeout: -1, 19594 progressBar: true 19595 }); 19596 const createUploader = (editor, uploadStatus) => Uploader(uploadStatus, { 19597 url: getImageUploadUrl(editor), 19598 basePath: getImageUploadBasePath(editor), 19599 credentials: getImagesUploadCredentials(editor), 19600 handler: getImagesUploadHandler(editor) 19601 }); 19602 const ImageUploader = editor => { 19603 const uploadStatus = UploadStatus(); 19604 const uploader = createUploader(editor, uploadStatus); 19605 return { upload: (blobInfos, showNotification = true) => uploader.upload(blobInfos, showNotification ? openNotification(editor) : undefined) }; 19606 }; 19607 19608 const
vendor: 3,946 bytes, lines 19608-19696
19608EditorUpload = editor => { 19609 const blobCache = BlobCache(); 19610 let uploader, imageScanner; 19611 const uploadStatus = UploadStatus(); 19612 const urlFilters = []; 19613 const aliveGuard = callback => { 19614 return result => { 19615 if (editor.selection) { 19616 return callback(result); 19617 } 19618 return []; 19619 }; 19620 }; 19621 const cacheInvalidator = url => url + (url.indexOf('?') === -1 ? '?' : '&') + new Date().getTime(); 19622 const replaceString = (content, search, replace) => { 19623 let index = 0; 19624 do { 19625 index = content.indexOf(search, index); 19626 if (index !== -1) { 19627 content = content.substring(0, index) + replace + content.substr(index + search.length); 19628 index += replace.length - search.length + 1; 19629 } 19630 } while (index !== -1); 19631 return content; 19632 }; 19633 const replaceImageUrl = (content, targetUrl, replacementUrl) => { 19634 const replacementString = `src="${ replacementUrl }"${ replacementUrl === Env.transparentSrc ? ' data-mce-placeholder="1"' : '' }`; 19635 content = replaceString(content, `src="${ targetUrl }"`, replacementString); 19636 content = replaceString(content, 'data-mce-src="' + targetUrl + '"', 'data-mce-src="' + replacementUrl + '"'); 19637 return content; 19638 }; 19639 const replaceUrlInUndoStack = (targetUrl, replacementUrl) => { 19640 each$e(editor.undoManager.data, level => { 19641 if (level.type === 'fragmented') { 19642 level.fragments = map$3(level.fragments, fragment => replaceImageUrl(fragment, targetUrl, replacementUrl)); 19643 } else { 19644 level.content = replaceImageUrl(level.content, targetUrl, replacementUrl); 19645 } 19646 }); 19647 }; 19648 const replaceImageUriInView = (image, resultUri) => { 19649 const src = editor.convertURL(resultUri, 'src'); 19650 replaceUrlInUndoStack(image.src, resultUri); 19651 setAll$1(SugarElement.fromDom(image), { 19652 'src': shouldReuseFileName(editor) ? cacheInvalidator(resultUri) : resultUri, 19653 'data-mce-src': src 19654 }); 19655 }; 19656 const uploadImages = () => { 19657 if (!uploader) { 19658 uploader = createUploader(editor, uploadStatus); 19659 } 19660 return scanForImages().then(aliveGuard(imageInfos => { 19661 const blobInfos = map$3(imageInfos, imageInfo => imageInfo.blobInfo); 19662 return uploader.upload(blobInfos, openNotification(editor)).then(aliveGuard(result => { 19663 const imagesToRemove = []; 19664 let shouldDispatchChange = false; 19665 const filteredResult = map$3(result, (uploadInfo, index) => { 19666 const {blobInfo, image} = imageInfos[index]; 19667 let removed = false; 19668 if (uploadInfo.status && shouldReplaceBlobUris(editor)) { 19669 if (uploadInfo.url && !contains$1(image.src, uploadInfo.url)) { 19670 shouldDispatchChange = true; 19671 } 19672 blobCache.removeByUri(image.src); 19673 if (isRtc(editor)) ; else { 19674 replaceImageUriInView(image, uploadInfo.url); 19675 } 19676 } else if (uploadInfo.error) { 19677 if (uploadInfo.error.remove) { 19678 replaceUrlInUndoStack(image.src, Env.transparentSrc); 19679 imagesToRemove.push(image); 19680 removed = true; 19681 } 19682 uploadError(editor, uploadInfo.error.message); 19683 } 19684 return { 19685 element: image, 19686 status: uploadInfo.status, 19687 uploadUri: uploadInfo.url, 19688 blobInfo, 19689 removed 19690 }; 19691 }); 19692 if (imagesToRemove.length > 0 && !isRtc(editor)) { 19693 editor.undoManager.transact(() => { 19694 each$e(imagesToRemove, element => { 19695 editor.dom.remove(element); 19696 blobCache.removeByUri(element
vendor: 26,293 bytes, lines 19696-20566
19696.src); 19697 }); 19698 }); 19699 } else if (shouldDispatchChange) { 19700 editor.undoManager.dispatchChange(); 19701 } 19702 return filteredResult; 19703 })); 19704 })); 19705 }; 19706 const uploadImagesAuto = () => isAutomaticUploadsEnabled(editor) ? uploadImages() : Promise.resolve([]); 19707 const isValidDataUriImage = imgElm => forall(urlFilters, filter => filter(imgElm)); 19708 const addFilter = filter => { 19709 urlFilters.push(filter); 19710 }; 19711 const scanForImages = () => { 19712 if (!imageScanner) { 19713 imageScanner = ImageScanner(uploadStatus, blobCache); 19714 } 19715 return imageScanner.findAll(editor.getBody(), isValidDataUriImage).then(aliveGuard(result => { 19716 const filteredResult = filter$5(result, resultItem => { 19717 if (isString(resultItem)) { 19718 displayError(editor, resultItem); 19719 return false; 19720 } else if (resultItem.uriType === 'blob') { 19721 return false; 19722 } else { 19723 return true; 19724 } 19725 }); 19726 if (isRtc(editor)) ; else { 19727 each$e(filteredResult, resultItem => { 19728 replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri()); 19729 resultItem.image.src = resultItem.blobInfo.blobUri(); 19730 resultItem.image.removeAttribute('data-mce-src'); 19731 }); 19732 } 19733 return filteredResult; 19734 })); 19735 }; 19736 const destroy = () => { 19737 blobCache.destroy(); 19738 uploadStatus.destroy(); 19739 imageScanner = uploader = null; 19740 }; 19741 const replaceBlobUris = content => { 19742 return content.replace(/src="(blob:[^"]+)"/g, (match, blobUri) => { 19743 const resultUri = uploadStatus.getResultUri(blobUri); 19744 if (resultUri) { 19745 return 'src="' + resultUri + '"'; 19746 } 19747 let blobInfo = blobCache.getByUri(blobUri); 19748 if (!blobInfo) { 19749 blobInfo = foldl(editor.editorManager.get(), (result, editor) => { 19750 return result || editor.editorUpload && editor.editorUpload.blobCache.getByUri(blobUri); 19751 }, undefined); 19752 } 19753 if (blobInfo) { 19754 const blob = blobInfo.blob(); 19755 return 'src="data:' + blob.type + ';base64,' + blobInfo.base64() + '"'; 19756 } 19757 return match; 19758 }); 19759 }; 19760 editor.on('SetContent', () => { 19761 if (isAutomaticUploadsEnabled(editor)) { 19762 uploadImagesAuto(); 19763 } else { 19764 scanForImages(); 19765 } 19766 }); 19767 editor.on('RawSaveContent', e => { 19768 e.content = replaceBlobUris(e.content); 19769 }); 19770 editor.on('GetContent', e => { 19771 if (e.source_view || e.format === 'raw' || e.format === 'tree') { 19772 return; 19773 } 19774 e.content = replaceBlobUris(e.content); 19775 }); 19776 editor.on('PostRender', () => { 19777 editor.parser.addNodeFilter('img', images => { 19778 each$e(images, img => { 19779 const src = img.attr('src'); 19780 if (!src || blobCache.getByUri(src)) { 19781 return; 19782 } 19783 const resultUri = uploadStatus.getResultUri(src); 19784 if (resultUri) { 19785 img.attr('src', resultUri); 19786 } 19787 }); 19788 }); 19789 }); 19790 return { 19791 blobCache, 19792 addFilter, 19793 uploadImages, 19794 uploadImagesAuto, 19795 scanForImages, 19796 destroy 19797 }; 19798 }; 19799 19800 const get$1 = editor => { 19801 const dom = editor.dom; 19802 const schemaType = editor.schema.type; 19803 const formats = { 19804 valigntop: [{ 19805 selector: 'td,th', 19806 styles: { verticalAlign: 'top' } 19807 }], 19808 valignmiddle: [{ 19809 selector: 'td,th', 19810 styles: { verticalAlign: 'middle' } 19811 }], 19812 valignbottom: [{ 19813 selector: 'td,th', 19814 styles: { verticalAlign: 'bottom' } 19815 }], 19816 alignleft: [ 19817 { 19818 selector: 'figure.image', 19819 collapsed: false, 19820 classes: 'align-left', 19821 ceFalseOverride: true, 19822 preview: 'font-family font-size' 19823 }, 19824 { 19825 selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre', 19826 styles: { textAlign: 'left' }, 19827 inherit: false, 19828 preview: false 19829 }, 19830 { 19831 selector: 'img,audio,video', 19832 collapsed: false, 19833 styles: { float: 'left' }, 19834 preview: 'font-family font-size' 19835 }, 19836 { 19837 selector: 'table', 19838 collapsed: false, 19839 styles: { 19840 marginLeft: '0px', 19841 marginRight: 'auto' 19842 }, 19843 onformat: table => { 19844 dom.setStyle(table, 'float', null); 19845 }, 19846 preview: 'font-family font-size' 19847 }, 19848 { 19849 selector: '.mce-preview-object,[data-ephox-embed-iri]', 19850 ceFalseOverride: true, 19851 styles: { float: 'left' } 19852 } 19853 ], 19854 aligncenter: [ 19855 { 19856 selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre', 19857 styles: { textAlign: 'center' }, 19858 inherit: false, 19859 preview: 'font-family font-size' 19860 }, 19861 { 19862 selector: 'figure.image', 19863 collapsed: false, 19864 classes: 'align-center', 19865 ceFalseOverride: true, 19866 preview: 'font-family font-size' 19867 }, 19868 { 19869 selector: 'img,audio,video', 19870 collapsed: false, 19871 styles: { 19872 display: 'block', 19873 marginLeft: 'auto', 19874 marginRight: 'auto' 19875 }, 19876 preview: false 19877 }, 19878 { 19879 selector: 'table', 19880 collapsed: false, 19881 styles: { 19882 marginLeft: 'auto', 19883 marginRight: 'auto' 19884 }, 19885 preview: 'font-family font-size' 19886 }, 19887 { 19888 selector: '.mce-preview-object', 19889 ceFalseOverride: true, 19890 styles: { 19891 display: 'table', 19892 marginLeft: 'auto', 19893 marginRight: 'auto' 19894 }, 19895 preview: false 19896 }, 19897 { 19898 selector: '[data-ephox-embed-iri]', 19899 ceFalseOverride: true, 19900 styles: { 19901 marginLeft: 'auto', 19902 marginRight: 'auto' 19903 }, 19904 preview: false 19905 } 19906 ], 19907 alignright: [ 19908 { 19909 selector: 'figure.image', 19910 collapsed: false, 19911 classes: 'align-right', 19912 ceFalseOverride: true, 19913 preview: 'font-family font-size' 19914 }, 19915 { 19916 selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre', 19917 styles: { textAlign: 'right' }, 19918 inherit: false, 19919 preview: 'font-family font-size' 19920 }, 19921 { 19922 selector: 'img,audio,video', 19923 collapsed: false, 19924 styles: { float: 'right' }, 19925 preview: 'font-family font-size' 19926 }, 19927 { 19928 selector: 'table', 19929 collapsed: false, 19930 styles: { 19931 marginRight: '0px', 19932 marginLeft: 'auto' 19933 }, 19934 onformat: table => { 19935 dom.setStyle(table, 'float', null); 19936 }, 19937 preview: 'font-family font-size' 19938 }, 19939 { 19940 selector: '.mce-preview-object,[data-ephox-embed-iri]', 19941 ceFalseOverride: true, 19942 styles: { float: 'right' }, 19943 preview: false 19944 } 19945 ], 19946 alignjustify: [{ 19947 selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre', 19948 styles: { textAlign: 'justify' }, 19949 inherit: false, 19950 preview: 'font-family font-size' 19951 }], 19952 bold: [ 19953 { 19954 inline: 'strong', 19955 remove: 'all', 19956 preserve_attributes: [ 19957 'class', 19958 'style' 19959 ] 19960 }, 19961 { 19962 inline: 'span', 19963 styles: { fontWeight: 'bold' } 19964 }, 19965 { 19966 inline: 'b', 19967 remove: 'all', 19968 preserve_attributes: [ 19969 'class', 19970 'style' 19971 ] 19972 } 19973 ], 19974 italic: [ 19975 { 19976 inline: 'em', 19977 remove: 'all', 19978 preserve_attributes: [ 19979 'class', 19980 'style' 19981 ] 19982 }, 19983 { 19984 inline: 'span', 19985 styles: { fontStyle: 'italic' } 19986 }, 19987 { 19988 inline: 'i', 19989 remove: 'all', 19990 preserve_attributes: [ 19991 'class', 19992 'style' 19993 ] 19994 } 19995 ], 19996 underline: [ 19997 { 19998 inline: 'span', 19999 styles: { textDecoration: 'underline' }, 20000 exact: true 20001 }, 20002 { 20003 inline: 'u', 20004 remove: 'all', 20005 preserve_attributes: [ 20006 'class', 20007 'style' 20008 ] 20009 } 20010 ], 20011 strikethrough: (() => { 20012 const span = { 20013 inline: 'span', 20014 styles: { textDecoration: 'line-through' }, 20015 exact: true 20016 }; 20017 const strike = { 20018 inline: 'strike', 20019 remove: 'all', 20020 preserve_attributes: [ 20021 'class', 20022 'style' 20023 ] 20024 }; 20025 const s = { 20026 inline: 's', 20027 remove: 'all', 20028 preserve_attributes: [ 20029 'class', 20030 'style' 20031 ] 20032 }; 20033 return schemaType !== 'html4' ? [ 20034 s, 20035 span, 20036 strike 20037 ] : [ 20038 span, 20039 s, 20040 strike 20041 ]; 20042 })(), 20043 forecolor: { 20044 inline: 'span', 20045 styles: { color: '%value' }, 20046 links: true, 20047 remove_similar: true, 20048 clear_child_styles: true 20049 }, 20050 hilitecolor: { 20051 inline: 'span', 20052 styles: { backgroundColor: '%value' }, 20053 links: true, 20054 remove_similar: true, 20055 clear_child_styles: true 20056 }, 20057 fontname: { 20058 inline: 'span', 20059 toggle: false, 20060 styles: { fontFamily: '%value' }, 20061 clear_child_styles: true 20062 }, 20063 fontsize: { 20064 inline: 'span', 20065 toggle: false, 20066 styles: { fontSize: '%value' }, 20067 clear_child_styles: true 20068 }, 20069 lineheight: { 20070 selector: 'h1,h2,h3,h4,h5,h6,p,li,td,th,div', 20071 styles: { lineHeight: '%value' } 20072 }, 20073 fontsize_class: { 20074 inline: 'span', 20075 attributes: { class: '%value' } 20076 }, 20077 blockquote: { 20078 block: 'blockquote', 20079 wrapper: true, 20080 remove: 'all' 20081 }, 20082 subscript: { inline: 'sub' }, 20083 superscript: { inline: 'sup' }, 20084 code: { inline: 'code' }, 20085 link: { 20086 inline: 'a', 20087 selector: 'a', 20088 remove: 'all', 20089 split: true, 20090 deep: true, 20091 onmatch: (node, _fmt, _itemName) => { 20092 return isElement$6(node) && node.hasAttribute('href'); 20093 }, 20094 onformat: (elm, _fmt, vars) => { 20095 Tools.each(vars, (value, key) => { 20096 dom.setAttrib(elm, key, value); 20097 }); 20098 } 20099 }, 20100 lang: { 20101 inline: 'span', 20102 clear_child_styles: true, 20103 remove_similar: true, 20104 attributes: { 20105 'lang': '%value', 20106 'data-mce-lang': vars => { 20107 var _a; 20108 return (_a = vars === null || vars === void 0 ? void 0 : vars.customValue) !== null && _a !== void 0 ? _a : null; 20109 } 20110 } 20111 }, 20112 removeformat: [ 20113 { 20114 selector: 'b,strong,em,i,font,u,strike,s,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins,small', 20115 remove: 'all', 20116 split: true, 20117 expand: false, 20118 block_expand: true, 20119 deep: true 20120 }, 20121 { 20122 selector: 'span', 20123 attributes: [ 20124 'style', 20125 'class' 20126 ], 20127 remove: 'empty', 20128 split: true, 20129 expand: false, 20130 deep: true 20131 }, 20132 { 20133 selector: '*', 20134 attributes: [ 20135 'style', 20136 'class' 20137 ], 20138 split: false, 20139 expand: false, 20140 deep: true 20141 } 20142 ] 20143 }; 20144 Tools.each('p h1 h2 h3 h4 h5 h6 div address pre dt dd samp'.split(/\s/), name => { 20145 formats[name] = { 20146 block: name, 20147 remove: 'all' 20148 }; 20149 }); 20150 return formats; 20151 }; 20152 20153 const genericBase = { 20154 remove_similar: true, 20155 inherit: false 20156 }; 20157 const cellBase = { 20158 selector: 'td,th', 20159 ...genericBase 20160 }; 20161 const cellFormats = { 20162 tablecellbackgroundcolor: { 20163 styles: { backgroundColor: '%value' }, 20164 ...cellBase 20165 }, 20166 tablecellverticalalign: { 20167 styles: { 'vertical-align': '%value' }, 20168 ...cellBase 20169 }, 20170 tablecellbordercolor: { 20171 styles: { borderColor: '%value' }, 20172 ...cellBase 20173 }, 20174 tablecellclass: { 20175 classes: ['%value'], 20176 ...cellBase 20177 }, 20178 tableclass: { 20179 selector: 'table', 20180 classes: ['%value'], 20181 ...genericBase 20182 }, 20183 tablecellborderstyle: { 20184 styles: { borderStyle: '%value' }, 20185 ...cellBase 20186 }, 20187 tablecellborderwidth: { 20188 styles: { borderWidth: '%value' }, 20189 ...cellBase 20190 } 20191 }; 20192 const get = constant(cellFormats); 20193 20194 const FormatRegistry = editor => { 20195 const formats = {}; 20196 const get$2 = name => isNonNullable(name) ? formats[name] : formats; 20197 const has = name => has$2(formats, name); 20198 const register = (name, format) => { 20199 if (name) { 20200 if (!isString(name)) { 20201 each$d(name, (format, name) => { 20202 register(name, format); 20203 }); 20204 } else { 20205 if (!isArray$1(format)) { 20206 format = [format]; 20207 } 20208 each$e(format, format => { 20209 if (isUndefined(format.deep)) { 20210 format.deep = !isSelectorFormat(format); 20211 } 20212 if (isUndefined(format.split)) { 20213 format.split = !isSelectorFormat(format) || isInlineFormat(format); 20214 } 20215 if (isUndefined(format.remove) && isSelectorFormat(format) && !isInlineFormat(format)) { 20216 format.remove = 'none'; 20217 } 20218 if (isSelectorFormat(format) && isInlineFormat(format)) { 20219 format.mixed = true; 20220 format.block_expand = true; 20221 } 20222 if (isString(format.classes)) { 20223 format.classes = format.classes.split(/\s+/); 20224 } 20225 }); 20226 formats[name] = format; 20227 } 20228 } 20229 }; 20230 const unregister = name => { 20231 if (name && formats[name]) { 20232 delete formats[name]; 20233 } 20234 return formats; 20235 }; 20236 register(get$1(editor)); 20237 register(get()); 20238 register(getFormats(editor)); 20239 return { 20240 get: get$2, 20241 has, 20242 register, 20243 unregister 20244 }; 20245 }; 20246 20247 const each$3 = Tools.each; 20248 const dom = DOMUtils.DOM; 20249 const isPreviewItem = item => isNonNullable(item) && isObject(item); 20250 const parsedSelectorToHtml = (ancestry, editor) => { 20251 const schema = editor && editor.schema || Schema({}); 20252 const decorate = (elm, item) => { 20253 if (item.classes.length > 0) { 20254 dom.addClass(elm, item.classes.join(' ')); 20255 } 20256 dom.setAttribs(elm, item.attrs); 20257 }; 20258 const createElement = sItem => { 20259 const item = isString(sItem) ? { 20260 name: sItem, 20261 classes: [], 20262 attrs: {} 20263 } : sItem; 20264 const elm = dom.create(item.name); 20265 decorate(elm, item); 20266 return elm; 20267 }; 20268 const getRequiredParent = (elm, candidate) => { 20269 const elmRule = schema.getElementRule(elm.nodeName.toLowerCase()); 20270 const parentsRequired = elmRule === null || elmRule === void 0 ? void 0 : elmRule.parentsRequired; 20271 if (parentsRequired && parentsRequired.length) { 20272 return candidate && contains$2(parentsRequired, candidate) ? candidate : parentsRequired[0]; 20273 } else { 20274 return false; 20275 } 20276 }; 20277 const wrapInHtml = (elm, ancestors, siblings) => { 20278 let parentCandidate; 20279 const ancestor = ancestors[0]; 20280 const ancestorName = isPreviewItem(ancestor) ? ancestor.name : undefined; 20281 const parentRequired = getRequiredParent(elm, ancestorName); 20282 if (parentRequired) { 20283 if (ancestorName === parentRequired) { 20284 parentCandidate = ancestor; 20285 ancestors = ancestors.slice(1); 20286 } else { 20287 parentCandidate = parentRequired; 20288 } 20289 } else if (ancestor) { 20290 parentCandidate = ancestor; 20291 ancestors = ancestors.slice(1); 20292 } else if (!siblings) { 20293 return elm; 20294 } 20295 const parent = parentCandidate ? createElement(parentCandidate) : dom.create('div'); 20296 parent.appendChild(elm); 20297 if (siblings) { 20298 Tools.each(siblings, sibling => { 20299 const siblingElm = createElement(sibling); 20300 parent.insertBefore(siblingElm, elm); 20301 }); 20302 } 20303 const parentSiblings = isPreviewItem(parentCandidate) ? parentCandidate.siblings : undefined; 20304 return wrapInHtml(parent, ancestors, parentSiblings); 20305 }; 20306 const fragment = dom.create('div'); 20307 if (ancestry.length > 0) { 20308 const item = ancestry[0]; 20309 const elm = createElement(item); 20310 const siblings = isPreviewItem(item) ? item.siblings : undefined; 20311 fragment.appendChild(wrapInHtml(elm, ancestry.slice(1), siblings)); 20312 } 20313 return fragment; 20314 }; 20315 const parseSelectorItem = item => { 20316 item = Tools.trim(item); 20317 let tagName = 'div'; 20318 const obj = { 20319 name: tagName, 20320 classes: [], 20321 attrs: {}, 20322 selector: item 20323 }; 20324 if (item !== '*') { 20325 tagName = item.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g, ($0, $1, $2, $3, $4) => { 20326 switch ($1) { 20327 case '#': 20328 obj.attrs.id = $2; 20329 break; 20330 case '.': 20331 obj.classes.push($2); 20332 break; 20333 case ':': 20334 if (Tools.inArray('checked disabled enabled read-only required'.split(' '), $2) !== -1) { 20335 obj.attrs[$2] = $2; 20336 } 20337 break; 20338 } 20339 if ($3 === '[') { 20340 const m = $4.match(/([\w\-]+)(?:\=\"([^\"]+))?/); 20341 if (m) { 20342 obj.attrs[m[1]] = m[2]; 20343 } 20344 } 20345 return ''; 20346 }); 20347 } 20348 obj.name = tagName || 'div'; 20349 return obj; 20350 }; 20351 const parseSelector = selector => { 20352 if (!isString(selector)) { 20353 return []; 20354 } 20355 selector = selector.split(/\s*,\s*/)[0]; 20356 selector = selector.replace(/\s*(~\+|~|\+|>)\s*/g, '$1'); 20357 return Tools.map(selector.split(/(?:>|\s+(?![^\[\]]+\]))/), item => { 20358 const siblings = Tools.map(item.split(/(?:~\+|~|\+)/), parseSelectorItem); 20359 const obj = siblings.pop(); 20360 if (siblings.length) { 20361 obj.siblings = siblings; 20362 } 20363 return obj; 20364 }).reverse(); 20365 }; 20366 const getCssText = (editor, format) => { 20367 let previewCss = ''; 20368 let previewStyles = getPreviewStyles(editor); 20369 if (previewStyles === '') { 20370 return ''; 20371 } 20372 const removeVars = val => { 20373 return isString(val) ? val.replace(/%(\w+)/g, '') : ''; 20374 }; 20375 const getComputedStyle = (name, elm) => { 20376 return dom.getStyle(elm !== null && elm !== void 0 ? elm : editor.getBody(), name, true); 20377 }; 20378 if (isString(format)) { 20379 const formats = editor.formatter.get(format); 20380 if (!formats) { 20381 return ''; 20382 } 20383 format = formats[0]; 20384 } 20385 if ('preview' in format) { 20386 const preview = format.preview; 20387 if (preview === false) { 20388 return ''; 20389 } else { 20390 previewStyles = preview || previewStyles; 20391 } 20392 } 20393 let name = format.block || format.inline || 'span'; 20394 let previewFrag; 20395 const items = parseSelector(format.selector); 20396 if (items.length > 0) { 20397 if (!items[0].name) { 20398 items[0].name = name; 20399 } 20400 name = format.selector; 20401 previewFrag = parsedSelectorToHtml(items, editor); 20402 } else { 20403 previewFrag = parsedSelectorToHtml([name], editor); 20404 } 20405 const previewElm = dom.select(name, previewFrag)[0] || previewFrag.firstChild; 20406 each$3(format.styles, (value, name) => { 20407 const newValue = removeVars(value); 20408 if (newValue) { 20409 dom.setStyle(previewElm, name, newValue); 20410 } 20411 }); 20412 each$3(format.attributes, (value, name) => { 20413 const newValue = removeVars(value); 20414 if (newValue) { 20415 dom.setAttrib(previewElm, name, newValue); 20416 } 20417 }); 20418 each$3(format.classes, value => { 20419 const newValue = removeVars(value); 20420 if (!dom.hasClass(previewElm, newValue)) { 20421 dom.addClass(previewElm, newValue); 20422 } 20423 }); 20424 editor.dispatch('PreviewFormats'); 20425 dom.setStyles(previewFrag, { 20426 position: 'absolute', 20427 left: -65535 20428 }); 20429 editor.getBody().appendChild(previewFrag); 20430 const rawParentFontSize = getComputedStyle('fontSize'); 20431 const parentFontSize = /px$/.test(rawParentFontSize) ? parseInt(rawParentFontSize, 10) : 0; 20432 each$3(previewStyles.split(' '), name => { 20433 let value = getComputedStyle(name, previewElm); 20434 if (name === 'background-color' && /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)) { 20435 value = getComputedStyle(name); 20436 if (rgbaToHexString(value).toLowerCase() === '#ffffff') { 20437 return; 20438 } 20439 } 20440 if (name === 'color') { 20441 if (rgbaToHexString(value).toLowerCase() === '#000000') { 20442 return; 20443 } 20444 } 20445 if (name === 'font-size') { 20446 if (/em|%$/.test(value)) { 20447 if (parentFontSize === 0) { 20448 return; 20449 } 20450 const numValue = parseFloat(value) / (/%$/.test(value) ? 100 : 1); 20451 value = numValue * parentFontSize + 'px'; 20452 } 20453 } 20454 if (name === 'border' && value) { 20455 previewCss += 'padding:0 2px;'; 20456 } 20457 previewCss += name + ':' + value + ';'; 20458 }); 20459 editor.dispatch('AfterPreviewFormats'); 20460 dom.remove(previewFrag); 20461 return previewCss; 20462 }; 20463 20464 const setup$r = editor => { 20465 editor.addShortcut('meta+b', '', 'Bold'); 20466 editor.addShortcut('meta+i', '', 'Italic'); 20467 editor.addShortcut('meta+u', '', 'Underline'); 20468 for (let i = 1; i <= 6; i++) { 20469 editor.addShortcut('access+' + i, '', [ 20470 'FormatBlock', 20471 false, 20472 'h' + i 20473 ]); 20474 } 20475 editor.addShortcut('access+7', '', [ 20476 'FormatBlock', 20477 false, 20478 'p' 20479 ]); 20480 editor.addShortcut('access+8', '', [ 20481 'FormatBlock', 20482 false, 20483 'div' 20484 ]); 20485 editor.addShortcut('access+9', '', [ 20486 'FormatBlock', 20487 false, 20488 'address' 20489 ]); 20490 }; 20491 20492 const Formatter = editor => { 20493 const formats = FormatRegistry(editor); 20494 const formatChangeState = Cell({}); 20495 setup$r(editor); 20496 setup$u(editor); 20497 if (!isRtc(editor)) { 20498 setup$t(formatChangeState, editor); 20499 } 20500 return { 20501 get: formats.get, 20502 has: formats.has, 20503 register: formats.register, 20504 unregister: formats.unregister, 20505 apply: (name, vars, node) => { 20506 applyFormat(editor, name, vars, node); 20507 }, 20508 remove: (name, vars, node, similar) => { 20509 removeFormat(editor, name, vars, node, similar); 20510 }, 20511 toggle: (name, vars, node) => { 20512 toggleFormat(editor, name, vars, node); 20513 }, 20514 match: (name, vars, node, similar) => matchFormat(editor, name, vars, node, similar), 20515 closest: names => closestFormat(editor, names), 20516 matchAll: (names, vars) => matchAllFormats(editor, names, vars), 20517 matchNode: (node, name, vars, similar) => matchNodeFormat(editor, node, name, vars, similar), 20518 canApply: name => canApplyFormat(editor, name), 20519 formatChanged: (formats, callback, similar, vars) => formatChanged(editor, formatChangeState, formats, callback, similar, vars), 20520 getCssText: curry(getCssText, editor) 20521 }; 20522 }; 20523 20524 const shouldIgnoreCommand = cmd => { 20525 switch (cmd.toLowerCase()) { 20526 case 'undo': 20527 case 'redo': 20528 case 'mcefocus': 20529 return true; 20530 default: 20531 return false; 20532 } 20533 }; 20534 const registerEvents = (editor, undoManager, locks) => { 20535 const isFirstTypedCharacter = Cell(false); 20536 const addNonTypingUndoLevel = e => { 20537 setTyping(undoManager, false, locks); 20538 undoManager.add({}, e); 20539 }; 20540 editor.on('init', () => { 20541 undoManager.add(); 20542 }); 20543 editor.on('BeforeExecCommand', e => { 20544 const cmd = e.command; 20545 if (!shouldIgnoreCommand(cmd)) { 20546 endTyping(undoManager, locks); 20547 undoManager.beforeChange(); 20548 } 20549 }); 20550 editor.on('ExecCommand', e => { 20551 const cmd = e.command; 20552 if (!shouldIgnoreCommand(cmd)) { 20553 addNonTypingUndoLevel(e); 20554 } 20555 }); 20556 editor.on('ObjectResizeStart cut', () => { 20557 undoManager.beforeChange(); 20558 }); 20559 editor.on('SaveContent ObjectResized blur', addNonTypingUndoLevel); 20560 editor.on('dragend', addNonTypingUndoLevel); 20561 editor.on('keyup', e => { 20562 const keyCode = e.keyCode; 20563 if (e.isDefaultPrevented()) { 20564 return; 20565 } 20566
vendor: 1,294 bytes, lines 20566-20598
20566if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45 || e.ctrlKey) { 20567 addNonTypingUndoLevel(); 20568 editor.nodeChanged(); 20569 } 20570 if (keyCode === 46 || keyCode === 8) { 20571 editor.nodeChanged(); 20572 } 20573 if (isFirstTypedCharacter.get() && undoManager.typing && !isEq$1(createFromEditor(editor), undoManager.data[0])) { 20574 if (!editor.isDirty()) { 20575 editor.setDirty(true); 20576 } 20577 editor.dispatch('TypingUndo'); 20578 isFirstTypedCharacter.set(false); 20579 editor.nodeChanged(); 20580 } 20581 }); 20582 editor.on('keydown', e => { 20583 const keyCode = e.keyCode; 20584 if (e.isDefaultPrevented()) { 20585 return; 20586 } 20587 if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45) { 20588 if (undoManager.typing) { 20589 addNonTypingUndoLevel(e); 20590 } 20591 return; 20592 } 20593 const modKey = e.ctrlKey && !e.altKey || e.metaKey; 20594 if ((keyCode < 16 || keyCode > 20) && keyCode !== 224 && keyCode !== 91 && !undoManager.typing && !modKey) { 20595 undoManager.beforeChange(); 20596 setTyping(undoManager, true, locks); 20597 undoManager.add({}, e); 20598 isFirstTypedCharacter.set(true
vendor: 8,750 bytes, lines 20598-20818
20598); 20599 } 20600 }); 20601 editor.on('mousedown', e => { 20602 if (undoManager.typing) { 20603 addNonTypingUndoLevel(e); 20604 } 20605 }); 20606 const isInsertReplacementText = event => event.inputType === 'insertReplacementText'; 20607 const isInsertTextDataNull = event => event.inputType === 'insertText' && event.data === null; 20608 const isInsertFromPasteOrDrop = event => event.inputType === 'insertFromPaste' || event.inputType === 'insertFromDrop'; 20609 editor.on('input', e => { 20610 if (e.inputType && (isInsertReplacementText(e) || isInsertTextDataNull(e) || isInsertFromPasteOrDrop(e))) { 20611 addNonTypingUndoLevel(e); 20612 } 20613 }); 20614 editor.on('AddUndo Undo Redo ClearUndos', e => { 20615 if (!e.isDefaultPrevented()) { 20616 editor.nodeChanged(); 20617 } 20618 }); 20619 }; 20620 const addKeyboardShortcuts = editor => { 20621 editor.addShortcut('meta+z', '', 'Undo'); 20622 editor.addShortcut('meta+y,meta+shift+z', '', 'Redo'); 20623 }; 20624 20625 const UndoManager = editor => { 20626 const beforeBookmark = value$2(); 20627 const locks = Cell(0); 20628 const index = Cell(0); 20629 const undoManager = { 20630 data: [], 20631 typing: false, 20632 beforeChange: () => { 20633 beforeChange(editor, locks, beforeBookmark); 20634 }, 20635 add: (level, event) => { 20636 return addUndoLevel(editor, undoManager, index, locks, beforeBookmark, level, event); 20637 }, 20638 dispatchChange: () => { 20639 editor.setDirty(true); 20640 const level = createFromEditor(editor); 20641 level.bookmark = getUndoBookmark(editor.selection); 20642 editor.dispatch('change', { 20643 level, 20644 lastLevel: get$b(undoManager.data, index.get()).getOrUndefined() 20645 }); 20646 }, 20647 undo: () => { 20648 return undo(editor, undoManager, locks, index); 20649 }, 20650 redo: () => { 20651 return redo(editor, index, undoManager.data); 20652 }, 20653 clear: () => { 20654 clear(editor, undoManager, index); 20655 }, 20656 reset: () => { 20657 reset(editor, undoManager); 20658 }, 20659 hasUndo: () => { 20660 return hasUndo(editor, undoManager, index); 20661 }, 20662 hasRedo: () => { 20663 return hasRedo(editor, undoManager, index); 20664 }, 20665 transact: callback => { 20666 return transact(editor, undoManager, locks, callback); 20667 }, 20668 ignore: callback => { 20669 ignore(editor, locks, callback); 20670 }, 20671 extra: (callback1, callback2) => { 20672 extra(editor, undoManager, index, callback1, callback2); 20673 } 20674 }; 20675 if (!isRtc(editor)) { 20676 registerEvents(editor, undoManager, locks); 20677 } 20678 addKeyboardShortcuts(editor); 20679 return undoManager; 20680 }; 20681 20682 const nonTypingKeycodes = [ 20683 9, 20684 27, 20685 VK.HOME, 20686 VK.END, 20687 19, 20688 20, 20689 44, 20690 144, 20691 145, 20692 33, 20693 34, 20694 45, 20695 16, 20696 17, 20697 18, 20698 91, 20699 92, 20700 93, 20701 VK.DOWN, 20702 VK.UP, 20703 VK.LEFT, 20704 VK.RIGHT 20705 ].concat(Env.browser.isFirefox() ? [224] : []); 20706 const placeholderAttr = 'data-mce-placeholder'; 20707 const isKeyboardEvent = e => e.type === 'keydown' || e.type === 'keyup'; 20708 const isDeleteEvent = e => { 20709 const keyCode = e.keyCode; 20710 return keyCode === VK.BACKSPACE || keyCode === VK.DELETE; 20711 }; 20712 const isNonTypingKeyboardEvent = e => { 20713 if (isKeyboardEvent(e)) { 20714 const keyCode = e.keyCode; 20715 return !isDeleteEvent(e) && (VK.metaKeyPressed(e) || e.altKey || keyCode >= 112 && keyCode <= 123 || contains$2(nonTypingKeycodes, keyCode)); 20716 } else { 20717 return false; 20718 } 20719 }; 20720 const isTypingKeyboardEvent = e => isKeyboardEvent(e) && !(isDeleteEvent(e) || e.type === 'keyup' && e.keyCode === 229); 20721 const isVisuallyEmpty = (dom, rootElm, forcedRootBlock) => { 20722 if (isEmpty$2(SugarElement.fromDom(rootElm), false)) { 20723 const firstElement = rootElm.firstElementChild; 20724 if (!firstElement) { 20725 return true; 20726 } else if (dom.getStyle(rootElm.firstElementChild, 'padding-left') || dom.getStyle(rootElm.firstElementChild, 'padding-right')) { 20727 return false; 20728 } else { 20729 return forcedRootBlock === firstElement.nodeName.toLowerCase(); 20730 } 20731 } else { 20732 return false; 20733 } 20734 }; 20735 const setup$q = editor => { 20736 var _a; 20737 const dom = editor.dom; 20738 const rootBlock = getForcedRootBlock(editor); 20739 const placeholder = (_a = getPlaceholder(editor)) !== null && _a !== void 0 ? _a : ''; 20740 const updatePlaceholder = (e, initial) => { 20741 if (isNonTypingKeyboardEvent(e)) { 20742 return; 20743 } 20744 const body = editor.getBody(); 20745 const showPlaceholder = isTypingKeyboardEvent(e) ? false : isVisuallyEmpty(dom, body, rootBlock); 20746 const isPlaceholderShown = dom.getAttrib(body, placeholderAttr) !== ''; 20747 if (isPlaceholderShown !== showPlaceholder || initial) { 20748 dom.setAttrib(body, placeholderAttr, showPlaceholder ? placeholder : null); 20749 dom.setAttrib(body, 'aria-placeholder', showPlaceholder ? placeholder : null); 20750 firePlaceholderToggle(editor, showPlaceholder); 20751 editor.on(showPlaceholder ? 'keydown' : 'keyup', updatePlaceholder); 20752 editor.off(showPlaceholder ? 'keyup' : 'keydown', updatePlaceholder); 20753 } 20754 }; 20755 if (isNotEmpty(placeholder)) { 20756 editor.on('init', e => { 20757 updatePlaceholder(e, true); 20758 editor.on('change SetContent ExecCommand', updatePlaceholder); 20759 editor.on('paste', e => Delay.setEditorTimeout(editor, () => updatePlaceholder(e))); 20760 }); 20761 } 20762 }; 20763 20764 const blockPosition = (block, position) => ({ 20765 block, 20766 position 20767 }); 20768 const blockBoundary = (from, to) => ({ 20769 from, 20770 to 20771 }); 20772 const getBlockPosition = (rootNode, pos) => { 20773 const rootElm = SugarElement.fromDom(rootNode); 20774 const containerElm = SugarElement.fromDom(pos.container()); 20775 return getParentBlock$2(rootElm, containerElm).map(block => blockPosition(block, pos)); 20776 }; 20777 const isDifferentBlocks = blockBoundary => !eq(blockBoundary.from.block, blockBoundary.to.block); 20778 const getClosestHost = (root, scope) => { 20779 const isRoot = node => eq(node, root); 20780 const isHost = node => isTableCell$2(node) || isContentEditableTrue$3(node.dom); 20781 return closest$4(scope, isHost, isRoot).filter(isElement$7).getOr(root); 20782 }; 20783 const hasSameHost = (rootNode, blockBoundary) => { 20784 const root = SugarElement.fromDom(rootNode); 20785 return eq(getClosestHost(root, blockBoundary.from.block), getClosestHost(root, blockBoundary.to.block)); 20786 }; 20787 const isEditable$1 = blockBoundary => isContentEditableFalse$b(blockBoundary.from.block.dom) === false && isContentEditableFalse$b(blockBoundary.to.block.dom) === false; 20788 const hasValidBlocks = blockBoundary => { 20789 const isValidBlock = block => isTextBlock$2(block) || hasBlockAttr(block.dom); 20790 return isValidBlock(blockBoundary.from.block) && isValidBlock(blockBoundary.to.block); 20791 }; 20792 const skipLastBr = (rootNode, forward, blockPosition) => { 20793 if (isBr$6(blockPosition.position.getNode()) && !isEmpty$2(blockPosition.block)) { 20794 return positionIn(false, blockPosition.block.dom).bind(lastPositionInBlock => { 20795 if (lastPositionInBlock.isEqual(blockPosition.position)) { 20796 return fromPosition(forward, rootNode, lastPositionInBlock).bind(to => getBlockPosition(rootNode, to)); 20797 } else { 20798 return Optional.some(blockPosition); 20799 } 20800 }).getOr(blockPosition); 20801 } else { 20802 return blockPosition; 20803 } 20804 }; 20805 const readFromRange = (rootNode, forward, rng) => { 20806 const fromBlockPos = getBlockPosition(rootNode, CaretPosition.fromRangeStart(rng)); 20807 const toBlockPos = fromBlockPos.bind(blockPos => fromPosition(forward, rootNode, blockPos.position).bind(to => getBlockPosition(rootNode, to).map(blockPos => skipLastBr(rootNode, forward, blockPos)))); 20808 return lift2(fromBlockPos, toBlockPos, blockBoundary).filter(blockBoundary => isDifferentBlocks(blockBoundary) && hasSameHost(rootNode, blockBoundary) && isEditable$1(blockBoundary) && hasValidBlocks(blockBoundary)); 20809 }; 20810 const read$1 = (rootNode, forward, rng) => rng.collapsed ? readFromRange(rootNode, forward, rng) : Optional.none(); 20811 20812 const getChildrenUntilBlockBoundary = block => { 20813 const children = children$1(block); 20814 return findIndex$2(children, isBlock$2).fold(constant(children), index => children.slice(0, index)); 20815 }; 20816 const extractChildren = block => { 20817 const children = getChildrenUntilBlockBoundary(block); 20818 each$e(children, remove$
vendor: 2,486 bytes, lines 20818-20871
208186); 20819 return children; 20820 }; 20821 const removeEmptyRoot = (rootNode, block) => { 20822 const parents = parentsAndSelf(block, rootNode); 20823 return find$2(parents.reverse(), element => isEmpty$2(element)).each(remove$6); 20824 }; 20825 const isEmptyBefore = el => filter$5(prevSiblings(el), el => !isEmpty$2(el)).length === 0; 20826 const nestedBlockMerge = (rootNode, fromBlock, toBlock, insertionPoint) => { 20827 if (isEmpty$2(toBlock)) { 20828 fillWithPaddingBr(toBlock); 20829 return firstPositionIn(toBlock.dom); 20830 } 20831 if (isEmptyBefore(insertionPoint) && isEmpty$2(fromBlock)) { 20832 before$3(insertionPoint, SugarElement.fromTag('br')); 20833 } 20834 const position = prevPosition(toBlock.dom, CaretPosition.before(insertionPoint.dom)); 20835 each$e(extractChildren(fromBlock), child => { 20836 before$3(insertionPoint, child); 20837 }); 20838 removeEmptyRoot(rootNode, fromBlock); 20839 return position; 20840 }; 20841 const sidelongBlockMerge = (rootNode, fromBlock, toBlock) => { 20842 if (isEmpty$2(toBlock)) { 20843 if (isEmpty$2(fromBlock)) { 20844 const getInlineToBlockDescendants = el => { 20845 const helper = (node, elements) => firstChild(node).fold(() => elements, child => isInline$1(child) ? helper(child, elements.concat(shallow$1(child))) : elements); 20846 return helper(el, []); 20847 }; 20848 const newFromBlockDescendants = foldr(getInlineToBlockDescendants(toBlock), (element, descendant) => { 20849 wrap$2(element, descendant); 20850 return descendant; 20851 }, createPaddingBr()); 20852 empty(fromBlock); 20853 append$1(fromBlock, newFromBlockDescendants); 20854 } 20855 remove$6(toBlock); 20856 return firstPositionIn(fromBlock.dom); 20857 } 20858 const position = lastPositionIn(toBlock.dom); 20859 each$e(extractChildren(fromBlock), child => { 20860 append$1(toBlock, child); 20861 }); 20862 removeEmptyRoot(rootNode, fromBlock); 20863 return position; 20864 }; 20865 const findInsertionPoint = (toBlock, block) => { 20866 const parentsAndSelf$1 = parentsAndSelf(block, toBlock); 20867 return Optional.from(parentsAndSelf$1[parentsAndSelf$1.length - 1]); 20868 }; 20869 const getInsertionPoint = (fromBlock, toBlock) => contains(toBlock, fromBlock) ? findInsertionPoint(toBlock, fromBlock) : Optional.none(); 20870 const trimBr = (first, block) => { 20871 positionIn(first, block.dom).bind(position => Optional.from(position.getNode())).map(SugarElement.fromDom).filter(isBr$5).each(remove$6
vendor: 13,287 bytes, lines 20871-21119
20871); 20872 }; 20873 const mergeBlockInto = (rootNode, fromBlock, toBlock) => { 20874 trimBr(true, fromBlock); 20875 trimBr(false, toBlock); 20876 return getInsertionPoint(fromBlock, toBlock).fold(curry(sidelongBlockMerge, rootNode, fromBlock, toBlock), curry(nestedBlockMerge, rootNode, fromBlock, toBlock)); 20877 }; 20878 const mergeBlocks = (rootNode, forward, block1, block2) => forward ? mergeBlockInto(rootNode, block2, block1) : mergeBlockInto(rootNode, block1, block2); 20879 20880 const backspaceDelete$8 = (editor, forward) => { 20881 const rootNode = SugarElement.fromDom(editor.getBody()); 20882 const position = read$1(rootNode.dom, forward, editor.selection.getRng()).map(blockBoundary => () => { 20883 mergeBlocks(rootNode, forward, blockBoundary.from.block, blockBoundary.to.block).each(pos => { 20884 editor.selection.setRng(pos.toRange()); 20885 }); 20886 }); 20887 return position; 20888 }; 20889 20890 const deleteRangeMergeBlocks = (rootNode, selection) => { 20891 const rng = selection.getRng(); 20892 return lift2(getParentBlock$2(rootNode, SugarElement.fromDom(rng.startContainer)), getParentBlock$2(rootNode, SugarElement.fromDom(rng.endContainer)), (block1, block2) => { 20893 if (!eq(block1, block2)) { 20894 return Optional.some(() => { 20895 rng.deleteContents(); 20896 mergeBlocks(rootNode, true, block1, block2).each(pos => { 20897 selection.setRng(pos.toRange()); 20898 }); 20899 }); 20900 } else { 20901 return Optional.none(); 20902 } 20903 }).getOr(Optional.none()); 20904 }; 20905 const isRawNodeInTable = (root, rawNode) => { 20906 const node = SugarElement.fromDom(rawNode); 20907 const isRoot = curry(eq, root); 20908 return ancestor$4(node, isTableCell$2, isRoot).isSome(); 20909 }; 20910 const isSelectionInTable = (root, rng) => isRawNodeInTable(root, rng.startContainer) || isRawNodeInTable(root, rng.endContainer); 20911 const isEverythingSelected = (root, rng) => { 20912 const noPrevious = prevPosition(root.dom, CaretPosition.fromRangeStart(rng)).isNone(); 20913 const noNext = nextPosition(root.dom, CaretPosition.fromRangeEnd(rng)).isNone(); 20914 return !isSelectionInTable(root, rng) && noPrevious && noNext; 20915 }; 20916 const emptyEditor = editor => { 20917 return Optional.some(() => { 20918 editor.setContent(''); 20919 editor.selection.setCursorLocation(); 20920 }); 20921 }; 20922 const deleteRange$2 = editor => { 20923 const rootNode = SugarElement.fromDom(editor.getBody()); 20924 const rng = editor.selection.getRng(); 20925 return isEverythingSelected(rootNode, rng) ? emptyEditor(editor) : deleteRangeMergeBlocks(rootNode, editor.selection); 20926 }; 20927 const backspaceDelete$7 = (editor, _forward) => editor.selection.isCollapsed() ? Optional.none() : deleteRange$2(editor); 20928 20929 const showCaret = (direction, editor, node, before, scrollIntoView) => Optional.from(editor._selectionOverrides.showCaret(direction, node, before, scrollIntoView)); 20930 const getNodeRange = node => { 20931 const rng = node.ownerDocument.createRange(); 20932 rng.selectNode(node); 20933 return rng; 20934 }; 20935 const selectNode = (editor, node) => { 20936 const e = editor.dispatch('BeforeObjectSelected', { target: node }); 20937 if (e.isDefaultPrevented()) { 20938 return Optional.none(); 20939 } 20940 return Optional.some(getNodeRange(node)); 20941 }; 20942 const renderCaretAtRange = (editor, range, scrollIntoView) => { 20943 const normalizedRange = normalizeRange(1, editor.getBody(), range); 20944 const caretPosition = CaretPosition.fromRangeStart(normalizedRange); 20945 const caretPositionNode = caretPosition.getNode(); 20946 if (isInlineFakeCaretTarget(caretPositionNode)) { 20947 return showCaret(1, editor, caretPositionNode, !caretPosition.isAtEnd(), false); 20948 } 20949 const caretPositionBeforeNode = caretPosition.getNode(true); 20950 if (isInlineFakeCaretTarget(caretPositionBeforeNode)) { 20951 return showCaret(1, editor, caretPositionBeforeNode, false, false); 20952 } 20953 const ceRoot = getContentEditableRoot$1(editor.dom.getRoot(), caretPosition.getNode()); 20954 if (isInlineFakeCaretTarget(ceRoot)) { 20955 return showCaret(1, editor, ceRoot, false, scrollIntoView); 20956 } 20957 return Optional.none(); 20958 }; 20959 const renderRangeCaret = (editor, range, scrollIntoView) => range.collapsed ? renderCaretAtRange(editor, range, scrollIntoView).getOr(range) : range; 20960 20961 const isBeforeBoundary = pos => isBeforeContentEditableFalse(pos) || isBeforeMedia(pos); 20962 const isAfterBoundary = pos => isAfterContentEditableFalse(pos) || isAfterMedia(pos); 20963 const trimEmptyTextNode = (dom, node) => { 20964 if (isText$a(node) && node.data.length === 0) { 20965 dom.remove(node); 20966 } 20967 }; 20968 const deleteContentAndShowCaret = (editor, range, node, direction, forward, peekCaretPosition) => { 20969 showCaret(direction, editor, peekCaretPosition.getNode(!forward), forward, true).each(caretRange => { 20970 if (range.collapsed) { 20971 const deleteRange = range.cloneRange(); 20972 if (forward) { 20973 deleteRange.setEnd(caretRange.startContainer, caretRange.startOffset); 20974 } else { 20975 deleteRange.setStart(caretRange.endContainer, caretRange.endOffset); 20976 } 20977 deleteRange.deleteContents(); 20978 } else { 20979 range.deleteContents(); 20980 } 20981 editor.selection.setRng(caretRange); 20982 }); 20983 trimEmptyTextNode(editor.dom, node); 20984 }; 20985 const deleteBoundaryText = (editor, forward) => { 20986 const range = editor.selection.getRng(); 20987 if (!isText$a(range.commonAncestorContainer)) { 20988 return Optional.none(); 20989 } 20990 const direction = forward ? HDirection.Forwards : HDirection.Backwards; 20991 const caretWalker = CaretWalker(editor.getBody()); 20992 const getNextPosFn = curry(getVisualCaretPosition, forward ? caretWalker.next : caretWalker.prev); 20993 const isBeforeFn = forward ? isBeforeBoundary : isAfterBoundary; 20994 const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range); 20995 const nextCaretPosition = getNextPosFn(caretPosition); 20996 const normalizedNextCaretPosition = nextCaretPosition ? normalizePosition(forward, nextCaretPosition) : nextCaretPosition; 20997 if (!normalizedNextCaretPosition || !isMoveInsideSameBlock(caretPosition, normalizedNextCaretPosition)) { 20998 return Optional.none(); 20999 } else if (isBeforeFn(normalizedNextCaretPosition)) { 21000 return Optional.some(() => deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, normalizedNextCaretPosition)); 21001 } 21002 const peekCaretPosition = getNextPosFn(normalizedNextCaretPosition); 21003 if (peekCaretPosition && isBeforeFn(peekCaretPosition)) { 21004 if (isMoveInsideSameBlock(normalizedNextCaretPosition, peekCaretPosition)) { 21005 return Optional.some(() => deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, peekCaretPosition)); 21006 } 21007 } 21008 return Optional.none(); 21009 }; 21010 const backspaceDelete$6 = (editor, forward) => deleteBoundaryText(editor, forward); 21011 21012 const getEdgeCefPosition = (editor, atStart) => { 21013 const root = editor.getBody(); 21014 return atStart ? firstPositionIn(root).filter(isBeforeContentEditableFalse) : lastPositionIn(root).filter(isAfterContentEditableFalse); 21015 }; 21016 const isCefAtEdgeSelected = editor => { 21017 const rng = editor.selection.getRng(); 21018 return !rng.collapsed && (getEdgeCefPosition(editor, true).exists(pos => pos.isEqual(CaretPosition.fromRangeStart(rng))) || getEdgeCefPosition(editor, false).exists(pos => pos.isEqual(CaretPosition.fromRangeEnd(rng)))); 21019 }; 21020 21021 const isCompoundElement = node => isNonNullable(node) && (isTableCell$2(SugarElement.fromDom(node)) || isListItem$1(SugarElement.fromDom(node))); 21022 const DeleteAction = Adt.generate([ 21023 { remove: ['element'] }, 21024 { moveToElement: ['element'] }, 21025 { moveToPosition: ['position'] } 21026 ]); 21027 const isAtContentEditableBlockCaret = (forward, from) => { 21028 const elm = from.getNode(!forward); 21029 const caretLocation = forward ? 'after' : 'before'; 21030 return isElement$6(elm) && elm.getAttribute('data-mce-caret') === caretLocation; 21031 }; 21032 const isDeleteFromCefDifferentBlocks = (root, forward, from, to) => { 21033 const inSameBlock = elm => isInline$1(SugarElement.fromDom(elm)) && !isInSameBlock(from, to, root); 21034 return getRelativeCefElm(!forward, from).fold(() => getRelativeCefElm(forward, to).fold(never, inSameBlock), inSameBlock); 21035 }; 21036 const deleteEmptyBlockOrMoveToCef = (root, forward, from, to) => { 21037 const toCefElm = to.getNode(!forward); 21038 return getParentBlock$2(SugarElement.fromDom(root), SugarElement.fromDom(from.getNode())).map(blockElm => isEmpty$2(blockElm) ? DeleteAction.remove(blockElm.dom) : DeleteAction.moveToElement(toCefElm)).orThunk(() => Optional.some(DeleteAction.moveToElement(toCefElm))); 21039 }; 21040 const findCefPosition = (root, forward, from) => fromPosition(forward, root, from).bind(to => { 21041 if (isCompoundElement(to.getNode())) { 21042 return Optional.none(); 21043 } else if (isDeleteFromCefDifferentBlocks(root, forward, from, to)) { 21044 return Optional.none(); 21045 } else if (forward && isContentEditableFalse$b(to.getNode())) { 21046 return deleteEmptyBlockOrMoveToCef(root, forward, from, to); 21047 } else if (!forward && isContentEditableFalse$b(to.getNode(true))) { 21048 return deleteEmptyBlockOrMoveToCef(root, forward, from, to); 21049 } else if (forward && isAfterContentEditableFalse(from)) { 21050 return Optional.some(DeleteAction.moveToPosition(to)); 21051 } else if (!forward && isBeforeContentEditableFalse(from)) { 21052 return Optional.some(DeleteAction.moveToPosition(to)); 21053 } else { 21054 return Optional.none(); 21055 } 21056 }); 21057 const getContentEditableBlockAction = (forward, elm) => { 21058 if (isNullable(elm)) { 21059 return Optional.none(); 21060 } else if (forward && isContentEditableFalse$b(elm.nextSibling)) { 21061 return Optional.some(DeleteAction.moveToElement(elm.nextSibling)); 21062 } else if (!forward && isContentEditableFalse$b(elm.previousSibling)) { 21063 return Optional.some(DeleteAction.moveToElement(elm.previousSibling)); 21064 } else { 21065 return Optional.none(); 21066 } 21067 }; 21068 const skipMoveToActionFromInlineCefToContent = (root, from, deleteAction) => deleteAction.fold(elm => Optional.some(DeleteAction.remove(elm)), elm => Optional.some(DeleteAction.moveToElement(elm)), to => { 21069 if (isInSameBlock(from, to, root)) { 21070 return Optional.none(); 21071 } else { 21072 return Optional.some(DeleteAction.moveToPosition(to)); 21073 } 21074 }); 21075 const getContentEditableAction = (root, forward, from) => { 21076 if (isAtContentEditableBlockCaret(forward, from)) { 21077 return getContentEditableBlockAction(forward, from.getNode(!forward)).orThunk(() => findCefPosition(root, forward, from)); 21078 } else { 21079 return findCefPosition(root, forward, from).bind(deleteAction => skipMoveToActionFromInlineCefToContent(root, from, deleteAction)); 21080 } 21081 }; 21082 const read = (root, forward, rng) => { 21083 const normalizedRange = normalizeRange(forward ? 1 : -1, root, rng); 21084 const from = CaretPosition.fromRangeStart(normalizedRange); 21085 const rootElement = SugarElement.fromDom(root); 21086 if (!forward && isAfterContentEditableFalse(from)) { 21087 return Optional.some(DeleteAction.remove(from.getNode(true))); 21088 } else if (forward && isBeforeContentEditableFalse(from)) { 21089 return Optional.some(DeleteAction.remove(from.getNode())); 21090 } else if (!forward && isBeforeContentEditableFalse(from) && isAfterBr(rootElement, from)) { 21091 return findPreviousBr(rootElement, from).map(br => DeleteAction.remove(br.getNode())); 21092 } else if (forward && isAfterContentEditableFalse(from) && isBeforeBr$1(rootElement, from)) { 21093 return findNextBr(rootElement, from).map(br => DeleteAction.remove(br.getNode())); 21094 } else { 21095 return getContentEditableAction(root, forward, from); 21096 } 21097 }; 21098 21099 const deleteElement$1 = (editor, forward) => element => { 21100 editor._selectionOverrides.hideFakeCaret(); 21101 deleteElement$2(editor, forward, SugarElement.fromDom(element)); 21102 return true; 21103 }; 21104 const moveToElement = (editor, forward) => element => { 21105 const pos = forward ? CaretPosition.before(element) : CaretPosition.after(element); 21106 editor.selection.setRng(pos.toRange()); 21107 return true; 21108 }; 21109 const moveToPosition = editor => pos => { 21110 editor.selection.setRng(pos.toRange()); 21111 return true; 21112 }; 21113 const getAncestorCe = (editor, node) => Optional.from(getContentEditableRoot$1(editor.getBody(), node)); 21114 const backspaceDeleteCaret = (editor, forward) => { 21115 const selectedNode = editor.selection.getNode(); 21116 return getAncestorCe(editor, selectedNode).filter(isContentEditableFalse$b).fold(() => read(editor.getBody(), forward, editor.selection.getRng()).map(deleteAction => () => deleteAction.fold(deleteElement$1(editor, forward), moveToElement(editor, forward), moveToPosition(editor))), () => Optional.some(noop)); 21117 }; 21118 const deleteOffscreenSelection = rootElement => { 21119 each$e(descendants(rootElement, '.mce-offscreen-selection'), remove$
vendor: 5,687 bytes, lines 21119-21260
211196); 21120 }; 21121 const backspaceDeleteRange = (editor, forward) => { 21122 const selectedNode = editor.selection.getNode(); 21123 if (isContentEditableFalse$b(selectedNode) && !isTableCell$3(selectedNode)) { 21124 const hasCefAncestor = getAncestorCe(editor, selectedNode.parentNode).filter(isContentEditableFalse$b); 21125 return hasCefAncestor.fold(() => Optional.some(() => { 21126 deleteOffscreenSelection(SugarElement.fromDom(editor.getBody())); 21127 deleteElement$2(editor, forward, SugarElement.fromDom(editor.selection.getNode())); 21128 paddEmptyBody(editor); 21129 }), () => Optional.some(noop)); 21130 } 21131 if (isCefAtEdgeSelected(editor)) { 21132 return Optional.some(() => { 21133 deleteRangeContents(editor, editor.selection.getRng(), SugarElement.fromDom(editor.getBody())); 21134 }); 21135 } 21136 return Optional.none(); 21137 }; 21138 const paddEmptyElement = editor => { 21139 const dom = editor.dom, selection = editor.selection; 21140 const ceRoot = getContentEditableRoot$1(editor.getBody(), selection.getNode()); 21141 if (isContentEditableTrue$3(ceRoot) && dom.isBlock(ceRoot) && dom.isEmpty(ceRoot)) { 21142 const br = dom.create('br', { 'data-mce-bogus': '1' }); 21143 dom.setHTML(ceRoot, ''); 21144 ceRoot.appendChild(br); 21145 selection.setRng(CaretPosition.before(br).toRange()); 21146 } 21147 return true; 21148 }; 21149 const backspaceDelete$5 = (editor, forward) => { 21150 if (editor.selection.isCollapsed()) { 21151 return backspaceDeleteCaret(editor, forward); 21152 } else { 21153 return backspaceDeleteRange(editor, forward); 21154 } 21155 }; 21156 21157 const deleteCaret$2 = (editor, forward) => { 21158 const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng()); 21159 return fromPosition(forward, editor.getBody(), fromPos).filter(pos => forward ? isBeforeImageBlock(pos) : isAfterImageBlock(pos)).bind(pos => getChildNodeAtRelativeOffset(forward ? 0 : -1, pos)).map(elm => () => editor.selection.select(elm)); 21160 }; 21161 const backspaceDelete$4 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret$2(editor, forward) : Optional.none(); 21162 21163 const isText$2 = isText$a; 21164 const startsWithCaretContainer = node => isText$2(node) && node.data[0] === ZWSP$1; 21165 const endsWithCaretContainer = node => isText$2(node) && node.data[node.data.length - 1] === ZWSP$1; 21166 const createZwsp = node => { 21167 var _a; 21168 const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document; 21169 return doc.createTextNode(ZWSP$1); 21170 }; 21171 const insertBefore = node => { 21172 var _a; 21173 if (isText$2(node.previousSibling)) { 21174 if (endsWithCaretContainer(node.previousSibling)) { 21175 return node.previousSibling; 21176 } else { 21177 node.previousSibling.appendData(ZWSP$1); 21178 return node.previousSibling; 21179 } 21180 } else if (isText$2(node)) { 21181 if (startsWithCaretContainer(node)) { 21182 return node; 21183 } else { 21184 node.insertData(0, ZWSP$1); 21185 return node; 21186 } 21187 } else { 21188 const newNode = createZwsp(node); 21189 (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(newNode, node); 21190 return newNode; 21191 } 21192 }; 21193 const insertAfter = node => { 21194 var _a, _b; 21195 if (isText$2(node.nextSibling)) { 21196 if (startsWithCaretContainer(node.nextSibling)) { 21197 return node.nextSibling; 21198 } else { 21199 node.nextSibling.insertData(0, ZWSP$1); 21200 return node.nextSibling; 21201 } 21202 } else if (isText$2(node)) { 21203 if (endsWithCaretContainer(node)) { 21204 return node; 21205 } else { 21206 node.appendData(ZWSP$1); 21207 return node; 21208 } 21209 } else { 21210 const newNode = createZwsp(node); 21211 if (node.nextSibling) { 21212 (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(newNode, node.nextSibling); 21213 } else { 21214 (_b = node.parentNode) === null || _b === void 0 ? void 0 : _b.appendChild(newNode); 21215 } 21216 return newNode; 21217 } 21218 }; 21219 const insertInline = (before, node) => before ? insertBefore(node) : insertAfter(node); 21220 const insertInlineBefore = curry(insertInline, true); 21221 const insertInlineAfter = curry(insertInline, false); 21222 21223 const insertInlinePos = (pos, before) => { 21224 if (isText$a(pos.container())) { 21225 return insertInline(before, pos.container()); 21226 } else { 21227 return insertInline(before, pos.getNode()); 21228 } 21229 }; 21230 const isPosCaretContainer = (pos, caret) => { 21231 const caretNode = caret.get(); 21232 return caretNode && pos.container() === caretNode && isCaretContainerInline(caretNode); 21233 }; 21234 const renderCaret = (caret, location) => location.fold(element => { 21235 remove$4(caret.get()); 21236 const text = insertInlineBefore(element); 21237 caret.set(text); 21238 return Optional.some(CaretPosition(text, text.length - 1)); 21239 }, element => firstPositionIn(element).map(pos => { 21240 if (!isPosCaretContainer(pos, caret)) { 21241 remove$4(caret.get()); 21242 const text = insertInlinePos(pos, true); 21243 caret.set(text); 21244 return CaretPosition(text, 1); 21245 } else { 21246 const node = caret.get(); 21247 return CaretPosition(node, 1); 21248 } 21249 }), element => lastPositionIn(element).map(pos => { 21250 if (!isPosCaretContainer(pos, caret)) { 21251 remove$4(caret.get()); 21252 const text = insertInlinePos(pos, false); 21253 caret.set(text); 21254 return CaretPosition(text, text.length - 1); 21255 } else { 21256 const node = caret.get(); 21257 return CaretPosition(node, node.length - 1); 21258 } 21259 }), element => { 21260 remove$4
vendor: 29,150 bytes, lines 21260-21877
21260(caret.get()); 21261 const text = insertInlineAfter(element); 21262 caret.set(text); 21263 return Optional.some(CaretPosition(text, 1)); 21264 }); 21265 21266 const evaluateUntil = (fns, args) => { 21267 for (let i = 0; i < fns.length; i++) { 21268 const result = fns[i].apply(null, args); 21269 if (result.isSome()) { 21270 return result; 21271 } 21272 } 21273 return Optional.none(); 21274 }; 21275 21276 const Location = Adt.generate([ 21277 { before: ['element'] }, 21278 { start: ['element'] }, 21279 { end: ['element'] }, 21280 { after: ['element'] } 21281 ]); 21282 const rescope$1 = (rootNode, node) => { 21283 const parentBlock = getParentBlock$3(node, rootNode); 21284 return parentBlock ? parentBlock : rootNode; 21285 }; 21286 const before = (isInlineTarget, rootNode, pos) => { 21287 const nPos = normalizeForwards(pos); 21288 const scope = rescope$1(rootNode, nPos.container()); 21289 return findRootInline(isInlineTarget, scope, nPos).fold(() => nextPosition(scope, nPos).bind(curry(findRootInline, isInlineTarget, scope)).map(inline => Location.before(inline)), Optional.none); 21290 }; 21291 const isNotInsideFormatCaretContainer = (rootNode, elm) => getParentCaretContainer(rootNode, elm) === null; 21292 const findInsideRootInline = (isInlineTarget, rootNode, pos) => findRootInline(isInlineTarget, rootNode, pos).filter(curry(isNotInsideFormatCaretContainer, rootNode)); 21293 const start$1 = (isInlineTarget, rootNode, pos) => { 21294 const nPos = normalizeBackwards(pos); 21295 return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(inline => { 21296 const prevPos = prevPosition(inline, nPos); 21297 return prevPos.isNone() ? Optional.some(Location.start(inline)) : Optional.none(); 21298 }); 21299 }; 21300 const end = (isInlineTarget, rootNode, pos) => { 21301 const nPos = normalizeForwards(pos); 21302 return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(inline => { 21303 const nextPos = nextPosition(inline, nPos); 21304 return nextPos.isNone() ? Optional.some(Location.end(inline)) : Optional.none(); 21305 }); 21306 }; 21307 const after = (isInlineTarget, rootNode, pos) => { 21308 const nPos = normalizeBackwards(pos); 21309 const scope = rescope$1(rootNode, nPos.container()); 21310 return findRootInline(isInlineTarget, scope, nPos).fold(() => prevPosition(scope, nPos).bind(curry(findRootInline, isInlineTarget, scope)).map(inline => Location.after(inline)), Optional.none); 21311 }; 21312 const isValidLocation = location => !isRtl(getElement(location)); 21313 const readLocation = (isInlineTarget, rootNode, pos) => { 21314 const location = evaluateUntil([ 21315 before, 21316 start$1, 21317 end, 21318 after 21319 ], [ 21320 isInlineTarget, 21321 rootNode, 21322 pos 21323 ]); 21324 return location.filter(isValidLocation); 21325 }; 21326 const getElement = location => location.fold(identity, identity, identity, identity); 21327 const getName = location => location.fold(constant('before'), constant('start'), constant('end'), constant('after')); 21328 const outside = location => location.fold(Location.before, Location.before, Location.after, Location.after); 21329 const inside = location => location.fold(Location.start, Location.start, Location.end, Location.end); 21330 const isEq = (location1, location2) => getName(location1) === getName(location2) && getElement(location1) === getElement(location2); 21331 const betweenInlines = (forward, isInlineTarget, rootNode, from, to, location) => lift2(findRootInline(isInlineTarget, rootNode, from), findRootInline(isInlineTarget, rootNode, to), (fromInline, toInline) => { 21332 if (fromInline !== toInline && hasSameParentBlock(rootNode, fromInline, toInline)) { 21333 return Location.after(forward ? fromInline : toInline); 21334 } else { 21335 return location; 21336 } 21337 }).getOr(location); 21338 const skipNoMovement = (fromLocation, toLocation) => fromLocation.fold(always, fromLocation => !isEq(fromLocation, toLocation)); 21339 const findLocationTraverse = (forward, isInlineTarget, rootNode, fromLocation, pos) => { 21340 const from = normalizePosition(forward, pos); 21341 const to = fromPosition(forward, rootNode, from).map(curry(normalizePosition, forward)); 21342 const location = to.fold(() => fromLocation.map(outside), to => readLocation(isInlineTarget, rootNode, to).map(curry(betweenInlines, forward, isInlineTarget, rootNode, from, to)).filter(curry(skipNoMovement, fromLocation))); 21343 return location.filter(isValidLocation); 21344 }; 21345 const findLocationSimple = (forward, location) => { 21346 if (forward) { 21347 return location.fold(compose(Optional.some, Location.start), Optional.none, compose(Optional.some, Location.after), Optional.none); 21348 } else { 21349 return location.fold(Optional.none, compose(Optional.some, Location.before), Optional.none, compose(Optional.some, Location.end)); 21350 } 21351 }; 21352 const findLocation$1 = (forward, isInlineTarget, rootNode, pos) => { 21353 const from = normalizePosition(forward, pos); 21354 const fromLocation = readLocation(isInlineTarget, rootNode, from); 21355 return readLocation(isInlineTarget, rootNode, from).bind(curry(findLocationSimple, forward)).orThunk(() => findLocationTraverse(forward, isInlineTarget, rootNode, fromLocation, pos)); 21356 }; 21357 21358 const hasSelectionModifyApi = editor => { 21359 return isFunction(editor.selection.getSel().modify); 21360 }; 21361 const moveRel = (forward, selection, pos) => { 21362 const delta = forward ? 1 : -1; 21363 selection.setRng(CaretPosition(pos.container(), pos.offset() + delta).toRange()); 21364 selection.getSel().modify('move', forward ? 'forward' : 'backward', 'word'); 21365 return true; 21366 }; 21367 const moveByWord = (forward, editor) => { 21368 const rng = editor.selection.getRng(); 21369 const pos = forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng); 21370 if (!hasSelectionModifyApi(editor)) { 21371 return false; 21372 } else if (forward && isBeforeInline(pos)) { 21373 return moveRel(true, editor.selection, pos); 21374 } else if (!forward && isAfterInline(pos)) { 21375 return moveRel(false, editor.selection, pos); 21376 } else { 21377 return false; 21378 } 21379 }; 21380 21381 var BreakType; 21382 (function (BreakType) { 21383 BreakType[BreakType['Br'] = 0] = 'Br'; 21384 BreakType[BreakType['Block'] = 1] = 'Block'; 21385 BreakType[BreakType['Wrap'] = 2] = 'Wrap'; 21386 BreakType[BreakType['Eol'] = 3] = 'Eol'; 21387 }(BreakType || (BreakType = {}))); 21388 const flip = (direction, positions) => direction === HDirection.Backwards ? reverse(positions) : positions; 21389 const walk$1 = (direction, caretWalker, pos) => direction === HDirection.Forwards ? caretWalker.next(pos) : caretWalker.prev(pos); 21390 const getBreakType = (scope, direction, currentPos, nextPos) => { 21391 if (isBr$6(nextPos.getNode(direction === HDirection.Forwards))) { 21392 return BreakType.Br; 21393 } else if (isInSameBlock(currentPos, nextPos) === false) { 21394 return BreakType.Block; 21395 } else { 21396 return BreakType.Wrap; 21397 } 21398 }; 21399 const getPositionsUntil = (predicate, direction, scope, start) => { 21400 const caretWalker = CaretWalker(scope); 21401 let currentPos = start; 21402 const positions = []; 21403 while (currentPos) { 21404 const nextPos = walk$1(direction, caretWalker, currentPos); 21405 if (!nextPos) { 21406 break; 21407 } 21408 if (isBr$6(nextPos.getNode(false))) { 21409 if (direction === HDirection.Forwards) { 21410 return { 21411 positions: flip(direction, positions).concat([nextPos]), 21412 breakType: BreakType.Br, 21413 breakAt: Optional.some(nextPos) 21414 }; 21415 } else { 21416 return { 21417 positions: flip(direction, positions), 21418 breakType: BreakType.Br, 21419 breakAt: Optional.some(nextPos) 21420 }; 21421 } 21422 } 21423 if (!nextPos.isVisible()) { 21424 currentPos = nextPos; 21425 continue; 21426 } 21427 if (predicate(currentPos, nextPos)) { 21428 const breakType = getBreakType(scope, direction, currentPos, nextPos); 21429 return { 21430 positions: flip(direction, positions), 21431 breakType, 21432 breakAt: Optional.some(nextPos) 21433 }; 21434 } 21435 positions.push(nextPos); 21436 currentPos = nextPos; 21437 } 21438 return { 21439 positions: flip(direction, positions), 21440 breakType: BreakType.Eol, 21441 breakAt: Optional.none() 21442 }; 21443 }; 21444 const getAdjacentLinePositions = (direction, getPositionsUntilBreak, scope, start) => getPositionsUntilBreak(scope, start).breakAt.map(pos => { 21445 const positions = getPositionsUntilBreak(scope, pos).positions; 21446 return direction === HDirection.Backwards ? positions.concat(pos) : [pos].concat(positions); 21447 }).getOr([]); 21448 const findClosestHorizontalPositionFromPoint = (positions, x) => foldl(positions, (acc, newPos) => acc.fold(() => Optional.some(newPos), lastPos => lift2(head(lastPos.getClientRects()), head(newPos.getClientRects()), (lastRect, newRect) => { 21449 const lastDist = Math.abs(x - lastRect.left); 21450 const newDist = Math.abs(x - newRect.left); 21451 return newDist <= lastDist ? newPos : lastPos; 21452 }).or(acc)), Optional.none()); 21453 const findClosestHorizontalPosition = (positions, pos) => head(pos.getClientRects()).bind(targetRect => findClosestHorizontalPositionFromPoint(positions, targetRect.left)); 21454 const getPositionsUntilPreviousLine = curry(getPositionsUntil, CaretPosition.isAbove, -1); 21455 const getPositionsUntilNextLine = curry(getPositionsUntil, CaretPosition.isBelow, 1); 21456 const getPositionsAbove = curry(getAdjacentLinePositions, -1, getPositionsUntilPreviousLine); 21457 const getPositionsBelow = curry(getAdjacentLinePositions, 1, getPositionsUntilNextLine); 21458 const isAtFirstLine = (scope, pos) => getPositionsUntilPreviousLine(scope, pos).breakAt.isNone(); 21459 const isAtLastLine = (scope, pos) => getPositionsUntilNextLine(scope, pos).breakAt.isNone(); 21460 const getFirstLinePositions = scope => firstPositionIn(scope).map(pos => [pos].concat(getPositionsUntilNextLine(scope, pos).positions)).getOr([]); 21461 const getLastLinePositions = scope => lastPositionIn(scope).map(pos => getPositionsUntilPreviousLine(scope, pos).positions.concat(pos)).getOr([]); 21462 const getClosestPositionAbove = (scope, pos) => findClosestHorizontalPosition(getPositionsAbove(scope, pos), pos); 21463 const getClosestPositionBelow = (scope, pos) => findClosestHorizontalPosition(getPositionsBelow(scope, pos), pos); 21464 21465 const isContentEditableFalse$4 = isContentEditableFalse$b; 21466 const distanceToRectLeft$1 = (clientRect, clientX) => Math.abs(clientRect.left - clientX); 21467 const distanceToRectRight$1 = (clientRect, clientX) => Math.abs(clientRect.right - clientX); 21468 const isNodeClientRect = rect => hasNonNullableKey(rect, 'node'); 21469 const findClosestClientRect = (clientRects, clientX) => reduce(clientRects, (oldClientRect, clientRect) => { 21470 const oldDistance = Math.min(distanceToRectLeft$1(oldClientRect, clientX), distanceToRectRight$1(oldClientRect, clientX)); 21471 const newDistance = Math.min(distanceToRectLeft$1(clientRect, clientX), distanceToRectRight$1(clientRect, clientX)); 21472 if (newDistance === oldDistance && isNodeClientRect(clientRect) && isContentEditableFalse$4(clientRect.node)) { 21473 return clientRect; 21474 } 21475 if (newDistance < oldDistance) { 21476 return clientRect; 21477 } 21478 return oldClientRect; 21479 }); 21480 21481 const getNodeClientRects = node => { 21482 const toArrayWithNode = clientRects => { 21483 return map$3(clientRects, rect => { 21484 const clientRect = clone$1(rect); 21485 clientRect.node = node; 21486 return clientRect; 21487 }); 21488 }; 21489 if (isElement$6(node)) { 21490 return toArrayWithNode(node.getClientRects()); 21491 } else if (isText$a(node)) { 21492 const rng = node.ownerDocument.createRange(); 21493 rng.setStart(node, 0); 21494 rng.setEnd(node, node.data.length); 21495 return toArrayWithNode(rng.getClientRects()); 21496 } else { 21497 return []; 21498 } 21499 }; 21500 const getClientRects = nodes => bind$3(nodes, getNodeClientRects); 21501 21502 var VDirection; 21503 (function (VDirection) { 21504 VDirection[VDirection['Up'] = -1] = 'Up'; 21505 VDirection[VDirection['Down'] = 1] = 'Down'; 21506 }(VDirection || (VDirection = {}))); 21507 const findUntil = (direction, root, predicateFn, node) => { 21508 let currentNode = node; 21509 while (currentNode = findNode(currentNode, direction, isEditableCaretCandidate$1, root)) { 21510 if (predicateFn(currentNode)) { 21511 return; 21512 } 21513 } 21514 }; 21515 const walkUntil = (direction, isAboveFn, isBeflowFn, root, predicateFn, caretPosition) => { 21516 let line = 0; 21517 const result = []; 21518 const add = node => { 21519 let clientRects = getClientRects([node]); 21520 if (direction === -1) { 21521 clientRects = clientRects.reverse(); 21522 } 21523 for (let i = 0; i < clientRects.length; i++) { 21524 const clientRect = clientRects[i]; 21525 if (isBeflowFn(clientRect, targetClientRect)) { 21526 continue; 21527 } 21528 if (result.length > 0 && isAboveFn(clientRect, last$2(result))) { 21529 line++; 21530 } 21531 clientRect.line = line; 21532 if (predicateFn(clientRect)) { 21533 return true; 21534 } 21535 result.push(clientRect); 21536 } 21537 return false; 21538 }; 21539 const targetClientRect = last$2(caretPosition.getClientRects()); 21540 if (!targetClientRect) { 21541 return result; 21542 } 21543 const node = caretPosition.getNode(); 21544 if (node) { 21545 add(node); 21546 findUntil(direction, root, add, node); 21547 } 21548 return result; 21549 }; 21550 const aboveLineNumber = (lineNumber, clientRect) => clientRect.line > lineNumber; 21551 const isLineNumber = (lineNumber, clientRect) => clientRect.line === lineNumber; 21552 const upUntil = curry(walkUntil, VDirection.Up, isAbove$1, isBelow$1); 21553 const downUntil = curry(walkUntil, VDirection.Down, isBelow$1, isAbove$1); 21554 const getLastClientRect = caretPosition => { 21555 return last$2(caretPosition.getClientRects()); 21556 }; 21557 const positionsUntil = (direction, root, predicateFn, node) => { 21558 const caretWalker = CaretWalker(root); 21559 let walkFn; 21560 let isBelowFn; 21561 let isAboveFn; 21562 let caretPosition; 21563 const result = []; 21564 let line = 0; 21565 if (direction === 1) { 21566 walkFn = caretWalker.next; 21567 isBelowFn = isBelow$1; 21568 isAboveFn = isAbove$1; 21569 caretPosition = CaretPosition.after(node); 21570 } else { 21571 walkFn = caretWalker.prev; 21572 isBelowFn = isAbove$1; 21573 isAboveFn = isBelow$1; 21574 caretPosition = CaretPosition.before(node); 21575 } 21576 const targetClientRect = getLastClientRect(caretPosition); 21577 do { 21578 if (!caretPosition.isVisible()) { 21579 continue; 21580 } 21581 const rect = getLastClientRect(caretPosition); 21582 if (isAboveFn(rect, targetClientRect)) { 21583 continue; 21584 } 21585 if (result.length > 0 && isBelowFn(rect, last$2(result))) { 21586 line++; 21587 } 21588 const clientRect = clone$1(rect); 21589 clientRect.position = caretPosition; 21590 clientRect.line = line; 21591 if (predicateFn(clientRect)) { 21592 return result; 21593 } 21594 result.push(clientRect); 21595 } while (caretPosition = walkFn(caretPosition)); 21596 return result; 21597 }; 21598 const isAboveLine = lineNumber => clientRect => aboveLineNumber(lineNumber, clientRect); 21599 const isLine = lineNumber => clientRect => isLineNumber(lineNumber, clientRect); 21600 21601 const moveToRange = (editor, rng) => { 21602 editor.selection.setRng(rng); 21603 scrollRangeIntoView(editor, editor.selection.getRng()); 21604 }; 21605 const renderRangeCaretOpt = (editor, range, scrollIntoView) => Optional.some(renderRangeCaret(editor, range, scrollIntoView)); 21606 const moveHorizontally = (editor, direction, range, isBefore, isAfter, isElement) => { 21607 const forwards = direction === HDirection.Forwards; 21608 const caretWalker = CaretWalker(editor.getBody()); 21609 const getNextPosFn = curry(getVisualCaretPosition, forwards ? caretWalker.next : caretWalker.prev); 21610 const isBeforeFn = forwards ? isBefore : isAfter; 21611 if (!range.collapsed) { 21612 const node = getSelectedNode(range); 21613 if (isElement(node)) { 21614 return showCaret(direction, editor, node, direction === HDirection.Backwards, false); 21615 } else if (isCefAtEdgeSelected(editor)) { 21616 const newRange = range.cloneRange(); 21617 newRange.collapse(direction === HDirection.Backwards); 21618 return Optional.from(newRange); 21619 } 21620 } 21621 const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range); 21622 if (isBeforeFn(caretPosition)) { 21623 return selectNode(editor, caretPosition.getNode(!forwards)); 21624 } 21625 let nextCaretPosition = getNextPosFn(caretPosition); 21626 const rangeIsInContainerBlock = isRangeInCaretContainerBlock(range); 21627 if (!nextCaretPosition) { 21628 return rangeIsInContainerBlock ? Optional.some(range) : Optional.none(); 21629 } else { 21630 nextCaretPosition = normalizePosition(forwards, nextCaretPosition); 21631 } 21632 if (isBeforeFn(nextCaretPosition)) { 21633 return showCaret(direction, editor, nextCaretPosition.getNode(!forwards), forwards, false); 21634 } 21635 const peekCaretPosition = getNextPosFn(nextCaretPosition); 21636 if (peekCaretPosition && isBeforeFn(peekCaretPosition)) { 21637 if (isMoveInsideSameBlock(nextCaretPosition, peekCaretPosition)) { 21638 return showCaret(direction, editor, peekCaretPosition.getNode(!forwards), forwards, false); 21639 } 21640 } 21641 if (rangeIsInContainerBlock) { 21642 return renderRangeCaretOpt(editor, nextCaretPosition.toRange(), false); 21643 } 21644 return Optional.none(); 21645 }; 21646 const moveVertically = (editor, direction, range, isBefore, isAfter, isElement) => { 21647 const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range); 21648 const caretClientRect = last$2(caretPosition.getClientRects()); 21649 const forwards = direction === VDirection.Down; 21650 const root = editor.getBody(); 21651 if (!caretClientRect) { 21652 return Optional.none(); 21653 } 21654 if (isCefAtEdgeSelected(editor)) { 21655 const caretPosition = forwards ? CaretPosition.fromRangeEnd(range) : CaretPosition.fromRangeStart(range); 21656 const getClosestFn = !forwards ? getClosestPositionAbove : getClosestPositionBelow; 21657 return getClosestFn(root, caretPosition).orThunk(() => Optional.from(caretPosition)).map(pos => pos.toRange()); 21658 } 21659 const walkerFn = forwards ? downUntil : upUntil; 21660 const linePositions = walkerFn(root, isAboveLine(1), caretPosition); 21661 const nextLinePositions = filter$5(linePositions, isLine(1)); 21662 const clientX = caretClientRect.left; 21663 const nextLineRect = findClosestClientRect(nextLinePositions, clientX); 21664 if (nextLineRect && isElement(nextLineRect.node)) { 21665 const dist1 = Math.abs(clientX - nextLineRect.left); 21666 const dist2 = Math.abs(clientX - nextLineRect.right); 21667 return showCaret(direction, editor, nextLineRect.node, dist1 < dist2, false); 21668 } 21669 let currentNode; 21670 if (isBefore(caretPosition)) { 21671 currentNode = caretPosition.getNode(); 21672 } else if (isAfter(caretPosition)) { 21673 currentNode = caretPosition.getNode(true); 21674 } else { 21675 currentNode = getSelectedNode(range); 21676 } 21677 if (currentNode) { 21678 const caretPositions = positionsUntil(direction, root, isAboveLine(1), currentNode); 21679 let closestNextLineRect = findClosestClientRect(filter$5(caretPositions, isLine(1)), clientX); 21680 if (closestNextLineRect) { 21681 return renderRangeCaretOpt(editor, closestNextLineRect.position.toRange(), false); 21682 } 21683 closestNextLineRect = last$2(filter$5(caretPositions, isLine(0))); 21684 if (closestNextLineRect) { 21685 return renderRangeCaretOpt(editor, closestNextLineRect.position.toRange(), false); 21686 } 21687 } 21688 if (nextLinePositions.length === 0) { 21689 return getLineEndPoint(editor, forwards).filter(forwards ? isAfter : isBefore).map(pos => renderRangeCaret(editor, pos.toRange(), false)); 21690 } 21691 return Optional.none(); 21692 }; 21693 const getLineEndPoint = (editor, forward) => { 21694 const rng = editor.selection.getRng(); 21695 const from = forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng); 21696 const host = getEditingHost(from.container(), editor.getBody()); 21697 if (forward) { 21698 const lineInfo = getPositionsUntilNextLine(host, from); 21699 return last$3(lineInfo.positions); 21700 } else { 21701 const lineInfo = getPositionsUntilPreviousLine(host, from); 21702 return head(lineInfo.positions); 21703 } 21704 }; 21705 const moveToLineEndPoint$3 = (editor, forward, isElementPosition) => getLineEndPoint(editor, forward).filter(isElementPosition).exists(pos => { 21706 editor.selection.setRng(pos.toRange()); 21707 return true; 21708 }); 21709 21710 const setCaretPosition = (editor, pos) => { 21711 const rng = editor.dom.createRng(); 21712 rng.setStart(pos.container(), pos.offset()); 21713 rng.setEnd(pos.container(), pos.offset()); 21714 editor.selection.setRng(rng); 21715 }; 21716 const setSelected = (state, elm) => { 21717 if (state) { 21718 elm.setAttribute('data-mce-selected', 'inline-boundary'); 21719 } else { 21720 elm.removeAttribute('data-mce-selected'); 21721 } 21722 }; 21723 const renderCaretLocation = (editor, caret, location) => renderCaret(caret, location).map(pos => { 21724 setCaretPosition(editor, pos); 21725 return location; 21726 }); 21727 const getPositionFromRange = (range, root, forward) => { 21728 const start = CaretPosition.fromRangeStart(range); 21729 if (range.collapsed) { 21730 return start; 21731 } else { 21732 const end = CaretPosition.fromRangeEnd(range); 21733 return forward ? prevPosition(root, end).getOr(end) : nextPosition(root, start).getOr(start); 21734 } 21735 }; 21736 const findLocation = (editor, caret, forward) => { 21737 const rootNode = editor.getBody(); 21738 const from = getPositionFromRange(editor.selection.getRng(), rootNode, forward); 21739 const isInlineTarget$1 = curry(isInlineTarget, editor); 21740 const location = findLocation$1(forward, isInlineTarget$1, rootNode, from); 21741 return location.bind(location => renderCaretLocation(editor, caret, location)); 21742 }; 21743 const toggleInlines = (isInlineTarget, dom, elms) => { 21744 const inlineBoundaries = map$3(descendants(SugarElement.fromDom(dom.getRoot()), '*[data-mce-selected="inline-boundary"]'), e => e.dom); 21745 const selectedInlines = filter$5(inlineBoundaries, isInlineTarget); 21746 const targetInlines = filter$5(elms, isInlineTarget); 21747 each$e(difference(selectedInlines, targetInlines), curry(setSelected, false)); 21748 each$e(difference(targetInlines, selectedInlines), curry(setSelected, true)); 21749 }; 21750 const safeRemoveCaretContainer = (editor, caret) => { 21751 const caretValue = caret.get(); 21752 if (editor.selection.isCollapsed() && !editor.composing && caretValue) { 21753 const pos = CaretPosition.fromRangeStart(editor.selection.getRng()); 21754 if (CaretPosition.isTextPosition(pos) && !isAtZwsp(pos)) { 21755 setCaretPosition(editor, removeAndReposition(caretValue, pos)); 21756 caret.set(null); 21757 } 21758 } 21759 }; 21760 const renderInsideInlineCaret = (isInlineTarget, editor, caret, elms) => { 21761 if (editor.selection.isCollapsed()) { 21762 const inlines = filter$5(elms, isInlineTarget); 21763 each$e(inlines, _inline => { 21764 const pos = CaretPosition.fromRangeStart(editor.selection.getRng()); 21765 readLocation(isInlineTarget, editor.getBody(), pos).bind(location => renderCaretLocation(editor, caret, location)); 21766 }); 21767 } 21768 }; 21769 const move$2 = (editor, caret, forward) => isInlineBoundariesEnabled(editor) ? findLocation(editor, caret, forward).isSome() : false; 21770 const moveWord = (forward, editor, _caret) => isInlineBoundariesEnabled(editor) ? moveByWord(forward, editor) : false; 21771 const setupSelectedState = editor => { 21772 const caret = Cell(null); 21773 const isInlineTarget$1 = curry(isInlineTarget, editor); 21774 editor.on('NodeChange', e => { 21775 if (isInlineBoundariesEnabled(editor)) { 21776 toggleInlines(isInlineTarget$1, editor.dom, e.parents); 21777 safeRemoveCaretContainer(editor, caret); 21778 renderInsideInlineCaret(isInlineTarget$1, editor, caret, e.parents); 21779 } 21780 }); 21781 return caret; 21782 }; 21783 const moveNextWord = curry(moveWord, true); 21784 const movePrevWord = curry(moveWord, false); 21785 const moveToLineEndPoint$2 = (editor, forward, caret) => { 21786 if (isInlineBoundariesEnabled(editor)) { 21787 const linePoint = getLineEndPoint(editor, forward).getOrThunk(() => { 21788 const rng = editor.selection.getRng(); 21789 return forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng); 21790 }); 21791 return readLocation(curry(isInlineTarget, editor), editor.getBody(), linePoint).exists(loc => { 21792 const outsideLoc = outside(loc); 21793 return renderCaret(caret, outsideLoc).exists(pos => { 21794 setCaretPosition(editor, pos); 21795 return true; 21796 }); 21797 }); 21798 } else { 21799 return false; 21800 } 21801 }; 21802 21803 const rangeFromPositions = (from, to) => { 21804 const range = document.createRange(); 21805 range.setStart(from.container(), from.offset()); 21806 range.setEnd(to.container(), to.offset()); 21807 return range; 21808 }; 21809 const hasOnlyTwoOrLessPositionsLeft = elm => lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => { 21810 const normalizedFirstPos = normalizePosition(true, firstPos); 21811 const normalizedLastPos = normalizePosition(false, lastPos); 21812 return nextPosition(elm, normalizedFirstPos).forall(pos => pos.isEqual(normalizedLastPos)); 21813 }).getOr(true); 21814 const setCaretLocation = (editor, caret) => location => renderCaret(caret, location).map(pos => () => setCaretPosition(editor, pos)); 21815 const deleteFromTo = (editor, caret, from, to) => { 21816 const rootNode = editor.getBody(); 21817 const isInlineTarget$1 = curry(isInlineTarget, editor); 21818 editor.undoManager.ignore(() => { 21819 editor.selection.setRng(rangeFromPositions(from, to)); 21820 execNativeDeleteCommand(editor); 21821 readLocation(isInlineTarget$1, rootNode, CaretPosition.fromRangeStart(editor.selection.getRng())).map(inside).bind(setCaretLocation(editor, caret)).each(call); 21822 }); 21823 editor.nodeChanged(); 21824 }; 21825 const rescope = (rootNode, node) => { 21826 const parentBlock = getParentBlock$3(node, rootNode); 21827 return parentBlock ? parentBlock : rootNode; 21828 }; 21829 const backspaceDeleteCollapsed = (editor, caret, forward, from) => { 21830 const rootNode = rescope(editor.getBody(), from.container()); 21831 const isInlineTarget$1 = curry(isInlineTarget, editor); 21832 const fromLocation = readLocation(isInlineTarget$1, rootNode, from); 21833 const location = fromLocation.bind(location => { 21834 if (forward) { 21835 return location.fold(constant(Optional.some(inside(location))), Optional.none, constant(Optional.some(outside(location))), Optional.none); 21836 } else { 21837 return location.fold(Optional.none, constant(Optional.some(outside(location))), Optional.none, constant(Optional.some(inside(location)))); 21838 } 21839 }); 21840 return location.map(setCaretLocation(editor, caret)).getOrThunk(() => { 21841 const toPosition = navigate(forward, rootNode, from); 21842 const toLocation = toPosition.bind(pos => readLocation(isInlineTarget$1, rootNode, pos)); 21843 return lift2(fromLocation, toLocation, () => findRootInline(isInlineTarget$1, rootNode, from).bind(elm => { 21844 if (hasOnlyTwoOrLessPositionsLeft(elm)) { 21845 return Optional.some(() => { 21846 deleteElement$2(editor, forward, SugarElement.fromDom(elm)); 21847 }); 21848 } else { 21849 return Optional.none(); 21850 } 21851 })).getOrThunk(() => toLocation.bind(() => toPosition.map(to => { 21852 return () => { 21853 if (forward) { 21854 deleteFromTo(editor, caret, from, to); 21855 } else { 21856 deleteFromTo(editor, caret, to, from); 21857 } 21858 }; 21859 }))); 21860 }); 21861 }; 21862 const backspaceDelete$3 = (editor, caret, forward) => { 21863 if (editor.selection.isCollapsed() && isInlineBoundariesEnabled(editor)) { 21864 const from = CaretPosition.fromRangeStart(editor.selection.getRng()); 21865 return backspaceDeleteCollapsed(editor, caret, forward, from); 21866 } 21867 return Optional.none(); 21868 }; 21869 21870 const hasMultipleChildren = elm => childNodesCount(elm) > 1; 21871 const getParentsUntil = (editor, pred) => { 21872 const rootElm = SugarElement.fromDom(editor.getBody()); 21873 const startElm = SugarElement.fromDom(editor.selection.getStart()); 21874 const parents = parentsAndSelf(startElm, rootElm); 21875 return findIndex$2(parents, pred).fold(constant(parents), index => parents.slice(0, index)); 21876 }; 21877 const
vendor: 948 bytes, lines 21877-21895
21877getParentInlinesUntilMultichildInline = editor => getParentsUntil(editor, elm => isBlock$2(elm) || hasMultipleChildren(elm)); 21878 const getParentInlines = editor => getParentsUntil(editor, isBlock$2); 21879 const getFormatNodes = (editor, parentInlines) => { 21880 const isFormatElement$1 = curry(isFormatElement, editor); 21881 return bind$3(parentInlines, elm => isFormatElement$1(elm) ? [elm.dom] : []); 21882 }; 21883 const getFormatNodesAtStart = editor => { 21884 const parentInlines = getParentInlines(editor); 21885 return getFormatNodes(editor, parentInlines); 21886 }; 21887 const deleteLastPosition = (forward, editor, target, parentInlines) => { 21888 const formatNodes = getFormatNodes(editor, parentInlines); 21889 if (formatNodes.length === 0) { 21890 deleteElement$2(editor, forward, target); 21891 } else { 21892 const pos = replaceWithCaretFormat(target.dom, formatNodes); 21893 editor.selection.setRng(pos.toRange()); 21894 } 21895 };
vendor: 1,095 bytes, lines 21896-21914
21896 const deleteCaret$1 = (editor, forward) => { 21897 const parentInlines = getParentInlinesUntilMultichildInline(editor); 21898 return last$3(parentInlines).bind(target => { 21899 const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng()); 21900 if (willDeleteLastPositionInElement(forward, fromPos, target.dom) && !isEmptyCaretFormatElement(target)) { 21901 return Optional.some(() => deleteLastPosition(forward, editor, target, parentInlines)); 21902 } else { 21903 return Optional.none(); 21904 } 21905 }); 21906 }; 21907 const isBrInEmptyElement = (editor, elm) => { 21908 const parentElm = elm.parentElement; 21909 return isBr$6(elm) && !isNull(parentElm) && editor.dom.isEmpty(parentElm); 21910 }; 21911 const isEmptyCaret = elm => isEmptyCaretFormatElement(SugarElement.fromDom(elm)); 21912 const createCaretFormatAtStart = (editor, formatNodes) => { 21913 const startElm = editor.selection.getStart(); 21914 const pos = isBrInEmptyElement(editor, startElm) || isEmptyCaret(startElm) ? replaceWithCaretFormat(startElm, formatNodes) : createCaretFormatAtStart$1(editor
vendor: 20,410 bytes, lines 21914-22393
21914, formatNodes); 21915 editor.selection.setRng(pos.toRange()); 21916 }; 21917 const updateCaretFormat = (editor, updateFormats) => { 21918 const missingFormats = difference(updateFormats, getFormatNodesAtStart(editor)); 21919 if (missingFormats.length > 0) { 21920 createCaretFormatAtStart(editor, missingFormats); 21921 } 21922 }; 21923 const rangeStartsAtTextContainer = rng => isText$a(rng.startContainer); 21924 const rangeStartsAtStartOfTextContainer = rng => rng.startOffset === 0 && rangeStartsAtTextContainer(rng); 21925 const rangeStartParentIsFormatElement = (editor, rng) => { 21926 const startParent = rng.startContainer.parentElement; 21927 return !isNull(startParent) && isFormatElement(editor, SugarElement.fromDom(startParent)); 21928 }; 21929 const rangeStartAndEndHaveSameParent = rng => { 21930 const startParent = rng.startContainer.parentNode; 21931 const endParent = rng.endContainer.parentNode; 21932 return !isNull(startParent) && !isNull(endParent) && startParent.isEqualNode(endParent); 21933 }; 21934 const rangeEndsAtEndOfEndContainer = rng => { 21935 const endContainer = rng.endContainer; 21936 return rng.endOffset === (isText$a(endContainer) ? endContainer.length : endContainer.childNodes.length); 21937 }; 21938 const rangeEndsAtEndOfStartContainer = rng => rangeStartAndEndHaveSameParent(rng) && rangeEndsAtEndOfEndContainer(rng); 21939 const rangeEndsAfterEndOfStartContainer = rng => !rng.endContainer.isEqualNode(rng.commonAncestorContainer); 21940 const rangeEndsAtOrAfterEndOfStartContainer = rng => rangeEndsAtEndOfStartContainer(rng) || rangeEndsAfterEndOfStartContainer(rng); 21941 const requiresDeleteRangeOverride = editor => { 21942 const rng = editor.selection.getRng(); 21943 return rangeStartsAtStartOfTextContainer(rng) && rangeStartParentIsFormatElement(editor, rng) && rangeEndsAtOrAfterEndOfStartContainer(rng); 21944 }; 21945 const deleteRange$1 = editor => { 21946 if (requiresDeleteRangeOverride(editor)) { 21947 const formatNodes = getFormatNodesAtStart(editor); 21948 return Optional.some(() => { 21949 execNativeDeleteCommand(editor); 21950 updateCaretFormat(editor, formatNodes); 21951 }); 21952 } else { 21953 return Optional.none(); 21954 } 21955 }; 21956 const backspaceDelete$2 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret$1(editor, forward) : deleteRange$1(editor); 21957 const hasAncestorInlineCaret = elm => ancestor$1(elm, node => isCaretNode(node.dom), isBlock$2); 21958 const hasAncestorInlineCaretAtStart = editor => hasAncestorInlineCaret(SugarElement.fromDom(editor.selection.getStart())); 21959 const requiresRefreshCaretOverride = editor => { 21960 const rng = editor.selection.getRng(); 21961 return rng.collapsed && (rangeStartsAtTextContainer(rng) || editor.dom.isEmpty(rng.startContainer)) && !hasAncestorInlineCaretAtStart(editor); 21962 }; 21963 const refreshCaret = editor => { 21964 if (requiresRefreshCaretOverride(editor)) { 21965 createCaretFormatAtStart(editor, []); 21966 } 21967 return true; 21968 }; 21969 21970 const deleteElement = (editor, forward, element) => { 21971 if (isNonNullable(element)) { 21972 return Optional.some(() => { 21973 editor._selectionOverrides.hideFakeCaret(); 21974 deleteElement$2(editor, forward, SugarElement.fromDom(element)); 21975 }); 21976 } else { 21977 return Optional.none(); 21978 } 21979 }; 21980 const deleteCaret = (editor, forward) => { 21981 const isNearMedia = forward ? isBeforeMedia : isAfterMedia; 21982 const direction = forward ? HDirection.Forwards : HDirection.Backwards; 21983 const fromPos = getNormalizedRangeEndPoint(direction, editor.getBody(), editor.selection.getRng()); 21984 if (isNearMedia(fromPos)) { 21985 return deleteElement(editor, forward, fromPos.getNode(!forward)); 21986 } else { 21987 return Optional.from(normalizePosition(forward, fromPos)).filter(pos => isNearMedia(pos) && isMoveInsideSameBlock(fromPos, pos)).bind(pos => deleteElement(editor, forward, pos.getNode(!forward))); 21988 } 21989 }; 21990 const deleteRange = (editor, forward) => { 21991 const selectedNode = editor.selection.getNode(); 21992 return isMedia$2(selectedNode) ? deleteElement(editor, forward, selectedNode) : Optional.none(); 21993 }; 21994 const backspaceDelete$1 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret(editor, forward) : deleteRange(editor, forward); 21995 21996 const isEditable = target => closest$4(target, elm => isContentEditableTrue$3(elm.dom) || isContentEditableFalse$b(elm.dom)).exists(elm => isContentEditableTrue$3(elm.dom)); 21997 const parseIndentValue = value => toInt(value !== null && value !== void 0 ? value : '').getOr(0); 21998 const getIndentStyleName = (useMargin, element) => { 21999 const indentStyleName = useMargin || isTable$1(element) ? 'margin' : 'padding'; 22000 const suffix = get$7(element, 'direction') === 'rtl' ? '-right' : '-left'; 22001 return indentStyleName + suffix; 22002 }; 22003 const indentElement = (dom, command, useMargin, value, unit, element) => { 22004 const indentStyleName = getIndentStyleName(useMargin, SugarElement.fromDom(element)); 22005 const parsedValue = parseIndentValue(dom.getStyle(element, indentStyleName)); 22006 if (command === 'outdent') { 22007 const styleValue = Math.max(0, parsedValue - value); 22008 dom.setStyle(element, indentStyleName, styleValue ? styleValue + unit : ''); 22009 } else { 22010 const styleValue = parsedValue + value + unit; 22011 dom.setStyle(element, indentStyleName, styleValue); 22012 } 22013 }; 22014 const validateBlocks = (editor, blocks) => forall(blocks, block => { 22015 const indentStyleName = getIndentStyleName(shouldIndentUseMargin(editor), block); 22016 const intentValue = getRaw(block, indentStyleName).map(parseIndentValue).getOr(0); 22017 const contentEditable = editor.dom.getContentEditable(block.dom); 22018 return contentEditable !== 'false' && intentValue > 0; 22019 }); 22020 const canOutdent = editor => { 22021 const blocks = getBlocksToIndent(editor); 22022 return !editor.mode.isReadOnly() && (blocks.length > 1 || validateBlocks(editor, blocks)); 22023 }; 22024 const isListComponent = el => isList(el) || isListItem$1(el); 22025 const parentIsListComponent = el => parent(el).exists(isListComponent); 22026 const getBlocksToIndent = editor => filter$5(fromDom$1(editor.selection.getSelectedBlocks()), el => !isListComponent(el) && !parentIsListComponent(el) && isEditable(el)); 22027 const handle = (editor, command) => { 22028 var _a, _b; 22029 const {dom} = editor; 22030 const indentation = getIndentation(editor); 22031 const indentUnit = (_b = (_a = /[a-z%]+$/i.exec(indentation)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : 'px'; 22032 const indentValue = parseIndentValue(indentation); 22033 const useMargin = shouldIndentUseMargin(editor); 22034 each$e(getBlocksToIndent(editor), block => { 22035 indentElement(dom, command, useMargin, indentValue, indentUnit, block.dom); 22036 }); 22037 }; 22038 const indent = editor => handle(editor, 'indent'); 22039 const outdent = editor => handle(editor, 'outdent'); 22040 22041 const backspaceDelete = editor => { 22042 if (editor.selection.isCollapsed() && canOutdent(editor)) { 22043 const dom = editor.dom; 22044 const rng = editor.selection.getRng(); 22045 const pos = CaretPosition.fromRangeStart(rng); 22046 const block = dom.getParent(rng.startContainer, dom.isBlock); 22047 if (block !== null && isAtStartOfBlock(SugarElement.fromDom(block), pos)) { 22048 return Optional.some(() => outdent(editor)); 22049 } 22050 } 22051 return Optional.none(); 22052 }; 22053 22054 const findAction = (editor, caret, forward) => findMap([ 22055 backspaceDelete, 22056 backspaceDelete$5, 22057 backspaceDelete$6, 22058 (editor, forward) => backspaceDelete$3(editor, caret, forward), 22059 backspaceDelete$8, 22060 backspaceDelete$9, 22061 backspaceDelete$4, 22062 backspaceDelete$1, 22063 backspaceDelete$7, 22064 backspaceDelete$2 22065 ], item => item(editor, forward)).filter(_ => editor.selection.isEditable()); 22066 const deleteCommand = (editor, caret) => { 22067 const result = findAction(editor, caret, false); 22068 result.fold(() => { 22069 execNativeDeleteCommand(editor); 22070 paddEmptyBody(editor); 22071 }, call); 22072 }; 22073 const forwardDeleteCommand = (editor, caret) => { 22074 const result = findAction(editor, caret, true); 22075 result.fold(() => execNativeForwardDeleteCommand(editor), call); 22076 }; 22077 const setup$p = (editor, caret) => { 22078 editor.addCommand('delete', () => { 22079 deleteCommand(editor, caret); 22080 }); 22081 editor.addCommand('forwardDelete', () => { 22082 forwardDeleteCommand(editor, caret); 22083 }); 22084 }; 22085 22086 const SIGNIFICANT_MOVE = 5; 22087 const LONGPRESS_DELAY = 400; 22088 const getTouch = event => { 22089 if (event.touches === undefined || event.touches.length !== 1) { 22090 return Optional.none(); 22091 } 22092 return Optional.some(event.touches[0]); 22093 }; 22094 const isFarEnough = (touch, data) => { 22095 const distX = Math.abs(touch.clientX - data.x); 22096 const distY = Math.abs(touch.clientY - data.y); 22097 return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE; 22098 }; 22099 const setup$o = editor => { 22100 const startData = value$2(); 22101 const longpressFired = Cell(false); 22102 const debounceLongpress = last$1(e => { 22103 editor.dispatch('longpress', { 22104 ...e, 22105 type: 'longpress' 22106 }); 22107 longpressFired.set(true); 22108 }, LONGPRESS_DELAY); 22109 editor.on('touchstart', e => { 22110 getTouch(e).each(touch => { 22111 debounceLongpress.cancel(); 22112 const data = { 22113 x: touch.clientX, 22114 y: touch.clientY, 22115 target: e.target 22116 }; 22117 debounceLongpress.throttle(e); 22118 longpressFired.set(false); 22119 startData.set(data); 22120 }); 22121 }, true); 22122 editor.on('touchmove', e => { 22123 debounceLongpress.cancel(); 22124 getTouch(e).each(touch => { 22125 startData.on(data => { 22126 if (isFarEnough(touch, data)) { 22127 startData.clear(); 22128 longpressFired.set(false); 22129 editor.dispatch('longpresscancel'); 22130 } 22131 }); 22132 }); 22133 }, true); 22134 editor.on('touchend touchcancel', e => { 22135 debounceLongpress.cancel(); 22136 if (e.type === 'touchcancel') { 22137 return; 22138 } 22139 startData.get().filter(data => data.target.isEqualNode(e.target)).each(() => { 22140 if (longpressFired.get()) { 22141 e.preventDefault(); 22142 } else { 22143 editor.dispatch('tap', { 22144 ...e, 22145 type: 'tap' 22146 }); 22147 } 22148 }); 22149 }, true); 22150 }; 22151 22152 const isBlockElement = (blockElements, node) => has$2(blockElements, node.nodeName); 22153 const isValidTarget = (schema, node) => { 22154 if (isText$a(node)) { 22155 return true; 22156 } else if (isElement$6(node)) { 22157 return !isBlockElement(schema.getBlockElements(), node) && !isBookmarkNode$1(node) && !isTransparentBlock(schema, node); 22158 } else { 22159 return false; 22160 } 22161 }; 22162 const hasBlockParent = (blockElements, root, node) => { 22163 return exists(parents(SugarElement.fromDom(node), SugarElement.fromDom(root)), elm => { 22164 return isBlockElement(blockElements, elm.dom); 22165 }); 22166 }; 22167 const shouldRemoveTextNode = (blockElements, node) => { 22168 if (isText$a(node)) { 22169 if (node.data.length === 0) { 22170 return true; 22171 } else if (/^\s+$/.test(node.data) && (!node.nextSibling || isBlockElement(blockElements, node.nextSibling))) { 22172 return true; 22173 } 22174 } 22175 return false; 22176 }; 22177 const createRootBlock = editor => editor.dom.create(getForcedRootBlock(editor), getForcedRootBlockAttrs(editor)); 22178 const addRootBlocks = editor => { 22179 const dom = editor.dom, selection = editor.selection; 22180 const schema = editor.schema; 22181 const blockElements = schema.getBlockElements(); 22182 const startNode = selection.getStart(); 22183 const rootNode = editor.getBody(); 22184 let rootBlockNode; 22185 let tempNode; 22186 let wrapped = false; 22187 const forcedRootBlock = getForcedRootBlock(editor); 22188 if (!startNode || !isElement$6(startNode)) { 22189 return; 22190 } 22191 const rootNodeName = rootNode.nodeName.toLowerCase(); 22192 if (!schema.isValidChild(rootNodeName, forcedRootBlock.toLowerCase()) || hasBlockParent(blockElements, rootNode, startNode)) { 22193 return; 22194 } 22195 const rng = selection.getRng(); 22196 const {startContainer, startOffset, endContainer, endOffset} = rng; 22197 const restoreSelection = hasFocus(editor); 22198 let node = rootNode.firstChild; 22199 while (node) { 22200 if (isElement$6(node)) { 22201 updateElement(schema, node); 22202 } 22203 if (isValidTarget(schema, node)) { 22204 if (shouldRemoveTextNode(blockElements, node)) { 22205 tempNode = node; 22206 node = node.nextSibling; 22207 dom.remove(tempNode); 22208 continue; 22209 } 22210 if (!rootBlockNode) { 22211 rootBlockNode = createRootBlock(editor); 22212 rootNode.insertBefore(rootBlockNode, node); 22213 wrapped = true; 22214 } 22215 tempNode = node; 22216 node = node.nextSibling; 22217 rootBlockNode.appendChild(tempNode); 22218 } else { 22219 rootBlockNode = null; 22220 node = node.nextSibling; 22221 } 22222 } 22223 if (wrapped && restoreSelection) { 22224 rng.setStart(startContainer, startOffset); 22225 rng.setEnd(endContainer, endOffset); 22226 selection.setRng(rng); 22227 editor.nodeChanged(); 22228 } 22229 }; 22230 const insertEmptyLine = (editor, root, insertBlock) => { 22231 const block = SugarElement.fromDom(createRootBlock(editor)); 22232 const br = createPaddingBr(); 22233 append$1(block, br); 22234 insertBlock(root, block); 22235 const rng = document.createRange(); 22236 rng.setStartBefore(br.dom); 22237 rng.setEndBefore(br.dom); 22238 return rng; 22239 }; 22240 const setup$n = editor => { 22241 editor.on('NodeChange', curry(addRootBlocks, editor)); 22242 }; 22243 22244 const hasClass = checkClassName => node => (' ' + node.attr('class') + ' ').indexOf(checkClassName) !== -1; 22245 const replaceMatchWithSpan = (editor, content, cls) => { 22246 return function (match) { 22247 const args = arguments, index = args[args.length - 2]; 22248 const prevChar = index > 0 ? content.charAt(index - 1) : ''; 22249 if (prevChar === '"') { 22250 return match; 22251 } 22252 if (prevChar === '>') { 22253 const findStartTagIndex = content.lastIndexOf('<', index); 22254 if (findStartTagIndex !== -1) { 22255 const tagHtml = content.substring(findStartTagIndex, index); 22256 if (tagHtml.indexOf('contenteditable="false"') !== -1) { 22257 return match; 22258 } 22259 } 22260 } 22261 return '<span class="' + cls + '" data-mce-content="' + editor.dom.encode(args[0]) + '">' + editor.dom.encode(typeof args[1] === 'string' ? args[1] : args[0]) + '</span>'; 22262 }; 22263 }; 22264 const convertRegExpsToNonEditable = (editor, nonEditableRegExps, e) => { 22265 let i = nonEditableRegExps.length, content = e.content; 22266 if (e.format === 'raw') { 22267 return; 22268 } 22269 while (i--) { 22270 content = content.replace(nonEditableRegExps[i], replaceMatchWithSpan(editor, content, getNonEditableClass(editor))); 22271 } 22272 e.content = content; 22273 }; 22274 const setup$m = editor => { 22275 const contentEditableAttrName = 'contenteditable'; 22276 const editClass = ' ' + Tools.trim(getEditableClass(editor)) + ' '; 22277 const nonEditClass = ' ' + Tools.trim(getNonEditableClass(editor)) + ' '; 22278 const hasEditClass = hasClass(editClass); 22279 const hasNonEditClass = hasClass(nonEditClass); 22280 const nonEditableRegExps = getNonEditableRegExps(editor); 22281 if (nonEditableRegExps.length > 0) { 22282 editor.on('BeforeSetContent', e => { 22283 convertRegExpsToNonEditable(editor, nonEditableRegExps, e); 22284 }); 22285 } 22286 editor.parser.addAttributeFilter('class', nodes => { 22287 let i = nodes.length; 22288 while (i--) { 22289 const node = nodes[i]; 22290 if (hasEditClass(node)) { 22291 node.attr(contentEditableAttrName, 'true'); 22292 } else if (hasNonEditClass(node)) { 22293 node.attr(contentEditableAttrName, 'false'); 22294 } 22295 } 22296 }); 22297 editor.serializer.addAttributeFilter(contentEditableAttrName, nodes => { 22298 let i = nodes.length; 22299 while (i--) { 22300 const node = nodes[i]; 22301 if (!hasEditClass(node) && !hasNonEditClass(node)) { 22302 continue; 22303 } 22304 if (nonEditableRegExps.length > 0 && node.attr('data-mce-content')) { 22305 node.name = '#text'; 22306 node.type = 3; 22307 node.raw = true; 22308 node.value = node.attr('data-mce-content'); 22309 } else { 22310 node.attr(contentEditableAttrName, null); 22311 } 22312 } 22313 }); 22314 }; 22315 22316 const findBlockCaretContainer = editor => descendant(SugarElement.fromDom(editor.getBody()), '*[data-mce-caret]').map(elm => elm.dom).getOrNull(); 22317 const showBlockCaretContainer = (editor, blockCaretContainer) => { 22318 if (blockCaretContainer.hasAttribute('data-mce-caret')) { 22319 showCaretContainerBlock(blockCaretContainer); 22320 editor.selection.setRng(editor.selection.getRng()); 22321 editor.selection.scrollIntoView(blockCaretContainer); 22322 } 22323 }; 22324 const handleBlockContainer = (editor, e) => { 22325 const blockCaretContainer = findBlockCaretContainer(editor); 22326 if (!blockCaretContainer) { 22327 return; 22328 } 22329 if (e.type === 'compositionstart') { 22330 e.preventDefault(); 22331 e.stopPropagation(); 22332 showBlockCaretContainer(editor, blockCaretContainer); 22333 return; 22334 } 22335 if (hasContent(blockCaretContainer)) { 22336 showBlockCaretContainer(editor, blockCaretContainer); 22337 editor.undoManager.add(); 22338 } 22339 }; 22340 const setup$l = editor => { 22341 editor.on('keyup compositionstart', curry(handleBlockContainer, editor)); 22342 }; 22343 22344 const isContentEditableFalse$3 = isContentEditableFalse$b; 22345 const moveToCeFalseHorizontally = (direction, editor, range) => moveHorizontally(editor, direction, range, isBeforeContentEditableFalse, isAfterContentEditableFalse, isContentEditableFalse$3); 22346 const moveToCeFalseVertically = (direction, editor, range) => { 22347 const isBefore = caretPosition => isBeforeContentEditableFalse(caretPosition) || isBeforeTable(caretPosition); 22348 const isAfter = caretPosition => isAfterContentEditableFalse(caretPosition) || isAfterTable(caretPosition); 22349 return moveVertically(editor, direction, range, isBefore, isAfter, isContentEditableFalse$3); 22350 }; 22351 const createTextBlock = editor => { 22352 const textBlock = editor.dom.create(getForcedRootBlock(editor)); 22353 textBlock.innerHTML = '<br data-mce-bogus="1">'; 22354 return textBlock; 22355 }; 22356 const exitPreBlock = (editor, direction, range) => { 22357 const caretWalker = CaretWalker(editor.getBody()); 22358 const getVisualCaretPosition$1 = curry(getVisualCaretPosition, direction === 1 ? caretWalker.next : caretWalker.prev); 22359 if (range.collapsed) { 22360 const pre = editor.dom.getParent(range.startContainer, 'PRE'); 22361 if (!pre) { 22362 return; 22363 } 22364 const caretPos = getVisualCaretPosition$1(CaretPosition.fromRangeStart(range)); 22365 if (!caretPos) { 22366 const newBlock = SugarElement.fromDom(createTextBlock(editor)); 22367 if (direction === 1) { 22368 after$4(SugarElement.fromDom(pre), newBlock); 22369 } else { 22370 before$3(SugarElement.fromDom(pre), newBlock); 22371 } 22372 editor.selection.select(newBlock.dom, true); 22373 editor.selection.collapse(); 22374 } 22375 } 22376 }; 22377 const getHorizontalRange = (editor, forward) => { 22378 const direction = forward ? HDirection.Forwards : HDirection.Backwards; 22379 const range = editor.selection.getRng(); 22380 return moveToCeFalseHorizontally(direction, editor, range).orThunk(() => { 22381 exitPreBlock(editor, direction, range); 22382 return Optional.none(); 22383 }); 22384 }; 22385 const getVerticalRange = (editor, down) => { 22386 const direction = down ? 1 : -1; 22387 const range = editor.selection.getRng(); 22388 return moveToCeFalseVertically(direction, editor, range).orThunk(() => { 22389 exitPreBlock(editor, direction, range); 22390 return Optional.none(); 22391 }); 22392 }; 22393 const
22393moveH$2 = (editor, forward) => getHorizontalRange(editor, forward
vendor: 43,962 bytes, lines 22393-23541
22393).exists(newRange => { 22394 moveToRange(editor, newRange); 22395 return true; 22396 }); 22397 const moveV$3 = (editor, down) => getVerticalRange(editor, down).exists(newRange => { 22398 moveToRange(editor, newRange); 22399 return true; 22400 }); 22401 const moveToLineEndPoint$1 = (editor, forward) => { 22402 const isCefPosition = forward ? isAfterContentEditableFalse : isBeforeContentEditableFalse; 22403 return moveToLineEndPoint$3(editor, forward, isCefPosition); 22404 }; 22405 const selectToEndPoint = (editor, forward) => getEdgeCefPosition(editor, !forward).map(pos => { 22406 const rng = pos.toRange(); 22407 const curRng = editor.selection.getRng(); 22408 if (forward) { 22409 rng.setStart(curRng.startContainer, curRng.startOffset); 22410 } else { 22411 rng.setEnd(curRng.endContainer, curRng.endOffset); 22412 } 22413 return rng; 22414 }).exists(rng => { 22415 moveToRange(editor, rng); 22416 return true; 22417 }); 22418 22419 const isTarget = node => contains$2(['figcaption'], name(node)); 22420 const getClosestTargetBlock = (pos, root) => { 22421 const isRoot = curry(eq, root); 22422 return closest$4(SugarElement.fromDom(pos.container()), isBlock$2, isRoot).filter(isTarget); 22423 }; 22424 const isAtFirstOrLastLine = (root, forward, pos) => forward ? isAtLastLine(root.dom, pos) : isAtFirstLine(root.dom, pos); 22425 const moveCaretToNewEmptyLine = (editor, forward) => { 22426 const root = SugarElement.fromDom(editor.getBody()); 22427 const pos = CaretPosition.fromRangeStart(editor.selection.getRng()); 22428 return getClosestTargetBlock(pos, root).exists(() => { 22429 if (isAtFirstOrLastLine(root, forward, pos)) { 22430 const insertFn = forward ? append$1 : prepend; 22431 const rng = insertEmptyLine(editor, root, insertFn); 22432 editor.selection.setRng(rng); 22433 return true; 22434 } else { 22435 return false; 22436 } 22437 }); 22438 }; 22439 const moveV$2 = (editor, forward) => { 22440 if (editor.selection.isCollapsed()) { 22441 return moveCaretToNewEmptyLine(editor, forward); 22442 } else { 22443 return false; 22444 } 22445 }; 22446 22447 const baseKeyPattern = { 22448 shiftKey: false, 22449 altKey: false, 22450 ctrlKey: false, 22451 metaKey: false, 22452 keyCode: 0 22453 }; 22454 const defaultPatterns = patterns => map$3(patterns, pattern => ({ 22455 ...baseKeyPattern, 22456 ...pattern 22457 })); 22458 const defaultDelayedPatterns = patterns => map$3(patterns, pattern => ({ 22459 ...baseKeyPattern, 22460 ...pattern 22461 })); 22462 const matchesEvent = (pattern, evt) => evt.keyCode === pattern.keyCode && evt.shiftKey === pattern.shiftKey && evt.altKey === pattern.altKey && evt.ctrlKey === pattern.ctrlKey && evt.metaKey === pattern.metaKey; 22463 const match$1 = (patterns, evt) => bind$3(defaultPatterns(patterns), pattern => matchesEvent(pattern, evt) ? [pattern] : []); 22464 const matchDelayed = (patterns, evt) => bind$3(defaultDelayedPatterns(patterns), pattern => matchesEvent(pattern, evt) ? [pattern] : []); 22465 const action = (f, ...x) => () => f.apply(null, x); 22466 const execute = (patterns, evt) => find$2(match$1(patterns, evt), pattern => pattern.action()); 22467 const executeWithDelayedAction = (patterns, evt) => findMap(matchDelayed(patterns, evt), pattern => pattern.action()); 22468 22469 const moveH$1 = (editor, forward) => { 22470 const direction = forward ? HDirection.Forwards : HDirection.Backwards; 22471 const range = editor.selection.getRng(); 22472 return moveHorizontally(editor, direction, range, isBeforeMedia, isAfterMedia, isMedia$2).exists(newRange => { 22473 moveToRange(editor, newRange); 22474 return true; 22475 }); 22476 }; 22477 const moveV$1 = (editor, down) => { 22478 const direction = down ? 1 : -1; 22479 const range = editor.selection.getRng(); 22480 return moveVertically(editor, direction, range, isBeforeMedia, isAfterMedia, isMedia$2).exists(newRange => { 22481 moveToRange(editor, newRange); 22482 return true; 22483 }); 22484 }; 22485 const moveToLineEndPoint = (editor, forward) => { 22486 const isNearMedia = forward ? isAfterMedia : isBeforeMedia; 22487 return moveToLineEndPoint$3(editor, forward, isNearMedia); 22488 }; 22489 22490 const adt = Adt.generate([ 22491 { none: ['current'] }, 22492 { first: ['current'] }, 22493 { 22494 middle: [ 22495 'current', 22496 'target' 22497 ] 22498 }, 22499 { last: ['current'] } 22500 ]); 22501 const none = current => adt.none(current); 22502 const CellLocation = { 22503 ...adt, 22504 none 22505 }; 22506 22507 const firstLayer = (scope, selector) => { 22508 return filterFirstLayer(scope, selector, always); 22509 }; 22510 const filterFirstLayer = (scope, selector, predicate) => { 22511 return bind$3(children$1(scope), x => { 22512 if (is$1(x, selector)) { 22513 return predicate(x) ? [x] : []; 22514 } else { 22515 return filterFirstLayer(x, selector, predicate); 22516 } 22517 }); 22518 }; 22519 22520 const lookup$1 = (tags, element, isRoot = never) => { 22521 if (isRoot(element)) { 22522 return Optional.none(); 22523 } 22524 if (contains$2(tags, name(element))) { 22525 return Optional.some(element); 22526 } 22527 const isRootOrUpperTable = elm => is$1(elm, 'table') || isRoot(elm); 22528 return ancestor$3(element, tags.join(','), isRootOrUpperTable); 22529 }; 22530 const cell = (element, isRoot) => lookup$1([ 22531 'td', 22532 'th' 22533 ], element, isRoot); 22534 const cells = ancestor => firstLayer(ancestor, 'th,td'); 22535 const table = (element, isRoot) => closest$3(element, 'table', isRoot); 22536 22537 const walk = (all, current, index, direction, isEligible = always) => { 22538 const forwards = direction === 1; 22539 if (!forwards && index <= 0) { 22540 return CellLocation.first(all[0]); 22541 } else if (forwards && index >= all.length - 1) { 22542 return CellLocation.last(all[all.length - 1]); 22543 } else { 22544 const newIndex = index + direction; 22545 const elem = all[newIndex]; 22546 return isEligible(elem) ? CellLocation.middle(current, elem) : walk(all, current, newIndex, direction, isEligible); 22547 } 22548 }; 22549 const detect = (current, isRoot) => { 22550 return table(current, isRoot).bind(table => { 22551 const all = cells(table); 22552 const index = findIndex$2(all, x => eq(current, x)); 22553 return index.map(index => ({ 22554 index, 22555 all 22556 })); 22557 }); 22558 }; 22559 const next = (current, isEligible, isRoot) => { 22560 const detection = detect(current, isRoot); 22561 return detection.fold(() => { 22562 return CellLocation.none(current); 22563 }, info => { 22564 return walk(info.all, current, info.index, 1, isEligible); 22565 }); 22566 }; 22567 const prev = (current, isEligible, isRoot) => { 22568 const detection = detect(current, isRoot); 22569 return detection.fold(() => { 22570 return CellLocation.none(); 22571 }, info => { 22572 return walk(info.all, current, info.index, -1, isEligible); 22573 }); 22574 }; 22575 22576 const deflate = (rect, delta) => ({ 22577 left: rect.left - delta, 22578 top: rect.top - delta, 22579 right: rect.right + delta * 2, 22580 bottom: rect.bottom + delta * 2, 22581 width: rect.width + delta, 22582 height: rect.height + delta 22583 }); 22584 const getCorners = (getYAxisValue, tds) => bind$3(tds, td => { 22585 const rect = deflate(clone$1(td.getBoundingClientRect()), -1); 22586 return [ 22587 { 22588 x: rect.left, 22589 y: getYAxisValue(rect), 22590 cell: td 22591 }, 22592 { 22593 x: rect.right, 22594 y: getYAxisValue(rect), 22595 cell: td 22596 } 22597 ]; 22598 }); 22599 const findClosestCorner = (corners, x, y) => foldl(corners, (acc, newCorner) => acc.fold(() => Optional.some(newCorner), oldCorner => { 22600 const oldDist = Math.sqrt(Math.abs(oldCorner.x - x) + Math.abs(oldCorner.y - y)); 22601 const newDist = Math.sqrt(Math.abs(newCorner.x - x) + Math.abs(newCorner.y - y)); 22602 return Optional.some(newDist < oldDist ? newCorner : oldCorner); 22603 }), Optional.none()); 22604 const getClosestCell = (getYAxisValue, isTargetCorner, table, x, y) => { 22605 const cells = descendants(SugarElement.fromDom(table), 'td,th,caption').map(e => e.dom); 22606 const corners = filter$5(getCorners(getYAxisValue, cells), corner => isTargetCorner(corner, y)); 22607 return findClosestCorner(corners, x, y).map(corner => corner.cell); 22608 }; 22609 const getBottomValue = rect => rect.bottom; 22610 const getTopValue = rect => rect.top; 22611 const isAbove = (corner, y) => corner.y < y; 22612 const isBelow = (corner, y) => corner.y > y; 22613 const getClosestCellAbove = curry(getClosestCell, getBottomValue, isAbove); 22614 const getClosestCellBelow = curry(getClosestCell, getTopValue, isBelow); 22615 const findClosestPositionInAboveCell = (table, pos) => head(pos.getClientRects()).bind(rect => getClosestCellAbove(table, rect.left, rect.top)).bind(cell => findClosestHorizontalPosition(getLastLinePositions(cell), pos)); 22616 const findClosestPositionInBelowCell = (table, pos) => last$3(pos.getClientRects()).bind(rect => getClosestCellBelow(table, rect.left, rect.top)).bind(cell => findClosestHorizontalPosition(getFirstLinePositions(cell), pos)); 22617 22618 const hasNextBreak = (getPositionsUntil, scope, lineInfo) => lineInfo.breakAt.exists(breakPos => getPositionsUntil(scope, breakPos).breakAt.isSome()); 22619 const startsWithWrapBreak = lineInfo => lineInfo.breakType === BreakType.Wrap && lineInfo.positions.length === 0; 22620 const startsWithBrBreak = lineInfo => lineInfo.breakType === BreakType.Br && lineInfo.positions.length === 1; 22621 const isAtTableCellLine = (getPositionsUntil, scope, pos) => { 22622 const lineInfo = getPositionsUntil(scope, pos); 22623 if (startsWithWrapBreak(lineInfo) || !isBr$6(pos.getNode()) && startsWithBrBreak(lineInfo)) { 22624 return !hasNextBreak(getPositionsUntil, scope, lineInfo); 22625 } else { 22626 return lineInfo.breakAt.isNone(); 22627 } 22628 }; 22629 const isAtFirstTableCellLine = curry(isAtTableCellLine, getPositionsUntilPreviousLine); 22630 const isAtLastTableCellLine = curry(isAtTableCellLine, getPositionsUntilNextLine); 22631 const isCaretAtStartOrEndOfTable = (forward, rng, table) => { 22632 const caretPos = CaretPosition.fromRangeStart(rng); 22633 return positionIn(!forward, table).exists(pos => pos.isEqual(caretPos)); 22634 }; 22635 const navigateHorizontally = (editor, forward, table, _td) => { 22636 const rng = editor.selection.getRng(); 22637 const direction = forward ? 1 : -1; 22638 if (isFakeCaretTableBrowser() && isCaretAtStartOrEndOfTable(forward, rng, table)) { 22639 showCaret(direction, editor, table, !forward, false).each(newRng => { 22640 moveToRange(editor, newRng); 22641 }); 22642 return true; 22643 } 22644 return false; 22645 }; 22646 const getClosestAbovePosition = (root, table, start) => findClosestPositionInAboveCell(table, start).orThunk(() => head(start.getClientRects()).bind(rect => findClosestHorizontalPositionFromPoint(getPositionsAbove(root, CaretPosition.before(table)), rect.left))).getOr(CaretPosition.before(table)); 22647 const getClosestBelowPosition = (root, table, start) => findClosestPositionInBelowCell(table, start).orThunk(() => head(start.getClientRects()).bind(rect => findClosestHorizontalPositionFromPoint(getPositionsBelow(root, CaretPosition.after(table)), rect.left))).getOr(CaretPosition.after(table)); 22648 const getTable = (previous, pos) => { 22649 const node = pos.getNode(previous); 22650 return isTable$2(node) ? Optional.some(node) : Optional.none(); 22651 }; 22652 const renderBlock = (down, editor, table) => { 22653 editor.undoManager.transact(() => { 22654 const insertFn = down ? after$4 : before$3; 22655 const rng = insertEmptyLine(editor, SugarElement.fromDom(table), insertFn); 22656 moveToRange(editor, rng); 22657 }); 22658 }; 22659 const moveCaret = (editor, down, pos) => { 22660 const table = down ? getTable(true, pos) : getTable(false, pos); 22661 const last = down === false; 22662 table.fold(() => moveToRange(editor, pos.toRange()), table => positionIn(last, editor.getBody()).filter(lastPos => lastPos.isEqual(pos)).fold(() => moveToRange(editor, pos.toRange()), _ => renderBlock(down, editor, table))); 22663 }; 22664 const navigateVertically = (editor, down, table, td) => { 22665 const rng = editor.selection.getRng(); 22666 const pos = CaretPosition.fromRangeStart(rng); 22667 const root = editor.getBody(); 22668 if (!down && isAtFirstTableCellLine(td, pos)) { 22669 const newPos = getClosestAbovePosition(root, table, pos); 22670 moveCaret(editor, down, newPos); 22671 return true; 22672 } else if (down && isAtLastTableCellLine(td, pos)) { 22673 const newPos = getClosestBelowPosition(root, table, pos); 22674 moveCaret(editor, down, newPos); 22675 return true; 22676 } else { 22677 return false; 22678 } 22679 }; 22680 const move$1 = (editor, forward, mover) => Optional.from(editor.dom.getParent(editor.selection.getNode(), 'td,th')).bind(td => Optional.from(editor.dom.getParent(td, 'table')).map(table => mover(editor, forward, table, td))).getOr(false); 22681 const moveH = (editor, forward) => move$1(editor, forward, navigateHorizontally); 22682 const moveV = (editor, forward) => move$1(editor, forward, navigateVertically); 22683 const getCellFirstCursorPosition = cell => { 22684 const selection = SimSelection.exact(cell, 0, cell, 0); 22685 return toNative(selection); 22686 }; 22687 const tabGo = (editor, isRoot, cell) => { 22688 return cell.fold(Optional.none, Optional.none, (_current, next) => { 22689 return first(next).map(cell => { 22690 return getCellFirstCursorPosition(cell); 22691 }); 22692 }, current => { 22693 editor.execCommand('mceTableInsertRowAfter'); 22694 return tabForward(editor, isRoot, current); 22695 }); 22696 }; 22697 const tabForward = (editor, isRoot, cell) => tabGo(editor, isRoot, next(cell, isEditable$3)); 22698 const tabBackward = (editor, isRoot, cell) => tabGo(editor, isRoot, prev(cell, isEditable$3)); 22699 const handleTab = (editor, forward) => { 22700 const rootElements = [ 22701 'table', 22702 'li', 22703 'dl' 22704 ]; 22705 const body = SugarElement.fromDom(editor.getBody()); 22706 const isRoot = element => { 22707 const name$1 = name(element); 22708 return eq(element, body) || contains$2(rootElements, name$1); 22709 }; 22710 const rng = editor.selection.getRng(); 22711 const container = SugarElement.fromDom(!forward ? rng.startContainer : rng.endContainer); 22712 return cell(container, isRoot).map(cell => { 22713 table(cell, isRoot).each(table => { 22714 editor.model.table.clearSelectedCells(table.dom); 22715 }); 22716 editor.selection.collapse(!forward); 22717 const navigation = !forward ? tabBackward : tabForward; 22718 const rng = navigation(editor, isRoot, cell); 22719 rng.each(range => { 22720 editor.selection.setRng(range); 22721 }); 22722 return true; 22723 }).getOr(false); 22724 }; 22725 22726 const executeKeydownOverride$4 = (editor, caret, evt) => { 22727 const isMac = Env.os.isMacOS() || Env.os.isiOS(); 22728 execute([ 22729 { 22730 keyCode: VK.RIGHT, 22731 action: action(moveH$2, editor, true) 22732 }, 22733 { 22734 keyCode: VK.LEFT, 22735 action: action(moveH$2, editor, false) 22736 }, 22737 { 22738 keyCode: VK.UP, 22739 action: action(moveV$3, editor, false) 22740 }, 22741 { 22742 keyCode: VK.DOWN, 22743 action: action(moveV$3, editor, true) 22744 }, 22745 ...isMac ? [ 22746 { 22747 keyCode: VK.UP, 22748 action: action(selectToEndPoint, editor, false), 22749 metaKey: true, 22750 shiftKey: true 22751 }, 22752 { 22753 keyCode: VK.DOWN, 22754 action: action(selectToEndPoint, editor, true), 22755 metaKey: true, 22756 shiftKey: true 22757 } 22758 ] : [], 22759 { 22760 keyCode: VK.RIGHT, 22761 action: action(moveH, editor, true) 22762 }, 22763 { 22764 keyCode: VK.LEFT, 22765 action: action(moveH, editor, false) 22766 }, 22767 { 22768 keyCode: VK.UP, 22769 action: action(moveV, editor, false) 22770 }, 22771 { 22772 keyCode: VK.DOWN, 22773 action: action(moveV, editor, true) 22774 }, 22775 { 22776 keyCode: VK.RIGHT, 22777 action: action(moveH$1, editor, true) 22778 }, 22779 { 22780 keyCode: VK.LEFT, 22781 action: action(moveH$1, editor, false) 22782 }, 22783 { 22784 keyCode: VK.UP, 22785 action: action(moveV$1, editor, false) 22786 }, 22787 { 22788 keyCode: VK.DOWN, 22789 action: action(moveV$1, editor, true) 22790 }, 22791 { 22792 keyCode: VK.RIGHT, 22793 action: action(move$2, editor, caret, true) 22794 }, 22795 { 22796 keyCode: VK.LEFT, 22797 action: action(move$2, editor, caret, false) 22798 }, 22799 { 22800 keyCode: VK.RIGHT, 22801 ctrlKey: !isMac, 22802 altKey: isMac, 22803 action: action(moveNextWord, editor, caret) 22804 }, 22805 { 22806 keyCode: VK.LEFT, 22807 ctrlKey: !isMac, 22808 altKey: isMac, 22809 action: action(movePrevWord, editor, caret) 22810 }, 22811 { 22812 keyCode: VK.UP, 22813 action: action(moveV$2, editor, false) 22814 }, 22815 { 22816 keyCode: VK.DOWN, 22817 action: action(moveV$2, editor, true) 22818 } 22819 ], evt).each(_ => { 22820 evt.preventDefault(); 22821 }); 22822 }; 22823 const setup$k = (editor, caret) => { 22824 editor.on('keydown', evt => { 22825 if (!evt.isDefaultPrevented()) { 22826 executeKeydownOverride$4(editor, caret, evt); 22827 } 22828 }); 22829 }; 22830 22831 const point = (container, offset) => ({ 22832 container, 22833 offset 22834 }); 22835 22836 const DOM$7 = DOMUtils.DOM; 22837 const alwaysNext = startNode => node => startNode === node ? -1 : 0; 22838 const isBoundary = dom => node => dom.isBlock(node) || contains$2([ 22839 'BR', 22840 'IMG', 22841 'HR', 22842 'INPUT' 22843 ], node.nodeName) || dom.getContentEditable(node) === 'false'; 22844 const textBefore = (node, offset, rootNode) => { 22845 if (isText$a(node) && offset >= 0) { 22846 return Optional.some(point(node, offset)); 22847 } else { 22848 const textSeeker = TextSeeker(DOM$7); 22849 return Optional.from(textSeeker.backwards(node, offset, alwaysNext(node), rootNode)).map(prev => point(prev.container, prev.container.data.length)); 22850 } 22851 }; 22852 const textAfter = (node, offset, rootNode) => { 22853 if (isText$a(node) && offset >= node.length) { 22854 return Optional.some(point(node, offset)); 22855 } else { 22856 const textSeeker = TextSeeker(DOM$7); 22857 return Optional.from(textSeeker.forwards(node, offset, alwaysNext(node), rootNode)).map(prev => point(prev.container, 0)); 22858 } 22859 }; 22860 const scanLeft = (node, offset, rootNode) => { 22861 if (!isText$a(node)) { 22862 return Optional.none(); 22863 } 22864 const text = node.data; 22865 if (offset >= 0 && offset <= text.length) { 22866 return Optional.some(point(node, offset)); 22867 } else { 22868 const textSeeker = TextSeeker(DOM$7); 22869 return Optional.from(textSeeker.backwards(node, offset, alwaysNext(node), rootNode)).bind(prev => { 22870 const prevText = prev.container.data; 22871 return scanLeft(prev.container, offset + prevText.length, rootNode); 22872 }); 22873 } 22874 }; 22875 const scanRight = (node, offset, rootNode) => { 22876 if (!isText$a(node)) { 22877 return Optional.none(); 22878 } 22879 const text = node.data; 22880 if (offset <= text.length) { 22881 return Optional.some(point(node, offset)); 22882 } else { 22883 const textSeeker = TextSeeker(DOM$7); 22884 return Optional.from(textSeeker.forwards(node, offset, alwaysNext(node), rootNode)).bind(next => scanRight(next.container, offset - text.length, rootNode)); 22885 } 22886 }; 22887 const repeatLeft = (dom, node, offset, process, rootNode) => { 22888 const search = TextSeeker(dom, isBoundary(dom)); 22889 return Optional.from(search.backwards(node, offset, process, rootNode)); 22890 }; 22891 22892 const isValidTextRange = rng => rng.collapsed && isText$a(rng.startContainer); 22893 const getText = rng => trim$1(rng.toString().replace(/\u00A0/g, ' ')); 22894 const isWhitespace = chr => chr !== '' && ' \xA0\f\n\r\t\x0B'.indexOf(chr) !== -1; 22895 22896 const stripTrigger = (text, trigger) => text.substring(trigger.length); 22897 const findTrigger = (text, index, trigger) => { 22898 let i; 22899 const firstChar = trigger.charAt(0); 22900 for (i = index - 1; i >= 0; i--) { 22901 const char = text.charAt(i); 22902 if (isWhitespace(char)) { 22903 return Optional.none(); 22904 } 22905 if (firstChar === char && contains$1(text, trigger, i, index)) { 22906 break; 22907 } 22908 } 22909 return Optional.some(i); 22910 }; 22911 const findStart = (dom, initRange, trigger, minChars = 0) => { 22912 if (!isValidTextRange(initRange)) { 22913 return Optional.none(); 22914 } 22915 const buffer = { 22916 text: '', 22917 offset: 0 22918 }; 22919 const findTriggerIndex = (element, offset, text) => { 22920 buffer.text = text + buffer.text; 22921 buffer.offset += offset; 22922 return findTrigger(buffer.text, buffer.offset, trigger).getOr(offset); 22923 }; 22924 const root = dom.getParent(initRange.startContainer, dom.isBlock) || dom.getRoot(); 22925 return repeatLeft(dom, initRange.startContainer, initRange.startOffset, findTriggerIndex, root).bind(spot => { 22926 const range = initRange.cloneRange(); 22927 range.setStart(spot.container, spot.offset); 22928 range.setEnd(initRange.endContainer, initRange.endOffset); 22929 if (range.collapsed) { 22930 return Optional.none(); 22931 } 22932 const text = getText(range); 22933 const triggerIndex = text.lastIndexOf(trigger); 22934 if (triggerIndex !== 0 || stripTrigger(text, trigger).length < minChars) { 22935 return Optional.none(); 22936 } else { 22937 return Optional.some({ 22938 text: stripTrigger(text, trigger), 22939 range, 22940 trigger 22941 }); 22942 } 22943 }); 22944 }; 22945 const getContext = (dom, initRange, trigger, minChars = 0) => detect$1(SugarElement.fromDom(initRange.startContainer)).fold(() => findStart(dom, initRange, trigger, minChars), elm => { 22946 const range = dom.createRng(); 22947 range.selectNode(elm.dom); 22948 const text = getText(range); 22949 return Optional.some({ 22950 range, 22951 text: stripTrigger(text, trigger), 22952 trigger 22953 }); 22954 }); 22955 22956 const isText$1 = node => node.nodeType === TEXT; 22957 const isElement = node => node.nodeType === ELEMENT; 22958 const toLast = node => { 22959 if (isText$1(node)) { 22960 return point(node, node.data.length); 22961 } else { 22962 const children = node.childNodes; 22963 return children.length > 0 ? toLast(children[children.length - 1]) : point(node, children.length); 22964 } 22965 }; 22966 const toLeaf = (node, offset) => { 22967 const children = node.childNodes; 22968 if (children.length > 0 && offset < children.length) { 22969 return toLeaf(children[offset], 0); 22970 } else if (children.length > 0 && isElement(node) && children.length === offset) { 22971 return toLast(children[children.length - 1]); 22972 } else { 22973 return point(node, offset); 22974 } 22975 }; 22976 22977 const isPreviousCharContent = (dom, leaf) => { 22978 var _a; 22979 const root = (_a = dom.getParent(leaf.container, dom.isBlock)) !== null && _a !== void 0 ? _a : dom.getRoot(); 22980 return repeatLeft(dom, leaf.container, leaf.offset, (_element, offset) => offset === 0 ? -1 : offset, root).filter(spot => { 22981 const char = spot.container.data.charAt(spot.offset - 1); 22982 return !isWhitespace(char); 22983 }).isSome(); 22984 }; 22985 const isStartOfWord = dom => rng => { 22986 const leaf = toLeaf(rng.startContainer, rng.startOffset); 22987 return !isPreviousCharContent(dom, leaf); 22988 }; 22989 const getTriggerContext = (dom, initRange, database) => findMap(database.triggers, trigger => getContext(dom, initRange, trigger)); 22990 const lookup = (editor, getDatabase) => { 22991 const database = getDatabase(); 22992 const rng = editor.selection.getRng(); 22993 return getTriggerContext(editor.dom, rng, database).bind(context => lookupWithContext(editor, getDatabase, context)); 22994 }; 22995 const lookupWithContext = (editor, getDatabase, context, fetchOptions = {}) => { 22996 var _a; 22997 const database = getDatabase(); 22998 const rng = editor.selection.getRng(); 22999 const startText = (_a = rng.startContainer.nodeValue) !== null && _a !== void 0 ? _a : ''; 23000 const autocompleters = filter$5(database.lookupByTrigger(context.trigger), autocompleter => context.text.length >= autocompleter.minChars && autocompleter.matches.getOrThunk(() => isStartOfWord(editor.dom))(context.range, startText, context.text)); 23001 if (autocompleters.length === 0) { 23002 return Optional.none(); 23003 } 23004 const lookupData = Promise.all(map$3(autocompleters, ac => { 23005 const fetchResult = ac.fetch(context.text, ac.maxResults, fetchOptions); 23006 return fetchResult.then(results => ({ 23007 matchText: context.text, 23008 items: results, 23009 columns: ac.columns, 23010 onAction: ac.onAction, 23011 highlightOn: ac.highlightOn 23012 })); 23013 })); 23014 return Optional.some({ 23015 lookupData, 23016 context 23017 }); 23018 }; 23019 23020 var SimpleResultType; 23021 (function (SimpleResultType) { 23022 SimpleResultType[SimpleResultType['Error'] = 0] = 'Error'; 23023 SimpleResultType[SimpleResultType['Value'] = 1] = 'Value'; 23024 }(SimpleResultType || (SimpleResultType = {}))); 23025 const fold$1 = (res, onError, onValue) => res.stype === SimpleResultType.Error ? onError(res.serror) : onValue(res.svalue); 23026 const partition = results => { 23027 const values = []; 23028 const errors = []; 23029 each$e(results, obj => { 23030 fold$1(obj, err => errors.push(err), val => values.push(val)); 23031 }); 23032 return { 23033 values, 23034 errors 23035 }; 23036 }; 23037 const mapError = (res, f) => { 23038 if (res.stype === SimpleResultType.Error) { 23039 return { 23040 stype: SimpleResultType.Error, 23041 serror: f(res.serror) 23042 }; 23043 } else { 23044 return res; 23045 } 23046 }; 23047 const map = (res, f) => { 23048 if (res.stype === SimpleResultType.Value) { 23049 return { 23050 stype: SimpleResultType.Value, 23051 svalue: f(res.svalue) 23052 }; 23053 } else { 23054 return res; 23055 } 23056 }; 23057 const bind$1 = (res, f) => { 23058 if (res.stype === SimpleResultType.Value) { 23059 return f(res.svalue); 23060 } else { 23061 return res; 23062 } 23063 }; 23064 const bindError = (res, f) => { 23065 if (res.stype === SimpleResultType.Error) { 23066 return f(res.serror); 23067 } else { 23068 return res; 23069 } 23070 }; 23071 const svalue = v => ({ 23072 stype: SimpleResultType.Value, 23073 svalue: v 23074 }); 23075 const serror = e => ({ 23076 stype: SimpleResultType.Error, 23077 serror: e 23078 }); 23079 const toResult = res => fold$1(res, Result.error, Result.value); 23080 const fromResult = res => res.fold(serror, svalue); 23081 const SimpleResult = { 23082 fromResult, 23083 toResult, 23084 svalue, 23085 partition, 23086 serror, 23087 bind: bind$1, 23088 bindError, 23089 map, 23090 mapError, 23091 fold: fold$1 23092 }; 23093 23094 const formatObj = input => { 23095 return isObject(input) && keys(input).length > 100 ? ' removed due to size' : JSON.stringify(input, null, 2); 23096 }; 23097 const formatErrors = errors => { 23098 const es = errors.length > 10 ? errors.slice(0, 10).concat([{ 23099 path: [], 23100 getErrorInfo: constant('... (only showing first ten failures)') 23101 }]) : errors; 23102 return map$3(es, e => { 23103 return 'Failed path: (' + e.path.join(' > ') + ')\n' + e.getErrorInfo(); 23104 }); 23105 }; 23106 23107 const nu = (path, getErrorInfo) => { 23108 return SimpleResult.serror([{ 23109 path, 23110 getErrorInfo 23111 }]); 23112 }; 23113 const missingRequired = (path, key, obj) => nu(path, () => 'Could not find valid *required* value for "' + key + '" in ' + formatObj(obj)); 23114 const missingKey = (path, key) => nu(path, () => 'Choice schema did not contain choice key: "' + key + '"'); 23115 const missingBranch = (path, branches, branch) => nu(path, () => 'The chosen schema: "' + branch + '" did not exist in branches: ' + formatObj(branches)); 23116 const custom = (path, err) => nu(path, constant(err)); 23117 23118 const chooseFrom = (path, input, branches, ch) => { 23119 const fields = get$a(branches, ch); 23120 return fields.fold(() => missingBranch(path, branches, ch), vp => vp.extract(path.concat(['branch: ' + ch]), input)); 23121 }; 23122 const choose$1 = (key, branches) => { 23123 const extract = (path, input) => { 23124 const choice = get$a(input, key); 23125 return choice.fold(() => missingKey(path, key), chosen => chooseFrom(path, input, branches, chosen)); 23126 }; 23127 const toString = () => 'chooseOn(' + key + '). Possible values: ' + keys(branches); 23128 return { 23129 extract, 23130 toString 23131 }; 23132 }; 23133 23134 const shallow = (old, nu) => { 23135 return nu; 23136 }; 23137 const deep = (old, nu) => { 23138 const bothObjects = isPlainObject(old) && isPlainObject(nu); 23139 return bothObjects ? deepMerge(old, nu) : nu; 23140 }; 23141 const baseMerge = merger => { 23142 return (...objects) => { 23143 if (objects.length === 0) { 23144 throw new Error(`Can't merge zero objects`); 23145 } 23146 const ret = {}; 23147 for (let j = 0; j < objects.length; j++) { 23148 const curObject = objects[j]; 23149 for (const key in curObject) { 23150 if (has$2(curObject, key)) { 23151 ret[key] = merger(ret[key], curObject[key]); 23152 } 23153 } 23154 } 23155 return ret; 23156 }; 23157 }; 23158 const deepMerge = baseMerge(deep); 23159 const merge = baseMerge(shallow); 23160 23161 const required = () => ({ 23162 tag: 'required', 23163 process: {} 23164 }); 23165 const defaultedThunk = fallbackThunk => ({ 23166 tag: 'defaultedThunk', 23167 process: fallbackThunk 23168 }); 23169 const defaulted$1 = fallback => defaultedThunk(constant(fallback)); 23170 const asOption = () => ({ 23171 tag: 'option', 23172 process: {} 23173 }); 23174 23175 const mergeValues = (values, base) => values.length > 0 ? SimpleResult.svalue(deepMerge(base, merge.apply(undefined, values))) : SimpleResult.svalue(base); 23176 const mergeErrors = errors => compose(SimpleResult.serror, flatten)(errors); 23177 const consolidateObj = (objects, base) => { 23178 const partition = SimpleResult.partition(objects); 23179 return partition.errors.length > 0 ? mergeErrors(partition.errors) : mergeValues(partition.values, base); 23180 }; 23181 const consolidateArr = objects => { 23182 const partitions = SimpleResult.partition(objects); 23183 return partitions.errors.length > 0 ? mergeErrors(partitions.errors) : SimpleResult.svalue(partitions.values); 23184 }; 23185 const ResultCombine = { 23186 consolidateObj, 23187 consolidateArr 23188 }; 23189 23190 const field$1 = (key, newKey, presence, prop) => ({ 23191 tag: 'field', 23192 key, 23193 newKey, 23194 presence, 23195 prop 23196 }); 23197 const customField$1 = (newKey, instantiator) => ({ 23198 tag: 'custom', 23199 newKey, 23200 instantiator 23201 }); 23202 const fold = (value, ifField, ifCustom) => { 23203 switch (value.tag) { 23204 case 'field': 23205 return ifField(value.key, value.newKey, value.presence, value.prop); 23206 case 'custom': 23207 return ifCustom(value.newKey, value.instantiator); 23208 } 23209 }; 23210 23211 const value = validator => { 23212 const extract = (path, val) => { 23213 return SimpleResult.bindError(validator(val), err => custom(path, err)); 23214 }; 23215 const toString = constant('val'); 23216 return { 23217 extract, 23218 toString 23219 }; 23220 }; 23221 const anyValue$1 = value(SimpleResult.svalue); 23222 23223 const requiredAccess = (path, obj, key, bundle) => get$a(obj, key).fold(() => missingRequired(path, key, obj), bundle); 23224 const fallbackAccess = (obj, key, fallback, bundle) => { 23225 const v = get$a(obj, key).getOrThunk(() => fallback(obj)); 23226 return bundle(v); 23227 }; 23228 const optionAccess = (obj, key, bundle) => bundle(get$a(obj, key)); 23229 const optionDefaultedAccess = (obj, key, fallback, bundle) => { 23230 const opt = get$a(obj, key).map(val => val === true ? fallback(obj) : val); 23231 return bundle(opt); 23232 }; 23233 const extractField = (field, path, obj, key, prop) => { 23234 const bundle = av => prop.extract(path.concat([key]), av); 23235 const bundleAsOption = optValue => optValue.fold(() => SimpleResult.svalue(Optional.none()), ov => { 23236 const result = prop.extract(path.concat([key]), ov); 23237 return SimpleResult.map(result, Optional.some); 23238 }); 23239 switch (field.tag) { 23240 case 'required': 23241 return requiredAccess(path, obj, key, bundle); 23242 case 'defaultedThunk': 23243 return fallbackAccess(obj, key, field.process, bundle); 23244 case 'option': 23245 return optionAccess(obj, key, bundleAsOption); 23246 case 'defaultedOptionThunk': 23247 return optionDefaultedAccess(obj, key, field.process, bundleAsOption); 23248 case 'mergeWithThunk': { 23249 return fallbackAccess(obj, key, constant({}), v => { 23250 const result = deepMerge(field.process(obj), v); 23251 return bundle(result); 23252 }); 23253 } 23254 } 23255 }; 23256 const extractFields = (path, obj, fields) => { 23257 const success = {}; 23258 const errors = []; 23259 for (const field of fields) { 23260 fold(field, (key, newKey, presence, prop) => { 23261 const result = extractField(presence, path, obj, key, prop); 23262 SimpleResult.fold(result, err => { 23263 errors.push(...err); 23264 }, res => { 23265 success[newKey] = res; 23266 }); 23267 }, (newKey, instantiator) => { 23268 success[newKey] = instantiator(obj); 23269 }); 23270 } 23271 return errors.length > 0 ? SimpleResult.serror(errors) : SimpleResult.svalue(success); 23272 }; 23273 const objOf = values => { 23274 const extract = (path, o) => extractFields(path, o, values); 23275 const toString = () => { 23276 const fieldStrings = map$3(values, value => fold(value, (key, _okey, _presence, prop) => key + ' -> ' + prop.toString(), (newKey, _instantiator) => 'state(' + newKey + ')')); 23277 return 'obj{\n' + fieldStrings.join('\n') + '}'; 23278 }; 23279 return { 23280 extract, 23281 toString 23282 }; 23283 }; 23284 const arrOf = prop => { 23285 const extract = (path, array) => { 23286 const results = map$3(array, (a, i) => prop.extract(path.concat(['[' + i + ']']), a)); 23287 return ResultCombine.consolidateArr(results); 23288 }; 23289 const toString = () => 'array(' + prop.toString() + ')'; 23290 return { 23291 extract, 23292 toString 23293 }; 23294 }; 23295 23296 const valueOf = validator => value(v => validator(v).fold(SimpleResult.serror, SimpleResult.svalue)); 23297 const extractValue = (label, prop, obj) => { 23298 const res = prop.extract([label], obj); 23299 return SimpleResult.mapError(res, errs => ({ 23300 input: obj, 23301 errors: errs 23302 })); 23303 }; 23304 const asRaw = (label, prop, obj) => SimpleResult.toResult(extractValue(label, prop, obj)); 23305 const formatError = errInfo => { 23306 return 'Errors: \n' + formatErrors(errInfo.errors).join('\n') + '\n\nInput object: ' + formatObj(errInfo.input); 23307 }; 23308 const choose = (key, branches) => choose$1(key, map$2(branches, objOf)); 23309 23310 const anyValue = constant(anyValue$1); 23311 const typedValue = (validator, expectedType) => value(a => { 23312 const actualType = typeof a; 23313 return validator(a) ? SimpleResult.svalue(a) : SimpleResult.serror(`Expected type: ${ expectedType } but got: ${ actualType }`); 23314 }); 23315 const number = typedValue(isNumber, 'number'); 23316 const string = typedValue(isString, 'string'); 23317 const boolean = typedValue(isBoolean, 'boolean'); 23318 const functionProcessor = typedValue(isFunction, 'function'); 23319 23320 const field = field$1; 23321 const customField = customField$1; 23322 const validateEnum = values => valueOf(value => contains$2(values, value) ? Result.value(value) : Result.error(`Unsupported value: "${ value }", choose one of "${ values.join(', ') }".`)); 23323 const requiredOf = (key, schema) => field(key, key, required(), schema); 23324 const requiredString = key => requiredOf(key, string); 23325 const requiredFunction = key => requiredOf(key, functionProcessor); 23326 const requiredArrayOf = (key, schema) => field(key, key, required(), arrOf(schema)); 23327 const optionOf = (key, schema) => field(key, key, asOption(), schema); 23328 const optionString = key => optionOf(key, string); 23329 const optionFunction = key => optionOf(key, functionProcessor); 23330 const defaulted = (key, fallback) => field(key, key, defaulted$1(fallback), anyValue()); 23331 const defaultedOf = (key, fallback, schema) => field(key, key, defaulted$1(fallback), schema); 23332 const defaultedNumber = (key, fallback) => defaultedOf(key, fallback, number); 23333 const defaultedString = (key, fallback) => defaultedOf(key, fallback, string); 23334 const defaultedStringEnum = (key, fallback, values) => defaultedOf(key, fallback, validateEnum(values)); 23335 const defaultedBoolean = (key, fallback) => defaultedOf(key, fallback, boolean); 23336 const defaultedFunction = (key, fallback) => defaultedOf(key, fallback, functionProcessor); 23337 const defaultedArrayOf = (key, fallback, schema) => defaultedOf(key, fallback, arrOf(schema)); 23338 23339 const type = requiredString('type'); 23340 const fetch$1 = requiredFunction('fetch'); 23341 const onAction = requiredFunction('onAction'); 23342 const onSetup = defaultedFunction('onSetup', () => noop); 23343 const optionalText = optionString('text'); 23344 const optionalIcon = optionString('icon'); 23345 const optionalTooltip = optionString('tooltip'); 23346 const optionalLabel = optionString('label'); 23347 const active = defaultedBoolean('active', false); 23348 const enabled = defaultedBoolean('enabled', true); 23349 const primary = defaultedBoolean('primary', false); 23350 const defaultedColumns = num => defaulted('columns', num); 23351 const defaultedType = type => defaultedString('type', type); 23352 23353 const autocompleterSchema = objOf([ 23354 type, 23355 requiredString('trigger'), 23356 defaultedNumber('minChars', 1), 23357 defaultedColumns(1), 23358 defaultedNumber('maxResults', 10), 23359 optionFunction('matches'), 23360 fetch$1, 23361 onAction, 23362 defaultedArrayOf('highlightOn', [], string) 23363 ]); 23364 const createAutocompleter = spec => asRaw('Autocompleter', autocompleterSchema, { 23365 trigger: spec.ch, 23366 ...spec 23367 }); 23368 23369 const baseToolbarButtonFields = [ 23370 enabled, 23371 optionalTooltip, 23372 optionalIcon, 23373 optionalText, 23374 onSetup 23375 ]; 23376 23377 const baseToolbarToggleButtonFields = [active].concat(baseToolbarButtonFields); 23378 23379 const contextBarFields = [ 23380 defaultedFunction('predicate', never), 23381 defaultedStringEnum('scope', 'node', [ 23382 'node', 23383 'editor' 23384 ]), 23385 defaultedStringEnum('position', 'selection', [ 23386 'node', 23387 'selection', 23388 'line' 23389 ]) 23390 ]; 23391 23392 const contextButtonFields = baseToolbarButtonFields.concat([ 23393 defaultedType('contextformbutton'), 23394 primary, 23395 onAction, 23396 customField('original', identity) 23397 ]); 23398 const contextToggleButtonFields = baseToolbarToggleButtonFields.concat([ 23399 defaultedType('contextformbutton'), 23400 primary, 23401 onAction, 23402 customField('original', identity) 23403 ]); 23404 const launchButtonFields = baseToolbarButtonFields.concat([defaultedType('contextformbutton')]); 23405 const launchToggleButtonFields = baseToolbarToggleButtonFields.concat([defaultedType('contextformtogglebutton')]); 23406 const toggleOrNormal = choose('type', { 23407 contextformbutton: contextButtonFields, 23408 contextformtogglebutton: contextToggleButtonFields 23409 }); 23410 objOf([ 23411 defaultedType('contextform'), 23412 defaultedFunction('initValue', constant('')), 23413 optionalLabel, 23414 requiredArrayOf('commands', toggleOrNormal), 23415 optionOf('launch', choose('type', { 23416 contextformbutton: launchButtonFields, 23417 contextformtogglebutton: launchToggleButtonFields 23418 })) 23419 ].concat(contextBarFields)); 23420 23421 const register$2 = editor => { 23422 const popups = editor.ui.registry.getAll().popups; 23423 const dataset = map$2(popups, popup => createAutocompleter(popup).fold(err => { 23424 throw new Error(formatError(err)); 23425 }, identity)); 23426 const triggers = stringArray(mapToArray(dataset, v => v.trigger)); 23427 const datasetValues = values(dataset); 23428 const lookupByTrigger = trigger => filter$5(datasetValues, dv => dv.trigger === trigger); 23429 return { 23430 dataset, 23431 triggers, 23432 lookupByTrigger 23433 }; 23434 }; 23435 23436 const setupEditorInput = (editor, api) => { 23437 const update = last$1(api.load, 50); 23438 editor.on('keypress compositionend', e => { 23439 if (e.which === 27) { 23440 return; 23441 } 23442 update.throttle(); 23443 }); 23444 editor.on('keydown', e => { 23445 const keyCode = e.which; 23446 if (keyCode === 8) { 23447 update.throttle(); 23448 } else if (keyCode === 27) { 23449 api.cancelIfNecessary(); 23450 } 23451 }); 23452 editor.on('remove', update.cancel); 23453 }; 23454 const setup$j = editor => { 23455 const activeAutocompleter = value$2(); 23456 const uiActive = Cell(false); 23457 const isActive = activeAutocompleter.isSet; 23458 const cancelIfNecessary = () => { 23459 if (isActive()) { 23460 removeAutocompleterDecoration(editor); 23461 fireAutocompleterEnd(editor); 23462 uiActive.set(false); 23463 activeAutocompleter.clear(); 23464 } 23465 }; 23466 const commenceIfNecessary = context => { 23467 if (!isActive()) { 23468 addAutocompleterDecoration(editor, context.range); 23469 activeAutocompleter.set({ 23470 trigger: context.trigger, 23471 matchLength: context.text.length 23472 }); 23473 } 23474 }; 23475 const getAutocompleters = cached(() => register$2(editor)); 23476 const doLookup = fetchOptions => activeAutocompleter.get().map(ac => getContext(editor.dom, editor.selection.getRng(), ac.trigger).bind(newContext => lookupWithContext(editor, getAutocompleters, newContext, fetchOptions))).getOrThunk(() => lookup(editor, getAutocompleters)); 23477 const load = fetchOptions => { 23478 doLookup(fetchOptions).fold(cancelIfNecessary, lookupInfo => { 23479 commenceIfNecessary(lookupInfo.context); 23480 lookupInfo.lookupData.then(lookupData => { 23481 activeAutocompleter.get().map(ac => { 23482 const context = lookupInfo.context; 23483 if (ac.trigger === context.trigger) { 23484 if (context.text.length - ac.matchLength >= 10) { 23485 cancelIfNecessary(); 23486 } else { 23487 activeAutocompleter.set({ 23488 ...ac, 23489 matchLength: context.text.length 23490 }); 23491 if (uiActive.get()) { 23492 fireAutocompleterUpdate(editor, { lookupData }); 23493 } else { 23494 uiActive.set(true); 23495 fireAutocompleterStart(editor, { lookupData }); 23496 } 23497 } 23498 } 23499 }); 23500 }); 23501 }); 23502 }; 23503 editor.addCommand('mceAutocompleterReload', (_ui, value) => { 23504 const fetchOptions = isObject(value) ? value.fetchOptions : {}; 23505 load(fetchOptions); 23506 }); 23507 editor.addCommand('mceAutocompleterClose', cancelIfNecessary); 23508 setupEditorInput(editor, { 23509 cancelIfNecessary, 23510 load 23511 }); 23512 }; 23513 23514 const createAndFireInputEvent = eventType => (editor, inputType, specifics = {}) => { 23515 const target = editor.getBody(); 23516 const overrides = { 23517 bubbles: true, 23518 composed: true, 23519 data: null, 23520 isComposing: false, 23521 detail: 0, 23522 view: null, 23523 target, 23524 currentTarget: target, 23525 eventPhase: Event.AT_TARGET, 23526 originalTarget: target, 23527 explicitOriginalTarget: target, 23528 isTrusted: false, 23529 srcElement: target, 23530 cancelable: false, 23531 preventDefault: noop, 23532 inputType 23533 }; 23534 const input = clone$3(new InputEvent(eventType)); 23535 return editor.dispatch(eventType, { 23536 ...input, 23537 ...overrides, 23538 ...specifics 23539 }); 23540 }; 23541 const fire
vendor: 26,267 bytes, lines 23541-24233
23541FakeInputEvent = createAndFireInputEvent('input'); 23542 const fireFakeBeforeInputEvent = createAndFireInputEvent('beforeinput'); 23543 23544 const executeKeydownOverride$3 = (editor, caret, evt) => { 23545 const inputType = evt.keyCode === VK.BACKSPACE ? 'deleteContentBackward' : 'deleteContentForward'; 23546 executeWithDelayedAction([ 23547 { 23548 keyCode: VK.BACKSPACE, 23549 action: action(backspaceDelete, editor) 23550 }, 23551 { 23552 keyCode: VK.BACKSPACE, 23553 action: action(backspaceDelete$5, editor, false) 23554 }, 23555 { 23556 keyCode: VK.DELETE, 23557 action: action(backspaceDelete$5, editor, true) 23558 }, 23559 { 23560 keyCode: VK.BACKSPACE, 23561 action: action(backspaceDelete$6, editor, false) 23562 }, 23563 { 23564 keyCode: VK.DELETE, 23565 action: action(backspaceDelete$6, editor, true) 23566 }, 23567 { 23568 keyCode: VK.BACKSPACE, 23569 action: action(backspaceDelete$3, editor, caret, false) 23570 }, 23571 { 23572 keyCode: VK.DELETE, 23573 action: action(backspaceDelete$3, editor, caret, true) 23574 }, 23575 { 23576 keyCode: VK.BACKSPACE, 23577 action: action(backspaceDelete$9, editor, false) 23578 }, 23579 { 23580 keyCode: VK.DELETE, 23581 action: action(backspaceDelete$9, editor, true) 23582 }, 23583 { 23584 keyCode: VK.BACKSPACE, 23585 action: action(backspaceDelete$4, editor, false) 23586 }, 23587 { 23588 keyCode: VK.DELETE, 23589 action: action(backspaceDelete$4, editor, true) 23590 }, 23591 { 23592 keyCode: VK.BACKSPACE, 23593 action: action(backspaceDelete$1, editor, false) 23594 }, 23595 { 23596 keyCode: VK.DELETE, 23597 action: action(backspaceDelete$1, editor, true) 23598 }, 23599 { 23600 keyCode: VK.BACKSPACE, 23601 action: action(backspaceDelete$7, editor, false) 23602 }, 23603 { 23604 keyCode: VK.DELETE, 23605 action: action(backspaceDelete$7, editor, true) 23606 }, 23607 { 23608 keyCode: VK.BACKSPACE, 23609 action: action(backspaceDelete$8, editor, false) 23610 }, 23611 { 23612 keyCode: VK.DELETE, 23613 action: action(backspaceDelete$8, editor, true) 23614 }, 23615 { 23616 keyCode: VK.BACKSPACE, 23617 action: action(backspaceDelete$2, editor, false) 23618 }, 23619 { 23620 keyCode: VK.DELETE, 23621 action: action(backspaceDelete$2, editor, true) 23622 } 23623 ], evt).filter(_ => editor.selection.isEditable()).each(applyAction => { 23624 evt.preventDefault(); 23625 const beforeInput = fireFakeBeforeInputEvent(editor, inputType); 23626 if (!beforeInput.isDefaultPrevented()) { 23627 applyAction(); 23628 fireFakeInputEvent(editor, inputType); 23629 } 23630 }); 23631 }; 23632 const executeKeyupOverride = (editor, evt, isBackspaceKeydown) => { 23633 const platform = detect$2(); 23634 const os = platform.os; 23635 const browser = platform.browser; 23636 const multiDeleteKeyPatterns = os.isMacOS() ? [ 23637 { 23638 keyCode: VK.BACKSPACE, 23639 altKey: true, 23640 action: action(refreshCaret, editor) 23641 }, 23642 { 23643 keyCode: VK.DELETE, 23644 altKey: true, 23645 action: action(refreshCaret, editor) 23646 } 23647 ] : [ 23648 { 23649 keyCode: VK.BACKSPACE, 23650 ctrlKey: true, 23651 action: action(refreshCaret, editor) 23652 }, 23653 { 23654 keyCode: VK.DELETE, 23655 ctrlKey: true, 23656 action: action(refreshCaret, editor) 23657 } 23658 ]; 23659 if (os.isMacOS() && isBackspaceKeydown) { 23660 multiDeleteKeyPatterns.push({ 23661 keyCode: browser.isFirefox() ? 224 : 91, 23662 action: action(refreshCaret, editor) 23663 }); 23664 } 23665 execute([ 23666 { 23667 keyCode: VK.BACKSPACE, 23668 action: action(paddEmptyElement, editor) 23669 }, 23670 { 23671 keyCode: VK.DELETE, 23672 action: action(paddEmptyElement, editor) 23673 }, 23674 ...multiDeleteKeyPatterns 23675 ], evt); 23676 }; 23677 const setup$i = (editor, caret) => { 23678 let isBackspaceKeydown = false; 23679 editor.on('keydown', evt => { 23680 isBackspaceKeydown = evt.keyCode === VK.BACKSPACE; 23681 if (!evt.isDefaultPrevented()) { 23682 executeKeydownOverride$3(editor, caret, evt); 23683 } 23684 }); 23685 editor.on('keyup', evt => { 23686 if (!evt.isDefaultPrevented()) { 23687 executeKeyupOverride(editor, evt, isBackspaceKeydown); 23688 } 23689 isBackspaceKeydown = false; 23690 }); 23691 }; 23692 23693 const firstNonWhiteSpaceNodeSibling = node => { 23694 while (node) { 23695 if (isElement$6(node) || isText$a(node) && node.data && /[\r\n\s]/.test(node.data)) { 23696 return node; 23697 } 23698 node = node.nextSibling; 23699 } 23700 return null; 23701 }; 23702 const moveToCaretPosition = (editor, root) => { 23703 const dom = editor.dom; 23704 const moveCaretBeforeOnEnterElementsMap = editor.schema.getMoveCaretBeforeOnEnterElements(); 23705 if (!root) { 23706 return; 23707 } 23708 if (/^(LI|DT|DD)$/.test(root.nodeName)) { 23709 const firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild); 23710 if (firstChild && /^(UL|OL|DL)$/.test(firstChild.nodeName)) { 23711 root.insertBefore(dom.doc.createTextNode(nbsp), root.firstChild); 23712 } 23713 } 23714 const rng = dom.createRng(); 23715 root.normalize(); 23716 if (root.hasChildNodes()) { 23717 const walker = new DomTreeWalker(root, root); 23718 let lastNode = root; 23719 let node; 23720 while (node = walker.current()) { 23721 if (isText$a(node)) { 23722 rng.setStart(node, 0); 23723 rng.setEnd(node, 0); 23724 break; 23725 } 23726 if (moveCaretBeforeOnEnterElementsMap[node.nodeName.toLowerCase()]) { 23727 rng.setStartBefore(node); 23728 rng.setEndBefore(node); 23729 break; 23730 } 23731 lastNode = node; 23732 node = walker.next(); 23733 } 23734 if (!node) { 23735 rng.setStart(lastNode, 0); 23736 rng.setEnd(lastNode, 0); 23737 } 23738 } else { 23739 if (isBr$6(root)) { 23740 if (root.nextSibling && dom.isBlock(root.nextSibling)) { 23741 rng.setStartBefore(root); 23742 rng.setEndBefore(root); 23743 } else { 23744 rng.setStartAfter(root); 23745 rng.setEndAfter(root); 23746 } 23747 } else { 23748 rng.setStart(root, 0); 23749 rng.setEnd(root, 0); 23750 } 23751 } 23752 editor.selection.setRng(rng); 23753 scrollRangeIntoView(editor, rng); 23754 }; 23755 const getEditableRoot = (dom, node) => { 23756 const root = dom.getRoot(); 23757 let editableRoot; 23758 let parent = node; 23759 while (parent !== root && parent && dom.getContentEditable(parent) !== 'false') { 23760 if (dom.getContentEditable(parent) === 'true') { 23761 editableRoot = parent; 23762 } 23763 parent = parent.parentNode; 23764 } 23765 return parent !== root ? editableRoot : root; 23766 }; 23767 const getParentBlock$1 = editor => { 23768 return Optional.from(editor.dom.getParent(editor.selection.getStart(true), editor.dom.isBlock)); 23769 }; 23770 const getParentBlockName = editor => { 23771 return getParentBlock$1(editor).fold(constant(''), parentBlock => { 23772 return parentBlock.nodeName.toUpperCase(); 23773 }); 23774 }; 23775 const isListItemParentBlock = editor => { 23776 return getParentBlock$1(editor).filter(elm => { 23777 return isListItem$1(SugarElement.fromDom(elm)); 23778 }).isSome(); 23779 }; 23780 23781 const hasFirstChild = (elm, name) => { 23782 return elm.firstChild && elm.firstChild.nodeName === name; 23783 }; 23784 const isFirstChild = elm => { 23785 var _a; 23786 return ((_a = elm.parentNode) === null || _a === void 0 ? void 0 : _a.firstChild) === elm; 23787 }; 23788 const hasParent = (elm, parentName) => { 23789 const parentNode = elm === null || elm === void 0 ? void 0 : elm.parentNode; 23790 return isNonNullable(parentNode) && parentNode.nodeName === parentName; 23791 }; 23792 const isListBlock = elm => { 23793 return isNonNullable(elm) && /^(OL|UL|LI)$/.test(elm.nodeName); 23794 }; 23795 const isListItem = elm => { 23796 return isNonNullable(elm) && /^(LI|DT|DD)$/.test(elm.nodeName); 23797 }; 23798 const isNestedList = elm => { 23799 return isListBlock(elm) && isListBlock(elm.parentNode); 23800 }; 23801 const getContainerBlock = containerBlock => { 23802 const containerBlockParent = containerBlock.parentNode; 23803 return isListItem(containerBlockParent) ? containerBlockParent : containerBlock; 23804 }; 23805 const isFirstOrLastLi = (containerBlock, parentBlock, first) => { 23806 let node = containerBlock[first ? 'firstChild' : 'lastChild']; 23807 while (node) { 23808 if (isElement$6(node)) { 23809 break; 23810 } 23811 node = node[first ? 'nextSibling' : 'previousSibling']; 23812 } 23813 return node === parentBlock; 23814 }; 23815 const insert$3 = (editor, createNewBlock, containerBlock, parentBlock, newBlockName) => { 23816 const dom = editor.dom; 23817 const rng = editor.selection.getRng(); 23818 const containerParent = containerBlock.parentNode; 23819 if (containerBlock === editor.getBody() || !containerParent) { 23820 return; 23821 } 23822 if (isNestedList(containerBlock)) { 23823 newBlockName = 'LI'; 23824 } 23825 let newBlock = createNewBlock(newBlockName); 23826 if (isFirstOrLastLi(containerBlock, parentBlock, true) && isFirstOrLastLi(containerBlock, parentBlock, false)) { 23827 if (hasParent(containerBlock, 'LI')) { 23828 const containerBlockParent = getContainerBlock(containerBlock); 23829 dom.insertAfter(newBlock, containerBlockParent); 23830 if (isFirstChild(containerBlock)) { 23831 dom.remove(containerBlockParent); 23832 } else { 23833 dom.remove(containerBlock); 23834 } 23835 } else { 23836 dom.replace(newBlock, containerBlock); 23837 } 23838 } else if (isFirstOrLastLi(containerBlock, parentBlock, true)) { 23839 if (hasParent(containerBlock, 'LI')) { 23840 dom.insertAfter(newBlock, getContainerBlock(containerBlock)); 23841 newBlock.appendChild(dom.doc.createTextNode(' ')); 23842 newBlock.appendChild(containerBlock); 23843 } else { 23844 containerParent.insertBefore(newBlock, containerBlock); 23845 } 23846 dom.remove(parentBlock); 23847 } else if (isFirstOrLastLi(containerBlock, parentBlock, false)) { 23848 dom.insertAfter(newBlock, getContainerBlock(containerBlock)); 23849 dom.remove(parentBlock); 23850 } else { 23851 containerBlock = getContainerBlock(containerBlock); 23852 const tmpRng = rng.cloneRange(); 23853 tmpRng.setStartAfter(parentBlock); 23854 tmpRng.setEndAfter(containerBlock); 23855 const fragment = tmpRng.extractContents(); 23856 if (newBlockName === 'LI' && hasFirstChild(fragment, 'LI')) { 23857 newBlock = fragment.firstChild; 23858 dom.insertAfter(fragment, containerBlock); 23859 } else { 23860 dom.insertAfter(fragment, containerBlock); 23861 dom.insertAfter(newBlock, containerBlock); 23862 } 23863 dom.remove(parentBlock); 23864 } 23865 moveToCaretPosition(editor, newBlock); 23866 }; 23867 23868 const trimZwsp = fragment => { 23869 each$e(descendants$1(SugarElement.fromDom(fragment), isText$b), text => { 23870 const rawNode = text.dom; 23871 rawNode.nodeValue = trim$1(rawNode.data); 23872 }); 23873 }; 23874 const isWithinNonEditableList = (editor, node) => { 23875 const parentList = editor.dom.getParent(node, 'ol,ul,dl'); 23876 return parentList !== null && editor.dom.getContentEditableParent(parentList) === 'false'; 23877 }; 23878 const isEmptyAnchor = (dom, elm) => { 23879 return elm && elm.nodeName === 'A' && dom.isEmpty(elm); 23880 }; 23881 const emptyBlock = elm => { 23882 elm.innerHTML = '<br data-mce-bogus="1">'; 23883 }; 23884 const containerAndSiblingName = (container, nodeName) => { 23885 return container.nodeName === nodeName || container.previousSibling && container.previousSibling.nodeName === nodeName; 23886 }; 23887 const canSplitBlock = (dom, node) => { 23888 return isNonNullable(node) && dom.isBlock(node) && !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) && !/^(fixed|absolute)/i.test(node.style.position) && dom.isEditable(node.parentNode) && dom.getContentEditable(node) !== 'false'; 23889 }; 23890 const trimInlineElementsOnLeftSideOfBlock = (dom, nonEmptyElementsMap, block) => { 23891 var _a; 23892 const firstChilds = []; 23893 if (!block) { 23894 return; 23895 } 23896 let currentNode = block; 23897 while (currentNode = currentNode.firstChild) { 23898 if (dom.isBlock(currentNode)) { 23899 return; 23900 } 23901 if (isElement$6(currentNode) && !nonEmptyElementsMap[currentNode.nodeName.toLowerCase()]) { 23902 firstChilds.push(currentNode); 23903 } 23904 } 23905 let i = firstChilds.length; 23906 while (i--) { 23907 currentNode = firstChilds[i]; 23908 if (!currentNode.hasChildNodes() || currentNode.firstChild === currentNode.lastChild && ((_a = currentNode.firstChild) === null || _a === void 0 ? void 0 : _a.nodeValue) === '') { 23909 dom.remove(currentNode); 23910 } else { 23911 if (isEmptyAnchor(dom, currentNode)) { 23912 dom.remove(currentNode); 23913 } 23914 } 23915 } 23916 }; 23917 const normalizeZwspOffset = (start, container, offset) => { 23918 if (!isText$a(container)) { 23919 return offset; 23920 } else if (start) { 23921 return offset === 1 && container.data.charAt(offset - 1) === ZWSP$1 ? 0 : offset; 23922 } else { 23923 return offset === container.data.length - 1 && container.data.charAt(offset) === ZWSP$1 ? container.data.length : offset; 23924 } 23925 }; 23926 const includeZwspInRange = rng => { 23927 const newRng = rng.cloneRange(); 23928 newRng.setStart(rng.startContainer, normalizeZwspOffset(true, rng.startContainer, rng.startOffset)); 23929 newRng.setEnd(rng.endContainer, normalizeZwspOffset(false, rng.endContainer, rng.endOffset)); 23930 return newRng; 23931 }; 23932 const trimLeadingLineBreaks = node => { 23933 let currentNode = node; 23934 do { 23935 if (isText$a(currentNode)) { 23936 currentNode.data = currentNode.data.replace(/^[\r\n]+/, ''); 23937 } 23938 currentNode = currentNode.firstChild; 23939 } while (currentNode); 23940 }; 23941 const applyAttributes = (editor, node, forcedRootBlockAttrs) => { 23942 const dom = editor.dom; 23943 Optional.from(forcedRootBlockAttrs.style).map(dom.parseStyle).each(attrStyles => { 23944 const currentStyles = getAllRaw(SugarElement.fromDom(node)); 23945 const newStyles = { 23946 ...currentStyles, 23947 ...attrStyles 23948 }; 23949 dom.setStyles(node, newStyles); 23950 }); 23951 const attrClassesOpt = Optional.from(forcedRootBlockAttrs.class).map(attrClasses => attrClasses.split(/\s+/)); 23952 const currentClassesOpt = Optional.from(node.className).map(currentClasses => filter$5(currentClasses.split(/\s+/), clazz => clazz !== '')); 23953 lift2(attrClassesOpt, currentClassesOpt, (attrClasses, currentClasses) => { 23954 const filteredClasses = filter$5(currentClasses, clazz => !contains$2(attrClasses, clazz)); 23955 const newClasses = [ 23956 ...attrClasses, 23957 ...filteredClasses 23958 ]; 23959 dom.setAttrib(node, 'class', newClasses.join(' ')); 23960 }); 23961 const appliedAttrs = [ 23962 'style', 23963 'class' 23964 ]; 23965 const remainingAttrs = filter$4(forcedRootBlockAttrs, (_, attrs) => !contains$2(appliedAttrs, attrs)); 23966 dom.setAttribs(node, remainingAttrs); 23967 }; 23968 const setForcedBlockAttrs = (editor, node) => { 23969 const forcedRootBlockName = getForcedRootBlock(editor); 23970 if (forcedRootBlockName.toLowerCase() === node.tagName.toLowerCase()) { 23971 const forcedRootBlockAttrs = getForcedRootBlockAttrs(editor); 23972 applyAttributes(editor, node, forcedRootBlockAttrs); 23973 } 23974 }; 23975 const wrapSelfAndSiblingsInDefaultBlock = (editor, newBlockName, rng, container, offset) => { 23976 var _a, _b; 23977 const dom = editor.dom; 23978 const editableRoot = (_a = getEditableRoot(dom, container)) !== null && _a !== void 0 ? _a : dom.getRoot(); 23979 let parentBlock = dom.getParent(container, dom.isBlock); 23980 if (!parentBlock || !canSplitBlock(dom, parentBlock)) { 23981 parentBlock = parentBlock || editableRoot; 23982 if (!parentBlock.hasChildNodes()) { 23983 const newBlock = dom.create(newBlockName); 23984 setForcedBlockAttrs(editor, newBlock); 23985 parentBlock.appendChild(newBlock); 23986 rng.setStart(newBlock, 0); 23987 rng.setEnd(newBlock, 0); 23988 return newBlock; 23989 } 23990 let node = container; 23991 while (node && node.parentNode !== parentBlock) { 23992 node = node.parentNode; 23993 } 23994 let startNode; 23995 while (node && !dom.isBlock(node)) { 23996 startNode = node; 23997 node = node.previousSibling; 23998 } 23999 const startNodeName = (_b = startNode === null || startNode === void 0 ? void 0 : startNode.parentElement) === null || _b === void 0 ? void 0 : _b.nodeName; 24000 if (startNode && startNodeName && editor.schema.isValidChild(startNodeName, newBlockName.toLowerCase())) { 24001 const startNodeParent = startNode.parentNode; 24002 const newBlock = dom.create(newBlockName); 24003 setForcedBlockAttrs(editor, newBlock); 24004 startNodeParent.insertBefore(newBlock, startNode); 24005 node = startNode; 24006 while (node && !dom.isBlock(node)) { 24007 const next = node.nextSibling; 24008 newBlock.appendChild(node); 24009 node = next; 24010 } 24011 rng.setStart(container, offset); 24012 rng.setEnd(container, offset); 24013 } 24014 } 24015 return container; 24016 }; 24017 const addBrToBlockIfNeeded = (dom, block) => { 24018 block.normalize(); 24019 const lastChild = block.lastChild; 24020 if (!lastChild || isElement$6(lastChild) && /^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true))) { 24021 dom.add(block, 'br'); 24022 } 24023 }; 24024 const shouldEndContainer = (editor, container) => { 24025 const optionValue = shouldEndContainerOnEmptyBlock(editor); 24026 if (isNullable(container)) { 24027 return false; 24028 } else if (isString(optionValue)) { 24029 return contains$2(Tools.explode(optionValue), container.nodeName.toLowerCase()); 24030 } else { 24031 return optionValue; 24032 } 24033 }; 24034 const insert$2 = (editor, evt) => { 24035 let container; 24036 let offset; 24037 let parentBlockName; 24038 let containerBlock; 24039 let isAfterLastNodeInContainer = false; 24040 const dom = editor.dom; 24041 const schema = editor.schema, nonEmptyElementsMap = schema.getNonEmptyElements(); 24042 const rng = editor.selection.getRng(); 24043 const newBlockName = getForcedRootBlock(editor); 24044 const createNewBlock = name => { 24045 let node = container; 24046 const textInlineElements = schema.getTextInlineElements(); 24047 let block; 24048 if (name || parentBlockName === 'TABLE' || parentBlockName === 'HR') { 24049 block = dom.create(name || newBlockName); 24050 } else { 24051 block = parentBlock.cloneNode(false); 24052 } 24053 let caretNode = block; 24054 if (shouldKeepStyles(editor) === false) { 24055 dom.setAttrib(block, 'style', null); 24056 dom.setAttrib(block, 'class', null); 24057 } else { 24058 do { 24059 if (textInlineElements[node.nodeName]) { 24060 if (isCaretNode(node) || isBookmarkNode$1(node)) { 24061 continue; 24062 } 24063 const clonedNode = node.cloneNode(false); 24064 dom.setAttrib(clonedNode, 'id', ''); 24065 if (block.hasChildNodes()) { 24066 clonedNode.appendChild(block.firstChild); 24067 block.appendChild(clonedNode); 24068 } else { 24069 caretNode = clonedNode; 24070 block.appendChild(clonedNode); 24071 } 24072 } 24073 } while ((node = node.parentNode) && node !== editableRoot); 24074 } 24075 setForcedBlockAttrs(editor, block); 24076 emptyBlock(caretNode); 24077 return block; 24078 }; 24079 const isCaretAtStartOrEndOfBlock = start => { 24080 const normalizedOffset = normalizeZwspOffset(start, container, offset); 24081 if (isText$a(container) && (start ? normalizedOffset > 0 : normalizedOffset < container.data.length)) { 24082 return false; 24083 } 24084 if (container.parentNode === parentBlock && isAfterLastNodeInContainer && !start) { 24085 return true; 24086 } 24087 if (start && isElement$6(container) && container === parentBlock.firstChild) { 24088 return true; 24089 } 24090 if (containerAndSiblingName(container, 'TABLE') || containerAndSiblingName(container, 'HR')) { 24091 return isAfterLastNodeInContainer && !start || !isAfterLastNodeInContainer && start; 24092 } 24093 const walker = new DomTreeWalker(container, parentBlock); 24094 if (isText$a(container)) { 24095 if (start && normalizedOffset === 0) { 24096 walker.prev(); 24097 } else if (!start && normalizedOffset === container.data.length) { 24098 walker.next(); 24099 } 24100 } 24101 let node; 24102 while (node = walker.current()) { 24103 if (isElement$6(node)) { 24104 if (!node.getAttribute('data-mce-bogus')) { 24105 const name = node.nodeName.toLowerCase(); 24106 if (nonEmptyElementsMap[name] && name !== 'br') { 24107 return false; 24108 } 24109 } 24110 } else if (isText$a(node) && !isWhitespaceText(node.data)) { 24111 return false; 24112 } 24113 if (start) { 24114 walker.prev(); 24115 } else { 24116 walker.next(); 24117 } 24118 } 24119 return true; 24120 }; 24121 const insertNewBlockAfter = () => { 24122 let block; 24123 if (/^(H[1-6]|PRE|FIGURE)$/.test(parentBlockName) && containerBlockName !== 'HGROUP') { 24124 block = createNewBlock(newBlockName); 24125 } else { 24126 block = createNewBlock(); 24127 } 24128 if (shouldEndContainer(editor, containerBlock) && canSplitBlock(dom, containerBlock) && dom.isEmpty(parentBlock)) { 24129 block = dom.split(containerBlock, parentBlock); 24130 } else { 24131 dom.insertAfter(block, parentBlock); 24132 } 24133 moveToCaretPosition(editor, block); 24134 return block; 24135 }; 24136 normalize$2(dom, rng).each(normRng => { 24137 rng.setStart(normRng.startContainer, normRng.startOffset); 24138 rng.setEnd(normRng.endContainer, normRng.endOffset); 24139 }); 24140 container = rng.startContainer; 24141 offset = rng.startOffset; 24142 const shiftKey = !!(evt && evt.shiftKey); 24143 const ctrlKey = !!(evt && evt.ctrlKey); 24144 if (isElement$6(container) && container.hasChildNodes()) { 24145 isAfterLastNodeInContainer = offset > container.childNodes.length - 1; 24146 container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container; 24147 if (isAfterLastNodeInContainer && isText$a(container)) { 24148 offset = container.data.length; 24149 } else { 24150 offset = 0; 24151 } 24152 } 24153 const editableRoot = getEditableRoot(dom, container); 24154 if (!editableRoot || isWithinNonEditableList(editor, container)) { 24155 return; 24156 } 24157 if (!shiftKey) { 24158 container = wrapSelfAndSiblingsInDefaultBlock(editor, newBlockName, rng, container, offset); 24159 } 24160 let parentBlock = dom.getParent(container, dom.isBlock) || dom.getRoot(); 24161 containerBlock = isNonNullable(parentBlock === null || parentBlock === void 0 ? void 0 : parentBlock.parentNode) ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null; 24162 parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : ''; 24163 const containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; 24164 if (containerBlockName === 'LI' && !ctrlKey) { 24165 const liBlock = containerBlock; 24166 parentBlock = liBlock; 24167 containerBlock = liBlock.parentNode; 24168 parentBlockName = containerBlockName; 24169 } 24170 if (/^(LI|DT|DD)$/.test(parentBlockName) && isElement$6(containerBlock)) { 24171 if (dom.isEmpty(parentBlock)) { 24172 insert$3(editor, createNewBlock, containerBlock, parentBlock, newBlockName); 24173 return; 24174 } 24175 } 24176 if (parentBlock === editor.getBody() || !canSplitBlock(dom, parentBlock)) { 24177 return; 24178 } 24179 const parentBlockParent = parentBlock.parentNode; 24180 let newBlock; 24181 if (isCaretContainerBlock$1(parentBlock)) { 24182 newBlock = showCaretContainerBlock(parentBlock); 24183 if (dom.isEmpty(parentBlock)) { 24184 emptyBlock(parentBlock); 24185 } 24186 setForcedBlockAttrs(editor, newBlock); 24187 moveToCaretPosition(editor, newBlock); 24188 } else if (isCaretAtStartOrEndOfBlock(false)) { 24189 newBlock = insertNewBlockAfter(); 24190 } else if (isCaretAtStartOrEndOfBlock(true) && parentBlockParent) { 24191 newBlock = parentBlockParent.insertBefore(createNewBlock(), parentBlock); 24192 moveToCaretPosition(editor, containerAndSiblingName(parentBlock, 'HR') ? newBlock : parentBlock); 24193 } else { 24194 const tmpRng = includeZwspInRange(rng).cloneRange(); 24195 tmpRng.setEndAfter(parentBlock); 24196 const fragment = tmpRng.extractContents(); 24197 trimZwsp(fragment); 24198 trimLeadingLineBreaks(fragment); 24199 newBlock = fragment.firstChild; 24200 dom.insertAfter(fragment, parentBlock); 24201 trimInlineElementsOnLeftSideOfBlock(dom, nonEmptyElementsMap, newBlock); 24202 addBrToBlockIfNeeded(dom, parentBlock); 24203 if (dom.isEmpty(parentBlock)) { 24204 emptyBlock(parentBlock); 24205 } 24206 newBlock.normalize(); 24207 if (dom.isEmpty(newBlock)) { 24208 dom.remove(newBlock); 24209 insertNewBlockAfter(); 24210 } else { 24211 setForcedBlockAttrs(editor, newBlock); 24212 moveToCaretPosition(editor, newBlock); 24213 } 24214 } 24215 dom.setAttrib(newBlock, 'id', ''); 24216 editor.dispatch('NewBlock', { newBlock }); 24217 }; 24218 const fakeEventName$1 = 'insertParagraph'; 24219 const blockbreak = { 24220 insert: insert$2, 24221 fakeEventName: fakeEventName$1 24222 }; 24223 24224 const hasRightSideContent = (schema, container, parentBlock) => { 24225 const walker = new DomTreeWalker(container, parentBlock); 24226 let node; 24227 const nonEmptyElementsMap = schema.getNonEmptyElements(); 24228 while (node = walker.next()) { 24229 if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || isText$a(node) && node.length > 0) { 24230 return true; 24231 } 24232 } 24233 return false;
vendor: 9,051 bytes, lines 24234-24487
24234 }; 24235 const moveSelectionToBr = (editor, brElm, extraBr) => { 24236 const rng = editor.dom.createRng(); 24237 if (!extraBr) { 24238 rng.setStartAfter(brElm); 24239 rng.setEndAfter(brElm); 24240 } else { 24241 rng.setStartBefore(brElm); 24242 rng.setEndBefore(brElm); 24243 } 24244 editor.selection.setRng(rng); 24245 scrollRangeIntoView(editor, rng); 24246 }; 24247 const insertBrAtCaret = (editor, evt) => { 24248 const selection = editor.selection; 24249 const dom = editor.dom; 24250 const rng = selection.getRng(); 24251 let brElm; 24252 let extraBr = false; 24253 normalize$2(dom, rng).each(normRng => { 24254 rng.setStart(normRng.startContainer, normRng.startOffset); 24255 rng.setEnd(normRng.endContainer, normRng.endOffset); 24256 }); 24257 let offset = rng.startOffset; 24258 let container = rng.startContainer; 24259 if (isElement$6(container) && container.hasChildNodes()) { 24260 const isAfterLastNodeInContainer = offset > container.childNodes.length - 1; 24261 container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container; 24262 if (isAfterLastNodeInContainer && isText$a(container)) { 24263 offset = container.data.length; 24264 } else { 24265 offset = 0; 24266 } 24267 } 24268 let parentBlock = dom.getParent(container, dom.isBlock); 24269 const containerBlock = parentBlock && parentBlock.parentNode ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null; 24270 const containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; 24271 const isControlKey = !!(evt && evt.ctrlKey); 24272 if (containerBlockName === 'LI' && !isControlKey) { 24273 parentBlock = containerBlock; 24274 } 24275 if (isText$a(container) && offset >= container.data.length) { 24276 if (!hasRightSideContent(editor.schema, container, parentBlock || dom.getRoot())) { 24277 brElm = dom.create('br'); 24278 rng.insertNode(brElm); 24279 rng.setStartAfter(brElm); 24280 rng.setEndAfter(brElm); 24281 extraBr = true; 24282 } 24283 } 24284 brElm = dom.create('br'); 24285 rangeInsertNode(dom, rng, brElm); 24286 moveSelectionToBr(editor, brElm, extraBr); 24287 editor.undoManager.add(); 24288 }; 24289 const insertBrBefore = (editor, inline) => { 24290 const br = SugarElement.fromTag('br'); 24291 before$3(SugarElement.fromDom(inline), br); 24292 editor.undoManager.add(); 24293 }; 24294 const insertBrAfter = (editor, inline) => { 24295 if (!hasBrAfter(editor.getBody(), inline)) { 24296 after$4(SugarElement.fromDom(inline), SugarElement.fromTag('br')); 24297 } 24298 const br = SugarElement.fromTag('br'); 24299 after$4(SugarElement.fromDom(inline), br); 24300 moveSelectionToBr(editor, br.dom, false); 24301 editor.undoManager.add(); 24302 }; 24303 const isBeforeBr = pos => { 24304 return isBr$6(pos.getNode()); 24305 }; 24306 const hasBrAfter = (rootNode, startNode) => { 24307 if (isBeforeBr(CaretPosition.after(startNode))) { 24308 return true; 24309 } else { 24310 return nextPosition(rootNode, CaretPosition.after(startNode)).map(pos => { 24311 return isBr$6(pos.getNode()); 24312 }).getOr(false); 24313 } 24314 }; 24315 const isAnchorLink = elm => { 24316 return elm && elm.nodeName === 'A' && 'href' in elm; 24317 }; 24318 const isInsideAnchor = location => { 24319 return location.fold(never, isAnchorLink, isAnchorLink, never); 24320 }; 24321 const readInlineAnchorLocation = editor => { 24322 const isInlineTarget$1 = curry(isInlineTarget, editor); 24323 const position = CaretPosition.fromRangeStart(editor.selection.getRng()); 24324 return readLocation(isInlineTarget$1, editor.getBody(), position).filter(isInsideAnchor); 24325 }; 24326 const insertBrOutsideAnchor = (editor, location) => { 24327 location.fold(noop, curry(insertBrBefore, editor), curry(insertBrAfter, editor), noop); 24328 }; 24329 const insert$1 = (editor, evt) => { 24330 const anchorLocation = readInlineAnchorLocation(editor); 24331 if (anchorLocation.isSome()) { 24332 anchorLocation.each(curry(insertBrOutsideAnchor, editor)); 24333 } else { 24334 insertBrAtCaret(editor, evt); 24335 } 24336 }; 24337 const fakeEventName = 'insertLineBreak'; 24338 const linebreak = { 24339 insert: insert$1, 24340 fakeEventName 24341 }; 24342 24343 const matchesSelector = (editor, selector) => { 24344 return getParentBlock$1(editor).filter(parentBlock => { 24345 return selector.length > 0 && is$1(SugarElement.fromDom(parentBlock), selector); 24346 }).isSome(); 24347 }; 24348 const shouldInsertBr = editor => { 24349 return matchesSelector(editor, getBrNewLineSelector(editor)); 24350 }; 24351 const shouldBlockNewLine$1 = editor => { 24352 return matchesSelector(editor, getNoNewLineSelector(editor)); 24353 }; 24354 24355 const newLineAction = Adt.generate([ 24356 { br: [] }, 24357 { block: [] }, 24358 { none: [] } 24359 ]); 24360 const shouldBlockNewLine = (editor, _shiftKey) => { 24361 return shouldBlockNewLine$1(editor); 24362 }; 24363 const inListBlock = requiredState => { 24364 return (editor, _shiftKey) => { 24365 return isListItemParentBlock(editor) === requiredState; 24366 }; 24367 }; 24368 const inBlock = (blockName, requiredState) => (editor, _shiftKey) => { 24369 const state = getParentBlockName(editor) === blockName.toUpperCase(); 24370 return state === requiredState; 24371 }; 24372 const inCefBlock = editor => { 24373 const editableRoot = getEditableRoot(editor.dom, editor.selection.getStart()); 24374 return isNullable(editableRoot); 24375 }; 24376 const inPreBlock = requiredState => inBlock('pre', requiredState); 24377 const inSummaryBlock = () => inBlock('summary', true); 24378 const shouldPutBrInPre = requiredState => { 24379 return (editor, _shiftKey) => { 24380 return shouldPutBrInPre$1(editor) === requiredState; 24381 }; 24382 }; 24383 const inBrContext = (editor, _shiftKey) => { 24384 return shouldInsertBr(editor); 24385 }; 24386 const hasShiftKey = (_editor, shiftKey) => { 24387 return shiftKey; 24388 }; 24389 const canInsertIntoEditableRoot = editor => { 24390 const forcedRootBlock = getForcedRootBlock(editor); 24391 const rootEditable = getEditableRoot(editor.dom, editor.selection.getStart()); 24392 return isNonNullable(rootEditable) && editor.schema.isValidChild(rootEditable.nodeName, forcedRootBlock); 24393 }; 24394 const match = (predicates, action) => { 24395 return (editor, shiftKey) => { 24396 const isMatch = foldl(predicates, (res, p) => { 24397 return res && p(editor, shiftKey); 24398 }, true); 24399 return isMatch ? Optional.some(action) : Optional.none(); 24400 }; 24401 }; 24402 const getAction = (editor, evt) => { 24403 return evaluateUntil([ 24404 match([shouldBlockNewLine], newLineAction.none()), 24405 match([ 24406 inPreBlock(true), 24407 inCefBlock 24408 ], newLineAction.none()), 24409 match([inSummaryBlock()], newLineAction.br()), 24410 match([ 24411 inPreBlock(true), 24412 shouldPutBrInPre(false), 24413 hasShiftKey 24414 ], newLineAction.br()), 24415 match([ 24416 inPreBlock(true), 24417 shouldPutBrInPre(false) 24418 ], newLineAction.block()), 24419 match([ 24420 inPreBlock(true), 24421 shouldPutBrInPre(true), 24422 hasShiftKey 24423 ], newLineAction.block()), 24424 match([ 24425 inPreBlock(true), 24426 shouldPutBrInPre(true) 24427 ], newLineAction.br()), 24428 match([ 24429 inListBlock(true), 24430 hasShiftKey 24431 ], newLineAction.br()), 24432 match([inListBlock(true)], newLineAction.block()), 24433 match([inBrContext], newLineAction.br()), 24434 match([hasShiftKey], newLineAction.br()), 24435 match([canInsertIntoEditableRoot], newLineAction.block()) 24436 ], [ 24437 editor, 24438 !!(evt && evt.shiftKey) 24439 ]).getOr(newLineAction.none()); 24440 }; 24441 24442 const insertBreak = (breakType, editor, evt) => { 24443 if (!editor.selection.isCollapsed()) { 24444 execEditorDeleteCommand(editor); 24445 } 24446 if (isNonNullable(evt)) { 24447 const event = fireFakeBeforeInputEvent(editor, breakType.fakeEventName); 24448 if (event.isDefaultPrevented()) { 24449 return; 24450 } 24451 } 24452 breakType.insert(editor, evt); 24453 if (isNonNullable(evt)) { 24454 fireFakeInputEvent(editor, breakType.fakeEventName); 24455 } 24456 }; 24457 const insert = (editor, evt) => { 24458 const br = () => insertBreak(linebreak, editor, evt); 24459 const block = () => insertBreak(blockbreak, editor, evt); 24460 const logicalAction = getAction(editor, evt); 24461 switch (getNewlineBehavior(editor)) { 24462 case 'linebreak': 24463 logicalAction.fold(br, br, noop); 24464 break; 24465 case 'block': 24466 logicalAction.fold(block, block, noop); 24467 break; 24468 case 'invert': 24469 logicalAction.fold(block, br, noop); 24470 break; 24471 default: 24472 logicalAction.fold(br, block, noop); 24473 break; 24474 } 24475 }; 24476 24477 const handleEnterKeyEvent = (editor, event) => { 24478 if (event.isDefaultPrevented()) { 24479 return; 24480 } 24481 event.preventDefault(); 24482 endTypingLevelIgnoreLocks(editor.undoManager); 24483 editor.undoManager.transact(() => { 24484 insert(editor, event); 24485 }); 24486 }; 24487 const setup$h = editor => {
vendor: 5,630 bytes, lines 24488-24649
24488 editor.on('keydown', event => { 24489 if (event.keyCode === VK.ENTER) { 24490 handleEnterKeyEvent(editor, event); 24491 } 24492 }); 24493 }; 24494 24495 const executeKeydownOverride$2 = (editor, caret, evt) => { 24496 const isMac = Env.os.isMacOS() || Env.os.isiOS(); 24497 execute([ 24498 { 24499 keyCode: VK.END, 24500 action: action(moveToLineEndPoint$1, editor, true) 24501 }, 24502 { 24503 keyCode: VK.HOME, 24504 action: action(moveToLineEndPoint$1, editor, false) 24505 }, 24506 ...!isMac ? [ 24507 { 24508 keyCode: VK.HOME, 24509 action: action(selectToEndPoint, editor, false), 24510 ctrlKey: true, 24511 shiftKey: true 24512 }, 24513 { 24514 keyCode: VK.END, 24515 action: action(selectToEndPoint, editor, true), 24516 ctrlKey: true, 24517 shiftKey: true 24518 } 24519 ] : [], 24520 { 24521 keyCode: VK.END, 24522 action: action(moveToLineEndPoint, editor, true) 24523 }, 24524 { 24525 keyCode: VK.HOME, 24526 action: action(moveToLineEndPoint, editor, false) 24527 }, 24528 { 24529 keyCode: VK.END, 24530 action: action(moveToLineEndPoint$2, editor, true, caret) 24531 }, 24532 { 24533 keyCode: VK.HOME, 24534 action: action(moveToLineEndPoint$2, editor, false, caret) 24535 } 24536 ], evt).each(_ => { 24537 evt.preventDefault(); 24538 }); 24539 }; 24540 const setup$g = (editor, caret) => { 24541 editor.on('keydown', evt => { 24542 if (!evt.isDefaultPrevented()) { 24543 executeKeydownOverride$2(editor, caret, evt); 24544 } 24545 }); 24546 }; 24547 24548 const setup$f = editor => { 24549 editor.on('input', e => { 24550 if (!e.isComposing) { 24551 normalizeNbspsInEditor(editor); 24552 } 24553 }); 24554 }; 24555 24556 const platform = detect$2(); 24557 const executeKeyupAction = (editor, caret, evt) => { 24558 execute([ 24559 { 24560 keyCode: VK.PAGE_UP, 24561 action: action(moveToLineEndPoint$2, editor, false, caret) 24562 }, 24563 { 24564 keyCode: VK.PAGE_DOWN, 24565 action: action(moveToLineEndPoint$2, editor, true, caret) 24566 } 24567 ], evt); 24568 }; 24569 const stopImmediatePropagation = e => e.stopImmediatePropagation(); 24570 const isPageUpDown = evt => evt.keyCode === VK.PAGE_UP || evt.keyCode === VK.PAGE_DOWN; 24571 const setNodeChangeBlocker = (blocked, editor, block) => { 24572 if (block && !blocked.get()) { 24573 editor.on('NodeChange', stopImmediatePropagation, true); 24574 } else if (!block && blocked.get()) { 24575 editor.off('NodeChange', stopImmediatePropagation); 24576 } 24577 blocked.set(block); 24578 }; 24579 const setup$e = (editor, caret) => { 24580 if (platform.os.isMacOS()) { 24581 return; 24582 } 24583 const blocked = Cell(false); 24584 editor.on('keydown', evt => { 24585 if (isPageUpDown(evt)) { 24586 setNodeChangeBlocker(blocked, editor, true); 24587 } 24588 }); 24589 editor.on('keyup', evt => { 24590 if (!evt.isDefaultPrevented()) { 24591 executeKeyupAction(editor, caret, evt); 24592 } 24593 if (isPageUpDown(evt) && blocked.get()) { 24594 setNodeChangeBlocker(blocked, editor, false); 24595 editor.nodeChanged(); 24596 } 24597 }); 24598 }; 24599 24600 const insertTextAtPosition = (text, pos) => { 24601 const container = pos.container(); 24602 const offset = pos.offset(); 24603 if (isText$a(container)) { 24604 container.insertData(offset, text); 24605 return Optional.some(CaretPosition(container, offset + text.length)); 24606 } else { 24607 return getElementFromPosition(pos).map(elm => { 24608 const textNode = SugarElement.fromText(text); 24609 if (pos.isAtEnd()) { 24610 after$4(elm, textNode); 24611 } else { 24612 before$3(elm, textNode); 24613 } 24614 return CaretPosition(textNode.dom, text.length); 24615 }); 24616 } 24617 }; 24618 const insertNbspAtPosition = curry(insertTextAtPosition, nbsp); 24619 const insertSpaceAtPosition = curry(insertTextAtPosition, ' '); 24620 24621 const locationToCaretPosition = root => location => location.fold(element => prevPosition(root.dom, CaretPosition.before(element)), element => firstPositionIn(element), element => lastPositionIn(element), element => nextPosition(root.dom, CaretPosition.after(element))); 24622 const insertInlineBoundarySpaceOrNbsp = (root, pos) => checkPos => needsToHaveNbsp(root, checkPos) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos); 24623 const setSelection = editor => pos => { 24624 editor.selection.setRng(pos.toRange()); 24625 editor.nodeChanged(); 24626 return true; 24627 }; 24628 const insertSpaceOrNbspAtSelection = editor => { 24629 const pos = CaretPosition.fromRangeStart(editor.selection.getRng()); 24630 const root = SugarElement.fromDom(editor.getBody()); 24631 if (editor.selection.isCollapsed()) { 24632 const isInlineTarget$1 = curry(isInlineTarget, editor); 24633 const caretPosition = CaretPosition.fromRangeStart(editor.selection.getRng()); 24634 return readLocation(isInlineTarget$1, editor.getBody(), caretPosition).bind(locationToCaretPosition(root)).map(checkPos => () => insertInlineBoundarySpaceOrNbsp(root, pos)(checkPos).each(setSelection(editor))); 24635 } else { 24636 return Optional.none(); 24637 } 24638 }; 24639 24640 const executeKeydownOverride$1 = (editor, evt) => { 24641 executeWithDelayedAction([{ 24642 keyCode: VK.SPACEBAR, 24643 action: action(insertSpaceOrNbspAtSelection, editor) 24644 }], evt).each(applyAction => { 24645 evt.preventDefault(); 24646 const event = fireFakeBeforeInputEvent(editor, 'insertText', { data: ' ' }); 24647 if (!event.isDefaultPrevented()) { 24648 applyAction(); 24649 fireFak
vendor: 4,619 bytes, lines 24649-24801
24649eInputEvent(editor, 'insertText', { data: ' ' }); 24650 } 24651 }); 24652 }; 24653 const setup$d = editor => { 24654 editor.on('keydown', evt => { 24655 if (!evt.isDefaultPrevented()) { 24656 executeKeydownOverride$1(editor, evt); 24657 } 24658 }); 24659 }; 24660 24661 const tableTabNavigation = editor => { 24662 if (hasTableTabNavigation(editor)) { 24663 return [ 24664 { 24665 keyCode: VK.TAB, 24666 action: action(handleTab, editor, true) 24667 }, 24668 { 24669 keyCode: VK.TAB, 24670 shiftKey: true, 24671 action: action(handleTab, editor, false) 24672 } 24673 ]; 24674 } else { 24675 return []; 24676 } 24677 }; 24678 const executeKeydownOverride = (editor, evt) => { 24679 execute([...tableTabNavigation(editor)], evt).each(_ => { 24680 evt.preventDefault(); 24681 }); 24682 }; 24683 const setup$c = editor => { 24684 editor.on('keydown', evt => { 24685 if (!evt.isDefaultPrevented()) { 24686 executeKeydownOverride(editor, evt); 24687 } 24688 }); 24689 }; 24690 24691 const setup$b = editor => { 24692 editor.addShortcut('Meta+P', '', 'mcePrint'); 24693 setup$j(editor); 24694 if (isRtc(editor)) { 24695 return Cell(null); 24696 } else { 24697 const caret = setupSelectedState(editor); 24698 setup$l(editor); 24699 setup$k(editor, caret); 24700 setup$i(editor, caret); 24701 setup$h(editor); 24702 setup$d(editor); 24703 setup$f(editor); 24704 setup$c(editor); 24705 setup$g(editor, caret); 24706 setup$e(editor, caret); 24707 return caret; 24708 } 24709 }; 24710 24711 class NodeChange { 24712 constructor(editor) { 24713 this.lastPath = []; 24714 this.editor = editor; 24715 let lastRng; 24716 const self = this; 24717 if (!('onselectionchange' in editor.getDoc())) { 24718 editor.on('NodeChange click mouseup keyup focus', e => { 24719 const nativeRng = editor.selection.getRng(); 24720 const fakeRng = { 24721 startContainer: nativeRng.startContainer, 24722 startOffset: nativeRng.startOffset, 24723 endContainer: nativeRng.endContainer, 24724 endOffset: nativeRng.endOffset 24725 }; 24726 if (e.type === 'nodechange' || !isEq$4(fakeRng, lastRng)) { 24727 editor.dispatch('SelectionChange'); 24728 } 24729 lastRng = fakeRng; 24730 }); 24731 } 24732 editor.on('contextmenu', () => { 24733 editor.dispatch('SelectionChange'); 24734 }); 24735 editor.on('SelectionChange', () => { 24736 const startElm = editor.selection.getStart(true); 24737 if (!startElm) { 24738 return; 24739 } 24740 if (hasAnyRanges(editor) && !self.isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) { 24741 editor.nodeChanged({ selectionChange: true }); 24742 } 24743 }); 24744 editor.on('mouseup', e => { 24745 if (!e.isDefaultPrevented() && hasAnyRanges(editor)) { 24746 if (editor.selection.getNode().nodeName === 'IMG') { 24747 Delay.setEditorTimeout(editor, () => { 24748 editor.nodeChanged(); 24749 }); 24750 } else { 24751 editor.nodeChanged(); 24752 } 24753 } 24754 }); 24755 } 24756 nodeChanged(args = {}) { 24757 const selection = this.editor.selection; 24758 let node; 24759 if (this.editor.initialized && selection && !shouldDisableNodeChange(this.editor) && !this.editor.mode.isReadOnly()) { 24760 const root = this.editor.getBody(); 24761 node = selection.getStart(true) || root; 24762 if (node.ownerDocument !== this.editor.getDoc() || !this.editor.dom.isChildOf(node, root)) { 24763 node = root; 24764 } 24765 const parents = []; 24766 this.editor.dom.getParent(node, node => { 24767 if (node === root) { 24768 return true; 24769 } else { 24770 parents.push(node); 24771 return false; 24772 } 24773 }); 24774 this.editor.dispatch('NodeChange', { 24775 ...args, 24776 element: node, 24777 parents 24778 }); 24779 } 24780 } 24781 isSameElementPath(startElm) { 24782 let i; 24783 const editor = this.editor; 24784 const currentPath = reverse(editor.dom.getParents(startElm, always, editor.getBody())); 24785 if (currentPath.length === this.lastPath.length) { 24786 for (i = currentPath.length; i >= 0; i--) { 24787 if (currentPath[i] !== this.lastPath[i]) { 24788 break; 24789 } 24790 } 24791 if (i === -1) { 24792 this.lastPath = currentPath; 24793 return true; 24794 } 24795 } 24796 this.lastPath = currentPath; 24797 return false; 24798 } 24799 } 24800 24801 const i
vendor: 45,989 bytes, lines 24801-25959
24801nternalMimeType = 'x-tinymce/html'; 24802 const internalHtmlMime = constant(internalMimeType); 24803 const internalMark = '<!-- ' + internalMimeType + ' -->'; 24804 const mark = html => internalMark + html; 24805 const unmark = html => html.replace(internalMark, ''); 24806 const isMarked = html => html.indexOf(internalMark) !== -1; 24807 24808 const isPlainText = text => { 24809 return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text); 24810 }; 24811 const openContainer = (rootTag, rootAttrs) => { 24812 let tag = '<' + rootTag; 24813 const attrs = mapToArray(rootAttrs, (value, key) => key + '="' + Entities.encodeAllRaw(value) + '"'); 24814 if (attrs.length) { 24815 tag += ' ' + attrs.join(' '); 24816 } 24817 return tag + '>'; 24818 }; 24819 const toBlockElements = (text, rootTag, rootAttrs) => { 24820 const blocks = text.split(/\n\n/); 24821 const tagOpen = openContainer(rootTag, rootAttrs); 24822 const tagClose = '</' + rootTag + '>'; 24823 const paragraphs = map$3(blocks, p => { 24824 return p.split(/\n/).join('<br />'); 24825 }); 24826 const stitch = p => { 24827 return tagOpen + p + tagClose; 24828 }; 24829 return paragraphs.length === 1 ? paragraphs[0] : map$3(paragraphs, stitch).join(''); 24830 }; 24831 24832 const pasteBinDefaultContent = '%MCEPASTEBIN%'; 24833 const create$6 = (editor, lastRngCell) => { 24834 const {dom, selection} = editor; 24835 const body = editor.getBody(); 24836 lastRngCell.set(selection.getRng()); 24837 const pasteBinElm = dom.add(editor.getBody(), 'div', { 24838 'id': 'mcepastebin', 24839 'class': 'mce-pastebin', 24840 'contentEditable': true, 24841 'data-mce-bogus': 'all', 24842 'style': 'position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0' 24843 }, pasteBinDefaultContent); 24844 if (Env.browser.isFirefox()) { 24845 dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 65535 : -65535); 24846 } 24847 dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', e => { 24848 e.stopPropagation(); 24849 }); 24850 pasteBinElm.focus(); 24851 selection.select(pasteBinElm, true); 24852 }; 24853 const remove = (editor, lastRngCell) => { 24854 const dom = editor.dom; 24855 if (getEl(editor)) { 24856 let pasteBinClone; 24857 const lastRng = lastRngCell.get(); 24858 while (pasteBinClone = getEl(editor)) { 24859 dom.remove(pasteBinClone); 24860 dom.unbind(pasteBinClone); 24861 } 24862 if (lastRng) { 24863 editor.selection.setRng(lastRng); 24864 } 24865 } 24866 lastRngCell.set(null); 24867 }; 24868 const getEl = editor => editor.dom.get('mcepastebin'); 24869 const isPasteBin = elm => isNonNullable(elm) && elm.id === 'mcepastebin'; 24870 const getHtml = editor => { 24871 const dom = editor.dom; 24872 const copyAndRemove = (toElm, fromElm) => { 24873 toElm.appendChild(fromElm); 24874 dom.remove(fromElm, true); 24875 }; 24876 const [pasteBinElm, ...pasteBinClones] = filter$5(editor.getBody().childNodes, isPasteBin); 24877 each$e(pasteBinClones, pasteBinClone => { 24878 copyAndRemove(pasteBinElm, pasteBinClone); 24879 }); 24880 const dirtyWrappers = dom.select('div[id=mcepastebin]', pasteBinElm); 24881 for (let i = dirtyWrappers.length - 1; i >= 0; i--) { 24882 const cleanWrapper = dom.create('div'); 24883 pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]); 24884 copyAndRemove(cleanWrapper, dirtyWrappers[i]); 24885 } 24886 return pasteBinElm ? pasteBinElm.innerHTML : ''; 24887 }; 24888 const isDefaultPasteBinContent = content => content === pasteBinDefaultContent; 24889 const PasteBin = editor => { 24890 const lastRng = Cell(null); 24891 return { 24892 create: () => create$6(editor, lastRng), 24893 remove: () => remove(editor, lastRng), 24894 getEl: () => getEl(editor), 24895 getHtml: () => getHtml(editor), 24896 getLastRng: lastRng.get 24897 }; 24898 }; 24899 24900 const filter$1 = (content, items) => { 24901 Tools.each(items, v => { 24902 if (is$4(v, RegExp)) { 24903 content = content.replace(v, ''); 24904 } else { 24905 content = content.replace(v[0], v[1]); 24906 } 24907 }); 24908 return content; 24909 }; 24910 const innerText = html => { 24911 const schema = Schema(); 24912 const domParser = DomParser({}, schema); 24913 let text = ''; 24914 const voidElements = schema.getVoidElements(); 24915 const ignoreElements = Tools.makeMap('script noscript style textarea video audio iframe object', ' '); 24916 const blockElements = schema.getBlockElements(); 24917 const walk = node => { 24918 const name = node.name, currentNode = node; 24919 if (name === 'br') { 24920 text += '\n'; 24921 return; 24922 } 24923 if (name === 'wbr') { 24924 return; 24925 } 24926 if (voidElements[name]) { 24927 text += ' '; 24928 } 24929 if (ignoreElements[name]) { 24930 text += ' '; 24931 return; 24932 } 24933 if (node.type === 3) { 24934 text += node.value; 24935 } 24936 if (!(node.name in schema.getVoidElements())) { 24937 let currentNode = node.firstChild; 24938 if (currentNode) { 24939 do { 24940 walk(currentNode); 24941 } while (currentNode = currentNode.next); 24942 } 24943 } 24944 if (blockElements[name] && currentNode.next) { 24945 text += '\n'; 24946 if (name === 'p') { 24947 text += '\n'; 24948 } 24949 } 24950 }; 24951 html = filter$1(html, [/<!\[[^\]]+\]>/g]); 24952 walk(domParser.parse(html)); 24953 return text; 24954 }; 24955 const trimHtml = html => { 24956 const trimSpaces = (all, s1, s2) => { 24957 if (!s1 && !s2) { 24958 return ' '; 24959 } 24960 return nbsp; 24961 }; 24962 html = filter$1(html, [ 24963 /^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig, 24964 /<!--StartFragment-->|<!--EndFragment-->/g, 24965 [ 24966 /( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g, 24967 trimSpaces 24968 ], 24969 /<br class="Apple-interchange-newline">/g, 24970 /<br>$/i 24971 ]); 24972 return html; 24973 }; 24974 const createIdGenerator = prefix => { 24975 let count = 0; 24976 return () => { 24977 return prefix + count++; 24978 }; 24979 }; 24980 const getImageMimeType = ext => { 24981 const lowerExt = ext.toLowerCase(); 24982 const mimeOverrides = { 24983 jpg: 'jpeg', 24984 jpe: 'jpeg', 24985 jfi: 'jpeg', 24986 jif: 'jpeg', 24987 jfif: 'jpeg', 24988 pjpeg: 'jpeg', 24989 pjp: 'jpeg', 24990 svg: 'svg+xml' 24991 }; 24992 return Tools.hasOwn(mimeOverrides, lowerExt) ? 'image/' + mimeOverrides[lowerExt] : 'image/' + lowerExt; 24993 }; 24994 24995 const preProcess = (editor, html) => { 24996 const parser = DomParser({ sanitize: shouldSanitizeXss(editor) }, editor.schema); 24997 parser.addNodeFilter('meta', nodes => { 24998 Tools.each(nodes, node => { 24999 node.remove(); 25000 }); 25001 }); 25002 const fragment = parser.parse(html, { 25003 forced_root_block: false, 25004 isRootContent: true 25005 }); 25006 return HtmlSerializer({ validate: true }, editor.schema).serialize(fragment); 25007 }; 25008 const processResult = (content, cancelled) => ({ 25009 content, 25010 cancelled 25011 }); 25012 const postProcessFilter = (editor, html, internal) => { 25013 const tempBody = editor.dom.create('div', { style: 'display:none' }, html); 25014 const postProcessArgs = firePastePostProcess(editor, tempBody, internal); 25015 return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented()); 25016 }; 25017 const filterContent = (editor, content, internal) => { 25018 const preProcessArgs = firePastePreProcess(editor, content, internal); 25019 const filteredContent = preProcess(editor, preProcessArgs.content); 25020 if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) { 25021 return postProcessFilter(editor, filteredContent, internal); 25022 } else { 25023 return processResult(filteredContent, preProcessArgs.isDefaultPrevented()); 25024 } 25025 }; 25026 const process = (editor, html, internal) => { 25027 return filterContent(editor, html, internal); 25028 }; 25029 25030 const pasteHtml$1 = (editor, html) => { 25031 editor.insertContent(html, { 25032 merge: shouldPasteMergeFormats(editor), 25033 paste: true 25034 }); 25035 return true; 25036 }; 25037 const isAbsoluteUrl = url => /^https?:\/\/[\w\-\/+=.,!;:&%@^~(){}?#]+$/i.test(url); 25038 const isImageUrl = (editor, url) => { 25039 return isAbsoluteUrl(url) && exists(getAllowedImageFileTypes(editor), type => endsWith(url.toLowerCase(), `.${ type.toLowerCase() }`)); 25040 }; 25041 const createImage = (editor, url, pasteHtmlFn) => { 25042 editor.undoManager.extra(() => { 25043 pasteHtmlFn(editor, url); 25044 }, () => { 25045 editor.insertContent('<img src="' + url + '">'); 25046 }); 25047 return true; 25048 }; 25049 const createLink = (editor, url, pasteHtmlFn) => { 25050 editor.undoManager.extra(() => { 25051 pasteHtmlFn(editor, url); 25052 }, () => { 25053 editor.execCommand('mceInsertLink', false, url); 25054 }); 25055 return true; 25056 }; 25057 const linkSelection = (editor, html, pasteHtmlFn) => !editor.selection.isCollapsed() && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtmlFn) : false; 25058 const insertImage = (editor, html, pasteHtmlFn) => isImageUrl(editor, html) ? createImage(editor, html, pasteHtmlFn) : false; 25059 const smartInsertContent = (editor, html) => { 25060 Tools.each([ 25061 linkSelection, 25062 insertImage, 25063 pasteHtml$1 25064 ], action => { 25065 return !action(editor, html, pasteHtml$1); 25066 }); 25067 }; 25068 const insertContent = (editor, html, pasteAsText) => { 25069 if (pasteAsText || !isSmartPasteEnabled(editor)) { 25070 pasteHtml$1(editor, html); 25071 } else { 25072 smartInsertContent(editor, html); 25073 } 25074 }; 25075 25076 const uniqueId = createIdGenerator('mceclip'); 25077 const doPaste = (editor, content, internal, pasteAsText) => { 25078 const args = process(editor, content, internal); 25079 if (!args.cancelled) { 25080 insertContent(editor, args.content, pasteAsText); 25081 } 25082 }; 25083 const pasteHtml = (editor, html, internalFlag) => { 25084 const internal = internalFlag ? internalFlag : isMarked(html); 25085 doPaste(editor, unmark(html), internal, false); 25086 }; 25087 const pasteText = (editor, text) => { 25088 const encodedText = editor.dom.encode(text).replace(/\r\n/g, '\n'); 25089 const normalizedText = normalize$4(encodedText, getPasteTabSpaces(editor)); 25090 const html = toBlockElements(normalizedText, getForcedRootBlock(editor), getForcedRootBlockAttrs(editor)); 25091 doPaste(editor, html, false, true); 25092 }; 25093 const getDataTransferItems = dataTransfer => { 25094 const items = {}; 25095 if (dataTransfer && dataTransfer.types) { 25096 for (let i = 0; i < dataTransfer.types.length; i++) { 25097 const contentType = dataTransfer.types[i]; 25098 try { 25099 items[contentType] = dataTransfer.getData(contentType); 25100 } catch (ex) { 25101 items[contentType] = ''; 25102 } 25103 } 25104 } 25105 return items; 25106 }; 25107 const hasContentType = (clipboardContent, mimeType) => mimeType in clipboardContent && clipboardContent[mimeType].length > 0; 25108 const hasHtmlOrText = content => hasContentType(content, 'text/html') || hasContentType(content, 'text/plain'); 25109 const extractFilename = (editor, str) => { 25110 const m = str.match(/([\s\S]+?)(?:\.[a-z0-9.]+)$/i); 25111 return isNonNullable(m) ? editor.dom.encode(m[1]) : undefined; 25112 }; 25113 const createBlobInfo = (editor, blobCache, file, base64) => { 25114 const id = uniqueId(); 25115 const useFileName = shouldReuseFileName(editor) && isNonNullable(file.name); 25116 const name = useFileName ? extractFilename(editor, file.name) : id; 25117 const filename = useFileName ? file.name : undefined; 25118 const blobInfo = blobCache.create(id, file, base64, name, filename); 25119 blobCache.add(blobInfo); 25120 return blobInfo; 25121 }; 25122 const pasteImage = (editor, imageItem) => { 25123 parseDataUri(imageItem.uri).each(({data, type, base64Encoded}) => { 25124 const base64 = base64Encoded ? data : btoa(data); 25125 const file = imageItem.file; 25126 const blobCache = editor.editorUpload.blobCache; 25127 const existingBlobInfo = blobCache.getByData(base64, type); 25128 const blobInfo = existingBlobInfo !== null && existingBlobInfo !== void 0 ? existingBlobInfo : createBlobInfo(editor, blobCache, file, base64); 25129 pasteHtml(editor, `<img src="${ blobInfo.blobUri() }">`, false); 25130 }); 25131 }; 25132 const isClipboardEvent = event => event.type === 'paste'; 25133 const readFilesAsDataUris = items => Promise.all(map$3(items, file => { 25134 return blobToDataUri(file).then(uri => ({ 25135 file, 25136 uri 25137 })); 25138 })); 25139 const isImage = editor => { 25140 const allowedExtensions = getAllowedImageFileTypes(editor); 25141 return file => startsWith(file.type, 'image/') && exists(allowedExtensions, extension => { 25142 return getImageMimeType(extension) === file.type; 25143 }); 25144 }; 25145 const getImagesFromDataTransfer = (editor, dataTransfer) => { 25146 const items = dataTransfer.items ? bind$3(from(dataTransfer.items), item => { 25147 return item.kind === 'file' ? [item.getAsFile()] : []; 25148 }) : []; 25149 const files = dataTransfer.files ? from(dataTransfer.files) : []; 25150 return filter$5(items.length > 0 ? items : files, isImage(editor)); 25151 }; 25152 const pasteImageData = (editor, e, rng) => { 25153 const dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer; 25154 if (shouldPasteDataImages(editor) && dataTransfer) { 25155 const images = getImagesFromDataTransfer(editor, dataTransfer); 25156 if (images.length > 0) { 25157 e.preventDefault(); 25158 readFilesAsDataUris(images).then(fileResults => { 25159 if (rng) { 25160 editor.selection.setRng(rng); 25161 } 25162 each$e(fileResults, result => { 25163 pasteImage(editor, result); 25164 }); 25165 }); 25166 return true; 25167 } 25168 } 25169 return false; 25170 }; 25171 const isBrokenAndroidClipboardEvent = e => { 25172 var _a, _b; 25173 return Env.os.isAndroid() && ((_b = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.items) === null || _b === void 0 ? void 0 : _b.length) === 0; 25174 }; 25175 const isKeyboardPasteEvent = e => VK.metaKeyPressed(e) && e.keyCode === 86 || e.shiftKey && e.keyCode === 45; 25176 const insertClipboardContent = (editor, clipboardContent, html, plainTextMode) => { 25177 let content = trimHtml(html); 25178 const isInternal = hasContentType(clipboardContent, internalHtmlMime()) || isMarked(html); 25179 const isPlainTextHtml = !isInternal && isPlainText(content); 25180 const isAbsoluteUrl$1 = isAbsoluteUrl(content); 25181 if (isDefaultPasteBinContent(content) || !content.length || isPlainTextHtml && !isAbsoluteUrl$1) { 25182 plainTextMode = true; 25183 } 25184 if (plainTextMode || isAbsoluteUrl$1) { 25185 if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) { 25186 content = clipboardContent['text/plain']; 25187 } else { 25188 content = innerText(content); 25189 } 25190 } 25191 if (isDefaultPasteBinContent(content)) { 25192 return; 25193 } 25194 if (plainTextMode) { 25195 pasteText(editor, content); 25196 } else { 25197 pasteHtml(editor, content, isInternal); 25198 } 25199 }; 25200 const registerEventHandlers = (editor, pasteBin, pasteFormat) => { 25201 let keyboardPastePlainTextState; 25202 const getLastRng = () => pasteBin.getLastRng() || editor.selection.getRng(); 25203 editor.on('keydown', e => { 25204 if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { 25205 keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86; 25206 } 25207 }); 25208 editor.on('paste', e => { 25209 if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) { 25210 return; 25211 } 25212 const plainTextMode = pasteFormat.get() === 'text' || keyboardPastePlainTextState; 25213 keyboardPastePlainTextState = false; 25214 const clipboardContent = getDataTransferItems(e.clipboardData); 25215 if (!hasHtmlOrText(clipboardContent) && pasteImageData(editor, e, getLastRng())) { 25216 return; 25217 } 25218 if (hasContentType(clipboardContent, 'text/html')) { 25219 e.preventDefault(); 25220 insertClipboardContent(editor, clipboardContent, clipboardContent['text/html'], plainTextMode); 25221 } else if (hasContentType(clipboardContent, 'text/plain') && hasContentType(clipboardContent, 'text/uri-list')) { 25222 e.preventDefault(); 25223 insertClipboardContent(editor, clipboardContent, clipboardContent['text/plain'], plainTextMode); 25224 } else { 25225 pasteBin.create(); 25226 Delay.setEditorTimeout(editor, () => { 25227 const html = pasteBin.getHtml(); 25228 pasteBin.remove(); 25229 insertClipboardContent(editor, clipboardContent, html, plainTextMode); 25230 }, 0); 25231 } 25232 }); 25233 }; 25234 const registerDataImageFilter = editor => { 25235 const isWebKitFakeUrl = src => startsWith(src, 'webkit-fake-url'); 25236 const isDataUri = src => startsWith(src, 'data:'); 25237 const isPasteInsert = args => { 25238 var _a; 25239 return ((_a = args.data) === null || _a === void 0 ? void 0 : _a.paste) === true; 25240 }; 25241 editor.parser.addNodeFilter('img', (nodes, name, args) => { 25242 if (!shouldPasteDataImages(editor) && isPasteInsert(args)) { 25243 for (const node of nodes) { 25244 const src = node.attr('src'); 25245 if (isString(src) && !node.attr('data-mce-object') && src !== Env.transparentSrc) { 25246 if (isWebKitFakeUrl(src)) { 25247 node.remove(); 25248 } else if (!shouldAllowHtmlDataUrls(editor) && isDataUri(src)) { 25249 node.remove(); 25250 } 25251 } 25252 } 25253 } 25254 }); 25255 }; 25256 const registerEventsAndFilters = (editor, pasteBin, pasteFormat) => { 25257 registerEventHandlers(editor, pasteBin, pasteFormat); 25258 registerDataImageFilter(editor); 25259 }; 25260 25261 const togglePlainTextPaste = (editor, pasteFormat) => { 25262 if (pasteFormat.get() === 'text') { 25263 pasteFormat.set('html'); 25264 firePastePlainTextToggle(editor, false); 25265 } else { 25266 pasteFormat.set('text'); 25267 firePastePlainTextToggle(editor, true); 25268 } 25269 editor.focus(); 25270 }; 25271 const register$1 = (editor, pasteFormat) => { 25272 editor.addCommand('mceTogglePlainTextPaste', () => { 25273 togglePlainTextPaste(editor, pasteFormat); 25274 }); 25275 editor.addCommand('mceInsertClipboardContent', (ui, value) => { 25276 if (value.html) { 25277 pasteHtml(editor, value.html, value.internal); 25278 } 25279 if (value.text) { 25280 pasteText(editor, value.text); 25281 } 25282 }); 25283 }; 25284 25285 const setHtml5Clipboard = (clipboardData, html, text) => { 25286 if (clipboardData) { 25287 try { 25288 clipboardData.clearData(); 25289 clipboardData.setData('text/html', html); 25290 clipboardData.setData('text/plain', text); 25291 clipboardData.setData(internalHtmlMime(), html); 25292 return true; 25293 } catch (e) { 25294 return false; 25295 } 25296 } else { 25297 return false; 25298 } 25299 }; 25300 const setClipboardData = (evt, data, fallback, done) => { 25301 if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) { 25302 evt.preventDefault(); 25303 done(); 25304 } else { 25305 fallback(data.html, done); 25306 } 25307 }; 25308 const fallback$1 = editor => (html, done) => { 25309 const {dom, selection} = editor; 25310 const outer = dom.create('div', { 25311 'contenteditable': 'false', 25312 'data-mce-bogus': 'all' 25313 }); 25314 const inner = dom.create('div', { contenteditable: 'true' }, html); 25315 dom.setStyles(outer, { 25316 position: 'fixed', 25317 top: '0', 25318 left: '-3000px', 25319 width: '1000px', 25320 overflow: 'hidden' 25321 }); 25322 outer.appendChild(inner); 25323 dom.add(editor.getBody(), outer); 25324 const range = selection.getRng(); 25325 inner.focus(); 25326 const offscreenRange = dom.createRng(); 25327 offscreenRange.selectNodeContents(inner); 25328 selection.setRng(offscreenRange); 25329 Delay.setEditorTimeout(editor, () => { 25330 selection.setRng(range); 25331 dom.remove(outer); 25332 done(); 25333 }, 0); 25334 }; 25335 const getData = editor => ({ 25336 html: mark(editor.selection.getContent({ contextual: true })), 25337 text: editor.selection.getContent({ format: 'text' }) 25338 }); 25339 const isTableSelection = editor => !!editor.dom.getParent(editor.selection.getStart(), 'td[data-mce-selected],th[data-mce-selected]', editor.getBody()); 25340 const hasSelectedContent = editor => !editor.selection.isCollapsed() || isTableSelection(editor); 25341 const cut = editor => evt => { 25342 if (!evt.isDefaultPrevented() && hasSelectedContent(editor)) { 25343 setClipboardData(evt, getData(editor), fallback$1(editor), () => { 25344 if (Env.browser.isChromium() || Env.browser.isFirefox()) { 25345 const rng = editor.selection.getRng(); 25346 Delay.setEditorTimeout(editor, () => { 25347 editor.selection.setRng(rng); 25348 editor.execCommand('Delete'); 25349 }, 0); 25350 } else { 25351 editor.execCommand('Delete'); 25352 } 25353 }); 25354 } 25355 }; 25356 const copy = editor => evt => { 25357 if (!evt.isDefaultPrevented() && hasSelectedContent(editor)) { 25358 setClipboardData(evt, getData(editor), fallback$1(editor), noop); 25359 } 25360 }; 25361 const register = editor => { 25362 editor.on('cut', cut(editor)); 25363 editor.on('copy', copy(editor)); 25364 }; 25365 25366 const getCaretRangeFromEvent = (editor, e) => { 25367 var _a, _b; 25368 return RangeUtils.getCaretRangeFromPoint((_a = e.clientX) !== null && _a !== void 0 ? _a : 0, (_b = e.clientY) !== null && _b !== void 0 ? _b : 0, editor.getDoc()); 25369 }; 25370 const isPlainTextFileUrl = content => { 25371 const plainTextContent = content['text/plain']; 25372 return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false; 25373 }; 25374 const setFocusedRange = (editor, rng) => { 25375 editor.focus(); 25376 if (rng) { 25377 editor.selection.setRng(rng); 25378 } 25379 }; 25380 const hasImage = dataTransfer => exists(dataTransfer.files, file => /^image\//.test(file.type)); 25381 const isTransparentBlockDrop = (dom, schema, target, dropContent) => { 25382 const parentTransparent = dom.getParent(target, node => isTransparentBlock(schema, node)); 25383 if (parentTransparent && has$2(dropContent, 'text/html')) { 25384 const fragment = new DOMParser().parseFromString(dropContent['text/html'], 'text/html').body; 25385 return !isNull(fragment.querySelector(parentTransparent.nodeName.toLowerCase())); 25386 } else { 25387 return false; 25388 } 25389 }; 25390 const setup$a = (editor, draggingInternallyState) => { 25391 if (shouldPasteBlockDrop(editor)) { 25392 editor.on('dragend dragover draggesture dragdrop drop drag', e => { 25393 e.preventDefault(); 25394 e.stopPropagation(); 25395 }); 25396 } 25397 if (!shouldPasteDataImages(editor)) { 25398 editor.on('drop', e => { 25399 const dataTransfer = e.dataTransfer; 25400 if (dataTransfer && hasImage(dataTransfer)) { 25401 e.preventDefault(); 25402 } 25403 }); 25404 } 25405 editor.on('drop', e => { 25406 if (e.isDefaultPrevented()) { 25407 return; 25408 } 25409 const rng = getCaretRangeFromEvent(editor, e); 25410 if (isNullable(rng)) { 25411 return; 25412 } 25413 const dropContent = getDataTransferItems(e.dataTransfer); 25414 const internal = hasContentType(dropContent, internalHtmlMime()); 25415 if ((!hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && pasteImageData(editor, e, rng)) { 25416 return; 25417 } 25418 const internalContent = dropContent[internalHtmlMime()]; 25419 const content = internalContent || dropContent['text/html'] || dropContent['text/plain']; 25420 const transparentElementDrop = isTransparentBlockDrop(editor.dom, editor.schema, rng.startContainer, dropContent); 25421 if (draggingInternallyState.get() && !transparentElementDrop) { 25422 return; 25423 } 25424 if (content) { 25425 e.preventDefault(); 25426 Delay.setEditorTimeout(editor, () => { 25427 editor.undoManager.transact(() => { 25428 if (internalContent) { 25429 editor.execCommand('Delete'); 25430 } 25431 setFocusedRange(editor, rng); 25432 const trimmedContent = trimHtml(content); 25433 if (dropContent['text/html']) { 25434 pasteHtml(editor, trimmedContent, internal); 25435 } else { 25436 pasteText(editor, trimmedContent); 25437 } 25438 }); 25439 }); 25440 } 25441 }); 25442 editor.on('dragstart', _e => { 25443 draggingInternallyState.set(true); 25444 }); 25445 editor.on('dragover dragend', e => { 25446 if (shouldPasteDataImages(editor) && !draggingInternallyState.get()) { 25447 e.preventDefault(); 25448 setFocusedRange(editor, getCaretRangeFromEvent(editor, e)); 25449 } 25450 if (e.type === 'dragend') { 25451 draggingInternallyState.set(false); 25452 } 25453 }); 25454 }; 25455 25456 const setup$9 = editor => { 25457 const processEvent = f => e => { 25458 f(editor, e); 25459 }; 25460 const preProcess = getPastePreProcess(editor); 25461 if (isFunction(preProcess)) { 25462 editor.on('PastePreProcess', processEvent(preProcess)); 25463 } 25464 const postProcess = getPastePostProcess(editor); 25465 if (isFunction(postProcess)) { 25466 editor.on('PastePostProcess', processEvent(postProcess)); 25467 } 25468 }; 25469 25470 const addPreProcessFilter = (editor, filterFunc) => { 25471 editor.on('PastePreProcess', e => { 25472 e.content = filterFunc(editor, e.content, e.internal); 25473 }); 25474 }; 25475 const rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi; 25476 const rgbToHex = value => Tools.trim(value).replace(rgbRegExp, rgbaToHexString).toLowerCase(); 25477 const removeWebKitStyles = (editor, content, internal) => { 25478 const webKitStylesOption = getPasteWebkitStyles(editor); 25479 if (internal || webKitStylesOption === 'all' || !shouldPasteRemoveWebKitStyles(editor)) { 25480 return content; 25481 } 25482 const webKitStyles = webKitStylesOption ? webKitStylesOption.split(/[, ]/) : []; 25483 if (webKitStyles && webKitStylesOption !== 'none') { 25484 const dom = editor.dom, node = editor.selection.getNode(); 25485 content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, (all, before, value, after) => { 25486 const inputStyles = dom.parseStyle(dom.decode(value)); 25487 const outputStyles = {}; 25488 for (let i = 0; i < webKitStyles.length; i++) { 25489 const inputValue = inputStyles[webKitStyles[i]]; 25490 let compareInput = inputValue; 25491 let currentValue = dom.getStyle(node, webKitStyles[i], true); 25492 if (/color/.test(webKitStyles[i])) { 25493 compareInput = rgbToHex(compareInput); 25494 currentValue = rgbToHex(currentValue); 25495 } 25496 if (currentValue !== compareInput) { 25497 outputStyles[webKitStyles[i]] = inputValue; 25498 } 25499 } 25500 const outputStyle = dom.serializeStyle(outputStyles, 'span'); 25501 if (outputStyle) { 25502 return before + ' style="' + outputStyle + '"' + after; 25503 } 25504 return before + after; 25505 }); 25506 } else { 25507 content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3'); 25508 } 25509 content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, (all, before, value, after) => { 25510 return before + ' style="' + value + '"' + after; 25511 }); 25512 return content; 25513 }; 25514 const setup$8 = editor => { 25515 if (Env.browser.isChromium() || Env.browser.isSafari()) { 25516 addPreProcessFilter(editor, removeWebKitStyles); 25517 } 25518 }; 25519 25520 const setup$7 = editor => { 25521 const draggingInternallyState = Cell(false); 25522 const pasteFormat = Cell(isPasteAsTextEnabled(editor) ? 'text' : 'html'); 25523 const pasteBin = PasteBin(editor); 25524 setup$8(editor); 25525 register$1(editor, pasteFormat); 25526 setup$9(editor); 25527 editor.on('PreInit', () => { 25528 register(editor); 25529 setup$a(editor, draggingInternallyState); 25530 registerEventsAndFilters(editor, pasteBin, pasteFormat); 25531 }); 25532 }; 25533 25534 const preventSummaryToggle = editor => { 25535 editor.on('click', e => { 25536 if (editor.dom.getParent(e.target, 'details')) { 25537 e.preventDefault(); 25538 } 25539 }); 25540 }; 25541 const filterDetails = editor => { 25542 editor.parser.addNodeFilter('details', elms => { 25543 each$e(elms, details => { 25544 details.attr('data-mce-open', details.attr('open')); 25545 details.attr('open', 'open'); 25546 }); 25547 }); 25548 editor.serializer.addNodeFilter('details', elms => { 25549 each$e(elms, details => { 25550 const open = details.attr('data-mce-open'); 25551 details.attr('open', isString(open) ? open : null); 25552 details.attr('data-mce-open', null); 25553 }); 25554 }); 25555 }; 25556 const setup$6 = editor => { 25557 preventSummaryToggle(editor); 25558 filterDetails(editor); 25559 }; 25560 25561 const isBr = isBr$6; 25562 const isText = isText$a; 25563 const isContentEditableFalse$2 = elm => isContentEditableFalse$b(elm.dom); 25564 const isContentEditableTrue = elm => isContentEditableTrue$3(elm.dom); 25565 const isRoot = rootNode => elm => eq(SugarElement.fromDom(rootNode), elm); 25566 const getClosestScope = (node, rootNode) => closest$4(SugarElement.fromDom(node), elm => isContentEditableTrue(elm) || isBlock$2(elm), isRoot(rootNode)).getOr(SugarElement.fromDom(rootNode)).dom; 25567 const getClosestCef = (node, rootNode) => closest$4(SugarElement.fromDom(node), isContentEditableFalse$2, isRoot(rootNode)); 25568 const findEdgeCaretCandidate = (startNode, scope, forward) => { 25569 const walker = new DomTreeWalker(startNode, scope); 25570 const next = forward ? walker.next.bind(walker) : walker.prev.bind(walker); 25571 let result = startNode; 25572 for (let current = forward ? startNode : next(); current && !isBr(current); current = next()) { 25573 if (isCaretCandidate$3(current)) { 25574 result = current; 25575 } 25576 } 25577 return result; 25578 }; 25579 const findClosestBlockRange = (startRng, rootNode) => { 25580 const startPos = CaretPosition.fromRangeStart(startRng); 25581 const clickNode = startPos.getNode(); 25582 const scope = getClosestScope(clickNode, rootNode); 25583 const startNode = findEdgeCaretCandidate(clickNode, scope, false); 25584 const endNode = findEdgeCaretCandidate(clickNode, scope, true); 25585 const rng = document.createRange(); 25586 getClosestCef(startNode, scope).fold(() => { 25587 if (isText(startNode)) { 25588 rng.setStart(startNode, 0); 25589 } else { 25590 rng.setStartBefore(startNode); 25591 } 25592 }, cef => rng.setStartBefore(cef.dom)); 25593 getClosestCef(endNode, scope).fold(() => { 25594 if (isText(endNode)) { 25595 rng.setEnd(endNode, endNode.data.length); 25596 } else { 25597 rng.setEndAfter(endNode); 25598 } 25599 }, cef => rng.setEndAfter(cef.dom)); 25600 return rng; 25601 }; 25602 const onTripleClickSelect = editor => { 25603 const rng = findClosestBlockRange(editor.selection.getRng(), editor.getBody()); 25604 editor.selection.setRng(normalize(rng)); 25605 }; 25606 const setup$5 = editor => { 25607 editor.on('mousedown', e => { 25608 if (e.detail >= 3) { 25609 e.preventDefault(); 25610 onTripleClickSelect(editor); 25611 } 25612 }); 25613 }; 25614 25615 var FakeCaretPosition; 25616 (function (FakeCaretPosition) { 25617 FakeCaretPosition['Before'] = 'before'; 25618 FakeCaretPosition['After'] = 'after'; 25619 }(FakeCaretPosition || (FakeCaretPosition = {}))); 25620 const distanceToRectLeft = (clientRect, clientX) => Math.abs(clientRect.left - clientX); 25621 const distanceToRectRight = (clientRect, clientX) => Math.abs(clientRect.right - clientX); 25622 const isInsideY = (clientY, clientRect) => clientY >= clientRect.top && clientY <= clientRect.bottom; 25623 const collidesY = (r1, r2) => r1.top < r2.bottom && r1.bottom > r2.top; 25624 const isOverlapping = (r1, r2) => { 25625 const overlap = overlapY(r1, r2) / Math.min(r1.height, r2.height); 25626 return collidesY(r1, r2) && overlap > 0.5; 25627 }; 25628 const splitRectsPerAxis = (rects, y) => { 25629 const intersectingRects = filter$5(rects, rect => isInsideY(y, rect)); 25630 return boundingClientRectFromRects(intersectingRects).fold(() => [ 25631 [], 25632 rects 25633 ], boundingRect => { 25634 const { 25635 pass: horizontal, 25636 fail: vertical 25637 } = partition$2(rects, rect => isOverlapping(rect, boundingRect)); 25638 return [ 25639 horizontal, 25640 vertical 25641 ]; 25642 }); 25643 }; 25644 const clientInfo = (rect, clientX) => { 25645 return { 25646 node: rect.node, 25647 position: distanceToRectLeft(rect, clientX) < distanceToRectRight(rect, clientX) ? FakeCaretPosition.Before : FakeCaretPosition.After 25648 }; 25649 }; 25650 const horizontalDistance = (rect, x, _y) => x > rect.left && x < rect.right ? 0 : Math.min(Math.abs(rect.left - x), Math.abs(rect.right - x)); 25651 const closestChildCaretCandidateNodeRect = (children, clientX, clientY) => { 25652 const caretCandidateRect = rect => { 25653 if (isCaretCandidate$3(rect.node)) { 25654 return Optional.some(rect); 25655 } else if (isElement$6(rect.node)) { 25656 return closestChildCaretCandidateNodeRect(from(rect.node.childNodes), clientX, clientY); 25657 } else { 25658 return Optional.none(); 25659 } 25660 }; 25661 const getClosestTextNode = (rects, distance) => { 25662 if (rects.length >= 2) { 25663 const r1 = caretCandidateRect(rects[0]).getOr(rects[0]); 25664 const r2 = caretCandidateRect(rects[1]).getOr(rects[1]); 25665 const deltaDistance = Math.abs(distance(r1, clientX, clientY) - distance(r2, clientX, clientY)); 25666 if (deltaDistance < 2) { 25667 if (isText$a(r1.node)) { 25668 return Optional.some(r1); 25669 } else if (isText$a(r2.node)) { 25670 return Optional.some(r2); 25671 } 25672 } 25673 } 25674 return Optional.none(); 25675 }; 25676 const findClosestCaretCandidateNodeRect = (rects, distance) => { 25677 const sortedRects = sort(rects, (r1, r2) => distance(r1, clientX, clientY) - distance(r2, clientX, clientY)); 25678 return getClosestTextNode(sortedRects, distance).orThunk(() => findMap(sortedRects, caretCandidateRect)); 25679 }; 25680 const [horizontalRects, verticalRects] = splitRectsPerAxis(getClientRects(children), clientY); 25681 const { 25682 pass: above, 25683 fail: below 25684 } = partition$2(verticalRects, rect => rect.top < clientY); 25685 return findClosestCaretCandidateNodeRect(horizontalRects, horizontalDistance).orThunk(() => findClosestCaretCandidateNodeRect(below, distanceToRectEdgeFromXY)).orThunk(() => findClosestCaretCandidateNodeRect(above, distanceToRectEdgeFromXY)); 25686 }; 25687 const traverseUp = (rootElm, scope, clientX, clientY) => { 25688 const helper = (scope, prevScope) => { 25689 const isDragGhostContainer = node => isElement$6(node) && node.classList.contains('mce-drag-container'); 25690 const childNodesWithoutGhost = filter$5(scope.dom.childNodes, not(isDragGhostContainer)); 25691 return prevScope.fold(() => closestChildCaretCandidateNodeRect(childNodesWithoutGhost, clientX, clientY), prevScope => { 25692 const uncheckedChildren = filter$5(childNodesWithoutGhost, node => node !== prevScope.dom); 25693 return closestChildCaretCandidateNodeRect(uncheckedChildren, clientX, clientY); 25694 }).orThunk(() => { 25695 const parent = eq(scope, rootElm) ? Optional.none() : parentElement(scope); 25696 return parent.bind(newScope => helper(newScope, Optional.some(scope))); 25697 }); 25698 }; 25699 return helper(scope, Optional.none()); 25700 }; 25701 const closestCaretCandidateNodeRect = (root, clientX, clientY) => { 25702 const rootElm = SugarElement.fromDom(root); 25703 const ownerDoc = documentOrOwner(rootElm); 25704 const elementAtPoint = SugarElement.fromPoint(ownerDoc, clientX, clientY).filter(elm => contains(rootElm, elm)); 25705 const element = elementAtPoint.getOr(rootElm); 25706 return traverseUp(rootElm, element, clientX, clientY); 25707 }; 25708 const closestFakeCaretCandidate = (root, clientX, clientY) => closestCaretCandidateNodeRect(root, clientX, clientY).filter(rect => isFakeCaretTarget(rect.node)).map(rect => clientInfo(rect, clientX)); 25709 25710 const getAbsolutePosition = elm => { 25711 var _a, _b; 25712 const clientRect = elm.getBoundingClientRect(); 25713 const doc = elm.ownerDocument; 25714 const docElem = doc.documentElement; 25715 const win = doc.defaultView; 25716 return { 25717 top: clientRect.top + ((_a = win === null || win === void 0 ? void 0 : win.scrollY) !== null && _a !== void 0 ? _a : 0) - docElem.clientTop, 25718 left: clientRect.left + ((_b = win === null || win === void 0 ? void 0 : win.scrollX) !== null && _b !== void 0 ? _b : 0) - docElem.clientLeft 25719 }; 25720 }; 25721 const getBodyPosition = editor => editor.inline ? getAbsolutePosition(editor.getBody()) : { 25722 left: 0, 25723 top: 0 25724 }; 25725 const getScrollPosition = editor => { 25726 const body = editor.getBody(); 25727 return editor.inline ? { 25728 left: body.scrollLeft, 25729 top: body.scrollTop 25730 } : { 25731 left: 0, 25732 top: 0 25733 }; 25734 }; 25735 const getBodyScroll = editor => { 25736 const body = editor.getBody(), docElm = editor.getDoc().documentElement; 25737 const inlineScroll = { 25738 left: body.scrollLeft, 25739 top: body.scrollTop 25740 }; 25741 const iframeScroll = { 25742 left: body.scrollLeft || docElm.scrollLeft, 25743 top: body.scrollTop || docElm.scrollTop 25744 }; 25745 return editor.inline ? inlineScroll : iframeScroll; 25746 }; 25747 const getMousePosition = (editor, event) => { 25748 if (event.target.ownerDocument !== editor.getDoc()) { 25749 const iframePosition = getAbsolutePosition(editor.getContentAreaContainer()); 25750 const scrollPosition = getBodyScroll(editor); 25751 return { 25752 left: event.pageX - iframePosition.left + scrollPosition.left, 25753 top: event.pageY - iframePosition.top + scrollPosition.top 25754 }; 25755 } 25756 return { 25757 left: event.pageX, 25758 top: event.pageY 25759 }; 25760 }; 25761 const calculatePosition = (bodyPosition, scrollPosition, mousePosition) => ({ 25762 pageX: mousePosition.left - bodyPosition.left + scrollPosition.left, 25763 pageY: mousePosition.top - bodyPosition.top + scrollPosition.top 25764 }); 25765 const calc = (editor, event) => calculatePosition(getBodyPosition(editor), getScrollPosition(editor), getMousePosition(editor, event)); 25766 25767 const makeDndEventFromMouseEvent = (type, mouseEvent, extra) => ({ 25768 ...mouseEvent, 25769 dataTransfer: null, 25770 type, 25771 ...extra 25772 }); 25773 const makeDndEvent = (type, props) => { 25774 const fail = die('Function not supported on simulated event.'); 25775 const event = { 25776 bubbles: true, 25777 cancelBubble: false, 25778 cancelable: true, 25779 composed: false, 25780 currentTarget: null, 25781 defaultPrevented: false, 25782 eventPhase: 0, 25783 isTrusted: true, 25784 returnValue: false, 25785 srcElement: null, 25786 target: null, 25787 timeStamp: 0, 25788 type, 25789 composedPath: fail, 25790 initEvent: fail, 25791 preventDefault: noop, 25792 stopImmediatePropagation: noop, 25793 stopPropagation: noop, 25794 AT_TARGET: window.Event.AT_TARGET, 25795 BUBBLING_PHASE: window.Event.BUBBLING_PHASE, 25796 CAPTURING_PHASE: window.Event.CAPTURING_PHASE, 25797 NONE: window.Event.NONE, 25798 altKey: false, 25799 button: 0, 25800 buttons: 0, 25801 clientX: 0, 25802 clientY: 0, 25803 ctrlKey: false, 25804 metaKey: false, 25805 movementX: 0, 25806 movementY: 0, 25807 offsetX: 0, 25808 offsetY: 0, 25809 pageX: 0, 25810 pageY: 0, 25811 relatedTarget: null, 25812 screenX: 0, 25813 screenY: 0, 25814 shiftKey: false, 25815 x: 0, 25816 y: 0, 25817 detail: 0, 25818 view: null, 25819 which: 0, 25820 initUIEvent: fail, 25821 initMouseEvent: fail, 25822 getModifierState: fail, 25823 dataTransfer: null, 25824 ...props 25825 }; 25826 return event; 25827 }; 25828 const fallback = target => ({ 25829 target, 25830 srcElement: target 25831 }); 25832 const dndEvent = type => target => makeDndEvent(type, fallback(target)); 25833 const dndEventFromMouseEvent = type => (mouseEvent, target) => makeDndEventFromMouseEvent(type, mouseEvent, fallback(target)); 25834 const makeDragstartEventFromMouseEvent = dndEventFromMouseEvent('dragstart'); 25835 const makeDropEventFromMouseEvent = dndEventFromMouseEvent('drop'); 25836 const makeDragendEvent = dndEvent('dragend'); 25837 const makeDragendEventFromMouseEvent = dndEventFromMouseEvent('dragend'); 25838 25839 const scrollPixelsPerInterval = 32; 25840 const scrollIntervalValue = 100; 25841 const mouseRangeToTriggerScrollInsideEditor = 8; 25842 const mouseRangeToTriggerScrollOutsideEditor = 16; 25843 const isContentEditableFalse$1 = isContentEditableFalse$b; 25844 const isContentEditable = or(isContentEditableFalse$1, isContentEditableTrue$3); 25845 const isDraggable = (dom, rootElm, elm) => isContentEditableFalse$1(elm) && elm !== rootElm && dom.isEditable(elm.parentElement); 25846 const isValidDropTarget = (editor, targetElement, dragElement) => { 25847 if (isNullable(targetElement)) { 25848 return false; 25849 } else if (targetElement === dragElement || editor.dom.isChildOf(targetElement, dragElement)) { 25850 return false; 25851 } else { 25852 return editor.dom.isEditable(targetElement); 25853 } 25854 }; 25855 const cloneElement = elm => { 25856 const cloneElm = elm.cloneNode(true); 25857 cloneElm.removeAttribute('data-mce-selected'); 25858 return cloneElm; 25859 }; 25860 const createGhost = (editor, elm, width, height) => { 25861 const dom = editor.dom; 25862 const clonedElm = elm.cloneNode(true); 25863 dom.setStyles(clonedElm, { 25864 width, 25865 height 25866 }); 25867 dom.setAttrib(clonedElm, 'data-mce-selected', null); 25868 const ghostElm = dom.create('div', { 25869 'class': 'mce-drag-container', 25870 'data-mce-bogus': 'all', 25871 'unselectable': 'on', 25872 'contenteditable': 'false' 25873 }); 25874 dom.setStyles(ghostElm, { 25875 position: 'absolute', 25876 opacity: 0.5, 25877 overflow: 'hidden', 25878 border: 0, 25879 padding: 0, 25880 margin: 0, 25881 width, 25882 height 25883 }); 25884 dom.setStyles(clonedElm, { 25885 margin: 0, 25886 boxSizing: 'border-box' 25887 }); 25888 ghostElm.appendChild(clonedElm); 25889 return ghostElm; 25890 }; 25891 const appendGhostToBody = (ghostElm, bodyElm) => { 25892 if (ghostElm.parentNode !== bodyElm) { 25893 bodyElm.appendChild(ghostElm); 25894 } 25895 }; 25896 const scrollEditor = (direction, amount) => win => () => { 25897 const current = direction === 'left' ? win.scrollX : win.scrollY; 25898 win.scroll({ 25899 [direction]: current + amount, 25900 behavior: 'smooth' 25901 }); 25902 }; 25903 const scrollLeft = scrollEditor('left', -scrollPixelsPerInterval); 25904 const scrollRight = scrollEditor('left', scrollPixelsPerInterval); 25905 const scrollUp = scrollEditor('top', -scrollPixelsPerInterval); 25906 const scrollDown = scrollEditor('top', scrollPixelsPerInterval); 25907 const moveGhost = (ghostElm, position, width, height, maxX, maxY, mouseY, mouseX, contentAreaContainer, win, state, mouseEventOriginatedFromWithinTheEditor) => { 25908 let overflowX = 0, overflowY = 0; 25909 ghostElm.style.left = position.pageX + 'px'; 25910 ghostElm.style.top = position.pageY + 'px'; 25911 if (position.pageX + width > maxX) { 25912 overflowX = position.pageX + width - maxX; 25913 } 25914 if (position.pageY + height > maxY) { 25915 overflowY = position.pageY + height - maxY; 25916 } 25917 ghostElm.style.width = width - overflowX + 'px'; 25918 ghostElm.style.height = height - overflowY + 'px'; 25919 const clientHeight = contentAreaContainer.clientHeight; 25920 const clientWidth = contentAreaContainer.clientWidth; 25921 const outerMouseY = mouseY + contentAreaContainer.getBoundingClientRect().top; 25922 const outerMouseX = mouseX + contentAreaContainer.getBoundingClientRect().left; 25923 state.on(state => { 25924 state.intervalId.clear(); 25925 if (state.dragging && mouseEventOriginatedFromWithinTheEditor) { 25926 if (mouseY + mouseRangeToTriggerScrollInsideEditor >= clientHeight) { 25927 state.intervalId.set(scrollDown(win)); 25928 } else if (mouseY - mouseRangeToTriggerScrollInsideEditor <= 0) { 25929 state.intervalId.set(scrollUp(win)); 25930 } else if (mouseX + mouseRangeToTriggerScrollInsideEditor >= clientWidth) { 25931 state.intervalId.set(scrollRight(win)); 25932 } else if (mouseX - mouseRangeToTriggerScrollInsideEditor <= 0) { 25933 state.intervalId.set(scrollLeft(win)); 25934 } else if (outerMouseY + mouseRangeToTriggerScrollOutsideEditor >= window.innerHeight) { 25935 state.intervalId.set(scrollDown(window)); 25936 } else if (outerMouseY - mouseRangeToTriggerScrollOutsideEditor <= 0) { 25937 state.intervalId.set(scrollUp(window)); 25938 } else if (outerMouseX + mouseRangeToTriggerScrollOutsideEditor >= window.innerWidth) { 25939 state.intervalId.set(scrollRight(window)); 25940 } else if (outerMouseX - mouseRangeToTriggerScrollOutsideEditor <= 0) { 25941 state.intervalId.set(scrollLeft(window)); 25942 } 25943 } 25944 }); 25945 }; 25946 const removeElement = elm => { 25947 if (elm && elm.parentNode) { 25948 elm.parentNode.removeChild(elm); 25949 } 25950 }; 25951 const removeElementWithPadding = (dom, elm) => { 25952 const parentBlock = dom.getParent(elm.parentNode, dom.isBlock); 25953 removeElement(elm); 25954 if (parentBlock && parentBlock !== dom.getRoot() && dom.isEmpty(parentBlock)) { 25955 fillWithPaddingBr(SugarElement.fromDom(parentBlock)); 25956 } 25957 }; 25958 const isLeftMouseButtonPressed = e => e.button === 0; 25959 const applyRelPos = (state, position) => ({
vendor: 4,642 bytes, lines 25960-26058
25960 pageX: position.pageX - state.relX, 25961 pageY: position.pageY + 5 25962 }); 25963 const start = (state, editor) => e => { 25964 if (isLeftMouseButtonPressed(e)) { 25965 const ceElm = find$2(editor.dom.getParents(e.target), isContentEditable).getOr(null); 25966 if (isNonNullable(ceElm) && isDraggable(editor.dom, editor.getBody(), ceElm)) { 25967 const elmPos = editor.dom.getPos(ceElm); 25968 const bodyElm = editor.getBody(); 25969 const docElm = editor.getDoc().documentElement; 25970 state.set({ 25971 element: ceElm, 25972 dragging: false, 25973 screenX: e.screenX, 25974 screenY: e.screenY, 25975 maxX: (editor.inline ? bodyElm.scrollWidth : docElm.offsetWidth) - 2, 25976 maxY: (editor.inline ? bodyElm.scrollHeight : docElm.offsetHeight) - 2, 25977 relX: e.pageX - elmPos.x, 25978 relY: e.pageY - elmPos.y, 25979 width: ceElm.offsetWidth, 25980 height: ceElm.offsetHeight, 25981 ghost: createGhost(editor, ceElm, ceElm.offsetWidth, ceElm.offsetHeight), 25982 intervalId: repeatable(scrollIntervalValue) 25983 }); 25984 } 25985 } 25986 }; 25987 const placeCaretAt = (editor, clientX, clientY) => { 25988 editor._selectionOverrides.hideFakeCaret(); 25989 closestFakeCaretCandidate(editor.getBody(), clientX, clientY).fold(() => editor.selection.placeCaretAt(clientX, clientY), caretInfo => { 25990 const range = editor._selectionOverrides.showCaret(1, caretInfo.node, caretInfo.position === FakeCaretPosition.Before, false); 25991 if (range) { 25992 editor.selection.setRng(range); 25993 } else { 25994 editor.selection.placeCaretAt(clientX, clientY); 25995 } 25996 }); 25997 }; 25998 const move = (state, editor) => { 25999 const throttledPlaceCaretAt = first$1((clientX, clientY) => placeCaretAt(editor, clientX, clientY), 0); 26000 editor.on('remove', throttledPlaceCaretAt.cancel); 26001 const state_ = state; 26002 return e => state.on(state => { 26003 const movement = Math.max(Math.abs(e.screenX - state.screenX), Math.abs(e.screenY - state.screenY)); 26004 if (!state.dragging && movement > 10) { 26005 const args = editor.dispatch('dragstart', makeDragstartEventFromMouseEvent(e, state.element)); 26006 if (args.isDefaultPrevented()) { 26007 return; 26008 } 26009 state.dragging = true; 26010 editor.focus(); 26011 } 26012 if (state.dragging) { 26013 const mouseEventOriginatedFromWithinTheEditor = e.currentTarget === editor.getDoc().documentElement; 26014 const targetPos = applyRelPos(state, calc(editor, e)); 26015 appendGhostToBody(state.ghost, editor.getBody()); 26016 moveGhost(state.ghost, targetPos, state.width, state.height, state.maxX, state.maxY, e.clientY, e.clientX, editor.getContentAreaContainer(), editor.getWin(), state_, mouseEventOriginatedFromWithinTheEditor); 26017 throttledPlaceCaretAt.throttle(e.clientX, e.clientY); 26018 } 26019 }); 26020 }; 26021 const getRawTarget = selection => { 26022 const sel = selection.getSel(); 26023 if (isNonNullable(sel)) { 26024 const rng = sel.getRangeAt(0); 26025 const startContainer = rng.startContainer; 26026 return isText$a(startContainer) ? startContainer.parentNode : startContainer; 26027 } else { 26028 return null; 26029 } 26030 }; 26031 const drop = (state, editor) => e => { 26032 state.on(state => { 26033 var _a; 26034 state.intervalId.clear(); 26035 if (state.dragging) { 26036 if (isValidDropTarget(editor, getRawTarget(editor.selection), state.element)) { 26037 const targetClone = cloneElement(state.element); 26038 const dropTarget = (_a = editor.getDoc().elementFromPoint(e.clientX, e.clientY)) !== null && _a !== void 0 ? _a : editor.getBody(); 26039 const args = editor.dispatch('drop', makeDropEventFromMouseEvent(e, dropTarget)); 26040 if (!args.isDefaultPrevented()) { 26041 editor.undoManager.transact(() => { 26042 removeElementWithPadding(editor.dom, state.element); 26043 editor.insertContent(editor.dom.getOuterHTML(targetClone)); 26044 editor._selectionOverrides.hideFakeCaret(); 26045 }); 26046 } 26047 } 26048 editor.dispatch('dragend', makeDragendEventFromMouseEvent(e, editor.getBody())); 26049 } 26050 }); 26051 removeDragState(state); 26052 }; 26053 const stopDragging = (state, editor, e) => { 26054 state.on(state => { 26055 state.intervalId.clear(); 26056 if (state.dragging) { 26057 const event = e.fold(() => makeDragendEvent(state.element), mouseEvent => makeDragendEventFromMouseEvent(mouseEvent, state.element)); 26058 editor.dispatch('dragend', event
vendor: 11,921 bytes, lines 26058-26368
26058); 26059 } 26060 }); 26061 removeDragState(state); 26062 }; 26063 const stop = (state, editor) => e => stopDragging(state, editor, Optional.some(e)); 26064 const removeDragState = state => { 26065 state.on(state => { 26066 state.intervalId.clear(); 26067 removeElement(state.ghost); 26068 }); 26069 state.clear(); 26070 }; 26071 const bindFakeDragEvents = editor => { 26072 const state = value$2(); 26073 const pageDom = DOMUtils.DOM; 26074 const rootDocument = document; 26075 const dragStartHandler = start(state, editor); 26076 const dragHandler = move(state, editor); 26077 const dropHandler = drop(state, editor); 26078 const dragEndHandler = stop(state, editor); 26079 editor.on('mousedown', dragStartHandler); 26080 editor.on('mousemove', dragHandler); 26081 editor.on('mouseup', dropHandler); 26082 pageDom.bind(rootDocument, 'mousemove', dragHandler); 26083 pageDom.bind(rootDocument, 'mouseup', dragEndHandler); 26084 editor.on('remove', () => { 26085 pageDom.unbind(rootDocument, 'mousemove', dragHandler); 26086 pageDom.unbind(rootDocument, 'mouseup', dragEndHandler); 26087 }); 26088 editor.on('keydown', e => { 26089 if (e.keyCode === VK.ESC) { 26090 stopDragging(state, editor, Optional.none()); 26091 } 26092 }); 26093 }; 26094 const blockUnsupportedFileDrop = editor => { 26095 const preventFileDrop = e => { 26096 if (!e.isDefaultPrevented()) { 26097 const dataTransfer = e.dataTransfer; 26098 if (dataTransfer && (contains$2(dataTransfer.types, 'Files') || dataTransfer.files.length > 0)) { 26099 e.preventDefault(); 26100 if (e.type === 'drop') { 26101 displayError(editor, 'Dropped file type is not supported'); 26102 } 26103 } 26104 } 26105 }; 26106 const preventFileDropIfUIElement = e => { 26107 if (isUIElement(editor, e.target)) { 26108 preventFileDrop(e); 26109 } 26110 }; 26111 const setup = () => { 26112 const pageDom = DOMUtils.DOM; 26113 const dom = editor.dom; 26114 const doc = document; 26115 const editorRoot = editor.inline ? editor.getBody() : editor.getDoc(); 26116 const eventNames = [ 26117 'drop', 26118 'dragover' 26119 ]; 26120 each$e(eventNames, name => { 26121 pageDom.bind(doc, name, preventFileDropIfUIElement); 26122 dom.bind(editorRoot, name, preventFileDrop); 26123 }); 26124 editor.on('remove', () => { 26125 each$e(eventNames, name => { 26126 pageDom.unbind(doc, name, preventFileDropIfUIElement); 26127 dom.unbind(editorRoot, name, preventFileDrop); 26128 }); 26129 }); 26130 }; 26131 editor.on('init', () => { 26132 Delay.setEditorTimeout(editor, setup, 0); 26133 }); 26134 }; 26135 const init$2 = editor => { 26136 bindFakeDragEvents(editor); 26137 if (shouldBlockUnsupportedDrop(editor)) { 26138 blockUnsupportedFileDrop(editor); 26139 } 26140 }; 26141 26142 const setup$4 = editor => { 26143 const renderFocusCaret = first$1(() => { 26144 if (!editor.removed && editor.getBody().contains(document.activeElement)) { 26145 const rng = editor.selection.getRng(); 26146 if (rng.collapsed) { 26147 const caretRange = renderRangeCaret(editor, rng, false); 26148 editor.selection.setRng(caretRange); 26149 } 26150 } 26151 }, 0); 26152 editor.on('focus', () => { 26153 renderFocusCaret.throttle(); 26154 }); 26155 editor.on('blur', () => { 26156 renderFocusCaret.cancel(); 26157 }); 26158 }; 26159 26160 const setup$3 = editor => { 26161 editor.on('init', () => { 26162 editor.on('focusin', e => { 26163 const target = e.target; 26164 if (isMedia$2(target)) { 26165 const ceRoot = getContentEditableRoot$1(editor.getBody(), target); 26166 const node = isContentEditableFalse$b(ceRoot) ? ceRoot : target; 26167 if (editor.selection.getNode() !== node) { 26168 selectNode(editor, node).each(rng => editor.selection.setRng(rng)); 26169 } 26170 } 26171 }); 26172 }); 26173 }; 26174 26175 const isContentEditableFalse = isContentEditableFalse$b; 26176 const getContentEditableRoot = (editor, node) => getContentEditableRoot$1(editor.getBody(), node); 26177 const SelectionOverrides = editor => { 26178 const selection = editor.selection, dom = editor.dom; 26179 const rootNode = editor.getBody(); 26180 const fakeCaret = FakeCaret(editor, rootNode, dom.isBlock, () => hasFocus(editor)); 26181 const realSelectionId = 'sel-' + dom.uniqueId(); 26182 const elementSelectionAttr = 'data-mce-selected'; 26183 let selectedElement; 26184 const isFakeSelectionElement = node => isNonNullable(node) && dom.hasClass(node, 'mce-offscreen-selection'); 26185 const isFakeSelectionTargetElement = node => node !== rootNode && (isContentEditableFalse(node) || isMedia$2(node)) && dom.isChildOf(node, rootNode) && dom.isEditable(node.parentNode); 26186 const setRange = range => { 26187 if (range) { 26188 selection.setRng(range); 26189 } 26190 }; 26191 const showCaret = (direction, node, before, scrollIntoView = true) => { 26192 const e = editor.dispatch('ShowCaret', { 26193 target: node, 26194 direction, 26195 before 26196 }); 26197 if (e.isDefaultPrevented()) { 26198 return null; 26199 } 26200 if (scrollIntoView) { 26201 selection.scrollIntoView(node, direction === -1); 26202 } 26203 return fakeCaret.show(before, node); 26204 }; 26205 const showBlockCaretContainer = blockCaretContainer => { 26206 if (blockCaretContainer.hasAttribute('data-mce-caret')) { 26207 showCaretContainerBlock(blockCaretContainer); 26208 selection.scrollIntoView(blockCaretContainer); 26209 } 26210 }; 26211 const registerEvents = () => { 26212 editor.on('click', e => { 26213 if (!dom.isEditable(e.target)) { 26214 e.preventDefault(); 26215 editor.focus(); 26216 } 26217 }); 26218 editor.on('blur NewBlock', removeElementSelection); 26219 editor.on('ResizeWindow FullscreenStateChanged', fakeCaret.reposition); 26220 editor.on('tap', e => { 26221 const targetElm = e.target; 26222 const contentEditableRoot = getContentEditableRoot(editor, targetElm); 26223 if (isContentEditableFalse(contentEditableRoot)) { 26224 e.preventDefault(); 26225 selectNode(editor, contentEditableRoot).each(setElementSelection); 26226 } else if (isFakeSelectionTargetElement(targetElm)) { 26227 selectNode(editor, targetElm).each(setElementSelection); 26228 } 26229 }, true); 26230 editor.on('mousedown', e => { 26231 const targetElm = e.target; 26232 if (targetElm !== rootNode && targetElm.nodeName !== 'HTML' && !dom.isChildOf(targetElm, rootNode)) { 26233 return; 26234 } 26235 if (!isXYInContentArea(editor, e.clientX, e.clientY)) { 26236 return; 26237 } 26238 removeElementSelection(); 26239 hideFakeCaret(); 26240 const closestContentEditable = getContentEditableRoot(editor, targetElm); 26241 if (isContentEditableFalse(closestContentEditable)) { 26242 e.preventDefault(); 26243 selectNode(editor, closestContentEditable).each(setElementSelection); 26244 } else { 26245 closestFakeCaretCandidate(rootNode, e.clientX, e.clientY).each(caretInfo => { 26246 e.preventDefault(); 26247 const range = showCaret(1, caretInfo.node, caretInfo.position === FakeCaretPosition.Before, false); 26248 setRange(range); 26249 if (isElement$6(closestContentEditable)) { 26250 closestContentEditable.focus(); 26251 } else { 26252 editor.getBody().focus(); 26253 } 26254 }); 26255 } 26256 }); 26257 editor.on('keypress', e => { 26258 if (VK.modifierPressed(e)) { 26259 return; 26260 } 26261 if (isContentEditableFalse(selection.getNode())) { 26262 e.preventDefault(); 26263 } 26264 }); 26265 editor.on('GetSelectionRange', e => { 26266 let rng = e.range; 26267 if (selectedElement) { 26268 if (!selectedElement.parentNode) { 26269 selectedElement = null; 26270 return; 26271 } 26272 rng = rng.cloneRange(); 26273 rng.selectNode(selectedElement); 26274 e.range = rng; 26275 } 26276 }); 26277 editor.on('SetSelectionRange', e => { 26278 e.range = normalizeVoidElementSelection(e.range); 26279 const rng = setElementSelection(e.range, e.forward); 26280 if (rng) { 26281 e.range = rng; 26282 } 26283 }); 26284 const isPasteBin = node => isElement$6(node) && node.id === 'mcepastebin'; 26285 editor.on('AfterSetSelectionRange', e => { 26286 const rng = e.range; 26287 const parent = rng.startContainer.parentElement; 26288 if (!isRangeInCaretContainer(rng) && !isPasteBin(parent)) { 26289 hideFakeCaret(); 26290 } 26291 if (!isFakeSelectionElement(parent)) { 26292 removeElementSelection(); 26293 } 26294 }); 26295 init$2(editor); 26296 setup$4(editor); 26297 setup$3(editor); 26298 }; 26299 const isWithinCaretContainer = node => isCaretContainer$2(node) || startsWithCaretContainer$1(node) || endsWithCaretContainer$1(node); 26300 const isRangeInCaretContainer = rng => isWithinCaretContainer(rng.startContainer) || isWithinCaretContainer(rng.endContainer); 26301 const normalizeVoidElementSelection = rng => { 26302 const voidElements = editor.schema.getVoidElements(); 26303 const newRng = dom.createRng(); 26304 const startContainer = rng.startContainer; 26305 const startOffset = rng.startOffset; 26306 const endContainer = rng.endContainer; 26307 const endOffset = rng.endOffset; 26308 if (has$2(voidElements, startContainer.nodeName.toLowerCase())) { 26309 if (startOffset === 0) { 26310 newRng.setStartBefore(startContainer); 26311 } else { 26312 newRng.setStartAfter(startContainer); 26313 } 26314 } else { 26315 newRng.setStart(startContainer, startOffset); 26316 } 26317 if (has$2(voidElements, endContainer.nodeName.toLowerCase())) { 26318 if (endOffset === 0) { 26319 newRng.setEndBefore(endContainer); 26320 } else { 26321 newRng.setEndAfter(endContainer); 26322 } 26323 } else { 26324 newRng.setEnd(endContainer, endOffset); 26325 } 26326 return newRng; 26327 }; 26328 const setupOffscreenSelection = (node, targetClone) => { 26329 const body = SugarElement.fromDom(editor.getBody()); 26330 const doc = editor.getDoc(); 26331 const realSelectionContainer = descendant(body, '#' + realSelectionId).getOrThunk(() => { 26332 const newContainer = SugarElement.fromHtml('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>', doc); 26333 set$3(newContainer, 'id', realSelectionId); 26334 append$1(body, newContainer); 26335 return newContainer; 26336 }); 26337 const newRange = dom.createRng(); 26338 empty(realSelectionContainer); 26339 append(realSelectionContainer, [ 26340 SugarElement.fromText(nbsp, doc), 26341 SugarElement.fromDom(targetClone), 26342 SugarElement.fromText(nbsp, doc) 26343 ]); 26344 newRange.setStart(realSelectionContainer.dom.firstChild, 1); 26345 newRange.setEnd(realSelectionContainer.dom.lastChild, 0); 26346 setAll(realSelectionContainer, { top: dom.getPos(node, editor.getBody()).y + 'px' }); 26347 focus$1(realSelectionContainer); 26348 const sel = selection.getSel(); 26349 if (sel) { 26350 sel.removeAllRanges(); 26351 sel.addRange(newRange); 26352 } 26353 return newRange; 26354 }; 26355 const selectElement = elm => { 26356 const targetClone = elm.cloneNode(true); 26357 const e = editor.dispatch('ObjectSelected', { 26358 target: elm, 26359 targetClone 26360 }); 26361 if (e.isDefaultPrevented()) { 26362 return null; 26363 } 26364 const range = setupOffscreenSelection(elm, e.targetClone); 26365 const nodeElm = SugarElement.fromDom(elm); 26366 each$e(descendants(SugarElement.fromDom(editor.getBody()), `*[${ elementSelectionAttr }]`), elm => { 26367 if (!eq(nodeElm, elm)) { 26368 remove$
26368b(elm, elementSelectionAttr); 26369 } 26370 }); 26371 if (!dom.getAttrib(elm, elementSelectionAttr)) { 26372 elm.setAttribute(elementSelectionAttr, '1'); 26373 } 26374 selectedElement = elm; 26375 hideFakeCaret(); 26376 return range; 26377 }; 26378 const setElementSelection = (range, forward) => { 26379 if (!range) { 26380 return null; 26381 } 26382 if (range.collapsed) { 26383 if (!isRangeInCaretContainer(range)) { 26384 const dir = forward ? 1 : -1; 26385 const caretPosition = getNormalizedRangeEndPoint(dir, rootNode, range); 26386 const beforeNode = caretPosition.getNode(!forward); 26387 if (isNonNullable(beforeNode)) { 26388 if (isFakeCaretTarget(beforeNode)) { 26389 return showCaret(dir, beforeNode, forward ? !caretPosition.isAt
vendor: 1,997 bytes, lines 26389-26436
26389End() : false, false); 26390 } 26391 if (isCaretContainerInline(beforeNode) && isContentEditableFalse$b(beforeNode.nextSibling)) { 26392 const rng = dom.createRng(); 26393 rng.setStart(beforeNode, 0); 26394 rng.setEnd(beforeNode, 0); 26395 return rng; 26396 } 26397 } 26398 const afterNode = caretPosition.getNode(forward); 26399 if (isNonNullable(afterNode)) { 26400 if (isFakeCaretTarget(afterNode)) { 26401 return showCaret(dir, afterNode, forward ? false : !caretPosition.isAtEnd(), false); 26402 } 26403 if (isCaretContainerInline(afterNode) && isContentEditableFalse$b(afterNode.previousSibling)) { 26404 const rng = dom.createRng(); 26405 rng.setStart(afterNode, 1); 26406 rng.setEnd(afterNode, 1); 26407 return rng; 26408 } 26409 } 26410 } 26411 return null; 26412 } 26413 let startContainer = range.startContainer; 26414 let startOffset = range.startOffset; 26415 const endOffset = range.endOffset; 26416 if (isText$a(startContainer) && startOffset === 0 && isContentEditableFalse(startContainer.parentNode)) { 26417 startContainer = startContainer.parentNode; 26418 startOffset = dom.nodeIndex(startContainer); 26419 startContainer = startContainer.parentNode; 26420 } 26421 if (!isElement$6(startContainer)) { 26422 return null; 26423 } 26424 if (endOffset === startOffset + 1 && startContainer === range.endContainer) { 26425 const node = startContainer.childNodes[startOffset]; 26426 if (isFakeSelectionTargetElement(node)) { 26427 return selectElement(node); 26428 } 26429 } 26430 return null; 26431 }; 26432 const removeElementSelection = () => { 26433 if (selectedElement) { 26434 selectedElement.removeAttribute(elementSelectionAttr); 26435 } 26436 descendant(SugarElement.fromDom(editor.getBody()), '#' + realSelectionId).each(remove$6
vendor: 35,575 bytes, lines 26436-27328
26436); 26437 selectedElement = null; 26438 }; 26439 const destroy = () => { 26440 fakeCaret.destroy(); 26441 selectedElement = null; 26442 }; 26443 const hideFakeCaret = () => { 26444 fakeCaret.hide(); 26445 }; 26446 if (!isRtc(editor)) { 26447 registerEvents(); 26448 } 26449 return { 26450 showCaret, 26451 showBlockCaretContainer, 26452 hideFakeCaret, 26453 destroy 26454 }; 26455 }; 26456 26457 const getNormalizedTextOffset = (container, offset) => { 26458 let normalizedOffset = offset; 26459 for (let node = container.previousSibling; isText$a(node); node = node.previousSibling) { 26460 normalizedOffset += node.data.length; 26461 } 26462 return normalizedOffset; 26463 }; 26464 const generatePath = (dom, root, node, offset, normalized) => { 26465 if (isText$a(node) && (offset < 0 || offset > node.data.length)) { 26466 return []; 26467 } 26468 const p = normalized && isText$a(node) ? [getNormalizedTextOffset(node, offset)] : [offset]; 26469 let current = node; 26470 while (current !== root && current.parentNode) { 26471 p.push(dom.nodeIndex(current, normalized)); 26472 current = current.parentNode; 26473 } 26474 return current === root ? p.reverse() : []; 26475 }; 26476 const generatePathRange = (dom, root, startNode, startOffset, endNode, endOffset, normalized = false) => { 26477 const start = generatePath(dom, root, startNode, startOffset, normalized); 26478 const end = generatePath(dom, root, endNode, endOffset, normalized); 26479 return { 26480 start, 26481 end 26482 }; 26483 }; 26484 const resolvePath = (root, path) => { 26485 const nodePath = path.slice(); 26486 const offset = nodePath.pop(); 26487 if (!isNumber(offset)) { 26488 return Optional.none(); 26489 } else { 26490 const resolvedNode = foldl(nodePath, (optNode, index) => optNode.bind(node => Optional.from(node.childNodes[index])), Optional.some(root)); 26491 return resolvedNode.bind(node => { 26492 if (isText$a(node) && (offset < 0 || offset > node.data.length)) { 26493 return Optional.none(); 26494 } else { 26495 return Optional.some({ 26496 node, 26497 offset 26498 }); 26499 } 26500 }); 26501 } 26502 }; 26503 const resolvePathRange = (root, range) => resolvePath(root, range.start).bind(({ 26504 node: startNode, 26505 offset: startOffset 26506 }) => resolvePath(root, range.end).map(({ 26507 node: endNode, 26508 offset: endOffset 26509 }) => { 26510 const rng = document.createRange(); 26511 rng.setStart(startNode, startOffset); 26512 rng.setEnd(endNode, endOffset); 26513 return rng; 26514 })); 26515 const generatePathRangeFromRange = (dom, root, range, normalized = false) => generatePathRange(dom, root, range.startContainer, range.startOffset, range.endContainer, range.endOffset, normalized); 26516 26517 const cleanEmptyNodes = (dom, node, isRoot) => { 26518 if (node && dom.isEmpty(node) && !isRoot(node)) { 26519 const parent = node.parentNode; 26520 dom.remove(node); 26521 cleanEmptyNodes(dom, parent, isRoot); 26522 } 26523 }; 26524 const deleteRng = (dom, rng, isRoot, clean = true) => { 26525 const startParent = rng.startContainer.parentNode; 26526 const endParent = rng.endContainer.parentNode; 26527 rng.deleteContents(); 26528 if (clean && !isRoot(rng.startContainer)) { 26529 if (isText$a(rng.startContainer) && rng.startContainer.data.length === 0) { 26530 dom.remove(rng.startContainer); 26531 } 26532 if (isText$a(rng.endContainer) && rng.endContainer.data.length === 0) { 26533 dom.remove(rng.endContainer); 26534 } 26535 cleanEmptyNodes(dom, startParent, isRoot); 26536 if (startParent !== endParent) { 26537 cleanEmptyNodes(dom, endParent, isRoot); 26538 } 26539 } 26540 }; 26541 const getParentBlock = (editor, rng) => Optional.from(editor.dom.getParent(rng.startContainer, editor.dom.isBlock)); 26542 const resolveFromDynamicPatterns = (patternSet, block, beforeText) => { 26543 const dynamicPatterns = patternSet.dynamicPatternsLookup({ 26544 text: beforeText, 26545 block 26546 }); 26547 return { 26548 ...patternSet, 26549 blockPatterns: getBlockPatterns(dynamicPatterns).concat(patternSet.blockPatterns), 26550 inlinePatterns: getInlinePatterns(dynamicPatterns).concat(patternSet.inlinePatterns) 26551 }; 26552 }; 26553 const getBeforeText = (dom, block, node, offset) => { 26554 const rng = dom.createRng(); 26555 rng.setStart(block, 0); 26556 rng.setEnd(node, offset); 26557 return rng.toString(); 26558 }; 26559 26560 const startsWithSingleSpace = s => /^\s[^\s]/.test(s); 26561 const stripPattern = (dom, block, pattern) => { 26562 const firstTextNode = textAfter(block, 0, block); 26563 firstTextNode.each(spot => { 26564 const node = spot.container; 26565 scanRight(node, pattern.start.length, block).each(end => { 26566 const rng = dom.createRng(); 26567 rng.setStart(node, 0); 26568 rng.setEnd(end.container, end.offset); 26569 deleteRng(dom, rng, e => e === block); 26570 }); 26571 const text = SugarElement.fromDom(node); 26572 const textContent = get$3(text); 26573 if (startsWithSingleSpace(textContent)) { 26574 set(text, textContent.slice(1)); 26575 } 26576 }); 26577 }; 26578 const applyPattern$1 = (editor, match) => { 26579 const dom = editor.dom; 26580 const pattern = match.pattern; 26581 const rng = resolvePathRange(dom.getRoot(), match.range).getOrDie('Unable to resolve path range'); 26582 const isBlockFormatName = (name, formatter) => { 26583 const formatSet = formatter.get(name); 26584 return isArray$1(formatSet) && head(formatSet).exists(format => has$2(format, 'block')); 26585 }; 26586 getParentBlock(editor, rng).each(block => { 26587 if (pattern.type === 'block-format') { 26588 if (isBlockFormatName(pattern.format, editor.formatter)) { 26589 editor.undoManager.transact(() => { 26590 stripPattern(editor.dom, block, pattern); 26591 editor.formatter.apply(pattern.format); 26592 }); 26593 } 26594 } else if (pattern.type === 'block-command') { 26595 editor.undoManager.transact(() => { 26596 stripPattern(editor.dom, block, pattern); 26597 editor.execCommand(pattern.cmd, false, pattern.value); 26598 }); 26599 } 26600 }); 26601 return true; 26602 }; 26603 const sortPatterns$1 = patterns => sort(patterns, (a, b) => b.start.length - a.start.length); 26604 const findPattern$1 = (patterns, text) => { 26605 const sortedPatterns = sortPatterns$1(patterns); 26606 const nuText = text.replace(nbsp, ' '); 26607 return find$2(sortedPatterns, pattern => text.indexOf(pattern.start) === 0 || nuText.indexOf(pattern.start) === 0); 26608 }; 26609 const findPatterns$1 = (editor, block, patternSet, normalizedMatches) => { 26610 var _a; 26611 const dom = editor.dom; 26612 const forcedRootBlock = getForcedRootBlock(editor); 26613 if (!dom.is(block, forcedRootBlock)) { 26614 return []; 26615 } 26616 const blockText = (_a = block.textContent) !== null && _a !== void 0 ? _a : ''; 26617 return findPattern$1(patternSet.blockPatterns, blockText).map(pattern => { 26618 if (Tools.trim(blockText).length === pattern.start.length) { 26619 return []; 26620 } 26621 return [{ 26622 pattern, 26623 range: generatePathRange(dom, dom.getRoot(), block, 0, block, 0, normalizedMatches) 26624 }]; 26625 }).getOr([]); 26626 }; 26627 const applyMatches$1 = (editor, matches) => { 26628 if (matches.length === 0) { 26629 return; 26630 } 26631 const bookmark = editor.selection.getBookmark(); 26632 each$e(matches, match => applyPattern$1(editor, match)); 26633 editor.selection.moveToBookmark(bookmark); 26634 }; 26635 26636 const newMarker = (dom, id) => dom.create('span', { 26637 'data-mce-type': 'bookmark', 26638 id 26639 }); 26640 const rangeFromMarker = (dom, marker) => { 26641 const rng = dom.createRng(); 26642 rng.setStartAfter(marker.start); 26643 rng.setEndBefore(marker.end); 26644 return rng; 26645 }; 26646 const createMarker = (dom, markerPrefix, pathRange) => { 26647 const rng = resolvePathRange(dom.getRoot(), pathRange).getOrDie('Unable to resolve path range'); 26648 const startNode = rng.startContainer; 26649 const endNode = rng.endContainer; 26650 const textEnd = rng.endOffset === 0 ? endNode : endNode.splitText(rng.endOffset); 26651 const textStart = rng.startOffset === 0 ? startNode : startNode.splitText(rng.startOffset); 26652 const startParentNode = textStart.parentNode; 26653 const endParentNode = textEnd.parentNode; 26654 return { 26655 prefix: markerPrefix, 26656 end: endParentNode.insertBefore(newMarker(dom, markerPrefix + '-end'), textEnd), 26657 start: startParentNode.insertBefore(newMarker(dom, markerPrefix + '-start'), textStart) 26658 }; 26659 }; 26660 const removeMarker = (dom, marker, isRoot) => { 26661 cleanEmptyNodes(dom, dom.get(marker.prefix + '-end'), isRoot); 26662 cleanEmptyNodes(dom, dom.get(marker.prefix + '-start'), isRoot); 26663 }; 26664 26665 const isReplacementPattern = pattern => pattern.start.length === 0; 26666 const matchesPattern = patternContent => (element, offset) => { 26667 const text = element.data; 26668 const searchText = text.substring(0, offset); 26669 const startEndIndex = searchText.lastIndexOf(patternContent.charAt(patternContent.length - 1)); 26670 const startIndex = searchText.lastIndexOf(patternContent); 26671 if (startIndex !== -1) { 26672 return startIndex + patternContent.length; 26673 } else if (startEndIndex !== -1) { 26674 return startEndIndex + 1; 26675 } else { 26676 return -1; 26677 } 26678 }; 26679 const findPatternStartFromSpot = (dom, pattern, block, spot) => { 26680 const startPattern = pattern.start; 26681 const startSpot = repeatLeft(dom, spot.container, spot.offset, matchesPattern(startPattern), block); 26682 return startSpot.bind(spot => { 26683 var _a, _b; 26684 const startPatternIndex = (_b = (_a = block.textContent) === null || _a === void 0 ? void 0 : _a.indexOf(startPattern)) !== null && _b !== void 0 ? _b : -1; 26685 const isCompleteMatch = startPatternIndex !== -1 && spot.offset >= startPatternIndex + startPattern.length; 26686 if (isCompleteMatch) { 26687 const rng = dom.createRng(); 26688 rng.setStart(spot.container, spot.offset - startPattern.length); 26689 rng.setEnd(spot.container, spot.offset); 26690 return Optional.some(rng); 26691 } else { 26692 const offset = spot.offset - startPattern.length; 26693 return scanLeft(spot.container, offset, block).map(nextSpot => { 26694 const rng = dom.createRng(); 26695 rng.setStart(nextSpot.container, nextSpot.offset); 26696 rng.setEnd(spot.container, spot.offset); 26697 return rng; 26698 }).filter(rng => rng.toString() === startPattern).orThunk(() => findPatternStartFromSpot(dom, pattern, block, point(spot.container, 0))); 26699 } 26700 }); 26701 }; 26702 const findPatternStart = (dom, pattern, node, offset, block, requireGap = false) => { 26703 if (pattern.start.length === 0 && !requireGap) { 26704 const rng = dom.createRng(); 26705 rng.setStart(node, offset); 26706 rng.setEnd(node, offset); 26707 return Optional.some(rng); 26708 } 26709 return textBefore(node, offset, block).bind(spot => { 26710 const start = findPatternStartFromSpot(dom, pattern, block, spot); 26711 return start.bind(startRange => { 26712 var _a; 26713 if (requireGap) { 26714 if (startRange.endContainer === spot.container && startRange.endOffset === spot.offset) { 26715 return Optional.none(); 26716 } else if (spot.offset === 0 && ((_a = startRange.endContainer.textContent) === null || _a === void 0 ? void 0 : _a.length) === startRange.endOffset) { 26717 return Optional.none(); 26718 } 26719 } 26720 return Optional.some(startRange); 26721 }); 26722 }); 26723 }; 26724 const findPattern = (editor, block, details, normalizedMatches) => { 26725 const dom = editor.dom; 26726 const root = dom.getRoot(); 26727 const pattern = details.pattern; 26728 const endNode = details.position.container; 26729 const endOffset = details.position.offset; 26730 return scanLeft(endNode, endOffset - details.pattern.end.length, block).bind(spot => { 26731 const endPathRng = generatePathRange(dom, root, spot.container, spot.offset, endNode, endOffset, normalizedMatches); 26732 if (isReplacementPattern(pattern)) { 26733 return Optional.some({ 26734 matches: [{ 26735 pattern, 26736 startRng: endPathRng, 26737 endRng: endPathRng 26738 }], 26739 position: spot 26740 }); 26741 } else { 26742 const resultsOpt = findPatternsRec(editor, details.remainingPatterns, spot.container, spot.offset, block, normalizedMatches); 26743 const results = resultsOpt.getOr({ 26744 matches: [], 26745 position: spot 26746 }); 26747 const pos = results.position; 26748 const start = findPatternStart(dom, pattern, pos.container, pos.offset, block, resultsOpt.isNone()); 26749 return start.map(startRng => { 26750 const startPathRng = generatePathRangeFromRange(dom, root, startRng, normalizedMatches); 26751 return { 26752 matches: results.matches.concat([{ 26753 pattern, 26754 startRng: startPathRng, 26755 endRng: endPathRng 26756 }]), 26757 position: point(startRng.startContainer, startRng.startOffset) 26758 }; 26759 }); 26760 } 26761 }); 26762 }; 26763 const findPatternsRec = (editor, patterns, node, offset, block, normalizedMatches) => { 26764 const dom = editor.dom; 26765 return textBefore(node, offset, dom.getRoot()).bind(endSpot => { 26766 const text = getBeforeText(dom, block, node, offset); 26767 for (let i = 0; i < patterns.length; i++) { 26768 const pattern = patterns[i]; 26769 if (!endsWith(text, pattern.end)) { 26770 continue; 26771 } 26772 const patternsWithoutCurrent = patterns.slice(); 26773 patternsWithoutCurrent.splice(i, 1); 26774 const result = findPattern(editor, block, { 26775 pattern, 26776 remainingPatterns: patternsWithoutCurrent, 26777 position: endSpot 26778 }, normalizedMatches); 26779 if (result.isNone() && offset > 0) { 26780 return findPatternsRec(editor, patterns, node, offset - 1, block, normalizedMatches); 26781 } 26782 if (result.isSome()) { 26783 return result; 26784 } 26785 } 26786 return Optional.none(); 26787 }); 26788 }; 26789 const applyPattern = (editor, pattern, patternRange) => { 26790 editor.selection.setRng(patternRange); 26791 if (pattern.type === 'inline-format') { 26792 each$e(pattern.format, format => { 26793 editor.formatter.apply(format); 26794 }); 26795 } else { 26796 editor.execCommand(pattern.cmd, false, pattern.value); 26797 } 26798 }; 26799 const applyReplacementPattern = (editor, pattern, marker, isRoot) => { 26800 const markerRange = rangeFromMarker(editor.dom, marker); 26801 deleteRng(editor.dom, markerRange, isRoot); 26802 applyPattern(editor, pattern, markerRange); 26803 }; 26804 const applyPatternWithContent = (editor, pattern, startMarker, endMarker, isRoot) => { 26805 const dom = editor.dom; 26806 const markerEndRange = rangeFromMarker(dom, endMarker); 26807 const markerStartRange = rangeFromMarker(dom, startMarker); 26808 deleteRng(dom, markerStartRange, isRoot); 26809 deleteRng(dom, markerEndRange, isRoot); 26810 const patternMarker = { 26811 prefix: startMarker.prefix, 26812 start: startMarker.end, 26813 end: endMarker.start 26814 }; 26815 const patternRange = rangeFromMarker(dom, patternMarker); 26816 applyPattern(editor, pattern, patternRange); 26817 }; 26818 const addMarkers = (dom, matches) => { 26819 const markerPrefix = generate$1('mce_textpattern'); 26820 const matchesWithEnds = foldr(matches, (acc, match) => { 26821 const endMarker = createMarker(dom, markerPrefix + `_end${ acc.length }`, match.endRng); 26822 return acc.concat([{ 26823 ...match, 26824 endMarker 26825 }]); 26826 }, []); 26827 return foldr(matchesWithEnds, (acc, match) => { 26828 const idx = matchesWithEnds.length - acc.length - 1; 26829 const startMarker = isReplacementPattern(match.pattern) ? match.endMarker : createMarker(dom, markerPrefix + `_start${ idx }`, match.startRng); 26830 return acc.concat([{ 26831 ...match, 26832 startMarker 26833 }]); 26834 }, []); 26835 }; 26836 const sortPatterns = patterns => sort(patterns, (a, b) => b.end.length - a.end.length); 26837 const getBestMatches = (matches, matchesWithSortedPatterns) => { 26838 const hasSameMatches = forall(matches, match => exists(matchesWithSortedPatterns, sortedMatch => match.pattern.start === sortedMatch.pattern.start && match.pattern.end === sortedMatch.pattern.end)); 26839 if (matches.length === matchesWithSortedPatterns.length) { 26840 if (hasSameMatches) { 26841 return matches; 26842 } else { 26843 return matchesWithSortedPatterns; 26844 } 26845 } 26846 return matches.length > matchesWithSortedPatterns.length ? matches : matchesWithSortedPatterns; 26847 }; 26848 const findPatterns = (editor, block, node, offset, patternSet, normalizedMatches) => { 26849 const matches = findPatternsRec(editor, patternSet.inlinePatterns, node, offset, block, normalizedMatches).fold(() => [], result => result.matches); 26850 const matchesWithSortedPatterns = findPatternsRec(editor, sortPatterns(patternSet.inlinePatterns), node, offset, block, normalizedMatches).fold(() => [], result => result.matches); 26851 return getBestMatches(matches, matchesWithSortedPatterns); 26852 }; 26853 const applyMatches = (editor, matches) => { 26854 if (matches.length === 0) { 26855 return; 26856 } 26857 const dom = editor.dom; 26858 const bookmark = editor.selection.getBookmark(); 26859 const matchesWithMarkers = addMarkers(dom, matches); 26860 each$e(matchesWithMarkers, match => { 26861 const block = dom.getParent(match.startMarker.start, dom.isBlock); 26862 const isRoot = node => node === block; 26863 if (isReplacementPattern(match.pattern)) { 26864 applyReplacementPattern(editor, match.pattern, match.endMarker, isRoot); 26865 } else { 26866 applyPatternWithContent(editor, match.pattern, match.startMarker, match.endMarker, isRoot); 26867 } 26868 removeMarker(dom, match.endMarker, isRoot); 26869 removeMarker(dom, match.startMarker, isRoot); 26870 }); 26871 editor.selection.moveToBookmark(bookmark); 26872 }; 26873 26874 const handleEnter = (editor, patternSet) => { 26875 const rng = editor.selection.getRng(); 26876 return getParentBlock(editor, rng).map(block => { 26877 var _a; 26878 const offset = Math.max(0, rng.startOffset); 26879 const dynamicPatternSet = resolveFromDynamicPatterns(patternSet, block, (_a = block.textContent) !== null && _a !== void 0 ? _a : ''); 26880 const inlineMatches = findPatterns(editor, block, rng.startContainer, offset, dynamicPatternSet, true); 26881 const blockMatches = findPatterns$1(editor, block, dynamicPatternSet, true); 26882 if (blockMatches.length > 0 || inlineMatches.length > 0) { 26883 editor.undoManager.add(); 26884 editor.undoManager.extra(() => { 26885 editor.execCommand('mceInsertNewLine'); 26886 }, () => { 26887 editor.insertContent(zeroWidth); 26888 applyMatches(editor, inlineMatches); 26889 applyMatches$1(editor, blockMatches); 26890 const range = editor.selection.getRng(); 26891 const spot = textBefore(range.startContainer, range.startOffset, editor.dom.getRoot()); 26892 editor.execCommand('mceInsertNewLine'); 26893 spot.each(s => { 26894 const node = s.container; 26895 if (node.data.charAt(s.offset - 1) === zeroWidth) { 26896 node.deleteData(s.offset - 1, 1); 26897 cleanEmptyNodes(editor.dom, node.parentNode, e => e === editor.dom.getRoot()); 26898 } 26899 }); 26900 }); 26901 return true; 26902 } 26903 return false; 26904 }).getOr(false); 26905 }; 26906 const handleInlineKey = (editor, patternSet) => { 26907 const rng = editor.selection.getRng(); 26908 getParentBlock(editor, rng).map(block => { 26909 const offset = Math.max(0, rng.startOffset - 1); 26910 const beforeText = getBeforeText(editor.dom, block, rng.startContainer, offset); 26911 const dynamicPatternSet = resolveFromDynamicPatterns(patternSet, block, beforeText); 26912 const inlineMatches = findPatterns(editor, block, rng.startContainer, offset, dynamicPatternSet, false); 26913 if (inlineMatches.length > 0) { 26914 editor.undoManager.transact(() => { 26915 applyMatches(editor, inlineMatches); 26916 }); 26917 } 26918 }); 26919 }; 26920 const checkKeyEvent = (codes, event, predicate) => { 26921 for (let i = 0; i < codes.length; i++) { 26922 if (predicate(codes[i], event)) { 26923 return true; 26924 } 26925 } 26926 return false; 26927 }; 26928 const checkKeyCode = (codes, event) => checkKeyEvent(codes, event, (code, event) => { 26929 return code === event.keyCode && !VK.modifierPressed(event); 26930 }); 26931 const checkCharCode = (chars, event) => checkKeyEvent(chars, event, (chr, event) => { 26932 return chr.charCodeAt(0) === event.charCode; 26933 }); 26934 26935 const setup$2 = editor => { 26936 const charCodes = [ 26937 ',', 26938 '.', 26939 ';', 26940 ':', 26941 '!', 26942 '?' 26943 ]; 26944 const keyCodes = [32]; 26945 const getPatternSet = () => createPatternSet(getTextPatterns(editor), getTextPatternsLookup(editor)); 26946 const hasDynamicPatterns = () => hasTextPatternsLookup(editor); 26947 editor.on('keydown', e => { 26948 if (e.keyCode === 13 && !VK.modifierPressed(e) && editor.selection.isCollapsed()) { 26949 const patternSet = getPatternSet(); 26950 const hasPatterns = patternSet.inlinePatterns.length > 0 || patternSet.blockPatterns.length > 0 || hasDynamicPatterns(); 26951 if (hasPatterns && handleEnter(editor, patternSet)) { 26952 e.preventDefault(); 26953 } 26954 } 26955 }, true); 26956 const handleInlineTrigger = () => { 26957 if (editor.selection.isCollapsed()) { 26958 const patternSet = getPatternSet(); 26959 const hasPatterns = patternSet.inlinePatterns.length > 0 || hasDynamicPatterns(); 26960 if (hasPatterns) { 26961 handleInlineKey(editor, patternSet); 26962 } 26963 } 26964 }; 26965 editor.on('keyup', e => { 26966 if (checkKeyCode(keyCodes, e)) { 26967 handleInlineTrigger(); 26968 } 26969 }); 26970 editor.on('keypress', e => { 26971 if (checkCharCode(charCodes, e)) { 26972 Delay.setEditorTimeout(editor, handleInlineTrigger); 26973 } 26974 }); 26975 }; 26976 26977 const setup$1 = editor => { 26978 setup$2(editor); 26979 }; 26980 26981 const Quirks = editor => { 26982 const each = Tools.each; 26983 const BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, parser = editor.parser; 26984 const browser = Env.browser; 26985 const isGecko = browser.isFirefox(); 26986 const isWebKit = browser.isChromium() || browser.isSafari(); 26987 const isiOS = Env.deviceType.isiPhone() || Env.deviceType.isiPad(); 26988 const isMac = Env.os.isMacOS() || Env.os.isiOS(); 26989 const setEditorCommandState = (cmd, state) => { 26990 try { 26991 editor.getDoc().execCommand(cmd, false, String(state)); 26992 } catch (ex) { 26993 } 26994 }; 26995 const isDefaultPrevented = e => { 26996 return e.isDefaultPrevented(); 26997 }; 26998 const emptyEditorWhenDeleting = () => { 26999 const serializeRng = rng => { 27000 const body = dom.create('body'); 27001 const contents = rng.cloneContents(); 27002 body.appendChild(contents); 27003 return selection.serializer.serialize(body, { format: 'html' }); 27004 }; 27005 const allContentsSelected = rng => { 27006 const selection = serializeRng(rng); 27007 const allRng = dom.createRng(); 27008 allRng.selectNode(editor.getBody()); 27009 const allSelection = serializeRng(allRng); 27010 return selection === allSelection; 27011 }; 27012 editor.on('keydown', e => { 27013 const keyCode = e.keyCode; 27014 if (!isDefaultPrevented(e) && (keyCode === DELETE || keyCode === BACKSPACE) && editor.selection.isEditable()) { 27015 const isCollapsed = editor.selection.isCollapsed(); 27016 const body = editor.getBody(); 27017 if (isCollapsed && !dom.isEmpty(body)) { 27018 return; 27019 } 27020 if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) { 27021 return; 27022 } 27023 e.preventDefault(); 27024 editor.setContent(''); 27025 if (body.firstChild && dom.isBlock(body.firstChild)) { 27026 editor.selection.setCursorLocation(body.firstChild, 0); 27027 } else { 27028 editor.selection.setCursorLocation(body, 0); 27029 } 27030 editor.nodeChanged(); 27031 } 27032 }); 27033 }; 27034 const selectAll = () => { 27035 editor.shortcuts.add('meta+a', null, 'SelectAll'); 27036 }; 27037 const documentElementEditingFocus = () => { 27038 if (!editor.inline) { 27039 dom.bind(editor.getDoc(), 'mousedown mouseup', e => { 27040 let rng; 27041 if (e.target === editor.getDoc().documentElement) { 27042 rng = selection.getRng(); 27043 editor.getBody().focus(); 27044 if (e.type === 'mousedown') { 27045 if (isCaretContainer$2(rng.startContainer)) { 27046 return; 27047 } 27048 selection.placeCaretAt(e.clientX, e.clientY); 27049 } else { 27050 selection.setRng(rng); 27051 } 27052 } 27053 }); 27054 } 27055 }; 27056 const removeHrOnBackspace = () => { 27057 editor.on('keydown', e => { 27058 if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) { 27059 if (!editor.getBody().getElementsByTagName('hr').length) { 27060 return; 27061 } 27062 if (selection.isCollapsed() && selection.getRng().startOffset === 0) { 27063 const node = selection.getNode(); 27064 const previousSibling = node.previousSibling; 27065 if (node.nodeName === 'HR') { 27066 dom.remove(node); 27067 e.preventDefault(); 27068 return; 27069 } 27070 if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'hr') { 27071 dom.remove(previousSibling); 27072 e.preventDefault(); 27073 } 27074 } 27075 } 27076 }); 27077 }; 27078 const focusBody = () => { 27079 if (!Range.prototype.getClientRects) { 27080 editor.on('mousedown', e => { 27081 if (!isDefaultPrevented(e) && e.target.nodeName === 'HTML') { 27082 const body = editor.getBody(); 27083 body.blur(); 27084 Delay.setEditorTimeout(editor, () => { 27085 body.focus(); 27086 }); 27087 } 27088 }); 27089 } 27090 }; 27091 const selectControlElements = () => { 27092 const visualAidsAnchorClass = getVisualAidsAnchorClass(editor); 27093 editor.on('click', e => { 27094 const target = e.target; 27095 if (/^(IMG|HR)$/.test(target.nodeName) && dom.isEditable(target.parentNode)) { 27096 e.preventDefault(); 27097 editor.selection.select(target); 27098 editor.nodeChanged(); 27099 } 27100 if (target.nodeName === 'A' && dom.hasClass(target, visualAidsAnchorClass) && target.childNodes.length === 0 && dom.isEditable(target.parentNode)) { 27101 e.preventDefault(); 27102 selection.select(target); 27103 } 27104 }); 27105 }; 27106 const removeStylesWhenDeletingAcrossBlockElements = () => { 27107 const getAttributeApplyFunction = () => { 27108 const template = dom.getAttribs(selection.getStart().cloneNode(false)); 27109 return () => { 27110 const target = selection.getStart(); 27111 if (target !== editor.getBody()) { 27112 dom.setAttrib(target, 'style', null); 27113 each(template, attr => { 27114 target.setAttributeNode(attr.cloneNode(true)); 27115 }); 27116 } 27117 }; 27118 }; 27119 const isSelectionAcrossElements = () => { 27120 return !selection.isCollapsed() && dom.getParent(selection.getStart(), dom.isBlock) !== dom.getParent(selection.getEnd(), dom.isBlock); 27121 }; 27122 editor.on('keypress', e => { 27123 let applyAttributes; 27124 if (!isDefaultPrevented(e) && (e.keyCode === 8 || e.keyCode === 46) && isSelectionAcrossElements()) { 27125 applyAttributes = getAttributeApplyFunction(); 27126 editor.getDoc().execCommand('delete', false); 27127 applyAttributes(); 27128 e.preventDefault(); 27129 return false; 27130 } else { 27131 return true; 27132 } 27133 }); 27134 dom.bind(editor.getDoc(), 'cut', e => { 27135 if (!isDefaultPrevented(e) && isSelectionAcrossElements()) { 27136 const applyAttributes = getAttributeApplyFunction(); 27137 Delay.setEditorTimeout(editor, () => { 27138 applyAttributes(); 27139 }); 27140 } 27141 }); 27142 }; 27143 const disableBackspaceIntoATable = () => { 27144 editor.on('keydown', e => { 27145 if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) { 27146 if (selection.isCollapsed() && selection.getRng().startOffset === 0) { 27147 const previousSibling = selection.getNode().previousSibling; 27148 if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'table') { 27149 e.preventDefault(); 27150 return false; 27151 } 27152 } 27153 } 27154 return true; 27155 }); 27156 }; 27157 const removeBlockQuoteOnBackSpace = () => { 27158 editor.on('keydown', e => { 27159 if (isDefaultPrevented(e) || e.keyCode !== VK.BACKSPACE) { 27160 return; 27161 } 27162 let rng = selection.getRng(); 27163 const container = rng.startContainer; 27164 const offset = rng.startOffset; 27165 const root = dom.getRoot(); 27166 let parent = container; 27167 if (!rng.collapsed || offset !== 0) { 27168 return; 27169 } 27170 while (parent.parentNode && parent.parentNode.firstChild === parent && parent.parentNode !== root) { 27171 parent = parent.parentNode; 27172 } 27173 if (parent.nodeName === 'BLOCKQUOTE') { 27174 editor.formatter.toggle('blockquote', undefined, parent); 27175 rng = dom.createRng(); 27176 rng.setStart(container, 0); 27177 rng.setEnd(container, 0); 27178 selection.setRng(rng); 27179 } 27180 }); 27181 }; 27182 const setGeckoEditingOptions = () => { 27183 const setOpts = () => { 27184 setEditorCommandState('StyleWithCSS', false); 27185 setEditorCommandState('enableInlineTableEditing', false); 27186 if (!getObjectResizing(editor)) { 27187 setEditorCommandState('enableObjectResizing', false); 27188 } 27189 }; 27190 if (!isReadOnly$1(editor)) { 27191 editor.on('BeforeExecCommand mousedown', setOpts); 27192 } 27193 }; 27194 const addBrAfterLastLinks = () => { 27195 const fixLinks = () => { 27196 each(dom.select('a:not([data-mce-block])'), node => { 27197 var _a; 27198 let parentNode = node.parentNode; 27199 const root = dom.getRoot(); 27200 if ((parentNode === null || parentNode === void 0 ? void 0 : parentNode.lastChild) === node) { 27201 while (parentNode && !dom.isBlock(parentNode)) { 27202 if (((_a = parentNode.parentNode) === null || _a === void 0 ? void 0 : _a.lastChild) !== parentNode || parentNode === root) { 27203 return; 27204 } 27205 parentNode = parentNode.parentNode; 27206 } 27207 dom.add(parentNode, 'br', { 'data-mce-bogus': 1 }); 27208 } 27209 }); 27210 }; 27211 editor.on('SetContent ExecCommand', e => { 27212 if (e.type === 'setcontent' || e.command === 'mceInsertLink') { 27213 fixLinks(); 27214 } 27215 }); 27216 }; 27217 const setDefaultBlockType = () => { 27218 editor.on('init', () => { 27219 setEditorCommandState('DefaultParagraphSeparator', getForcedRootBlock(editor)); 27220 }); 27221 }; 27222 const isAllContentSelected = editor => { 27223 const body = editor.getBody(); 27224 const rng = editor.selection.getRng(); 27225 return rng.startContainer === rng.endContainer && rng.startContainer === body && rng.startOffset === 0 && rng.endOffset === body.childNodes.length; 27226 }; 27227 const normalizeSelection = () => { 27228 editor.on('keyup focusin mouseup', e => { 27229 if (!VK.modifierPressed(e) && !isAllContentSelected(editor)) { 27230 selection.normalize(); 27231 } 27232 }, true); 27233 }; 27234 const showBrokenImageIcon = () => { 27235 editor.contentStyles.push('img:-moz-broken {' + '-moz-force-broken-image-icon:1;' + 'min-width:24px;' + 'min-height:24px' + '}'); 27236 }; 27237 const restoreFocusOnKeyDown = () => { 27238 if (!editor.inline) { 27239 editor.on('keydown', () => { 27240 if (document.activeElement === document.body) { 27241 editor.getWin().focus(); 27242 } 27243 }); 27244 } 27245 }; 27246 const bodyHeight = () => { 27247 if (!editor.inline) { 27248 editor.contentStyles.push('body {min-height: 150px}'); 27249 editor.on('click', e => { 27250 let rng; 27251 if (e.target.nodeName === 'HTML') { 27252 rng = editor.selection.getRng(); 27253 editor.getBody().focus(); 27254 editor.selection.setRng(rng); 27255 editor.selection.normalize(); 27256 editor.nodeChanged(); 27257 } 27258 }); 27259 } 27260 }; 27261 const blockCmdArrowNavigation = () => { 27262 if (isMac) { 27263 editor.on('keydown', e => { 27264 if (VK.metaKeyPressed(e) && !e.shiftKey && (e.keyCode === 37 || e.keyCode === 39)) { 27265 e.preventDefault(); 27266 const selection = editor.selection.getSel(); 27267 selection.modify('move', e.keyCode === 37 ? 'backward' : 'forward', 'lineboundary'); 27268 } 27269 }); 27270 } 27271 }; 27272 const tapLinksAndImages = () => { 27273 editor.on('click', e => { 27274 let elm = e.target; 27275 do { 27276 if (elm.tagName === 'A') { 27277 e.preventDefault(); 27278 return; 27279 } 27280 } while (elm = elm.parentNode); 27281 }); 27282 editor.contentStyles.push('.mce-content-body {-webkit-touch-callout: none}'); 27283 }; 27284 const blockFormSubmitInsideEditor = () => { 27285 editor.on('init', () => { 27286 editor.dom.bind(editor.getBody(), 'submit', e => { 27287 e.preventDefault(); 27288 }); 27289 }); 27290 }; 27291 const removeAppleInterchangeBrs = () => { 27292 parser.addNodeFilter('br', nodes => { 27293 let i = nodes.length; 27294 while (i--) { 27295 if (nodes[i].attr('class') === 'Apple-interchange-newline') { 27296 nodes[i].remove(); 27297 } 27298 } 27299 }); 27300 }; 27301 const refreshContentEditable = noop; 27302 const isHidden = () => { 27303 if (!isGecko || editor.removed) { 27304 return false; 27305 } 27306 const sel = editor.selection.getSel(); 27307 return !sel || !sel.rangeCount || sel.rangeCount === 0; 27308 }; 27309 const setupRtc = () => { 27310 if (isWebKit) { 27311 documentElementEditingFocus(); 27312 selectControlElements(); 27313 blockFormSubmitInsideEditor(); 27314 selectAll(); 27315 if (isiOS) { 27316 restoreFocusOnKeyDown(); 27317 bodyHeight(); 27318 tapLinksAndImages(); 27319 } 27320 } 27321 if (isGecko) { 27322 focusBody(); 27323 setGeckoEditingOptions(); 27324 showBrokenImageIcon(); 27325 blockCmdArrowNavigation(); 27326 } 27327 }; 27328 const
vendor: 16,354 bytes, lines 27328-27767
27328setup = () => { 27329 removeBlockQuoteOnBackSpace(); 27330 emptyEditorWhenDeleting(); 27331 if (!Env.windowsPhone) { 27332 normalizeSelection(); 27333 } 27334 if (isWebKit) { 27335 documentElementEditingFocus(); 27336 selectControlElements(); 27337 setDefaultBlockType(); 27338 blockFormSubmitInsideEditor(); 27339 disableBackspaceIntoATable(); 27340 removeAppleInterchangeBrs(); 27341 if (isiOS) { 27342 restoreFocusOnKeyDown(); 27343 bodyHeight(); 27344 tapLinksAndImages(); 27345 } else { 27346 selectAll(); 27347 } 27348 } 27349 if (isGecko) { 27350 removeHrOnBackspace(); 27351 focusBody(); 27352 removeStylesWhenDeletingAcrossBlockElements(); 27353 setGeckoEditingOptions(); 27354 addBrAfterLastLinks(); 27355 showBrokenImageIcon(); 27356 blockCmdArrowNavigation(); 27357 disableBackspaceIntoATable(); 27358 } 27359 }; 27360 if (isRtc(editor)) { 27361 setupRtc(); 27362 } else { 27363 setup(); 27364 } 27365 return { 27366 refreshContentEditable, 27367 isHidden 27368 }; 27369 }; 27370 27371 const DOM$6 = DOMUtils.DOM; 27372 const appendStyle = (editor, text) => { 27373 const body = SugarElement.fromDom(editor.getBody()); 27374 const container = getStyleContainer(getRootNode(body)); 27375 const style = SugarElement.fromTag('style'); 27376 set$3(style, 'type', 'text/css'); 27377 append$1(style, SugarElement.fromText(text)); 27378 append$1(container, style); 27379 editor.on('remove', () => { 27380 remove$6(style); 27381 }); 27382 }; 27383 const getRootName = editor => editor.inline ? editor.getElement().nodeName.toLowerCase() : undefined; 27384 const removeUndefined = obj => filter$4(obj, v => isUndefined(v) === false); 27385 const mkParserSettings = editor => { 27386 const getOption = editor.options.get; 27387 const blobCache = editor.editorUpload.blobCache; 27388 return removeUndefined({ 27389 allow_conditional_comments: getOption('allow_conditional_comments'), 27390 allow_html_data_urls: getOption('allow_html_data_urls'), 27391 allow_svg_data_urls: getOption('allow_svg_data_urls'), 27392 allow_html_in_named_anchor: getOption('allow_html_in_named_anchor'), 27393 allow_script_urls: getOption('allow_script_urls'), 27394 allow_unsafe_link_target: getOption('allow_unsafe_link_target'), 27395 convert_fonts_to_spans: getOption('convert_fonts_to_spans'), 27396 fix_list_elements: getOption('fix_list_elements'), 27397 font_size_legacy_values: getOption('font_size_legacy_values'), 27398 forced_root_block: getOption('forced_root_block'), 27399 forced_root_block_attrs: getOption('forced_root_block_attrs'), 27400 preserve_cdata: getOption('preserve_cdata'), 27401 remove_trailing_brs: getOption('remove_trailing_brs'), 27402 inline_styles: getOption('inline_styles'), 27403 root_name: getRootName(editor), 27404 sanitize: getOption('xss_sanitization'), 27405 validate: true, 27406 blob_cache: blobCache, 27407 document: editor.getDoc() 27408 }); 27409 }; 27410 const mkSchemaSettings = editor => { 27411 const getOption = editor.options.get; 27412 return removeUndefined({ 27413 custom_elements: getOption('custom_elements'), 27414 extended_valid_elements: getOption('extended_valid_elements'), 27415 invalid_elements: getOption('invalid_elements'), 27416 invalid_styles: getOption('invalid_styles'), 27417 schema: getOption('schema'), 27418 valid_children: getOption('valid_children'), 27419 valid_classes: getOption('valid_classes'), 27420 valid_elements: getOption('valid_elements'), 27421 valid_styles: getOption('valid_styles'), 27422 verify_html: getOption('verify_html'), 27423 padd_empty_block_inline_children: getOption('format_empty_lines') 27424 }); 27425 }; 27426 const mkSerializerSettings = editor => { 27427 const getOption = editor.options.get; 27428 return { 27429 ...mkParserSettings(editor), 27430 ...mkSchemaSettings(editor), 27431 ...removeUndefined({ 27432 url_converter: getOption('url_converter'), 27433 url_converter_scope: getOption('url_converter_scope'), 27434 element_format: getOption('element_format'), 27435 entities: getOption('entities'), 27436 entity_encoding: getOption('entity_encoding'), 27437 indent: getOption('indent'), 27438 indent_after: getOption('indent_after'), 27439 indent_before: getOption('indent_before') 27440 }) 27441 }; 27442 }; 27443 const createParser = editor => { 27444 const parser = DomParser(mkParserSettings(editor), editor.schema); 27445 parser.addAttributeFilter('src,href,style,tabindex', (nodes, name) => { 27446 const dom = editor.dom; 27447 const internalName = 'data-mce-' + name; 27448 let i = nodes.length; 27449 while (i--) { 27450 const node = nodes[i]; 27451 let value = node.attr(name); 27452 if (value && !node.attr(internalName)) { 27453 if (value.indexOf('data:') === 0 || value.indexOf('blob:') === 0) { 27454 continue; 27455 } 27456 if (name === 'style') { 27457 value = dom.serializeStyle(dom.parseStyle(value), node.name); 27458 if (!value.length) { 27459 value = null; 27460 } 27461 node.attr(internalName, value); 27462 node.attr(name, value); 27463 } else if (name === 'tabindex') { 27464 node.attr(internalName, value); 27465 node.attr(name, null); 27466 } else { 27467 node.attr(internalName, editor.convertURL(value, name, node.name)); 27468 } 27469 } 27470 } 27471 }); 27472 parser.addNodeFilter('script', nodes => { 27473 let i = nodes.length; 27474 while (i--) { 27475 const node = nodes[i]; 27476 const type = node.attr('type') || 'no/type'; 27477 if (type.indexOf('mce-') !== 0) { 27478 node.attr('type', 'mce-' + type); 27479 } 27480 } 27481 }); 27482 if (shouldPreserveCData(editor)) { 27483 parser.addNodeFilter('#cdata', nodes => { 27484 var _a; 27485 let i = nodes.length; 27486 while (i--) { 27487 const node = nodes[i]; 27488 node.type = 8; 27489 node.name = '#comment'; 27490 node.value = '[CDATA[' + editor.dom.encode((_a = node.value) !== null && _a !== void 0 ? _a : '') + ']]'; 27491 } 27492 }); 27493 } 27494 parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', nodes => { 27495 let i = nodes.length; 27496 const nonEmptyElements = editor.schema.getNonEmptyElements(); 27497 while (i--) { 27498 const node = nodes[i]; 27499 if (node.isEmpty(nonEmptyElements) && node.getAll('br').length === 0) { 27500 node.append(new AstNode('br', 1)); 27501 } 27502 } 27503 }); 27504 return parser; 27505 }; 27506 const autoFocus = editor => { 27507 const autoFocus = getAutoFocus(editor); 27508 if (autoFocus) { 27509 Delay.setEditorTimeout(editor, () => { 27510 let focusEditor; 27511 if (autoFocus === true) { 27512 focusEditor = editor; 27513 } else { 27514 focusEditor = editor.editorManager.get(autoFocus); 27515 } 27516 if (focusEditor && !focusEditor.destroyed) { 27517 focusEditor.focus(); 27518 focusEditor.selection.scrollIntoView(); 27519 } 27520 }, 100); 27521 } 27522 }; 27523 const moveSelectionToFirstCaretPosition = editor => { 27524 const root = editor.dom.getRoot(); 27525 if (!editor.inline && (!hasAnyRanges(editor) || editor.selection.getStart(true) === root)) { 27526 firstPositionIn(root).each(pos => { 27527 const node = pos.getNode(); 27528 const caretPos = isTable$2(node) ? firstPositionIn(node).getOr(pos) : pos; 27529 editor.selection.setRng(caretPos.toRange()); 27530 }); 27531 } 27532 }; 27533 const initEditor = editor => { 27534 editor.bindPendingEventDelegates(); 27535 editor.initialized = true; 27536 fireInit(editor); 27537 editor.focus(true); 27538 moveSelectionToFirstCaretPosition(editor); 27539 editor.nodeChanged({ initial: true }); 27540 const initInstanceCallback = getInitInstanceCallback(editor); 27541 if (isFunction(initInstanceCallback)) { 27542 initInstanceCallback.call(editor, editor); 27543 } 27544 autoFocus(editor); 27545 }; 27546 const getStyleSheetLoader$1 = editor => editor.inline ? editor.ui.styleSheetLoader : editor.dom.styleSheetLoader; 27547 const makeStylesheetLoadingPromises = (editor, css, framedFonts) => { 27548 const promises = [getStyleSheetLoader$1(editor).loadAll(css)]; 27549 if (editor.inline) { 27550 return promises; 27551 } else { 27552 return promises.concat([editor.ui.styleSheetLoader.loadAll(framedFonts)]); 27553 } 27554 }; 27555 const loadContentCss = editor => { 27556 const styleSheetLoader = getStyleSheetLoader$1(editor); 27557 const fontCss = getFontCss(editor); 27558 const css = editor.contentCSS; 27559 const removeCss = () => { 27560 styleSheetLoader.unloadAll(css); 27561 if (!editor.inline) { 27562 editor.ui.styleSheetLoader.unloadAll(fontCss); 27563 } 27564 }; 27565 const loaded = () => { 27566 if (editor.removed) { 27567 removeCss(); 27568 } else { 27569 editor.on('remove', removeCss); 27570 } 27571 }; 27572 if (editor.contentStyles.length > 0) { 27573 let contentCssText = ''; 27574 Tools.each(editor.contentStyles, style => { 27575 contentCssText += style + '\r\n'; 27576 }); 27577 editor.dom.addStyle(contentCssText); 27578 } 27579 const allStylesheets = Promise.all(makeStylesheetLoadingPromises(editor, css, fontCss)).then(loaded).catch(loaded); 27580 const contentStyle = getContentStyle(editor); 27581 if (contentStyle) { 27582 appendStyle(editor, contentStyle); 27583 } 27584 return allStylesheets; 27585 }; 27586 const preInit = editor => { 27587 const doc = editor.getDoc(), body = editor.getBody(); 27588 firePreInit(editor); 27589 if (!shouldBrowserSpellcheck(editor)) { 27590 doc.body.spellcheck = false; 27591 DOM$6.setAttrib(body, 'spellcheck', 'false'); 27592 } 27593 editor.quirks = Quirks(editor); 27594 firePostRender(editor); 27595 const directionality = getDirectionality(editor); 27596 if (directionality !== undefined) { 27597 body.dir = directionality; 27598 } 27599 const protect = getProtect(editor); 27600 if (protect) { 27601 editor.on('BeforeSetContent', e => { 27602 Tools.each(protect, pattern => { 27603 e.content = e.content.replace(pattern, str => { 27604 return '<!--mce:protected ' + escape(str) + '-->'; 27605 }); 27606 }); 27607 }); 27608 } 27609 editor.on('SetContent', () => { 27610 editor.addVisual(editor.getBody()); 27611 }); 27612 editor.on('compositionstart compositionend', e => { 27613 editor.composing = e.type === 'compositionstart'; 27614 }); 27615 }; 27616 const loadInitialContent = editor => { 27617 if (!isRtc(editor)) { 27618 editor.load({ 27619 initial: true, 27620 format: 'html' 27621 }); 27622 } 27623 editor.startContent = editor.getContent({ format: 'raw' }); 27624 }; 27625 const initEditorWithInitialContent = editor => { 27626 if (editor.removed !== true) { 27627 loadInitialContent(editor); 27628 initEditor(editor); 27629 } 27630 }; 27631 const contentBodyLoaded = editor => { 27632 const targetElm = editor.getElement(); 27633 let doc = editor.getDoc(); 27634 if (editor.inline) { 27635 DOM$6.addClass(targetElm, 'mce-content-body'); 27636 editor.contentDocument = doc = document; 27637 editor.contentWindow = window; 27638 editor.bodyElement = targetElm; 27639 editor.contentAreaContainer = targetElm; 27640 } 27641 const body = editor.getBody(); 27642 body.disabled = true; 27643 editor.readonly = isReadOnly$1(editor); 27644 if (!editor.readonly) { 27645 if (editor.inline && DOM$6.getStyle(body, 'position', true) === 'static') { 27646 body.style.position = 'relative'; 27647 } 27648 body.contentEditable = 'true'; 27649 } 27650 body.disabled = false; 27651 editor.editorUpload = EditorUpload(editor); 27652 editor.schema = Schema(mkSchemaSettings(editor)); 27653 editor.dom = DOMUtils(doc, { 27654 keep_values: true, 27655 url_converter: editor.convertURL, 27656 url_converter_scope: editor, 27657 update_styles: true, 27658 root_element: editor.inline ? editor.getBody() : null, 27659 collect: editor.inline, 27660 schema: editor.schema, 27661 contentCssCors: shouldUseContentCssCors(editor), 27662 referrerPolicy: getReferrerPolicy(editor), 27663 onSetAttrib: e => { 27664 editor.dispatch('SetAttrib', e); 27665 } 27666 }); 27667 editor.parser = createParser(editor); 27668 editor.serializer = DomSerializer(mkSerializerSettings(editor), editor); 27669 editor.selection = EditorSelection(editor.dom, editor.getWin(), editor.serializer, editor); 27670 editor.annotator = Annotator(editor); 27671 editor.formatter = Formatter(editor); 27672 editor.undoManager = UndoManager(editor); 27673 editor._nodeChangeDispatcher = new NodeChange(editor); 27674 editor._selectionOverrides = SelectionOverrides(editor); 27675 setup$o(editor); 27676 setup$6(editor); 27677 setup$m(editor); 27678 if (!isRtc(editor)) { 27679 setup$5(editor); 27680 setup$1(editor); 27681 } 27682 const caret = setup$b(editor); 27683 setup$p(editor, caret); 27684 setup$n(editor); 27685 setup$q(editor); 27686 setup$7(editor); 27687 const setupRtcThunk = setup$s(editor); 27688 preInit(editor); 27689 setupRtcThunk.fold(() => { 27690 loadContentCss(editor).then(() => initEditorWithInitialContent(editor)); 27691 }, setupRtc => { 27692 editor.setProgressState(true); 27693 loadContentCss(editor).then(() => { 27694 setupRtc().then(_rtcMode => { 27695 editor.setProgressState(false); 27696 initEditorWithInitialContent(editor); 27697 bindEvents(editor); 27698 }, err => { 27699 editor.notificationManager.open({ 27700 type: 'error', 27701 text: String(err) 27702 }); 27703 initEditorWithInitialContent(editor); 27704 bindEvents(editor); 27705 }); 27706 }); 27707 }); 27708 }; 27709 27710 const filter = always; 27711 const bind = (element, event, handler) => bind$2(element, event, filter, handler); 27712 27713 const DOM$5 = DOMUtils.DOM; 27714 const createIframeElement = (id, title, customAttrs, tabindex) => { 27715 const iframe = SugarElement.fromTag('iframe'); 27716 tabindex.each(t => set$3(iframe, 'tabindex', t)); 27717 setAll$1(iframe, customAttrs); 27718 setAll$1(iframe, { 27719 id: id + '_ifr', 27720 frameBorder: '0', 27721 allowTransparency: 'true', 27722 title 27723 }); 27724 add$2(iframe, 'tox-edit-area__iframe'); 27725 return iframe; 27726 }; 27727 const getIframeHtml = editor => { 27728 let iframeHTML = getDocType(editor) + '<html><head>'; 27729 if (getDocumentBaseUrl(editor) !== editor.documentBaseUrl) { 27730 iframeHTML += '<base href="' + editor.documentBaseURI.getURI() + '" />'; 27731 } 27732 iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'; 27733 const bodyId = getBodyId(editor); 27734 const bodyClass = getBodyClass(editor); 27735 const translatedAriaText = editor.translate(getIframeAriaText(editor)); 27736 if (getContentSecurityPolicy(editor)) { 27737 iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + getContentSecurityPolicy(editor) + '" />'; 27738 } 27739 iframeHTML += '</head>' + `<body id="${ bodyId }" class="mce-content-body ${ bodyClass }" data-id="${ editor.id }" aria-label="${ translatedAriaText }">` + '<br>' + '</body></html>'; 27740 return iframeHTML; 27741 }; 27742 const createIframe = (editor, boxInfo) => { 27743 const iframeTitle = editor.translate('Rich Text Area'); 27744 const tabindex = getOpt(SugarElement.fromDom(editor.getElement()), 'tabindex').bind(toInt); 27745 const ifr = createIframeElement(editor.id, iframeTitle, getIframeAttrs(editor), tabindex).dom; 27746 ifr.onload = () => { 27747 ifr.onload = null; 27748 editor.dispatch('load'); 27749 }; 27750 editor.contentAreaContainer = boxInfo.iframeContainer; 27751 editor.iframeElement = ifr; 27752 editor.iframeHTML = getIframeHtml(editor); 27753 DOM$5.add(boxInfo.iframeContainer, ifr); 27754 }; 27755 const setupIframeBody = editor => { 27756 const iframe = editor.iframeElement; 27757 const binder = bind(SugarElement.fromDom(iframe), 'load', () => { 27758 binder.unbind(); 27759 editor.contentDocument = iframe.contentDocument; 27760 contentBodyLoaded(editor); 27761 }); 27762 if (Env.browser.isFirefox()) { 27763 const doc = editor.getDoc(); 27764 doc.open(); 27765 doc.write(editor.iframeHTML); 27766 doc.close(); 27767 } else {
vendor: 10,218 bytes, lines 27767-28035
27767 27768 iframe.srcdoc = editor.iframeHTML; 27769 } 27770 }; 27771 const init$1 = (editor, boxInfo) => { 27772 createIframe(editor, boxInfo); 27773 if (boxInfo.editorContainer) { 27774 boxInfo.editorContainer.style.display = editor.orgDisplay; 27775 editor.hidden = DOM$5.isHidden(boxInfo.editorContainer); 27776 } 27777 editor.getElement().style.display = 'none'; 27778 DOM$5.setAttrib(editor.id, 'aria-hidden', 'true'); 27779 editor.getElement().style.visibility = editor.orgVisibility; 27780 setupIframeBody(editor); 27781 }; 27782 27783 const DOM$4 = DOMUtils.DOM; 27784 const initPlugin = (editor, initializedPlugins, plugin) => { 27785 const Plugin = PluginManager.get(plugin); 27786 const pluginUrl = PluginManager.urls[plugin] || editor.documentBaseUrl.replace(/\/$/, ''); 27787 plugin = Tools.trim(plugin); 27788 if (Plugin && Tools.inArray(initializedPlugins, plugin) === -1) { 27789 if (editor.plugins[plugin]) { 27790 return; 27791 } 27792 try { 27793 const pluginInstance = Plugin(editor, pluginUrl) || {}; 27794 editor.plugins[plugin] = pluginInstance; 27795 if (isFunction(pluginInstance.init)) { 27796 pluginInstance.init(editor, pluginUrl); 27797 initializedPlugins.push(plugin); 27798 } 27799 } catch (e) { 27800 pluginInitError(editor, plugin, e); 27801 } 27802 } 27803 }; 27804 const trimLegacyPrefix = name => { 27805 return name.replace(/^\-/, ''); 27806 }; 27807 const initPlugins = editor => { 27808 const initializedPlugins = []; 27809 each$e(getPlugins(editor), name => { 27810 initPlugin(editor, initializedPlugins, trimLegacyPrefix(name)); 27811 }); 27812 }; 27813 const initIcons = editor => { 27814 const iconPackName = Tools.trim(getIconPackName(editor)); 27815 const currentIcons = editor.ui.registry.getAll().icons; 27816 const loadIcons = { 27817 ...IconManager.get('default').icons, 27818 ...IconManager.get(iconPackName).icons 27819 }; 27820 each$d(loadIcons, (svgData, icon) => { 27821 if (!has$2(currentIcons, icon)) { 27822 editor.ui.registry.addIcon(icon, svgData); 27823 } 27824 }); 27825 }; 27826 const initTheme = editor => { 27827 const theme = getTheme(editor); 27828 if (isString(theme)) { 27829 const Theme = ThemeManager.get(theme); 27830 editor.theme = Theme(editor, ThemeManager.urls[theme]) || {}; 27831 if (isFunction(editor.theme.init)) { 27832 editor.theme.init(editor, ThemeManager.urls[theme] || editor.documentBaseUrl.replace(/\/$/, '')); 27833 } 27834 } else { 27835 editor.theme = {}; 27836 } 27837 }; 27838 const initModel = editor => { 27839 const model = getModel(editor); 27840 const Model = ModelManager.get(model); 27841 editor.model = Model(editor, ModelManager.urls[model]); 27842 }; 27843 const renderFromLoadedTheme = editor => { 27844 const render = editor.theme.renderUI; 27845 return render ? render() : renderThemeFalse(editor); 27846 }; 27847 const renderFromThemeFunc = editor => { 27848 const elm = editor.getElement(); 27849 const theme = getTheme(editor); 27850 const info = theme(editor, elm); 27851 if (info.editorContainer.nodeType) { 27852 info.editorContainer.id = info.editorContainer.id || editor.id + '_parent'; 27853 } 27854 if (info.iframeContainer && info.iframeContainer.nodeType) { 27855 info.iframeContainer.id = info.iframeContainer.id || editor.id + '_iframecontainer'; 27856 } 27857 info.height = info.iframeHeight ? info.iframeHeight : elm.offsetHeight; 27858 return info; 27859 }; 27860 const createThemeFalseResult = (element, iframe) => { 27861 return { 27862 editorContainer: element, 27863 iframeContainer: iframe, 27864 api: {} 27865 }; 27866 }; 27867 const renderThemeFalseIframe = targetElement => { 27868 const iframeContainer = DOM$4.create('div'); 27869 DOM$4.insertAfter(iframeContainer, targetElement); 27870 return createThemeFalseResult(iframeContainer, iframeContainer); 27871 }; 27872 const renderThemeFalse = editor => { 27873 const targetElement = editor.getElement(); 27874 return editor.inline ? createThemeFalseResult(null) : renderThemeFalseIframe(targetElement); 27875 }; 27876 const renderThemeUi = editor => { 27877 const elm = editor.getElement(); 27878 editor.orgDisplay = elm.style.display; 27879 if (isString(getTheme(editor))) { 27880 return renderFromLoadedTheme(editor); 27881 } else if (isFunction(getTheme(editor))) { 27882 return renderFromThemeFunc(editor); 27883 } else { 27884 return renderThemeFalse(editor); 27885 } 27886 }; 27887 const augmentEditorUiApi = (editor, api) => { 27888 const uiApiFacade = { 27889 show: Optional.from(api.show).getOr(noop), 27890 hide: Optional.from(api.hide).getOr(noop), 27891 isEnabled: Optional.from(api.isEnabled).getOr(always), 27892 setEnabled: state => { 27893 if (!editor.mode.isReadOnly()) { 27894 Optional.from(api.setEnabled).each(f => f(state)); 27895 } 27896 } 27897 }; 27898 editor.ui = { 27899 ...editor.ui, 27900 ...uiApiFacade 27901 }; 27902 }; 27903 const init = async editor => { 27904 editor.dispatch('ScriptsLoaded'); 27905 initIcons(editor); 27906 initTheme(editor); 27907 initModel(editor); 27908 initPlugins(editor); 27909 const renderInfo = await renderThemeUi(editor); 27910 augmentEditorUiApi(editor, Optional.from(renderInfo.api).getOr({})); 27911 editor.editorContainer = renderInfo.editorContainer; 27912 appendContentCssFromSettings(editor); 27913 if (editor.inline) { 27914 contentBodyLoaded(editor); 27915 } else { 27916 init$1(editor, { 27917 editorContainer: renderInfo.editorContainer, 27918 iframeContainer: renderInfo.iframeContainer 27919 }); 27920 } 27921 }; 27922 27923 const DOM$3 = DOMUtils.DOM; 27924 const hasSkipLoadPrefix = name => name.charAt(0) === '-'; 27925 const loadLanguage = (scriptLoader, editor) => { 27926 const languageCode = getLanguageCode(editor); 27927 const languageUrl = getLanguageUrl(editor); 27928 if (!I18n.hasCode(languageCode) && languageCode !== 'en') { 27929 const url = isNotEmpty(languageUrl) ? languageUrl : `${ editor.editorManager.baseURL }/langs/${ languageCode }.js`; 27930 scriptLoader.add(url).catch(() => { 27931 languageLoadError(editor, url, languageCode); 27932 }); 27933 } 27934 }; 27935 const loadTheme = (editor, suffix) => { 27936 const theme = getTheme(editor); 27937 if (isString(theme) && !hasSkipLoadPrefix(theme) && !has$2(ThemeManager.urls, theme)) { 27938 const themeUrl = getThemeUrl(editor); 27939 const url = themeUrl ? editor.documentBaseURI.toAbsolute(themeUrl) : `themes/${ theme }/theme${ suffix }.js`; 27940 ThemeManager.load(theme, url).catch(() => { 27941 themeLoadError(editor, url, theme); 27942 }); 27943 } 27944 }; 27945 const loadModel = (editor, suffix) => { 27946 const model = getModel(editor); 27947 if (model !== 'plugin' && !has$2(ModelManager.urls, model)) { 27948 const modelUrl = getModelUrl(editor); 27949 const url = isString(modelUrl) ? editor.documentBaseURI.toAbsolute(modelUrl) : `models/${ model }/model${ suffix }.js`; 27950 ModelManager.load(model, url).catch(() => { 27951 modelLoadError(editor, url, model); 27952 }); 27953 } 27954 }; 27955 const getIconsUrlMetaFromUrl = editor => Optional.from(getIconsUrl(editor)).filter(isNotEmpty).map(url => ({ 27956 url, 27957 name: Optional.none() 27958 })); 27959 const getIconsUrlMetaFromName = (editor, name, suffix) => Optional.from(name).filter(name => isNotEmpty(name) && !IconManager.has(name)).map(name => ({ 27960 url: `${ editor.editorManager.baseURL }/icons/${ name }/icons${ suffix }.js`, 27961 name: Optional.some(name) 27962 })); 27963 const loadIcons = (scriptLoader, editor, suffix) => { 27964 const defaultIconsUrl = getIconsUrlMetaFromName(editor, 'default', suffix); 27965 const customIconsUrl = getIconsUrlMetaFromUrl(editor).orThunk(() => getIconsUrlMetaFromName(editor, getIconPackName(editor), '')); 27966 each$e(cat([ 27967 defaultIconsUrl, 27968 customIconsUrl 27969 ]), urlMeta => { 27970 scriptLoader.add(urlMeta.url).catch(() => { 27971 iconsLoadError(editor, urlMeta.url, urlMeta.name.getOrUndefined()); 27972 }); 27973 }); 27974 }; 27975 const loadPlugins = (editor, suffix) => { 27976 const loadPlugin = (name, url) => { 27977 PluginManager.load(name, url).catch(() => { 27978 pluginLoadError(editor, url, name); 27979 }); 27980 }; 27981 each$d(getExternalPlugins$1(editor), (url, name) => { 27982 loadPlugin(name, url); 27983 editor.options.set('plugins', getPlugins(editor).concat(name)); 27984 }); 27985 each$e(getPlugins(editor), plugin => { 27986 plugin = Tools.trim(plugin); 27987 if (plugin && !PluginManager.urls[plugin] && !hasSkipLoadPrefix(plugin)) { 27988 loadPlugin(plugin, `plugins/${ plugin }/plugin${ suffix }.js`); 27989 } 27990 }); 27991 }; 27992 const isThemeLoaded = editor => { 27993 const theme = getTheme(editor); 27994 return !isString(theme) || isNonNullable(ThemeManager.get(theme)); 27995 }; 27996 const isModelLoaded = editor => { 27997 const model = getModel(editor); 27998 return isNonNullable(ModelManager.get(model)); 27999 }; 28000 const loadScripts = (editor, suffix) => { 28001 const scriptLoader = ScriptLoader.ScriptLoader; 28002 const initEditor = () => { 28003 if (!editor.removed && isThemeLoaded(editor) && isModelLoaded(editor)) { 28004 init(editor); 28005 } 28006 }; 28007 loadTheme(editor, suffix); 28008 loadModel(editor, suffix); 28009 loadLanguage(scriptLoader, editor); 28010 loadIcons(scriptLoader, editor, suffix); 28011 loadPlugins(editor, suffix); 28012 scriptLoader.loadQueue().then(initEditor, initEditor); 28013 }; 28014 const getStyleSheetLoader = (element, editor) => instance.forElement(element, { 28015 contentCssCors: hasContentCssCors(editor), 28016 referrerPolicy: getReferrerPolicy(editor) 28017 }); 28018 const render = editor => { 28019 const id = editor.id; 28020 I18n.setCode(getLanguageCode(editor)); 28021 const readyHandler = () => { 28022 DOM$3.unbind(window, 'ready', readyHandler); 28023 editor.render(); 28024 }; 28025 if (!EventUtils.Event.domLoaded) { 28026 DOM$3.bind(window, 'ready', readyHandler); 28027 return; 28028 } 28029 if (!editor.getElement()) { 28030 return; 28031 } 28032 const element = SugarElement.fromDom(editor.getElement()); 28033 const snapshot = clone$4(element); 28034 editor.on('remove', () => { 28035 eachr(element.dom.attributes, attr => remove$
vendor: 3,848 bytes, lines 28035-28141
28035b(element, attr.name)); 28036 setAll$1(element, snapshot); 28037 }); 28038 editor.ui.styleSheetLoader = getStyleSheetLoader(element, editor); 28039 if (!isInline(editor)) { 28040 editor.orgVisibility = editor.getElement().style.visibility; 28041 editor.getElement().style.visibility = 'hidden'; 28042 } else { 28043 editor.inline = true; 28044 } 28045 const form = editor.getElement().form || DOM$3.getParent(id, 'form'); 28046 if (form) { 28047 editor.formElement = form; 28048 if (hasHiddenInput(editor) && !isTextareaOrInput(editor.getElement())) { 28049 DOM$3.insertAfter(DOM$3.create('input', { 28050 type: 'hidden', 28051 name: id 28052 }), id); 28053 editor.hasHiddenInput = true; 28054 } 28055 editor.formEventDelegate = e => { 28056 editor.dispatch(e.type, e); 28057 }; 28058 DOM$3.bind(form, 'submit reset', editor.formEventDelegate); 28059 editor.on('reset', () => { 28060 editor.resetContent(); 28061 }); 28062 if (shouldPatchSubmit(editor) && !form.submit.nodeType && !form.submit.length && !form._mceOldSubmit) { 28063 form._mceOldSubmit = form.submit; 28064 form.submit = () => { 28065 editor.editorManager.triggerSave(); 28066 editor.setDirty(false); 28067 return form._mceOldSubmit(form); 28068 }; 28069 } 28070 } 28071 editor.windowManager = WindowManager(editor); 28072 editor.notificationManager = NotificationManager(editor); 28073 if (isEncodingXml(editor)) { 28074 editor.on('GetContent', e => { 28075 if (e.save) { 28076 e.content = DOM$3.encode(e.content); 28077 } 28078 }); 28079 } 28080 if (shouldAddFormSubmitTrigger(editor)) { 28081 editor.on('submit', () => { 28082 if (editor.initialized) { 28083 editor.save(); 28084 } 28085 }); 28086 } 28087 if (shouldAddUnloadTrigger(editor)) { 28088 editor._beforeUnload = () => { 28089 if (editor.initialized && !editor.destroyed && !editor.isHidden()) { 28090 editor.save({ 28091 format: 'raw', 28092 no_events: true, 28093 set_dirty: false 28094 }); 28095 } 28096 }; 28097 editor.editorManager.on('BeforeUnload', editor._beforeUnload); 28098 } 28099 editor.editorManager.add(editor); 28100 loadScripts(editor, editor.suffix); 28101 }; 28102 28103 const sectionResult = (sections, settings) => ({ 28104 sections: constant(sections), 28105 options: constant(settings) 28106 }); 28107 const deviceDetection = detect$2().deviceType; 28108 const isPhone = deviceDetection.isPhone(); 28109 const isTablet = deviceDetection.isTablet(); 28110 const normalizePlugins = plugins => { 28111 if (isNullable(plugins)) { 28112 return []; 28113 } else { 28114 const pluginNames = isArray$1(plugins) ? plugins : plugins.split(/[ ,]/); 28115 const trimmedPlugins = map$3(pluginNames, trim$3); 28116 return filter$5(trimmedPlugins, isNotEmpty); 28117 } 28118 }; 28119 const extractSections = (keys, options) => { 28120 const result = bifilter(options, (value, key) => { 28121 return contains$2(keys, key); 28122 }); 28123 return sectionResult(result.t, result.f); 28124 }; 28125 const getSection = (sectionResult, name, defaults = {}) => { 28126 const sections = sectionResult.sections(); 28127 const sectionOptions = get$a(sections, name).getOr({}); 28128 return Tools.extend({}, defaults, sectionOptions); 28129 }; 28130 const hasSection = (sectionResult, name) => { 28131 return has$2(sectionResult.sections(), name); 28132 }; 28133 const getSectionConfig = (sectionResult, name) => { 28134 return hasSection(sectionResult, name) ? sectionResult.sections()[name] : {}; 28135 }; 28136 const getMobileOverrideOptions = (mobileOptions, isPhone) => { 28137 const defaultMobileOptions = { 28138 table_grid: false, 28139 object_resizing: false, 28140 resize: false, 28141 toolbar_mode: get$a(mobileOptions, 'toolbar_mode').getOr('scrolling'),
vendor: 8,312 bytes, lines 28142-28350
28142 toolbar_sticky: false 28143 }; 28144 const defaultPhoneOptions = { menubar: false }; 28145 return { 28146 ...defaultMobileOptions, 28147 ...isPhone ? defaultPhoneOptions : {} 28148 }; 28149 }; 28150 const getExternalPlugins = (overrideOptions, options) => { 28151 var _a; 28152 const userDefinedExternalPlugins = (_a = options.external_plugins) !== null && _a !== void 0 ? _a : {}; 28153 if (overrideOptions && overrideOptions.external_plugins) { 28154 return Tools.extend({}, overrideOptions.external_plugins, userDefinedExternalPlugins); 28155 } else { 28156 return userDefinedExternalPlugins; 28157 } 28158 }; 28159 const combinePlugins = (forcedPlugins, plugins) => [ 28160 ...normalizePlugins(forcedPlugins), 28161 ...normalizePlugins(plugins) 28162 ]; 28163 const getPlatformPlugins = (isMobileDevice, sectionResult, desktopPlugins, mobilePlugins) => { 28164 if (isMobileDevice && hasSection(sectionResult, 'mobile')) { 28165 return mobilePlugins; 28166 } else { 28167 return desktopPlugins; 28168 } 28169 }; 28170 const processPlugins = (isMobileDevice, sectionResult, defaultOverrideOptions, options) => { 28171 const forcedPlugins = normalizePlugins(defaultOverrideOptions.forced_plugins); 28172 const desktopPlugins = normalizePlugins(options.plugins); 28173 const mobileConfig = getSectionConfig(sectionResult, 'mobile'); 28174 const mobilePlugins = mobileConfig.plugins ? normalizePlugins(mobileConfig.plugins) : desktopPlugins; 28175 const platformPlugins = getPlatformPlugins(isMobileDevice, sectionResult, desktopPlugins, mobilePlugins); 28176 const combinedPlugins = combinePlugins(forcedPlugins, platformPlugins); 28177 return Tools.extend(options, { 28178 forced_plugins: forcedPlugins, 28179 plugins: combinedPlugins 28180 }); 28181 }; 28182 const isOnMobile = (isMobileDevice, sectionResult) => { 28183 return isMobileDevice && hasSection(sectionResult, 'mobile'); 28184 }; 28185 const combineOptions = (isMobileDevice, isPhone, defaultOptions, defaultOverrideOptions, options) => { 28186 var _a; 28187 const deviceOverrideOptions = isMobileDevice ? { mobile: getMobileOverrideOptions((_a = options.mobile) !== null && _a !== void 0 ? _a : {}, isPhone) } : {}; 28188 const sectionResult = extractSections(['mobile'], deepMerge(deviceOverrideOptions, options)); 28189 const extendedOptions = Tools.extend(defaultOptions, defaultOverrideOptions, sectionResult.options(), isOnMobile(isMobileDevice, sectionResult) ? getSection(sectionResult, 'mobile') : {}, { external_plugins: getExternalPlugins(defaultOverrideOptions, sectionResult.options()) }); 28190 return processPlugins(isMobileDevice, sectionResult, defaultOverrideOptions, extendedOptions); 28191 }; 28192 const normalizeOptions = (defaultOverrideOptions, options) => combineOptions(isPhone || isTablet, isPhone, options, defaultOverrideOptions, options); 28193 28194 const addVisual = (editor, elm) => addVisual$1(editor, elm); 28195 28196 const registerExecCommands$3 = editor => { 28197 const toggleFormat = (name, value) => { 28198 editor.formatter.toggle(name, value); 28199 editor.nodeChanged(); 28200 }; 28201 const toggleAlign = align => () => { 28202 each$e('left,center,right,justify'.split(','), name => { 28203 if (align !== name) { 28204 editor.formatter.remove('align' + name); 28205 } 28206 }); 28207 if (align !== 'none') { 28208 toggleFormat('align' + align); 28209 } 28210 }; 28211 editor.editorCommands.addCommands({ 28212 JustifyLeft: toggleAlign('left'), 28213 JustifyCenter: toggleAlign('center'), 28214 JustifyRight: toggleAlign('right'), 28215 JustifyFull: toggleAlign('justify'), 28216 JustifyNone: toggleAlign('none') 28217 }); 28218 }; 28219 const registerQueryStateCommands$1 = editor => { 28220 const alignStates = name => () => { 28221 const selection = editor.selection; 28222 const nodes = selection.isCollapsed() ? [editor.dom.getParent(selection.getNode(), editor.dom.isBlock)] : selection.getSelectedBlocks(); 28223 return exists(nodes, node => isNonNullable(editor.formatter.matchNode(node, name))); 28224 }; 28225 editor.editorCommands.addCommands({ 28226 JustifyLeft: alignStates('alignleft'), 28227 JustifyCenter: alignStates('aligncenter'), 28228 JustifyRight: alignStates('alignright'), 28229 JustifyFull: alignStates('alignjustify') 28230 }, 'state'); 28231 }; 28232 const registerCommands$a = editor => { 28233 registerExecCommands$3(editor); 28234 registerQueryStateCommands$1(editor); 28235 }; 28236 28237 const registerCommands$9 = editor => { 28238 editor.editorCommands.addCommands({ 28239 'Cut,Copy,Paste': command => { 28240 const doc = editor.getDoc(); 28241 let failed; 28242 try { 28243 doc.execCommand(command); 28244 } catch (ex) { 28245 failed = true; 28246 } 28247 if (command === 'paste' && !doc.queryCommandEnabled(command)) { 28248 failed = true; 28249 } 28250 if (failed || !doc.queryCommandSupported(command)) { 28251 let msg = editor.translate(`Your browser doesn't support direct access to the clipboard. ` + 'Please use the Ctrl+X/C/V keyboard shortcuts instead.'); 28252 if (Env.os.isMacOS() || Env.os.isiOS()) { 28253 msg = msg.replace(/Ctrl\+/g, '\u2318+'); 28254 } 28255 editor.notificationManager.open({ 28256 text: msg, 28257 type: 'error' 28258 }); 28259 } 28260 } 28261 }); 28262 }; 28263 28264 const trimOrPadLeftRight = (dom, rng, html) => { 28265 const root = SugarElement.fromDom(dom.getRoot()); 28266 if (needsToBeNbspLeft(root, CaretPosition.fromRangeStart(rng))) { 28267 html = html.replace(/^ /, ' '); 28268 } else { 28269 html = html.replace(/^ /, ' '); 28270 } 28271 if (needsToBeNbspRight(root, CaretPosition.fromRangeEnd(rng))) { 28272 html = html.replace(/( | )(<br( \/)>)?$/, ' '); 28273 } else { 28274 html = html.replace(/ (<br( \/)?>)?$/, ' '); 28275 } 28276 return html; 28277 }; 28278 28279 const processValue$1 = value => { 28280 if (typeof value !== 'string') { 28281 const details = Tools.extend({ 28282 paste: value.paste, 28283 data: { paste: value.paste } 28284 }, value); 28285 return { 28286 content: value.content, 28287 details 28288 }; 28289 } 28290 return { 28291 content: value, 28292 details: {} 28293 }; 28294 }; 28295 const trimOrPad = (editor, value) => { 28296 const selection = editor.selection; 28297 const dom = editor.dom; 28298 if (/^ | $/.test(value)) { 28299 return trimOrPadLeftRight(dom, selection.getRng(), value); 28300 } else { 28301 return value; 28302 } 28303 }; 28304 const insertAtCaret = (editor, value) => { 28305 if (editor.selection.isEditable()) { 28306 const {content, details} = processValue$1(value); 28307 preProcessSetContent(editor, { 28308 ...details, 28309 content: trimOrPad(editor, content), 28310 format: 'html', 28311 set: false, 28312 selection: true 28313 }).each(args => { 28314 const insertedContent = insertContent$1(editor, args.content, details); 28315 postProcessSetContent(editor, insertedContent, args); 28316 editor.addVisual(); 28317 }); 28318 } 28319 }; 28320 28321 const registerCommands$8 = editor => { 28322 editor.editorCommands.addCommands({ 28323 mceCleanup: () => { 28324 const bm = editor.selection.getBookmark(); 28325 editor.setContent(editor.getContent()); 28326 editor.selection.moveToBookmark(bm); 28327 }, 28328 insertImage: (_command, _ui, value) => { 28329 insertAtCaret(editor, editor.dom.createHTML('img', { src: value })); 28330 }, 28331 insertHorizontalRule: () => { 28332 editor.execCommand('mceInsertContent', false, '<hr>'); 28333 }, 28334 insertText: (_command, _ui, value) => { 28335 insertAtCaret(editor, editor.dom.encode(value)); 28336 }, 28337 insertHTML: (_command, _ui, value) => { 28338 insertAtCaret(editor, value); 28339 }, 28340 mceInsertContent: (_command, _ui, value) => { 28341 insertAtCaret(editor, value); 28342 }, 28343 mceSetContent: (_command, _ui, value) => { 28344 editor.setContent(value); 28345 }, 28346 mceReplaceContent: (_command, _ui, value) => { 28347 editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, editor.selection.getContent({ format: 'text' }))); 28348 }, 28349 mceNewDocument: () => { 28350 editor.setContent(''
vendor: 7,989 bytes, lines 28350-28549
28350); 28351 } 28352 }); 28353 }; 28354 28355 const legacyPropNames = { 28356 'font-size': 'size', 28357 'font-family': 'face' 28358 }; 28359 const isFont = isTag('font'); 28360 const getSpecifiedFontProp = (propName, rootElm, elm) => { 28361 const getProperty = elm => getRaw(elm, propName).orThunk(() => { 28362 if (isFont(elm)) { 28363 return get$a(legacyPropNames, propName).bind(legacyPropName => getOpt(elm, legacyPropName)); 28364 } else { 28365 return Optional.none(); 28366 } 28367 }); 28368 const isRoot = elm => eq(SugarElement.fromDom(rootElm), elm); 28369 return closest$1(SugarElement.fromDom(elm), elm => getProperty(elm), isRoot); 28370 }; 28371 const normalizeFontFamily = fontFamily => fontFamily.replace(/[\'\"\\]/g, '').replace(/,\s+/g, ','); 28372 const getComputedFontProp = (propName, elm) => Optional.from(DOMUtils.DOM.getStyle(elm, propName, true)); 28373 const getFontProp = propName => (rootElm, elm) => Optional.from(elm).map(SugarElement.fromDom).filter(isElement$7).bind(element => getSpecifiedFontProp(propName, rootElm, element.dom).or(getComputedFontProp(propName, element.dom))).getOr(''); 28374 const getFontSize = getFontProp('font-size'); 28375 const getFontFamily = compose(normalizeFontFamily, getFontProp('font-family')); 28376 28377 const findFirstCaretElement = editor => firstPositionIn(editor.getBody()).bind(caret => { 28378 const container = caret.container(); 28379 return Optional.from(isText$a(container) ? container.parentNode : container); 28380 }); 28381 const getCaretElement = editor => Optional.from(editor.selection.getRng()).bind(rng => { 28382 const root = editor.getBody(); 28383 const atStartOfNode = rng.startContainer === root && rng.startOffset === 0; 28384 return atStartOfNode ? Optional.none() : Optional.from(editor.selection.getStart(true)); 28385 }); 28386 const bindRange = (editor, binder) => getCaretElement(editor).orThunk(curry(findFirstCaretElement, editor)).map(SugarElement.fromDom).filter(isElement$7).bind(binder); 28387 const mapRange = (editor, mapper) => bindRange(editor, compose1(Optional.some, mapper)); 28388 28389 const fromFontSizeNumber = (editor, value) => { 28390 if (/^[0-9.]+$/.test(value)) { 28391 const fontSizeNumber = parseInt(value, 10); 28392 if (fontSizeNumber >= 1 && fontSizeNumber <= 7) { 28393 const fontSizes = getFontStyleValues(editor); 28394 const fontClasses = getFontSizeClasses(editor); 28395 if (fontClasses.length > 0) { 28396 return fontClasses[fontSizeNumber - 1] || value; 28397 } else { 28398 return fontSizes[fontSizeNumber - 1] || value; 28399 } 28400 } else { 28401 return value; 28402 } 28403 } else { 28404 return value; 28405 } 28406 }; 28407 const normalizeFontNames = font => { 28408 const fonts = font.split(/\s*,\s*/); 28409 return map$3(fonts, font => { 28410 if (font.indexOf(' ') !== -1 && !(startsWith(font, '"') || startsWith(font, `'`))) { 28411 return `'${ font }'`; 28412 } else { 28413 return font; 28414 } 28415 }).join(','); 28416 }; 28417 const fontNameAction = (editor, value) => { 28418 const font = fromFontSizeNumber(editor, value); 28419 editor.formatter.toggle('fontname', { value: normalizeFontNames(font) }); 28420 editor.nodeChanged(); 28421 }; 28422 const fontNameQuery = editor => mapRange(editor, elm => getFontFamily(editor.getBody(), elm.dom)).getOr(''); 28423 const fontSizeAction = (editor, value) => { 28424 editor.formatter.toggle('fontsize', { value: fromFontSizeNumber(editor, value) }); 28425 editor.nodeChanged(); 28426 }; 28427 const fontSizeQuery = editor => mapRange(editor, elm => getFontSize(editor.getBody(), elm.dom)).getOr(''); 28428 28429 const lineHeightQuery = editor => mapRange(editor, elm => { 28430 const root = SugarElement.fromDom(editor.getBody()); 28431 const specifiedStyle = closest$1(elm, elm => getRaw(elm, 'line-height'), curry(eq, root)); 28432 const computedStyle = () => { 28433 const lineHeight = parseFloat(get$7(elm, 'line-height')); 28434 const fontSize = parseFloat(get$7(elm, 'font-size')); 28435 return String(lineHeight / fontSize); 28436 }; 28437 return specifiedStyle.getOrThunk(computedStyle); 28438 }).getOr(''); 28439 const lineHeightAction = (editor, lineHeight) => { 28440 editor.formatter.toggle('lineheight', { value: String(lineHeight) }); 28441 editor.nodeChanged(); 28442 }; 28443 28444 const registerExecCommands$2 = editor => { 28445 const toggleFormat = (name, value) => { 28446 editor.formatter.toggle(name, value); 28447 editor.nodeChanged(); 28448 }; 28449 editor.editorCommands.addCommands({ 28450 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': command => { 28451 toggleFormat(command); 28452 }, 28453 'ForeColor,HiliteColor': (command, _ui, value) => { 28454 toggleFormat(command, { value }); 28455 }, 28456 'BackColor': (_command, _ui, value) => { 28457 toggleFormat('hilitecolor', { value }); 28458 }, 28459 'FontName': (_command, _ui, value) => { 28460 fontNameAction(editor, value); 28461 }, 28462 'FontSize': (_command, _ui, value) => { 28463 fontSizeAction(editor, value); 28464 }, 28465 'LineHeight': (_command, _ui, value) => { 28466 lineHeightAction(editor, value); 28467 }, 28468 'Lang': (command, _ui, lang) => { 28469 var _a; 28470 toggleFormat(command, { 28471 value: lang.code, 28472 customValue: (_a = lang.customCode) !== null && _a !== void 0 ? _a : null 28473 }); 28474 }, 28475 'RemoveFormat': command => { 28476 editor.formatter.remove(command); 28477 }, 28478 'mceBlockQuote': () => { 28479 toggleFormat('blockquote'); 28480 }, 28481 'FormatBlock': (_command, _ui, value) => { 28482 toggleFormat(isString(value) ? value : 'p'); 28483 }, 28484 'mceToggleFormat': (_command, _ui, value) => { 28485 toggleFormat(value); 28486 } 28487 }); 28488 }; 28489 const registerQueryValueCommands = editor => { 28490 const isFormatMatch = name => editor.formatter.match(name); 28491 editor.editorCommands.addCommands({ 28492 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': command => isFormatMatch(command), 28493 'mceBlockQuote': () => isFormatMatch('blockquote') 28494 }, 'state'); 28495 editor.editorCommands.addQueryValueHandler('FontName', () => fontNameQuery(editor)); 28496 editor.editorCommands.addQueryValueHandler('FontSize', () => fontSizeQuery(editor)); 28497 editor.editorCommands.addQueryValueHandler('LineHeight', () => lineHeightQuery(editor)); 28498 }; 28499 const registerCommands$7 = editor => { 28500 registerExecCommands$2(editor); 28501 registerQueryValueCommands(editor); 28502 }; 28503 28504 const registerCommands$6 = editor => { 28505 editor.editorCommands.addCommands({ 28506 mceAddUndoLevel: () => { 28507 editor.undoManager.add(); 28508 }, 28509 mceEndUndoLevel: () => { 28510 editor.undoManager.add(); 28511 }, 28512 Undo: () => { 28513 editor.undoManager.undo(); 28514 }, 28515 Redo: () => { 28516 editor.undoManager.redo(); 28517 } 28518 }); 28519 }; 28520 28521 const registerCommands$5 = editor => { 28522 editor.editorCommands.addCommands({ 28523 Indent: () => { 28524 indent(editor); 28525 }, 28526 Outdent: () => { 28527 outdent(editor); 28528 } 28529 }); 28530 editor.editorCommands.addCommands({ Outdent: () => canOutdent(editor) }, 'state'); 28531 }; 28532 28533 const registerCommands$4 = editor => { 28534 const applyLinkToSelection = (_command, _ui, value) => { 28535 const linkDetails = isString(value) ? { href: value } : value; 28536 const anchor = editor.dom.getParent(editor.selection.getNode(), 'a'); 28537 if (isObject(linkDetails) && isString(linkDetails.href)) { 28538 linkDetails.href = linkDetails.href.replace(/ /g, '%20'); 28539 if (!anchor || !linkDetails.href) { 28540 editor.formatter.remove('link'); 28541 } 28542 if (linkDetails.href) { 28543 editor.formatter.apply('link', linkDetails, anchor); 28544 } 28545 } 28546 }; 28547 editor.editorCommands.addCommands({ 28548 unlink: () => { 28549 if (editor.selection.is
vendor: 3,364 bytes, lines 28549-28643
28549Collapsed()) { 28550 const elm = editor.dom.getParent(editor.selection.getStart(), 'a'); 28551 if (elm) { 28552 editor.dom.remove(elm, true); 28553 } 28554 return; 28555 } 28556 editor.formatter.remove('link'); 28557 }, 28558 mceInsertLink: applyLinkToSelection, 28559 createLink: applyLinkToSelection 28560 }); 28561 }; 28562 28563 const registerExecCommands$1 = editor => { 28564 editor.editorCommands.addCommands({ 28565 'InsertUnorderedList,InsertOrderedList': command => { 28566 editor.getDoc().execCommand(command); 28567 const listElm = editor.dom.getParent(editor.selection.getNode(), 'ol,ul'); 28568 if (listElm) { 28569 const listParent = listElm.parentNode; 28570 if (listParent && /^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) { 28571 const bm = editor.selection.getBookmark(); 28572 editor.dom.split(listParent, listElm); 28573 editor.selection.moveToBookmark(bm); 28574 } 28575 } 28576 } 28577 }); 28578 }; 28579 const registerQueryStateCommands = editor => { 28580 editor.editorCommands.addCommands({ 28581 'InsertUnorderedList,InsertOrderedList': command => { 28582 const list = editor.dom.getParent(editor.selection.getNode(), 'ul,ol'); 28583 return list && (command === 'insertunorderedlist' && list.tagName === 'UL' || command === 'insertorderedlist' && list.tagName === 'OL'); 28584 } 28585 }, 'state'); 28586 }; 28587 const registerCommands$3 = editor => { 28588 registerExecCommands$1(editor); 28589 registerQueryStateCommands(editor); 28590 }; 28591 28592 const registerCommands$2 = editor => { 28593 editor.editorCommands.addCommands({ 28594 insertParagraph: () => { 28595 insertBreak(blockbreak, editor); 28596 }, 28597 mceInsertNewLine: (_command, _ui, value) => { 28598 insert(editor, value); 28599 }, 28600 InsertLineBreak: (_command, _ui, _value) => { 28601 insertBreak(linebreak, editor); 28602 } 28603 }); 28604 }; 28605 28606 const registerCommands$1 = editor => { 28607 editor.editorCommands.addCommands({ 28608 mceSelectNodeDepth: (_command, _ui, value) => { 28609 let counter = 0; 28610 editor.dom.getParent(editor.selection.getNode(), node => { 28611 if (isElement$6(node) && counter++ === value) { 28612 editor.selection.select(node); 28613 return false; 28614 } else { 28615 return true; 28616 } 28617 }, editor.getBody()); 28618 }, 28619 mceSelectNode: (_command, _ui, value) => { 28620 editor.selection.select(value); 28621 }, 28622 selectAll: () => { 28623 const editingHost = editor.dom.getParent(editor.selection.getStart(), isContentEditableTrue$3); 28624 if (editingHost) { 28625 const rng = editor.dom.createRng(); 28626 rng.selectNodeContents(editingHost); 28627 editor.selection.setRng(rng); 28628 } 28629 } 28630 }); 28631 }; 28632 28633 const registerExecCommands = editor => { 28634 editor.editorCommands.addCommands({ 28635 mceRemoveNode: (_command, _ui, value) => { 28636 const node = value !== null && value !== void 0 ? value : editor.selection.getNode(); 28637 if (node !== editor.getBody()) { 28638 const bm = editor.selection.getBookmark(); 28639 editor.dom.remove(node, true); 28640 editor.selection.moveToBookmark(bm); 28641 } 28642 }, 28643 mcePrint: () => {
vendor: 8,603 bytes, lines 28644-28883
28644 editor.getWin().print(); 28645 }, 28646 mceFocus: (_command, _ui, value) => { 28647 focus(editor, value === true); 28648 }, 28649 mceToggleVisualAid: () => { 28650 editor.hasVisual = !editor.hasVisual; 28651 editor.addVisual(); 28652 } 28653 }); 28654 }; 28655 const registerCommands = editor => { 28656 registerCommands$a(editor); 28657 registerCommands$9(editor); 28658 registerCommands$6(editor); 28659 registerCommands$1(editor); 28660 registerCommands$8(editor); 28661 registerCommands$4(editor); 28662 registerCommands$5(editor); 28663 registerCommands$2(editor); 28664 registerCommands$3(editor); 28665 registerCommands$7(editor); 28666 registerExecCommands(editor); 28667 }; 28668 28669 const selectionSafeCommands = ['toggleview']; 28670 const isSelectionSafeCommand = command => contains$2(selectionSafeCommands, command.toLowerCase()); 28671 class EditorCommands { 28672 constructor(editor) { 28673 this.commands = { 28674 state: {}, 28675 exec: {}, 28676 value: {} 28677 }; 28678 this.editor = editor; 28679 } 28680 execCommand(command, ui = false, value, args) { 28681 const editor = this.editor; 28682 const lowerCaseCommand = command.toLowerCase(); 28683 const skipFocus = args === null || args === void 0 ? void 0 : args.skip_focus; 28684 if (editor.removed) { 28685 return false; 28686 } 28687 if (lowerCaseCommand !== 'mcefocus') { 28688 if (!/^(mceAddUndoLevel|mceEndUndoLevel)$/i.test(lowerCaseCommand) && !skipFocus) { 28689 editor.focus(); 28690 } else { 28691 restore(editor); 28692 } 28693 } 28694 const eventArgs = editor.dispatch('BeforeExecCommand', { 28695 command, 28696 ui, 28697 value 28698 }); 28699 if (eventArgs.isDefaultPrevented()) { 28700 return false; 28701 } 28702 const func = this.commands.exec[lowerCaseCommand]; 28703 if (isFunction(func)) { 28704 func(lowerCaseCommand, ui, value); 28705 editor.dispatch('ExecCommand', { 28706 command, 28707 ui, 28708 value 28709 }); 28710 return true; 28711 } 28712 return false; 28713 } 28714 queryCommandState(command) { 28715 if (!isSelectionSafeCommand(command) && this.editor.quirks.isHidden() || this.editor.removed) { 28716 return false; 28717 } 28718 const lowerCaseCommand = command.toLowerCase(); 28719 const func = this.commands.state[lowerCaseCommand]; 28720 if (isFunction(func)) { 28721 return func(lowerCaseCommand); 28722 } 28723 return false; 28724 } 28725 queryCommandValue(command) { 28726 if (!isSelectionSafeCommand(command) && this.editor.quirks.isHidden() || this.editor.removed) { 28727 return ''; 28728 } 28729 const lowerCaseCommand = command.toLowerCase(); 28730 const func = this.commands.value[lowerCaseCommand]; 28731 if (isFunction(func)) { 28732 return func(lowerCaseCommand); 28733 } 28734 return ''; 28735 } 28736 addCommands(commandList, type = 'exec') { 28737 const commands = this.commands; 28738 each$d(commandList, (callback, command) => { 28739 each$e(command.toLowerCase().split(','), command => { 28740 commands[type][command] = callback; 28741 }); 28742 }); 28743 } 28744 addCommand(command, callback, scope) { 28745 const lowerCaseCommand = command.toLowerCase(); 28746 this.commands.exec[lowerCaseCommand] = (_command, ui, value) => callback.call(scope !== null && scope !== void 0 ? scope : this.editor, ui, value); 28747 } 28748 queryCommandSupported(command) { 28749 const lowerCaseCommand = command.toLowerCase(); 28750 if (this.commands.exec[lowerCaseCommand]) { 28751 return true; 28752 } else { 28753 return false; 28754 } 28755 } 28756 addQueryStateHandler(command, callback, scope) { 28757 this.commands.state[command.toLowerCase()] = () => callback.call(scope !== null && scope !== void 0 ? scope : this.editor); 28758 } 28759 addQueryValueHandler(command, callback, scope) { 28760 this.commands.value[command.toLowerCase()] = () => callback.call(scope !== null && scope !== void 0 ? scope : this.editor); 28761 } 28762 } 28763 28764 const internalContentEditableAttr = 'data-mce-contenteditable'; 28765 const toggleClass = (elm, cls, state) => { 28766 if (has(elm, cls) && !state) { 28767 remove$8(elm, cls); 28768 } else if (state) { 28769 add$2(elm, cls); 28770 } 28771 }; 28772 const setEditorCommandState = (editor, cmd, state) => { 28773 try { 28774 editor.getDoc().execCommand(cmd, false, String(state)); 28775 } catch (ex) { 28776 } 28777 }; 28778 const setContentEditable = (elm, state) => { 28779 elm.dom.contentEditable = state ? 'true' : 'false'; 28780 }; 28781 const switchOffContentEditableTrue = elm => { 28782 each$e(descendants(elm, '*[contenteditable="true"]'), elm => { 28783 set$3(elm, internalContentEditableAttr, 'true'); 28784 setContentEditable(elm, false); 28785 }); 28786 }; 28787 const switchOnContentEditableTrue = elm => { 28788 each$e(descendants(elm, `*[${ internalContentEditableAttr }="true"]`), elm => { 28789 remove$b(elm, internalContentEditableAttr); 28790 setContentEditable(elm, true); 28791 }); 28792 }; 28793 const removeFakeSelection = editor => { 28794 Optional.from(editor.selection.getNode()).each(elm => { 28795 elm.removeAttribute('data-mce-selected'); 28796 }); 28797 }; 28798 const restoreFakeSelection = editor => { 28799 editor.selection.setRng(editor.selection.getRng()); 28800 }; 28801 const toggleReadOnly = (editor, state) => { 28802 const body = SugarElement.fromDom(editor.getBody()); 28803 toggleClass(body, 'mce-content-readonly', state); 28804 if (state) { 28805 editor.selection.controlSelection.hideResizeRect(); 28806 editor._selectionOverrides.hideFakeCaret(); 28807 removeFakeSelection(editor); 28808 editor.readonly = true; 28809 setContentEditable(body, false); 28810 switchOffContentEditableTrue(body); 28811 } else { 28812 editor.readonly = false; 28813 setContentEditable(body, true); 28814 switchOnContentEditableTrue(body); 28815 setEditorCommandState(editor, 'StyleWithCSS', false); 28816 setEditorCommandState(editor, 'enableInlineTableEditing', false); 28817 setEditorCommandState(editor, 'enableObjectResizing', false); 28818 if (hasEditorOrUiFocus(editor)) { 28819 editor.focus(); 28820 } 28821 restoreFakeSelection(editor); 28822 editor.nodeChanged(); 28823 } 28824 }; 28825 const isReadOnly = editor => editor.readonly; 28826 const registerFilters = editor => { 28827 editor.parser.addAttributeFilter('contenteditable', nodes => { 28828 if (isReadOnly(editor)) { 28829 each$e(nodes, node => { 28830 node.attr(internalContentEditableAttr, node.attr('contenteditable')); 28831 node.attr('contenteditable', 'false'); 28832 }); 28833 } 28834 }); 28835 editor.serializer.addAttributeFilter(internalContentEditableAttr, nodes => { 28836 if (isReadOnly(editor)) { 28837 each$e(nodes, node => { 28838 node.attr('contenteditable', node.attr(internalContentEditableAttr)); 28839 }); 28840 } 28841 }); 28842 editor.serializer.addTempAttr(internalContentEditableAttr); 28843 }; 28844 const registerReadOnlyContentFilters = editor => { 28845 if (editor.serializer) { 28846 registerFilters(editor); 28847 } else { 28848 editor.on('PreInit', () => { 28849 registerFilters(editor); 28850 }); 28851 } 28852 }; 28853 const isClickEvent = e => e.type === 'click'; 28854 const allowedEvents = ['copy']; 28855 const isReadOnlyAllowedEvent = e => contains$2(allowedEvents, e.type); 28856 const getAnchorHrefOpt = (editor, elm) => { 28857 const isRoot = elm => eq(elm, SugarElement.fromDom(editor.getBody())); 28858 return closest$3(elm, 'a', isRoot).bind(a => getOpt(a, 'href')); 28859 }; 28860 const processReadonlyEvents = (editor, e) => { 28861 if (isClickEvent(e) && !VK.metaKeyPressed(e)) { 28862 const elm = SugarElement.fromDom(e.target); 28863 getAnchorHrefOpt(editor, elm).each(href => { 28864 e.preventDefault(); 28865 if (/^#/.test(href)) { 28866 const targetEl = editor.dom.select(`${ href },[name="${ removeLeading(href, '#') }"]`); 28867 if (targetEl.length) { 28868 editor.selection.scrollIntoView(targetEl[0], true); 28869 } 28870 } else { 28871 window.open(href, '_blank', 'rel=noopener noreferrer,menubar=yes,toolbar=yes,location=yes,status=yes,resizable=yes,scrollbars=yes'); 28872 } 28873 }); 28874 } else if (isReadOnlyAllowedEvent(e)) { 28875 editor.dispatch(e.type, e); 28876 } 28877 }; 28878 const registerReadOnlySelectionBlockers = editor => { 28879 editor.on('ShowCaret', e => { 28880 if (isReadOnly(editor)) { 28881 e.preventDefault(); 28882 } 28883 });
28884 editor.on('ObjectSelected', e => { 28885 if (isReadOnly(editor)) { 28886 e.preventDefault(); 28887 } 28888 }); 28889 }; 28890 28891 const nativeEvents = Tools.makeMap('focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange ' + 'mouseout mouseenter mouseleave wheel keydown keypress keyup input beforeinput contextmenu dragstart dragend dragover ' + 'draggesture dragdrop drop drag submit ' + 'compositionstart compositionend compositionupdate touchstart touchmove touchend touchcancel', ' '); 28892 class EventDispatcher { 28893 constructor(settings) { 28894 this.bindings = {}; 28895 this.settings = settings || {}; 28896 this.scope = this.settings.scope || this; 28897 this.toggleEvent = this.settings.toggleEvent || never; 28898 } 28899 static isNative(name) { 28900 return !!nativeEvents[name.toLowerCase()]
vendor: 34,147 bytes, lines 28900-29970
28900; 28901 } 28902 fire(name, args) { 28903 return this.dispatch(name, args); 28904 } 28905 dispatch(name, args) { 28906 const lcName = name.toLowerCase(); 28907 const event = normalize$3(lcName, args !== null && args !== void 0 ? args : {}, this.scope); 28908 if (this.settings.beforeFire) { 28909 this.settings.beforeFire(event); 28910 } 28911 const handlers = this.bindings[lcName]; 28912 if (handlers) { 28913 for (let i = 0, l = handlers.length; i < l; i++) { 28914 const callback = handlers[i]; 28915 if (callback.removed) { 28916 continue; 28917 } 28918 if (callback.once) { 28919 this.off(lcName, callback.func); 28920 } 28921 if (event.isImmediatePropagationStopped()) { 28922 return event; 28923 } 28924 if (callback.func.call(this.scope, event) === false) { 28925 event.preventDefault(); 28926 return event; 28927 } 28928 } 28929 } 28930 return event; 28931 } 28932 on(name, callback, prepend, extra) { 28933 if (callback === false) { 28934 callback = never; 28935 } 28936 if (callback) { 28937 const wrappedCallback = { 28938 func: callback, 28939 removed: false 28940 }; 28941 if (extra) { 28942 Tools.extend(wrappedCallback, extra); 28943 } 28944 const names = name.toLowerCase().split(' '); 28945 let i = names.length; 28946 while (i--) { 28947 const currentName = names[i]; 28948 let handlers = this.bindings[currentName]; 28949 if (!handlers) { 28950 handlers = []; 28951 this.toggleEvent(currentName, true); 28952 } 28953 if (prepend) { 28954 handlers = [ 28955 wrappedCallback, 28956 ...handlers 28957 ]; 28958 } else { 28959 handlers = [ 28960 ...handlers, 28961 wrappedCallback 28962 ]; 28963 } 28964 this.bindings[currentName] = handlers; 28965 } 28966 } 28967 return this; 28968 } 28969 off(name, callback) { 28970 if (name) { 28971 const names = name.toLowerCase().split(' '); 28972 let i = names.length; 28973 while (i--) { 28974 const currentName = names[i]; 28975 let handlers = this.bindings[currentName]; 28976 if (!currentName) { 28977 each$d(this.bindings, (_value, bindingName) => { 28978 this.toggleEvent(bindingName, false); 28979 delete this.bindings[bindingName]; 28980 }); 28981 return this; 28982 } 28983 if (handlers) { 28984 if (!callback) { 28985 handlers.length = 0; 28986 } else { 28987 const filteredHandlers = partition$2(handlers, handler => handler.func === callback); 28988 handlers = filteredHandlers.fail; 28989 this.bindings[currentName] = handlers; 28990 each$e(filteredHandlers.pass, handler => { 28991 handler.removed = true; 28992 }); 28993 } 28994 if (!handlers.length) { 28995 this.toggleEvent(name, false); 28996 delete this.bindings[currentName]; 28997 } 28998 } 28999 } 29000 } else { 29001 each$d(this.bindings, (_value, name) => { 29002 this.toggleEvent(name, false); 29003 }); 29004 this.bindings = {}; 29005 } 29006 return this; 29007 } 29008 once(name, callback, prepend) { 29009 return this.on(name, callback, prepend, { once: true }); 29010 } 29011 has(name) { 29012 name = name.toLowerCase(); 29013 const binding = this.bindings[name]; 29014 return !(!binding || binding.length === 0); 29015 } 29016 } 29017 29018 const getEventDispatcher = obj => { 29019 if (!obj._eventDispatcher) { 29020 obj._eventDispatcher = new EventDispatcher({ 29021 scope: obj, 29022 toggleEvent: (name, state) => { 29023 if (EventDispatcher.isNative(name) && obj.toggleNativeEvent) { 29024 obj.toggleNativeEvent(name, state); 29025 } 29026 } 29027 }); 29028 } 29029 return obj._eventDispatcher; 29030 }; 29031 const Observable = { 29032 fire(name, args, bubble) { 29033 return this.dispatch(name, args, bubble); 29034 }, 29035 dispatch(name, args, bubble) { 29036 const self = this; 29037 if (self.removed && name !== 'remove' && name !== 'detach') { 29038 return normalize$3(name.toLowerCase(), args !== null && args !== void 0 ? args : {}, self); 29039 } 29040 const dispatcherArgs = getEventDispatcher(self).dispatch(name, args); 29041 if (bubble !== false && self.parent) { 29042 let parent = self.parent(); 29043 while (parent && !dispatcherArgs.isPropagationStopped()) { 29044 parent.dispatch(name, dispatcherArgs, false); 29045 parent = parent.parent ? parent.parent() : undefined; 29046 } 29047 } 29048 return dispatcherArgs; 29049 }, 29050 on(name, callback, prepend) { 29051 return getEventDispatcher(this).on(name, callback, prepend); 29052 }, 29053 off(name, callback) { 29054 return getEventDispatcher(this).off(name, callback); 29055 }, 29056 once(name, callback) { 29057 return getEventDispatcher(this).once(name, callback); 29058 }, 29059 hasEventListeners(name) { 29060 return getEventDispatcher(this).has(name); 29061 } 29062 }; 29063 29064 const DOM$2 = DOMUtils.DOM; 29065 let customEventRootDelegates; 29066 const getEventTarget = (editor, eventName) => { 29067 if (eventName === 'selectionchange') { 29068 return editor.getDoc(); 29069 } 29070 if (!editor.inline && /^(?:mouse|touch|click|contextmenu|drop|dragover|dragend)/.test(eventName)) { 29071 return editor.getDoc().documentElement; 29072 } 29073 const eventRoot = getEventRoot(editor); 29074 if (eventRoot) { 29075 if (!editor.eventRoot) { 29076 editor.eventRoot = DOM$2.select(eventRoot)[0]; 29077 } 29078 return editor.eventRoot; 29079 } 29080 return editor.getBody(); 29081 }; 29082 const isListening = editor => !editor.hidden && !isReadOnly(editor); 29083 const fireEvent = (editor, eventName, e) => { 29084 if (isListening(editor)) { 29085 editor.dispatch(eventName, e); 29086 } else if (isReadOnly(editor)) { 29087 processReadonlyEvents(editor, e); 29088 } 29089 }; 29090 const bindEventDelegate = (editor, eventName) => { 29091 if (!editor.delegates) { 29092 editor.delegates = {}; 29093 } 29094 if (editor.delegates[eventName] || editor.removed) { 29095 return; 29096 } 29097 const eventRootElm = getEventTarget(editor, eventName); 29098 if (getEventRoot(editor)) { 29099 if (!customEventRootDelegates) { 29100 customEventRootDelegates = {}; 29101 editor.editorManager.on('removeEditor', () => { 29102 if (!editor.editorManager.activeEditor) { 29103 if (customEventRootDelegates) { 29104 each$d(customEventRootDelegates, (_value, name) => { 29105 editor.dom.unbind(getEventTarget(editor, name)); 29106 }); 29107 customEventRootDelegates = null; 29108 } 29109 } 29110 }); 29111 } 29112 if (customEventRootDelegates[eventName]) { 29113 return; 29114 } 29115 const delegate = e => { 29116 const target = e.target; 29117 const editors = editor.editorManager.get(); 29118 let i = editors.length; 29119 while (i--) { 29120 const body = editors[i].getBody(); 29121 if (body === target || DOM$2.isChildOf(target, body)) { 29122 fireEvent(editors[i], eventName, e); 29123 } 29124 } 29125 }; 29126 customEventRootDelegates[eventName] = delegate; 29127 DOM$2.bind(eventRootElm, eventName, delegate); 29128 } else { 29129 const delegate = e => { 29130 fireEvent(editor, eventName, e); 29131 }; 29132 DOM$2.bind(eventRootElm, eventName, delegate); 29133 editor.delegates[eventName] = delegate; 29134 } 29135 }; 29136 const EditorObservable = { 29137 ...Observable, 29138 bindPendingEventDelegates() { 29139 const self = this; 29140 Tools.each(self._pendingNativeEvents, name => { 29141 bindEventDelegate(self, name); 29142 }); 29143 }, 29144 toggleNativeEvent(name, state) { 29145 const self = this; 29146 if (name === 'focus' || name === 'blur') { 29147 return; 29148 } 29149 if (self.removed) { 29150 return; 29151 } 29152 if (state) { 29153 if (self.initialized) { 29154 bindEventDelegate(self, name); 29155 } else { 29156 if (!self._pendingNativeEvents) { 29157 self._pendingNativeEvents = [name]; 29158 } else { 29159 self._pendingNativeEvents.push(name); 29160 } 29161 } 29162 } else if (self.initialized && self.delegates) { 29163 self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]); 29164 delete self.delegates[name]; 29165 } 29166 }, 29167 unbindAllNativeEvents() { 29168 const self = this; 29169 const body = self.getBody(); 29170 const dom = self.dom; 29171 if (self.delegates) { 29172 each$d(self.delegates, (value, name) => { 29173 self.dom.unbind(getEventTarget(self, name), name, value); 29174 }); 29175 delete self.delegates; 29176 } 29177 if (!self.inline && body && dom) { 29178 body.onload = null; 29179 dom.unbind(self.getWin()); 29180 dom.unbind(self.getDoc()); 29181 } 29182 if (dom) { 29183 dom.unbind(body); 29184 dom.unbind(self.getContainer()); 29185 } 29186 } 29187 }; 29188 29189 const stringListProcessor = value => { 29190 if (isString(value)) { 29191 return { 29192 value: value.split(/[ ,]/), 29193 valid: true 29194 }; 29195 } else if (isArrayOf(value, isString)) { 29196 return { 29197 value, 29198 valid: true 29199 }; 29200 } else { 29201 return { 29202 valid: false, 29203 message: `The value must be a string[] or a comma/space separated string.` 29204 }; 29205 } 29206 }; 29207 const getBuiltInProcessor = type => { 29208 const validator = (() => { 29209 switch (type) { 29210 case 'array': 29211 return isArray$1; 29212 case 'boolean': 29213 return isBoolean; 29214 case 'function': 29215 return isFunction; 29216 case 'number': 29217 return isNumber; 29218 case 'object': 29219 return isObject; 29220 case 'string': 29221 return isString; 29222 case 'string[]': 29223 return stringListProcessor; 29224 case 'object[]': 29225 return val => isArrayOf(val, isObject); 29226 case 'regexp': 29227 return val => is$4(val, RegExp); 29228 default: 29229 return always; 29230 } 29231 })(); 29232 return value => processValue(value, validator, `The value must be a ${ type }.`); 29233 }; 29234 const isBuiltInSpec = spec => isString(spec.processor); 29235 const getErrorMessage = (message, result) => { 29236 const additionalText = isEmpty$3(result.message) ? '' : `. ${ result.message }`; 29237 return message + additionalText; 29238 }; 29239 const isValidResult = result => result.valid; 29240 const processValue = (value, processor, message = '') => { 29241 const result = processor(value); 29242 if (isBoolean(result)) { 29243 return result ? { 29244 value: value, 29245 valid: true 29246 } : { 29247 valid: false, 29248 message 29249 }; 29250 } else { 29251 return result; 29252 } 29253 }; 29254 const processDefaultValue = (name, defaultValue, processor) => { 29255 if (!isUndefined(defaultValue)) { 29256 const result = processValue(defaultValue, processor); 29257 if (isValidResult(result)) { 29258 return result.value; 29259 } else { 29260 console.error(getErrorMessage(`Invalid default value passed for the "${ name }" option`, result)); 29261 } 29262 } 29263 return undefined; 29264 }; 29265 const create$5 = (editor, initialOptions) => { 29266 const registry = {}; 29267 const values = {}; 29268 const setValue = (name, value, processor) => { 29269 const result = processValue(value, processor); 29270 if (isValidResult(result)) { 29271 values[name] = result.value; 29272 return true; 29273 } else { 29274 console.warn(getErrorMessage(`Invalid value passed for the ${ name } option`, result)); 29275 return false; 29276 } 29277 }; 29278 const register = (name, spec) => { 29279 const processor = isBuiltInSpec(spec) ? getBuiltInProcessor(spec.processor) : spec.processor; 29280 const defaultValue = processDefaultValue(name, spec.default, processor); 29281 registry[name] = { 29282 ...spec, 29283 default: defaultValue, 29284 processor 29285 }; 29286 const initValue = get$a(values, name).orThunk(() => get$a(initialOptions, name)); 29287 initValue.each(value => setValue(name, value, processor)); 29288 }; 29289 const isRegistered = name => has$2(registry, name); 29290 const get = name => get$a(values, name).orThunk(() => get$a(registry, name).map(spec => spec.default)).getOrUndefined(); 29291 const set = (name, value) => { 29292 if (!isRegistered(name)) { 29293 console.warn(`"${ name }" is not a registered option. Ensure the option has been registered before setting a value.`); 29294 return false; 29295 } else { 29296 const spec = registry[name]; 29297 if (spec.immutable) { 29298 console.error(`"${ name }" is an immutable option and cannot be updated`); 29299 return false; 29300 } else { 29301 return setValue(name, value, spec.processor); 29302 } 29303 } 29304 }; 29305 const unset = name => { 29306 const registered = isRegistered(name); 29307 if (registered) { 29308 delete values[name]; 29309 } 29310 return registered; 29311 }; 29312 const isSet = name => has$2(values, name); 29313 return { 29314 register, 29315 isRegistered, 29316 get, 29317 set, 29318 unset, 29319 isSet 29320 }; 29321 }; 29322 29323 const defaultModes = [ 29324 'design', 29325 'readonly' 29326 ]; 29327 const switchToMode = (editor, activeMode, availableModes, mode) => { 29328 const oldMode = availableModes[activeMode.get()]; 29329 const newMode = availableModes[mode]; 29330 try { 29331 newMode.activate(); 29332 } catch (e) { 29333 console.error(`problem while activating editor mode ${ mode }:`, e); 29334 return; 29335 } 29336 oldMode.deactivate(); 29337 if (oldMode.editorReadOnly !== newMode.editorReadOnly) { 29338 toggleReadOnly(editor, newMode.editorReadOnly); 29339 } 29340 activeMode.set(mode); 29341 fireSwitchMode(editor, mode); 29342 }; 29343 const setMode = (editor, availableModes, activeMode, mode) => { 29344 if (mode === activeMode.get()) { 29345 return; 29346 } else if (!has$2(availableModes, mode)) { 29347 throw new Error(`Editor mode '${ mode }' is invalid`); 29348 } 29349 if (editor.initialized) { 29350 switchToMode(editor, activeMode, availableModes, mode); 29351 } else { 29352 editor.on('init', () => switchToMode(editor, activeMode, availableModes, mode)); 29353 } 29354 }; 29355 const registerMode = (availableModes, mode, api) => { 29356 if (contains$2(defaultModes, mode)) { 29357 throw new Error(`Cannot override default mode ${ mode }`); 29358 } 29359 return { 29360 ...availableModes, 29361 [mode]: { 29362 ...api, 29363 deactivate: () => { 29364 try { 29365 api.deactivate(); 29366 } catch (e) { 29367 console.error(`problem while deactivating editor mode ${ mode }:`, e); 29368 } 29369 } 29370 } 29371 }; 29372 }; 29373 29374 const create$4 = editor => { 29375 const activeMode = Cell('design'); 29376 const availableModes = Cell({ 29377 design: { 29378 activate: noop, 29379 deactivate: noop, 29380 editorReadOnly: false 29381 }, 29382 readonly: { 29383 activate: noop, 29384 deactivate: noop, 29385 editorReadOnly: true 29386 } 29387 }); 29388 registerReadOnlyContentFilters(editor); 29389 registerReadOnlySelectionBlockers(editor); 29390 return { 29391 isReadOnly: () => isReadOnly(editor), 29392 set: mode => setMode(editor, availableModes.get(), activeMode, mode), 29393 get: () => activeMode.get(), 29394 register: (mode, api) => { 29395 availableModes.set(registerMode(availableModes.get(), mode, api)); 29396 } 29397 }; 29398 }; 29399 29400 const each$2 = Tools.each, explode = Tools.explode; 29401 const keyCodeLookup = { 29402 f1: 112, 29403 f2: 113, 29404 f3: 114, 29405 f4: 115, 29406 f5: 116, 29407 f6: 117, 29408 f7: 118, 29409 f8: 119, 29410 f9: 120, 29411 f10: 121, 29412 f11: 122, 29413 f12: 123 29414 }; 29415 const modifierNames = Tools.makeMap('alt,ctrl,shift,meta,access'); 29416 const isModifier = key => key in modifierNames; 29417 const parseShortcut = pattern => { 29418 const shortcut = {}; 29419 const isMac = Env.os.isMacOS() || Env.os.isiOS(); 29420 each$2(explode(pattern.toLowerCase(), '+'), value => { 29421 if (isModifier(value)) { 29422 shortcut[value] = true; 29423 } else { 29424 if (/^[0-9]{2,}$/.test(value)) { 29425 shortcut.keyCode = parseInt(value, 10); 29426 } else { 29427 shortcut.charCode = value.charCodeAt(0); 29428 shortcut.keyCode = keyCodeLookup[value] || value.toUpperCase().charCodeAt(0); 29429 } 29430 } 29431 }); 29432 const id = [shortcut.keyCode]; 29433 let key; 29434 for (key in modifierNames) { 29435 if (shortcut[key]) { 29436 id.push(key); 29437 } else { 29438 shortcut[key] = false; 29439 } 29440 } 29441 shortcut.id = id.join(','); 29442 if (shortcut.access) { 29443 shortcut.alt = true; 29444 if (isMac) { 29445 shortcut.ctrl = true; 29446 } else { 29447 shortcut.shift = true; 29448 } 29449 } 29450 if (shortcut.meta) { 29451 if (isMac) { 29452 shortcut.meta = true; 29453 } else { 29454 shortcut.ctrl = true; 29455 shortcut.meta = false; 29456 } 29457 } 29458 return shortcut; 29459 }; 29460 class Shortcuts { 29461 constructor(editor) { 29462 this.shortcuts = {}; 29463 this.pendingPatterns = []; 29464 this.editor = editor; 29465 const self = this; 29466 editor.on('keyup keypress keydown', e => { 29467 if ((self.hasModifier(e) || self.isFunctionKey(e)) && !e.isDefaultPrevented()) { 29468 each$2(self.shortcuts, shortcut => { 29469 if (self.matchShortcut(e, shortcut)) { 29470 self.pendingPatterns = shortcut.subpatterns.slice(0); 29471 if (e.type === 'keydown') { 29472 self.executeShortcutAction(shortcut); 29473 } 29474 } 29475 }); 29476 if (self.matchShortcut(e, self.pendingPatterns[0])) { 29477 if (self.pendingPatterns.length === 1) { 29478 if (e.type === 'keydown') { 29479 self.executeShortcutAction(self.pendingPatterns[0]); 29480 } 29481 } 29482 self.pendingPatterns.shift(); 29483 } 29484 } 29485 }); 29486 } 29487 add(pattern, desc, cmdFunc, scope) { 29488 const self = this; 29489 const func = self.normalizeCommandFunc(cmdFunc); 29490 each$2(explode(Tools.trim(pattern)), pattern => { 29491 const shortcut = self.createShortcut(pattern, desc, func, scope); 29492 self.shortcuts[shortcut.id] = shortcut; 29493 }); 29494 return true; 29495 } 29496 remove(pattern) { 29497 const shortcut = this.createShortcut(pattern); 29498 if (this.shortcuts[shortcut.id]) { 29499 delete this.shortcuts[shortcut.id]; 29500 return true; 29501 } 29502 return false; 29503 } 29504 normalizeCommandFunc(cmdFunc) { 29505 const self = this; 29506 const cmd = cmdFunc; 29507 if (typeof cmd === 'string') { 29508 return () => { 29509 self.editor.execCommand(cmd, false, null); 29510 }; 29511 } else if (Tools.isArray(cmd)) { 29512 return () => { 29513 self.editor.execCommand(cmd[0], cmd[1], cmd[2]); 29514 }; 29515 } else { 29516 return cmd; 29517 } 29518 } 29519 createShortcut(pattern, desc, cmdFunc, scope) { 29520 const shortcuts = Tools.map(explode(pattern, '>'), parseShortcut); 29521 shortcuts[shortcuts.length - 1] = Tools.extend(shortcuts[shortcuts.length - 1], { 29522 func: cmdFunc, 29523 scope: scope || this.editor 29524 }); 29525 return Tools.extend(shortcuts[0], { 29526 desc: this.editor.translate(desc), 29527 subpatterns: shortcuts.slice(1) 29528 }); 29529 } 29530 hasModifier(e) { 29531 return e.altKey || e.ctrlKey || e.metaKey; 29532 } 29533 isFunctionKey(e) { 29534 return e.type === 'keydown' && e.keyCode >= 112 && e.keyCode <= 123; 29535 } 29536 matchShortcut(e, shortcut) { 29537 if (!shortcut) { 29538 return false; 29539 } 29540 if (shortcut.ctrl !== e.ctrlKey || shortcut.meta !== e.metaKey) { 29541 return false; 29542 } 29543 if (shortcut.alt !== e.altKey || shortcut.shift !== e.shiftKey) { 29544 return false; 29545 } 29546 if (e.keyCode === shortcut.keyCode || e.charCode && e.charCode === shortcut.charCode) { 29547 e.preventDefault(); 29548 return true; 29549 } 29550 return false; 29551 } 29552 executeShortcutAction(shortcut) { 29553 return shortcut.func ? shortcut.func.call(shortcut.scope) : null; 29554 } 29555 } 29556 29557 const create$3 = () => { 29558 const buttons = {}; 29559 const menuItems = {}; 29560 const popups = {}; 29561 const icons = {}; 29562 const contextMenus = {}; 29563 const contextToolbars = {}; 29564 const sidebars = {}; 29565 const views = {}; 29566 const add = (collection, type) => (name, spec) => { 29567 collection[name.toLowerCase()] = { 29568 ...spec, 29569 type 29570 }; 29571 }; 29572 const addIcon = (name, svgData) => icons[name.toLowerCase()] = svgData; 29573 return { 29574 addButton: add(buttons, 'button'), 29575 addGroupToolbarButton: add(buttons, 'grouptoolbarbutton'), 29576 addToggleButton: add(buttons, 'togglebutton'), 29577 addMenuButton: add(buttons, 'menubutton'), 29578 addSplitButton: add(buttons, 'splitbutton'), 29579 addMenuItem: add(menuItems, 'menuitem'), 29580 addNestedMenuItem: add(menuItems, 'nestedmenuitem'), 29581 addToggleMenuItem: add(menuItems, 'togglemenuitem'), 29582 addAutocompleter: add(popups, 'autocompleter'), 29583 addContextMenu: add(contextMenus, 'contextmenu'), 29584 addContextToolbar: add(contextToolbars, 'contexttoolbar'), 29585 addContextForm: add(contextToolbars, 'contextform'), 29586 addSidebar: add(sidebars, 'sidebar'), 29587 addView: add(views, 'views'), 29588 addIcon, 29589 getAll: () => ({ 29590 buttons, 29591 menuItems, 29592 icons, 29593 popups, 29594 contextMenus, 29595 contextToolbars, 29596 sidebars, 29597 views 29598 }) 29599 }; 29600 }; 29601 29602 const registry = () => { 29603 const bridge = create$3(); 29604 return { 29605 addAutocompleter: bridge.addAutocompleter, 29606 addButton: bridge.addButton, 29607 addContextForm: bridge.addContextForm, 29608 addContextMenu: bridge.addContextMenu, 29609 addContextToolbar: bridge.addContextToolbar, 29610 addIcon: bridge.addIcon, 29611 addMenuButton: bridge.addMenuButton, 29612 addMenuItem: bridge.addMenuItem, 29613 addNestedMenuItem: bridge.addNestedMenuItem, 29614 addSidebar: bridge.addSidebar, 29615 addSplitButton: bridge.addSplitButton, 29616 addToggleButton: bridge.addToggleButton, 29617 addGroupToolbarButton: bridge.addGroupToolbarButton, 29618 addToggleMenuItem: bridge.addToggleMenuItem, 29619 addView: bridge.addView, 29620 getAll: bridge.getAll 29621 }; 29622 }; 29623 29624 const DOM$1 = DOMUtils.DOM; 29625 const extend = Tools.extend, each$1 = Tools.each; 29626 class Editor { 29627 constructor(id, options, editorManager) { 29628 this.plugins = {}; 29629 this.contentCSS = []; 29630 this.contentStyles = []; 29631 this.loadedCSS = {}; 29632 this.isNotDirty = false; 29633 this.composing = false; 29634 this.destroyed = false; 29635 this.hasHiddenInput = false; 29636 this.iframeElement = null; 29637 this.initialized = false; 29638 this.readonly = false; 29639 this.removed = false; 29640 this.startContent = ''; 29641 this._pendingNativeEvents = []; 29642 this._skinLoaded = false; 29643 this.editorManager = editorManager; 29644 this.documentBaseUrl = editorManager.documentBaseURL; 29645 extend(this, EditorObservable); 29646 const self = this; 29647 this.id = id; 29648 this.hidden = false; 29649 const normalizedOptions = normalizeOptions(editorManager.defaultOptions, options); 29650 this.options = create$5(self, normalizedOptions); 29651 register$7(self); 29652 const getOption = this.options.get; 29653 if (getOption('deprecation_warnings')) { 29654 logWarnings(options, normalizedOptions); 29655 } 29656 const suffix = getOption('suffix'); 29657 if (suffix) { 29658 editorManager.suffix = suffix; 29659 } 29660 this.suffix = editorManager.suffix; 29661 const baseUrl = getOption('base_url'); 29662 if (baseUrl) { 29663 editorManager._setBaseUrl(baseUrl); 29664 } 29665 this.baseUri = editorManager.baseURI; 29666 const referrerPolicy = getReferrerPolicy(self); 29667 if (referrerPolicy) { 29668 ScriptLoader.ScriptLoader._setReferrerPolicy(referrerPolicy); 29669 DOMUtils.DOM.styleSheetLoader._setReferrerPolicy(referrerPolicy); 29670 } 29671 const contentCssCors = hasContentCssCors(self); 29672 if (isNonNullable(contentCssCors)) { 29673 DOMUtils.DOM.styleSheetLoader._setContentCssCors(contentCssCors); 29674 } 29675 AddOnManager.languageLoad = getOption('language_load'); 29676 AddOnManager.baseURL = editorManager.baseURL; 29677 this.setDirty(false); 29678 this.documentBaseURI = new URI(getDocumentBaseUrl(self), { base_uri: this.baseUri }); 29679 this.baseURI = this.baseUri; 29680 this.inline = isInline(self); 29681 this.hasVisual = isVisualAidsEnabled(self); 29682 this.shortcuts = new Shortcuts(this); 29683 this.editorCommands = new EditorCommands(this); 29684 registerCommands(this); 29685 const cacheSuffix = getOption('cache_suffix'); 29686 if (cacheSuffix) { 29687 Env.cacheSuffix = cacheSuffix.replace(/^[\?\&]+/, ''); 29688 } 29689 this.ui = { 29690 registry: registry(), 29691 styleSheetLoader: undefined, 29692 show: noop, 29693 hide: noop, 29694 setEnabled: noop, 29695 isEnabled: always 29696 }; 29697 this.mode = create$4(self); 29698 editorManager.dispatch('SetupEditor', { editor: this }); 29699 const setupCallback = getSetupCallback(self); 29700 if (isFunction(setupCallback)) { 29701 setupCallback.call(self, self); 29702 } 29703 } 29704 render() { 29705 render(this); 29706 } 29707 focus(skipFocus) { 29708 this.execCommand('mceFocus', false, skipFocus); 29709 } 29710 hasFocus() { 29711 return hasFocus(this); 29712 } 29713 translate(text) { 29714 return I18n.translate(text); 29715 } 29716 getParam(name, defaultVal, type) { 29717 const options = this.options; 29718 if (!options.isRegistered(name)) { 29719 if (isNonNullable(type)) { 29720 options.register(name, { 29721 processor: type, 29722 default: defaultVal 29723 }); 29724 } else { 29725 options.register(name, { 29726 processor: always, 29727 default: defaultVal 29728 }); 29729 } 29730 } 29731 return !options.isSet(name) && !isUndefined(defaultVal) ? defaultVal : options.get(name); 29732 } 29733 hasPlugin(name, loaded) { 29734 const hasPlugin = contains$2(getPlugins(this), name); 29735 if (hasPlugin) { 29736 return loaded ? PluginManager.get(name) !== undefined : true; 29737 } else { 29738 return false; 29739 } 29740 } 29741 nodeChanged(args) { 29742 this._nodeChangeDispatcher.nodeChanged(args); 29743 } 29744 addCommand(name, callback, scope) { 29745 this.editorCommands.addCommand(name, callback, scope); 29746 } 29747 addQueryStateHandler(name, callback, scope) { 29748 this.editorCommands.addQueryStateHandler(name, callback, scope); 29749 } 29750 addQueryValueHandler(name, callback, scope) { 29751 this.editorCommands.addQueryValueHandler(name, callback, scope); 29752 } 29753 addShortcut(pattern, desc, cmdFunc, scope) { 29754 this.shortcuts.add(pattern, desc, cmdFunc, scope); 29755 } 29756 execCommand(cmd, ui, value, args) { 29757 return this.editorCommands.execCommand(cmd, ui, value, args); 29758 } 29759 queryCommandState(cmd) { 29760 return this.editorCommands.queryCommandState(cmd); 29761 } 29762 queryCommandValue(cmd) { 29763 return this.editorCommands.queryCommandValue(cmd); 29764 } 29765 queryCommandSupported(cmd) { 29766 return this.editorCommands.queryCommandSupported(cmd); 29767 } 29768 show() { 29769 const self = this; 29770 if (self.hidden) { 29771 self.hidden = false; 29772 if (self.inline) { 29773 self.getBody().contentEditable = 'true'; 29774 } else { 29775 DOM$1.show(self.getContainer()); 29776 DOM$1.hide(self.id); 29777 } 29778 self.load(); 29779 self.dispatch('show'); 29780 } 29781 } 29782 hide() { 29783 const self = this; 29784 if (!self.hidden) { 29785 self.save(); 29786 if (self.inline) { 29787 self.getBody().contentEditable = 'false'; 29788 if (self === self.editorManager.focusedEditor) { 29789 self.editorManager.focusedEditor = null; 29790 } 29791 } else { 29792 DOM$1.hide(self.getContainer()); 29793 DOM$1.setStyle(self.id, 'display', self.orgDisplay); 29794 } 29795 self.hidden = true; 29796 self.dispatch('hide'); 29797 } 29798 } 29799 isHidden() { 29800 return this.hidden; 29801 } 29802 setProgressState(state, time) { 29803 this.dispatch('ProgressState', { 29804 state, 29805 time 29806 }); 29807 } 29808 load(args = {}) { 29809 const self = this; 29810 const elm = self.getElement(); 29811 if (self.removed) { 29812 return ''; 29813 } 29814 if (elm) { 29815 const loadArgs = { 29816 ...args, 29817 load: true 29818 }; 29819 const value = isTextareaOrInput(elm) ? elm.value : elm.innerHTML; 29820 const html = self.setContent(value, loadArgs); 29821 if (!loadArgs.no_events) { 29822 self.dispatch('LoadContent', { 29823 ...loadArgs, 29824 element: elm 29825 }); 29826 } 29827 return html; 29828 } else { 29829 return ''; 29830 } 29831 } 29832 save(args = {}) { 29833 const self = this; 29834 let elm = self.getElement(); 29835 if (!elm || !self.initialized || self.removed) { 29836 return ''; 29837 } 29838 const getArgs = { 29839 ...args, 29840 save: true, 29841 element: elm 29842 }; 29843 let html = self.getContent(getArgs); 29844 const saveArgs = { 29845 ...getArgs, 29846 content: html 29847 }; 29848 if (!saveArgs.no_events) { 29849 self.dispatch('SaveContent', saveArgs); 29850 } 29851 if (saveArgs.format === 'raw') { 29852 self.dispatch('RawSaveContent', saveArgs); 29853 } 29854 html = saveArgs.content; 29855 if (!isTextareaOrInput(elm)) { 29856 if (args.is_removing || !self.inline) { 29857 elm.innerHTML = html; 29858 } 29859 const form = DOM$1.getParent(self.id, 'form'); 29860 if (form) { 29861 each$1(form.elements, elm => { 29862 if (elm.name === self.id) { 29863 elm.value = html; 29864 return false; 29865 } else { 29866 return true; 29867 } 29868 }); 29869 } 29870 } else { 29871 elm.value = html; 29872 } 29873 saveArgs.element = getArgs.element = elm = null; 29874 if (saveArgs.set_dirty !== false) { 29875 self.setDirty(false); 29876 } 29877 return html; 29878 } 29879 setContent(content, args) { 29880 return setContent(this, content, args); 29881 } 29882 getContent(args) { 29883 return getContent(this, args); 29884 } 29885 insertContent(content, args) { 29886 if (args) { 29887 content = extend({ content }, args); 29888 } 29889 this.execCommand('mceInsertContent', false, content); 29890 } 29891 resetContent(initialContent) { 29892 if (initialContent === undefined) { 29893 setContent(this, this.startContent, { format: 'raw' }); 29894 } else { 29895 setContent(this, initialContent); 29896 } 29897 this.undoManager.reset(); 29898 this.setDirty(false); 29899 this.nodeChanged(); 29900 } 29901 isDirty() { 29902 return !this.isNotDirty; 29903 } 29904 setDirty(state) { 29905 const oldState = !this.isNotDirty; 29906 this.isNotDirty = !state; 29907 if (state && state !== oldState) { 29908 this.dispatch('dirty'); 29909 } 29910 } 29911 getContainer() { 29912 const self = this; 29913 if (!self.container) { 29914 self.container = self.editorContainer || DOM$1.get(self.id + '_parent'); 29915 } 29916 return self.container; 29917 } 29918 getContentAreaContainer() { 29919 return this.contentAreaContainer; 29920 } 29921 getElement() { 29922 if (!this.targetElm) { 29923 this.targetElm = DOM$1.get(this.id); 29924 } 29925 return this.targetElm; 29926 } 29927 getWin() { 29928 const self = this; 29929 if (!self.contentWindow) { 29930 const elm = self.iframeElement; 29931 if (elm) { 29932 self.contentWindow = elm.contentWindow; 29933 } 29934 } 29935 return self.contentWindow; 29936 } 29937 getDoc() { 29938 const self = this; 29939 if (!self.contentDocument) { 29940 const win = self.getWin(); 29941 if (win) { 29942 self.contentDocument = win.document; 29943 } 29944 } 29945 return self.contentDocument; 29946 } 29947 getBody() { 29948 var _a, _b; 29949 const doc = this.getDoc(); 29950 return (_b = (_a = this.bodyElement) !== null && _a !== void 0 ? _a : doc === null || doc === void 0 ? void 0 : doc.body) !== null && _b !== void 0 ? _b : null; 29951 } 29952 convertURL(url, name, elm) { 29953 const self = this, getOption = self.options.get; 29954 const urlConverterCallback = getUrlConverterCallback(self); 29955 if (isFunction(urlConverterCallback)) { 29956 return urlConverterCallback.call(self, url, elm, true, name); 29957 } 29958 if (!getOption('convert_urls') || elm === 'link' || isObject(elm) && elm.nodeName === 'LINK' || url.indexOf('file:') === 0 || url.length === 0) { 29959 return url; 29960 } 29961 if (getOption('relative_urls')) { 29962 return self.documentBaseURI.toRelative(url); 29963 } 29964 url = self.documentBaseURI.toAbsolute(url, getOption('remove_script_host')); 29965 return url; 29966 } 29967 addVisual(elm) { 29968 addVisual(this, elm); 29969 } 29970
vendor: 2,318 bytes, lines 29970-30046
29970remove() { 29971 remove$1(this); 29972 } 29973 destroy(automatic) { 29974 destroy(this, automatic); 29975 } 29976 uploadImages() { 29977 return this.editorUpload.uploadImages(); 29978 } 29979 _scanForImages() { 29980 return this.editorUpload.scanForImages(); 29981 } 29982 } 29983 29984 const DOM = DOMUtils.DOM; 29985 const each = Tools.each; 29986 let boundGlobalEvents = false; 29987 let beforeUnloadDelegate; 29988 let editors = []; 29989 const globalEventDelegate = e => { 29990 const type = e.type; 29991 each(EditorManager.get(), editor => { 29992 switch (type) { 29993 case 'scroll': 29994 editor.dispatch('ScrollWindow', e); 29995 break; 29996 case 'resize': 29997 editor.dispatch('ResizeWindow', e); 29998 break; 29999 } 30000 }); 30001 }; 30002 const toggleGlobalEvents = state => { 30003 if (state !== boundGlobalEvents) { 30004 const DOM = DOMUtils.DOM; 30005 if (state) { 30006 DOM.bind(window, 'resize', globalEventDelegate); 30007 DOM.bind(window, 'scroll', globalEventDelegate); 30008 } else { 30009 DOM.unbind(window, 'resize', globalEventDelegate); 30010 DOM.unbind(window, 'scroll', globalEventDelegate); 30011 } 30012 boundGlobalEvents = state; 30013 } 30014 }; 30015 const removeEditorFromList = targetEditor => { 30016 const oldEditors = editors; 30017 editors = filter$5(editors, editor => { 30018 return targetEditor !== editor; 30019 }); 30020 if (EditorManager.activeEditor === targetEditor) { 30021 EditorManager.activeEditor = editors.length > 0 ? editors[0] : null; 30022 } 30023 if (EditorManager.focusedEditor === targetEditor) { 30024 EditorManager.focusedEditor = null; 30025 } 30026 return oldEditors.length !== editors.length; 30027 }; 30028 const purgeDestroyedEditor = editor => { 30029 if (editor && editor.initialized && !(editor.getContainer() || editor.getBody()).parentNode) { 30030 removeEditorFromList(editor); 30031 editor.unbindAllNativeEvents(); 30032 editor.destroy(true); 30033 editor.removed = true; 30034 } 30035 }; 30036 const isQuirksMode = document.compatMode !== 'CSS1Compat'; 30037 const EditorManager = { 30038 ...Observable, 30039 baseURI: null, 30040 baseURL: null, 30041 defaultOptions: {}, 30042 documentBaseURL: null, 30043 suffix: null, 30044 majorVersion: '6', 30045 minorVersion: '4.2', 30046 releaseDate: '2023-04-26
vendor: 18,364 bytes, lines 30046-30653
30046', 30047 i18n: I18n, 30048 activeEditor: null, 30049 focusedEditor: null, 30050 setup() { 30051 const self = this; 30052 let baseURL = ''; 30053 let suffix = ''; 30054 let documentBaseURL = URI.getDocumentBaseUrl(document.location); 30055 if (/^[^:]+:\/\/\/?[^\/]+\//.test(documentBaseURL)) { 30056 documentBaseURL = documentBaseURL.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, ''); 30057 if (!/[\/\\]$/.test(documentBaseURL)) { 30058 documentBaseURL += '/'; 30059 } 30060 } 30061 const preInit = window.tinymce || window.tinyMCEPreInit; 30062 if (preInit) { 30063 baseURL = preInit.base || preInit.baseURL; 30064 suffix = preInit.suffix; 30065 } else { 30066 const scripts = document.getElementsByTagName('script'); 30067 for (let i = 0; i < scripts.length; i++) { 30068 const src = scripts[i].src || ''; 30069 if (src === '') { 30070 continue; 30071 } 30072 const srcScript = src.substring(src.lastIndexOf('/')); 30073 if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) { 30074 if (srcScript.indexOf('.min') !== -1) { 30075 suffix = '.min'; 30076 } 30077 baseURL = src.substring(0, src.lastIndexOf('/')); 30078 break; 30079 } 30080 } 30081 if (!baseURL && document.currentScript) { 30082 const src = document.currentScript.src; 30083 if (src.indexOf('.min') !== -1) { 30084 suffix = '.min'; 30085 } 30086 baseURL = src.substring(0, src.lastIndexOf('/')); 30087 } 30088 } 30089 self.baseURL = new URI(documentBaseURL).toAbsolute(baseURL); 30090 self.documentBaseURL = documentBaseURL; 30091 self.baseURI = new URI(self.baseURL); 30092 self.suffix = suffix; 30093 setup$v(self); 30094 }, 30095 overrideDefaults(defaultOptions) { 30096 const baseUrl = defaultOptions.base_url; 30097 if (baseUrl) { 30098 this._setBaseUrl(baseUrl); 30099 } 30100 const suffix = defaultOptions.suffix; 30101 if (suffix) { 30102 this.suffix = suffix; 30103 } 30104 this.defaultOptions = defaultOptions; 30105 const pluginBaseUrls = defaultOptions.plugin_base_urls; 30106 if (pluginBaseUrls !== undefined) { 30107 each$d(pluginBaseUrls, (pluginBaseUrl, pluginName) => { 30108 AddOnManager.PluginManager.urls[pluginName] = pluginBaseUrl; 30109 }); 30110 } 30111 }, 30112 init(options) { 30113 const self = this; 30114 let result; 30115 const invalidInlineTargets = Tools.makeMap('area base basefont br col frame hr img input isindex link meta param embed source wbr track ' + 'colgroup option table tbody tfoot thead tr th td script noscript style textarea video audio iframe object menu', ' '); 30116 const isInvalidInlineTarget = (options, elm) => options.inline && elm.tagName.toLowerCase() in invalidInlineTargets; 30117 const createId = elm => { 30118 let id = elm.id; 30119 if (!id) { 30120 id = get$a(elm, 'name').filter(name => !DOM.get(name)).getOrThunk(DOM.uniqueId); 30121 elm.setAttribute('id', id); 30122 } 30123 return id; 30124 }; 30125 const execCallback = name => { 30126 const callback = options[name]; 30127 if (!callback) { 30128 return; 30129 } 30130 return callback.apply(self, []); 30131 }; 30132 const findTargets = options => { 30133 if (Env.browser.isIE() || Env.browser.isEdge()) { 30134 initError('TinyMCE does not support the browser you are using. For a list of supported' + ' browsers please see: https://www.tiny.cloud/docs/tinymce/6/support/#supportedwebbrowsers'); 30135 return []; 30136 } else if (isQuirksMode) { 30137 initError('Failed to initialize the editor as the document is not in standards mode. ' + 'TinyMCE requires standards mode.'); 30138 return []; 30139 } else if (isString(options.selector)) { 30140 return DOM.select(options.selector); 30141 } else if (isNonNullable(options.target)) { 30142 return [options.target]; 30143 } else { 30144 return []; 30145 } 30146 }; 30147 let provideResults = editors => { 30148 result = editors; 30149 }; 30150 const initEditors = () => { 30151 let initCount = 0; 30152 const editors = []; 30153 let targets; 30154 const createEditor = (id, options, targetElm) => { 30155 const editor = new Editor(id, options, self); 30156 editors.push(editor); 30157 editor.on('init', () => { 30158 if (++initCount === targets.length) { 30159 provideResults(editors); 30160 } 30161 }); 30162 editor.targetElm = editor.targetElm || targetElm; 30163 editor.render(); 30164 }; 30165 DOM.unbind(window, 'ready', initEditors); 30166 execCallback('onpageload'); 30167 targets = unique$1(findTargets(options)); 30168 Tools.each(targets, elm => { 30169 purgeDestroyedEditor(self.get(elm.id)); 30170 }); 30171 targets = Tools.grep(targets, elm => { 30172 return !self.get(elm.id); 30173 }); 30174 if (targets.length === 0) { 30175 provideResults([]); 30176 } else { 30177 each(targets, elm => { 30178 if (isInvalidInlineTarget(options, elm)) { 30179 initError('Could not initialize inline editor on invalid inline target element', elm); 30180 } else { 30181 createEditor(createId(elm), options, elm); 30182 } 30183 }); 30184 } 30185 }; 30186 DOM.bind(window, 'ready', initEditors); 30187 return new Promise(resolve => { 30188 if (result) { 30189 resolve(result); 30190 } else { 30191 provideResults = editors => { 30192 resolve(editors); 30193 }; 30194 } 30195 }); 30196 }, 30197 get(id) { 30198 if (arguments.length === 0) { 30199 return editors.slice(0); 30200 } else if (isString(id)) { 30201 return find$2(editors, editor => { 30202 return editor.id === id; 30203 }).getOr(null); 30204 } else if (isNumber(id)) { 30205 return editors[id] ? editors[id] : null; 30206 } else { 30207 return null; 30208 } 30209 }, 30210 add(editor) { 30211 const self = this; 30212 const existingEditor = self.get(editor.id); 30213 if (existingEditor === editor) { 30214 return editor; 30215 } 30216 if (existingEditor === null) { 30217 editors.push(editor); 30218 } 30219 toggleGlobalEvents(true); 30220 self.activeEditor = editor; 30221 self.dispatch('AddEditor', { editor }); 30222 if (!beforeUnloadDelegate) { 30223 beforeUnloadDelegate = e => { 30224 const event = self.dispatch('BeforeUnload'); 30225 if (event.returnValue) { 30226 e.preventDefault(); 30227 e.returnValue = event.returnValue; 30228 return event.returnValue; 30229 } 30230 }; 30231 window.addEventListener('beforeunload', beforeUnloadDelegate); 30232 } 30233 return editor; 30234 }, 30235 createEditor(id, options) { 30236 return this.add(new Editor(id, options, this)); 30237 }, 30238 remove(selector) { 30239 const self = this; 30240 let editor; 30241 if (!selector) { 30242 for (let i = editors.length - 1; i >= 0; i--) { 30243 self.remove(editors[i]); 30244 } 30245 return; 30246 } 30247 if (isString(selector)) { 30248 each(DOM.select(selector), elm => { 30249 editor = self.get(elm.id); 30250 if (editor) { 30251 self.remove(editor); 30252 } 30253 }); 30254 return; 30255 } 30256 editor = selector; 30257 if (isNull(self.get(editor.id))) { 30258 return null; 30259 } 30260 if (removeEditorFromList(editor)) { 30261 self.dispatch('RemoveEditor', { editor }); 30262 } 30263 if (editors.length === 0) { 30264 window.removeEventListener('beforeunload', beforeUnloadDelegate); 30265 } 30266 editor.remove(); 30267 toggleGlobalEvents(editors.length > 0); 30268 return editor; 30269 }, 30270 execCommand(cmd, ui, value) { 30271 var _a; 30272 const self = this; 30273 const editorId = isObject(value) ? (_a = value.id) !== null && _a !== void 0 ? _a : value.index : value; 30274 switch (cmd) { 30275 case 'mceAddEditor': { 30276 if (!self.get(editorId)) { 30277 const editorOptions = value.options; 30278 new Editor(editorId, editorOptions, self).render(); 30279 } 30280 return true; 30281 } 30282 case 'mceRemoveEditor': { 30283 const editor = self.get(editorId); 30284 if (editor) { 30285 editor.remove(); 30286 } 30287 return true; 30288 } 30289 case 'mceToggleEditor': { 30290 const editor = self.get(editorId); 30291 if (!editor) { 30292 self.execCommand('mceAddEditor', false, value); 30293 return true; 30294 } 30295 if (editor.isHidden()) { 30296 editor.show(); 30297 } else { 30298 editor.hide(); 30299 } 30300 return true; 30301 } 30302 } 30303 if (self.activeEditor) { 30304 return self.activeEditor.execCommand(cmd, ui, value); 30305 } 30306 return false; 30307 }, 30308 triggerSave: () => { 30309 each(editors, editor => { 30310 editor.save(); 30311 }); 30312 }, 30313 addI18n: (code, items) => { 30314 I18n.add(code, items); 30315 }, 30316 translate: text => { 30317 return I18n.translate(text); 30318 }, 30319 setActive(editor) { 30320 const activeEditor = this.activeEditor; 30321 if (this.activeEditor !== editor) { 30322 if (activeEditor) { 30323 activeEditor.dispatch('deactivate', { relatedTarget: editor }); 30324 } 30325 editor.dispatch('activate', { relatedTarget: activeEditor }); 30326 } 30327 this.activeEditor = editor; 30328 }, 30329 _setBaseUrl(baseUrl) { 30330 this.baseURL = new URI(this.documentBaseURL).toAbsolute(baseUrl.replace(/\/+$/, '')); 30331 this.baseURI = new URI(this.baseURL); 30332 } 30333 }; 30334 EditorManager.setup(); 30335 30336 const setup = () => { 30337 const dataValue = value$2(); 30338 const FakeClipboardItem = items => ({ 30339 items, 30340 types: keys(items), 30341 getType: type => get$a(items, type).getOrUndefined() 30342 }); 30343 const write = data => { 30344 dataValue.set(data); 30345 }; 30346 const read = () => dataValue.get().getOrUndefined(); 30347 const clear = dataValue.clear; 30348 return { 30349 FakeClipboardItem, 30350 write, 30351 read, 30352 clear 30353 }; 30354 }; 30355 const FakeClipboard = setup(); 30356 30357 const min = Math.min, max = Math.max, round = Math.round; 30358 const relativePosition = (rect, targetRect, rel) => { 30359 let x = targetRect.x; 30360 let y = targetRect.y; 30361 const w = rect.w; 30362 const h = rect.h; 30363 const targetW = targetRect.w; 30364 const targetH = targetRect.h; 30365 const relChars = (rel || '').split(''); 30366 if (relChars[0] === 'b') { 30367 y += targetH; 30368 } 30369 if (relChars[1] === 'r') { 30370 x += targetW; 30371 } 30372 if (relChars[0] === 'c') { 30373 y += round(targetH / 2); 30374 } 30375 if (relChars[1] === 'c') { 30376 x += round(targetW / 2); 30377 } 30378 if (relChars[3] === 'b') { 30379 y -= h; 30380 } 30381 if (relChars[4] === 'r') { 30382 x -= w; 30383 } 30384 if (relChars[3] === 'c') { 30385 y -= round(h / 2); 30386 } 30387 if (relChars[4] === 'c') { 30388 x -= round(w / 2); 30389 } 30390 return create$2(x, y, w, h); 30391 }; 30392 const findBestRelativePosition = (rect, targetRect, constrainRect, rels) => { 30393 for (let i = 0; i < rels.length; i++) { 30394 const pos = relativePosition(rect, targetRect, rels[i]); 30395 if (pos.x >= constrainRect.x && pos.x + pos.w <= constrainRect.w + constrainRect.x && pos.y >= constrainRect.y && pos.y + pos.h <= constrainRect.h + constrainRect.y) { 30396 return rels[i]; 30397 } 30398 } 30399 return null; 30400 }; 30401 const inflate = (rect, w, h) => { 30402 return create$2(rect.x - w, rect.y - h, rect.w + w * 2, rect.h + h * 2); 30403 }; 30404 const intersect = (rect, cropRect) => { 30405 const x1 = max(rect.x, cropRect.x); 30406 const y1 = max(rect.y, cropRect.y); 30407 const x2 = min(rect.x + rect.w, cropRect.x + cropRect.w); 30408 const y2 = min(rect.y + rect.h, cropRect.y + cropRect.h); 30409 if (x2 - x1 < 0 || y2 - y1 < 0) { 30410 return null; 30411 } 30412 return create$2(x1, y1, x2 - x1, y2 - y1); 30413 }; 30414 const clamp = (rect, clampRect, fixedSize) => { 30415 let x1 = rect.x; 30416 let y1 = rect.y; 30417 let x2 = rect.x + rect.w; 30418 let y2 = rect.y + rect.h; 30419 const cx2 = clampRect.x + clampRect.w; 30420 const cy2 = clampRect.y + clampRect.h; 30421 const underflowX1 = max(0, clampRect.x - x1); 30422 const underflowY1 = max(0, clampRect.y - y1); 30423 const overflowX2 = max(0, x2 - cx2); 30424 const overflowY2 = max(0, y2 - cy2); 30425 x1 += underflowX1; 30426 y1 += underflowY1; 30427 if (fixedSize) { 30428 x2 += underflowX1; 30429 y2 += underflowY1; 30430 x1 -= overflowX2; 30431 y1 -= overflowY2; 30432 } 30433 x2 -= overflowX2; 30434 y2 -= overflowY2; 30435 return create$2(x1, y1, x2 - x1, y2 - y1); 30436 }; 30437 const create$2 = (x, y, w, h) => { 30438 return { 30439 x, 30440 y, 30441 w, 30442 h 30443 }; 30444 }; 30445 const fromClientRect = clientRect => { 30446 return create$2(clientRect.left, clientRect.top, clientRect.width, clientRect.height); 30447 }; 30448 const Rect = { 30449 inflate, 30450 relativePosition, 30451 findBestRelativePosition, 30452 intersect, 30453 clamp, 30454 create: create$2, 30455 fromClientRect 30456 }; 30457 30458 const awaiter = (resolveCb, rejectCb, timeout = 1000) => { 30459 let done = false; 30460 let timer = null; 30461 const complete = completer => (...args) => { 30462 if (!done) { 30463 done = true; 30464 if (timer !== null) { 30465 clearTimeout(timer); 30466 timer = null; 30467 } 30468 completer.apply(null, args); 30469 } 30470 }; 30471 const resolve = complete(resolveCb); 30472 const reject = complete(rejectCb); 30473 const start = (...args) => { 30474 if (!done && timer === null) { 30475 timer = setTimeout(() => reject.apply(null, args), timeout); 30476 } 30477 }; 30478 return { 30479 start, 30480 resolve, 30481 reject 30482 }; 30483 }; 30484 const create$1 = () => { 30485 const tasks = {}; 30486 const resultFns = {}; 30487 const load = (id, url) => { 30488 const loadErrMsg = `Script at URL "${ url }" failed to load`; 30489 const runErrMsg = `Script at URL "${ url }" did not call \`tinymce.Resource.add('${ id }', data)\` within 1 second`; 30490 if (tasks[id] !== undefined) { 30491 return tasks[id]; 30492 } else { 30493 const task = new Promise((resolve, reject) => { 30494 const waiter = awaiter(resolve, reject); 30495 resultFns[id] = waiter.resolve; 30496 ScriptLoader.ScriptLoader.loadScript(url).then(() => waiter.start(runErrMsg), () => waiter.reject(loadErrMsg)); 30497 }); 30498 tasks[id] = task; 30499 return task; 30500 } 30501 }; 30502 const add = (id, data) => { 30503 if (resultFns[id] !== undefined) { 30504 resultFns[id](data); 30505 delete resultFns[id]; 30506 } 30507 tasks[id] = Promise.resolve(data); 30508 }; 30509 const unload = id => { 30510 delete tasks[id]; 30511 }; 30512 return { 30513 load, 30514 add, 30515 unload 30516 }; 30517 }; 30518 const Resource = create$1(); 30519 30520 const create = () => (() => { 30521 let data = {}; 30522 let keys = []; 30523 const storage = { 30524 getItem: key => { 30525 const item = data[key]; 30526 return item ? item : null; 30527 }, 30528 setItem: (key, value) => { 30529 keys.push(key); 30530 data[key] = String(value); 30531 }, 30532 key: index => { 30533 return keys[index]; 30534 }, 30535 removeItem: key => { 30536 keys = keys.filter(k => k === key); 30537 delete data[key]; 30538 }, 30539 clear: () => { 30540 keys = []; 30541 data = {}; 30542 }, 30543 length: 0 30544 }; 30545 Object.defineProperty(storage, 'length', { 30546 get: () => keys.length, 30547 configurable: false, 30548 enumerable: false 30549 }); 30550 return storage; 30551 })(); 30552 30553 let localStorage; 30554 try { 30555 const test = '__storage_test__'; 30556 localStorage = window.localStorage; 30557 localStorage.setItem(test, test); 30558 localStorage.removeItem(test); 30559 } catch (e) { 30560 localStorage = create(); 30561 } 30562 var LocalStorage = localStorage; 30563 30564 const publicApi = { 30565 geom: { Rect }, 30566 util: { 30567 Delay, 30568 Tools, 30569 VK, 30570 URI, 30571 EventDispatcher, 30572 Observable, 30573 I18n, 30574 LocalStorage, 30575 ImageUploader 30576 }, 30577 dom: { 30578 EventUtils, 30579 TreeWalker: DomTreeWalker, 30580 TextSeeker, 30581 DOMUtils, 30582 ScriptLoader, 30583 RangeUtils, 30584 Serializer: DomSerializer, 30585 StyleSheetLoader, 30586 ControlSelection, 30587 BookmarkManager, 30588 Selection: EditorSelection, 30589 Event: EventUtils.Event 30590 }, 30591 html: { 30592 Styles, 30593 Entities, 30594 Node: AstNode, 30595 Schema, 30596 DomParser, 30597 Writer, 30598 Serializer: HtmlSerializer 30599 }, 30600 Env, 30601 AddOnManager, 30602 Annotator, 30603 Formatter, 30604 UndoManager, 30605 EditorCommands, 30606 WindowManager, 30607 NotificationManager, 30608 EditorObservable, 30609 Shortcuts, 30610 Editor, 30611 FocusManager, 30612 EditorManager, 30613 DOM: DOMUtils.DOM, 30614 ScriptLoader: ScriptLoader.ScriptLoader, 30615 PluginManager, 30616 ThemeManager, 30617 ModelManager, 30618 IconManager, 30619 Resource, 30620 FakeClipboard, 30621 trim: Tools.trim, 30622 isArray: Tools.isArray, 30623 is: Tools.is, 30624 toArray: Tools.toArray, 30625 makeMap: Tools.makeMap, 30626 each: Tools.each, 30627 map: Tools.map, 30628 grep: Tools.grep, 30629 inArray: Tools.inArray, 30630 extend: Tools.extend, 30631 walk: Tools.walk, 30632 resolve: Tools.resolve, 30633 explode: Tools.explode, 30634 _addCacheSuffix: Tools._addCacheSuffix 30635 }; 30636 const tinymce = Tools.extend(EditorManager, publicApi); 30637 30638 const exportToModuleLoaders = tinymce => { 30639 if (typeof module === 'object') { 30640 try { 30641 module.exports = tinymce; 30642 } catch (_) { 30643 } 30644 } 30645 }; 30646 const exportToWindowGlobal = tinymce => { 30647 window.tinymce = tinymce; 30648 window.tinyMCE = tinymce; 30649 }; 30650 exportToWindowGlobal(tinymce); 30651 exportToModuleLoaders(tinymce); 30652 30653})();
30654 30655 30656
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.