1/* 2Trix 2.1.18 3Copyright © 2026 37signals, LLC 4 */ 5(function (global, factory) { 6 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 7 typeof define === 'function' && define.amd ? define(factory) : 8 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Trix = factory()); 9})(this, (function () { 'use strict'; 10 11 var name = "trix"; 12 var version = "2.1.18
vendor: 58,385 bytes, lines 12-1768
12"; 13 var description = "A rich text editor for everyday writing"; 14 var main = "dist/trix.umd.min.js"; 15 var module = "dist/trix.esm.min.js"; 16 var style = "dist/trix.css"; 17 var files = [ 18 "dist/*.css", 19 "dist/*.js", 20 "dist/*.map", 21 "src/{inspector,trix}/*.js" 22 ]; 23 var repository = { 24 type: "git", 25 url: "git+https://github.com/basecamp/trix.git" 26 }; 27 var keywords = [ 28 "rich text", 29 "wysiwyg", 30 "editor" 31 ]; 32 var author = "37signals, LLC"; 33 var license = "MIT"; 34 var bugs = { 35 url: "https://github.com/basecamp/trix/issues" 36 }; 37 var homepage = "https://trix-editor.org/"; 38 var devDependencies = { 39 "@babel/core": "^7.16.0", 40 "@babel/preset-env": "^7.16.4", 41 "@rollup/plugin-babel": "^5.3.0", 42 "@rollup/plugin-commonjs": "^22.0.2", 43 "@rollup/plugin-json": "^4.1.0", 44 "@rollup/plugin-node-resolve": "^13.3.0", 45 "@web/dev-server": "^0.1.34", 46 "@web/test-runner": "^0.20.2", 47 "@web/test-runner-playwright": "^0.11.1", 48 "@web/test-runner-webdriver": "^0.9.0", 49 "babel-eslint": "^10.1.0", 50 chokidar: "^4.0.2", 51 concurrently: "^7.4.0", 52 eslint: "^7.32.0", 53 esm: "^3.2.25", 54 idiomorph: "^0.7.3", 55 qunit: "2.19.1", 56 rangy: "^1.3.0", 57 rollup: "^2.56.3", 58 "rollup-plugin-includepaths": "^0.2.4", 59 "rollup-plugin-terser": "^7.0.2", 60 sass: "^1.83.0", 61 "source-map": "^0.7.6", 62 svgo: "^2.8.0", 63 webdriverio: "^7.19.5" 64 }; 65 var resolutions = { 66 webdriverio: "^7.19.5" 67 }; 68 var scripts = { 69 "build-css": "bin/sass-build assets/trix.scss dist/trix.css action_text-trix/app/assets/stylesheets/trix.css", 70 "build-js": "rollup -c", 71 "build-assets": "cp -f assets/*.html dist/", 72 "build-ruby": "rake -C action_text-trix sync", 73 build: "yarn run build-js && yarn run build-css && yarn run build-assets && yarn run build-ruby", 74 watch: "rollup -c -w", 75 lint: "eslint .", 76 pretest: "yarn run lint && yarn run build", 77 test: "web-test-runner", 78 "test:watch": "web-test-runner --watch", 79 version: "yarn build && git add action_text-trix", 80 prerelease: "yarn version && yarn test", 81 "release-npm": "npm adduser && npm publish", 82 "release-ruby": "rake -C action_text-trix release", 83 release: "yarn run release-npm && yarn run release-ruby", 84 postrelease: "git push && git push --tags", 85 dev: "web-dev-server --app-index index.html --root-dir dist --node-resolve --open", 86 start: "yarn build-assets && concurrently --kill-others --names js,css,dev-server 'yarn watch' 'yarn build-css --watch' 'yarn dev'" 87 }; 88 var dependencies = { 89 dompurify: "^3.2.5" 90 }; 91 var engines = { 92 node: ">= 18" 93 }; 94 var _package = { 95 name: name, 96 version: version, 97 description: description, 98 main: main, 99 module: module, 100 style: style, 101 files: files, 102 repository: repository, 103 keywords: keywords, 104 author: author, 105 license: license, 106 bugs: bugs, 107 homepage: homepage, 108 devDependencies: devDependencies, 109 resolutions: resolutions, 110 scripts: scripts, 111 dependencies: dependencies, 112 engines: engines 113 }; 114 115 const attachmentSelector = "[data-trix-attachment]"; 116 const attachments = { 117 preview: { 118 presentation: "gallery", 119 caption: { 120 name: true, 121 size: true 122 } 123 }, 124 file: { 125 caption: { 126 size: true 127 } 128 } 129 }; 130 131 const attributes = { 132 default: { 133 tagName: "div", 134 parse: false 135 }, 136 quote: { 137 tagName: "blockquote", 138 nestable: true 139 }, 140 heading1: { 141 tagName: "h1", 142 terminal: true, 143 breakOnReturn: true, 144 group: false 145 }, 146 code: { 147 tagName: "pre", 148 terminal: true, 149 htmlAttributes: ["language"], 150 text: { 151 plaintext: true 152 } 153 }, 154 bulletList: { 155 tagName: "ul", 156 parse: false 157 }, 158 bullet: { 159 tagName: "li", 160 listAttribute: "bulletList", 161 group: false, 162 nestable: true, 163 test(element) { 164 return tagName$1(element.parentNode) === attributes[this.listAttribute].tagName; 165 } 166 }, 167 numberList: { 168 tagName: "ol", 169 parse: false 170 }, 171 number: { 172 tagName: "li", 173 listAttribute: "numberList", 174 group: false, 175 nestable: true, 176 test(element) { 177 return tagName$1(element.parentNode) === attributes[this.listAttribute].tagName; 178 } 179 }, 180 attachmentGallery: { 181 tagName: "div", 182 exclusive: true, 183 terminal: true, 184 parse: false, 185 group: false 186 } 187 }; 188 const tagName$1 = element => { 189 var _element$tagName; 190 return element === null || element === void 0 || (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase(); 191 }; 192 193 const androidVersionMatch = navigator.userAgent.match(/android\s([0-9]+.*Chrome)/i); 194 const androidVersion = androidVersionMatch && parseInt(androidVersionMatch[1]); 195 var browser$1 = { 196 // Android emits composition events when moving the cursor through existing text 197 // Introduced in Chrome 65: https://bugs.chromium.org/p/chromium/issues/detail?id=764439#c9 198 composesExistingText: /Android.*Chrome/.test(navigator.userAgent), 199 // Android 13, especially on Samsung keyboards, emits extra compositionend and beforeinput events 200 // that can make the input handler lose the current selection or enter an infinite input -> render -> input 201 // loop. 202 recentAndroid: androidVersion && androidVersion > 12, 203 samsungAndroid: androidVersion && navigator.userAgent.match(/Android.*SM-/), 204 // IE 11 activates resizing handles on editable elements that have "layout" 205 forcesObjectResizing: /Trident.*rv:11/.test(navigator.userAgent), 206 // https://www.w3.org/TR/input-events-1/ + https://www.w3.org/TR/input-events-2/ 207 supportsInputEvents: typeof InputEvent !== "undefined" && ["data", "getTargetRanges", "inputType"].every(prop => prop in InputEvent.prototype) 208 }; 209 210 var css$3 = { 211 attachment: "attachment", 212 attachmentCaption: "attachment__caption", 213 attachmentCaptionEditor: "attachment__caption-editor", 214 attachmentMetadata: "attachment__metadata", 215 attachmentMetadataContainer: "attachment__metadata-container", 216 attachmentName: "attachment__name", 217 attachmentProgress: "attachment__progress", 218 attachmentSize: "attachment__size", 219 attachmentToolbar: "attachment__toolbar", 220 attachmentGallery: "attachment-gallery" 221 }; 222 223 var dompurify = { 224 ADD_ATTR: ["language"], 225 SAFE_FOR_XML: false, 226 RETURN_DOM: true 227 }; 228 229 var lang$1 = { 230 attachFiles: "Attach Files", 231 bold: "Bold", 232 bullets: "Bullets", 233 byte: "Byte", 234 bytes: "Bytes", 235 captionPlaceholder: "Add a captionâ¦", 236 code: "Code", 237 heading1: "Heading", 238 indent: "Increase Level", 239 italic: "Italic", 240 link: "Link", 241 numbers: "Numbers", 242 outdent: "Decrease Level", 243 quote: "Quote", 244 redo: "Redo", 245 remove: "Remove", 246 strike: "Strikethrough", 247 undo: "Undo", 248 unlink: "Unlink", 249 url: "URL", 250 urlPlaceholder: "Enter a URLâ¦", 251 GB: "GB", 252 KB: "KB", 253 MB: "MB", 254 PB: "PB", 255 TB: "TB" 256 }; 257 258 /* eslint-disable 259 no-case-declarations, 260 */ 261 const sizes = [lang$1.bytes, lang$1.KB, lang$1.MB, lang$1.GB, lang$1.TB, lang$1.PB]; 262 var file_size_formatting = { 263 prefix: "IEC", 264 precision: 2, 265 formatter(number) { 266 switch (number) { 267 case 0: 268 return "0 ".concat(lang$1.bytes); 269 case 1: 270 return "1 ".concat(lang$1.byte); 271 default: 272 let base; 273 if (this.prefix === "SI") { 274 base = 1000; 275 } else if (this.prefix === "IEC") { 276 base = 1024; 277 } 278 const exp = Math.floor(Math.log(number) / Math.log(base)); 279 const humanSize = number / Math.pow(base, exp); 280 const string = humanSize.toFixed(this.precision); 281 const withoutInsignificantZeros = string.replace(/0*$/, "").replace(/\.$/, ""); 282 return "".concat(withoutInsignificantZeros, " ").concat(sizes[exp]); 283 } 284 } 285 }; 286 287 const ZERO_WIDTH_SPACE = "\uFEFF"; 288 const NON_BREAKING_SPACE = "\u00A0"; 289 const OBJECT_REPLACEMENT_CHARACTER = "\uFFFC"; 290 291 const extend = function (properties) { 292 for (const key in properties) { 293 const value = properties[key]; 294 this[key] = value; 295 } 296 return this; 297 }; 298 299 const html$2 = document.documentElement; 300 const match = html$2.matches; 301 const handleEvent = function (eventName) { 302 let { 303 onElement, 304 matchingSelector, 305 withCallback, 306 inPhase, 307 preventDefault, 308 times 309 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 310 const element = onElement ? onElement : html$2; 311 const selector = matchingSelector; 312 const useCapture = inPhase === "capturing"; 313 const handler = function (event) { 314 if (times != null && --times === 0) { 315 handler.destroy(); 316 } 317 const target = findClosestElementFromNode(event.target, { 318 matchingSelector: selector 319 }); 320 if (target != null) { 321 withCallback === null || withCallback === void 0 || withCallback.call(target, event, target); 322 if (preventDefault) { 323 event.preventDefault(); 324 } 325 } 326 }; 327 handler.destroy = () => element.removeEventListener(eventName, handler, useCapture); 328 element.addEventListener(eventName, handler, useCapture); 329 return handler; 330 }; 331 const handleEventOnce = function (eventName) { 332 let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 333 options.times = 1; 334 return handleEvent(eventName, options); 335 }; 336 const createEvent = function (eventName) { 337 let { 338 bubbles, 339 cancelable, 340 attributes 341 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 342 bubbles = bubbles !== false; 343 cancelable = cancelable !== false; 344 const event = document.createEvent("Events"); 345 event.initEvent(eventName, bubbles, cancelable); 346 if (attributes != null) { 347 extend.call(event, attributes); 348 } 349 return event; 350 }; 351 const triggerEvent = function (eventName) { 352 let { 353 onElement, 354 bubbles, 355 cancelable, 356 attributes 357 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 358 const element = onElement != null ? onElement : html$2; 359 const event = createEvent(eventName, { 360 bubbles, 361 cancelable, 362 attributes 363 }); 364 return element.dispatchEvent(event); 365 }; 366 const elementMatchesSelector = function (element, selector) { 367 if ((element === null || element === void 0 ? void 0 : element.nodeType) === 1) { 368 return match.call(element, selector); 369 } 370 }; 371 const findClosestElementFromNode = function (node) { 372 let { 373 matchingSelector, 374 untilNode 375 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 376 while (node && node.nodeType !== Node.ELEMENT_NODE) { 377 node = node.parentNode; 378 } 379 if (node == null) { 380 return; 381 } 382 if (matchingSelector != null) { 383 if (node.closest && untilNode == null) { 384 return node.closest(matchingSelector); 385 } else { 386 while (node && node !== untilNode) { 387 if (elementMatchesSelector(node, matchingSelector)) { 388 return node; 389 } 390 node = node.parentNode; 391 } 392 } 393 } else { 394 return node; 395 } 396 }; 397 const findInnerElement = function (element) { 398 while ((_element = element) !== null && _element !== void 0 && _element.firstElementChild) { 399 var _element; 400 element = element.firstElementChild; 401 } 402 return element; 403 }; 404 const innerElementIsActive = element => document.activeElement !== element && elementContainsNode(element, document.activeElement); 405 const elementContainsNode = function (element, node) { 406 if (!element || !node) { 407 return; 408 } 409 while (node) { 410 if (node === element) { 411 return true; 412 } 413 node = node.parentNode; 414 } 415 }; 416 const findNodeFromContainerAndOffset = function (container, offset) { 417 if (!container) { 418 return; 419 } 420 if (container.nodeType === Node.TEXT_NODE) { 421 return container; 422 } else if (offset === 0) { 423 return container.firstChild != null ? container.firstChild : container; 424 } else { 425 return container.childNodes.item(offset - 1); 426 } 427 }; 428 const findElementFromContainerAndOffset = function (container, offset) { 429 const node = findNodeFromContainerAndOffset(container, offset); 430 return findClosestElementFromNode(node); 431 }; 432 const findChildIndexOfNode = function (node) { 433 var _node; 434 if (!((_node = node) !== null && _node !== void 0 && _node.parentNode)) { 435 return; 436 } 437 let childIndex = 0; 438 node = node.previousSibling; 439 while (node) { 440 childIndex++; 441 node = node.previousSibling; 442 } 443 return childIndex; 444 }; 445 const removeNode = node => { 446 var _node$parentNode; 447 return node === null || node === void 0 || (_node$parentNode = node.parentNode) === null || _node$parentNode === void 0 ? void 0 : _node$parentNode.removeChild(node); 448 }; 449 const walkTree = function (tree) { 450 let { 451 onlyNodesOfType, 452 usingFilter, 453 expandEntityReferences 454 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 455 const whatToShow = (() => { 456 switch (onlyNodesOfType) { 457 case "element": 458 return NodeFilter.SHOW_ELEMENT; 459 case "text": 460 return NodeFilter.SHOW_TEXT; 461 case "comment": 462 return NodeFilter.SHOW_COMMENT; 463 default: 464 return NodeFilter.SHOW_ALL; 465 } 466 })(); 467 return document.createTreeWalker(tree, whatToShow, usingFilter != null ? usingFilter : null, expandEntityReferences === true); 468 }; 469 const tagName = element => { 470 var _element$tagName; 471 return element === null || element === void 0 || (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase(); 472 }; 473 const makeElement = function (tag) { 474 let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 475 let key, value; 476 if (typeof tag === "object") { 477 options = tag; 478 tag = options.tagName; 479 } else { 480 options = { 481 attributes: options 482 }; 483 } 484 const element = document.createElement(tag); 485 if (options.editable != null) { 486 if (options.attributes == null) { 487 options.attributes = {}; 488 } 489 options.attributes.contenteditable = options.editable; 490 } 491 if (options.attributes) { 492 for (key in options.attributes) { 493 value = options.attributes[key]; 494 element.setAttribute(key, value); 495 } 496 } 497 if (options.style) { 498 for (key in options.style) { 499 value = options.style[key]; 500 element.style[key] = value; 501 } 502 } 503 if (options.data) { 504 for (key in options.data) { 505 value = options.data[key]; 506 element.dataset[key] = value; 507 } 508 } 509 if (options.className) { 510 options.className.split(" ").forEach(className => { 511 element.classList.add(className); 512 }); 513 } 514 if (options.textContent) { 515 element.textContent = options.textContent; 516 } 517 if (options.childNodes) { 518 [].concat(options.childNodes).forEach(childNode => { 519 element.appendChild(childNode); 520 }); 521 } 522 return element; 523 }; 524 let blockTagNames = undefined; 525 const getBlockTagNames = function () { 526 if (blockTagNames != null) { 527 return blockTagNames; 528 } 529 blockTagNames = []; 530 for (const key in attributes) { 531 const attributes$1 = attributes[key]; 532 if (attributes$1.tagName) { 533 blockTagNames.push(attributes$1.tagName); 534 } 535 } 536 return blockTagNames; 537 }; 538 const nodeIsBlockContainer = node => nodeIsBlockStartComment(node === null || node === void 0 ? void 0 : node.firstChild); 539 const nodeProbablyIsBlockContainer = function (node) { 540 return getBlockTagNames().includes(tagName(node)) && !getBlockTagNames().includes(tagName(node.firstChild)); 541 }; 542 const nodeIsBlockStart = function (node) { 543 let { 544 strict 545 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { 546 strict: true 547 }; 548 if (strict) { 549 return nodeIsBlockStartComment(node); 550 } else { 551 return nodeIsBlockStartComment(node) || !nodeIsBlockStartComment(node.firstChild) && nodeProbablyIsBlockContainer(node); 552 } 553 }; 554 const nodeIsBlockStartComment = node => nodeIsCommentNode(node) && (node === null || node === void 0 ? void 0 : node.data) === "block"; 555 const nodeIsCommentNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.COMMENT_NODE; 556 const nodeIsCursorTarget = function (node) { 557 let { 558 name 559 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 560 if (!node) { 561 return; 562 } 563 if (nodeIsTextNode(node)) { 564 if (node.data === ZERO_WIDTH_SPACE) { 565 if (name) { 566 return node.parentNode.dataset.trixCursorTarget === name; 567 } else { 568 return true; 569 } 570 } 571 } else { 572 return nodeIsCursorTarget(node.firstChild); 573 } 574 }; 575 const nodeIsAttachmentElement = node => elementMatchesSelector(node, attachmentSelector); 576 const nodeIsEmptyTextNode = node => nodeIsTextNode(node) && (node === null || node === void 0 ? void 0 : node.data) === ""; 577 const nodeIsTextNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.TEXT_NODE; 578 579 const input = { 580 level2Enabled: true, 581 getLevel() { 582 if (this.level2Enabled && browser$1.supportsInputEvents) { 583 return 2; 584 } else { 585 return 0; 586 } 587 }, 588 pickFiles(callback) { 589 const input = makeElement("input", { 590 type: "file", 591 multiple: true, 592 hidden: true, 593 id: this.fileInputId 594 }); 595 input.addEventListener("change", () => { 596 callback(input.files); 597 removeNode(input); 598 }); 599 removeNode(document.getElementById(this.fileInputId)); 600 document.body.appendChild(input); 601 input.click(); 602 } 603 }; 604 605 var key_names = { 606 8: "backspace", 607 9: "tab", 608 13: "return", 609 27: "escape", 610 37: "left", 611 39: "right", 612 46: "delete", 613 68: "d", 614 72: "h", 615 79: "o" 616 }; 617 618 var parser = { 619 removeBlankTableCells: false, 620 tableCellSeparator: " | ", 621 tableRowSeparator: "\n" 622 }; 623 624 var text_attributes = { 625 bold: { 626 tagName: "strong", 627 inheritable: true, 628 parser(element) { 629 const style = window.getComputedStyle(element); 630 return style.fontWeight === "bold" || style.fontWeight >= 600; 631 } 632 }, 633 italic: { 634 tagName: "em", 635 inheritable: true, 636 parser(element) { 637 const style = window.getComputedStyle(element); 638 return style.fontStyle === "italic"; 639 } 640 }, 641 href: { 642 groupTagName: "a", 643 parser(element) { 644 const matchingSelector = "a:not(".concat(attachmentSelector, ")"); 645 const link = element.closest(matchingSelector); 646 if (link) { 647 return link.getAttribute("href"); 648 } 649 } 650 }, 651 strike: { 652 tagName: "del", 653 inheritable: true 654 }, 655 frozen: { 656 style: { 657 backgroundColor: "highlight" 658 } 659 } 660 }; 661 662 var toolbar = { 663 getDefaultHTML() { 664 return "<div class=\"trix-button-row\">\n <span class=\"trix-button-group trix-button-group--text-tools\" data-trix-button-group=\"text-tools\">\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-bold\" data-trix-attribute=\"bold\" data-trix-key=\"b\" title=\"".concat(lang$1.bold, "\" tabindex=\"-1\">").concat(lang$1.bold, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-italic\" data-trix-attribute=\"italic\" data-trix-key=\"i\" title=\"").concat(lang$1.italic, "\" tabindex=\"-1\">").concat(lang$1.italic, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-strike\" data-trix-attribute=\"strike\" title=\"").concat(lang$1.strike, "\" tabindex=\"-1\">").concat(lang$1.strike, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-link\" data-trix-attribute=\"href\" data-trix-action=\"link\" data-trix-key=\"k\" title=\"").concat(lang$1.link, "\" tabindex=\"-1\">").concat(lang$1.link, "</button>\n </span>\n\n <span class=\"trix-button-group trix-button-group--block-tools\" data-trix-button-group=\"block-tools\">\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-heading-1\" data-trix-attribute=\"heading1\" title=\"").concat(lang$1.heading1, "\" tabindex=\"-1\">").concat(lang$1.heading1, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-quote\" data-trix-attribute=\"quote\" title=\"").concat(lang$1.quote, "\" tabindex=\"-1\">").concat(lang$1.quote, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-code\" data-trix-attribute=\"code\" title=\"").concat(lang$1.code, "\" tabindex=\"-1\">").concat(lang$1.code, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-bullet-list\" data-trix-attribute=\"bullet\" title=\"").concat(lang$1.bullets, "\" tabindex=\"-1\">").concat(lang$1.bullets, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-number-list\" data-trix-attribute=\"number\" title=\"").concat(lang$1.numbers, "\" tabindex=\"-1\">").concat(lang$1.numbers, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-decrease-nesting-level\" data-trix-action=\"decreaseNestingLevel\" title=\"").concat(lang$1.outdent, "\" tabindex=\"-1\">").concat(lang$1.outdent, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-increase-nesting-level\" data-trix-action=\"increaseNestingLevel\" title=\"").concat(lang$1.indent, "\" tabindex=\"-1\">").concat(lang$1.indent, "</button>\n </span>\n\n <span class=\"trix-button-group trix-button-group--file-tools\" data-trix-button-group=\"file-tools\">\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-attach\" data-trix-action=\"attachFiles\" title=\"").concat(lang$1.attachFiles, "\" tabindex=\"-1\">").concat(lang$1.attachFiles, "</button>\n </span>\n\n <span class=\"trix-button-group-spacer\"></span>\n\n <span class=\"trix-button-group trix-button-group--history-tools\" data-trix-button-group=\"history-tools\">\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-undo\" data-trix-action=\"undo\" data-trix-key=\"z\" title=\"").concat(lang$1.undo, "\" tabindex=\"-1\">").concat(lang$1.undo, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-redo\" data-trix-action=\"redo\" data-trix-key=\"shift+z\" title=\"").concat(lang$1.redo, "\" tabindex=\"-1\">").concat(lang$1.redo, "</button>\n </span>\n </div>\n\n <div class=\"trix-dialogs\" data-trix-dialogs>\n <div class=\"trix-dialog trix-dialog--link\" data-trix-dialog=\"href\" data-trix-dialog-attribute=\"href\">\n <div class=\"trix-dialog__link-fields\">\n <input type=\"url\" name=\"href\" class=\"trix-input trix-input--dialog\" placeholder=\"").concat(lang$1.urlPlaceholder, "\" aria-label=\"").concat(lang$1.url, "\" data-trix-validate-href required data-trix-input>\n <div class=\"trix-button-group\">\n <input type=\"button\" class=\"trix-button trix-button--dialog\" value=\"").concat(lang$1.link, "\" data-trix-method=\"setAttribute\">\n <input type=\"button\" class=\"trix-button trix-button--dialog\" value=\"").concat(lang$1.unlink, "\" data-trix-method=\"removeAttribute\">\n </div>\n </div>\n </div>\n </div>"); 665 } 666 }; 667 668 const undo = { 669 interval: 5000 670 }; 671 672 var config = /*#__PURE__*/Object.freeze({ 673 __proto__: null, 674 attachments: attachments, 675 blockAttributes: attributes, 676 browser: browser$1, 677 css: css$3, 678 dompurify: dompurify, 679 fileSize: file_size_formatting, 680 input: input, 681 keyNames: key_names, 682 lang: lang$1, 683 parser: parser, 684 textAttributes: text_attributes, 685 toolbar: toolbar, 686 undo: undo 687 }); 688 689 class BasicObject { 690 static proxyMethod(expression) { 691 const { 692 name, 693 toMethod, 694 toProperty, 695 optional 696 } = parseProxyMethodExpression(expression); 697 this.prototype[name] = function () { 698 let subject; 699 let object; 700 if (toMethod) { 701 if (optional) { 702 var _this$toMethod; 703 object = (_this$toMethod = this[toMethod]) === null || _this$toMethod === void 0 ? void 0 : _this$toMethod.call(this); 704 } else { 705 object = this[toMethod](); 706 } 707 } else if (toProperty) { 708 object = this[toProperty]; 709 } 710 if (optional) { 711 var _object; 712 subject = (_object = object) === null || _object === void 0 ? void 0 : _object[name]; 713 if (subject) { 714 return apply$1.call(subject, object, arguments); 715 } 716 } else { 717 subject = object[name]; 718 return apply$1.call(subject, object, arguments); 719 } 720 }; 721 } 722 } 723 const parseProxyMethodExpression = function (expression) { 724 const match = expression.match(proxyMethodExpressionPattern); 725 if (!match) { 726 throw new Error("can't parse @proxyMethod expression: ".concat(expression)); 727 } 728 const args = { 729 name: match[4] 730 }; 731 if (match[2] != null) { 732 args.toMethod = match[1]; 733 } else { 734 args.toProperty = match[1]; 735 } 736 if (match[3] != null) { 737 args.optional = true; 738 } 739 return args; 740 }; 741 const { 742 apply: apply$1 743 } = Function.prototype; 744 const proxyMethodExpressionPattern = new RegExp("\ 745^\ 746(.+?)\ 747(\\(\\))?\ 748(\\?)?\ 749\\.\ 750(.+?)\ 751$\ 752"); 753 754 var _Array$from, _$codePointAt$1, _$1, _String$fromCodePoint; 755 class UTF16String extends BasicObject { 756 static box() { 757 let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; 758 if (value instanceof this) { 759 return value; 760 } else { 761 return this.fromUCS2String(value === null || value === void 0 ? void 0 : value.toString()); 762 } 763 } 764 static fromUCS2String(ucs2String) { 765 return new this(ucs2String, ucs2decode(ucs2String)); 766 } 767 static fromCodepoints(codepoints) { 768 return new this(ucs2encode(codepoints), codepoints); 769 } 770 constructor(ucs2String, codepoints) { 771 super(...arguments); 772 this.ucs2String = ucs2String; 773 this.codepoints = codepoints; 774 this.length = this.codepoints.length; 775 this.ucs2Length = this.ucs2String.length; 776 } 777 offsetToUCS2Offset(offset) { 778 return ucs2encode(this.codepoints.slice(0, Math.max(0, offset))).length; 779 } 780 offsetFromUCS2Offset(ucs2Offset) { 781 return ucs2decode(this.ucs2String.slice(0, Math.max(0, ucs2Offset))).length; 782 } 783 slice() { 784 return this.constructor.fromCodepoints(this.codepoints.slice(...arguments)); 785 } 786 charAt(offset) { 787 return this.slice(offset, offset + 1); 788 } 789 isEqualTo(value) { 790 return this.constructor.box(value).ucs2String === this.ucs2String; 791 } 792 toJSON() { 793 return this.ucs2String; 794 } 795 getCacheKey() { 796 return this.ucs2String; 797 } 798 toString() { 799 return this.ucs2String; 800 } 801 } 802 const hasArrayFrom = ((_Array$from = Array.from) === null || _Array$from === void 0 ? void 0 : _Array$from.call(Array, "\ud83d\udc7c").length) === 1; 803 const hasStringCodePointAt$1 = ((_$codePointAt$1 = (_$1 = " ").codePointAt) === null || _$codePointAt$1 === void 0 ? void 0 : _$codePointAt$1.call(_$1, 0)) != null; 804 const hasStringFromCodePoint = ((_String$fromCodePoint = String.fromCodePoint) === null || _String$fromCodePoint === void 0 ? void 0 : _String$fromCodePoint.call(String, 32, 128124)) === " \ud83d\udc7c"; 805 806 // UCS-2 conversion helpers ported from Mathias Bynens' Punycode.js: 807 // https://github.com/bestiejs/punycode.js#punycodeucs2 808 809 let ucs2decode, ucs2encode; 810 811 // Creates an array containing the numeric code points of each Unicode 812 // character in the string. While JavaScript uses UCS-2 internally, 813 // this function will convert a pair of surrogate halves (each of which 814 // UCS-2 exposes as separate characters) into a single code point, 815 // matching UTF-16. 816 if (hasArrayFrom && hasStringCodePointAt$1) { 817 ucs2decode = string => Array.from(string).map(char => char.codePointAt(0)); 818 } else { 819 ucs2decode = function (string) { 820 const output = []; 821 let counter = 0; 822 const { 823 length 824 } = string; 825 while (counter < length) { 826 let value = string.charCodeAt(counter++); 827 if (0xd800 <= value && value <= 0xdbff && counter < length) { 828 // high surrogate, and there is a next character 829 const extra = string.charCodeAt(counter++); 830 if ((extra & 0xfc00) === 0xdc00) { 831 // low surrogate 832 value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; 833 } else { 834 // unmatched surrogate; only append this code unit, in case the 835 // next code unit is the high surrogate of a surrogate pair 836 counter--; 837 } 838 } 839 output.push(value); 840 } 841 return output; 842 }; 843 } 844 845 // Creates a string based on an array of numeric code points. 846 if (hasStringFromCodePoint) { 847 ucs2encode = array => String.fromCodePoint(...Array.from(array || [])); 848 } else { 849 ucs2encode = function (array) { 850 const characters = (() => { 851 const result = []; 852 Array.from(array).forEach(value => { 853 let output = ""; 854 if (value > 0xffff) { 855 value -= 0x10000; 856 output += String.fromCharCode(value >>> 10 & 0x3ff | 0xd800); 857 value = 0xdc00 | value & 0x3ff; 858 } 859 result.push(output + String.fromCharCode(value)); 860 }); 861 return result; 862 })(); 863 return characters.join(""); 864 }; 865 } 866 867 let id$2 = 0; 868 class TrixObject extends BasicObject { 869 static fromJSONString(jsonString) { 870 return this.fromJSON(JSON.parse(jsonString)); 871 } 872 constructor() { 873 super(...arguments); 874 this.id = ++id$2; 875 } 876 hasSameConstructorAs(object) { 877 return this.constructor === (object === null || object === void 0 ? void 0 : object.constructor); 878 } 879 isEqualTo(object) { 880 return this === object; 881 } 882 inspect() { 883 const parts = []; 884 const contents = this.contentsForInspection() || {}; 885 for (const key in contents) { 886 const value = contents[key]; 887 parts.push("".concat(key, "=").concat(value)); 888 } 889 return "#<".concat(this.constructor.name, ":").concat(this.id).concat(parts.length ? " ".concat(parts.join(", ")) : "", ">"); 890 } 891 contentsForInspection() {} 892 toJSONString() { 893 return JSON.stringify(this); 894 } 895 toUTF16String() { 896 return UTF16String.box(this); 897 } 898 getCacheKey() { 899 return this.id.toString(); 900 } 901 } 902 903 /* eslint-disable 904 id-length, 905 */ 906 const arraysAreEqual = function () { 907 let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 908 let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; 909 if (a.length !== b.length) { 910 return false; 911 } 912 for (let index = 0; index < a.length; index++) { 913 const value = a[index]; 914 if (value !== b[index]) { 915 return false; 916 } 917 } 918 return true; 919 }; 920 const arrayStartsWith = function () { 921 let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 922 let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; 923 return arraysAreEqual(a.slice(0, b.length), b); 924 }; 925 const spliceArray = function (array) { 926 const result = array.slice(0); 927 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 928 args[_key - 1] = arguments[_key]; 929 } 930 result.splice(...args); 931 return result; 932 }; 933 const summarizeArrayChange = function () { 934 let oldArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 935 let newArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; 936 const added = []; 937 const removed = []; 938 const existingValues = new Set(); 939 oldArray.forEach(value => { 940 existingValues.add(value); 941 }); 942 const currentValues = new Set(); 943 newArray.forEach(value => { 944 currentValues.add(value); 945 if (!existingValues.has(value)) { 946 added.push(value); 947 } 948 }); 949 oldArray.forEach(value => { 950 if (!currentValues.has(value)) { 951 removed.push(value); 952 } 953 }); 954 return { 955 added, 956 removed 957 }; 958 }; 959 960 // https://github.com/mathiasbynens/unicode-2.1.8/blob/master/Bidi_Class/Right_To_Left/regex.js 961 const RTL_PATTERN = /[\u05BE\u05C0\u05C3\u05D0-\u05EA\u05F0-\u05F4\u061B\u061F\u0621-\u063A\u0640-\u064A\u066D\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D5\u06E5\u06E6\u200F\u202B\u202E\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE72\uFE74\uFE76-\uFEFC]/; 962 const getDirection = function () { 963 const input = makeElement("input", { 964 dir: "auto", 965 name: "x", 966 dirName: "x.dir" 967 }); 968 const textArea = makeElement("textarea", { 969 dir: "auto", 970 name: "y", 971 dirName: "y.dir" 972 }); 973 const form = makeElement("form"); 974 form.appendChild(input); 975 form.appendChild(textArea); 976 const supportsDirName = function () { 977 try { 978 return new FormData(form).has(textArea.dirName); 979 } catch (error) { 980 return false; 981 } 982 }(); 983 const supportsDirSelector = function () { 984 try { 985 return input.matches(":dir(ltr),:dir(rtl)"); 986 } catch (error) { 987 return false; 988 } 989 }(); 990 if (supportsDirName) { 991 return function (string) { 992 textArea.value = string; 993 return new FormData(form).get(textArea.dirName); 994 }; 995 } else if (supportsDirSelector) { 996 return function (string) { 997 input.value = string; 998 if (input.matches(":dir(rtl)")) { 999 return "rtl"; 1000 } else { 1001 return "ltr"; 1002 } 1003 }; 1004 } else { 1005 return function (string) { 1006 const char = string.trim().charAt(0); 1007 if (RTL_PATTERN.test(char)) { 1008 return "rtl"; 1009 } else { 1010 return "ltr"; 1011 } 1012 }; 1013 } 1014 }(); 1015 1016 let allAttributeNames = null; 1017 let blockAttributeNames = null; 1018 let textAttributeNames = null; 1019 let listAttributeNames = null; 1020 const getAllAttributeNames = () => { 1021 if (!allAttributeNames) { 1022 allAttributeNames = getTextAttributeNames().concat(getBlockAttributeNames()); 1023 } 1024 return allAttributeNames; 1025 }; 1026 const getBlockConfig = attributeName => attributes[attributeName]; 1027 const getBlockAttributeNames = () => { 1028 if (!blockAttributeNames) { 1029 blockAttributeNames = Object.keys(attributes); 1030 } 1031 return blockAttributeNames; 1032 }; 1033 const getTextConfig = attributeName => text_attributes[attributeName]; 1034 const getTextAttributeNames = () => { 1035 if (!textAttributeNames) { 1036 textAttributeNames = Object.keys(text_attributes); 1037 } 1038 return textAttributeNames; 1039 }; 1040 const getListAttributeNames = () => { 1041 if (!listAttributeNames) { 1042 listAttributeNames = []; 1043 for (const key in attributes) { 1044 const { 1045 listAttribute 1046 } = attributes[key]; 1047 if (listAttribute != null) { 1048 listAttributeNames.push(listAttribute); 1049 } 1050 } 1051 } 1052 return listAttributeNames; 1053 }; 1054 1055 /* eslint-disable 1056 */ 1057 const installDefaultCSSForTagName = function (tagName, defaultCSS) { 1058 const styleElement = insertStyleElementForTagName(tagName); 1059 styleElement.textContent = defaultCSS.replace(/%t/g, tagName); 1060 }; 1061 const insertStyleElementForTagName = function (tagName) { 1062 const element = document.createElement("style"); 1063 element.setAttribute("type", "text/css"); 1064 element.setAttribute("data-tag-name", tagName.toLowerCase()); 1065 const nonce = getCSPNonce(); 1066 if (nonce) { 1067 element.setAttribute("nonce", nonce); 1068 } 1069 document.head.insertBefore(element, document.head.firstChild); 1070 return element; 1071 }; 1072 const getCSPNonce = function () { 1073 const element = getMetaElement("trix-csp-nonce") || getMetaElement("csp-nonce"); 1074 if (element) { 1075 const { 1076 nonce, 1077 content 1078 } = element; 1079 return nonce == "" ? content : nonce; 1080 } 1081 }; 1082 const getMetaElement = name => document.head.querySelector("meta[name=".concat(name, "]")); 1083 1084 const testTransferData = { 1085 "application/x-trix-feature-detection": "test" 1086 }; 1087 const dataTransferIsPlainText = function (dataTransfer) { 1088 const text = dataTransfer.getData("text/plain"); 1089 const html = dataTransfer.getData("text/html"); 1090 if (text && html) { 1091 const { 1092 body 1093 } = new DOMParser().parseFromString(html, "text/html"); 1094 if (body.textContent === text) { 1095 return !body.querySelector("*"); 1096 } 1097 } else { 1098 return text === null || text === void 0 ? void 0 : text.length; 1099 } 1100 }; 1101 const dataTransferIsMsOfficePaste = _ref => { 1102 let { 1103 dataTransfer 1104 } = _ref; 1105 return dataTransfer.types.includes("Files") && dataTransfer.types.includes("text/html") && dataTransfer.getData("text/html").includes("urn:schemas-microsoft-com:office:office"); 1106 }; 1107 const dataTransferIsWritable = function (dataTransfer) { 1108 if (!(dataTransfer !== null && dataTransfer !== void 0 && dataTransfer.setData)) return false; 1109 for (const key in testTransferData) { 1110 const value = testTransferData[key]; 1111 try { 1112 dataTransfer.setData(key, value); 1113 if (!dataTransfer.getData(key) === value) return false; 1114 } catch (error) { 1115 return false; 1116 } 1117 } 1118 return true; 1119 }; 1120 const keyEventIsKeyboardCommand = function () { 1121 if (/Mac|^iP/.test(navigator.platform)) { 1122 return event => event.metaKey; 1123 } else { 1124 return event => event.ctrlKey; 1125 } 1126 }(); 1127 function shouldRenderInmmediatelyToDealWithIOSDictation(inputEvent) { 1128 if (/iPhone|iPad/.test(navigator.userAgent)) { 1129 // Handle garbled content and duplicated newlines when using dictation on iOS 18+. Upon dictation completion, iOS sends 1130 // the list of insertText / insertParagraph events in a quick sequence. If we don't render 1131 // the editor synchronously, the internal range fails to update and results in garbled content or duplicated newlines. 1132 // 1133 // This workaround is necessary because iOS doesn't send composing events as expected while dictating: 1134 // https://bugs.webkit.org/show_bug.cgi?id=261764 1135 return !inputEvent.inputType || inputEvent.inputType === "insertParagraph"; 1136 } else { 1137 return false; 1138 } 1139 } 1140 1141 const defer = fn => setTimeout(fn, 1); 1142 1143 /* eslint-disable 1144 id-length, 1145 */ 1146 const copyObject = function () { 1147 let object = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 1148 const result = {}; 1149 for (const key in object) { 1150 const value = object[key]; 1151 result[key] = value; 1152 } 1153 return result; 1154 }; 1155 const objectsAreEqual = function () { 1156 let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 1157 let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 1158 if (Object.keys(a).length !== Object.keys(b).length) { 1159 return false; 1160 } 1161 for (const key in a) { 1162 const value = a[key]; 1163 if (value !== b[key]) { 1164 return false; 1165 } 1166 } 1167 return true; 1168 }; 1169 1170 const normalizeRange = function (range) { 1171 if (range == null) return; 1172 if (!Array.isArray(range)) { 1173 range = [range, range]; 1174 } 1175 return [copyValue(range[0]), copyValue(range[1] != null ? range[1] : range[0])]; 1176 }; 1177 const rangeIsCollapsed = function (range) { 1178 if (range == null) return; 1179 const [start, end] = normalizeRange(range); 1180 return rangeValuesAreEqual(start, end); 1181 }; 1182 const rangesAreEqual = function (leftRange, rightRange) { 1183 if (leftRange == null || rightRange == null) return; 1184 const [leftStart, leftEnd] = normalizeRange(leftRange); 1185 const [rightStart, rightEnd] = normalizeRange(rightRange); 1186 return rangeValuesAreEqual(leftStart, rightStart) && rangeValuesAreEqual(leftEnd, rightEnd); 1187 }; 1188 const copyValue = function (value) { 1189 if (typeof value === "number") { 1190 return value; 1191 } else { 1192 return copyObject(value); 1193 } 1194 }; 1195 const rangeValuesAreEqual = function (left, right) { 1196 if (typeof left === "number") { 1197 return left === right; 1198 } else { 1199 return objectsAreEqual(left, right); 1200 } 1201 }; 1202 1203 class SelectionChangeObserver extends BasicObject { 1204 constructor() { 1205 super(...arguments); 1206 this.update = this.update.bind(this); 1207 this.selectionManagers = []; 1208 } 1209 start() { 1210 if (!this.started) { 1211 this.started = true; 1212 document.addEventListener("selectionchange", this.update, true); 1213 } 1214 } 1215 stop() { 1216 if (this.started) { 1217 this.started = false; 1218 return document.removeEventListener("selectionchange", this.update, true); 1219 } 1220 } 1221 registerSelectionManager(selectionManager) { 1222 if (!this.selectionManagers.includes(selectionManager)) { 1223 this.selectionManagers.push(selectionManager); 1224 return this.start(); 1225 } 1226 } 1227 unregisterSelectionManager(selectionManager) { 1228 this.selectionManagers = this.selectionManagers.filter(sm => sm !== selectionManager); 1229 if (this.selectionManagers.length === 0) { 1230 return this.stop(); 1231 } 1232 } 1233 notifySelectionManagersOfSelectionChange() { 1234 return this.selectionManagers.map(selectionManager => selectionManager.selectionDidChange()); 1235 } 1236 update() { 1237 this.notifySelectionManagersOfSelectionChange(); 1238 } 1239 reset() { 1240 this.update(); 1241 } 1242 } 1243 const selectionChangeObserver = new SelectionChangeObserver(); 1244 const getDOMSelection = function () { 1245 const selection = window.getSelection(); 1246 if (selection.rangeCount > 0) { 1247 return selection; 1248 } 1249 }; 1250 const getDOMRange = function () { 1251 var _getDOMSelection; 1252 const domRange = (_getDOMSelection = getDOMSelection()) === null || _getDOMSelection === void 0 ? void 0 : _getDOMSelection.getRangeAt(0); 1253 if (domRange) { 1254 if (!domRangeIsPrivate(domRange)) { 1255 return domRange; 1256 } 1257 } 1258 }; 1259 const setDOMRange = function (domRange) { 1260 const selection = window.getSelection(); 1261 selection.removeAllRanges(); 1262 selection.addRange(domRange); 1263 return selectionChangeObserver.update(); 1264 }; 1265 1266 // In Firefox, clicking certain <input> elements changes the selection to a 1267 // private element used to draw its UI. Attempting to access properties of those 1268 // elements throws an error. 1269 // https://bugzilla.mozilla.org/show_bug.cgi?id=208427 1270 const domRangeIsPrivate = domRange => nodeIsPrivate(domRange.startContainer) || nodeIsPrivate(domRange.endContainer); 1271 const nodeIsPrivate = node => !Object.getPrototypeOf(node); 1272 1273 /* eslint-disable 1274 id-length, 1275 no-useless-escape, 1276 */ 1277 const normalizeSpaces = string => string.replace(new RegExp("".concat(ZERO_WIDTH_SPACE), "g"), "").replace(new RegExp("".concat(NON_BREAKING_SPACE), "g"), " "); 1278 const normalizeNewlines = string => string.replace(/\r\n?/g, "\n"); 1279 const breakableWhitespacePattern = new RegExp("[^\\S".concat(NON_BREAKING_SPACE, "]")); 1280 const squishBreakableWhitespace = string => string 1281 // Replace all breakable whitespace characters with a space 1282 .replace(new RegExp("".concat(breakableWhitespacePattern.source), "g"), " ") 1283 // Replace two or more spaces with a single space 1284 .replace(/\ {2,}/g, " "); 1285 const summarizeStringChange = function (oldString, newString) { 1286 let added, removed; 1287 oldString = UTF16String.box(oldString); 1288 newString = UTF16String.box(newString); 1289 if (newString.length < oldString.length) { 1290 [removed, added] = utf16StringDifferences(oldString, newString); 1291 } else { 1292 [added, removed] = utf16StringDifferences(newString, oldString); 1293 } 1294 return { 1295 added, 1296 removed 1297 }; 1298 }; 1299 const utf16StringDifferences = function (a, b) { 1300 if (a.isEqualTo(b)) { 1301 return ["", ""]; 1302 } 1303 const diffA = utf16StringDifference(a, b); 1304 const { 1305 length 1306 } = diffA.utf16String; 1307 let diffB; 1308 if (length) { 1309 const { 1310 offset 1311 } = diffA; 1312 const codepoints = a.codepoints.slice(0, offset).concat(a.codepoints.slice(offset + length)); 1313 diffB = utf16StringDifference(b, UTF16String.fromCodepoints(codepoints)); 1314 } else { 1315 diffB = utf16StringDifference(b, a); 1316 } 1317 return [diffA.utf16String.toString(), diffB.utf16String.toString()]; 1318 }; 1319 const utf16StringDifference = function (a, b) { 1320 let leftIndex = 0; 1321 let rightIndexA = a.length; 1322 let rightIndexB = b.length; 1323 while (leftIndex < rightIndexA && a.charAt(leftIndex).isEqualTo(b.charAt(leftIndex))) { 1324 leftIndex++; 1325 } 1326 while (rightIndexA > leftIndex + 1 && a.charAt(rightIndexA - 1).isEqualTo(b.charAt(rightIndexB - 1))) { 1327 rightIndexA--; 1328 rightIndexB--; 1329 } 1330 return { 1331 utf16String: a.slice(leftIndex, rightIndexA), 1332 offset: leftIndex 1333 }; 1334 }; 1335 1336 class Hash extends TrixObject { 1337 static fromCommonAttributesOfObjects() { 1338 let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 1339 if (!objects.length) { 1340 return new this(); 1341 } 1342 let hash = box(objects[0]); 1343 let keys = hash.getKeys(); 1344 objects.slice(1).forEach(object => { 1345 keys = hash.getKeysCommonToHash(box(object)); 1346 hash = hash.slice(keys); 1347 }); 1348 return hash; 1349 } 1350 static box(values) { 1351 return box(values); 1352 } 1353 constructor() { 1354 let values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 1355 super(...arguments); 1356 this.values = copy(values); 1357 } 1358 add(key, value) { 1359 return this.merge(object(key, value)); 1360 } 1361 remove(key) { 1362 return new Hash(copy(this.values, key)); 1363 } 1364 get(key) { 1365 return this.values[key]; 1366 } 1367 has(key) { 1368 return key in this.values; 1369 } 1370 merge(values) { 1371 return new Hash(merge(this.values, unbox(values))); 1372 } 1373 slice(keys) { 1374 const values = {}; 1375 Array.from(keys).forEach(key => { 1376 if (this.has(key)) { 1377 values[key] = this.values[key]; 1378 } 1379 }); 1380 return new Hash(values); 1381 } 1382 getKeys() { 1383 return Object.keys(this.values); 1384 } 1385 getKeysCommonToHash(hash) { 1386 hash = box(hash); 1387 return this.getKeys().filter(key => this.values[key] === hash.values[key]); 1388 } 1389 isEqualTo(values) { 1390 return arraysAreEqual(this.toArray(), box(values).toArray()); 1391 } 1392 isEmpty() { 1393 return this.getKeys().length === 0; 1394 } 1395 toArray() { 1396 if (!this.array) { 1397 const result = []; 1398 for (const key in this.values) { 1399 const value = this.values[key]; 1400 result.push(result.push(key, value)); 1401 } 1402 this.array = result.slice(0); 1403 } 1404 return this.array; 1405 } 1406 toObject() { 1407 return copy(this.values); 1408 } 1409 toJSON() { 1410 return this.toObject(); 1411 } 1412 contentsForInspection() { 1413 return { 1414 values: JSON.stringify(this.values) 1415 }; 1416 } 1417 } 1418 const object = function (key, value) { 1419 const result = {}; 1420 result[key] = value; 1421 return result; 1422 }; 1423 const merge = function (object, values) { 1424 const result = copy(object); 1425 for (const key in values) { 1426 const value = values[key]; 1427 result[key] = value; 1428 } 1429 return result; 1430 }; 1431 const copy = function (object, keyToRemove) { 1432 const result = {}; 1433 const sortedKeys = Object.keys(object).sort(); 1434 sortedKeys.forEach(key => { 1435 if (key !== keyToRemove) { 1436 result[key] = object[key]; 1437 } 1438 }); 1439 return result; 1440 }; 1441 const box = function (object) { 1442 if (object instanceof Hash) { 1443 return object; 1444 } else { 1445 return new Hash(object); 1446 } 1447 }; 1448 const unbox = function (object) { 1449 if (object instanceof Hash) { 1450 return object.values; 1451 } else { 1452 return object; 1453 } 1454 }; 1455 1456 class ObjectGroup { 1457 static groupObjects() { 1458 let ungroupedObjects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 1459 let { 1460 depth, 1461 asTree 1462 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 1463 let group; 1464 if (asTree) { 1465 if (depth == null) { 1466 depth = 0; 1467 } 1468 } 1469 const objects = []; 1470 Array.from(ungroupedObjects).forEach(object => { 1471 var _object$canBeGrouped2; 1472 if (group) { 1473 var _object$canBeGrouped, _group$canBeGroupedWi, _group; 1474 if ((_object$canBeGrouped = object.canBeGrouped) !== null && _object$canBeGrouped !== void 0 && _object$canBeGrouped.call(object, depth) && (_group$canBeGroupedWi = (_group = group[group.length - 1]).canBeGroupedWith) !== null && _group$canBeGroupedWi !== void 0 && _group$canBeGroupedWi.call(_group, object, depth)) { 1475 group.push(object); 1476 return; 1477 } else { 1478 objects.push(new this(group, { 1479 depth, 1480 asTree 1481 })); 1482 group = null; 1483 } 1484 } 1485 if ((_object$canBeGrouped2 = object.canBeGrouped) !== null && _object$canBeGrouped2 !== void 0 && _object$canBeGrouped2.call(object, depth)) { 1486 group = [object]; 1487 } else { 1488 objects.push(object); 1489 } 1490 }); 1491 if (group) { 1492 objects.push(new this(group, { 1493 depth, 1494 asTree 1495 })); 1496 } 1497 return objects; 1498 } 1499 constructor() { 1500 let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 1501 let { 1502 depth, 1503 asTree 1504 } = arguments.length > 1 ? arguments[1] : undefined; 1505 this.objects = objects; 1506 if (asTree) { 1507 this.depth = depth; 1508 this.objects = this.constructor.groupObjects(this.objects, { 1509 asTree, 1510 depth: this.depth + 1 1511 }); 1512 } 1513 } 1514 getObjects() { 1515 return this.objects; 1516 } 1517 getDepth() { 1518 return this.depth; 1519 } 1520 getCacheKey() { 1521 const keys = ["objectGroup"]; 1522 Array.from(this.getObjects()).forEach(object => { 1523 keys.push(object.getCacheKey()); 1524 }); 1525 return keys.join("/"); 1526 } 1527 } 1528 1529 class ObjectMap extends BasicObject { 1530 constructor() { 1531 let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 1532 super(...arguments); 1533 this.objects = {}; 1534 Array.from(objects).forEach(object => { 1535 const hash = JSON.stringify(object); 1536 if (this.objects[hash] == null) { 1537 this.objects[hash] = object; 1538 } 1539 }); 1540 } 1541 find(object) { 1542 const hash = JSON.stringify(object); 1543 return this.objects[hash]; 1544 } 1545 } 1546 1547 class ElementStore { 1548 constructor(elements) { 1549 this.reset(elements); 1550 } 1551 add(element) { 1552 const key = getKey(element); 1553 this.elements[key] = element; 1554 } 1555 remove(element) { 1556 const key = getKey(element); 1557 const value = this.elements[key]; 1558 if (value) { 1559 delete this.elements[key]; 1560 return value; 1561 } 1562 } 1563 reset() { 1564 let elements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 1565 this.elements = {}; 1566 Array.from(elements).forEach(element => { 1567 this.add(element); 1568 }); 1569 return elements; 1570 } 1571 } 1572 const getKey = element => element.dataset.trixStoreKey; 1573 1574 class Operation extends BasicObject { 1575 isPerforming() { 1576 return this.performing === true; 1577 } 1578 hasPerformed() { 1579 return this.performed === true; 1580 } 1581 hasSucceeded() { 1582 return this.performed && this.succeeded; 1583 } 1584 hasFailed() { 1585 return this.performed && !this.succeeded; 1586 } 1587 getPromise() { 1588 if (!this.promise) { 1589 this.promise = new Promise((resolve, reject) => { 1590 this.performing = true; 1591 return this.perform((succeeded, result) => { 1592 this.succeeded = succeeded; 1593 this.performing = false; 1594 this.performed = true; 1595 if (this.succeeded) { 1596 resolve(result); 1597 } else { 1598 reject(result); 1599 } 1600 }); 1601 }); 1602 } 1603 return this.promise; 1604 } 1605 perform(callback) { 1606 return callback(false); 1607 } 1608 release() { 1609 var _this$promise, _this$promise$cancel; 1610 (_this$promise = this.promise) === null || _this$promise === void 0 || (_this$promise$cancel = _this$promise.cancel) === null || _this$promise$cancel === void 0 || _this$promise$cancel.call(_this$promise); 1611 this.promise = null; 1612 this.performing = null; 1613 this.performed = null; 1614 this.succeeded = null; 1615 } 1616 } 1617 Operation.proxyMethod("getPromise().then"); 1618 Operation.proxyMethod("getPromise().catch"); 1619 1620 class ObjectView extends BasicObject { 1621 constructor(object) { 1622 let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 1623 super(...arguments); 1624 this.object = object; 1625 this.options = options; 1626 this.childViews = []; 1627 this.rootView = this; 1628 } 1629 getNodes() { 1630 if (!this.nodes) { 1631 this.nodes = this.createNodes(); 1632 } 1633 return this.nodes.map(node => node.cloneNode(true)); 1634 } 1635 invalidate() { 1636 var _this$parentView; 1637 this.nodes = null; 1638 this.childViews = []; 1639 return (_this$parentView = this.parentView) === null || _this$parentView === void 0 ? void 0 : _this$parentView.invalidate(); 1640 } 1641 invalidateViewForObject(object) { 1642 var _this$findViewForObje; 1643 return (_this$findViewForObje = this.findViewForObject(object)) === null || _this$findViewForObje === void 0 ? void 0 : _this$findViewForObje.invalidate(); 1644 } 1645 findOrCreateCachedChildView(viewClass, object, options) { 1646 let view = this.getCachedViewForObject(object); 1647 if (view) { 1648 this.recordChildView(view); 1649 } else { 1650 view = this.createChildView(...arguments); 1651 this.cacheViewForObject(view, object); 1652 } 1653 return view; 1654 } 1655 createChildView(viewClass, object) { 1656 let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; 1657 if (object instanceof ObjectGroup) { 1658 options.viewClass = viewClass; 1659 viewClass = ObjectGroupView; 1660 } 1661 const view = new viewClass(object, options); 1662 return this.recordChildView(view); 1663 } 1664 recordChildView(view) { 1665 view.parentView = this; 1666 view.rootView = this.rootView; 1667 this.childViews.push(view); 1668 return view; 1669 } 1670 getAllChildViews() { 1671 let views = []; 1672 this.childViews.forEach(childView => { 1673 views.push(childView); 1674 views = views.concat(childView.getAllChildViews()); 1675 }); 1676 return views; 1677 } 1678 findElement() { 1679 return this.findElementForObject(this.object); 1680 } 1681 findElementForObject(object) { 1682 const id = object === null || object === void 0 ? void 0 : object.id; 1683 if (id) { 1684 return this.rootView.element.querySelector("[data-trix-id='".concat(id, "']")); 1685 } 1686 } 1687 findViewForObject(object) { 1688 for (const view of this.getAllChildViews()) { 1689 if (view.object === object) { 1690 return view; 1691 } 1692 } 1693 } 1694 getViewCache() { 1695 if (this.rootView === this) { 1696 if (this.isViewCachingEnabled()) { 1697 if (!this.viewCache) { 1698 this.viewCache = {}; 1699 } 1700 return this.viewCache; 1701 } 1702 } else { 1703 return this.rootView.getViewCache(); 1704 } 1705 } 1706 isViewCachingEnabled() { 1707 return this.shouldCacheViews !== false; 1708 } 1709 enableViewCaching() { 1710 this.shouldCacheViews = true; 1711 } 1712 disableViewCaching() { 1713 this.shouldCacheViews = false; 1714 } 1715 getCachedViewForObject(object) { 1716 var _this$getViewCache; 1717 return (_this$getViewCache = this.getViewCache()) === null || _this$getViewCache === void 0 ? void 0 : _this$getViewCache[object.getCacheKey()]; 1718 } 1719 cacheViewForObject(view, object) { 1720 const cache = this.getViewCache(); 1721 if (cache) { 1722 cache[object.getCacheKey()] = view; 1723 } 1724 } 1725 garbageCollectCachedViews() { 1726 const cache = this.getViewCache(); 1727 if (cache) { 1728 const views = this.getAllChildViews().concat(this); 1729 const objectKeys = views.map(view => view.object.getCacheKey()); 1730 for (const key in cache) { 1731 if (!objectKeys.includes(key)) { 1732 delete cache[key]; 1733 } 1734 } 1735 } 1736 } 1737 } 1738 class ObjectGroupView extends ObjectView { 1739 constructor() { 1740 super(...arguments); 1741 this.objectGroup = this.object; 1742 this.viewClass = this.options.viewClass; 1743 delete this.options.viewClass; 1744 } 1745 getChildViews() { 1746 if (!this.childViews.length) { 1747 Array.from(this.objectGroup.getObjects()).forEach(object => { 1748 this.findOrCreateCachedChildView(this.viewClass, object, this.options); 1749 }); 1750 } 1751 return this.childViews; 1752 } 1753 createNodes() { 1754 const element = this.createContainerElement(); 1755 this.getChildViews().forEach(view => { 1756 Array.from(view.getNodes()).forEach(node => { 1757 element.appendChild(node); 1758 }); 1759 }); 1760 return [element]; 1761 } 1762 createContainerElement() { 1763 let depth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.objectGroup.getDepth(); 1764 return this.getChildViews()[0].createContainerElement(depth); 1765 } 1766 } 1767 1768 /*! @license DOMPurify 3.
vendor: 9,474 bytes, lines 1768-1963
17682.7 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.7/LICENSE */ 1769 1770 const { 1771 entries, 1772 setPrototypeOf, 1773 isFrozen, 1774 getPrototypeOf, 1775 getOwnPropertyDescriptor 1776 } = Object; 1777 let { 1778 freeze, 1779 seal, 1780 create 1781 } = Object; // eslint-disable-line import/no-mutable-exports 1782 let { 1783 apply, 1784 construct 1785 } = typeof Reflect !== 'undefined' && Reflect; 1786 if (!freeze) { 1787 freeze = function freeze(x) { 1788 return x; 1789 }; 1790 } 1791 if (!seal) { 1792 seal = function seal(x) { 1793 return x; 1794 }; 1795 } 1796 if (!apply) { 1797 apply = function apply(func, thisArg) { 1798 for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { 1799 args[_key - 2] = arguments[_key]; 1800 } 1801 return func.apply(thisArg, args); 1802 }; 1803 } 1804 if (!construct) { 1805 construct = function construct(Func) { 1806 for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { 1807 args[_key2 - 1] = arguments[_key2]; 1808 } 1809 return new Func(...args); 1810 }; 1811 } 1812 const arrayForEach = unapply(Array.prototype.forEach); 1813 const arrayLastIndexOf = unapply(Array.prototype.lastIndexOf); 1814 const arrayPop = unapply(Array.prototype.pop); 1815 const arrayPush = unapply(Array.prototype.push); 1816 const arraySplice = unapply(Array.prototype.splice); 1817 const stringToLowerCase = unapply(String.prototype.toLowerCase); 1818 const stringToString = unapply(String.prototype.toString); 1819 const stringMatch = unapply(String.prototype.match); 1820 const stringReplace = unapply(String.prototype.replace); 1821 const stringIndexOf = unapply(String.prototype.indexOf); 1822 const stringTrim = unapply(String.prototype.trim); 1823 const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty); 1824 const regExpTest = unapply(RegExp.prototype.test); 1825 const typeErrorCreate = unconstruct(TypeError); 1826 /** 1827 * Creates a new function that calls the given function with a specified thisArg and arguments. 1828 * 1829 * @param func - The function to be wrapped and called. 1830 * @returns A new function that calls the given function with a specified thisArg and arguments. 1831 */ 1832 function unapply(func) { 1833 return function (thisArg) { 1834 if (thisArg instanceof RegExp) { 1835 thisArg.lastIndex = 0; 1836 } 1837 for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { 1838 args[_key3 - 1] = arguments[_key3]; 1839 } 1840 return apply(func, thisArg, args); 1841 }; 1842 } 1843 /** 1844 * Creates a new function that constructs an instance of the given constructor function with the provided arguments. 1845 * 1846 * @param func - The constructor function to be wrapped and called. 1847 * @returns A new function that constructs an instance of the given constructor function with the provided arguments. 1848 */ 1849 function unconstruct(Func) { 1850 return function () { 1851 for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { 1852 args[_key4] = arguments[_key4]; 1853 } 1854 return construct(Func, args); 1855 }; 1856 } 1857 /** 1858 * Add properties to a lookup table 1859 * 1860 * @param set - The set to which elements will be added. 1861 * @param array - The array containing elements to be added to the set. 1862 * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set. 1863 * @returns The modified set with added elements. 1864 */ 1865 function addToSet(set, array) { 1866 let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase; 1867 if (setPrototypeOf) { 1868 // Make 'in' and truthy checks like Boolean(set.constructor) 1869 // independent of any properties defined on Object.prototype. 1870 // Prevent prototype setters from intercepting set as a this value. 1871 setPrototypeOf(set, null); 1872 } 1873 let l = array.length; 1874 while (l--) { 1875 let element = array[l]; 1876 if (typeof element === 'string') { 1877 const lcElement = transformCaseFunc(element); 1878 if (lcElement !== element) { 1879 // Config presets (e.g. tags.js, attrs.js) are immutable. 1880 if (!isFrozen(array)) { 1881 array[l] = lcElement; 1882 } 1883 element = lcElement; 1884 } 1885 } 1886 set[element] = true; 1887 } 1888 return set; 1889 } 1890 /** 1891 * Clean up an array to harden against CSPP 1892 * 1893 * @param array - The array to be cleaned. 1894 * @returns The cleaned version of the array 1895 */ 1896 function cleanArray(array) { 1897 for (let index = 0; index < array.length; index++) { 1898 const isPropertyExist = objectHasOwnProperty(array, index); 1899 if (!isPropertyExist) { 1900 array[index] = null; 1901 } 1902 } 1903 return array; 1904 } 1905 /** 1906 * Shallow clone an object 1907 * 1908 * @param object - The object to be cloned. 1909 * @returns A new object that copies the original. 1910 */ 1911 function clone(object) { 1912 const newObject = create(null); 1913 for (const [property, value] of entries(object)) { 1914 const isPropertyExist = objectHasOwnProperty(object, property); 1915 if (isPropertyExist) { 1916 if (Array.isArray(value)) { 1917 newObject[property] = cleanArray(value); 1918 } else if (value && typeof value === 'object' && value.constructor === Object) { 1919 newObject[property] = clone(value); 1920 } else { 1921 newObject[property] = value; 1922 } 1923 } 1924 } 1925 return newObject; 1926 } 1927 /** 1928 * This method automatically checks if the prop is function or getter and behaves accordingly. 1929 * 1930 * @param object - The object to look up the getter function in its prototype chain. 1931 * @param prop - The property name for which to find the getter function. 1932 * @returns The getter function found in the prototype chain or a fallback function. 1933 */ 1934 function lookupGetter(object, prop) { 1935 while (object !== null) { 1936 const desc = getOwnPropertyDescriptor(object, prop); 1937 if (desc) { 1938 if (desc.get) { 1939 return unapply(desc.get); 1940 } 1941 if (typeof desc.value === 'function') { 1942 return unapply(desc.value); 1943 } 1944 } 1945 object = getPrototypeOf(object); 1946 } 1947 function fallbackValue() { 1948 return null; 1949 } 1950 return fallbackValue; 1951 } 1952 const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']); 1953 const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'slot', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']); 1954 const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']); 1955 // List of SVG elements that are disallowed by default. 1956 // We still need to know them so that we can do namespace 1957 // checks properly in case one wants to add them to 1958 // allow-list. 1959 const svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']); 1960 const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']); 1961 // Similarly to SVG, we want to know all MathML elements, 1962 // even those that we disallow by default. 1963 const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'n
1963one']); 1964 const text = freeze(['#text']); 1965 const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']); 1966 const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']); 1967 const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'n
vendor: 8,803 bytes, lines 1967-2182
1967otation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']); 1968 const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']); 1969 1970 // eslint-disable-next-line unicorn/better-regex 1971 const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode 1972 const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm); 1973 const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex 1974 const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape 1975 const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape 1976 const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape 1977 ); 1978 const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); 1979 const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex 1980 ); 1981 const DOCTYPE_NAME = seal(/^html$/i); 1982 const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i); 1983 var EXPRESSIONS = /*#__PURE__*/Object.freeze({ 1984 __proto__: null, 1985 ARIA_ATTR: ARIA_ATTR, 1986 ATTR_WHITESPACE: ATTR_WHITESPACE, 1987 CUSTOM_ELEMENT: CUSTOM_ELEMENT, 1988 DATA_ATTR: DATA_ATTR, 1989 DOCTYPE_NAME: DOCTYPE_NAME, 1990 ERB_EXPR: ERB_EXPR, 1991 IS_ALLOWED_URI: IS_ALLOWED_URI, 1992 IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA, 1993 MUSTACHE_EXPR: MUSTACHE_EXPR, 1994 TMPLIT_EXPR: TMPLIT_EXPR 1995 }); 1996 1997 /* eslint-disable @typescript-eslint/indent */ 1998 // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType 1999 const NODE_TYPE = { 2000 element: 1, 2001 attribute: 2, 2002 text: 3, 2003 cdataSection: 4, 2004 entityReference: 5, 2005 // Deprecated 2006 entityNode: 6, 2007 // Deprecated 2008 progressingInstruction: 7, 2009 comment: 8, 2010 document: 9, 2011 documentType: 10, 2012 documentFragment: 11, 2013 notation: 12 // Deprecated 2014 }; 2015 const getGlobal = function getGlobal() { 2016 return typeof window === 'undefined' ? null : window; 2017 }; 2018 /** 2019 * Creates a no-op policy for internal use only. 2020 * Don't export this function outside this module! 2021 * @param trustedTypes The policy factory. 2022 * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix). 2023 * @return The policy created (or null, if Trusted Types 2024 * are not supported or creating the policy failed). 2025 */ 2026 const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) { 2027 if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') { 2028 return null; 2029 } 2030 // Allow the callers to control the unique policy name 2031 // by adding a data-tt-policy-suffix to the script element with the DOMPurify. 2032 // Policy creation with duplicate names throws in Trusted Types. 2033 let suffix = null; 2034 const ATTR_NAME = 'data-tt-policy-suffix'; 2035 if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) { 2036 suffix = purifyHostElement.getAttribute(ATTR_NAME); 2037 } 2038 const policyName = 'dompurify' + (suffix ? '#' + suffix : ''); 2039 try { 2040 return trustedTypes.createPolicy(policyName, { 2041 createHTML(html) { 2042 return html; 2043 }, 2044 createScriptURL(scriptUrl) { 2045 return scriptUrl; 2046 } 2047 }); 2048 } catch (_) { 2049 // Policy creation failed (most likely another DOMPurify script has 2050 // already run). Skip creating the policy, as this will only cause errors 2051 // if TT are enforced. 2052 console.warn('TrustedTypes policy ' + policyName + ' could not be created.'); 2053 return null; 2054 } 2055 }; 2056 const _createHooksMap = function _createHooksMap() { 2057 return { 2058 afterSanitizeAttributes: [], 2059 afterSanitizeElements: [], 2060 afterSanitizeShadowDOM: [], 2061 beforeSanitizeAttributes: [], 2062 beforeSanitizeElements: [], 2063 beforeSanitizeShadowDOM: [], 2064 uponSanitizeAttribute: [], 2065 uponSanitizeElement: [], 2066 uponSanitizeShadowNode: [] 2067 }; 2068 }; 2069 function createDOMPurify() { 2070 let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal(); 2071 const DOMPurify = root => createDOMPurify(root); 2072 DOMPurify.version = '3.2.7'; 2073 DOMPurify.removed = []; 2074 if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) { 2075 // Not running in a browser, provide a factory function 2076 // so that you can pass your own Window 2077 DOMPurify.isSupported = false; 2078 return DOMPurify; 2079 } 2080 let { 2081 document 2082 } = window; 2083 const originalDocument = document; 2084 const currentScript = originalDocument.currentScript; 2085 const { 2086 DocumentFragment, 2087 HTMLTemplateElement, 2088 Node, 2089 Element, 2090 NodeFilter, 2091 NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap, 2092 HTMLFormElement, 2093 DOMParser, 2094 trustedTypes 2095 } = window; 2096 const ElementPrototype = Element.prototype; 2097 const cloneNode = lookupGetter(ElementPrototype, 'cloneNode'); 2098 const remove = lookupGetter(ElementPrototype, 'remove'); 2099 const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling'); 2100 const getChildNodes = lookupGetter(ElementPrototype, 'childNodes'); 2101 const getParentNode = lookupGetter(ElementPrototype, 'parentNode'); 2102 // As per issue #47, the web-components registry is inherited by a 2103 // new document created via createHTMLDocument. As per the spec 2104 // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries) 2105 // a new empty registry is used when creating a template contents owner 2106 // document, so we use that as our parent document to ensure nothing 2107 // is inherited. 2108 if (typeof HTMLTemplateElement === 'function') { 2109 const template = document.createElement('template'); 2110 if (template.content && template.content.ownerDocument) { 2111 document = template.content.ownerDocument; 2112 } 2113 } 2114 let trustedTypesPolicy; 2115 let emptyHTML = ''; 2116 const { 2117 implementation, 2118 createNodeIterator, 2119 createDocumentFragment, 2120 getElementsByTagName 2121 } = document; 2122 const { 2123 importNode 2124 } = originalDocument; 2125 let hooks = _createHooksMap(); 2126 /** 2127 * Expose whether this browser supports running the full DOMPurify. 2128 */ 2129 DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined; 2130 const { 2131 MUSTACHE_EXPR, 2132 ERB_EXPR, 2133 TMPLIT_EXPR, 2134 DATA_ATTR, 2135 ARIA_ATTR, 2136 IS_SCRIPT_OR_DATA, 2137 ATTR_WHITESPACE, 2138 CUSTOM_ELEMENT 2139 } = EXPRESSIONS; 2140 let { 2141 IS_ALLOWED_URI: IS_ALLOWED_URI$1 2142 } = EXPRESSIONS; 2143 /** 2144 * We consider the elements and attributes below to be safe. Ideally 2145 * don't add any new ones but feel free to remove unwanted ones. 2146 */ 2147 /* allowed element names */ 2148 let ALLOWED_TAGS = null; 2149 const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]); 2150 /* Allowed attribute names */ 2151 let ALLOWED_ATTR = null; 2152 const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]); 2153 /* 2154 * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements. 2155 * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements) 2156 * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list) 2157 * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`. 2158 */ 2159 let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, { 2160 tagNameCheck: { 2161 writable: true, 2162 configurable: false, 2163 enumerable: true, 2164 value: null 2165 }, 2166 attributeNameCheck: { 2167 writable: true, 2168 configurable: false, 2169 enumerable: true, 2170 value: null 2171 }, 2172 allowCustomizedBuiltInElements: { 2173 writable: true, 2174 configurable: false, 2175 enumerable: true, 2176 value: false 2177 } 2178 })); 2179 /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */ 2180 let FORBID_TAGS = null; 2181 /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */ 2182 let FORBID_ATTR = null
vendor: 3,330 bytes, lines 2182-2246
2182; 2183 /* Decide if ARIA attributes are okay */ 2184 let ALLOW_ARIA_ATTR = true; 2185 /* Decide if custom data attributes are okay */ 2186 let ALLOW_DATA_ATTR = true; 2187 /* Decide if unknown protocols are okay */ 2188 let ALLOW_UNKNOWN_PROTOCOLS = false; 2189 /* Decide if self-closing tags in attributes are allowed. 2190 * Usually removed due to a mXSS issue in jQuery 3.0 */ 2191 let ALLOW_SELF_CLOSE_IN_ATTR = true; 2192 /* Output should be safe for common template engines. 2193 * This means, DOMPurify removes data attributes, mustaches and ERB 2194 */ 2195 let SAFE_FOR_TEMPLATES = false; 2196 /* Output should be safe even for XML used within HTML and alike. 2197 * This means, DOMPurify removes comments when containing risky content. 2198 */ 2199 let SAFE_FOR_XML = true; 2200 /* Decide if document with <html>... should be returned */ 2201 let WHOLE_DOCUMENT = false; 2202 /* Track whether config is already set on this instance of DOMPurify. */ 2203 let SET_CONFIG = false; 2204 /* Decide if all elements (e.g. style, script) must be children of 2205 * document.body. By default, browsers might move them to document.head */ 2206 let FORCE_BODY = false; 2207 /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html 2208 * string (or a TrustedHTML object if Trusted Types are supported). 2209 * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead 2210 */ 2211 let RETURN_DOM = false; 2212 /* Decide if a DOM `DocumentFragment` should be returned, instead of a html 2213 * string (or a TrustedHTML object if Trusted Types are supported) */ 2214 let RETURN_DOM_FRAGMENT = false; 2215 /* Try to return a Trusted Type object instead of a string, return a string in 2216 * case Trusted Types are not supported */ 2217 let RETURN_TRUSTED_TYPE = false; 2218 /* Output should be free from DOM clobbering attacks? 2219 * This sanitizes markups named with colliding, clobberable built-in DOM APIs. 2220 */ 2221 let SANITIZE_DOM = true; 2222 /* Achieve full DOM Clobbering protection by isolating the namespace of named 2223 * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules. 2224 * 2225 * HTML/DOM spec rules that enable DOM Clobbering: 2226 * - Named Access on Window (§7.3.3) 2227 * - DOM Tree Accessors (§3.1.5) 2228 * - Form Element Parent-Child Relations (§4.10.3) 2229 * - Iframe srcdoc / Nested WindowProxies (§4.8.5) 2230 * - HTMLCollection (§4.2.10.2) 2231 * 2232 * Namespace isolation is implemented by prefixing `id` and `name` attributes 2233 * with a constant string, i.e., `user-content-` 2234 */ 2235 let SANITIZE_NAMED_PROPS = false; 2236 const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-'; 2237 /* Keep element content when removing element? */ 2238 let KEEP_CONTENT = true; 2239 /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead 2240 * of importing it into a new Document and returning a sanitized copy */ 2241 let IN_PLACE = false; 2242 /* Allow usage of profiles like html, svg and mathMl */ 2243 let USE_PROFILES = {}; 2244 /* Tags to ignore content of when KEEP_CONTENT is true */ 2245 let FORBID_CONTENTS = null; 2246 const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'n
vendor: 5,875 bytes, lines 2246-2333
2246oscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']); 2247 /* Tags that are safe for data: URIs */ 2248 let DATA_URI_TAGS = null; 2249 const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']); 2250 /* Attributes safe for values like "javascript:" */ 2251 let URI_SAFE_ATTRIBUTES = null; 2252 const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']); 2253 const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML'; 2254 const SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; 2255 const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'; 2256 /* Document namespace */ 2257 let NAMESPACE = HTML_NAMESPACE; 2258 let IS_EMPTY_INPUT = false; 2259 /* Allowed XHTML+XML namespaces */ 2260 let ALLOWED_NAMESPACES = null; 2261 const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString); 2262 let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']); 2263 let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']); 2264 // Certain elements are allowed in both SVG and HTML 2265 // namespace. We need to specify them explicitly 2266 // so that they don't get erroneously deleted from 2267 // HTML namespace. 2268 const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']); 2269 /* Parsing of strict XHTML documents */ 2270 let PARSER_MEDIA_TYPE = null; 2271 const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html']; 2272 const DEFAULT_PARSER_MEDIA_TYPE = 'text/html'; 2273 let transformCaseFunc = null; 2274 /* Keep a reference to config to pass to hooks */ 2275 let CONFIG = null; 2276 /* Ideally, do not touch anything below this line */ 2277 /* ______________________________________________ */ 2278 const formElement = document.createElement('form'); 2279 const isRegexOrFunction = function isRegexOrFunction(testValue) { 2280 return testValue instanceof RegExp || testValue instanceof Function; 2281 }; 2282 /** 2283 * _parseConfig 2284 * 2285 * @param cfg optional config literal 2286 */ 2287 // eslint-disable-next-line complexity 2288 const _parseConfig = function _parseConfig() { 2289 let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 2290 if (CONFIG && CONFIG === cfg) { 2291 return; 2292 } 2293 /* Shield configuration object from tampering */ 2294 if (!cfg || typeof cfg !== 'object') { 2295 cfg = {}; 2296 } 2297 /* Shield configuration object from prototype pollution */ 2298 cfg = clone(cfg); 2299 PARSER_MEDIA_TYPE = 2300 // eslint-disable-next-line unicorn/prefer-includes 2301 SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE; 2302 // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is. 2303 transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase; 2304 /* Set configuration parameters */ 2305 ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS; 2306 ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR; 2307 ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES; 2308 URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES; 2309 DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS; 2310 FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS; 2311 FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({}); 2312 FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({}); 2313 USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false; 2314 ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true 2315 ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true 2316 ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false 2317 ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true 2318 SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false 2319 SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true 2320 WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false 2321 RETURN_DOM = cfg.RETURN_DOM || false; // Default false 2322 RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false 2323 RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false 2324 FORCE_BODY = cfg.FORCE_BODY || false; // Default false 2325 SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true 2326 SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false 2327 KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true 2328 IN_PLACE = cfg.IN_PLACE || false; // Default false 2329 IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI; 2330 NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE; 2331 MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS; 2332 HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS; 2333 CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING ||
vendor: 1,622 bytes, lines 2333-2372
2333{}; 2334 if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) { 2335 CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck; 2336 } 2337 if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) { 2338 CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck; 2339 } 2340 if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') { 2341 CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements; 2342 } 2343 if (SAFE_FOR_TEMPLATES) { 2344 ALLOW_DATA_ATTR = false; 2345 } 2346 if (RETURN_DOM_FRAGMENT) { 2347 RETURN_DOM = true; 2348 } 2349 /* Parse profile info */ 2350 if (USE_PROFILES) { 2351 ALLOWED_TAGS = addToSet({}, text); 2352 ALLOWED_ATTR = []; 2353 if (USE_PROFILES.html === true) { 2354 addToSet(ALLOWED_TAGS, html$1); 2355 addToSet(ALLOWED_ATTR, html); 2356 } 2357 if (USE_PROFILES.svg === true) { 2358 addToSet(ALLOWED_TAGS, svg$1); 2359 addToSet(ALLOWED_ATTR, svg); 2360 addToSet(ALLOWED_ATTR, xml); 2361 } 2362 if (USE_PROFILES.svgFilters === true) { 2363 addToSet(ALLOWED_TAGS, svgFilters); 2364 addToSet(ALLOWED_ATTR, svg); 2365 addToSet(ALLOWED_ATTR, xml); 2366 } 2367 if (USE_PROFILES.mathMl === true) { 2368 addToSet(ALLOWED_TAGS, mathMl$1); 2369 addToSet(ALLOWED_ATTR, mathMl); 2370 addToSet(ALLOWED_ATTR, xml); 2371 } 2372 }
vendor: 5,664 bytes, lines 2373-2500
2373 /* Merge configuration parameters */ 2374 if (cfg.ADD_TAGS) { 2375 if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) { 2376 ALLOWED_TAGS = clone(ALLOWED_TAGS); 2377 } 2378 addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc); 2379 } 2380 if (cfg.ADD_ATTR) { 2381 if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) { 2382 ALLOWED_ATTR = clone(ALLOWED_ATTR); 2383 } 2384 addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc); 2385 } 2386 if (cfg.ADD_URI_SAFE_ATTR) { 2387 addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc); 2388 } 2389 if (cfg.FORBID_CONTENTS) { 2390 if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) { 2391 FORBID_CONTENTS = clone(FORBID_CONTENTS); 2392 } 2393 addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc); 2394 } 2395 /* Add #text in case KEEP_CONTENT is set to true */ 2396 if (KEEP_CONTENT) { 2397 ALLOWED_TAGS['#text'] = true; 2398 } 2399 /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */ 2400 if (WHOLE_DOCUMENT) { 2401 addToSet(ALLOWED_TAGS, ['html', 'head', 'body']); 2402 } 2403 /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */ 2404 if (ALLOWED_TAGS.table) { 2405 addToSet(ALLOWED_TAGS, ['tbody']); 2406 delete FORBID_TAGS.tbody; 2407 } 2408 if (cfg.TRUSTED_TYPES_POLICY) { 2409 if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') { 2410 throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.'); 2411 } 2412 if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') { 2413 throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.'); 2414 } 2415 // Overwrite existing TrustedTypes policy. 2416 trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY; 2417 // Sign local variables required by `sanitize`. 2418 emptyHTML = trustedTypesPolicy.createHTML(''); 2419 } else { 2420 // Uninitialized policy, attempt to initialize the internal dompurify policy. 2421 if (trustedTypesPolicy === undefined) { 2422 trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript); 2423 } 2424 // If creating the internal policy succeeded sign internal variables. 2425 if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') { 2426 emptyHTML = trustedTypesPolicy.createHTML(''); 2427 } 2428 } 2429 // Prevent further manipulation of configuration. 2430 // Not available in IE8, Safari 5, etc. 2431 if (freeze) { 2432 freeze(cfg); 2433 } 2434 CONFIG = cfg; 2435 }; 2436 /* Keep track of all possible SVG and MathML tags 2437 * so that we can perform the namespace checks 2438 * correctly. */ 2439 const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]); 2440 const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]); 2441 /** 2442 * @param element a DOM element whose namespace is being checked 2443 * @returns Return false if the element has a 2444 * namespace that a spec-compliant parser would never 2445 * return. Return true otherwise. 2446 */ 2447 const _checkValidNamespace = function _checkValidNamespace(element) { 2448 let parent = getParentNode(element); 2449 // In JSDOM, if we're inside shadow DOM, then parentNode 2450 // can be null. We just simulate parent in this case. 2451 if (!parent || !parent.tagName) { 2452 parent = { 2453 namespaceURI: NAMESPACE, 2454 tagName: 'template' 2455 }; 2456 } 2457 const tagName = stringToLowerCase(element.tagName); 2458 const parentTagName = stringToLowerCase(parent.tagName); 2459 if (!ALLOWED_NAMESPACES[element.namespaceURI]) { 2460 return false; 2461 } 2462 if (element.namespaceURI === SVG_NAMESPACE) { 2463 // The only way to switch from HTML namespace to SVG 2464 // is via <svg>. If it happens via any other tag, then 2465 // it should be killed. 2466 if (parent.namespaceURI === HTML_NAMESPACE) { 2467 return tagName === 'svg'; 2468 } 2469 // The only way to switch from MathML to SVG is via` 2470 // svg if parent is either <annotation-xml> or MathML 2471 // text integration points. 2472 if (parent.namespaceURI === MATHML_NAMESPACE) { 2473 return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]); 2474 } 2475 // We only allow elements that are defined in SVG 2476 // spec. All others are disallowed in SVG namespace. 2477 return Boolean(ALL_SVG_TAGS[tagName]); 2478 } 2479 if (element.namespaceURI === MATHML_NAMESPACE) { 2480 // The only way to switch from HTML namespace to MathML 2481 // is via <math>. If it happens via any other tag, then 2482 // it should be killed. 2483 if (parent.namespaceURI === HTML_NAMESPACE) { 2484 return tagName === 'math'; 2485 } 2486 // The only way to switch from SVG to MathML is via 2487 // <math> and HTML integration points 2488 if (parent.namespaceURI === SVG_NAMESPACE) { 2489 return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName]; 2490 } 2491 // We only allow elements that are defined in MathML 2492 // spec. All others are disallowed in MathML namespace. 2493 return Boolean(ALL_MATHML_TAGS[tagName]); 2494 } 2495 if (element.namespaceURI === HTML_NAMESPACE) { 2496 // The only way to switch from SVG to HTML is via 2497 // HTML integration points, and from MathML to HTML 2498 // is via MathML text integration points 2499 if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) { 2500 return false;
2501 } 2502 if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) { 2503 return false; 2504 } 2505 // We disallow tags that are specific for MathML 2506 // or SVG and should never appear in HTML namespace 2507 return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]); 2508 } 2509 // For XHTML and XML documents that support custom namespaces 2510 if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) { 2511 return true; 2512 } 2513 // The code should never reach this place (this means 2514 // that the element somehow got namespace that is not 2515 // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES). 2516 // Return false just in case. 2517 return false; 2518 }; 2519 /** 2520 * _forceRemove 2521 * 2522 * @param node a DOM node 2523 */ 2524 const _forceRemove = function _forceRemove(node) { 2525 arrayPush(DOMPurify.removed, { 2526 element: node 2527 }); 2528 try {
vendor: 6,975 bytes, lines 2529-2696
2529 // eslint-disable-next-line unicorn/prefer-dom-node-remove 2530 getParentNode(node).removeChild(node); 2531 } catch (_) { 2532 remove(node); 2533 } 2534 }; 2535 /** 2536 * _removeAttribute 2537 * 2538 * @param name an Attribute name 2539 * @param element a DOM node 2540 */ 2541 const _removeAttribute = function _removeAttribute(name, element) { 2542 try { 2543 arrayPush(DOMPurify.removed, { 2544 attribute: element.getAttributeNode(name), 2545 from: element 2546 }); 2547 } catch (_) { 2548 arrayPush(DOMPurify.removed, { 2549 attribute: null, 2550 from: element 2551 }); 2552 } 2553 element.removeAttribute(name); 2554 // We void attribute values for unremovable "is" attributes 2555 if (name === 'is') { 2556 if (RETURN_DOM || RETURN_DOM_FRAGMENT) { 2557 try { 2558 _forceRemove(element); 2559 } catch (_) {} 2560 } else { 2561 try { 2562 element.setAttribute(name, ''); 2563 } catch (_) {} 2564 } 2565 } 2566 }; 2567 /** 2568 * _initDocument 2569 * 2570 * @param dirty - a string of dirty markup 2571 * @return a DOM, filled with the dirty markup 2572 */ 2573 const _initDocument = function _initDocument(dirty) { 2574 /* Create a HTML document */ 2575 let doc = null; 2576 let leadingWhitespace = null; 2577 if (FORCE_BODY) { 2578 dirty = '<remove></remove>' + dirty; 2579 } else { 2580 /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */ 2581 const matches = stringMatch(dirty, /^[\r\n\t ]+/); 2582 leadingWhitespace = matches && matches[0]; 2583 } 2584 if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) { 2585 // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict) 2586 dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>'; 2587 } 2588 const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty; 2589 /* 2590 * Use the DOMParser API by default, fallback later if needs be 2591 * DOMParser not work for svg when has multiple root element. 2592 */ 2593 if (NAMESPACE === HTML_NAMESPACE) { 2594 try { 2595 doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE); 2596 } catch (_) {} 2597 } 2598 /* Use createHTMLDocument in case DOMParser is not available */ 2599 if (!doc || !doc.documentElement) { 2600 doc = implementation.createDocument(NAMESPACE, 'template', null); 2601 try { 2602 doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload; 2603 } catch (_) { 2604 // Syntax error if dirtyPayload is invalid xml 2605 } 2606 } 2607 const body = doc.body || doc.documentElement; 2608 if (dirty && leadingWhitespace) { 2609 body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null); 2610 } 2611 /* Work on whole document or just its body */ 2612 if (NAMESPACE === HTML_NAMESPACE) { 2613 return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0]; 2614 } 2615 return WHOLE_DOCUMENT ? doc.documentElement : body; 2616 }; 2617 /** 2618 * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document. 2619 * 2620 * @param root The root element or node to start traversing on. 2621 * @return The created NodeIterator 2622 */ 2623 const _createNodeIterator = function _createNodeIterator(root) { 2624 return createNodeIterator.call(root.ownerDocument || root, root, 2625 // eslint-disable-next-line no-bitwise 2626 NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null); 2627 }; 2628 /** 2629 * _isClobbered 2630 * 2631 * @param element element to check for clobbering attacks 2632 * @return true if clobbered, false if safe 2633 */ 2634 const _isClobbered = function _isClobbered(element) { 2635 return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function'); 2636 }; 2637 /** 2638 * Checks whether the given object is a DOM node. 2639 * 2640 * @param value object to check whether it's a DOM node 2641 * @return true is object is a DOM node 2642 */ 2643 const _isNode = function _isNode(value) { 2644 return typeof Node === 'function' && value instanceof Node; 2645 }; 2646 function _executeHooks(hooks, currentNode, data) { 2647 arrayForEach(hooks, hook => { 2648 hook.call(DOMPurify, currentNode, data, CONFIG); 2649 }); 2650 } 2651 /** 2652 * _sanitizeElements 2653 * 2654 * @protect nodeName 2655 * @protect textContent 2656 * @protect removeChild 2657 * @param currentNode to check for permission to exist 2658 * @return true if node was killed, false if left alive 2659 */ 2660 const _sanitizeElements = function _sanitizeElements(currentNode) { 2661 let content = null; 2662 /* Execute a hook if present */ 2663 _executeHooks(hooks.beforeSanitizeElements, currentNode, null); 2664 /* Check if element is clobbered or can clobber */ 2665 if (_isClobbered(currentNode)) { 2666 _forceRemove(currentNode); 2667 return true; 2668 } 2669 /* Now let's check the element's type and name */ 2670 const tagName = transformCaseFunc(currentNode.nodeName); 2671 /* Execute a hook if present */ 2672 _executeHooks(hooks.uponSanitizeElement, currentNode, { 2673 tagName, 2674 allowedTags: ALLOWED_TAGS 2675 }); 2676 /* Detect mXSS attempts abusing namespace confusion */ 2677 if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) { 2678 _forceRemove(currentNode); 2679 return true; 2680 } 2681 /* Remove any occurrence of processing instructions */ 2682 if (currentNode.nodeType === NODE_TYPE.progressingInstruction) { 2683 _forceRemove(currentNode); 2684 return true; 2685 } 2686 /* Remove any kind of possibly harmful comments */ 2687 if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) { 2688 _forceRemove(currentNode); 2689 return true; 2690 } 2691 /* Remove element if anything forbids its presence */ 2692 if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) { 2693 /* Check if we have a custom element to handle */ 2694 if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) { 2695 if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) { 2696 return false;
vendor: 4,720 bytes, lines 2697-2773
2697 } 2698 if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) { 2699 return false; 2700 } 2701 } 2702 /* Keep content except for bad-listed elements */ 2703 if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) { 2704 const parentNode = getParentNode(currentNode) || currentNode.parentNode; 2705 const childNodes = getChildNodes(currentNode) || currentNode.childNodes; 2706 if (childNodes && parentNode) { 2707 const childCount = childNodes.length; 2708 for (let i = childCount - 1; i >= 0; --i) { 2709 const childClone = cloneNode(childNodes[i], true); 2710 childClone.__removalCount = (currentNode.__removalCount || 0) + 1; 2711 parentNode.insertBefore(childClone, getNextSibling(currentNode)); 2712 } 2713 } 2714 } 2715 _forceRemove(currentNode); 2716 return true; 2717 } 2718 /* Check whether element has a valid namespace */ 2719 if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) { 2720 _forceRemove(currentNode); 2721 return true; 2722 } 2723 /* Make sure that older browsers don't get fallback-tag mXSS */ 2724 if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) { 2725 _forceRemove(currentNode); 2726 return true; 2727 } 2728 /* Sanitize element content to be template-safe */ 2729 if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) { 2730 /* Get the element's text content */ 2731 content = currentNode.textContent; 2732 arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => { 2733 content = stringReplace(content, expr, ' '); 2734 }); 2735 if (currentNode.textContent !== content) { 2736 arrayPush(DOMPurify.removed, { 2737 element: currentNode.cloneNode() 2738 }); 2739 currentNode.textContent = content; 2740 } 2741 } 2742 /* Execute a hook if present */ 2743 _executeHooks(hooks.afterSanitizeElements, currentNode, null); 2744 return false; 2745 }; 2746 /** 2747 * _isValidAttribute 2748 * 2749 * @param lcTag Lowercase tag name of containing element. 2750 * @param lcName Lowercase attribute name. 2751 * @param value Attribute value. 2752 * @return Returns true if `value` is valid, otherwise false. 2753 */ 2754 // eslint-disable-next-line complexity 2755 const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) { 2756 /* Make sure attribute cannot clobber */ 2757 if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) { 2758 return false; 2759 } 2760 /* Allow valid data-* attributes: At least one character after "-" 2761 (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes) 2762 XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804) 2763 We don't need to check the value; it's always URI safe. */ 2764 if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ;else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ;else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) { 2765 if ( 2766 // First condition does a very basic check if a) it's basically a valid custom element tagname AND 2767 // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck 2768 // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck 2769 _isBasicCustomElement(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, lcTag)) || 2770 // Alternative, second condition checks if it's an `is`-attribute, AND 2771 // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck 2772 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))) ;else { 2773 return false;
vendor: 10,972 bytes, lines 2774-3044
2774 } 2775 /* Check value is safe. First, is attr inert? If so, is safe */ 2776 } else if (URI_SAFE_ATTRIBUTES[lcName]) ;else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ;else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ;else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ;else if (value) { 2777 return false; 2778 } else ; 2779 return true; 2780 }; 2781 /** 2782 * _isBasicCustomElement 2783 * checks if at least one dash is included in tagName, and it's not the first char 2784 * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name 2785 * 2786 * @param tagName name of the tag of the node to sanitize 2787 * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false. 2788 */ 2789 const _isBasicCustomElement = function _isBasicCustomElement(tagName) { 2790 return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT); 2791 }; 2792 /** 2793 * _sanitizeAttributes 2794 * 2795 * @protect attributes 2796 * @protect nodeName 2797 * @protect removeAttribute 2798 * @protect setAttribute 2799 * 2800 * @param currentNode to sanitize 2801 */ 2802 const _sanitizeAttributes = function _sanitizeAttributes(currentNode) { 2803 /* Execute a hook if present */ 2804 _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null); 2805 const { 2806 attributes 2807 } = currentNode; 2808 /* Check if we have attributes; if not we might have a text node */ 2809 if (!attributes || _isClobbered(currentNode)) { 2810 return; 2811 } 2812 const hookEvent = { 2813 attrName: '', 2814 attrValue: '', 2815 keepAttr: true, 2816 allowedAttributes: ALLOWED_ATTR, 2817 forceKeepAttr: undefined 2818 }; 2819 let l = attributes.length; 2820 /* Go backwards over all attributes; safely remove bad ones */ 2821 while (l--) { 2822 const attr = attributes[l]; 2823 const { 2824 name, 2825 namespaceURI, 2826 value: attrValue 2827 } = attr; 2828 const lcName = transformCaseFunc(name); 2829 const initValue = attrValue; 2830 let value = name === 'value' ? initValue : stringTrim(initValue); 2831 /* Execute a hook if present */ 2832 hookEvent.attrName = lcName; 2833 hookEvent.attrValue = value; 2834 hookEvent.keepAttr = true; 2835 hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set 2836 _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent); 2837 value = hookEvent.attrValue; 2838 /* Full DOM Clobbering protection via namespace isolation, 2839 * Prefix id and name attributes with `user-content-` 2840 */ 2841 if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) { 2842 // Remove the attribute with this value 2843 _removeAttribute(name, currentNode); 2844 // Prefix the value and later re-create the attribute with the sanitized value 2845 value = SANITIZE_NAMED_PROPS_PREFIX + value; 2846 } 2847 /* Work around a security issue with comments inside attributes */ 2848 if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title|textarea)/i, value)) { 2849 _removeAttribute(name, currentNode); 2850 continue; 2851 } 2852 /* Make sure we cannot easily use animated hrefs, even if animations are allowed */ 2853 if (lcName === 'attributename' && stringMatch(value, 'href')) { 2854 _removeAttribute(name, currentNode); 2855 continue; 2856 } 2857 /* Did the hooks approve of the attribute? */ 2858 if (hookEvent.forceKeepAttr) { 2859 continue; 2860 } 2861 /* Did the hooks approve of the attribute? */ 2862 if (!hookEvent.keepAttr) { 2863 _removeAttribute(name, currentNode); 2864 continue; 2865 } 2866 /* Work around a security issue in jQuery 3.0 */ 2867 if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) { 2868 _removeAttribute(name, currentNode); 2869 continue; 2870 } 2871 /* Sanitize attribute content to be template-safe */ 2872 if (SAFE_FOR_TEMPLATES) { 2873 arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => { 2874 value = stringReplace(value, expr, ' '); 2875 }); 2876 } 2877 /* Is `value` valid for this attribute? */ 2878 const lcTag = transformCaseFunc(currentNode.nodeName); 2879 if (!_isValidAttribute(lcTag, lcName, value)) { 2880 _removeAttribute(name, currentNode); 2881 continue; 2882 } 2883 /* Handle attributes that require Trusted Types */ 2884 if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') { 2885 if (namespaceURI) ;else { 2886 switch (trustedTypes.getAttributeType(lcTag, lcName)) { 2887 case 'TrustedHTML': 2888 { 2889 value = trustedTypesPolicy.createHTML(value); 2890 break; 2891 } 2892 case 'TrustedScriptURL': 2893 { 2894 value = trustedTypesPolicy.createScriptURL(value); 2895 break; 2896 } 2897 } 2898 } 2899 } 2900 /* Handle invalid data-* attribute set by try-catching it */ 2901 if (value !== initValue) { 2902 try { 2903 if (namespaceURI) { 2904 currentNode.setAttributeNS(namespaceURI, name, value); 2905 } else { 2906 /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */ 2907 currentNode.setAttribute(name, value); 2908 } 2909 if (_isClobbered(currentNode)) { 2910 _forceRemove(currentNode); 2911 } else { 2912 arrayPop(DOMPurify.removed); 2913 } 2914 } catch (_) { 2915 _removeAttribute(name, currentNode); 2916 } 2917 } 2918 } 2919 /* Execute a hook if present */ 2920 _executeHooks(hooks.afterSanitizeAttributes, currentNode, null); 2921 }; 2922 /** 2923 * _sanitizeShadowDOM 2924 * 2925 * @param fragment to iterate over recursively 2926 */ 2927 const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) { 2928 let shadowNode = null; 2929 const shadowIterator = _createNodeIterator(fragment); 2930 /* Execute a hook if present */ 2931 _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null); 2932 while (shadowNode = shadowIterator.nextNode()) { 2933 /* Execute a hook if present */ 2934 _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null); 2935 /* Sanitize tags and elements */ 2936 _sanitizeElements(shadowNode); 2937 /* Check attributes next */ 2938 _sanitizeAttributes(shadowNode); 2939 /* Deep shadow DOM detected */ 2940 if (shadowNode.content instanceof DocumentFragment) { 2941 _sanitizeShadowDOM(shadowNode.content); 2942 } 2943 } 2944 /* Execute a hook if present */ 2945 _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null); 2946 }; 2947 // eslint-disable-next-line complexity 2948 DOMPurify.sanitize = function (dirty) { 2949 let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 2950 let body = null; 2951 let importedNode = null; 2952 let currentNode = null; 2953 let returnNode = null; 2954 /* Make sure we have a string to sanitize. 2955 DO NOT return early, as this will return the wrong type if 2956 the user has requested a DOM object rather than a string */ 2957 IS_EMPTY_INPUT = !dirty; 2958 if (IS_EMPTY_INPUT) { 2959 dirty = '<!-->'; 2960 } 2961 /* Stringify, in case dirty is an object */ 2962 if (typeof dirty !== 'string' && !_isNode(dirty)) { 2963 if (typeof dirty.toString === 'function') { 2964 dirty = dirty.toString(); 2965 if (typeof dirty !== 'string') { 2966 throw typeErrorCreate('dirty is not a string, aborting'); 2967 } 2968 } else { 2969 throw typeErrorCreate('toString is not a function'); 2970 } 2971 } 2972 /* Return dirty HTML if DOMPurify cannot run */ 2973 if (!DOMPurify.isSupported) { 2974 return dirty; 2975 } 2976 /* Assign config vars */ 2977 if (!SET_CONFIG) { 2978 _parseConfig(cfg); 2979 } 2980 /* Clean up removed elements */ 2981 DOMPurify.removed = []; 2982 /* Check if dirty is correctly typed for IN_PLACE */ 2983 if (typeof dirty === 'string') { 2984 IN_PLACE = false; 2985 } 2986 if (IN_PLACE) { 2987 /* Do some early pre-sanitization to avoid unsafe root nodes */ 2988 if (dirty.nodeName) { 2989 const tagName = transformCaseFunc(dirty.nodeName); 2990 if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) { 2991 throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place'); 2992 } 2993 } 2994 } else if (dirty instanceof Node) { 2995 /* If dirty is a DOM element, append to an empty document to avoid 2996 elements being stripped by the parser */ 2997 body = _initDocument('<!---->'); 2998 importedNode = body.ownerDocument.importNode(dirty, true); 2999 if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') { 3000 /* Node is already a body, use as is */ 3001 body = importedNode; 3002 } else if (importedNode.nodeName === 'HTML') { 3003 body = importedNode; 3004 } else { 3005 // eslint-disable-next-line unicorn/prefer-dom-node-append 3006 body.appendChild(importedNode); 3007 } 3008 } else { 3009 /* Exit directly if we have nothing to do */ 3010 if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && 3011 // eslint-disable-next-line unicorn/prefer-includes 3012 dirty.indexOf('<') === -1) { 3013 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty; 3014 } 3015 /* Initialize the document to work on */ 3016 body = _initDocument(dirty); 3017 /* Check we have a DOM node from the data */ 3018 if (!body) { 3019 return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : ''; 3020 } 3021 } 3022 /* Remove first element node (ours) if FORCE_BODY is set */ 3023 if (body && FORCE_BODY) { 3024 _forceRemove(body.firstChild); 3025 } 3026 /* Get node iterator */ 3027 const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body); 3028 /* Now start iterating over the created document */ 3029 while (currentNode = nodeIterator.nextNode()) { 3030 /* Sanitize tags and elements */ 3031 _sanitizeElements(currentNode); 3032 /* Check attributes next */ 3033 _sanitizeAttributes(currentNode); 3034 /* Shadow DOM detected, sanitize it */ 3035 if (currentNode.content instanceof DocumentFragment) { 3036 _sanitizeShadowDOM(currentNode.content); 3037 } 3038 } 3039 /* If we sanitized `dirty` in-place, return it. */ 3040 if (IN_PLACE) { 3041 return dirty; 3042 } 3043 /* Return sanitized string or DOM */ 3044 if (RETURN_DOM) {
vendor: 398,676 bytes, lines 3044-13886
3044 3045 if (RETURN_DOM_FRAGMENT) { 3046 returnNode = createDocumentFragment.call(body.ownerDocument); 3047 while (body.firstChild) { 3048 // eslint-disable-next-line unicorn/prefer-dom-node-append 3049 returnNode.appendChild(body.firstChild); 3050 } 3051 } else { 3052 returnNode = body; 3053 } 3054 if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) { 3055 /* 3056 AdoptNode() is not used because internal state is not reset 3057 (e.g. the past names map of a HTMLFormElement), this is safe 3058 in theory but we would rather not risk another attack vector. 3059 The state that is cloned by importNode() is explicitly defined 3060 by the specs. 3061 */ 3062 returnNode = importNode.call(originalDocument, returnNode, true); 3063 } 3064 return returnNode; 3065 } 3066 let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML; 3067 /* Serialize doctype if allowed */ 3068 if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) { 3069 serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML; 3070 } 3071 /* Sanitize final string template-safe */ 3072 if (SAFE_FOR_TEMPLATES) { 3073 arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => { 3074 serializedHTML = stringReplace(serializedHTML, expr, ' '); 3075 }); 3076 } 3077 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML; 3078 }; 3079 DOMPurify.setConfig = function () { 3080 let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 3081 _parseConfig(cfg); 3082 SET_CONFIG = true; 3083 }; 3084 DOMPurify.clearConfig = function () { 3085 CONFIG = null; 3086 SET_CONFIG = false; 3087 }; 3088 DOMPurify.isValidAttribute = function (tag, attr, value) { 3089 /* Initialize shared config vars if necessary. */ 3090 if (!CONFIG) { 3091 _parseConfig({}); 3092 } 3093 const lcTag = transformCaseFunc(tag); 3094 const lcName = transformCaseFunc(attr); 3095 return _isValidAttribute(lcTag, lcName, value); 3096 }; 3097 DOMPurify.addHook = function (entryPoint, hookFunction) { 3098 if (typeof hookFunction !== 'function') { 3099 return; 3100 } 3101 arrayPush(hooks[entryPoint], hookFunction); 3102 }; 3103 DOMPurify.removeHook = function (entryPoint, hookFunction) { 3104 if (hookFunction !== undefined) { 3105 const index = arrayLastIndexOf(hooks[entryPoint], hookFunction); 3106 return index === -1 ? undefined : arraySplice(hooks[entryPoint], index, 1)[0]; 3107 } 3108 return arrayPop(hooks[entryPoint]); 3109 }; 3110 DOMPurify.removeHooks = function (entryPoint) { 3111 hooks[entryPoint] = []; 3112 }; 3113 DOMPurify.removeAllHooks = function () { 3114 hooks = _createHooksMap(); 3115 }; 3116 return DOMPurify; 3117 } 3118 var purify = createDOMPurify(); 3119 3120 purify.addHook("uponSanitizeAttribute", function (node, data) { 3121 if (data.attrName === "data-trix-serialized-attributes") { 3122 data.keepAttr = false; 3123 return; 3124 } 3125 const allowedAttributePattern = /^data-trix-/; 3126 if (allowedAttributePattern.test(data.attrName)) { 3127 data.forceKeepAttr = true; 3128 } 3129 }); 3130 const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height language class".split(" "); 3131 const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" "); 3132 const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form noscript".split(" "); 3133 class HTMLSanitizer extends BasicObject { 3134 static setHTML(element, html, options) { 3135 const sanitizedElement = new this(html, options).sanitize(); 3136 const sanitizedHtml = sanitizedElement.getHTML ? sanitizedElement.getHTML() : sanitizedElement.outerHTML; 3137 element.innerHTML = sanitizedHtml; 3138 } 3139 static sanitize(html, options) { 3140 const sanitizer = new this(html, options); 3141 sanitizer.sanitize(); 3142 return sanitizer; 3143 } 3144 constructor(html) { 3145 let { 3146 allowedAttributes, 3147 forbiddenProtocols, 3148 forbiddenElements, 3149 purifyOptions 3150 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 3151 super(...arguments); 3152 this.allowedAttributes = allowedAttributes || DEFAULT_ALLOWED_ATTRIBUTES; 3153 this.forbiddenProtocols = forbiddenProtocols || DEFAULT_FORBIDDEN_PROTOCOLS; 3154 this.forbiddenElements = forbiddenElements || DEFAULT_FORBIDDEN_ELEMENTS; 3155 this.purifyOptions = purifyOptions || {}; 3156 this.body = createBodyElementForHTML(html); 3157 } 3158 sanitize() { 3159 this.sanitizeElements(); 3160 this.normalizeListElementNesting(); 3161 const purifyConfig = Object.assign({}, dompurify, this.purifyOptions); 3162 purify.setConfig(purifyConfig); 3163 this.body = purify.sanitize(this.body); 3164 return this.body; 3165 } 3166 getHTML() { 3167 return this.body.innerHTML; 3168 } 3169 getBody() { 3170 return this.body; 3171 } 3172 3173 // Private 3174 3175 sanitizeElements() { 3176 const walker = walkTree(this.body); 3177 const nodesToRemove = []; 3178 while (walker.nextNode()) { 3179 const node = walker.currentNode; 3180 switch (node.nodeType) { 3181 case Node.ELEMENT_NODE: 3182 if (this.elementIsRemovable(node)) { 3183 nodesToRemove.push(node); 3184 } else { 3185 this.sanitizeElement(node); 3186 } 3187 break; 3188 case Node.COMMENT_NODE: 3189 nodesToRemove.push(node); 3190 break; 3191 } 3192 } 3193 nodesToRemove.forEach(node => removeNode(node)); 3194 return this.body; 3195 } 3196 sanitizeElement(element) { 3197 if (element.hasAttribute("href")) { 3198 if (this.forbiddenProtocols.includes(element.protocol)) { 3199 element.removeAttribute("href"); 3200 } 3201 } 3202 Array.from(element.attributes).forEach(_ref => { 3203 let { 3204 name 3205 } = _ref; 3206 if (!this.allowedAttributes.includes(name) && name.indexOf("data-trix") !== 0) { 3207 element.removeAttribute(name); 3208 } 3209 }); 3210 return element; 3211 } 3212 normalizeListElementNesting() { 3213 Array.from(this.body.querySelectorAll("ul,ol")).forEach(listElement => { 3214 const previousElement = listElement.previousElementSibling; 3215 if (previousElement) { 3216 if (tagName(previousElement) === "li") { 3217 previousElement.appendChild(listElement); 3218 } 3219 } 3220 }); 3221 return this.body; 3222 } 3223 elementIsRemovable(element) { 3224 if ((element === null || element === void 0 ? void 0 : element.nodeType) !== Node.ELEMENT_NODE) return; 3225 return this.elementIsForbidden(element) || this.elementIsntSerializable(element); 3226 } 3227 elementIsForbidden(element) { 3228 return this.forbiddenElements.includes(tagName(element)); 3229 } 3230 elementIsntSerializable(element) { 3231 return element.getAttribute("data-trix-serialize") === "false" && !nodeIsAttachmentElement(element); 3232 } 3233 } 3234 const createBodyElementForHTML = function () { 3235 let html = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; 3236 // Remove everything after </html> 3237 html = html.replace(/<\/html[^>]*>[^]*$/i, "</html>"); 3238 const doc = document.implementation.createHTMLDocument(""); 3239 doc.documentElement.innerHTML = html; 3240 Array.from(doc.head.querySelectorAll("style")).forEach(element => { 3241 doc.body.appendChild(element); 3242 }); 3243 return doc.body; 3244 }; 3245 3246 const { 3247 css: css$2 3248 } = config; 3249 class AttachmentView extends ObjectView { 3250 constructor() { 3251 super(...arguments); 3252 this.attachment = this.object; 3253 this.attachment.uploadProgressDelegate = this; 3254 this.attachmentPiece = this.options.piece; 3255 } 3256 createContentNodes() { 3257 return []; 3258 } 3259 createNodes() { 3260 let innerElement; 3261 const figure = innerElement = makeElement({ 3262 tagName: "figure", 3263 className: this.getClassName(), 3264 data: this.getData(), 3265 editable: false 3266 }); 3267 const href = this.getHref(); 3268 if (href) { 3269 innerElement = makeElement({ 3270 tagName: "a", 3271 editable: false, 3272 attributes: { 3273 href, 3274 tabindex: -1 3275 } 3276 }); 3277 figure.appendChild(innerElement); 3278 } 3279 if (this.attachment.hasContent()) { 3280 HTMLSanitizer.setHTML(innerElement, this.attachment.getContent()); 3281 } else { 3282 this.createContentNodes().forEach(node => { 3283 innerElement.appendChild(node); 3284 }); 3285 } 3286 innerElement.appendChild(this.createCaptionElement()); 3287 if (this.attachment.isPending()) { 3288 this.progressElement = makeElement({ 3289 tagName: "progress", 3290 attributes: { 3291 class: css$2.attachmentProgress, 3292 value: this.attachment.getUploadProgress(), 3293 max: 100 3294 }, 3295 data: { 3296 trixMutable: true, 3297 trixStoreKey: ["progressElement", this.attachment.id].join("/") 3298 } 3299 }); 3300 figure.appendChild(this.progressElement); 3301 } 3302 return [createCursorTarget("left"), figure, createCursorTarget("right")]; 3303 } 3304 createCaptionElement() { 3305 const figcaption = makeElement({ 3306 tagName: "figcaption", 3307 className: css$2.attachmentCaption 3308 }); 3309 const caption = this.attachmentPiece.getCaption(); 3310 if (caption) { 3311 figcaption.classList.add("".concat(css$2.attachmentCaption, "--edited")); 3312 figcaption.textContent = caption; 3313 } else { 3314 let name, size; 3315 const captionConfig = this.getCaptionConfig(); 3316 if (captionConfig.name) { 3317 name = this.attachment.getFilename(); 3318 } 3319 if (captionConfig.size) { 3320 size = this.attachment.getFormattedFilesize(); 3321 } 3322 if (name) { 3323 const nameElement = makeElement({ 3324 tagName: "span", 3325 className: css$2.attachmentName, 3326 textContent: name 3327 }); 3328 figcaption.appendChild(nameElement); 3329 } 3330 if (size) { 3331 if (name) { 3332 figcaption.appendChild(document.createTextNode(" ")); 3333 } 3334 const sizeElement = makeElement({ 3335 tagName: "span", 3336 className: css$2.attachmentSize, 3337 textContent: size 3338 }); 3339 figcaption.appendChild(sizeElement); 3340 } 3341 } 3342 return figcaption; 3343 } 3344 getClassName() { 3345 const names = [css$2.attachment, "".concat(css$2.attachment, "--").concat(this.attachment.getType())]; 3346 const extension = this.attachment.getExtension(); 3347 if (extension) { 3348 names.push("".concat(css$2.attachment, "--").concat(extension)); 3349 } 3350 return names.join(" "); 3351 } 3352 getData() { 3353 const data = { 3354 trixAttachment: JSON.stringify(this.attachment), 3355 trixContentType: this.attachment.getContentType(), 3356 trixId: this.attachment.id 3357 }; 3358 const { 3359 attributes 3360 } = this.attachmentPiece; 3361 if (!attributes.isEmpty()) { 3362 data.trixAttributes = JSON.stringify(attributes); 3363 } 3364 if (this.attachment.isPending()) { 3365 data.trixSerialize = false; 3366 } 3367 return data; 3368 } 3369 getHref() { 3370 if (!htmlContainsTagName(this.attachment.getContent(), "a")) { 3371 const href = this.attachment.getHref(); 3372 if (href && purify.isValidAttribute("a", "href", href)) { 3373 return href; 3374 } 3375 } 3376 } 3377 getCaptionConfig() { 3378 var _config$attachments$t; 3379 const type = this.attachment.getType(); 3380 const captionConfig = copyObject((_config$attachments$t = attachments[type]) === null || _config$attachments$t === void 0 ? void 0 : _config$attachments$t.caption); 3381 if (type === "file") { 3382 captionConfig.name = true; 3383 } 3384 return captionConfig; 3385 } 3386 findProgressElement() { 3387 var _this$findElement; 3388 return (_this$findElement = this.findElement()) === null || _this$findElement === void 0 ? void 0 : _this$findElement.querySelector("progress"); 3389 } 3390 3391 // Attachment delegate 3392 3393 attachmentDidChangeUploadProgress() { 3394 const value = this.attachment.getUploadProgress(); 3395 const progressElement = this.findProgressElement(); 3396 if (progressElement) { 3397 progressElement.value = value; 3398 } 3399 } 3400 } 3401 const createCursorTarget = name => makeElement({ 3402 tagName: "span", 3403 textContent: ZERO_WIDTH_SPACE, 3404 data: { 3405 trixCursorTarget: name, 3406 trixSerialize: false 3407 } 3408 }); 3409 const htmlContainsTagName = function (html, tagName) { 3410 const div = makeElement("div"); 3411 HTMLSanitizer.setHTML(div, html || ""); 3412 return div.querySelector(tagName); 3413 }; 3414 3415 class PreviewableAttachmentView extends AttachmentView { 3416 constructor() { 3417 super(...arguments); 3418 this.attachment.previewDelegate = this; 3419 } 3420 createContentNodes() { 3421 this.image = makeElement({ 3422 tagName: "img", 3423 attributes: { 3424 src: "" 3425 }, 3426 data: { 3427 trixMutable: true 3428 } 3429 }); 3430 this.refresh(this.image); 3431 return [this.image]; 3432 } 3433 createCaptionElement() { 3434 const figcaption = super.createCaptionElement(...arguments); 3435 if (!figcaption.textContent) { 3436 figcaption.setAttribute("data-trix-placeholder", lang$1.captionPlaceholder); 3437 } 3438 return figcaption; 3439 } 3440 refresh(image) { 3441 if (!image) { 3442 var _this$findElement; 3443 image = (_this$findElement = this.findElement()) === null || _this$findElement === void 0 ? void 0 : _this$findElement.querySelector("img"); 3444 } 3445 if (image) { 3446 return this.updateAttributesForImage(image); 3447 } 3448 } 3449 updateAttributesForImage(image) { 3450 const url = this.attachment.getURL(); 3451 const previewURL = this.attachment.getPreviewURL(); 3452 image.src = previewURL || url; 3453 if (previewURL === url) { 3454 image.removeAttribute("data-trix-serialized-attributes"); 3455 } else { 3456 const serializedAttributes = JSON.stringify({ 3457 src: url 3458 }); 3459 image.setAttribute("data-trix-serialized-attributes", serializedAttributes); 3460 } 3461 const width = this.attachment.getWidth(); 3462 const height = this.attachment.getHeight(); 3463 const alt = this.attachment.getAttribute("alt"); 3464 if (width != null) { 3465 image.width = width; 3466 } 3467 if (height != null) { 3468 image.height = height; 3469 } 3470 if (alt != null) { 3471 image.alt = alt; 3472 } 3473 const storeKey = ["imageElement", this.attachment.id, image.src, image.width, image.height].join("/"); 3474 image.dataset.trixStoreKey = storeKey; 3475 } 3476 3477 // Attachment delegate 3478 3479 attachmentDidChangeAttributes() { 3480 this.refresh(this.image); 3481 return this.refresh(); 3482 } 3483 } 3484 3485 /* eslint-disable 3486 no-useless-escape, 3487 no-var, 3488 */ 3489 class PieceView extends ObjectView { 3490 constructor() { 3491 super(...arguments); 3492 this.piece = this.object; 3493 this.attributes = this.piece.getAttributes(); 3494 this.textConfig = this.options.textConfig; 3495 this.context = this.options.context; 3496 if (this.piece.attachment) { 3497 this.attachment = this.piece.attachment; 3498 } else { 3499 this.string = this.piece.toString(); 3500 } 3501 } 3502 createNodes() { 3503 let nodes = this.attachment ? this.createAttachmentNodes() : this.createStringNodes(); 3504 const element = this.createElement(); 3505 if (element) { 3506 const innerElement = findInnerElement(element); 3507 Array.from(nodes).forEach(node => { 3508 innerElement.appendChild(node); 3509 }); 3510 nodes = [element]; 3511 } 3512 return nodes; 3513 } 3514 createAttachmentNodes() { 3515 const constructor = this.attachment.isPreviewable() ? PreviewableAttachmentView : AttachmentView; 3516 const view = this.createChildView(constructor, this.piece.attachment, { 3517 piece: this.piece 3518 }); 3519 return view.getNodes(); 3520 } 3521 createStringNodes() { 3522 var _this$textConfig; 3523 if ((_this$textConfig = this.textConfig) !== null && _this$textConfig !== void 0 && _this$textConfig.plaintext) { 3524 return [document.createTextNode(this.string)]; 3525 } else { 3526 const nodes = []; 3527 const iterable = this.string.split("\n"); 3528 for (let index = 0; index < iterable.length; index++) { 3529 const substring = iterable[index]; 3530 if (index > 0) { 3531 const element = makeElement("br"); 3532 nodes.push(element); 3533 } 3534 if (substring.length) { 3535 const node = document.createTextNode(this.preserveSpaces(substring)); 3536 nodes.push(node); 3537 } 3538 } 3539 return nodes; 3540 } 3541 } 3542 createElement() { 3543 let element, key, value; 3544 const styles = {}; 3545 for (key in this.attributes) { 3546 value = this.attributes[key]; 3547 const config = getTextConfig(key); 3548 if (config) { 3549 if (config.tagName) { 3550 var innerElement; 3551 const pendingElement = makeElement(config.tagName); 3552 if (innerElement) { 3553 innerElement.appendChild(pendingElement); 3554 innerElement = pendingElement; 3555 } else { 3556 element = innerElement = pendingElement; 3557 } 3558 } 3559 if (config.styleProperty) { 3560 styles[config.styleProperty] = value; 3561 } 3562 if (config.style) { 3563 for (key in config.style) { 3564 value = config.style[key]; 3565 styles[key] = value; 3566 } 3567 } 3568 } 3569 } 3570 if (Object.keys(styles).length) { 3571 if (!element) { 3572 element = makeElement("span"); 3573 } 3574 for (key in styles) { 3575 value = styles[key]; 3576 element.style[key] = value; 3577 } 3578 } 3579 return element; 3580 } 3581 createContainerElement() { 3582 for (const key in this.attributes) { 3583 const value = this.attributes[key]; 3584 const config = getTextConfig(key); 3585 if (config) { 3586 if (config.groupTagName) { 3587 const attributes = {}; 3588 attributes[key] = value; 3589 return makeElement(config.groupTagName, attributes); 3590 } 3591 } 3592 } 3593 } 3594 preserveSpaces(string) { 3595 if (this.context.isLast) { 3596 string = string.replace(/\ $/, NON_BREAKING_SPACE); 3597 } 3598 string = string.replace(/(\S)\ {3}(\S)/g, "$1 ".concat(NON_BREAKING_SPACE, " $2")).replace(/\ {2}/g, "".concat(NON_BREAKING_SPACE, " ")).replace(/\ {2}/g, " ".concat(NON_BREAKING_SPACE)); 3599 if (this.context.isFirst || this.context.followsWhitespace) { 3600 string = string.replace(/^\ /, NON_BREAKING_SPACE); 3601 } 3602 return string; 3603 } 3604 } 3605 3606 /* eslint-disable 3607 no-var, 3608 */ 3609 class TextView extends ObjectView { 3610 constructor() { 3611 super(...arguments); 3612 this.text = this.object; 3613 this.textConfig = this.options.textConfig; 3614 } 3615 createNodes() { 3616 const nodes = []; 3617 const pieces = ObjectGroup.groupObjects(this.getPieces()); 3618 const lastIndex = pieces.length - 1; 3619 for (let index = 0; index < pieces.length; index++) { 3620 const piece = pieces[index]; 3621 const context = {}; 3622 if (index === 0) { 3623 context.isFirst = true; 3624 } 3625 if (index === lastIndex) { 3626 context.isLast = true; 3627 } 3628 if (endsWithWhitespace(previousPiece)) { 3629 context.followsWhitespace = true; 3630 } 3631 const view = this.findOrCreateCachedChildView(PieceView, piece, { 3632 textConfig: this.textConfig, 3633 context 3634 }); 3635 nodes.push(...Array.from(view.getNodes() || [])); 3636 var previousPiece = piece; 3637 } 3638 return nodes; 3639 } 3640 getPieces() { 3641 return Array.from(this.text.getPieces()).filter(piece => !piece.hasAttribute("blockBreak")); 3642 } 3643 } 3644 const endsWithWhitespace = piece => /\s$/.test(piece === null || piece === void 0 ? void 0 : piece.toString()); 3645 3646 const { 3647 css: css$1 3648 } = config; 3649 class BlockView extends ObjectView { 3650 constructor() { 3651 super(...arguments); 3652 this.block = this.object; 3653 this.attributes = this.block.getAttributes(); 3654 } 3655 createNodes() { 3656 const comment = document.createComment("block"); 3657 const nodes = [comment]; 3658 if (this.block.isEmpty()) { 3659 nodes.push(makeElement("br")); 3660 } else { 3661 var _getBlockConfig; 3662 const textConfig = (_getBlockConfig = getBlockConfig(this.block.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.text; 3663 const textView = this.findOrCreateCachedChildView(TextView, this.block.text, { 3664 textConfig 3665 }); 3666 nodes.push(...Array.from(textView.getNodes() || [])); 3667 if (this.shouldAddExtraNewlineElement()) { 3668 nodes.push(makeElement("br")); 3669 } 3670 } 3671 if (this.attributes.length) { 3672 return nodes; 3673 } else { 3674 let attributes$1; 3675 const { 3676 tagName 3677 } = attributes.default; 3678 if (this.block.isRTL()) { 3679 attributes$1 = { 3680 dir: "rtl" 3681 }; 3682 } 3683 const element = makeElement({ 3684 tagName, 3685 attributes: attributes$1 3686 }); 3687 nodes.forEach(node => element.appendChild(node)); 3688 return [element]; 3689 } 3690 } 3691 createContainerElement(depth) { 3692 const attributes = {}; 3693 let className; 3694 const attributeName = this.attributes[depth]; 3695 const { 3696 tagName, 3697 htmlAttributes = [] 3698 } = getBlockConfig(attributeName); 3699 if (depth === 0 && this.block.isRTL()) { 3700 Object.assign(attributes, { 3701 dir: "rtl" 3702 }); 3703 } 3704 if (attributeName === "attachmentGallery") { 3705 const size = this.block.getBlockBreakPosition(); 3706 className = "".concat(css$1.attachmentGallery, " ").concat(css$1.attachmentGallery, "--").concat(size); 3707 } 3708 Object.entries(this.block.htmlAttributes).forEach(_ref => { 3709 let [name, value] = _ref; 3710 if (htmlAttributes.includes(name)) { 3711 attributes[name] = value; 3712 } 3713 }); 3714 return makeElement({ 3715 tagName, 3716 className, 3717 attributes 3718 }); 3719 } 3720 3721 // A single <br> at the end of a block element has no visual representation 3722 // so add an extra one. 3723 shouldAddExtraNewlineElement() { 3724 return /\n\n$/.test(this.block.toString()); 3725 } 3726 } 3727 3728 class DocumentView extends ObjectView { 3729 static render(document) { 3730 const element = makeElement("div"); 3731 const view = new this(document, { 3732 element 3733 }); 3734 view.render(); 3735 view.sync(); 3736 return element; 3737 } 3738 constructor() { 3739 super(...arguments); 3740 this.element = this.options.element; 3741 this.elementStore = new ElementStore(); 3742 this.setDocument(this.object); 3743 } 3744 setDocument(document) { 3745 if (!document.isEqualTo(this.document)) { 3746 this.document = this.object = document; 3747 } 3748 } 3749 render() { 3750 this.childViews = []; 3751 this.shadowElement = makeElement("div"); 3752 if (!this.document.isEmpty()) { 3753 const objects = ObjectGroup.groupObjects(this.document.getBlocks(), { 3754 asTree: true 3755 }); 3756 Array.from(objects).forEach(object => { 3757 const view = this.findOrCreateCachedChildView(BlockView, object); 3758 Array.from(view.getNodes()).map(node => this.shadowElement.appendChild(node)); 3759 }); 3760 } 3761 } 3762 isSynced() { 3763 return elementsHaveEqualHTML(this.shadowElement, this.element); 3764 } 3765 sync() { 3766 const render = (element, documentFragment) => { 3767 while (element.lastChild) { 3768 element.removeChild(element.lastChild); 3769 } 3770 element.appendChild(documentFragment); 3771 }; 3772 const event = createEvent("trix-before-render", { 3773 cancelable: false, 3774 attributes: { 3775 render 3776 } 3777 }); 3778 this.element.dispatchEvent(event); 3779 const fragment = this.createDocumentFragmentForSync(); 3780 event.render(this.element, fragment); 3781 return this.didSync(); 3782 } 3783 3784 // Private 3785 3786 didSync() { 3787 this.elementStore.reset(findStoredElements(this.element)); 3788 return defer(() => this.garbageCollectCachedViews()); 3789 } 3790 createDocumentFragmentForSync() { 3791 const fragment = document.createDocumentFragment(); 3792 Array.from(this.shadowElement.childNodes).forEach(node => { 3793 fragment.appendChild(node.cloneNode(true)); 3794 }); 3795 Array.from(findStoredElements(fragment)).forEach(element => { 3796 const storedElement = this.elementStore.remove(element); 3797 if (storedElement) { 3798 element.parentNode.replaceChild(storedElement, element); 3799 } 3800 }); 3801 return fragment; 3802 } 3803 } 3804 const findStoredElements = element => element.querySelectorAll("[data-trix-store-key]"); 3805 const elementsHaveEqualHTML = (element, otherElement) => ignoreSpaces(element.innerHTML) === ignoreSpaces(otherElement.innerHTML); 3806 const ignoreSpaces = html => html.replace(/ /g, " "); 3807 3808 function _AsyncGenerator(e) { 3809 var r, t; 3810 function resume(r, t) { 3811 try { 3812 var n = e[r](t), 3813 o = n.value, 3814 u = o instanceof _OverloadYield; 3815 Promise.resolve(u ? o.v : o).then(function (t) { 3816 if (u) { 3817 var i = "return" === r ? "return" : "next"; 3818 if (!o.k || t.done) return resume(i, t); 3819 t = e[i](t).value; 3820 } 3821 settle(n.done ? "return" : "normal", t); 3822 }, function (e) { 3823 resume("throw", e); 3824 }); 3825 } catch (e) { 3826 settle("throw", e); 3827 } 3828 } 3829 function settle(e, n) { 3830 switch (e) { 3831 case "return": 3832 r.resolve({ 3833 value: n, 3834 done: !0 3835 }); 3836 break; 3837 case "throw": 3838 r.reject(n); 3839 break; 3840 default: 3841 r.resolve({ 3842 value: n, 3843 done: !1 3844 }); 3845 } 3846 (r = r.next) ? resume(r.key, r.arg) : t = null; 3847 } 3848 this._invoke = function (e, n) { 3849 return new Promise(function (o, u) { 3850 var i = { 3851 key: e, 3852 arg: n, 3853 resolve: o, 3854 reject: u, 3855 next: null 3856 }; 3857 t ? t = t.next = i : (r = t = i, resume(e, n)); 3858 }); 3859 }, "function" != typeof e.return && (this.return = void 0); 3860 } 3861 _AsyncGenerator.prototype["function" == typeof Symbol && Symbol.asyncIterator || "@@asyncIterator"] = function () { 3862 return this; 3863 }, _AsyncGenerator.prototype.next = function (e) { 3864 return this._invoke("next", e); 3865 }, _AsyncGenerator.prototype.throw = function (e) { 3866 return this._invoke("throw", e); 3867 }, _AsyncGenerator.prototype.return = function (e) { 3868 return this._invoke("return", e); 3869 }; 3870 function _OverloadYield(t, e) { 3871 this.v = t, this.k = e; 3872 } 3873 function old_createMetadataMethodsForProperty(e, t, a, r) { 3874 return { 3875 getMetadata: function (o) { 3876 old_assertNotFinished(r, "getMetadata"), old_assertMetadataKey(o); 3877 var i = e[o]; 3878 if (void 0 !== i) if (1 === t) { 3879 var n = i.public; 3880 if (void 0 !== n) return n[a]; 3881 } else if (2 === t) { 3882 var l = i.private; 3883 if (void 0 !== l) return l.get(a); 3884 } else if (Object.hasOwnProperty.call(i, "constructor")) return i.constructor; 3885 }, 3886 setMetadata: function (o, i) { 3887 old_assertNotFinished(r, "setMetadata"), old_assertMetadataKey(o); 3888 var n = e[o]; 3889 if (void 0 === n && (n = e[o] = {}), 1 === t) { 3890 var l = n.public; 3891 void 0 === l && (l = n.public = {}), l[a] = i; 3892 } else if (2 === t) { 3893 var s = n.priv; 3894 void 0 === s && (s = n.private = new Map()), s.set(a, i); 3895 } else n.constructor = i; 3896 } 3897 }; 3898 } 3899 function old_convertMetadataMapToFinal(e, t) { 3900 var a = e[Symbol.metadata || Symbol.for("Symbol.metadata")], 3901 r = Object.getOwnPropertySymbols(t); 3902 if (0 !== r.length) { 3903 for (var o = 0; o < r.length; o++) { 3904 var i = r[o], 3905 n = t[i], 3906 l = a ? a[i] : null, 3907 s = n.public, 3908 c = l ? l.public : null; 3909 s && c && Object.setPrototypeOf(s, c); 3910 var d = n.private; 3911 if (d) { 3912 var u = Array.from(d.values()), 3913 f = l ? l.private : null; 3914 f && (u = u.concat(f)), n.private = u; 3915 } 3916 l && Object.setPrototypeOf(n, l); 3917 } 3918 a && Object.setPrototypeOf(t, a), e[Symbol.metadata || Symbol.for("Symbol.metadata")] = t; 3919 } 3920 } 3921 function old_createAddInitializerMethod(e, t) { 3922 return function (a) { 3923 old_assertNotFinished(t, "addInitializer"), old_assertCallable(a, "An initializer"), e.push(a); 3924 }; 3925 } 3926 function old_memberDec(e, t, a, r, o, i, n, l, s) { 3927 var c; 3928 switch (i) { 3929 case 1: 3930 c = "accessor"; 3931 break; 3932 case 2: 3933 c = "method"; 3934 break; 3935 case 3: 3936 c = "getter"; 3937 break; 3938 case 4: 3939 c = "setter"; 3940 break; 3941 default: 3942 c = "field"; 3943 } 3944 var d, 3945 u, 3946 f = { 3947 kind: c, 3948 name: l ? "#" + t : _toPropertyKey(t), 3949 isStatic: n, 3950 isPrivate: l 3951 }, 3952 p = { 3953 v: !1 3954 }; 3955 if (0 !== i && (f.addInitializer = old_createAddInitializerMethod(o, p)), l) { 3956 d = 2, u = Symbol(t); 3957 var v = {}; 3958 0 === i ? (v.get = a.get, v.set = a.set) : 2 === i ? v.get = function () { 3959 return a.value; 3960 } : (1 !== i && 3 !== i || (v.get = function () { 3961 return a.get.call(this); 3962 }), 1 !== i && 4 !== i || (v.set = function (e) { 3963 a.set.call(this, e); 3964 })), f.access = v; 3965 } else d = 1, u = t; 3966 try { 3967 return e(s, Object.assign(f, old_createMetadataMethodsForProperty(r, d, u, p))); 3968 } finally { 3969 p.v = !0; 3970 } 3971 } 3972 function old_assertNotFinished(e, t) { 3973 if (e.v) throw new Error("attempted to call " + t + " after decoration was finished"); 3974 } 3975 function old_assertMetadataKey(e) { 3976 if ("symbol" != typeof e) throw new TypeError("Metadata keys must be symbols, received: " + e); 3977 } 3978 function old_assertCallable(e, t) { 3979 if ("function" != typeof e) throw new TypeError(t + " must be a function"); 3980 } 3981 function old_assertValidReturnValue(e, t) { 3982 var a = typeof t; 3983 if (1 === e) { 3984 if ("object" !== a || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); 3985 void 0 !== t.get && old_assertCallable(t.get, "accessor.get"), void 0 !== t.set && old_assertCallable(t.set, "accessor.set"), void 0 !== t.init && old_assertCallable(t.init, "accessor.init"), void 0 !== t.initializer && old_assertCallable(t.initializer, "accessor.initializer"); 3986 } else if ("function" !== a) throw new TypeError((0 === e ? "field" : 10 === e ? "class" : "method") + " decorators must return a function or void 0"); 3987 } 3988 function old_getInit(e) { 3989 var t; 3990 return null == (t = e.init) && (t = e.initializer) && "undefined" != typeof console && console.warn(".initializer has been renamed to .init as of March 2022"), t; 3991 } 3992 function old_applyMemberDec(e, t, a, r, o, i, n, l, s) { 3993 var c, 3994 d, 3995 u, 3996 f, 3997 p, 3998 v, 3999 y, 4000 h = a[0]; 4001 if (n ? (0 === o || 1 === o ? (c = { 4002 get: a[3], 4003 set: a[4] 4004 }, u = "get") : 3 === o ? (c = { 4005 get: a[3] 4006 }, u = "get") : 4 === o ? (c = { 4007 set: a[3] 4008 }, u = "set") : c = { 4009 value: a[3] 4010 }, 0 !== o && (1 === o && _setFunctionName(a[4], "#" + r, "set"), _setFunctionName(a[3], "#" + r, u))) : 0 !== o && (c = Object.getOwnPropertyDescriptor(t, r)), 1 === o ? f = { 4011 get: c.get, 4012 set: c.set 4013 } : 2 === o ? f = c.value : 3 === o ? f = c.get : 4 === o && (f = c.set), "function" == typeof h) void 0 !== (p = old_memberDec(h, r, c, l, s, o, i, n, f)) && (old_assertValidReturnValue(o, p), 0 === o ? d = p : 1 === o ? (d = old_getInit(p), v = p.get || f.get, y = p.set || f.set, f = { 4014 get: v, 4015 set: y 4016 }) : f = p);else for (var m = h.length - 1; m >= 0; m--) { 4017 var b; 4018 void 0 !== (p = old_memberDec(h[m], r, c, l, s, o, i, n, f)) && (old_assertValidReturnValue(o, p), 0 === o ? b = p : 1 === o ? (b = old_getInit(p), v = p.get || f.get, y = p.set || f.set, f = { 4019 get: v, 4020 set: y 4021 }) : f = p, void 0 !== b && (void 0 === d ? d = b : "function" == typeof d ? d = [d, b] : d.push(b))); 4022 } 4023 if (0 === o || 1 === o) { 4024 if (void 0 === d) d = function (e, t) { 4025 return t; 4026 };else if ("function" != typeof d) { 4027 var g = d; 4028 d = function (e, t) { 4029 for (var a = t, r = 0; r < g.length; r++) a = g[r].call(e, a); 4030 return a; 4031 }; 4032 } else { 4033 var _ = d; 4034 d = function (e, t) { 4035 return _.call(e, t); 4036 }; 4037 } 4038 e.push(d); 4039 } 4040 0 !== o && (1 === o ? (c.get = f.get, c.set = f.set) : 2 === o ? c.value = f : 3 === o ? c.get = f : 4 === o && (c.set = f), n ? 1 === o ? (e.push(function (e, t) { 4041 return f.get.call(e, t); 4042 }), e.push(function (e, t) { 4043 return f.set.call(e, t); 4044 })) : 2 === o ? e.push(f) : e.push(function (e, t) { 4045 return f.call(e, t); 4046 }) : Object.defineProperty(t, r, c)); 4047 } 4048 function old_applyMemberDecs(e, t, a, r, o) { 4049 for (var i, n, l = new Map(), s = new Map(), c = 0; c < o.length; c++) { 4050 var d = o[c]; 4051 if (Array.isArray(d)) { 4052 var u, 4053 f, 4054 p, 4055 v = d[1], 4056 y = d[2], 4057 h = d.length > 3, 4058 m = v >= 5; 4059 if (m ? (u = t, f = r, 0 != (v -= 5) && (p = n = n || [])) : (u = t.prototype, f = a, 0 !== v && (p = i = i || [])), 0 !== v && !h) { 4060 var b = m ? s : l, 4061 g = b.get(y) || 0; 4062 if (!0 === g || 3 === g && 4 !== v || 4 === g && 3 !== v) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + y); 4063 !g && v > 2 ? b.set(y, v) : b.set(y, !0); 4064 } 4065 old_applyMemberDec(e, u, d, y, v, m, h, f, p); 4066 } 4067 } 4068 old_pushInitializers(e, i), old_pushInitializers(e, n); 4069 } 4070 function old_pushInitializers(e, t) { 4071 t && e.push(function (e) { 4072 for (var a = 0; a < t.length; a++) t[a].call(e); 4073 return e; 4074 }); 4075 } 4076 function old_applyClassDecs(e, t, a, r) { 4077 if (r.length > 0) { 4078 for (var o = [], i = t, n = t.name, l = r.length - 1; l >= 0; l--) { 4079 var s = { 4080 v: !1 4081 }; 4082 try { 4083 var c = Object.assign({ 4084 kind: "class", 4085 name: n, 4086 addInitializer: old_createAddInitializerMethod(o, s) 4087 }, old_createMetadataMethodsForProperty(a, 0, n, s)), 4088 d = r[l](i, c); 4089 } finally { 4090 s.v = !0; 4091 } 4092 void 0 !== d && (old_assertValidReturnValue(10, d), i = d); 4093 } 4094 e.push(i, function () { 4095 for (var e = 0; e < o.length; e++) o[e].call(i); 4096 }); 4097 } 4098 } 4099 function _applyDecs(e, t, a) { 4100 var r = [], 4101 o = {}, 4102 i = {}; 4103 return old_applyMemberDecs(r, e, i, o, t), old_convertMetadataMapToFinal(e.prototype, i), old_applyClassDecs(r, e, o, a), old_convertMetadataMapToFinal(e, o), r; 4104 } 4105 function applyDecs2203Factory() { 4106 function createAddInitializerMethod(e, t) { 4107 return function (r) { 4108 !function (e, t) { 4109 if (e.v) throw new Error("attempted to call addInitializer after decoration was finished"); 4110 }(t), assertCallable(r, "An initializer"), e.push(r); 4111 }; 4112 } 4113 function memberDec(e, t, r, a, n, i, s, o) { 4114 var c; 4115 switch (n) { 4116 case 1: 4117 c = "accessor"; 4118 break; 4119 case 2: 4120 c = "method"; 4121 break; 4122 case 3: 4123 c = "getter"; 4124 break; 4125 case 4: 4126 c = "setter"; 4127 break; 4128 default: 4129 c = "field"; 4130 } 4131 var l, 4132 u, 4133 f = { 4134 kind: c, 4135 name: s ? "#" + t : t, 4136 static: i, 4137 private: s 4138 }, 4139 p = { 4140 v: !1 4141 }; 4142 0 !== n && (f.addInitializer = createAddInitializerMethod(a, p)), 0 === n ? s ? (l = r.get, u = r.set) : (l = function () { 4143 return this[t]; 4144 }, u = function (e) { 4145 this[t] = e; 4146 }) : 2 === n ? l = function () { 4147 return r.value; 4148 } : (1 !== n && 3 !== n || (l = function () { 4149 return r.get.call(this); 4150 }), 1 !== n && 4 !== n || (u = function (e) { 4151 r.set.call(this, e); 4152 })), f.access = l && u ? { 4153 get: l, 4154 set: u 4155 } : l ? { 4156 get: l 4157 } : { 4158 set: u 4159 }; 4160 try { 4161 return e(o, f); 4162 } finally { 4163 p.v = !0; 4164 } 4165 } 4166 function assertCallable(e, t) { 4167 if ("function" != typeof e) throw new TypeError(t + " must be a function"); 4168 } 4169 function assertValidReturnValue(e, t) { 4170 var r = typeof t; 4171 if (1 === e) { 4172 if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); 4173 void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init"); 4174 } else if ("function" !== r) throw new TypeError((0 === e ? "field" : 10 === e ? "class" : "method") + " decorators must return a function or void 0"); 4175 } 4176 function applyMemberDec(e, t, r, a, n, i, s, o) { 4177 var c, 4178 l, 4179 u, 4180 f, 4181 p, 4182 d, 4183 h = r[0]; 4184 if (s ? c = 0 === n || 1 === n ? { 4185 get: r[3], 4186 set: r[4] 4187 } : 3 === n ? { 4188 get: r[3] 4189 } : 4 === n ? { 4190 set: r[3] 4191 } : { 4192 value: r[3] 4193 } : 0 !== n && (c = Object.getOwnPropertyDescriptor(t, a)), 1 === n ? u = { 4194 get: c.get, 4195 set: c.set 4196 } : 2 === n ? u = c.value : 3 === n ? u = c.get : 4 === n && (u = c.set), "function" == typeof h) void 0 !== (f = memberDec(h, a, c, o, n, i, s, u)) && (assertValidReturnValue(n, f), 0 === n ? l = f : 1 === n ? (l = f.init, p = f.get || u.get, d = f.set || u.set, u = { 4197 get: p, 4198 set: d 4199 }) : u = f);else for (var v = h.length - 1; v >= 0; v--) { 4200 var g; 4201 void 0 !== (f = memberDec(h[v], a, c, o, n, i, s, u)) && (assertValidReturnValue(n, f), 0 === n ? g = f : 1 === n ? (g = f.init, p = f.get || u.get, d = f.set || u.set, u = { 4202 get: p, 4203 set: d 4204 }) : u = f, void 0 !== g && (void 0 === l ? l = g : "function" == typeof l ? l = [l, g] : l.push(g))); 4205 } 4206 if (0 === n || 1 === n) { 4207 if (void 0 === l) l = function (e, t) { 4208 return t; 4209 };else if ("function" != typeof l) { 4210 var y = l; 4211 l = function (e, t) { 4212 for (var r = t, a = 0; a < y.length; a++) r = y[a].call(e, r); 4213 return r; 4214 }; 4215 } else { 4216 var m = l; 4217 l = function (e, t) { 4218 return m.call(e, t); 4219 }; 4220 } 4221 e.push(l); 4222 } 4223 0 !== n && (1 === n ? (c.get = u.get, c.set = u.set) : 2 === n ? c.value = u : 3 === n ? c.get = u : 4 === n && (c.set = u), s ? 1 === n ? (e.push(function (e, t) { 4224 return u.get.call(e, t); 4225 }), e.push(function (e, t) { 4226 return u.set.call(e, t); 4227 })) : 2 === n ? e.push(u) : e.push(function (e, t) { 4228 return u.call(e, t); 4229 }) : Object.defineProperty(t, a, c)); 4230 } 4231 function pushInitializers(e, t) { 4232 t && e.push(function (e) { 4233 for (var r = 0; r < t.length; r++) t[r].call(e); 4234 return e; 4235 }); 4236 } 4237 return function (e, t, r) { 4238 var a = []; 4239 return function (e, t, r) { 4240 for (var a, n, i = new Map(), s = new Map(), o = 0; o < r.length; o++) { 4241 var c = r[o]; 4242 if (Array.isArray(c)) { 4243 var l, 4244 u, 4245 f = c[1], 4246 p = c[2], 4247 d = c.length > 3, 4248 h = f >= 5; 4249 if (h ? (l = t, 0 != (f -= 5) && (u = n = n || [])) : (l = t.prototype, 0 !== f && (u = a = a || [])), 0 !== f && !d) { 4250 var v = h ? s : i, 4251 g = v.get(p) || 0; 4252 if (!0 === g || 3 === g && 4 !== f || 4 === g && 3 !== f) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + p); 4253 !g && f > 2 ? v.set(p, f) : v.set(p, !0); 4254 } 4255 applyMemberDec(e, l, c, p, f, h, d, u); 4256 } 4257 } 4258 pushInitializers(e, a), pushInitializers(e, n); 4259 }(a, e, t), function (e, t, r) { 4260 if (r.length > 0) { 4261 for (var a = [], n = t, i = t.name, s = r.length - 1; s >= 0; s--) { 4262 var o = { 4263 v: !1 4264 }; 4265 try { 4266 var c = r[s](n, { 4267 kind: "class", 4268 name: i, 4269 addInitializer: createAddInitializerMethod(a, o) 4270 }); 4271 } finally { 4272 o.v = !0; 4273 } 4274 void 0 !== c && (assertValidReturnValue(10, c), n = c); 4275 } 4276 e.push(n, function () { 4277 for (var e = 0; e < a.length; e++) a[e].call(n); 4278 }); 4279 } 4280 }(a, e, r), a; 4281 }; 4282 } 4283 var applyDecs2203Impl; 4284 function _applyDecs2203(e, t, r) { 4285 return (applyDecs2203Impl = applyDecs2203Impl || applyDecs2203Factory())(e, t, r); 4286 } 4287 function applyDecs2203RFactory() { 4288 function createAddInitializerMethod(e, t) { 4289 return function (r) { 4290 !function (e, t) { 4291 if (e.v) throw new Error("attempted to call addInitializer after decoration was finished"); 4292 }(t), assertCallable(r, "An initializer"), e.push(r); 4293 }; 4294 } 4295 function memberDec(e, t, r, n, a, i, o, s) { 4296 var c; 4297 switch (a) { 4298 case 1: 4299 c = "accessor"; 4300 break; 4301 case 2: 4302 c = "method"; 4303 break; 4304 case 3: 4305 c = "getter"; 4306 break; 4307 case 4: 4308 c = "setter"; 4309 break; 4310 default: 4311 c = "field"; 4312 } 4313 var l, 4314 u, 4315 f = { 4316 kind: c, 4317 name: o ? "#" + t : _toPropertyKey(t), 4318 static: i, 4319 private: o 4320 }, 4321 p = { 4322 v: !1 4323 }; 4324 0 !== a && (f.addInitializer = createAddInitializerMethod(n, p)), 0 === a ? o ? (l = r.get, u = r.set) : (l = function () { 4325 return this[t]; 4326 }, u = function (e) { 4327 this[t] = e; 4328 }) : 2 === a ? l = function () { 4329 return r.value; 4330 } : (1 !== a && 3 !== a || (l = function () { 4331 return r.get.call(this); 4332 }), 1 !== a && 4 !== a || (u = function (e) { 4333 r.set.call(this, e); 4334 })), f.access = l && u ? { 4335 get: l, 4336 set: u 4337 } : l ? { 4338 get: l 4339 } : { 4340 set: u 4341 }; 4342 try { 4343 return e(s, f); 4344 } finally { 4345 p.v = !0; 4346 } 4347 } 4348 function assertCallable(e, t) { 4349 if ("function" != typeof e) throw new TypeError(t + " must be a function"); 4350 } 4351 function assertValidReturnValue(e, t) { 4352 var r = typeof t; 4353 if (1 === e) { 4354 if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); 4355 void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init"); 4356 } else if ("function" !== r) throw new TypeError((0 === e ? "field" : 10 === e ? "class" : "method") + " decorators must return a function or void 0"); 4357 } 4358 function applyMemberDec(e, t, r, n, a, i, o, s) { 4359 var c, 4360 l, 4361 u, 4362 f, 4363 p, 4364 d, 4365 h, 4366 v = r[0]; 4367 if (o ? (0 === a || 1 === a ? (c = { 4368 get: r[3], 4369 set: r[4] 4370 }, u = "get") : 3 === a ? (c = { 4371 get: r[3] 4372 }, u = "get") : 4 === a ? (c = { 4373 set: r[3] 4374 }, u = "set") : c = { 4375 value: r[3] 4376 }, 0 !== a && (1 === a && _setFunctionName(r[4], "#" + n, "set"), _setFunctionName(r[3], "#" + n, u))) : 0 !== a && (c = Object.getOwnPropertyDescriptor(t, n)), 1 === a ? f = { 4377 get: c.get, 4378 set: c.set 4379 } : 2 === a ? f = c.value : 3 === a ? f = c.get : 4 === a && (f = c.set), "function" == typeof v) void 0 !== (p = memberDec(v, n, c, s, a, i, o, f)) && (assertValidReturnValue(a, p), 0 === a ? l = p : 1 === a ? (l = p.init, d = p.get || f.get, h = p.set || f.set, f = { 4380 get: d, 4381 set: h 4382 }) : f = p);else for (var g = v.length - 1; g >= 0; g--) { 4383 var y; 4384 void 0 !== (p = memberDec(v[g], n, c, s, a, i, o, f)) && (assertValidReturnValue(a, p), 0 === a ? y = p : 1 === a ? (y = p.init, d = p.get || f.get, h = p.set || f.set, f = { 4385 get: d, 4386 set: h 4387 }) : f = p, void 0 !== y && (void 0 === l ? l = y : "function" == typeof l ? l = [l, y] : l.push(y))); 4388 } 4389 if (0 === a || 1 === a) { 4390 if (void 0 === l) l = function (e, t) { 4391 return t; 4392 };else if ("function" != typeof l) { 4393 var m = l; 4394 l = function (e, t) { 4395 for (var r = t, n = 0; n < m.length; n++) r = m[n].call(e, r); 4396 return r; 4397 }; 4398 } else { 4399 var b = l; 4400 l = function (e, t) { 4401 return b.call(e, t); 4402 }; 4403 } 4404 e.push(l); 4405 } 4406 0 !== a && (1 === a ? (c.get = f.get, c.set = f.set) : 2 === a ? c.value = f : 3 === a ? c.get = f : 4 === a && (c.set = f), o ? 1 === a ? (e.push(function (e, t) { 4407 return f.get.call(e, t); 4408 }), e.push(function (e, t) { 4409 return f.set.call(e, t); 4410 })) : 2 === a ? e.push(f) : e.push(function (e, t) { 4411 return f.call(e, t); 4412 }) : Object.defineProperty(t, n, c)); 4413 } 4414 function applyMemberDecs(e, t) { 4415 for (var r, n, a = [], i = new Map(), o = new Map(), s = 0; s < t.length; s++) { 4416 var c = t[s]; 4417 if (Array.isArray(c)) { 4418 var l, 4419 u, 4420 f = c[1], 4421 p = c[2], 4422 d = c.length > 3, 4423 h = f >= 5; 4424 if (h ? (l = e, 0 != (f -= 5) && (u = n = n || [])) : (l = e.prototype, 0 !== f && (u = r = r || [])), 0 !== f && !d) { 4425 var v = h ? o : i, 4426 g = v.get(p) || 0; 4427 if (!0 === g || 3 === g && 4 !== f || 4 === g && 3 !== f) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + p); 4428 !g && f > 2 ? v.set(p, f) : v.set(p, !0); 4429 } 4430 applyMemberDec(a, l, c, p, f, h, d, u); 4431 } 4432 } 4433 return pushInitializers(a, r), pushInitializers(a, n), a; 4434 } 4435 function pushInitializers(e, t) { 4436 t && e.push(function (e) { 4437 for (var r = 0; r < t.length; r++) t[r].call(e); 4438 return e; 4439 }); 4440 } 4441 return function (e, t, r) { 4442 return { 4443 e: applyMemberDecs(e, t), 4444 get c() { 4445 return function (e, t) { 4446 if (t.length > 0) { 4447 for (var r = [], n = e, a = e.name, i = t.length - 1; i >= 0; i--) { 4448 var o = { 4449 v: !1 4450 }; 4451 try { 4452 var s = t[i](n, { 4453 kind: "class", 4454 name: a, 4455 addInitializer: createAddInitializerMethod(r, o) 4456 }); 4457 } finally { 4458 o.v = !0; 4459 } 4460 void 0 !== s && (assertValidReturnValue(10, s), n = s); 4461 } 4462 return [n, function () { 4463 for (var e = 0; e < r.length; e++) r[e].call(n); 4464 }]; 4465 } 4466 }(e, r); 4467 } 4468 }; 4469 }; 4470 } 4471 function _applyDecs2203R(e, t, r) { 4472 return (_applyDecs2203R = applyDecs2203RFactory())(e, t, r); 4473 } 4474 function applyDecs2301Factory() { 4475 function createAddInitializerMethod(e, t) { 4476 return function (r) { 4477 !function (e, t) { 4478 if (e.v) throw new Error("attempted to call addInitializer after decoration was finished"); 4479 }(t), assertCallable(r, "An initializer"), e.push(r); 4480 }; 4481 } 4482 function assertInstanceIfPrivate(e, t) { 4483 if (!e(t)) throw new TypeError("Attempted to access private element on non-instance"); 4484 } 4485 function memberDec(e, t, r, n, a, i, s, o, c) { 4486 var u; 4487 switch (a) { 4488 case 1: 4489 u = "accessor"; 4490 break; 4491 case 2: 4492 u = "method"; 4493 break; 4494 case 3: 4495 u = "getter"; 4496 break; 4497 case 4: 4498 u = "setter"; 4499 break; 4500 default: 4501 u = "field"; 4502 } 4503 var l, 4504 f, 4505 p = { 4506 kind: u, 4507 name: s ? "#" + t : _toPropertyKey(t), 4508 static: i, 4509 private: s 4510 }, 4511 d = { 4512 v: !1 4513 }; 4514 if (0 !== a && (p.addInitializer = createAddInitializerMethod(n, d)), s || 0 !== a && 2 !== a) { 4515 if (2 === a) l = function (e) { 4516 return assertInstanceIfPrivate(c, e), r.value; 4517 };else { 4518 var h = 0 === a || 1 === a; 4519 (h || 3 === a) && (l = s ? function (e) { 4520 return assertInstanceIfPrivate(c, e), r.get.call(e); 4521 } : function (e) { 4522 return r.get.call(e); 4523 }), (h || 4 === a) && (f = s ? function (e, t) { 4524 assertInstanceIfPrivate(c, e), r.set.call(e, t); 4525 } : function (e, t) { 4526 r.set.call(e, t); 4527 }); 4528 } 4529 } else l = function (e) { 4530 return e[t]; 4531 }, 0 === a && (f = function (e, r) { 4532 e[t] = r; 4533 }); 4534 var v = s ? c.bind() : function (e) { 4535 return t in e; 4536 }; 4537 p.access = l && f ? { 4538 get: l, 4539 set: f, 4540 has: v 4541 } : l ? { 4542 get: l, 4543 has: v 4544 } : { 4545 set: f, 4546 has: v 4547 }; 4548 try { 4549 return e(o, p); 4550 } finally { 4551 d.v = !0; 4552 } 4553 } 4554 function assertCallable(e, t) { 4555 if ("function" != typeof e) throw new TypeError(t + " must be a function"); 4556 } 4557 function assertValidReturnValue(e, t) { 4558 var r = typeof t; 4559 if (1 === e) { 4560 if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); 4561 void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init"); 4562 } else if ("function" !== r) throw new TypeError((0 === e ? "field" : 10 === e ? "class" : "method") + " decorators must return a function or void 0"); 4563 } 4564 function curryThis2(e) { 4565 return function (t) { 4566 e(this, t); 4567 }; 4568 } 4569 function applyMemberDec(e, t, r, n, a, i, s, o, c) { 4570 var u, 4571 l, 4572 f, 4573 p, 4574 d, 4575 h, 4576 v, 4577 y, 4578 g = r[0]; 4579 if (s ? (0 === a || 1 === a ? (u = { 4580 get: (d = r[3], function () { 4581 return d(this); 4582 }), 4583 set: curryThis2(r[4]) 4584 }, f = "get") : 3 === a ? (u = { 4585 get: r[3] 4586 }, f = "get") : 4 === a ? (u = { 4587 set: r[3] 4588 }, f = "set") : u = { 4589 value: r[3] 4590 }, 0 !== a && (1 === a && _setFunctionName(u.set, "#" + n, "set"), _setFunctionName(u[f || "value"], "#" + n, f))) : 0 !== a && (u = Object.getOwnPropertyDescriptor(t, n)), 1 === a ? p = { 4591 get: u.get, 4592 set: u.set 4593 } : 2 === a ? p = u.value : 3 === a ? p = u.get : 4 === a && (p = u.set), "function" == typeof g) void 0 !== (h = memberDec(g, n, u, o, a, i, s, p, c)) && (assertValidReturnValue(a, h), 0 === a ? l = h : 1 === a ? (l = h.init, v = h.get || p.get, y = h.set || p.set, p = { 4594 get: v, 4595 set: y 4596 }) : p = h);else for (var m = g.length - 1; m >= 0; m--) { 4597 var b; 4598 void 0 !== (h = memberDec(g[m], n, u, o, a, i, s, p, c)) && (assertValidReturnValue(a, h), 0 === a ? b = h : 1 === a ? (b = h.init, v = h.get || p.get, y = h.set || p.set, p = { 4599 get: v, 4600 set: y 4601 }) : p = h, void 0 !== b && (void 0 === l ? l = b : "function" == typeof l ? l = [l, b] : l.push(b))); 4602 } 4603 if (0 === a || 1 === a) { 4604 if (void 0 === l) l = function (e, t) { 4605 return t; 4606 };else if ("function" != typeof l) { 4607 var I = l; 4608 l = function (e, t) { 4609 for (var r = t, n = 0; n < I.length; n++) r = I[n].call(e, r); 4610 return r; 4611 }; 4612 } else { 4613 var w = l; 4614 l = function (e, t) { 4615 return w.call(e, t); 4616 }; 4617 } 4618 e.push(l); 4619 } 4620 0 !== a && (1 === a ? (u.get = p.get, u.set = p.set) : 2 === a ? u.value = p : 3 === a ? u.get = p : 4 === a && (u.set = p), s ? 1 === a ? (e.push(function (e, t) { 4621 return p.get.call(e, t); 4622 }), e.push(function (e, t) { 4623 return p.set.call(e, t); 4624 })) : 2 === a ? e.push(p) : e.push(function (e, t) { 4625 return p.call(e, t); 4626 }) : Object.defineProperty(t, n, u)); 4627 } 4628 function applyMemberDecs(e, t, r) { 4629 for (var n, a, i, s = [], o = new Map(), c = new Map(), u = 0; u < t.length; u++) { 4630 var l = t[u]; 4631 if (Array.isArray(l)) { 4632 var f, 4633 p, 4634 d = l[1], 4635 h = l[2], 4636 v = l.length > 3, 4637 y = d >= 5, 4638 g = r; 4639 if (y ? (f = e, 0 != (d -= 5) && (p = a = a || []), v && !i && (i = function (t) { 4640 return _checkInRHS(t) === e; 4641 }), g = i) : (f = e.prototype, 0 !== d && (p = n = n || [])), 0 !== d && !v) { 4642 var m = y ? c : o, 4643 b = m.get(h) || 0; 4644 if (!0 === b || 3 === b && 4 !== d || 4 === b && 3 !== d) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + h); 4645 !b && d > 2 ? m.set(h, d) : m.set(h, !0); 4646 } 4647 applyMemberDec(s, f, l, h, d, y, v, p, g); 4648 } 4649 } 4650 return pushInitializers(s, n), pushInitializers(s, a), s; 4651 } 4652 function pushInitializers(e, t) { 4653 t && e.push(function (e) { 4654 for (var r = 0; r < t.length; r++) t[r].call(e); 4655 return e; 4656 }); 4657 } 4658 return function (e, t, r, n) { 4659 return { 4660 e: applyMemberDecs(e, t, n), 4661 get c() { 4662 return function (e, t) { 4663 if (t.length > 0) { 4664 for (var r = [], n = e, a = e.name, i = t.length - 1; i >= 0; i--) { 4665 var s = { 4666 v: !1 4667 }; 4668 try { 4669 var o = t[i](n, { 4670 kind: "class", 4671 name: a, 4672 addInitializer: createAddInitializerMethod(r, s) 4673 }); 4674 } finally { 4675 s.v = !0; 4676 } 4677 void 0 !== o && (assertValidReturnValue(10, o), n = o); 4678 } 4679 return [n, function () { 4680 for (var e = 0; e < r.length; e++) r[e].call(n); 4681 }]; 4682 } 4683 }(e, r); 4684 } 4685 }; 4686 }; 4687 } 4688 function _applyDecs2301(e, t, r, n) { 4689 return (_applyDecs2301 = applyDecs2301Factory())(e, t, r, n); 4690 } 4691 function _applyDecs2305(e, t, r, n, o, a) { 4692 function i(e, t, r) { 4693 return function (n, o) { 4694 return r && r(n), e[t].call(n, o); 4695 }; 4696 } 4697 function c(e, t) { 4698 for (var r = 0; r < e.length; r++) e[r].call(t); 4699 return t; 4700 } 4701 function s(e, t, r, n) { 4702 if ("function" != typeof e && (n || void 0 !== e)) throw new TypeError(t + " must " + (r || "be") + " a function" + (n ? "" : " or undefined")); 4703 return e; 4704 } 4705 function applyDec(e, t, r, n, o, a, c, u, l, f, p, d, h) { 4706 function m(e) { 4707 if (!h(e)) throw new TypeError("Attempted to access private element on non-instance"); 4708 } 4709 var y, 4710 v = t[0], 4711 g = t[3], 4712 b = !u; 4713 if (!b) { 4714 r || Array.isArray(v) || (v = [v]); 4715 var w = {}, 4716 S = [], 4717 A = 3 === o ? "get" : 4 === o || d ? "set" : "value"; 4718 f ? (p || d ? w = { 4719 get: _setFunctionName(function () { 4720 return g(this); 4721 }, n, "get"), 4722 set: function (e) { 4723 t[4](this, e); 4724 } 4725 } : w[A] = g, p || _setFunctionName(w[A], n, 2 === o ? "" : A)) : p || (w = Object.getOwnPropertyDescriptor(e, n)); 4726 } 4727 for (var P = e, j = v.length - 1; j >= 0; j -= r ? 2 : 1) { 4728 var D = v[j], 4729 E = r ? v[j - 1] : void 0, 4730 I = {}, 4731 O = { 4732 kind: ["field", "accessor", "method", "getter", "setter", "class"][o], 4733 name: n, 4734 metadata: a, 4735 addInitializer: function (e, t) { 4736 if (e.v) throw new Error("attempted to call addInitializer after decoration was finished"); 4737 s(t, "An initializer", "be", !0), c.push(t); 4738 }.bind(null, I) 4739 }; 4740 try { 4741 if (b) (y = s(D.call(E, P, O), "class decorators", "return")) && (P = y);else { 4742 var k, F; 4743 O.static = l, O.private = f, f ? 2 === o ? k = function (e) { 4744 return m(e), w.value; 4745 } : (o < 4 && (k = i(w, "get", m)), 3 !== o && (F = i(w, "set", m))) : (k = function (e) { 4746 return e[n]; 4747 }, (o < 2 || 4 === o) && (F = function (e, t) { 4748 e[n] = t; 4749 })); 4750 var N = O.access = { 4751 has: f ? h.bind() : function (e) { 4752 return n in e; 4753 } 4754 }; 4755 if (k && (N.get = k), F && (N.set = F), P = D.call(E, d ? { 4756 get: w.get, 4757 set: w.set 4758 } : w[A], O), d) { 4759 if ("object" == typeof P && P) (y = s(P.get, "accessor.get")) && (w.get = y), (y = s(P.set, "accessor.set")) && (w.set = y), (y = s(P.init, "accessor.init")) && S.push(y);else if (void 0 !== P) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); 4760 } else s(P, (p ? "field" : "method") + " decorators", "return") && (p ? S.push(P) : w[A] = P); 4761 } 4762 } finally { 4763 I.v = !0; 4764 } 4765 } 4766 return (p || d) && u.push(function (e, t) { 4767 for (var r = S.length - 1; r >= 0; r--) t = S[r].call(e, t); 4768 return t; 4769 }), p || b || (f ? d ? u.push(i(w, "get"), i(w, "set")) : u.push(2 === o ? w[A] : i.call.bind(w[A])) : Object.defineProperty(e, n, w)), P; 4770 } 4771 function u(e, t) { 4772 return Object.defineProperty(e, Symbol.metadata || Symbol.for("Symbol.metadata"), { 4773 configurable: !0, 4774 enumerable: !0, 4775 value: t 4776 }); 4777 } 4778 if (arguments.length >= 6) var l = a[Symbol.metadata || Symbol.for("Symbol.metadata")]; 4779 var f = Object.create(null == l ? null : l), 4780 p = function (e, t, r, n) { 4781 var o, 4782 a, 4783 i = [], 4784 s = function (t) { 4785 return _checkInRHS(t) === e; 4786 }, 4787 u = new Map(); 4788 function l(e) { 4789 e && i.push(c.bind(null, e)); 4790 } 4791 for (var f = 0; f < t.length; f++) { 4792 var p = t[f]; 4793 if (Array.isArray(p)) { 4794 var d = p[1], 4795 h = p[2], 4796 m = p.length > 3, 4797 y = 16 & d, 4798 v = !!(8 & d), 4799 g = 0 == (d &= 7), 4800 b = h + "/" + v; 4801 if (!g && !m) { 4802 var w = u.get(b); 4803 if (!0 === w || 3 === w && 4 !== d || 4 === w && 3 !== d) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + h); 4804 u.set(b, !(d > 2) || d); 4805 } 4806 applyDec(v ? e : e.prototype, p, y, m ? "#" + h : _toPropertyKey(h), d, n, v ? a = a || [] : o = o || [], i, v, m, g, 1 === d, v && m ? s : r); 4807 } 4808 } 4809 return l(o), l(a), i; 4810 }(e, t, o, f); 4811 return r.length || u(e, f), { 4812 e: p, 4813 get c() { 4814 var t = []; 4815 return r.length && [u(applyDec(e, [r], n, e.name, 5, f, t), f), c.bind(null, t, e)]; 4816 } 4817 }; 4818 } 4819 function _asyncGeneratorDelegate(t) { 4820 var e = {}, 4821 n = !1; 4822 function pump(e, r) { 4823 return n = !0, r = new Promise(function (n) { 4824 n(t[e](r)); 4825 }), { 4826 done: !1, 4827 value: new _OverloadYield(r, 1) 4828 }; 4829 } 4830 return e["undefined" != typeof Symbol && Symbol.iterator || "@@iterator"] = function () { 4831 return this; 4832 }, e.next = function (t) { 4833 return n ? (n = !1, t) : pump("next", t); 4834 }, "function" == typeof t.throw && (e.throw = function (t) { 4835 if (n) throw n = !1, t; 4836 return pump("throw", t); 4837 }), "function" == typeof t.return && (e.return = function (t) { 4838 return n ? (n = !1, t) : pump("return", t); 4839 }), e; 4840 } 4841 function _asyncIterator(r) { 4842 var n, 4843 t, 4844 o, 4845 e = 2; 4846 for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) { 4847 if (t && null != (n = r[t])) return n.call(r); 4848 if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r)); 4849 t = "@@asyncIterator", o = "@@iterator"; 4850 } 4851 throw new TypeError("Object is not async iterable"); 4852 } 4853 function AsyncFromSyncIterator(r) { 4854 function AsyncFromSyncIteratorContinuation(r) { 4855 if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object.")); 4856 var n = r.done; 4857 return Promise.resolve(r.value).then(function (r) { 4858 return { 4859 value: r, 4860 done: n 4861 }; 4862 }); 4863 } 4864 return AsyncFromSyncIterator = function (r) { 4865 this.s = r, this.n = r.next; 4866 }, AsyncFromSyncIterator.prototype = { 4867 s: null, 4868 n: null, 4869 next: function () { 4870 return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); 4871 }, 4872 return: function (r) { 4873 var n = this.s.return; 4874 return void 0 === n ? Promise.resolve({ 4875 value: r, 4876 done: !0 4877 }) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); 4878 }, 4879 throw: function (r) { 4880 var n = this.s.return; 4881 return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); 4882 } 4883 }, new AsyncFromSyncIterator(r); 4884 } 4885 function _awaitAsyncGenerator(e) { 4886 return new _OverloadYield(e, 0); 4887 } 4888 function _callSuper(t, o, e) { 4889 return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); 4890 } 4891 function _checkInRHS(e) { 4892 if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); 4893 return e; 4894 } 4895 function _construct(t, e, r) { 4896 if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments); 4897 var o = [null]; 4898 o.push.apply(o, e); 4899 var p = new (t.bind.apply(t, o))(); 4900 return r && _setPrototypeOf(p, r.prototype), p; 4901 } 4902 function _defineAccessor(e, r, n, t) { 4903 var c = { 4904 configurable: !0, 4905 enumerable: !0 4906 }; 4907 return c[e] = t, Object.defineProperty(r, n, c); 4908 } 4909 function dispose_SuppressedError(r, e) { 4910 return "undefined" != typeof SuppressedError ? dispose_SuppressedError = SuppressedError : (dispose_SuppressedError = function (r, e) { 4911 this.suppressed = e, this.error = r, this.stack = new Error().stack; 4912 }, dispose_SuppressedError.prototype = Object.create(Error.prototype, { 4913 constructor: { 4914 value: dispose_SuppressedError, 4915 writable: !0, 4916 configurable: !0 4917 } 4918 })), new dispose_SuppressedError(r, e); 4919 } 4920 function _dispose(r, e, s) { 4921 function next() { 4922 for (; r.length > 0;) try { 4923 var o = r.pop(), 4924 p = o.d.call(o.v); 4925 if (o.a) return Promise.resolve(p).then(next, err); 4926 } catch (r) { 4927 return err(r); 4928 } 4929 if (s) throw e; 4930 } 4931 function err(r) { 4932 return e = s ? new dispose_SuppressedError(e, r) : r, s = !0, next(); 4933 } 4934 return next(); 4935 } 4936 function _importDeferProxy(e) { 4937 var t = null, 4938 constValue = function (e) { 4939 return function () { 4940 return e; 4941 }; 4942 }, 4943 proxy = function (r) { 4944 return function (n, o, f) { 4945 return null === t && (t = e()), r(t, o, f); 4946 }; 4947 }; 4948 return new Proxy({}, { 4949 defineProperty: constValue(!1), 4950 deleteProperty: constValue(!1), 4951 get: proxy(Reflect.get), 4952 getOwnPropertyDescriptor: proxy(Reflect.getOwnPropertyDescriptor), 4953 getPrototypeOf: constValue(null), 4954 isExtensible: constValue(!1), 4955 has: proxy(Reflect.has), 4956 ownKeys: proxy(Reflect.ownKeys), 4957 preventExtensions: constValue(!0), 4958 set: constValue(!1), 4959 setPrototypeOf: constValue(!1) 4960 }); 4961 } 4962 function _getRequireWildcardCache(e) { 4963 if ("function" != typeof WeakMap) return null; 4964 var r = new WeakMap(), 4965 t = new WeakMap(); 4966 return (_getRequireWildcardCache = function (e) { 4967 return e ? t : r; 4968 })(e); 4969 } 4970 function _interopRequireWildcard(e, r) { 4971 if (!r && e && e.__esModule) return e; 4972 if (null === e || "object" != typeof e && "function" != typeof e) return { 4973 default: e 4974 }; 4975 var t = _getRequireWildcardCache(r); 4976 if (t && t.has(e)) return t.get(e); 4977 var n = { 4978 __proto__: null 4979 }, 4980 a = Object.defineProperty && Object.getOwnPropertyDescriptor; 4981 for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { 4982 var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; 4983 i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; 4984 } 4985 return n.default = e, t && t.set(e, n), n; 4986 } 4987 function _isNativeReflectConstruct() { 4988 try { 4989 var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); 4990 } catch (t) {} 4991 return (_isNativeReflectConstruct = function () { 4992 return !!t; 4993 })(); 4994 } 4995 function _iterableToArrayLimit(r, l) { 4996 var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; 4997 if (null != t) { 4998 var e, 4999 n, 5000 i, 5001 u, 5002 a = [], 5003 f = !0, 5004 o = !1; 5005 try { 5006 if (i = (t = t.call(r)).next, 0 === l) { 5007 if (Object(t) !== t) return; 5008 f = !1; 5009 } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); 5010 } catch (r) { 5011 o = !0, n = r; 5012 } finally { 5013 try { 5014 if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; 5015 } finally { 5016 if (o) throw n; 5017 } 5018 } 5019 return a; 5020 } 5021 } 5022 function _iterableToArrayLimitLoose(e, r) { 5023 var t = e && ("undefined" != typeof Symbol && e[Symbol.iterator] || e["@@iterator"]); 5024 if (null != t) { 5025 var o, 5026 l = []; 5027 for (t = t.call(e); e.length < r && !(o = t.next()).done;) l.push(o.value); 5028 return l; 5029 } 5030 } 5031 var REACT_ELEMENT_TYPE; 5032 function _jsx(e, r, E, l) { 5033 REACT_ELEMENT_TYPE || (REACT_ELEMENT_TYPE = "function" == typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103); 5034 var o = e && e.defaultProps, 5035 n = arguments.length - 3; 5036 if (r || 0 === n || (r = { 5037 children: void 0 5038 }), 1 === n) r.children = l;else if (n > 1) { 5039 for (var t = new Array(n), f = 0; f < n; f++) t[f] = arguments[f + 3]; 5040 r.children = t; 5041 } 5042 if (r && o) for (var i in o) void 0 === r[i] && (r[i] = o[i]);else r || (r = o || {}); 5043 return { 5044 $$typeof: REACT_ELEMENT_TYPE, 5045 type: e, 5046 key: void 0 === E ? null : "" + E, 5047 ref: null, 5048 props: r, 5049 _owner: null 5050 }; 5051 } 5052 function ownKeys(e, r) { 5053 var t = Object.keys(e); 5054 if (Object.getOwnPropertySymbols) { 5055 var o = Object.getOwnPropertySymbols(e); 5056 r && (o = o.filter(function (r) { 5057 return Object.getOwnPropertyDescriptor(e, r).enumerable; 5058 })), t.push.apply(t, o); 5059 } 5060 return t; 5061 } 5062 function _objectSpread2(e) { 5063 for (var r = 1; r < arguments.length; r++) { 5064 var t = null != arguments[r] ? arguments[r] : {}; 5065 r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { 5066 _defineProperty(e, r, t[r]); 5067 }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { 5068 Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); 5069 }); 5070 } 5071 return e; 5072 } 5073 function _regeneratorRuntime() { 5074 "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ 5075 _regeneratorRuntime = function () { 5076 return e; 5077 }; 5078 var t, 5079 e = {}, 5080 r = Object.prototype, 5081 n = r.hasOwnProperty, 5082 o = Object.defineProperty || function (t, e, r) { 5083 t[e] = r.value; 5084 }, 5085 i = "function" == typeof Symbol ? Symbol : {}, 5086 a = i.iterator || "@@iterator", 5087 c = i.asyncIterator || "@@asyncIterator", 5088 u = i.toStringTag || "@@toStringTag"; 5089 function define(t, e, r) { 5090 return Object.defineProperty(t, e, { 5091 value: r, 5092 enumerable: !0, 5093 configurable: !0, 5094 writable: !0 5095 }), t[e]; 5096 } 5097 try { 5098 define({}, ""); 5099 } catch (t) { 5100 define = function (t, e, r) { 5101 return t[e] = r; 5102 }; 5103 } 5104 function wrap(t, e, r, n) { 5105 var i = e && e.prototype instanceof Generator ? e : Generator, 5106 a = Object.create(i.prototype), 5107 c = new Context(n || []); 5108 return o(a, "_invoke", { 5109 value: makeInvokeMethod(t, r, c) 5110 }), a; 5111 } 5112 function tryCatch(t, e, r) { 5113 try { 5114 return { 5115 type: "normal", 5116 arg: t.call(e, r) 5117 }; 5118 } catch (t) { 5119 return { 5120 type: "throw", 5121 arg: t 5122 }; 5123 } 5124 } 5125 e.wrap = wrap; 5126 var h = "suspendedStart", 5127 l = "suspendedYield", 5128 f = "executing", 5129 s = "completed", 5130 y = {}; 5131 function Generator() {} 5132 function GeneratorFunction() {} 5133 function GeneratorFunctionPrototype() {} 5134 var p = {}; 5135 define(p, a, function () { 5136 return this; 5137 }); 5138 var d = Object.getPrototypeOf, 5139 v = d && d(d(values([]))); 5140 v && v !== r && n.call(v, a) && (p = v); 5141 var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); 5142 function defineIteratorMethods(t) { 5143 ["next", "throw", "return"].forEach(function (e) { 5144 define(t, e, function (t) { 5145 return this._invoke(e, t); 5146 }); 5147 }); 5148 } 5149 function AsyncIterator(t, e) { 5150 function invoke(r, o, i, a) { 5151 var c = tryCatch(t[r], t, o); 5152 if ("throw" !== c.type) { 5153 var u = c.arg, 5154 h = u.value; 5155 return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { 5156 invoke("next", t, i, a); 5157 }, function (t) { 5158 invoke("throw", t, i, a); 5159 }) : e.resolve(h).then(function (t) { 5160 u.value = t, i(u); 5161 }, function (t) { 5162 return invoke("throw", t, i, a); 5163 }); 5164 } 5165 a(c.arg); 5166 } 5167 var r; 5168 o(this, "_invoke", { 5169 value: function (t, n) { 5170 function callInvokeWithMethodAndArg() { 5171 return new e(function (e, r) { 5172 invoke(t, n, e, r); 5173 }); 5174 } 5175 return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); 5176 } 5177 }); 5178 } 5179 function makeInvokeMethod(e, r, n) { 5180 var o = h; 5181 return function (i, a) { 5182 if (o === f) throw new Error("Generator is already running"); 5183 if (o === s) { 5184 if ("throw" === i) throw a; 5185 return { 5186 value: t, 5187 done: !0 5188 }; 5189 } 5190 for (n.method = i, n.arg = a;;) { 5191 var c = n.delegate; 5192 if (c) { 5193 var u = maybeInvokeDelegate(c, n); 5194 if (u) { 5195 if (u === y) continue; 5196 return u; 5197 } 5198 } 5199 if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { 5200 if (o === h) throw o = s, n.arg; 5201 n.dispatchException(n.arg); 5202 } else "return" === n.method && n.abrupt("return", n.arg); 5203 o = f; 5204 var p = tryCatch(e, r, n); 5205 if ("normal" === p.type) { 5206 if (o = n.done ? s : l, p.arg === y) continue; 5207 return { 5208 value: p.arg, 5209 done: n.done 5210 }; 5211 } 5212 "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); 5213 } 5214 }; 5215 } 5216 function maybeInvokeDelegate(e, r) { 5217 var n = r.method, 5218 o = e.iterator[n]; 5219 if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; 5220 var i = tryCatch(o, e.iterator, r.arg); 5221 if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; 5222 var a = i.arg; 5223 return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); 5224 } 5225 function pushTryEntry(t) { 5226 var e = { 5227 tryLoc: t[0] 5228 }; 5229 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); 5230 } 5231 function resetTryEntry(t) { 5232 var e = t.completion || {}; 5233 e.type = "normal", delete e.arg, t.completion = e; 5234 } 5235 function Context(t) { 5236 this.tryEntries = [{ 5237 tryLoc: "root" 5238 }], t.forEach(pushTryEntry, this), this.reset(!0); 5239 } 5240 function values(e) { 5241 if (e || "" === e) { 5242 var r = e[a]; 5243 if (r) return r.call(e); 5244 if ("function" == typeof e.next) return e; 5245 if (!isNaN(e.length)) { 5246 var o = -1, 5247 i = function next() { 5248 for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; 5249 return next.value = t, next.done = !0, next; 5250 }; 5251 return i.next = i; 5252 } 5253 } 5254 throw new TypeError(typeof e + " is not iterable"); 5255 } 5256 return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { 5257 value: GeneratorFunctionPrototype, 5258 configurable: !0 5259 }), o(GeneratorFunctionPrototype, "constructor", { 5260 value: GeneratorFunction, 5261 configurable: !0 5262 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { 5263 var e = "function" == typeof t && t.constructor; 5264 return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); 5265 }, e.mark = function (t) { 5266 return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; 5267 }, e.awrap = function (t) { 5268 return { 5269 __await: t 5270 }; 5271 }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { 5272 return this; 5273 }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { 5274 void 0 === i && (i = Promise); 5275 var a = new AsyncIterator(wrap(t, r, n, o), i); 5276 return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { 5277 return t.done ? t.value : a.next(); 5278 }); 5279 }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { 5280 return this; 5281 }), define(g, "toString", function () { 5282 return "[object Generator]"; 5283 }), e.keys = function (t) { 5284 var e = Object(t), 5285 r = []; 5286 for (var n in e) r.push(n); 5287 return r.reverse(), function next() { 5288 for (; r.length;) { 5289 var t = r.pop(); 5290 if (t in e) return next.value = t, next.done = !1, next; 5291 } 5292 return next.done = !0, next; 5293 }; 5294 }, e.values = values, Context.prototype = { 5295 constructor: Context, 5296 reset: function (e) { 5297 if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); 5298 }, 5299 stop: function () { 5300 this.done = !0; 5301 var t = this.tryEntries[0].completion; 5302 if ("throw" === t.type) throw t.arg; 5303 return this.rval; 5304 }, 5305 dispatchException: function (e) { 5306 if (this.done) throw e; 5307 var r = this; 5308 function handle(n, o) { 5309 return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; 5310 } 5311 for (var o = this.tryEntries.length - 1; o >= 0; --o) { 5312 var i = this.tryEntries[o], 5313 a = i.completion; 5314 if ("root" === i.tryLoc) return handle("end"); 5315 if (i.tryLoc <= this.prev) { 5316 var c = n.call(i, "catchLoc"), 5317 u = n.call(i, "finallyLoc"); 5318 if (c && u) { 5319 if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); 5320 if (this.prev < i.finallyLoc) return handle(i.finallyLoc); 5321 } else if (c) { 5322 if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); 5323 } else { 5324 if (!u) throw new Error("try statement without catch or finally"); 5325 if (this.prev < i.finallyLoc) return handle(i.finallyLoc); 5326 } 5327 } 5328 } 5329 }, 5330 abrupt: function (t, e) { 5331 for (var r = this.tryEntries.length - 1; r >= 0; --r) { 5332 var o = this.tryEntries[r]; 5333 if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { 5334 var i = o; 5335 break; 5336 } 5337 } 5338 i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); 5339 var a = i ? i.completion : {}; 5340 return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); 5341 }, 5342 complete: function (t, e) { 5343 if ("throw" === t.type) throw t.arg; 5344 return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; 5345 }, 5346 finish: function (t) { 5347 for (var e = this.tryEntries.length - 1; e >= 0; --e) { 5348 var r = this.tryEntries[e]; 5349 if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; 5350 } 5351 }, 5352 catch: function (t) { 5353 for (var e = this.tryEntries.length - 1; e >= 0; --e) { 5354 var r = this.tryEntries[e]; 5355 if (r.tryLoc === t) { 5356 var n = r.completion; 5357 if ("throw" === n.type) { 5358 var o = n.arg; 5359 resetTryEntry(r); 5360 } 5361 return o; 5362 } 5363 } 5364 throw new Error("illegal catch attempt"); 5365 }, 5366 delegateYield: function (e, r, n) { 5367 return this.delegate = { 5368 iterator: values(e), 5369 resultName: r, 5370 nextLoc: n 5371 }, "next" === this.method && (this.arg = t), y; 5372 } 5373 }, e; 5374 } 5375 function _setFunctionName(e, t, n) { 5376 "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); 5377 try { 5378 Object.defineProperty(e, "name", { 5379 configurable: !0, 5380 value: n ? n + " " + t : t 5381 }); 5382 } catch (e) {} 5383 return e; 5384 } 5385 function _toPrimitive(t, r) { 5386 if ("object" != typeof t || !t) return t; 5387 var e = t[Symbol.toPrimitive]; 5388 if (void 0 !== e) { 5389 var i = e.call(t, r || "default"); 5390 if ("object" != typeof i) return i; 5391 throw new TypeError("@@toPrimitive must return a primitive value."); 5392 } 5393 return ("string" === r ? String : Number)(t); 5394 } 5395 function _toPropertyKey(t) { 5396 var i = _toPrimitive(t, "string"); 5397 return "symbol" == typeof i ? i : String(i); 5398 } 5399 function _typeof(o) { 5400 "@babel/helpers - typeof"; 5401 5402 return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { 5403 return typeof o; 5404 } : function (o) { 5405 return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; 5406 }, _typeof(o); 5407 } 5408 function _using(o, n, e) { 5409 if (null == n) return n; 5410 if (Object(n) !== n) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined."); 5411 if (e) var r = n[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")]; 5412 if (null == r && (r = n[Symbol.dispose || Symbol.for("Symbol.dispose")]), "function" != typeof r) throw new TypeError("Property [Symbol.dispose] is not a function."); 5413 return o.push({ 5414 v: n, 5415 d: r, 5416 a: e 5417 }), n; 5418 } 5419 function _usingCtx() { 5420 var r = "function" == typeof SuppressedError ? SuppressedError : function (r, n) { 5421 var e = new Error(); 5422 return e.name = "SuppressedError", e.suppressed = n, e.error = r, e; 5423 }, 5424 n = {}, 5425 e = []; 5426 function using(r, n) { 5427 if (null != n) { 5428 if (Object(n) !== n) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined."); 5429 if (r) var o = n[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")]; 5430 if (null == o && (o = n[Symbol.dispose || Symbol.for("Symbol.dispose")]), "function" != typeof o) throw new TypeError("Property [Symbol.dispose] is not a function."); 5431 e.push({ 5432 v: n, 5433 d: o, 5434 a: r 5435 }); 5436 } 5437 return n; 5438 } 5439 return { 5440 e: n, 5441 u: using.bind(null, !1), 5442 a: using.bind(null, !0), 5443 d: function () { 5444 var o = this.e; 5445 function next() { 5446 for (; r = e.pop();) try { 5447 var r, 5448 t = r.d.call(r.v); 5449 if (r.a) return Promise.resolve(t).then(next, err); 5450 } catch (r) { 5451 return err(r); 5452 } 5453 if (o !== n) throw o; 5454 } 5455 function err(e) { 5456 return o = o !== n ? new r(o, e) : e, next(); 5457 } 5458 return next(); 5459 } 5460 }; 5461 } 5462 function _wrapRegExp() { 5463 _wrapRegExp = function (e, r) { 5464 return new BabelRegExp(e, void 0, r); 5465 }; 5466 var e = RegExp.prototype, 5467 r = new WeakMap(); 5468 function BabelRegExp(e, t, p) { 5469 var o = new RegExp(e, t); 5470 return r.set(o, p || r.get(e)), _setPrototypeOf(o, BabelRegExp.prototype); 5471 } 5472 function buildGroups(e, t) { 5473 var p = r.get(t); 5474 return Object.keys(p).reduce(function (r, t) { 5475 var o = p[t]; 5476 if ("number" == typeof o) r[t] = e[o];else { 5477 for (var i = 0; void 0 === e[o[i]] && i + 1 < o.length;) i++; 5478 r[t] = e[o[i]]; 5479 } 5480 return r; 5481 }, Object.create(null)); 5482 } 5483 return _inherits(BabelRegExp, RegExp), BabelRegExp.prototype.exec = function (r) { 5484 var t = e.exec.call(this, r); 5485 if (t) { 5486 t.groups = buildGroups(t, this); 5487 var p = t.indices; 5488 p && (p.groups = buildGroups(p, this)); 5489 } 5490 return t; 5491 }, BabelRegExp.prototype[Symbol.replace] = function (t, p) { 5492 if ("string" == typeof p) { 5493 var o = r.get(this); 5494 return e[Symbol.replace].call(this, t, p.replace(/\$<([^>]+)>/g, function (e, r) { 5495 var t = o[r]; 5496 return "$" + (Array.isArray(t) ? t.join("$") : t); 5497 })); 5498 } 5499 if ("function" == typeof p) { 5500 var i = this; 5501 return e[Symbol.replace].call(this, t, function () { 5502 var e = arguments; 5503 return "object" != typeof e[e.length - 1] && (e = [].slice.call(e)).push(buildGroups(e, i)), p.apply(this, e); 5504 }); 5505 } 5506 return e[Symbol.replace].call(this, t, p); 5507 }, _wrapRegExp.apply(this, arguments); 5508 } 5509 function _AwaitValue(value) { 5510 this.wrapped = value; 5511 } 5512 function _wrapAsyncGenerator(fn) { 5513 return function () { 5514 return new _AsyncGenerator(fn.apply(this, arguments)); 5515 }; 5516 } 5517 function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { 5518 try { 5519 var info = gen[key](arg); 5520 var value = info.value; 5521 } catch (error) { 5522 reject(error); 5523 return; 5524 } 5525 if (info.done) { 5526 resolve(value); 5527 } else { 5528 Promise.resolve(value).then(_next, _throw); 5529 } 5530 } 5531 function _asyncToGenerator(fn) { 5532 return function () { 5533 var self = this, 5534 args = arguments; 5535 return new Promise(function (resolve, reject) { 5536 var gen = fn.apply(self, args); 5537 function _next(value) { 5538 asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); 5539 } 5540 function _throw(err) { 5541 asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); 5542 } 5543 _next(undefined); 5544 }); 5545 }; 5546 } 5547 function _classCallCheck(instance, Constructor) { 5548 if (!(instance instanceof Constructor)) { 5549 throw new TypeError("Cannot call a class as a function"); 5550 } 5551 } 5552 function _defineProperties(target, props) { 5553 for (var i = 0; i < props.length; i++) { 5554 var descriptor = props[i]; 5555 descriptor.enumerable = descriptor.enumerable || false; 5556 descriptor.configurable = true; 5557 if ("value" in descriptor) descriptor.writable = true; 5558 Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); 5559 } 5560 } 5561 function _createClass(Constructor, protoProps, staticProps) { 5562 if (protoProps) _defineProperties(Constructor.prototype, protoProps); 5563 if (staticProps) _defineProperties(Constructor, staticProps); 5564 Object.defineProperty(Constructor, "prototype", { 5565 writable: false 5566 }); 5567 return Constructor; 5568 } 5569 function _defineEnumerableProperties(obj, descs) { 5570 for (var key in descs) { 5571 var desc = descs[key]; 5572 desc.configurable = desc.enumerable = true; 5573 if ("value" in desc) desc.writable = true; 5574 Object.defineProperty(obj, key, desc); 5575 } 5576 if (Object.getOwnPropertySymbols) { 5577 var objectSymbols = Object.getOwnPropertySymbols(descs); 5578 for (var i = 0; i < objectSymbols.length; i++) { 5579 var sym = objectSymbols[i]; 5580 var desc = descs[sym]; 5581 desc.configurable = desc.enumerable = true; 5582 if ("value" in desc) desc.writable = true; 5583 Object.defineProperty(obj, sym, desc); 5584 } 5585 } 5586 return obj; 5587 } 5588 function _defaults(obj, defaults) { 5589 var keys = Object.getOwnPropertyNames(defaults); 5590 for (var i = 0; i < keys.length; i++) { 5591 var key = keys[i]; 5592 var value = Object.getOwnPropertyDescriptor(defaults, key); 5593 if (value && value.configurable && obj[key] === undefined) { 5594 Object.defineProperty(obj, key, value); 5595 } 5596 } 5597 return obj; 5598 } 5599 function _defineProperty(obj, key, value) { 5600 key = _toPropertyKey(key); 5601 if (key in obj) { 5602 Object.defineProperty(obj, key, { 5603 value: value, 5604 enumerable: true, 5605 configurable: true, 5606 writable: true 5607 }); 5608 } else { 5609 obj[key] = value; 5610 } 5611 return obj; 5612 } 5613 function _extends() { 5614 _extends = Object.assign ? Object.assign.bind() : function (target) { 5615 for (var i = 1; i < arguments.length; i++) { 5616 var source = arguments[i]; 5617 for (var key in source) { 5618 if (Object.prototype.hasOwnProperty.call(source, key)) { 5619 target[key] = source[key]; 5620 } 5621 } 5622 } 5623 return target; 5624 }; 5625 return _extends.apply(this, arguments); 5626 } 5627 function _objectSpread(target) { 5628 for (var i = 1; i < arguments.length; i++) { 5629 var source = arguments[i] != null ? Object(arguments[i]) : {}; 5630 var ownKeys = Object.keys(source); 5631 if (typeof Object.getOwnPropertySymbols === 'function') { 5632 ownKeys.push.apply(ownKeys, Object.getOwnPropertySymbols(source).filter(function (sym) { 5633 return Object.getOwnPropertyDescriptor(source, sym).enumerable; 5634 })); 5635 } 5636 ownKeys.forEach(function (key) { 5637 _defineProperty(target, key, source[key]); 5638 }); 5639 } 5640 return target; 5641 } 5642 function _inherits(subClass, superClass) { 5643 if (typeof superClass !== "function" && superClass !== null) { 5644 throw new TypeError("Super expression must either be null or a function"); 5645 } 5646 subClass.prototype = Object.create(superClass && superClass.prototype, { 5647 constructor: { 5648 value: subClass, 5649 writable: true, 5650 configurable: true 5651 } 5652 }); 5653 Object.defineProperty(subClass, "prototype", { 5654 writable: false 5655 }); 5656 if (superClass) _setPrototypeOf(subClass, superClass); 5657 } 5658 function _inheritsLoose(subClass, superClass) { 5659 subClass.prototype = Object.create(superClass.prototype); 5660 subClass.prototype.constructor = subClass; 5661 _setPrototypeOf(subClass, superClass); 5662 } 5663 function _getPrototypeOf(o) { 5664 _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { 5665 return o.__proto__ || Object.getPrototypeOf(o); 5666 }; 5667 return _getPrototypeOf(o); 5668 } 5669 function _setPrototypeOf(o, p) { 5670 _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { 5671 o.__proto__ = p; 5672 return o; 5673 }; 5674 return _setPrototypeOf(o, p); 5675 } 5676 function _isNativeFunction(fn) { 5677 try { 5678 return Function.toString.call(fn).indexOf("[native code]") !== -1; 5679 } catch (e) { 5680 return typeof fn === "function"; 5681 } 5682 } 5683 function _wrapNativeSuper(Class) { 5684 var _cache = typeof Map === "function" ? new Map() : undefined; 5685 _wrapNativeSuper = function _wrapNativeSuper(Class) { 5686 if (Class === null || !_isNativeFunction(Class)) return Class; 5687 if (typeof Class !== "function") { 5688 throw new TypeError("Super expression must either be null or a function"); 5689 } 5690 if (typeof _cache !== "undefined") { 5691 if (_cache.has(Class)) return _cache.get(Class); 5692 _cache.set(Class, Wrapper); 5693 } 5694 function Wrapper() { 5695 return _construct(Class, arguments, _getPrototypeOf(this).constructor); 5696 } 5697 Wrapper.prototype = Object.create(Class.prototype, { 5698 constructor: { 5699 value: Wrapper, 5700 enumerable: false, 5701 writable: true, 5702 configurable: true 5703 } 5704 }); 5705 return _setPrototypeOf(Wrapper, Class); 5706 }; 5707 return _wrapNativeSuper(Class); 5708 } 5709 function _instanceof(left, right) { 5710 if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { 5711 return !!right[Symbol.hasInstance](left); 5712 } else { 5713 return left instanceof right; 5714 } 5715 } 5716 function _interopRequireDefault(obj) { 5717 return obj && obj.__esModule ? obj : { 5718 default: obj 5719 }; 5720 } 5721 function _newArrowCheck(innerThis, boundThis) { 5722 if (innerThis !== boundThis) { 5723 throw new TypeError("Cannot instantiate an arrow function"); 5724 } 5725 } 5726 function _objectDestructuringEmpty(obj) { 5727 if (obj == null) throw new TypeError("Cannot destructure " + obj); 5728 } 5729 function _objectWithoutPropertiesLoose(source, excluded) { 5730 if (source == null) return {}; 5731 var target = {}; 5732 var sourceKeys = Object.keys(source); 5733 var key, i; 5734 for (i = 0; i < sourceKeys.length; i++) { 5735 key = sourceKeys[i]; 5736 if (excluded.indexOf(key) >= 0) continue; 5737 target[key] = source[key]; 5738 } 5739 return target; 5740 } 5741 function _objectWithoutProperties(source, excluded) { 5742 if (source == null) return {}; 5743 var target = _objectWithoutPropertiesLoose(source, excluded); 5744 var key, i; 5745 if (Object.getOwnPropertySymbols) { 5746 var sourceSymbolKeys = Object.getOwnPropertySymbols(source); 5747 for (i = 0; i < sourceSymbolKeys.length; i++) { 5748 key = sourceSymbolKeys[i]; 5749 if (excluded.indexOf(key) >= 0) continue; 5750 if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; 5751 target[key] = source[key]; 5752 } 5753 } 5754 return target; 5755 } 5756 function _assertThisInitialized(self) { 5757 if (self === void 0) { 5758 throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 5759 } 5760 return self; 5761 } 5762 function _possibleConstructorReturn(self, call) { 5763 if (call && (typeof call === "object" || typeof call === "function")) { 5764 return call; 5765 } else if (call !== void 0) { 5766 throw new TypeError("Derived constructors may only return object or undefined"); 5767 } 5768 return _assertThisInitialized(self); 5769 } 5770 function _createSuper(Derived) { 5771 var hasNativeReflectConstruct = _isNativeReflectConstruct(); 5772 return function _createSuperInternal() { 5773 var Super = _getPrototypeOf(Derived), 5774 result; 5775 if (hasNativeReflectConstruct) { 5776 var NewTarget = _getPrototypeOf(this).constructor; 5777 result = Reflect.construct(Super, arguments, NewTarget); 5778 } else { 5779 result = Super.apply(this, arguments); 5780 } 5781 return _possibleConstructorReturn(this, result); 5782 }; 5783 } 5784 function _superPropBase(object, property) { 5785 while (!Object.prototype.hasOwnProperty.call(object, property)) { 5786 object = _getPrototypeOf(object); 5787 if (object === null) break; 5788 } 5789 return object; 5790 } 5791 function _get() { 5792 if (typeof Reflect !== "undefined" && Reflect.get) { 5793 _get = Reflect.get.bind(); 5794 } else { 5795 _get = function _get(target, property, receiver) { 5796 var base = _superPropBase(target, property); 5797 if (!base) return; 5798 var desc = Object.getOwnPropertyDescriptor(base, property); 5799 if (desc.get) { 5800 return desc.get.call(arguments.length < 3 ? target : receiver); 5801 } 5802 return desc.value; 5803 }; 5804 } 5805 return _get.apply(this, arguments); 5806 } 5807 function set(target, property, value, receiver) { 5808 if (typeof Reflect !== "undefined" && Reflect.set) { 5809 set = Reflect.set; 5810 } else { 5811 set = function set(target, property, value, receiver) { 5812 var base = _superPropBase(target, property); 5813 var desc; 5814 if (base) { 5815 desc = Object.getOwnPropertyDescriptor(base, property); 5816 if (desc.set) { 5817 desc.set.call(receiver, value); 5818 return true; 5819 } else if (!desc.writable) { 5820 return false; 5821 } 5822 } 5823 desc = Object.getOwnPropertyDescriptor(receiver, property); 5824 if (desc) { 5825 if (!desc.writable) { 5826 return false; 5827 } 5828 desc.value = value; 5829 Object.defineProperty(receiver, property, desc); 5830 } else { 5831 _defineProperty(receiver, property, value); 5832 } 5833 return true; 5834 }; 5835 } 5836 return set(target, property, value, receiver); 5837 } 5838 function _set(target, property, value, receiver, isStrict) { 5839 var s = set(target, property, value, receiver || target); 5840 if (!s && isStrict) { 5841 throw new TypeError('failed to set property'); 5842 } 5843 return value; 5844 } 5845 function _taggedTemplateLiteral(strings, raw) { 5846 if (!raw) { 5847 raw = strings.slice(0); 5848 } 5849 return Object.freeze(Object.defineProperties(strings, { 5850 raw: { 5851 value: Object.freeze(raw) 5852 } 5853 })); 5854 } 5855 function _taggedTemplateLiteralLoose(strings, raw) { 5856 if (!raw) { 5857 raw = strings.slice(0); 5858 } 5859 strings.raw = raw; 5860 return strings; 5861 } 5862 function _readOnlyError(name) { 5863 throw new TypeError("\"" + name + "\" is read-only"); 5864 } 5865 function _writeOnlyError(name) { 5866 throw new TypeError("\"" + name + "\" is write-only"); 5867 } 5868 function _classNameTDZError(name) { 5869 throw new ReferenceError("Class \"" + name + "\" cannot be referenced in computed property keys."); 5870 } 5871 function _temporalUndefined() {} 5872 function _tdz(name) { 5873 throw new ReferenceError(name + " is not defined - temporal dead zone"); 5874 } 5875 function _temporalRef(val, name) { 5876 return val === _temporalUndefined ? _tdz(name) : val; 5877 } 5878 function _slicedToArray(arr, i) { 5879 return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); 5880 } 5881 function _slicedToArrayLoose(arr, i) { 5882 return _arrayWithHoles(arr) || _iterableToArrayLimitLoose(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); 5883 } 5884 function _toArray(arr) { 5885 return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); 5886 } 5887 function _toConsumableArray(arr) { 5888 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); 5889 } 5890 function _arrayWithoutHoles(arr) { 5891 if (Array.isArray(arr)) return _arrayLikeToArray(arr); 5892 } 5893 function _arrayWithHoles(arr) { 5894 if (Array.isArray(arr)) return arr; 5895 } 5896 function _maybeArrayLike(next, arr, i) { 5897 if (arr && !Array.isArray(arr) && typeof arr.length === "number") { 5898 var len = arr.length; 5899 return _arrayLikeToArray(arr, i !== void 0 && i < len ? i : len); 5900 } 5901 return next(arr, i); 5902 } 5903 function _iterableToArray(iter) { 5904 if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); 5905 } 5906 function _unsupportedIterableToArray(o, minLen) { 5907 if (!o) return; 5908 if (typeof o === "string") return _arrayLikeToArray(o, minLen); 5909 var n = Object.prototype.toString.call(o).slice(8, -1); 5910 if (n === "Object" && o.constructor) n = o.constructor.name; 5911 if (n === "Map" || n === "Set") return Array.from(o); 5912 if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); 5913 } 5914 function _arrayLikeToArray(arr, len) { 5915 if (len == null || len > arr.length) len = arr.length; 5916 for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; 5917 return arr2; 5918 } 5919 function _nonIterableSpread() { 5920 throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); 5921 } 5922 function _nonIterableRest() { 5923 throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); 5924 } 5925 function _createForOfIteratorHelper(o, allowArrayLike) { 5926 var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; 5927 if (!it) { 5928 if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { 5929 if (it) o = it; 5930 var i = 0; 5931 var F = function () {}; 5932 return { 5933 s: F, 5934 n: function () { 5935 if (i >= o.length) return { 5936 done: true 5937 }; 5938 return { 5939 done: false, 5940 value: o[i++] 5941 }; 5942 }, 5943 e: function (e) { 5944 throw e; 5945 }, 5946 f: F 5947 }; 5948 } 5949 throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); 5950 } 5951 var normalCompletion = true, 5952 didErr = false, 5953 err; 5954 return { 5955 s: function () { 5956 it = it.call(o); 5957 }, 5958 n: function () { 5959 var step = it.next(); 5960 normalCompletion = step.done; 5961 return step; 5962 }, 5963 e: function (e) { 5964 didErr = true; 5965 err = e; 5966 }, 5967 f: function () { 5968 try { 5969 if (!normalCompletion && it.return != null) it.return(); 5970 } finally { 5971 if (didErr) throw err; 5972 } 5973 } 5974 }; 5975 } 5976 function _createForOfIteratorHelperLoose(o, allowArrayLike) { 5977 var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; 5978 if (it) return (it = it.call(o)).next.bind(it); 5979 if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { 5980 if (it) o = it; 5981 var i = 0; 5982 return function () { 5983 if (i >= o.length) return { 5984 done: true 5985 }; 5986 return { 5987 done: false, 5988 value: o[i++] 5989 }; 5990 }; 5991 } 5992 throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); 5993 } 5994 function _skipFirstGeneratorNext(fn) { 5995 return function () { 5996 var it = fn.apply(this, arguments); 5997 it.next(); 5998 return it; 5999 }; 6000 } 6001 function _initializerWarningHelper(descriptor, context) { 6002 throw new Error('Decorating class property failed. Please ensure that ' + 'transform-class-properties is enabled and runs after the decorators transform.'); 6003 } 6004 function _initializerDefineProperty(target, property, descriptor, context) { 6005 if (!descriptor) return; 6006 Object.defineProperty(target, property, { 6007 enumerable: descriptor.enumerable, 6008 configurable: descriptor.configurable, 6009 writable: descriptor.writable, 6010 value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 6011 }); 6012 } 6013 function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { 6014 var desc = {}; 6015 Object.keys(descriptor).forEach(function (key) { 6016 desc[key] = descriptor[key]; 6017 }); 6018 desc.enumerable = !!desc.enumerable; 6019 desc.configurable = !!desc.configurable; 6020 if ('value' in desc || desc.initializer) { 6021 desc.writable = true; 6022 } 6023 desc = decorators.slice().reverse().reduce(function (desc, decorator) { 6024 return decorator(target, property, desc) || desc; 6025 }, desc); 6026 if (context && desc.initializer !== void 0) { 6027 desc.value = desc.initializer ? desc.initializer.call(context) : void 0; 6028 desc.initializer = undefined; 6029 } 6030 if (desc.initializer === void 0) { 6031 Object.defineProperty(target, property, desc); 6032 desc = null; 6033 } 6034 return desc; 6035 } 6036 var id$1 = 0; 6037 function _classPrivateFieldLooseKey(name) { 6038 return "__private_" + id$1++ + "_" + name; 6039 } 6040 function _classPrivateFieldLooseBase(receiver, privateKey) { 6041 if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { 6042 throw new TypeError("attempted to use private field on non-instance"); 6043 } 6044 return receiver; 6045 } 6046 function _classPrivateFieldGet(receiver, privateMap) { 6047 var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); 6048 return _classApplyDescriptorGet(receiver, descriptor); 6049 } 6050 function _classPrivateFieldSet(receiver, privateMap, value) { 6051 var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); 6052 _classApplyDescriptorSet(receiver, descriptor, value); 6053 return value; 6054 } 6055 function _classPrivateFieldDestructureSet(receiver, privateMap) { 6056 var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); 6057 return _classApplyDescriptorDestructureSet(receiver, descriptor); 6058 } 6059 function _classExtractFieldDescriptor(receiver, privateMap, action) { 6060 if (!privateMap.has(receiver)) { 6061 throw new TypeError("attempted to " + action + " private field on non-instance"); 6062 } 6063 return privateMap.get(receiver); 6064 } 6065 function _classStaticPrivateFieldSpecGet(receiver, classConstructor, descriptor) { 6066 _classCheckPrivateStaticAccess(receiver, classConstructor); 6067 _classCheckPrivateStaticFieldDescriptor(descriptor, "get"); 6068 return _classApplyDescriptorGet(receiver, descriptor); 6069 } 6070 function _classStaticPrivateFieldSpecSet(receiver, classConstructor, descriptor, value) { 6071 _classCheckPrivateStaticAccess(receiver, classConstructor); 6072 _classCheckPrivateStaticFieldDescriptor(descriptor, "set"); 6073 _classApplyDescriptorSet(receiver, descriptor, value); 6074 return value; 6075 } 6076 function _classStaticPrivateMethodGet(receiver, classConstructor, method) { 6077 _classCheckPrivateStaticAccess(receiver, classConstructor); 6078 return method; 6079 } 6080 function _classStaticPrivateMethodSet() { 6081 throw new TypeError("attempted to set read only static private field"); 6082 } 6083 function _classApplyDescriptorGet(receiver, descriptor) { 6084 if (descriptor.get) { 6085 return descriptor.get.call(receiver); 6086 } 6087 return descriptor.value; 6088 } 6089 function _classApplyDescriptorSet(receiver, descriptor, value) { 6090 if (descriptor.set) { 6091 descriptor.set.call(receiver, value); 6092 } else { 6093 if (!descriptor.writable) { 6094 throw new TypeError("attempted to set read only private field"); 6095 } 6096 descriptor.value = value; 6097 } 6098 } 6099 function _classApplyDescriptorDestructureSet(receiver, descriptor) { 6100 if (descriptor.set) { 6101 if (!("__destrObj" in descriptor)) { 6102 descriptor.__destrObj = { 6103 set value(v) { 6104 descriptor.set.call(receiver, v); 6105 } 6106 }; 6107 } 6108 return descriptor.__destrObj; 6109 } else { 6110 if (!descriptor.writable) { 6111 throw new TypeError("attempted to set read only private field"); 6112 } 6113 return descriptor; 6114 } 6115 } 6116 function _classStaticPrivateFieldDestructureSet(receiver, classConstructor, descriptor) { 6117 _classCheckPrivateStaticAccess(receiver, classConstructor); 6118 _classCheckPrivateStaticFieldDescriptor(descriptor, "set"); 6119 return _classApplyDescriptorDestructureSet(receiver, descriptor); 6120 } 6121 function _classCheckPrivateStaticAccess(receiver, classConstructor) { 6122 if (receiver !== classConstructor) { 6123 throw new TypeError("Private static access of wrong provenance"); 6124 } 6125 } 6126 function _classCheckPrivateStaticFieldDescriptor(descriptor, action) { 6127 if (descriptor === undefined) { 6128 throw new TypeError("attempted to " + action + " private static field before its declaration"); 6129 } 6130 } 6131 function _decorate(decorators, factory, superClass, mixins) { 6132 var api = _getDecoratorsApi(); 6133 if (mixins) { 6134 for (var i = 0; i < mixins.length; i++) { 6135 api = mixins[i](api); 6136 } 6137 } 6138 var r = factory(function initialize(O) { 6139 api.initializeInstanceElements(O, decorated.elements); 6140 }, superClass); 6141 var decorated = api.decorateClass(_coalesceClassElements(r.d.map(_createElementDescriptor)), decorators); 6142 api.initializeClassElements(r.F, decorated.elements); 6143 return api.runClassFinishers(r.F, decorated.finishers); 6144 } 6145 function _getDecoratorsApi() { 6146 _getDecoratorsApi = function () { 6147 return api; 6148 }; 6149 var api = { 6150 elementsDefinitionOrder: [["method"], ["field"]], 6151 initializeInstanceElements: function (O, elements) { 6152 ["method", "field"].forEach(function (kind) { 6153 elements.forEach(function (element) { 6154 if (element.kind === kind && element.placement === "own") { 6155 this.defineClassElement(O, element); 6156 } 6157 }, this); 6158 }, this); 6159 }, 6160 initializeClassElements: function (F, elements) { 6161 var proto = F.prototype; 6162 ["method", "field"].forEach(function (kind) { 6163 elements.forEach(function (element) { 6164 var placement = element.placement; 6165 if (element.kind === kind && (placement === "static" || placement === "prototype")) { 6166 var receiver = placement === "static" ? F : proto; 6167 this.defineClassElement(receiver, element); 6168 } 6169 }, this); 6170 }, this); 6171 }, 6172 defineClassElement: function (receiver, element) { 6173 var descriptor = element.descriptor; 6174 if (element.kind === "field") { 6175 var initializer = element.initializer; 6176 descriptor = { 6177 enumerable: descriptor.enumerable, 6178 writable: descriptor.writable, 6179 configurable: descriptor.configurable, 6180 value: initializer === void 0 ? void 0 : initializer.call(receiver) 6181 }; 6182 } 6183 Object.defineProperty(receiver, element.key, descriptor); 6184 }, 6185 decorateClass: function (elements, decorators) { 6186 var newElements = []; 6187 var finishers = []; 6188 var placements = { 6189 static: [], 6190 prototype: [], 6191 own: [] 6192 }; 6193 elements.forEach(function (element) { 6194 this.addElementPlacement(element, placements); 6195 }, this); 6196 elements.forEach(function (element) { 6197 if (!_hasDecorators(element)) return newElements.push(element); 6198 var elementFinishersExtras = this.decorateElement(element, placements); 6199 newElements.push(elementFinishersExtras.element); 6200 newElements.push.apply(newElements, elementFinishersExtras.extras); 6201 finishers.push.apply(finishers, elementFinishersExtras.finishers); 6202 }, this); 6203 if (!decorators) { 6204 return { 6205 elements: newElements, 6206 finishers: finishers 6207 }; 6208 } 6209 var result = this.decorateConstructor(newElements, decorators); 6210 finishers.push.apply(finishers, result.finishers); 6211 result.finishers = finishers; 6212 return result; 6213 }, 6214 addElementPlacement: function (element, placements, silent) { 6215 var keys = placements[element.placement]; 6216 if (!silent && keys.indexOf(element.key) !== -1) { 6217 throw new TypeError("Duplicated element (" + element.key + ")"); 6218 } 6219 keys.push(element.key); 6220 }, 6221 decorateElement: function (element, placements) { 6222 var extras = []; 6223 var finishers = []; 6224 for (var decorators = element.decorators, i = decorators.length - 1; i >= 0; i--) { 6225 var keys = placements[element.placement]; 6226 keys.splice(keys.indexOf(element.key), 1); 6227 var elementObject = this.fromElementDescriptor(element); 6228 var elementFinisherExtras = this.toElementFinisherExtras((0, decorators[i])(elementObject) || elementObject); 6229 element = elementFinisherExtras.element; 6230 this.addElementPlacement(element, placements); 6231 if (elementFinisherExtras.finisher) { 6232 finishers.push(elementFinisherExtras.finisher); 6233 } 6234 var newExtras = elementFinisherExtras.extras; 6235 if (newExtras) { 6236 for (var j = 0; j < newExtras.length; j++) { 6237 this.addElementPlacement(newExtras[j], placements); 6238 } 6239 extras.push.apply(extras, newExtras); 6240 } 6241 } 6242 return { 6243 element: element, 6244 finishers: finishers, 6245 extras: extras 6246 }; 6247 }, 6248 decorateConstructor: function (elements, decorators) { 6249 var finishers = []; 6250 for (var i = decorators.length - 1; i >= 0; i--) { 6251 var obj = this.fromClassDescriptor(elements); 6252 var elementsAndFinisher = this.toClassDescriptor((0, decorators[i])(obj) || obj); 6253 if (elementsAndFinisher.finisher !== undefined) { 6254 finishers.push(elementsAndFinisher.finisher); 6255 } 6256 if (elementsAndFinisher.elements !== undefined) { 6257 elements = elementsAndFinisher.elements; 6258 for (var j = 0; j < elements.length - 1; j++) { 6259 for (var k = j + 1; k < elements.length; k++) { 6260 if (elements[j].key === elements[k].key && elements[j].placement === elements[k].placement) { 6261 throw new TypeError("Duplicated element (" + elements[j].key + ")"); 6262 } 6263 } 6264 } 6265 } 6266 } 6267 return { 6268 elements: elements, 6269 finishers: finishers 6270 }; 6271 }, 6272 fromElementDescriptor: function (element) { 6273 var obj = { 6274 kind: element.kind, 6275 key: element.key, 6276 placement: element.placement, 6277 descriptor: element.descriptor 6278 }; 6279 var desc = { 6280 value: "Descriptor", 6281 configurable: true 6282 }; 6283 Object.defineProperty(obj, Symbol.toStringTag, desc); 6284 if (element.kind === "field") obj.initializer = element.initializer; 6285 return obj; 6286 }, 6287 toElementDescriptors: function (elementObjects) { 6288 if (elementObjects === undefined) return; 6289 return _toArray(elementObjects).map(function (elementObject) { 6290 var element = this.toElementDescriptor(elementObject); 6291 this.disallowProperty(elementObject, "finisher", "An element descriptor"); 6292 this.disallowProperty(elementObject, "extras", "An element descriptor"); 6293 return element; 6294 }, this); 6295 }, 6296 toElementDescriptor: function (elementObject) { 6297 var kind = String(elementObject.kind); 6298 if (kind !== "method" && kind !== "field") { 6299 throw new TypeError('An element descriptor\'s .kind property must be either "method" or' + ' "field", but a decorator created an element descriptor with' + ' .kind "' + kind + '"'); 6300 } 6301 var key = _toPropertyKey(elementObject.key); 6302 var placement = String(elementObject.placement); 6303 if (placement !== "static" && placement !== "prototype" && placement !== "own") { 6304 throw new TypeError('An element descriptor\'s .placement property must be one of "static",' + ' "prototype" or "own", but a decorator created an element descriptor' + ' with .placement "' + placement + '"'); 6305 } 6306 var descriptor = elementObject.descriptor; 6307 this.disallowProperty(elementObject, "elements", "An element descriptor"); 6308 var element = { 6309 kind: kind, 6310 key: key, 6311 placement: placement, 6312 descriptor: Object.assign({}, descriptor) 6313 }; 6314 if (kind !== "field") { 6315 this.disallowProperty(elementObject, "initializer", "A method descriptor"); 6316 } else { 6317 this.disallowProperty(descriptor, "get", "The property descriptor of a field descriptor"); 6318 this.disallowProperty(descriptor, "set", "The property descriptor of a field descriptor"); 6319 this.disallowProperty(descriptor, "value", "The property descriptor of a field descriptor"); 6320 element.initializer = elementObject.initializer; 6321 } 6322 return element; 6323 }, 6324 toElementFinisherExtras: function (elementObject) { 6325 var element = this.toElementDescriptor(elementObject); 6326 var finisher = _optionalCallableProperty(elementObject, "finisher"); 6327 var extras = this.toElementDescriptors(elementObject.extras); 6328 return { 6329 element: element, 6330 finisher: finisher, 6331 extras: extras 6332 }; 6333 }, 6334 fromClassDescriptor: function (elements) { 6335 var obj = { 6336 kind: "class", 6337 elements: elements.map(this.fromElementDescriptor, this) 6338 }; 6339 var desc = { 6340 value: "Descriptor", 6341 configurable: true 6342 }; 6343 Object.defineProperty(obj, Symbol.toStringTag, desc); 6344 return obj; 6345 }, 6346 toClassDescriptor: function (obj) { 6347 var kind = String(obj.kind); 6348 if (kind !== "class") { 6349 throw new TypeError('A class descriptor\'s .kind property must be "class", but a decorator' + ' created a class descriptor with .kind "' + kind + '"'); 6350 } 6351 this.disallowProperty(obj, "key", "A class descriptor"); 6352 this.disallowProperty(obj, "placement", "A class descriptor"); 6353 this.disallowProperty(obj, "descriptor", "A class descriptor"); 6354 this.disallowProperty(obj, "initializer", "A class descriptor"); 6355 this.disallowProperty(obj, "extras", "A class descriptor"); 6356 var finisher = _optionalCallableProperty(obj, "finisher"); 6357 var elements = this.toElementDescriptors(obj.elements); 6358 return { 6359 elements: elements, 6360 finisher: finisher 6361 }; 6362 }, 6363 runClassFinishers: function (constructor, finishers) { 6364 for (var i = 0; i < finishers.length; i++) { 6365 var newConstructor = (0, finishers[i])(constructor); 6366 if (newConstructor !== undefined) { 6367 if (typeof newConstructor !== "function") { 6368 throw new TypeError("Finishers must return a constructor."); 6369 } 6370 constructor = newConstructor; 6371 } 6372 } 6373 return constructor; 6374 }, 6375 disallowProperty: function (obj, name, objectType) { 6376 if (obj[name] !== undefined) { 6377 throw new TypeError(objectType + " can't have a ." + name + " property."); 6378 } 6379 } 6380 }; 6381 return api; 6382 } 6383 function _createElementDescriptor(def) { 6384 var key = _toPropertyKey(def.key); 6385 var descriptor; 6386 if (def.kind === "method") { 6387 descriptor = { 6388 value: def.value, 6389 writable: true, 6390 configurable: true, 6391 enumerable: false 6392 }; 6393 } else if (def.kind === "get") { 6394 descriptor = { 6395 get: def.value, 6396 configurable: true, 6397 enumerable: false 6398 }; 6399 } else if (def.kind === "set") { 6400 descriptor = { 6401 set: def.value, 6402 configurable: true, 6403 enumerable: false 6404 }; 6405 } else if (def.kind === "field") { 6406 descriptor = { 6407 configurable: true, 6408 writable: true, 6409 enumerable: true 6410 }; 6411 } 6412 var element = { 6413 kind: def.kind === "field" ? "field" : "method", 6414 key: key, 6415 placement: def.static ? "static" : def.kind === "field" ? "own" : "prototype", 6416 descriptor: descriptor 6417 }; 6418 if (def.decorators) element.decorators = def.decorators; 6419 if (def.kind === "field") element.initializer = def.value; 6420 return element; 6421 } 6422 function _coalesceGetterSetter(element, other) { 6423 if (element.descriptor.get !== undefined) { 6424 other.descriptor.get = element.descriptor.get; 6425 } else { 6426 other.descriptor.set = element.descriptor.set; 6427 } 6428 } 6429 function _coalesceClassElements(elements) { 6430 var newElements = []; 6431 var isSameElement = function (other) { 6432 return other.kind === "method" && other.key === element.key && other.placement === element.placement; 6433 }; 6434 for (var i = 0; i < elements.length; i++) { 6435 var element = elements[i]; 6436 var other; 6437 if (element.kind === "method" && (other = newElements.find(isSameElement))) { 6438 if (_isDataDescriptor(element.descriptor) || _isDataDescriptor(other.descriptor)) { 6439 if (_hasDecorators(element) || _hasDecorators(other)) { 6440 throw new ReferenceError("Duplicated methods (" + element.key + ") can't be decorated."); 6441 } 6442 other.descriptor = element.descriptor; 6443 } else { 6444 if (_hasDecorators(element)) { 6445 if (_hasDecorators(other)) { 6446 throw new ReferenceError("Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ")."); 6447 } 6448 other.decorators = element.decorators; 6449 } 6450 _coalesceGetterSetter(element, other); 6451 } 6452 } else { 6453 newElements.push(element); 6454 } 6455 } 6456 return newElements; 6457 } 6458 function _hasDecorators(element) { 6459 return element.decorators && element.decorators.length; 6460 } 6461 function _isDataDescriptor(desc) { 6462 return desc !== undefined && !(desc.value === undefined && desc.writable === undefined); 6463 } 6464 function _optionalCallableProperty(obj, name) { 6465 var value = obj[name]; 6466 if (value !== undefined && typeof value !== "function") { 6467 throw new TypeError("Expected '" + name + "' to be a function"); 6468 } 6469 return value; 6470 } 6471 function _classPrivateMethodGet(receiver, privateSet, fn) { 6472 if (!privateSet.has(receiver)) { 6473 throw new TypeError("attempted to get private field on non-instance"); 6474 } 6475 return fn; 6476 } 6477 function _checkPrivateRedeclaration(obj, privateCollection) { 6478 if (privateCollection.has(obj)) { 6479 throw new TypeError("Cannot initialize the same private elements twice on an object"); 6480 } 6481 } 6482 function _classPrivateFieldInitSpec(obj, privateMap, value) { 6483 _checkPrivateRedeclaration(obj, privateMap); 6484 privateMap.set(obj, value); 6485 } 6486 function _classPrivateMethodInitSpec(obj, privateSet) { 6487 _checkPrivateRedeclaration(obj, privateSet); 6488 privateSet.add(obj); 6489 } 6490 function _classPrivateMethodSet() { 6491 throw new TypeError("attempted to reassign private method"); 6492 } 6493 function _identity(x) { 6494 return x; 6495 } 6496 function _nullishReceiverError(r) { 6497 throw new TypeError("Cannot set property of null or undefined."); 6498 } 6499 6500 class Piece extends TrixObject { 6501 static registerType(type, constructor) { 6502 constructor.type = type; 6503 this.types[type] = constructor; 6504 } 6505 static fromJSON(pieceJSON) { 6506 const constructor = this.types[pieceJSON.type]; 6507 if (constructor) { 6508 return constructor.fromJSON(pieceJSON); 6509 } 6510 } 6511 constructor(value) { 6512 let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 6513 super(...arguments); 6514 this.attributes = Hash.box(attributes); 6515 } 6516 copyWithAttributes(attributes) { 6517 return new this.constructor(this.getValue(), attributes); 6518 } 6519 copyWithAdditionalAttributes(attributes) { 6520 return this.copyWithAttributes(this.attributes.merge(attributes)); 6521 } 6522 copyWithoutAttribute(attribute) { 6523 return this.copyWithAttributes(this.attributes.remove(attribute)); 6524 } 6525 copy() { 6526 return this.copyWithAttributes(this.attributes); 6527 } 6528 getAttribute(attribute) { 6529 return this.attributes.get(attribute); 6530 } 6531 getAttributesHash() { 6532 return this.attributes; 6533 } 6534 getAttributes() { 6535 return this.attributes.toObject(); 6536 } 6537 hasAttribute(attribute) { 6538 return this.attributes.has(attribute); 6539 } 6540 hasSameStringValueAsPiece(piece) { 6541 return piece && this.toString() === piece.toString(); 6542 } 6543 hasSameAttributesAsPiece(piece) { 6544 return piece && (this.attributes === piece.attributes || this.attributes.isEqualTo(piece.attributes)); 6545 } 6546 isBlockBreak() { 6547 return false; 6548 } 6549 isEqualTo(piece) { 6550 return super.isEqualTo(...arguments) || this.hasSameConstructorAs(piece) && this.hasSameStringValueAsPiece(piece) && this.hasSameAttributesAsPiece(piece); 6551 } 6552 isEmpty() { 6553 return this.length === 0; 6554 } 6555 isSerializable() { 6556 return true; 6557 } 6558 toJSON() { 6559 return { 6560 type: this.constructor.type, 6561 attributes: this.getAttributes() 6562 }; 6563 } 6564 contentsForInspection() { 6565 return { 6566 type: this.constructor.type, 6567 attributes: this.attributes.inspect() 6568 }; 6569 } 6570 6571 // Grouping 6572 6573 canBeGrouped() { 6574 return this.hasAttribute("href"); 6575 } 6576 canBeGroupedWith(piece) { 6577 return this.getAttribute("href") === piece.getAttribute("href"); 6578 } 6579 6580 // Splittable 6581 6582 getLength() { 6583 return this.length; 6584 } 6585 canBeConsolidatedWith(piece) { 6586 return false; 6587 } 6588 } 6589 _defineProperty(Piece, "types", {}); 6590 6591 class ImagePreloadOperation extends Operation { 6592 constructor(url) { 6593 super(...arguments); 6594 this.url = url; 6595 } 6596 perform(callback) { 6597 const image = new Image(); 6598 image.onload = () => { 6599 image.width = this.width = image.naturalWidth; 6600 image.height = this.height = image.naturalHeight; 6601 return callback(true, image); 6602 }; 6603 image.onerror = () => callback(false); 6604 image.src = this.url; 6605 } 6606 } 6607 6608 class Attachment extends TrixObject { 6609 static attachmentForFile(file) { 6610 const attributes = this.attributesForFile(file); 6611 const attachment = new this(attributes); 6612 attachment.setFile(file); 6613 return attachment; 6614 } 6615 static attributesForFile(file) { 6616 return new Hash({ 6617 filename: file.name, 6618 filesize: file.size, 6619 contentType: file.type 6620 }); 6621 } 6622 static fromJSON(attachmentJSON) { 6623 return new this(attachmentJSON); 6624 } 6625 constructor() { 6626 let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 6627 super(attributes); 6628 this.releaseFile = this.releaseFile.bind(this); 6629 this.attributes = Hash.box(attributes); 6630 this.didChangeAttributes(); 6631 } 6632 setAttribute(attribute, value) { 6633 this.setAttributes({ 6634 [attribute]: value 6635 }); 6636 } 6637 getAttribute(attribute) { 6638 return this.attributes.get(attribute); 6639 } 6640 hasAttribute(attribute) { 6641 return this.attributes.has(attribute); 6642 } 6643 getAttributes() { 6644 return this.attributes.toObject(); 6645 } 6646 setAttributes() { 6647 let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 6648 const newAttributes = this.attributes.merge(attributes); 6649 if (!this.attributes.isEqualTo(newAttributes)) { 6650 var _this$previewDelegate, _this$previewDelegate2, _this$delegate, _this$delegate$attach; 6651 this.attributes = newAttributes; 6652 this.didChangeAttributes(); 6653 (_this$previewDelegate = this.previewDelegate) === null || _this$previewDelegate === void 0 || (_this$previewDelegate2 = _this$previewDelegate.attachmentDidChangeAttributes) === null || _this$previewDelegate2 === void 0 || _this$previewDelegate2.call(_this$previewDelegate, this); 6654 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$attach = _this$delegate.attachmentDidChangeAttributes) === null || _this$delegate$attach === void 0 ? void 0 : _this$delegate$attach.call(_this$delegate, this); 6655 } 6656 } 6657 didChangeAttributes() { 6658 if (this.isPreviewable()) { 6659 return this.preloadURL(); 6660 } 6661 } 6662 isPending() { 6663 return this.file != null && !(this.getURL() || this.getHref()); 6664 } 6665 isPreviewable() { 6666 if (this.attributes.has("previewable")) { 6667 return this.attributes.get("previewable"); 6668 } else { 6669 return Attachment.previewablePattern.test(this.getContentType()); 6670 } 6671 } 6672 getType() { 6673 if (this.hasContent()) { 6674 return "content"; 6675 } else if (this.isPreviewable()) { 6676 return "preview"; 6677 } else { 6678 return "file"; 6679 } 6680 } 6681 getURL() { 6682 return this.attributes.get("url"); 6683 } 6684 getHref() { 6685 return this.attributes.get("href"); 6686 } 6687 getFilename() { 6688 return this.attributes.get("filename") || ""; 6689 } 6690 getFilesize() { 6691 return this.attributes.get("filesize"); 6692 } 6693 getFormattedFilesize() { 6694 const filesize = this.attributes.get("filesize"); 6695 if (typeof filesize === "number") { 6696 return file_size_formatting.formatter(filesize); 6697 } else { 6698 return ""; 6699 } 6700 } 6701 getExtension() { 6702 var _this$getFilename$mat; 6703 return (_this$getFilename$mat = this.getFilename().match(/\.(\w+)$/)) === null || _this$getFilename$mat === void 0 ? void 0 : _this$getFilename$mat[1].toLowerCase(); 6704 } 6705 getContentType() { 6706 return this.attributes.get("contentType"); 6707 } 6708 hasContent() { 6709 return this.attributes.has("content"); 6710 } 6711 getContent() { 6712 return this.attributes.get("content"); 6713 } 6714 getWidth() { 6715 return this.attributes.get("width"); 6716 } 6717 getHeight() { 6718 return this.attributes.get("height"); 6719 } 6720 getFile() { 6721 return this.file; 6722 } 6723 setFile(file) { 6724 this.file = file; 6725 if (this.isPreviewable()) { 6726 return this.preloadFile(); 6727 } 6728 } 6729 releaseFile() { 6730 this.releasePreloadedFile(); 6731 this.file = null; 6732 } 6733 getUploadProgress() { 6734 return this.uploadProgress != null ? this.uploadProgress : 0; 6735 } 6736 setUploadProgress(value) { 6737 if (this.uploadProgress !== value) { 6738 var _this$uploadProgressD, _this$uploadProgressD2; 6739 this.uploadProgress = value; 6740 return (_this$uploadProgressD = this.uploadProgressDelegate) === null || _this$uploadProgressD === void 0 || (_this$uploadProgressD2 = _this$uploadProgressD.attachmentDidChangeUploadProgress) === null || _this$uploadProgressD2 === void 0 ? void 0 : _this$uploadProgressD2.call(_this$uploadProgressD, this); 6741 } 6742 } 6743 toJSON() { 6744 return this.getAttributes(); 6745 } 6746 getCacheKey() { 6747 return [super.getCacheKey(...arguments), this.attributes.getCacheKey(), this.getPreviewURL()].join("/"); 6748 } 6749 6750 // Previewable 6751 6752 getPreviewURL() { 6753 return this.previewURL || this.preloadingURL; 6754 } 6755 setPreviewURL(url) { 6756 if (url !== this.getPreviewURL()) { 6757 var _this$previewDelegate3, _this$previewDelegate4, _this$delegate2, _this$delegate2$attac; 6758 this.previewURL = url; 6759 (_this$previewDelegate3 = this.previewDelegate) === null || _this$previewDelegate3 === void 0 || (_this$previewDelegate4 = _this$previewDelegate3.attachmentDidChangeAttributes) === null || _this$previewDelegate4 === void 0 || _this$previewDelegate4.call(_this$previewDelegate3, this); 6760 return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$attac = _this$delegate2.attachmentDidChangePreviewURL) === null || _this$delegate2$attac === void 0 ? void 0 : _this$delegate2$attac.call(_this$delegate2, this); 6761 } 6762 } 6763 preloadURL() { 6764 return this.preload(this.getURL(), this.releaseFile); 6765 } 6766 preloadFile() { 6767 if (this.file) { 6768 this.fileObjectURL = URL.createObjectURL(this.file); 6769 return this.preload(this.fileObjectURL); 6770 } 6771 } 6772 releasePreloadedFile() { 6773 if (this.fileObjectURL) { 6774 URL.revokeObjectURL(this.fileObjectURL); 6775 this.fileObjectURL = null; 6776 } 6777 } 6778 preload(url, callback) { 6779 if (url && url !== this.getPreviewURL()) { 6780 this.preloadingURL = url; 6781 const operation = new ImagePreloadOperation(url); 6782 return operation.then(_ref => { 6783 let { 6784 width, 6785 height 6786 } = _ref; 6787 if (!this.getWidth() || !this.getHeight()) { 6788 this.setAttributes({ 6789 width, 6790 height 6791 }); 6792 } 6793 this.preloadingURL = null; 6794 this.setPreviewURL(url); 6795 return callback === null || callback === void 0 ? void 0 : callback(); 6796 }).catch(() => { 6797 this.preloadingURL = null; 6798 return callback === null || callback === void 0 ? void 0 : callback(); 6799 }); 6800 } 6801 } 6802 } 6803 _defineProperty(Attachment, "previewablePattern", /^image(\/(gif|png|webp|jpe?g)|$)/); 6804 6805 class AttachmentPiece extends Piece { 6806 static fromJSON(pieceJSON) { 6807 return new this(Attachment.fromJSON(pieceJSON.attachment), pieceJSON.attributes); 6808 } 6809 constructor(attachment) { 6810 super(...arguments); 6811 this.attachment = attachment; 6812 this.length = 1; 6813 this.ensureAttachmentExclusivelyHasAttribute("href"); 6814 if (!this.attachment.hasContent()) { 6815 this.removeProhibitedAttributes(); 6816 } 6817 } 6818 ensureAttachmentExclusivelyHasAttribute(attribute) { 6819 if (this.hasAttribute(attribute)) { 6820 if (!this.attachment.hasAttribute(attribute)) { 6821 this.attachment.setAttributes(this.attributes.slice([attribute])); 6822 } 6823 this.attributes = this.attributes.remove(attribute); 6824 } 6825 } 6826 removeProhibitedAttributes() { 6827 const attributes = this.attributes.slice(AttachmentPiece.permittedAttributes); 6828 if (!attributes.isEqualTo(this.attributes)) { 6829 this.attributes = attributes; 6830 } 6831 } 6832 getValue() { 6833 return this.attachment; 6834 } 6835 isSerializable() { 6836 return !this.attachment.isPending(); 6837 } 6838 getCaption() { 6839 return this.attributes.get("caption") || ""; 6840 } 6841 isEqualTo(piece) { 6842 var _piece$attachment; 6843 return super.isEqualTo(piece) && this.attachment.id === (piece === null || piece === void 0 || (_piece$attachment = piece.attachment) === null || _piece$attachment === void 0 ? void 0 : _piece$attachment.id); 6844 } 6845 toString() { 6846 return OBJECT_REPLACEMENT_CHARACTER; 6847 } 6848 toJSON() { 6849 const json = super.toJSON(...arguments); 6850 json.attachment = this.attachment; 6851 return json; 6852 } 6853 getCacheKey() { 6854 return [super.getCacheKey(...arguments), this.attachment.getCacheKey()].join("/"); 6855 } 6856 toConsole() { 6857 return JSON.stringify(this.toString()); 6858 } 6859 } 6860 _defineProperty(AttachmentPiece, "permittedAttributes", ["caption", "presentation"]); 6861 Piece.registerType("attachment", AttachmentPiece); 6862 6863 class StringPiece extends Piece { 6864 static fromJSON(pieceJSON) { 6865 const attributes = { 6866 ...pieceJSON.attributes 6867 }; 6868 if (attributes.href && !purify.isValidAttribute("a", "href", attributes.href)) { 6869 delete attributes.href; 6870 } 6871 return new this(pieceJSON.string, attributes); 6872 } 6873 constructor(string) { 6874 super(...arguments); 6875 this.string = normalizeNewlines(string); 6876 this.length = this.string.length; 6877 } 6878 getValue() { 6879 return this.string; 6880 } 6881 toString() { 6882 return this.string.toString(); 6883 } 6884 isBlockBreak() { 6885 return this.toString() === "\n" && this.getAttribute("blockBreak") === true; 6886 } 6887 toJSON() { 6888 const result = super.toJSON(...arguments); 6889 result.string = this.string; 6890 return result; 6891 } 6892 6893 // Splittable 6894 6895 canBeConsolidatedWith(piece) { 6896 return piece && this.hasSameConstructorAs(piece) && this.hasSameAttributesAsPiece(piece); 6897 } 6898 consolidateWith(piece) { 6899 return new this.constructor(this.toString() + piece.toString(), this.attributes); 6900 } 6901 splitAtOffset(offset) { 6902 let left, right; 6903 if (offset === 0) { 6904 left = null; 6905 right = this; 6906 } else if (offset === this.length) { 6907 left = this; 6908 right = null; 6909 } else { 6910 left = new this.constructor(this.string.slice(0, offset), this.attributes); 6911 right = new this.constructor(this.string.slice(offset), this.attributes); 6912 } 6913 return [left, right]; 6914 } 6915 toConsole() { 6916 let { 6917 string 6918 } = this; 6919 if (string.length > 15) { 6920 string = string.slice(0, 14) + "â¦"; 6921 } 6922 return JSON.stringify(string.toString()); 6923 } 6924 } 6925 Piece.registerType("string", StringPiece); 6926 6927 /* eslint-disable 6928 prefer-const, 6929 */ 6930 class SplittableList extends TrixObject { 6931 static box(objects) { 6932 if (objects instanceof this) { 6933 return objects; 6934 } else { 6935 return new this(objects); 6936 } 6937 } 6938 constructor() { 6939 let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 6940 super(...arguments); 6941 this.objects = objects.slice(0); 6942 this.length = this.objects.length; 6943 } 6944 indexOf(object) { 6945 return this.objects.indexOf(object); 6946 } 6947 splice() { 6948 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 6949 args[_key] = arguments[_key]; 6950 } 6951 return new this.constructor(spliceArray(this.objects, ...args)); 6952 } 6953 eachObject(callback) { 6954 return this.objects.map((object, index) => callback(object, index)); 6955 } 6956 insertObjectAtIndex(object, index) { 6957 return this.splice(index, 0, object); 6958 } 6959 insertSplittableListAtIndex(splittableList, index) { 6960 return this.splice(index, 0, ...splittableList.objects); 6961 } 6962 insertSplittableListAtPosition(splittableList, position) { 6963 const [objects, index] = this.splitObjectAtPosition(position); 6964 return new this.constructor(objects).insertSplittableListAtIndex(splittableList, index); 6965 } 6966 editObjectAtIndex(index, callback) { 6967 return this.replaceObjectAtIndex(callback(this.objects[index]), index); 6968 } 6969 replaceObjectAtIndex(object, index) { 6970 return this.splice(index, 1, object); 6971 } 6972 removeObjectAtIndex(index) { 6973 return this.splice(index, 1); 6974 } 6975 getObjectAtIndex(index) { 6976 return this.objects[index]; 6977 } 6978 getSplittableListInRange(range) { 6979 const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range); 6980 return new this.constructor(objects.slice(leftIndex, rightIndex + 1)); 6981 } 6982 selectSplittableList(test) { 6983 const objects = this.objects.filter(object => test(object)); 6984 return new this.constructor(objects); 6985 } 6986 removeObjectsInRange(range) { 6987 const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range); 6988 return new this.constructor(objects).splice(leftIndex, rightIndex - leftIndex + 1); 6989 } 6990 transformObjectsInRange(range, transform) { 6991 const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range); 6992 const transformedObjects = objects.map((object, index) => leftIndex <= index && index <= rightIndex ? transform(object) : object); 6993 return new this.constructor(transformedObjects); 6994 } 6995 splitObjectsAtRange(range) { 6996 let rightOuterIndex; 6997 let [objects, leftInnerIndex, offset] = this.splitObjectAtPosition(startOfRange(range)); 6998 [objects, rightOuterIndex] = new this.constructor(objects).splitObjectAtPosition(endOfRange(range) + offset); 6999 return [objects, leftInnerIndex, rightOuterIndex - 1]; 7000 } 7001 getObjectAtPosition(position) { 7002 const { 7003 index 7004 } = this.findIndexAndOffsetAtPosition(position); 7005 return this.objects[index]; 7006 } 7007 splitObjectAtPosition(position) { 7008 let splitIndex, splitOffset; 7009 const { 7010 index, 7011 offset 7012 } = this.findIndexAndOffsetAtPosition(position); 7013 const objects = this.objects.slice(0); 7014 if (index != null) { 7015 if (offset === 0) { 7016 splitIndex = index; 7017 splitOffset = 0; 7018 } else { 7019 const object = this.getObjectAtIndex(index); 7020 const [leftObject, rightObject] = object.splitAtOffset(offset); 7021 objects.splice(index, 1, leftObject, rightObject); 7022 splitIndex = index + 1; 7023 splitOffset = leftObject.getLength() - offset; 7024 } 7025 } else { 7026 splitIndex = objects.length; 7027 splitOffset = 0; 7028 } 7029 return [objects, splitIndex, splitOffset]; 7030 } 7031 consolidate() { 7032 const objects = []; 7033 let pendingObject = this.objects[0]; 7034 this.objects.slice(1).forEach(object => { 7035 var _pendingObject$canBeC, _pendingObject; 7036 if ((_pendingObject$canBeC = (_pendingObject = pendingObject).canBeConsolidatedWith) !== null && _pendingObject$canBeC !== void 0 && _pendingObject$canBeC.call(_pendingObject, object)) { 7037 pendingObject = pendingObject.consolidateWith(object); 7038 } else { 7039 objects.push(pendingObject); 7040 pendingObject = object; 7041 } 7042 }); 7043 if (pendingObject) { 7044 objects.push(pendingObject); 7045 } 7046 return new this.constructor(objects); 7047 } 7048 consolidateFromIndexToIndex(startIndex, endIndex) { 7049 const objects = this.objects.slice(0); 7050 const objectsInRange = objects.slice(startIndex, endIndex + 1); 7051 const consolidatedInRange = new this.constructor(objectsInRange).consolidate().toArray(); 7052 return this.splice(startIndex, objectsInRange.length, ...consolidatedInRange); 7053 } 7054 findIndexAndOffsetAtPosition(position) { 7055 let index; 7056 let currentPosition = 0; 7057 for (index = 0; index < this.objects.length; index++) { 7058 const object = this.objects[index]; 7059 const nextPosition = currentPosition + object.getLength(); 7060 if (currentPosition <= position && position < nextPosition) { 7061 return { 7062 index, 7063 offset: position - currentPosition 7064 }; 7065 } 7066 currentPosition = nextPosition; 7067 } 7068 return { 7069 index: null, 7070 offset: null 7071 }; 7072 } 7073 findPositionAtIndexAndOffset(index, offset) { 7074 let position = 0; 7075 for (let currentIndex = 0; currentIndex < this.objects.length; currentIndex++) { 7076 const object = this.objects[currentIndex]; 7077 if (currentIndex < index) { 7078 position += object.getLength(); 7079 } else if (currentIndex === index) { 7080 position += offset; 7081 break; 7082 } 7083 } 7084 return position; 7085 } 7086 getEndPosition() { 7087 if (this.endPosition == null) { 7088 this.endPosition = 0; 7089 this.objects.forEach(object => this.endPosition += object.getLength()); 7090 } 7091 return this.endPosition; 7092 } 7093 toString() { 7094 return this.objects.join(""); 7095 } 7096 toArray() { 7097 return this.objects.slice(0); 7098 } 7099 toJSON() { 7100 return this.toArray(); 7101 } 7102 isEqualTo(splittableList) { 7103 return super.isEqualTo(...arguments) || objectArraysAreEqual(this.objects, splittableList === null || splittableList === void 0 ? void 0 : splittableList.objects); 7104 } 7105 contentsForInspection() { 7106 return { 7107 objects: "[".concat(this.objects.map(object => object.inspect()).join(", "), "]") 7108 }; 7109 } 7110 } 7111 const objectArraysAreEqual = function (left) { 7112 let right = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; 7113 if (left.length !== right.length) { 7114 return false; 7115 } 7116 let result = true; 7117 for (let index = 0; index < left.length; index++) { 7118 const object = left[index]; 7119 if (result && !object.isEqualTo(right[index])) { 7120 result = false; 7121 } 7122 } 7123 return result; 7124 }; 7125 const startOfRange = range => range[0]; 7126 const endOfRange = range => range[1]; 7127 7128 class Text extends TrixObject { 7129 static textForAttachmentWithAttributes(attachment, attributes) { 7130 const piece = new AttachmentPiece(attachment, attributes); 7131 return new this([piece]); 7132 } 7133 static textForStringWithAttributes(string, attributes) { 7134 const piece = new StringPiece(string, attributes); 7135 return new this([piece]); 7136 } 7137 static fromJSON(textJSON) { 7138 const pieces = Array.from(textJSON).map(pieceJSON => Piece.fromJSON(pieceJSON)); 7139 return new this(pieces); 7140 } 7141 constructor() { 7142 let pieces = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 7143 super(...arguments); 7144 const notEmpty = pieces.filter(piece => !piece.isEmpty()); 7145 this.pieceList = new SplittableList(notEmpty); 7146 } 7147 copy() { 7148 return this.copyWithPieceList(this.pieceList); 7149 } 7150 copyWithPieceList(pieceList) { 7151 return new this.constructor(pieceList.consolidate().toArray()); 7152 } 7153 copyUsingObjectMap(objectMap) { 7154 const pieces = this.getPieces().map(piece => objectMap.find(piece) || piece); 7155 return new this.constructor(pieces); 7156 } 7157 appendText(text) { 7158 return this.insertTextAtPosition(text, this.getLength()); 7159 } 7160 insertTextAtPosition(text, position) { 7161 return this.copyWithPieceList(this.pieceList.insertSplittableListAtPosition(text.pieceList, position)); 7162 } 7163 removeTextAtRange(range) { 7164 return this.copyWithPieceList(this.pieceList.removeObjectsInRange(range)); 7165 } 7166 replaceTextAtRange(text, range) { 7167 return this.removeTextAtRange(range).insertTextAtPosition(text, range[0]); 7168 } 7169 moveTextFromRangeToPosition(range, position) { 7170 if (range[0] <= position && position <= range[1]) return; 7171 const text = this.getTextAtRange(range); 7172 const length = text.getLength(); 7173 if (range[0] < position) { 7174 position -= length; 7175 } 7176 return this.removeTextAtRange(range).insertTextAtPosition(text, position); 7177 } 7178 addAttributeAtRange(attribute, value, range) { 7179 const attributes = {}; 7180 attributes[attribute] = value; 7181 return this.addAttributesAtRange(attributes, range); 7182 } 7183 addAttributesAtRange(attributes, range) { 7184 return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithAdditionalAttributes(attributes))); 7185 } 7186 removeAttributeAtRange(attribute, range) { 7187 return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithoutAttribute(attribute))); 7188 } 7189 setAttributesAtRange(attributes, range) { 7190 return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithAttributes(attributes))); 7191 } 7192 getAttributesAtPosition(position) { 7193 var _this$pieceList$getOb; 7194 return ((_this$pieceList$getOb = this.pieceList.getObjectAtPosition(position)) === null || _this$pieceList$getOb === void 0 ? void 0 : _this$pieceList$getOb.getAttributes()) || {}; 7195 } 7196 getCommonAttributes() { 7197 const objects = Array.from(this.pieceList.toArray()).map(piece => piece.getAttributes()); 7198 return Hash.fromCommonAttributesOfObjects(objects).toObject(); 7199 } 7200 getCommonAttributesAtRange(range) { 7201 return this.getTextAtRange(range).getCommonAttributes() || {}; 7202 } 7203 getExpandedRangeForAttributeAtOffset(attributeName, offset) { 7204 let right; 7205 let left = right = offset; 7206 const length = this.getLength(); 7207 while (left > 0 && this.getCommonAttributesAtRange([left - 1, right])[attributeName]) { 7208 left--; 7209 } 7210 while (right < length && this.getCommonAttributesAtRange([offset, right + 1])[attributeName]) { 7211 right++; 7212 } 7213 return [left, right]; 7214 } 7215 getTextAtRange(range) { 7216 return this.copyWithPieceList(this.pieceList.getSplittableListInRange(range)); 7217 } 7218 getStringAtRange(range) { 7219 return this.pieceList.getSplittableListInRange(range).toString(); 7220 } 7221 getStringAtPosition(position) { 7222 return this.getStringAtRange([position, position + 1]); 7223 } 7224 startsWithString(string) { 7225 return this.getStringAtRange([0, string.length]) === string; 7226 } 7227 endsWithString(string) { 7228 const length = this.getLength(); 7229 return this.getStringAtRange([length - string.length, length]) === string; 7230 } 7231 getAttachmentPieces() { 7232 return this.pieceList.toArray().filter(piece => !!piece.attachment); 7233 } 7234 getAttachments() { 7235 return this.getAttachmentPieces().map(piece => piece.attachment); 7236 } 7237 getAttachmentAndPositionById(attachmentId) { 7238 let position = 0; 7239 for (const piece of this.pieceList.toArray()) { 7240 var _piece$attachment; 7241 if (((_piece$attachment = piece.attachment) === null || _piece$attachment === void 0 ? void 0 : _piece$attachment.id) === attachmentId) { 7242 return { 7243 attachment: piece.attachment, 7244 position 7245 }; 7246 } 7247 position += piece.length; 7248 } 7249 return { 7250 attachment: null, 7251 position: null 7252 }; 7253 } 7254 getAttachmentById(attachmentId) { 7255 const { 7256 attachment 7257 } = this.getAttachmentAndPositionById(attachmentId); 7258 return attachment; 7259 } 7260 getRangeOfAttachment(attachment) { 7261 const attachmentAndPosition = this.getAttachmentAndPositionById(attachment.id); 7262 const position = attachmentAndPosition.position; 7263 attachment = attachmentAndPosition.attachment; 7264 if (attachment) { 7265 return [position, position + 1]; 7266 } 7267 } 7268 updateAttributesForAttachment(attributes, attachment) { 7269 const range = this.getRangeOfAttachment(attachment); 7270 if (range) { 7271 return this.addAttributesAtRange(attributes, range); 7272 } else { 7273 return this; 7274 } 7275 } 7276 getLength() { 7277 return this.pieceList.getEndPosition(); 7278 } 7279 isEmpty() { 7280 return this.getLength() === 0; 7281 } 7282 isEqualTo(text) { 7283 var _text$pieceList; 7284 return super.isEqualTo(text) || (text === null || text === void 0 || (_text$pieceList = text.pieceList) === null || _text$pieceList === void 0 ? void 0 : _text$pieceList.isEqualTo(this.pieceList)); 7285 } 7286 isBlockBreak() { 7287 return this.getLength() === 1 && this.pieceList.getObjectAtIndex(0).isBlockBreak(); 7288 } 7289 eachPiece(callback) { 7290 return this.pieceList.eachObject(callback); 7291 } 7292 getPieces() { 7293 return this.pieceList.toArray(); 7294 } 7295 getPieceAtPosition(position) { 7296 return this.pieceList.getObjectAtPosition(position); 7297 } 7298 contentsForInspection() { 7299 return { 7300 pieceList: this.pieceList.inspect() 7301 }; 7302 } 7303 toSerializableText() { 7304 const pieceList = this.pieceList.selectSplittableList(piece => piece.isSerializable()); 7305 return this.copyWithPieceList(pieceList); 7306 } 7307 toString() { 7308 return this.pieceList.toString(); 7309 } 7310 toJSON() { 7311 return this.pieceList.toJSON(); 7312 } 7313 toConsole() { 7314 return JSON.stringify(this.pieceList.toArray().map(piece => JSON.parse(piece.toConsole()))); 7315 } 7316 7317 // BIDI 7318 7319 getDirection() { 7320 return getDirection(this.toString()); 7321 } 7322 isRTL() { 7323 return this.getDirection() === "rtl"; 7324 } 7325 } 7326 7327 class Block extends TrixObject { 7328 static fromJSON(blockJSON) { 7329 const text = Text.fromJSON(blockJSON.text); 7330 return new this(text, blockJSON.attributes, blockJSON.htmlAttributes); 7331 } 7332 constructor(text, attributes, htmlAttributes) { 7333 super(...arguments); 7334 this.text = applyBlockBreakToText(text || new Text()); 7335 this.attributes = attributes || []; 7336 this.htmlAttributes = htmlAttributes || {}; 7337 } 7338 isEmpty() { 7339 return this.text.isBlockBreak(); 7340 } 7341 isEqualTo(block) { 7342 if (super.isEqualTo(block)) return true; 7343 return this.text.isEqualTo(block === null || block === void 0 ? void 0 : block.text) && arraysAreEqual(this.attributes, block === null || block === void 0 ? void 0 : block.attributes) && objectsAreEqual(this.htmlAttributes, block === null || block === void 0 ? void 0 : block.htmlAttributes); 7344 } 7345 copyWithText(text) { 7346 return new Block(text, this.attributes, this.htmlAttributes); 7347 } 7348 copyWithoutText() { 7349 return this.copyWithText(null); 7350 } 7351 copyWithAttributes(attributes) { 7352 return new Block(this.text, attributes, this.htmlAttributes); 7353 } 7354 copyWithoutAttributes() { 7355 return this.copyWithAttributes(null); 7356 } 7357 copyUsingObjectMap(objectMap) { 7358 const mappedText = objectMap.find(this.text); 7359 if (mappedText) { 7360 return this.copyWithText(mappedText); 7361 } else { 7362 return this.copyWithText(this.text.copyUsingObjectMap(objectMap)); 7363 } 7364 } 7365 addAttribute(attribute) { 7366 const attributes = this.attributes.concat(expandAttribute(attribute)); 7367 return this.copyWithAttributes(attributes); 7368 } 7369 addHTMLAttribute(attribute, value) { 7370 const htmlAttributes = Object.assign({}, this.htmlAttributes, { 7371 [attribute]: value 7372 }); 7373 return new Block(this.text, this.attributes, htmlAttributes); 7374 } 7375 removeAttribute(attribute) { 7376 const { 7377 listAttribute 7378 } = getBlockConfig(attribute); 7379 const attributes = removeLastValue(removeLastValue(this.attributes, attribute), listAttribute); 7380 return this.copyWithAttributes(attributes); 7381 } 7382 removeLastAttribute() { 7383 return this.removeAttribute(this.getLastAttribute()); 7384 } 7385 getLastAttribute() { 7386 return getLastElement(this.attributes); 7387 } 7388 getAttributes() { 7389 return this.attributes.slice(0); 7390 } 7391 getAttributeLevel() { 7392 return this.attributes.length; 7393 } 7394 getAttributeAtLevel(level) { 7395 return this.attributes[level - 1]; 7396 } 7397 hasAttribute(attributeName) { 7398 return this.attributes.includes(attributeName); 7399 } 7400 hasAttributes() { 7401 return this.getAttributeLevel() > 0; 7402 } 7403 getLastNestableAttribute() { 7404 return getLastElement(this.getNestableAttributes()); 7405 } 7406 getNestableAttributes() { 7407 return this.attributes.filter(attribute => getBlockConfig(attribute).nestable); 7408 } 7409 getNestingLevel() { 7410 return this.getNestableAttributes().length; 7411 } 7412 decreaseNestingLevel() { 7413 const attribute = this.getLastNestableAttribute(); 7414 if (attribute) { 7415 return this.removeAttribute(attribute); 7416 } else { 7417 return this; 7418 } 7419 } 7420 increaseNestingLevel() { 7421 const attribute = this.getLastNestableAttribute(); 7422 if (attribute) { 7423 const index = this.attributes.lastIndexOf(attribute); 7424 const attributes = spliceArray(this.attributes, index + 1, 0, ...expandAttribute(attribute)); 7425 return this.copyWithAttributes(attributes); 7426 } else { 7427 return this; 7428 } 7429 } 7430 getListItemAttributes() { 7431 return this.attributes.filter(attribute => getBlockConfig(attribute).listAttribute); 7432 } 7433 isListItem() { 7434 var _getBlockConfig; 7435 return (_getBlockConfig = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.listAttribute; 7436 } 7437 isTerminalBlock() { 7438 var _getBlockConfig2; 7439 return (_getBlockConfig2 = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig2 === void 0 ? void 0 : _getBlockConfig2.terminal; 7440 } 7441 breaksOnReturn() { 7442 var _getBlockConfig3; 7443 return (_getBlockConfig3 = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig3 === void 0 ? void 0 : _getBlockConfig3.breakOnReturn; 7444 } 7445 findLineBreakInDirectionFromPosition(direction, position) { 7446 const string = this.toString(); 7447 let result; 7448 switch (direction) { 7449 case "forward": 7450 result = string.indexOf("\n", position); 7451 break; 7452 case "backward": 7453 result = string.slice(0, position).lastIndexOf("\n"); 7454 } 7455 if (result !== -1) { 7456 return result; 7457 } 7458 } 7459 contentsForInspection() { 7460 return { 7461 text: this.text.inspect(), 7462 attributes: this.attributes 7463 }; 7464 } 7465 toString() { 7466 return this.text.toString(); 7467 } 7468 toJSON() { 7469 return { 7470 text: this.text, 7471 attributes: this.attributes, 7472 htmlAttributes: this.htmlAttributes 7473 }; 7474 } 7475 7476 // BIDI 7477 7478 getDirection() { 7479 return this.text.getDirection(); 7480 } 7481 isRTL() { 7482 return this.text.isRTL(); 7483 } 7484 7485 // Splittable 7486 7487 getLength() { 7488 return this.text.getLength(); 7489 } 7490 canBeConsolidatedWith(block) { 7491 return !this.hasAttributes() && !block.hasAttributes() && this.getDirection() === block.getDirection(); 7492 } 7493 consolidateWith(block) { 7494 const newlineText = Text.textForStringWithAttributes("\n"); 7495 const text = this.getTextWithoutBlockBreak().appendText(newlineText); 7496 return this.copyWithText(text.appendText(block.text)); 7497 } 7498 splitAtOffset(offset) { 7499 let left, right; 7500 if (offset === 0) { 7501 left = null; 7502 right = this; 7503 } else if (offset === this.getLength()) { 7504 left = this; 7505 right = null; 7506 } else { 7507 left = this.copyWithText(this.text.getTextAtRange([0, offset])); 7508 right = this.copyWithText(this.text.getTextAtRange([offset, this.getLength()])); 7509 } 7510 return [left, right]; 7511 } 7512 getBlockBreakPosition() { 7513 return this.text.getLength() - 1; 7514 } 7515 getTextWithoutBlockBreak() { 7516 if (textEndsInBlockBreak(this.text)) { 7517 return this.text.getTextAtRange([0, this.getBlockBreakPosition()]); 7518 } else { 7519 return this.text.copy(); 7520 } 7521 } 7522 7523 // Grouping 7524 7525 canBeGrouped(depth) { 7526 return this.attributes[depth]; 7527 } 7528 canBeGroupedWith(otherBlock, depth) { 7529 const otherAttributes = otherBlock.getAttributes(); 7530 const otherAttribute = otherAttributes[depth]; 7531 const attribute = this.attributes[depth]; 7532 return attribute === otherAttribute && !(getBlockConfig(attribute).group === false && !getListAttributeNames().includes(otherAttributes[depth + 1])) && (this.getDirection() === otherBlock.getDirection() || otherBlock.isEmpty()); 7533 } 7534 } 7535 7536 // Block breaks 7537 7538 const applyBlockBreakToText = function (text) { 7539 text = unmarkExistingInnerBlockBreaksInText(text); 7540 text = addBlockBreakToText(text); 7541 return text; 7542 }; 7543 const unmarkExistingInnerBlockBreaksInText = function (text) { 7544 let modified = false; 7545 const pieces = text.getPieces(); 7546 let innerPieces = pieces.slice(0, pieces.length - 1); 7547 const lastPiece = pieces[pieces.length - 1]; 7548 if (!lastPiece) return text; 7549 innerPieces = innerPieces.map(piece => { 7550 if (piece.isBlockBreak()) { 7551 modified = true; 7552 return unmarkBlockBreakPiece(piece); 7553 } else { 7554 return piece; 7555 } 7556 }); 7557 if (modified) { 7558 return new Text([...innerPieces, lastPiece]); 7559 } else { 7560 return text; 7561 } 7562 }; 7563 const blockBreakText = Text.textForStringWithAttributes("\n", { 7564 blockBreak: true 7565 }); 7566 const addBlockBreakToText = function (text) { 7567 if (textEndsInBlockBreak(text)) { 7568 return text; 7569 } else { 7570 return text.appendText(blockBreakText); 7571 } 7572 }; 7573 const textEndsInBlockBreak = function (text) { 7574 const length = text.getLength(); 7575 if (length === 0) { 7576 return false; 7577 } 7578 const endText = text.getTextAtRange([length - 1, length]); 7579 return endText.isBlockBreak(); 7580 }; 7581 const unmarkBlockBreakPiece = piece => piece.copyWithoutAttribute("blockBreak"); 7582 7583 // Attributes 7584 7585 const expandAttribute = function (attribute) { 7586 const { 7587 listAttribute 7588 } = getBlockConfig(attribute); 7589 if (listAttribute) { 7590 return [listAttribute, attribute]; 7591 } else { 7592 return [attribute]; 7593 } 7594 }; 7595 7596 // Array helpers 7597 7598 const getLastElement = array => array.slice(-1)[0]; 7599 const removeLastValue = function (array, value) { 7600 const index = array.lastIndexOf(value); 7601 if (index === -1) { 7602 return array; 7603 } else { 7604 return spliceArray(array, index, 1); 7605 } 7606 }; 7607 7608 class Document extends TrixObject { 7609 static fromJSON(documentJSON) { 7610 const blocks = Array.from(documentJSON).map(blockJSON => Block.fromJSON(blockJSON)); 7611 return new this(blocks); 7612 } 7613 static fromString(string, textAttributes) { 7614 const text = Text.textForStringWithAttributes(string, textAttributes); 7615 return new this([new Block(text)]); 7616 } 7617 constructor() { 7618 let blocks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 7619 super(...arguments); 7620 if (blocks.length === 0) { 7621 blocks = [new Block()]; 7622 } 7623 this.blockList = SplittableList.box(blocks); 7624 } 7625 isEmpty() { 7626 const block = this.getBlockAtIndex(0); 7627 return this.blockList.length === 1 && block.isEmpty() && !block.hasAttributes(); 7628 } 7629 copy() { 7630 let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 7631 const blocks = options.consolidateBlocks ? this.blockList.consolidate().toArray() : this.blockList.toArray(); 7632 return new this.constructor(blocks); 7633 } 7634 copyUsingObjectsFromDocument(sourceDocument) { 7635 const objectMap = new ObjectMap(sourceDocument.getObjects()); 7636 return this.copyUsingObjectMap(objectMap); 7637 } 7638 copyUsingObjectMap(objectMap) { 7639 const blocks = this.getBlocks().map(block => { 7640 const mappedBlock = objectMap.find(block); 7641 return mappedBlock || block.copyUsingObjectMap(objectMap); 7642 }); 7643 return new this.constructor(blocks); 7644 } 7645 copyWithBaseBlockAttributes() { 7646 let blockAttributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 7647 const blocks = this.getBlocks().map(block => { 7648 const attributes = blockAttributes.concat(block.getAttributes()); 7649 return block.copyWithAttributes(attributes); 7650 }); 7651 return new this.constructor(blocks); 7652 } 7653 replaceBlock(oldBlock, newBlock) { 7654 const index = this.blockList.indexOf(oldBlock); 7655 if (index === -1) { 7656 return this; 7657 } 7658 return new this.constructor(this.blockList.replaceObjectAtIndex(newBlock, index)); 7659 } 7660 insertDocumentAtRange(document, range) { 7661 const { 7662 blockList 7663 } = document; 7664 range = normalizeRange(range); 7665 let [position] = range; 7666 const { 7667 index, 7668 offset 7669 } = this.locationFromPosition(position); 7670 let result = this; 7671 const block = this.getBlockAtPosition(position); 7672 if (rangeIsCollapsed(range) && block.isEmpty() && !block.hasAttributes()) { 7673 result = new this.constructor(result.blockList.removeObjectAtIndex(index)); 7674 } else if (block.getBlockBreakPosition() === offset) { 7675 position++; 7676 } 7677 result = result.removeTextAtRange(range); 7678 return new this.constructor(result.blockList.insertSplittableListAtPosition(blockList, position)); 7679 } 7680 mergeDocumentAtRange(document, range) { 7681 let formattedDocument, result; 7682 range = normalizeRange(range); 7683 const [startPosition] = range; 7684 const startLocation = this.locationFromPosition(startPosition); 7685 const blockAttributes = this.getBlockAtIndex(startLocation.index).getAttributes(); 7686 const baseBlockAttributes = document.getBaseBlockAttributes(); 7687 const trailingBlockAttributes = blockAttributes.slice(-baseBlockAttributes.length); 7688 if (arraysAreEqual(baseBlockAttributes, trailingBlockAttributes)) { 7689 const leadingBlockAttributes = blockAttributes.slice(0, -baseBlockAttributes.length); 7690 formattedDocument = document.copyWithBaseBlockAttributes(leadingBlockAttributes); 7691 } else { 7692 formattedDocument = document.copy({ 7693 consolidateBlocks: true 7694 }).copyWithBaseBlockAttributes(blockAttributes); 7695 } 7696 const blockCount = formattedDocument.getBlockCount(); 7697 const firstBlock = formattedDocument.getBlockAtIndex(0); 7698 if (arraysAreEqual(blockAttributes, firstBlock.getAttributes())) { 7699 const firstText = firstBlock.getTextWithoutBlockBreak(); 7700 result = this.insertTextAtRange(firstText, range); 7701 if (blockCount > 1) { 7702 formattedDocument = new this.constructor(formattedDocument.getBlocks().slice(1)); 7703 const position = startPosition + firstText.getLength(); 7704 result = result.insertDocumentAtRange(formattedDocument, position); 7705 } 7706 } else { 7707 result = this.insertDocumentAtRange(formattedDocument, range); 7708 } 7709 return result; 7710 } 7711 insertTextAtRange(text, range) { 7712 range = normalizeRange(range); 7713 const [startPosition] = range; 7714 const { 7715 index, 7716 offset 7717 } = this.locationFromPosition(startPosition); 7718 const document = this.removeTextAtRange(range); 7719 return new this.constructor(document.blockList.editObjectAtIndex(index, block => block.copyWithText(block.text.insertTextAtPosition(text, offset)))); 7720 } 7721 removeTextAtRange(range) { 7722 let blocks; 7723 range = normalizeRange(range); 7724 const [leftPosition, rightPosition] = range; 7725 if (rangeIsCollapsed(range)) { 7726 return this; 7727 } 7728 const [leftLocation, rightLocation] = Array.from(this.locationRangeFromRange(range)); 7729 const leftIndex = leftLocation.index; 7730 const leftOffset = leftLocation.offset; 7731 const leftBlock = this.getBlockAtIndex(leftIndex); 7732 const rightIndex = rightLocation.index; 7733 const rightOffset = rightLocation.offset; 7734 const rightBlock = this.getBlockAtIndex(rightIndex); 7735 const removeRightNewline = rightPosition - leftPosition === 1 && leftBlock.getBlockBreakPosition() === leftOffset && rightBlock.getBlockBreakPosition() !== rightOffset && rightBlock.text.getStringAtPosition(rightOffset) === "\n"; 7736 if (removeRightNewline) { 7737 blocks = this.blockList.editObjectAtIndex(rightIndex, block => block.copyWithText(block.text.removeTextAtRange([rightOffset, rightOffset + 1]))); 7738 } else { 7739 let block; 7740 const leftText = leftBlock.text.getTextAtRange([0, leftOffset]); 7741 const rightText = rightBlock.text.getTextAtRange([rightOffset, rightBlock.getLength()]); 7742 const text = leftText.appendText(rightText); 7743 const removingLeftBlock = leftIndex !== rightIndex && leftOffset === 0; 7744 const useRightBlock = removingLeftBlock && leftBlock.getAttributeLevel() >= rightBlock.getAttributeLevel(); 7745 if (useRightBlock) { 7746 block = rightBlock.copyWithText(text); 7747 } else { 7748 block = leftBlock.copyWithText(text); 7749 } 7750 const affectedBlockCount = rightIndex + 1 - leftIndex; 7751 blocks = this.blockList.splice(leftIndex, affectedBlockCount, block); 7752 } 7753 return new this.constructor(blocks); 7754 } 7755 moveTextFromRangeToPosition(range, position) { 7756 let text; 7757 range = normalizeRange(range); 7758 const [startPosition, endPosition] = range; 7759 if (startPosition <= position && position <= endPosition) { 7760 return this; 7761 } 7762 let document = this.getDocumentAtRange(range); 7763 let result = this.removeTextAtRange(range); 7764 const movingRightward = startPosition < position; 7765 if (movingRightward) { 7766 position -= document.getLength(); 7767 } 7768 const [firstBlock, ...blocks] = document.getBlocks(); 7769 if (blocks.length === 0) { 7770 text = firstBlock.getTextWithoutBlockBreak(); 7771 if (movingRightward) { 7772 position += 1; 7773 } 7774 } else { 7775 text = firstBlock.text; 7776 } 7777 result = result.insertTextAtRange(text, position); 7778 if (blocks.length === 0) { 7779 return result; 7780 } 7781 document = new this.constructor(blocks); 7782 position += text.getLength(); 7783 return result.insertDocumentAtRange(document, position); 7784 } 7785 addAttributeAtRange(attribute, value, range) { 7786 let { 7787 blockList 7788 } = this; 7789 this.eachBlockAtRange(range, (block, textRange, index) => blockList = blockList.editObjectAtIndex(index, function () { 7790 if (getBlockConfig(attribute)) { 7791 return block.addAttribute(attribute, value); 7792 } else { 7793 if (textRange[0] === textRange[1]) { 7794 return block; 7795 } else { 7796 return block.copyWithText(block.text.addAttributeAtRange(attribute, value, textRange)); 7797 } 7798 } 7799 })); 7800 return new this.constructor(blockList); 7801 } 7802 addAttribute(attribute, value) { 7803 let { 7804 blockList 7805 } = this; 7806 this.eachBlock((block, index) => blockList = blockList.editObjectAtIndex(index, () => block.addAttribute(attribute, value))); 7807 return new this.constructor(blockList); 7808 } 7809 removeAttributeAtRange(attribute, range) { 7810 let { 7811 blockList 7812 } = this; 7813 this.eachBlockAtRange(range, function (block, textRange, index) { 7814 if (getBlockConfig(attribute)) { 7815 blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(attribute)); 7816 } else if (textRange[0] !== textRange[1]) { 7817 blockList = blockList.editObjectAtIndex(index, () => block.copyWithText(block.text.removeAttributeAtRange(attribute, textRange))); 7818 } 7819 }); 7820 return new this.constructor(blockList); 7821 } 7822 updateAttributesForAttachment(attributes, attachment) { 7823 const range = this.getRangeOfAttachment(attachment); 7824 const [startPosition] = Array.from(range); 7825 const { 7826 index 7827 } = this.locationFromPosition(startPosition); 7828 const text = this.getTextAtIndex(index); 7829 return new this.constructor(this.blockList.editObjectAtIndex(index, block => block.copyWithText(text.updateAttributesForAttachment(attributes, attachment)))); 7830 } 7831 removeAttributeForAttachment(attribute, attachment) { 7832 const range = this.getRangeOfAttachment(attachment); 7833 return this.removeAttributeAtRange(attribute, range); 7834 } 7835 setHTMLAttributeAtPosition(position, name, value) { 7836 const block = this.getBlockAtPosition(position); 7837 const updatedBlock = block.addHTMLAttribute(name, value); 7838 return this.replaceBlock(block, updatedBlock); 7839 } 7840 insertBlockBreakAtRange(range) { 7841 let blocks; 7842 range = normalizeRange(range); 7843 const [startPosition] = range; 7844 const { 7845 offset 7846 } = this.locationFromPosition(startPosition); 7847 const document = this.removeTextAtRange(range); 7848 if (offset === 0) { 7849 blocks = [new Block()]; 7850 } 7851 return new this.constructor(document.blockList.insertSplittableListAtPosition(new SplittableList(blocks), startPosition)); 7852 } 7853 applyBlockAttributeAtRange(attributeName, value, range) { 7854 const expanded = this.expandRangeToLineBreaksAndSplitBlocks(range); 7855 let document = expanded.document; 7856 range = expanded.range; 7857 const blockConfig = getBlockConfig(attributeName); 7858 if (blockConfig.listAttribute) { 7859 document = document.removeLastListAttributeAtRange(range, { 7860 exceptAttributeName: attributeName 7861 }); 7862 const converted = document.convertLineBreaksToBlockBreaksInRange(range); 7863 document = converted.document; 7864 range = converted.range; 7865 } else if (blockConfig.exclusive) { 7866 document = document.removeBlockAttributesAtRange(range); 7867 } else if (blockConfig.terminal) { 7868 document = document.removeLastTerminalAttributeAtRange(range); 7869 } else { 7870 document = document.consolidateBlocksAtRange(range); 7871 } 7872 return document.addAttributeAtRange(attributeName, value, range); 7873 } 7874 removeLastListAttributeAtRange(range) { 7875 let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 7876 let { 7877 blockList 7878 } = this; 7879 this.eachBlockAtRange(range, function (block, textRange, index) { 7880 const lastAttributeName = block.getLastAttribute(); 7881 if (!lastAttributeName) { 7882 return; 7883 } 7884 if (!getBlockConfig(lastAttributeName).listAttribute) { 7885 return; 7886 } 7887 if (lastAttributeName === options.exceptAttributeName) { 7888 return; 7889 } 7890 blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(lastAttributeName)); 7891 }); 7892 return new this.constructor(blockList); 7893 } 7894 removeLastTerminalAttributeAtRange(range) { 7895 let { 7896 blockList 7897 } = this; 7898 this.eachBlockAtRange(range, function (block, textRange, index) { 7899 const lastAttributeName = block.getLastAttribute(); 7900 if (!lastAttributeName) { 7901 return; 7902 } 7903 if (!getBlockConfig(lastAttributeName).terminal) { 7904 return; 7905 } 7906 blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(lastAttributeName)); 7907 }); 7908 return new this.constructor(blockList); 7909 } 7910 removeBlockAttributesAtRange(range) { 7911 let { 7912 blockList 7913 } = this; 7914 this.eachBlockAtRange(range, function (block, textRange, index) { 7915 if (block.hasAttributes()) { 7916 blockList = blockList.editObjectAtIndex(index, () => block.copyWithoutAttributes()); 7917 } 7918 }); 7919 return new this.constructor(blockList); 7920 } 7921 expandRangeToLineBreaksAndSplitBlocks(range) { 7922 let position; 7923 range = normalizeRange(range); 7924 let [startPosition, endPosition] = range; 7925 const startLocation = this.locationFromPosition(startPosition); 7926 const endLocation = this.locationFromPosition(endPosition); 7927 let document = this; 7928 const startBlock = document.getBlockAtIndex(startLocation.index); 7929 startLocation.offset = startBlock.findLineBreakInDirectionFromPosition("backward", startLocation.offset); 7930 if (startLocation.offset != null) { 7931 position = document.positionFromLocation(startLocation); 7932 document = document.insertBlockBreakAtRange([position, position + 1]); 7933 endLocation.index += 1; 7934 endLocation.offset -= document.getBlockAtIndex(startLocation.index).getLength(); 7935 startLocation.index += 1; 7936 } 7937 startLocation.offset = 0; 7938 if (endLocation.offset === 0 && endLocation.index > startLocation.index) { 7939 endLocation.index -= 1; 7940 endLocation.offset = document.getBlockAtIndex(endLocation.index).getBlockBreakPosition(); 7941 } else { 7942 const endBlock = document.getBlockAtIndex(endLocation.index); 7943 if (endBlock.text.getStringAtRange([endLocation.offset - 1, endLocation.offset]) === "\n") { 7944 endLocation.offset -= 1; 7945 } else { 7946 endLocation.offset = endBlock.findLineBreakInDirectionFromPosition("forward", endLocation.offset); 7947 } 7948 if (endLocation.offset !== endBlock.getBlockBreakPosition()) { 7949 position = document.positionFromLocation(endLocation); 7950 document = document.insertBlockBreakAtRange([position, position + 1]); 7951 } 7952 } 7953 startPosition = document.positionFromLocation(startLocation); 7954 endPosition = document.positionFromLocation(endLocation); 7955 range = normalizeRange([startPosition, endPosition]); 7956 return { 7957 document, 7958 range 7959 }; 7960 } 7961 convertLineBreaksToBlockBreaksInRange(range) { 7962 range = normalizeRange(range); 7963 let [position] = range; 7964 const string = this.getStringAtRange(range).slice(0, -1); 7965 let document = this; 7966 string.replace(/.*?\n/g, function (match) { 7967 position += match.length; 7968 document = document.insertBlockBreakAtRange([position - 1, position]); 7969 }); 7970 return { 7971 document, 7972 range 7973 }; 7974 } 7975 consolidateBlocksAtRange(range) { 7976 range = normalizeRange(range); 7977 const [startPosition, endPosition] = range; 7978 const startIndex = this.locationFromPosition(startPosition).index; 7979 const endIndex = this.locationFromPosition(endPosition).index; 7980 return new this.constructor(this.blockList.consolidateFromIndexToIndex(startIndex, endIndex)); 7981 } 7982 getDocumentAtRange(range) { 7983 range = normalizeRange(range); 7984 const blocks = this.blockList.getSplittableListInRange(range).toArray(); 7985 return new this.constructor(blocks); 7986 } 7987 getStringAtRange(range) { 7988 let endIndex; 7989 const array = range = normalizeRange(range), 7990 endPosition = array[array.length - 1]; 7991 if (endPosition !== this.getLength()) { 7992 endIndex = -1; 7993 } 7994 return this.getDocumentAtRange(range).toString().slice(0, endIndex); 7995 } 7996 getBlockAtIndex(index) { 7997 return this.blockList.getObjectAtIndex(index); 7998 } 7999 getBlockAtPosition(position) { 8000 const { 8001 index 8002 } = this.locationFromPosition(position); 8003 return this.getBlockAtIndex(index); 8004 } 8005 getTextAtIndex(index) { 8006 var _this$getBlockAtIndex; 8007 return (_this$getBlockAtIndex = this.getBlockAtIndex(index)) === null || _this$getBlockAtIndex === void 0 ? void 0 : _this$getBlockAtIndex.text; 8008 } 8009 getTextAtPosition(position) { 8010 const { 8011 index 8012 } = this.locationFromPosition(position); 8013 return this.getTextAtIndex(index); 8014 } 8015 getPieceAtPosition(position) { 8016 const { 8017 index, 8018 offset 8019 } = this.locationFromPosition(position); 8020 return this.getTextAtIndex(index).getPieceAtPosition(offset); 8021 } 8022 getCharacterAtPosition(position) { 8023 const { 8024 index, 8025 offset 8026 } = this.locationFromPosition(position); 8027 return this.getTextAtIndex(index).getStringAtRange([offset, offset + 1]); 8028 } 8029 getLength() { 8030 return this.blockList.getEndPosition(); 8031 } 8032 getBlocks() { 8033 return this.blockList.toArray(); 8034 } 8035 getBlockCount() { 8036 return this.blockList.length; 8037 } 8038 getEditCount() { 8039 return this.editCount; 8040 } 8041 eachBlock(callback) { 8042 return this.blockList.eachObject(callback); 8043 } 8044 eachBlockAtRange(range, callback) { 8045 let block, textRange; 8046 range = normalizeRange(range); 8047 const [startPosition, endPosition] = range; 8048 const startLocation = this.locationFromPosition(startPosition); 8049 const endLocation = this.locationFromPosition(endPosition); 8050 if (startLocation.index === endLocation.index) { 8051 block = this.getBlockAtIndex(startLocation.index); 8052 textRange = [startLocation.offset, endLocation.offset]; 8053 return callback(block, textRange, startLocation.index); 8054 } else { 8055 for (let index = startLocation.index; index <= endLocation.index; index++) { 8056 block = this.getBlockAtIndex(index); 8057 if (block) { 8058 switch (index) { 8059 case startLocation.index: 8060 textRange = [startLocation.offset, block.text.getLength()]; 8061 break; 8062 case endLocation.index: 8063 textRange = [0, endLocation.offset]; 8064 break; 8065 default: 8066 textRange = [0, block.text.getLength()]; 8067 } 8068 callback(block, textRange, index); 8069 } 8070 } 8071 } 8072 } 8073 getCommonAttributesAtRange(range) { 8074 range = normalizeRange(range); 8075 const [startPosition] = range; 8076 if (rangeIsCollapsed(range)) { 8077 return this.getCommonAttributesAtPosition(startPosition); 8078 } else { 8079 const textAttributes = []; 8080 const blockAttributes = []; 8081 this.eachBlockAtRange(range, function (block, textRange) { 8082 if (textRange[0] !== textRange[1]) { 8083 textAttributes.push(block.text.getCommonAttributesAtRange(textRange)); 8084 return blockAttributes.push(attributesForBlock(block)); 8085 } 8086 }); 8087 return Hash.fromCommonAttributesOfObjects(textAttributes).merge(Hash.fromCommonAttributesOfObjects(blockAttributes)).toObject(); 8088 } 8089 } 8090 getCommonAttributesAtPosition(position) { 8091 let key, value; 8092 const { 8093 index, 8094 offset 8095 } = this.locationFromPosition(position); 8096 const block = this.getBlockAtIndex(index); 8097 if (!block) { 8098 return {}; 8099 } 8100 const commonAttributes = attributesForBlock(block); 8101 const attributes = block.text.getAttributesAtPosition(offset); 8102 const attributesLeft = block.text.getAttributesAtPosition(offset - 1); 8103 const inheritableAttributes = Object.keys(text_attributes).filter(key => { 8104 return text_attributes[key].inheritable; 8105 }); 8106 for (key in attributesLeft) { 8107 value = attributesLeft[key]; 8108 if (value === attributes[key] || inheritableAttributes.includes(key)) { 8109 commonAttributes[key] = value; 8110 } 8111 } 8112 return commonAttributes; 8113 } 8114 getRangeOfCommonAttributeAtPosition(attributeName, position) { 8115 const { 8116 index, 8117 offset 8118 } = this.locationFromPosition(position); 8119 const text = this.getTextAtIndex(index); 8120 const [startOffset, endOffset] = Array.from(text.getExpandedRangeForAttributeAtOffset(attributeName, offset)); 8121 const start = this.positionFromLocation({ 8122 index, 8123 offset: startOffset 8124 }); 8125 const end = this.positionFromLocation({ 8126 index, 8127 offset: endOffset 8128 }); 8129 return normalizeRange([start, end]); 8130 } 8131 getBaseBlockAttributes() { 8132 let baseBlockAttributes = this.getBlockAtIndex(0).getAttributes(); 8133 for (let blockIndex = 1; blockIndex < this.getBlockCount(); blockIndex++) { 8134 const blockAttributes = this.getBlockAtIndex(blockIndex).getAttributes(); 8135 const lastAttributeIndex = Math.min(baseBlockAttributes.length, blockAttributes.length); 8136 baseBlockAttributes = (() => { 8137 const result = []; 8138 for (let index = 0; index < lastAttributeIndex; index++) { 8139 if (blockAttributes[index] !== baseBlockAttributes[index]) { 8140 break; 8141 } 8142 result.push(blockAttributes[index]); 8143 } 8144 return result; 8145 })(); 8146 } 8147 return baseBlockAttributes; 8148 } 8149 getAttachmentById(attachmentId) { 8150 for (const attachment of this.getAttachments()) { 8151 if (attachment.id === attachmentId) { 8152 return attachment; 8153 } 8154 } 8155 } 8156 getAttachmentPieces() { 8157 let attachmentPieces = []; 8158 this.blockList.eachObject(_ref => { 8159 let { 8160 text 8161 } = _ref; 8162 return attachmentPieces = attachmentPieces.concat(text.getAttachmentPieces()); 8163 }); 8164 return attachmentPieces; 8165 } 8166 getAttachments() { 8167 return this.getAttachmentPieces().map(piece => piece.attachment); 8168 } 8169 getRangeOfAttachment(attachment) { 8170 let position = 0; 8171 const iterable = this.blockList.toArray(); 8172 for (let index = 0; index < iterable.length; index++) { 8173 const { 8174 text 8175 } = iterable[index]; 8176 const textRange = text.getRangeOfAttachment(attachment); 8177 if (textRange) { 8178 return normalizeRange([position + textRange[0], position + textRange[1]]); 8179 } 8180 position += text.getLength(); 8181 } 8182 } 8183 getLocationRangeOfAttachment(attachment) { 8184 const range = this.getRangeOfAttachment(attachment); 8185 return this.locationRangeFromRange(range); 8186 } 8187 getAttachmentPieceForAttachment(attachment) { 8188 for (const piece of this.getAttachmentPieces()) { 8189 if (piece.attachment === attachment) { 8190 return piece; 8191 } 8192 } 8193 } 8194 findRangesForBlockAttribute(attributeName) { 8195 let position = 0; 8196 const ranges = []; 8197 this.getBlocks().forEach(block => { 8198 const length = block.getLength(); 8199 if (block.hasAttribute(attributeName)) { 8200 ranges.push([position, position + length]); 8201 } 8202 position += length; 8203 }); 8204 return ranges; 8205 } 8206 findRangesForTextAttribute(attributeName) { 8207 let { 8208 withValue 8209 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 8210 let position = 0; 8211 let range = []; 8212 const ranges = []; 8213 const match = function (piece) { 8214 if (withValue) { 8215 return piece.getAttribute(attributeName) === withValue; 8216 } else { 8217 return piece.hasAttribute(attributeName); 8218 } 8219 }; 8220 this.getPieces().forEach(piece => { 8221 const length = piece.getLength(); 8222 if (match(piece)) { 8223 if (range[1] === position) { 8224 range[1] = position + length; 8225 } else { 8226 ranges.push(range = [position, position + length]); 8227 } 8228 } 8229 position += length; 8230 }); 8231 return ranges; 8232 } 8233 locationFromPosition(position) { 8234 const location = this.blockList.findIndexAndOffsetAtPosition(Math.max(0, position)); 8235 if (location.index != null) { 8236 return location; 8237 } else { 8238 const blocks = this.getBlocks(); 8239 return { 8240 index: blocks.length - 1, 8241 offset: blocks[blocks.length - 1].getLength() 8242 }; 8243 } 8244 } 8245 positionFromLocation(location) { 8246 return this.blockList.findPositionAtIndexAndOffset(location.index, location.offset); 8247 } 8248 locationRangeFromPosition(position) { 8249 return normalizeRange(this.locationFromPosition(position)); 8250 } 8251 locationRangeFromRange(range) { 8252 range = normalizeRange(range); 8253 if (!range) return; 8254 const [startPosition, endPosition] = Array.from(range); 8255 const startLocation = this.locationFromPosition(startPosition); 8256 const endLocation = this.locationFromPosition(endPosition); 8257 return normalizeRange([startLocation, endLocation]); 8258 } 8259 rangeFromLocationRange(locationRange) { 8260 let rightPosition; 8261 locationRange = normalizeRange(locationRange); 8262 const leftPosition = this.positionFromLocation(locationRange[0]); 8263 if (!rangeIsCollapsed(locationRange)) { 8264 rightPosition = this.positionFromLocation(locationRange[1]); 8265 } 8266 return normalizeRange([leftPosition, rightPosition]); 8267 } 8268 isEqualTo(document) { 8269 return this.blockList.isEqualTo(document === null || document === void 0 ? void 0 : document.blockList); 8270 } 8271 getTexts() { 8272 return this.getBlocks().map(block => block.text); 8273 } 8274 getPieces() { 8275 const pieces = []; 8276 Array.from(this.getTexts()).forEach(text => { 8277 pieces.push(...Array.from(text.getPieces() || [])); 8278 }); 8279 return pieces; 8280 } 8281 getObjects() { 8282 return this.getBlocks().concat(this.getTexts()).concat(this.getPieces()); 8283 } 8284 toSerializableDocument() { 8285 const blocks = []; 8286 this.blockList.eachObject(block => blocks.push(block.copyWithText(block.text.toSerializableText()))); 8287 return new this.constructor(blocks); 8288 } 8289 toString() { 8290 return this.blockList.toString(); 8291 } 8292 toJSON() { 8293 return this.blockList.toJSON(); 8294 } 8295 toConsole() { 8296 return JSON.stringify(this.blockList.toArray().map(block => JSON.parse(block.text.toConsole()))); 8297 } 8298 } 8299 const attributesForBlock = function (block) { 8300 const attributes = {}; 8301 const attributeName = block.getLastAttribute(); 8302 if (attributeName) { 8303 attributes[attributeName] = true; 8304 } 8305 return attributes; 8306 }; 8307 8308 /* eslint-disable 8309 no-case-declarations, 8310 no-irregular-whitespace, 8311 */ 8312 const pieceForString = function (string) { 8313 let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 8314 const type = "string"; 8315 string = normalizeSpaces(string); 8316 return { 8317 string, 8318 attributes, 8319 type 8320 }; 8321 }; 8322 const pieceForAttachment = function (attachment) { 8323 let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 8324 const type = "attachment"; 8325 return { 8326 attachment, 8327 attributes, 8328 type 8329 }; 8330 }; 8331 const blockForAttributes = function () { 8332 let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 8333 let htmlAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 8334 const text = []; 8335 return { 8336 text, 8337 attributes, 8338 htmlAttributes 8339 }; 8340 }; 8341 const parseTrixDataAttribute = (element, name) => { 8342 try { 8343 return JSON.parse(element.getAttribute("data-trix-".concat(name))); 8344 } catch (error) { 8345 return {}; 8346 } 8347 }; 8348 const getImageDimensions = element => { 8349 const width = element.getAttribute("width"); 8350 const height = element.getAttribute("height"); 8351 const dimensions = {}; 8352 if (width) { 8353 dimensions.width = parseInt(width, 10); 8354 } 8355 if (height) { 8356 dimensions.height = parseInt(height, 10); 8357 } 8358 return dimensions; 8359 }; 8360 class HTMLParser extends BasicObject { 8361 static parse(html, options) { 8362 const parser = new this(html, options); 8363 parser.parse(); 8364 return parser; 8365 } 8366 constructor(html) { 8367 let { 8368 referenceElement, 8369 purifyOptions 8370 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 8371 super(...arguments); 8372 this.html = html; 8373 this.referenceElement = referenceElement; 8374 this.purifyOptions = purifyOptions; 8375 this.blocks = []; 8376 this.blockElements = []; 8377 this.processedElements = []; 8378 } 8379 getDocument() { 8380 return Document.fromJSON(this.blocks); 8381 } 8382 8383 // HTML parsing 8384 8385 parse() { 8386 try { 8387 this.createHiddenContainer(); 8388 HTMLSanitizer.setHTML(this.containerElement, this.html, { 8389 purifyOptions: this.purifyOptions 8390 }); 8391 const walker = walkTree(this.containerElement, { 8392 usingFilter: nodeFilter 8393 }); 8394 while (walker.nextNode()) { 8395 this.processNode(walker.currentNode); 8396 } 8397 return this.translateBlockElementMarginsToNewlines(); 8398 } finally { 8399 this.removeHiddenContainer(); 8400 } 8401 } 8402 createHiddenContainer() { 8403 if (this.referenceElement) { 8404 this.containerElement = this.referenceElement.cloneNode(false); 8405 this.containerElement.removeAttribute("id"); 8406 this.containerElement.setAttribute("data-trix-internal", ""); 8407 this.containerElement.style.display = "none"; 8408 return this.referenceElement.parentNode.insertBefore(this.containerElement, this.referenceElement.nextSibling); 8409 } else { 8410 this.containerElement = makeElement({ 8411 tagName: "div", 8412 style: { 8413 display: "none" 8414 } 8415 }); 8416 return document.body.appendChild(this.containerElement); 8417 } 8418 } 8419 removeHiddenContainer() { 8420 return removeNode(this.containerElement); 8421 } 8422 processNode(node) { 8423 switch (node.nodeType) { 8424 case Node.TEXT_NODE: 8425 if (!this.isInsignificantTextNode(node)) { 8426 this.appendBlockForTextNode(node); 8427 return this.processTextNode(node); 8428 } 8429 break; 8430 case Node.ELEMENT_NODE: 8431 this.appendBlockForElement(node); 8432 return this.processElement(node); 8433 } 8434 } 8435 appendBlockForTextNode(node) { 8436 const element = node.parentNode; 8437 if (element === this.currentBlockElement && this.isBlockElement(node.previousSibling)) { 8438 return this.appendStringWithAttributes("\n"); 8439 } else if (element === this.containerElement || this.isBlockElement(element)) { 8440 var _this$currentBlock; 8441 const attributes = this.getBlockAttributes(element); 8442 const htmlAttributes = this.getBlockHTMLAttributes(element); 8443 if (!arraysAreEqual(attributes, (_this$currentBlock = this.currentBlock) === null || _this$currentBlock === void 0 ? void 0 : _this$currentBlock.attributes)) { 8444 this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element, htmlAttributes); 8445 this.currentBlockElement = element; 8446 } 8447 } 8448 } 8449 appendBlockForElement(element) { 8450 const elementIsBlockElement = this.isBlockElement(element); 8451 const currentBlockContainsElement = elementContainsNode(this.currentBlockElement, element); 8452 if (elementIsBlockElement && !this.isBlockElement(element.firstChild)) { 8453 if (!this.isInsignificantTextNode(element.firstChild) || !this.isBlockElement(element.firstElementChild)) { 8454 const attributes = this.getBlockAttributes(element); 8455 const htmlAttributes = this.getBlockHTMLAttributes(element); 8456 if (element.firstChild) { 8457 if (!(currentBlockContainsElement && arraysAreEqual(attributes, this.currentBlock.attributes))) { 8458 this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element, htmlAttributes); 8459 this.currentBlockElement = element; 8460 } else { 8461 return this.appendStringWithAttributes("\n"); 8462 } 8463 } 8464 } 8465 } else if (this.currentBlockElement && !currentBlockContainsElement && !elementIsBlockElement) { 8466 const parentBlockElement = this.findParentBlockElement(element); 8467 if (parentBlockElement) { 8468 return this.appendBlockForElement(parentBlockElement); 8469 } else { 8470 this.currentBlock = this.appendEmptyBlock(); 8471 this.currentBlockElement = null; 8472 } 8473 } 8474 } 8475 findParentBlockElement(element) { 8476 let { 8477 parentElement 8478 } = element; 8479 while (parentElement && parentElement !== this.containerElement) { 8480 if (this.isBlockElement(parentElement) && this.blockElements.includes(parentElement)) { 8481 return parentElement; 8482 } else { 8483 parentElement = parentElement.parentElement; 8484 } 8485 } 8486 return null; 8487 } 8488 processTextNode(node) { 8489 let string = node.data; 8490 if (!elementCanDisplayPreformattedText(node.parentNode)) { 8491 var _node$previousSibling; 8492 string = squishBreakableWhitespace(string); 8493 if (stringEndsWithWhitespace((_node$previousSibling = node.previousSibling) === null || _node$previousSibling === void 0 ? void 0 : _node$previousSibling.textContent)) { 8494 string = leftTrimBreakableWhitespace(string); 8495 } 8496 } 8497 return this.appendStringWithAttributes(string, this.getTextAttributes(node.parentNode)); 8498 } 8499 processElement(element) { 8500 let attributes; 8501 if (nodeIsAttachmentElement(element)) { 8502 attributes = parseTrixDataAttribute(element, "attachment"); 8503 if (Object.keys(attributes).length) { 8504 const textAttributes = this.getTextAttributes(element); 8505 this.appendAttachmentWithAttributes(attributes, textAttributes); 8506 // We have everything we need so avoid processing inner nodes 8507 element.innerHTML = ""; 8508 } 8509 return this.processedElements.push(element); 8510 } else { 8511 switch (tagName(element)) { 8512 case "br": 8513 if (!this.isExtraBR(element) && !this.isBlockElement(element.nextSibling)) { 8514 this.appendStringWithAttributes("\n", this.getTextAttributes(element)); 8515 } 8516 return this.processedElements.push(element); 8517 case "img": 8518 attributes = { 8519 url: element.getAttribute("src"), 8520 contentType: "image" 8521 }; 8522 const object = getImageDimensions(element); 8523 for (const key in object) { 8524 const value = object[key]; 8525 attributes[key] = value; 8526 } 8527 this.appendAttachmentWithAttributes(attributes, this.getTextAttributes(element)); 8528 return this.processedElements.push(element); 8529 case "tr": 8530 if (this.needsTableSeparator(element)) { 8531 return this.appendStringWithAttributes(parser.tableRowSeparator); 8532 } 8533 break; 8534 case "td": 8535 if (this.needsTableSeparator(element)) { 8536 return this.appendStringWithAttributes(parser.tableCellSeparator); 8537 } 8538 break; 8539 } 8540 } 8541 } 8542 8543 // Document construction 8544 8545 appendBlockForAttributesWithElement(attributes, element) { 8546 let htmlAttributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; 8547 this.blockElements.push(element); 8548 const block = blockForAttributes(attributes, htmlAttributes); 8549 this.blocks.push(block); 8550 return block; 8551 } 8552 appendEmptyBlock() { 8553 return this.appendBlockForAttributesWithElement([], null); 8554 } 8555 appendStringWithAttributes(string, attributes) { 8556 return this.appendPiece(pieceForString(string, attributes)); 8557 } 8558 appendAttachmentWithAttributes(attachment, attributes) { 8559 return this.appendPiece(pieceForAttachment(attachment, attributes)); 8560 } 8561 appendPiece(piece) { 8562 if (this.blocks.length === 0) { 8563 this.appendEmptyBlock(); 8564 } 8565 return this.blocks[this.blocks.length - 1].text.push(piece); 8566 } 8567 appendStringToTextAtIndex(string, index) { 8568 const { 8569 text 8570 } = this.blocks[index]; 8571 const piece = text[text.length - 1]; 8572 if ((piece === null || piece === void 0 ? void 0 : piece.type) === "string") { 8573 piece.string += string; 8574 } else { 8575 return text.push(pieceForString(string)); 8576 } 8577 } 8578 prependStringToTextAtIndex(string, index) { 8579 const { 8580 text 8581 } = this.blocks[index]; 8582 const piece = text[0]; 8583 if ((piece === null || piece === void 0 ? void 0 : piece.type) === "string") { 8584 piece.string = string + piece.string; 8585 } else { 8586 return text.unshift(pieceForString(string)); 8587 } 8588 } 8589 8590 // Attribute parsing 8591 8592 getTextAttributes(element) { 8593 let value; 8594 const attributes = {}; 8595 for (const attribute in text_attributes) { 8596 const configAttr = text_attributes[attribute]; 8597 if (configAttr.tagName && findClosestElementFromNode(element, { 8598 matchingSelector: configAttr.tagName, 8599 untilNode: this.containerElement 8600 })) { 8601 attributes[attribute] = true; 8602 } else if (configAttr.parser) { 8603 value = configAttr.parser(element); 8604 if (value) { 8605 let attributeInheritedFromBlock = false; 8606 for (const blockElement of this.findBlockElementAncestors(element)) { 8607 if (configAttr.parser(blockElement) === value) { 8608 attributeInheritedFromBlock = true; 8609 break; 8610 } 8611 } 8612 if (!attributeInheritedFromBlock) { 8613 attributes[attribute] = value; 8614 } 8615 } 8616 } else if (configAttr.styleProperty) { 8617 value = element.style[configAttr.styleProperty]; 8618 if (value) { 8619 attributes[attribute] = value; 8620 } 8621 } 8622 } 8623 if (nodeIsAttachmentElement(element)) { 8624 const object = parseTrixDataAttribute(element, "attributes"); 8625 for (const key in object) { 8626 value = object[key]; 8627 attributes[key] = value; 8628 } 8629 } 8630 return attributes; 8631 } 8632 getBlockAttributes(element) { 8633 const attributes$1 = []; 8634 while (element && element !== this.containerElement) { 8635 for (const attribute in attributes) { 8636 const attrConfig = attributes[attribute]; 8637 if (attrConfig.parse !== false) { 8638 if (tagName(element) === attrConfig.tagName) { 8639 var _attrConfig$test; 8640 if ((_attrConfig$test = attrConfig.test) !== null && _attrConfig$test !== void 0 && _attrConfig$test.call(attrConfig, element) || !attrConfig.test) { 8641 attributes$1.push(attribute); 8642 if (attrConfig.listAttribute) { 8643 attributes$1.push(attrConfig.listAttribute); 8644 } 8645 } 8646 } 8647 } 8648 } 8649 element = element.parentNode; 8650 } 8651 return attributes$1.reverse(); 8652 } 8653 getBlockHTMLAttributes(element) { 8654 const attributes$1 = {}; 8655 const blockConfig = Object.values(attributes).find(settings => settings.tagName === tagName(element)); 8656 const allowedAttributes = (blockConfig === null || blockConfig === void 0 ? void 0 : blockConfig.htmlAttributes) || []; 8657 allowedAttributes.forEach(attribute => { 8658 if (element.hasAttribute(attribute)) { 8659 attributes$1[attribute] = element.getAttribute(attribute); 8660 } 8661 }); 8662 return attributes$1; 8663 } 8664 findBlockElementAncestors(element) { 8665 const ancestors = []; 8666 while (element && element !== this.containerElement) { 8667 const tag = tagName(element); 8668 if (getBlockTagNames().includes(tag)) { 8669 ancestors.push(element); 8670 } 8671 element = element.parentNode; 8672 } 8673 return ancestors; 8674 } 8675 8676 // Element inspection 8677 8678 isBlockElement(element) { 8679 if ((element === null || element === void 0 ? void 0 : element.nodeType) !== Node.ELEMENT_NODE) return; 8680 if (nodeIsAttachmentElement(element)) return; 8681 if (findClosestElementFromNode(element, { 8682 matchingSelector: "td", 8683 untilNode: this.containerElement 8684 })) return; 8685 return getBlockTagNames().includes(tagName(element)) || window.getComputedStyle(element).display === "block"; 8686 } 8687 isInsignificantTextNode(node) { 8688 if ((node === null || node === void 0 ? void 0 : node.nodeType) !== Node.TEXT_NODE) return; 8689 if (!stringIsAllBreakableWhitespace(node.data)) return; 8690 const { 8691 parentNode, 8692 previousSibling, 8693 nextSibling 8694 } = node; 8695 if (nodeEndsWithNonWhitespace(parentNode.previousSibling) && !this.isBlockElement(parentNode.previousSibling)) return; 8696 if (elementCanDisplayPreformattedText(parentNode)) return; 8697 return !previousSibling || this.isBlockElement(previousSibling) || !nextSibling || this.isBlockElement(nextSibling); 8698 } 8699 isExtraBR(element) { 8700 return tagName(element) === "br" && this.isBlockElement(element.parentNode) && element.parentNode.lastChild === element; 8701 } 8702 needsTableSeparator(element) { 8703 if (parser.removeBlankTableCells) { 8704 var _element$previousSibl; 8705 const content = (_element$previousSibl = element.previousSibling) === null || _element$previousSibl === void 0 ? void 0 : _element$previousSibl.textContent; 8706 return content && /\S/.test(content); 8707 } else { 8708 return element.previousSibling; 8709 } 8710 } 8711 8712 // Margin translation 8713 8714 translateBlockElementMarginsToNewlines() { 8715 const defaultMargin = this.getMarginOfDefaultBlockElement(); 8716 for (let index = 0; index < this.blocks.length; index++) { 8717 const margin = this.getMarginOfBlockElementAtIndex(index); 8718 if (margin) { 8719 if (margin.top > defaultMargin.top * 2) { 8720 this.prependStringToTextAtIndex("\n", index); 8721 } 8722 if (margin.bottom > defaultMargin.bottom * 2) { 8723 this.appendStringToTextAtIndex("\n", index); 8724 } 8725 } 8726 } 8727 } 8728 getMarginOfBlockElementAtIndex(index) { 8729 const element = this.blockElements[index]; 8730 if (element) { 8731 if (element.textContent) { 8732 if (!getBlockTagNames().includes(tagName(element)) && !this.processedElements.includes(element)) { 8733 return getBlockElementMargin(element); 8734 } 8735 } 8736 } 8737 } 8738 getMarginOfDefaultBlockElement() { 8739 const element = makeElement(attributes.default.tagName); 8740 this.containerElement.appendChild(element); 8741 return getBlockElementMargin(element); 8742 } 8743 } 8744 8745 // Helpers 8746 8747 const elementCanDisplayPreformattedText = function (element) { 8748 const { 8749 whiteSpace 8750 } = window.getComputedStyle(element); 8751 return ["pre", "pre-wrap", "pre-line"].includes(whiteSpace); 8752 }; 8753 const nodeEndsWithNonWhitespace = node => node && !stringEndsWithWhitespace(node.textContent); 8754 const getBlockElementMargin = function (element) { 8755 const style = window.getComputedStyle(element); 8756 if (style.display === "block") { 8757 return { 8758 top: parseInt(style.marginTop), 8759 bottom: parseInt(style.marginBottom) 8760 }; 8761 } 8762 }; 8763 const nodeFilter = function (node) { 8764 if (tagName(node) === "style") { 8765 return NodeFilter.FILTER_REJECT; 8766 } else { 8767 return NodeFilter.FILTER_ACCEPT; 8768 } 8769 }; 8770 8771 // Whitespace 8772 8773 const leftTrimBreakableWhitespace = string => string.replace(new RegExp("^".concat(breakableWhitespacePattern.source, "+")), ""); 8774 const stringIsAllBreakableWhitespace = string => new RegExp("^".concat(breakableWhitespacePattern.source, "*$")).test(string); 8775 const stringEndsWithWhitespace = string => /\s$/.test(string); 8776 8777 /* eslint-disable 8778 no-empty, 8779 */ 8780 const unserializableElementSelector = "[data-trix-serialize=false]"; 8781 const unserializableAttributeNames = ["contenteditable", "data-trix-id", "data-trix-store-key", "data-trix-mutable", "data-trix-placeholder", "tabindex"]; 8782 const serializedAttributesAttribute = "data-trix-serialized-attributes"; 8783 const serializedAttributesSelector = "[".concat(serializedAttributesAttribute, "]"); 8784 const blockCommentPattern = new RegExp("<!--block-->", "g"); 8785 const serializers = { 8786 "application/json": function (serializable) { 8787 let document; 8788 if (serializable instanceof Document) { 8789 document = serializable; 8790 } else if (serializable instanceof HTMLElement) { 8791 document = HTMLParser.parse(serializable.innerHTML).getDocument(); 8792 } else { 8793 throw new Error("unserializable object"); 8794 } 8795 return document.toSerializableDocument().toJSONString(); 8796 }, 8797 "text/html": function (serializable) { 8798 let element; 8799 if (serializable instanceof Document) { 8800 element = DocumentView.render(serializable); 8801 } else if (serializable instanceof HTMLElement) { 8802 element = serializable.cloneNode(true); 8803 } else { 8804 throw new Error("unserializable object"); 8805 } 8806 8807 // Remove unserializable elements 8808 Array.from(element.querySelectorAll(unserializableElementSelector)).forEach(el => { 8809 removeNode(el); 8810 }); 8811 8812 // Remove unserializable attributes 8813 unserializableAttributeNames.forEach(attribute => { 8814 Array.from(element.querySelectorAll("[".concat(attribute, "]"))).forEach(el => { 8815 el.removeAttribute(attribute); 8816 }); 8817 }); 8818 8819 // Rewrite elements with serialized attribute overrides 8820 Array.from(element.querySelectorAll(serializedAttributesSelector)).forEach(el => { 8821 try { 8822 const attributes = JSON.parse(el.getAttribute(serializedAttributesAttribute)); 8823 el.removeAttribute(serializedAttributesAttribute); 8824 for (const name in attributes) { 8825 const value = attributes[name]; 8826 el.setAttribute(name, value); 8827 } 8828 } catch (error) {} 8829 }); 8830 return element.innerHTML.replace(blockCommentPattern, ""); 8831 } 8832 }; 8833 const deserializers = { 8834 "application/json": function (string) { 8835 return Document.fromJSONString(string); 8836 }, 8837 "text/html": function (string) { 8838 return HTMLParser.parse(string).getDocument(); 8839 } 8840 }; 8841 const serializeToContentType = function (serializable, contentType) { 8842 const serializer = serializers[contentType]; 8843 if (serializer) { 8844 return serializer(serializable); 8845 } else { 8846 throw new Error("unknown content type: ".concat(contentType)); 8847 } 8848 }; 8849 const deserializeFromContentType = function (string, contentType) { 8850 const deserializer = deserializers[contentType]; 8851 if (deserializer) { 8852 return deserializer(string); 8853 } else { 8854 throw new Error("unknown content type: ".concat(contentType)); 8855 } 8856 }; 8857 8858 var core = /*#__PURE__*/Object.freeze({ 8859 __proto__: null 8860 }); 8861 8862 class ManagedAttachment extends BasicObject { 8863 constructor(attachmentManager, attachment) { 8864 super(...arguments); 8865 this.attachmentManager = attachmentManager; 8866 this.attachment = attachment; 8867 this.id = this.attachment.id; 8868 this.file = this.attachment.file; 8869 } 8870 remove() { 8871 return this.attachmentManager.requestRemovalOfAttachment(this.attachment); 8872 } 8873 } 8874 ManagedAttachment.proxyMethod("attachment.getAttribute"); 8875 ManagedAttachment.proxyMethod("attachment.hasAttribute"); 8876 ManagedAttachment.proxyMethod("attachment.setAttribute"); 8877 ManagedAttachment.proxyMethod("attachment.getAttributes"); 8878 ManagedAttachment.proxyMethod("attachment.setAttributes"); 8879 ManagedAttachment.proxyMethod("attachment.isPending"); 8880 ManagedAttachment.proxyMethod("attachment.isPreviewable"); 8881 ManagedAttachment.proxyMethod("attachment.getURL"); 8882 ManagedAttachment.proxyMethod("attachment.getPreviewURL"); 8883 ManagedAttachment.proxyMethod("attachment.setPreviewURL"); 8884 ManagedAttachment.proxyMethod("attachment.getHref"); 8885 ManagedAttachment.proxyMethod("attachment.getFilename"); 8886 ManagedAttachment.proxyMethod("attachment.getFilesize"); 8887 ManagedAttachment.proxyMethod("attachment.getFormattedFilesize"); 8888 ManagedAttachment.proxyMethod("attachment.getExtension"); 8889 ManagedAttachment.proxyMethod("attachment.getContentType"); 8890 ManagedAttachment.proxyMethod("attachment.getFile"); 8891 ManagedAttachment.proxyMethod("attachment.setFile"); 8892 ManagedAttachment.proxyMethod("attachment.releaseFile"); 8893 ManagedAttachment.proxyMethod("attachment.getUploadProgress"); 8894 ManagedAttachment.proxyMethod("attachment.setUploadProgress"); 8895 8896 class AttachmentManager extends BasicObject { 8897 constructor() { 8898 let attachments = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 8899 super(...arguments); 8900 this.managedAttachments = {}; 8901 Array.from(attachments).forEach(attachment => { 8902 this.manageAttachment(attachment); 8903 }); 8904 } 8905 getAttachments() { 8906 const result = []; 8907 for (const id in this.managedAttachments) { 8908 const attachment = this.managedAttachments[id]; 8909 result.push(attachment); 8910 } 8911 return result; 8912 } 8913 manageAttachment(attachment) { 8914 if (!this.managedAttachments[attachment.id]) { 8915 this.managedAttachments[attachment.id] = new ManagedAttachment(this, attachment); 8916 } 8917 return this.managedAttachments[attachment.id]; 8918 } 8919 attachmentIsManaged(attachment) { 8920 return attachment.id in this.managedAttachments; 8921 } 8922 requestRemovalOfAttachment(attachment) { 8923 if (this.attachmentIsManaged(attachment)) { 8924 var _this$delegate, _this$delegate$attach; 8925 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$attach = _this$delegate.attachmentManagerDidRequestRemovalOfAttachment) === null || _this$delegate$attach === void 0 ? void 0 : _this$delegate$attach.call(_this$delegate, attachment); 8926 } 8927 } 8928 unmanageAttachment(attachment) { 8929 const managedAttachment = this.managedAttachments[attachment.id]; 8930 delete this.managedAttachments[attachment.id]; 8931 return managedAttachment; 8932 } 8933 } 8934 8935 class LineBreakInsertion { 8936 constructor(composition) { 8937 this.composition = composition; 8938 this.document = this.composition.document; 8939 const selectedRange = this.composition.getSelectedRange(); 8940 this.startPosition = selectedRange[0]; 8941 this.endPosition = selectedRange[1]; 8942 this.startLocation = this.document.locationFromPosition(this.startPosition); 8943 this.endLocation = this.document.locationFromPosition(this.endPosition); 8944 this.block = this.document.getBlockAtIndex(this.endLocation.index); 8945 this.breaksOnReturn = this.block.breaksOnReturn(); 8946 this.previousCharacter = this.block.text.getStringAtPosition(this.endLocation.offset - 1); 8947 this.nextCharacter = this.block.text.getStringAtPosition(this.endLocation.offset); 8948 } 8949 shouldInsertBlockBreak() { 8950 if (this.block.hasAttributes() && this.block.isListItem() && !this.block.isEmpty()) { 8951 return this.startLocation.offset !== 0; 8952 } else { 8953 return this.breaksOnReturn && this.nextCharacter !== "\n"; 8954 } 8955 } 8956 shouldBreakFormattedBlock() { 8957 return this.block.hasAttributes() && !this.block.isListItem() && (this.breaksOnReturn && this.nextCharacter === "\n" || this.previousCharacter === "\n"); 8958 } 8959 shouldDecreaseListLevel() { 8960 return this.block.hasAttributes() && this.block.isListItem() && this.block.isEmpty(); 8961 } 8962 shouldPrependListItem() { 8963 return this.block.isListItem() && this.startLocation.offset === 0 && !this.block.isEmpty(); 8964 } 8965 shouldRemoveLastBlockAttribute() { 8966 return this.block.hasAttributes() && !this.block.isListItem() && this.block.isEmpty(); 8967 } 8968 } 8969 8970 const PLACEHOLDER = " "; 8971 class Composition extends BasicObject { 8972 constructor() { 8973 super(...arguments); 8974 this.document = new Document(); 8975 this.attachments = []; 8976 this.currentAttributes = {}; 8977 this.revision = 0; 8978 } 8979 setDocument(document) { 8980 if (!document.isEqualTo(this.document)) { 8981 var _this$delegate, _this$delegate$compos; 8982 this.document = document; 8983 this.refreshAttachments(); 8984 this.revision++; 8985 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$compos = _this$delegate.compositionDidChangeDocument) === null || _this$delegate$compos === void 0 ? void 0 : _this$delegate$compos.call(_this$delegate, document); 8986 } 8987 } 8988 8989 // Snapshots 8990 8991 getSnapshot() { 8992 return { 8993 document: this.document, 8994 selectedRange: this.getSelectedRange() 8995 }; 8996 } 8997 loadSnapshot(_ref) { 8998 var _this$delegate2, _this$delegate2$compo, _this$delegate3, _this$delegate3$compo; 8999 let { 9000 document, 9001 selectedRange 9002 } = _ref; 9003 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$compo = _this$delegate2.compositionWillLoadSnapshot) === null || _this$delegate2$compo === void 0 || _this$delegate2$compo.call(_this$delegate2); 9004 this.setDocument(document != null ? document : new Document()); 9005 this.setSelection(selectedRange != null ? selectedRange : [0, 0]); 9006 return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || (_this$delegate3$compo = _this$delegate3.compositionDidLoadSnapshot) === null || _this$delegate3$compo === void 0 ? void 0 : _this$delegate3$compo.call(_this$delegate3); 9007 } 9008 9009 // Responder protocol 9010 9011 insertText(text) { 9012 let { 9013 updatePosition 9014 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { 9015 updatePosition: true 9016 }; 9017 const selectedRange = this.getSelectedRange(); 9018 this.setDocument(this.document.insertTextAtRange(text, selectedRange)); 9019 const startPosition = selectedRange[0]; 9020 const endPosition = startPosition + text.getLength(); 9021 if (updatePosition) { 9022 this.setSelection(endPosition); 9023 } 9024 return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); 9025 } 9026 insertBlock() { 9027 let block = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Block(); 9028 const document = new Document([block]); 9029 return this.insertDocument(document); 9030 } 9031 insertDocument() { 9032 let document = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Document(); 9033 const selectedRange = this.getSelectedRange(); 9034 this.setDocument(this.document.insertDocumentAtRange(document, selectedRange)); 9035 const startPosition = selectedRange[0]; 9036 const endPosition = startPosition + document.getLength(); 9037 this.setSelection(endPosition); 9038 return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); 9039 } 9040 insertString(string, options) { 9041 const attributes = this.getCurrentTextAttributes(); 9042 const text = Text.textForStringWithAttributes(string, attributes); 9043 return this.insertText(text, options); 9044 } 9045 insertBlockBreak() { 9046 const selectedRange = this.getSelectedRange(); 9047 this.setDocument(this.document.insertBlockBreakAtRange(selectedRange)); 9048 const startPosition = selectedRange[0]; 9049 const endPosition = startPosition + 1; 9050 this.setSelection(endPosition); 9051 return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); 9052 } 9053 insertLineBreak() { 9054 const insertion = new LineBreakInsertion(this); 9055 if (insertion.shouldDecreaseListLevel()) { 9056 this.decreaseListLevel(); 9057 return this.setSelection(insertion.startPosition); 9058 } else if (insertion.shouldPrependListItem()) { 9059 const document = new Document([insertion.block.copyWithoutText()]); 9060 return this.insertDocument(document); 9061 } else if (insertion.shouldInsertBlockBreak()) { 9062 return this.insertBlockBreak(); 9063 } else if (insertion.shouldRemoveLastBlockAttribute()) { 9064 return this.removeLastBlockAttribute(); 9065 } else if (insertion.shouldBreakFormattedBlock()) { 9066 return this.breakFormattedBlock(insertion); 9067 } else { 9068 return this.insertString("\n"); 9069 } 9070 } 9071 insertHTML(html) { 9072 const document = HTMLParser.parse(html, { 9073 purifyOptions: { 9074 SAFE_FOR_XML: true 9075 } 9076 }).getDocument(); 9077 const selectedRange = this.getSelectedRange(); 9078 this.setDocument(this.document.mergeDocumentAtRange(document, selectedRange)); 9079 const startPosition = selectedRange[0]; 9080 const endPosition = startPosition + document.getLength() - 1; 9081 this.setSelection(endPosition); 9082 return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); 9083 } 9084 replaceHTML(html) { 9085 const document = HTMLParser.parse(html).getDocument().copyUsingObjectsFromDocument(this.document); 9086 const locationRange = this.getLocationRange({ 9087 strict: false 9088 }); 9089 const selectedRange = this.document.rangeFromLocationRange(locationRange); 9090 this.setDocument(document); 9091 return this.setSelection(selectedRange); 9092 } 9093 insertFile(file) { 9094 return this.insertFiles([file]); 9095 } 9096 insertFiles(files) { 9097 const attachments = []; 9098 Array.from(files).forEach(file => { 9099 var _this$delegate4; 9100 if ((_this$delegate4 = this.delegate) !== null && _this$delegate4 !== void 0 && _this$delegate4.compositionShouldAcceptFile(file)) { 9101 const attachment = Attachment.attachmentForFile(file); 9102 attachments.push(attachment); 9103 } 9104 }); 9105 return this.insertAttachments(attachments); 9106 } 9107 insertAttachment(attachment) { 9108 return this.insertAttachments([attachment]); 9109 } 9110 insertAttachments(attachments$1) { 9111 let text = new Text(); 9112 Array.from(attachments$1).forEach(attachment => { 9113 var _config$attachments$t; 9114 const type = attachment.getType(); 9115 const presentation = (_config$attachments$t = attachments[type]) === null || _config$attachments$t === void 0 ? void 0 : _config$attachments$t.presentation; 9116 const attributes = this.getCurrentTextAttributes(); 9117 if (presentation) { 9118 attributes.presentation = presentation; 9119 } 9120 const attachmentText = Text.textForAttachmentWithAttributes(attachment, attributes); 9121 text = text.appendText(attachmentText); 9122 }); 9123 return this.insertText(text); 9124 } 9125 shouldManageDeletingInDirection(direction) { 9126 const locationRange = this.getLocationRange(); 9127 if (rangeIsCollapsed(locationRange)) { 9128 if (direction === "backward" && locationRange[0].offset === 0) { 9129 return true; 9130 } 9131 if (this.shouldManageMovingCursorInDirection(direction)) { 9132 return true; 9133 } 9134 } else { 9135 if (locationRange[0].index !== locationRange[1].index) { 9136 return true; 9137 } 9138 } 9139 return false; 9140 } 9141 deleteInDirection(direction) { 9142 let { 9143 length 9144 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 9145 let attachment, deletingIntoPreviousBlock, selectionSpansBlocks; 9146 const locationRange = this.getLocationRange(); 9147 let range = this.getSelectedRange(); 9148 const selectionIsCollapsed = rangeIsCollapsed(range); 9149 if (selectionIsCollapsed) { 9150 deletingIntoPreviousBlock = direction === "backward" && locationRange[0].offset === 0; 9151 } else { 9152 selectionSpansBlocks = locationRange[0].index !== locationRange[1].index; 9153 } 9154 if (deletingIntoPreviousBlock) { 9155 if (this.canDecreaseBlockAttributeLevel()) { 9156 const block = this.getBlock(); 9157 if (block.isListItem()) { 9158 this.decreaseListLevel(); 9159 } else { 9160 this.decreaseBlockAttributeLevel(); 9161 } 9162 this.setSelection(range[0]); 9163 if (block.isEmpty()) { 9164 return false; 9165 } 9166 } 9167 } 9168 if (selectionIsCollapsed) { 9169 range = this.getExpandedRangeInDirection(direction, { 9170 length 9171 }); 9172 if (direction === "backward") { 9173 attachment = this.getAttachmentAtRange(range); 9174 } 9175 } 9176 if (attachment) { 9177 this.editAttachment(attachment); 9178 return false; 9179 } else { 9180 this.setDocument(this.document.removeTextAtRange(range)); 9181 this.setSelection(range[0]); 9182 if (deletingIntoPreviousBlock || selectionSpansBlocks) { 9183 return false; 9184 } 9185 } 9186 } 9187 moveTextFromRange(range) { 9188 const [position] = Array.from(this.getSelectedRange()); 9189 this.setDocument(this.document.moveTextFromRangeToPosition(range, position)); 9190 return this.setSelection(position); 9191 } 9192 removeAttachment(attachment) { 9193 const range = this.document.getRangeOfAttachment(attachment); 9194 if (range) { 9195 this.stopEditingAttachment(); 9196 this.setDocument(this.document.removeTextAtRange(range)); 9197 return this.setSelection(range[0]); 9198 } 9199 } 9200 removeLastBlockAttribute() { 9201 const [startPosition, endPosition] = Array.from(this.getSelectedRange()); 9202 const block = this.document.getBlockAtPosition(endPosition); 9203 this.removeCurrentAttribute(block.getLastAttribute()); 9204 return this.setSelection(startPosition); 9205 } 9206 insertPlaceholder() { 9207 this.placeholderPosition = this.getPosition(); 9208 return this.insertString(PLACEHOLDER); 9209 } 9210 selectPlaceholder() { 9211 if (this.placeholderPosition != null) { 9212 this.setSelectedRange([this.placeholderPosition, this.placeholderPosition + PLACEHOLDER.length]); 9213 return this.getSelectedRange(); 9214 } 9215 } 9216 forgetPlaceholder() { 9217 this.placeholderPosition = null; 9218 } 9219 9220 // Current attributes 9221 9222 hasCurrentAttribute(attributeName) { 9223 const value = this.currentAttributes[attributeName]; 9224 return value != null && value !== false; 9225 } 9226 toggleCurrentAttribute(attributeName) { 9227 const value = !this.currentAttributes[attributeName]; 9228 if (value) { 9229 return this.setCurrentAttribute(attributeName, value); 9230 } else { 9231 return this.removeCurrentAttribute(attributeName); 9232 } 9233 } 9234 canSetCurrentAttribute(attributeName) { 9235 if (getBlockConfig(attributeName)) { 9236 return this.canSetCurrentBlockAttribute(attributeName); 9237 } else { 9238 return this.canSetCurrentTextAttribute(attributeName); 9239 } 9240 } 9241 canSetCurrentTextAttribute(attributeName) { 9242 const document = this.getSelectedDocument(); 9243 if (!document) return; 9244 for (const attachment of Array.from(document.getAttachments())) { 9245 if (!attachment.hasContent()) { 9246 return false; 9247 } 9248 } 9249 return true; 9250 } 9251 canSetCurrentBlockAttribute(attributeName) { 9252 const block = this.getBlock(); 9253 if (!block) return; 9254 return !block.isTerminalBlock(); 9255 } 9256 setCurrentAttribute(attributeName, value) { 9257 if (getBlockConfig(attributeName)) { 9258 return this.setBlockAttribute(attributeName, value); 9259 } else { 9260 this.setTextAttribute(attributeName, value); 9261 this.currentAttributes[attributeName] = value; 9262 return this.notifyDelegateOfCurrentAttributesChange(); 9263 } 9264 } 9265 setHTMLAtributeAtPosition(position, attributeName, value) { 9266 var _getBlockConfig; 9267 const block = this.document.getBlockAtPosition(position); 9268 const allowedHTMLAttributes = (_getBlockConfig = getBlockConfig(block.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.htmlAttributes; 9269 if (block && allowedHTMLAttributes !== null && allowedHTMLAttributes !== void 0 && allowedHTMLAttributes.includes(attributeName)) { 9270 const newDocument = this.document.setHTMLAttributeAtPosition(position, attributeName, value); 9271 this.setDocument(newDocument); 9272 } 9273 } 9274 setTextAttribute(attributeName, value) { 9275 const selectedRange = this.getSelectedRange(); 9276 if (!selectedRange) return; 9277 const [startPosition, endPosition] = Array.from(selectedRange); 9278 if (startPosition === endPosition) { 9279 if (attributeName === "href") { 9280 const text = Text.textForStringWithAttributes(value, { 9281 href: value 9282 }); 9283 return this.insertText(text); 9284 } 9285 } else { 9286 return this.setDocument(this.document.addAttributeAtRange(attributeName, value, selectedRange)); 9287 } 9288 } 9289 setBlockAttribute(attributeName, value) { 9290 const selectedRange = this.getSelectedRange(); 9291 if (this.canSetCurrentAttribute(attributeName)) { 9292 this.setDocument(this.document.applyBlockAttributeAtRange(attributeName, value, selectedRange)); 9293 return this.setSelection(selectedRange); 9294 } 9295 } 9296 removeCurrentAttribute(attributeName) { 9297 if (getBlockConfig(attributeName)) { 9298 this.removeBlockAttribute(attributeName); 9299 return this.updateCurrentAttributes(); 9300 } else { 9301 this.removeTextAttribute(attributeName); 9302 delete this.currentAttributes[attributeName]; 9303 return this.notifyDelegateOfCurrentAttributesChange(); 9304 } 9305 } 9306 removeTextAttribute(attributeName) { 9307 const selectedRange = this.getSelectedRange(); 9308 if (!selectedRange) return; 9309 return this.setDocument(this.document.removeAttributeAtRange(attributeName, selectedRange)); 9310 } 9311 removeBlockAttribute(attributeName) { 9312 const selectedRange = this.getSelectedRange(); 9313 if (!selectedRange) return; 9314 return this.setDocument(this.document.removeAttributeAtRange(attributeName, selectedRange)); 9315 } 9316 canDecreaseNestingLevel() { 9317 var _this$getBlock; 9318 return ((_this$getBlock = this.getBlock()) === null || _this$getBlock === void 0 ? void 0 : _this$getBlock.getNestingLevel()) > 0; 9319 } 9320 canIncreaseNestingLevel() { 9321 var _getBlockConfig2; 9322 const block = this.getBlock(); 9323 if (!block) return; 9324 if ((_getBlockConfig2 = getBlockConfig(block.getLastNestableAttribute())) !== null && _getBlockConfig2 !== void 0 && _getBlockConfig2.listAttribute) { 9325 const previousBlock = this.getPreviousBlock(); 9326 if (previousBlock) { 9327 return arrayStartsWith(previousBlock.getListItemAttributes(), block.getListItemAttributes()); 9328 } 9329 } else { 9330 return block.getNestingLevel() > 0; 9331 } 9332 } 9333 decreaseNestingLevel() { 9334 const block = this.getBlock(); 9335 if (!block) return; 9336 return this.setDocument(this.document.replaceBlock(block, block.decreaseNestingLevel())); 9337 } 9338 increaseNestingLevel() { 9339 const block = this.getBlock(); 9340 if (!block) return; 9341 return this.setDocument(this.document.replaceBlock(block, block.increaseNestingLevel())); 9342 } 9343 canDecreaseBlockAttributeLevel() { 9344 var _this$getBlock2; 9345 return ((_this$getBlock2 = this.getBlock()) === null || _this$getBlock2 === void 0 ? void 0 : _this$getBlock2.getAttributeLevel()) > 0; 9346 } 9347 decreaseBlockAttributeLevel() { 9348 var _this$getBlock3; 9349 const attribute = (_this$getBlock3 = this.getBlock()) === null || _this$getBlock3 === void 0 ? void 0 : _this$getBlock3.getLastAttribute(); 9350 if (attribute) { 9351 return this.removeCurrentAttribute(attribute); 9352 } 9353 } 9354 decreaseListLevel() { 9355 let [startPosition] = Array.from(this.getSelectedRange()); 9356 const { 9357 index 9358 } = this.document.locationFromPosition(startPosition); 9359 let endIndex = index; 9360 const attributeLevel = this.getBlock().getAttributeLevel(); 9361 let block = this.document.getBlockAtIndex(endIndex + 1); 9362 while (block) { 9363 if (!block.isListItem() || block.getAttributeLevel() <= attributeLevel) { 9364 break; 9365 } 9366 endIndex++; 9367 block = this.document.getBlockAtIndex(endIndex + 1); 9368 } 9369 startPosition = this.document.positionFromLocation({ 9370 index, 9371 offset: 0 9372 }); 9373 const endPosition = this.document.positionFromLocation({ 9374 index: endIndex, 9375 offset: 0 9376 }); 9377 return this.setDocument(this.document.removeLastListAttributeAtRange([startPosition, endPosition])); 9378 } 9379 updateCurrentAttributes() { 9380 const selectedRange = this.getSelectedRange({ 9381 ignoreLock: true 9382 }); 9383 if (selectedRange) { 9384 const currentAttributes = this.document.getCommonAttributesAtRange(selectedRange); 9385 Array.from(getAllAttributeNames()).forEach(attributeName => { 9386 if (!currentAttributes[attributeName]) { 9387 if (!this.canSetCurrentAttribute(attributeName)) { 9388 currentAttributes[attributeName] = false; 9389 } 9390 } 9391 }); 9392 if (!objectsAreEqual(currentAttributes, this.currentAttributes)) { 9393 this.currentAttributes = currentAttributes; 9394 return this.notifyDelegateOfCurrentAttributesChange(); 9395 } 9396 } 9397 } 9398 getCurrentAttributes() { 9399 return extend.call({}, this.currentAttributes); 9400 } 9401 getCurrentTextAttributes() { 9402 const attributes = {}; 9403 for (const key in this.currentAttributes) { 9404 const value = this.currentAttributes[key]; 9405 if (value !== false) { 9406 if (getTextConfig(key)) { 9407 attributes[key] = value; 9408 } 9409 } 9410 } 9411 return attributes; 9412 } 9413 9414 // Selection freezing 9415 9416 freezeSelection() { 9417 return this.setCurrentAttribute("frozen", true); 9418 } 9419 thawSelection() { 9420 return this.removeCurrentAttribute("frozen"); 9421 } 9422 hasFrozenSelection() { 9423 return this.hasCurrentAttribute("frozen"); 9424 } 9425 setSelection(selectedRange) { 9426 var _this$delegate5; 9427 const locationRange = this.document.locationRangeFromRange(selectedRange); 9428 return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 ? void 0 : _this$delegate5.compositionDidRequestChangingSelectionToLocationRange(locationRange); 9429 } 9430 getSelectedRange() { 9431 const locationRange = this.getLocationRange(); 9432 if (locationRange) { 9433 return this.document.rangeFromLocationRange(locationRange); 9434 } 9435 } 9436 setSelectedRange(selectedRange) { 9437 const locationRange = this.document.locationRangeFromRange(selectedRange); 9438 return this.getSelectionManager().setLocationRange(locationRange); 9439 } 9440 getPosition() { 9441 const locationRange = this.getLocationRange(); 9442 if (locationRange) { 9443 return this.document.positionFromLocation(locationRange[0]); 9444 } 9445 } 9446 getLocationRange(options) { 9447 if (this.targetLocationRange) { 9448 return this.targetLocationRange; 9449 } else { 9450 return this.getSelectionManager().getLocationRange(options) || normalizeRange({ 9451 index: 0, 9452 offset: 0 9453 }); 9454 } 9455 } 9456 withTargetLocationRange(locationRange, fn) { 9457 let result; 9458 this.targetLocationRange = locationRange; 9459 try { 9460 result = fn(); 9461 } finally { 9462 this.targetLocationRange = null; 9463 } 9464 return result; 9465 } 9466 withTargetRange(range, fn) { 9467 const locationRange = this.document.locationRangeFromRange(range); 9468 return this.withTargetLocationRange(locationRange, fn); 9469 } 9470 withTargetDOMRange(domRange, fn) { 9471 const locationRange = this.createLocationRangeFromDOMRange(domRange, { 9472 strict: false 9473 }); 9474 return this.withTargetLocationRange(locationRange, fn); 9475 } 9476 getExpandedRangeInDirection(direction) { 9477 let { 9478 length 9479 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 9480 let [startPosition, endPosition] = Array.from(this.getSelectedRange()); 9481 if (direction === "backward") { 9482 if (length) { 9483 startPosition -= length; 9484 } else { 9485 startPosition = this.translateUTF16PositionFromOffset(startPosition, -1); 9486 } 9487 } else { 9488 if (length) { 9489 endPosition += length; 9490 } else { 9491 endPosition = this.translateUTF16PositionFromOffset(endPosition, 1); 9492 } 9493 } 9494 return normalizeRange([startPosition, endPosition]); 9495 } 9496 shouldManageMovingCursorInDirection(direction) { 9497 if (this.editingAttachment) { 9498 return true; 9499 } 9500 const range = this.getExpandedRangeInDirection(direction); 9501 return this.getAttachmentAtRange(range) != null; 9502 } 9503 moveCursorInDirection(direction) { 9504 let canEditAttachment, range; 9505 if (this.editingAttachment) { 9506 range = this.document.getRangeOfAttachment(this.editingAttachment); 9507 } else { 9508 const selectedRange = this.getSelectedRange(); 9509 range = this.getExpandedRangeInDirection(direction); 9510 canEditAttachment = !rangesAreEqual(selectedRange, range); 9511 } 9512 if (direction === "backward") { 9513 this.setSelectedRange(range[0]); 9514 } else { 9515 this.setSelectedRange(range[1]); 9516 } 9517 if (canEditAttachment) { 9518 const attachment = this.getAttachmentAtRange(range); 9519 if (attachment) { 9520 return this.editAttachment(attachment); 9521 } 9522 } 9523 } 9524 expandSelectionInDirection(direction) { 9525 let { 9526 length 9527 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 9528 const range = this.getExpandedRangeInDirection(direction, { 9529 length 9530 }); 9531 return this.setSelectedRange(range); 9532 } 9533 expandSelectionForEditing() { 9534 if (this.hasCurrentAttribute("href")) { 9535 return this.expandSelectionAroundCommonAttribute("href"); 9536 } 9537 } 9538 expandSelectionAroundCommonAttribute(attributeName) { 9539 const position = this.getPosition(); 9540 const range = this.document.getRangeOfCommonAttributeAtPosition(attributeName, position); 9541 return this.setSelectedRange(range); 9542 } 9543 selectionContainsAttachments() { 9544 var _this$getSelectedAtta; 9545 return ((_this$getSelectedAtta = this.getSelectedAttachments()) === null || _this$getSelectedAtta === void 0 ? void 0 : _this$getSelectedAtta.length) > 0; 9546 } 9547 selectionIsInCursorTarget() { 9548 return this.editingAttachment || this.positionIsCursorTarget(this.getPosition()); 9549 } 9550 positionIsCursorTarget(position) { 9551 const location = this.document.locationFromPosition(position); 9552 if (location) { 9553 return this.locationIsCursorTarget(location); 9554 } 9555 } 9556 positionIsBlockBreak(position) { 9557 var _this$document$getPie; 9558 return (_this$document$getPie = this.document.getPieceAtPosition(position)) === null || _this$document$getPie === void 0 ? void 0 : _this$document$getPie.isBlockBreak(); 9559 } 9560 getSelectedDocument() { 9561 const selectedRange = this.getSelectedRange(); 9562 if (selectedRange) { 9563 return this.document.getDocumentAtRange(selectedRange); 9564 } 9565 } 9566 getSelectedAttachments() { 9567 var _this$getSelectedDocu; 9568 return (_this$getSelectedDocu = this.getSelectedDocument()) === null || _this$getSelectedDocu === void 0 ? void 0 : _this$getSelectedDocu.getAttachments(); 9569 } 9570 9571 // Attachments 9572 9573 getAttachments() { 9574 return this.attachments.slice(0); 9575 } 9576 refreshAttachments() { 9577 const attachments = this.document.getAttachments(); 9578 const { 9579 added, 9580 removed 9581 } = summarizeArrayChange(this.attachments, attachments); 9582 this.attachments = attachments; 9583 Array.from(removed).forEach(attachment => { 9584 var _this$delegate6, _this$delegate6$compo; 9585 attachment.delegate = null; 9586 (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || (_this$delegate6$compo = _this$delegate6.compositionDidRemoveAttachment) === null || _this$delegate6$compo === void 0 || _this$delegate6$compo.call(_this$delegate6, attachment); 9587 }); 9588 return (() => { 9589 const result = []; 9590 Array.from(added).forEach(attachment => { 9591 var _this$delegate7, _this$delegate7$compo; 9592 attachment.delegate = this; 9593 result.push((_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || (_this$delegate7$compo = _this$delegate7.compositionDidAddAttachment) === null || _this$delegate7$compo === void 0 ? void 0 : _this$delegate7$compo.call(_this$delegate7, attachment)); 9594 }); 9595 return result; 9596 })(); 9597 } 9598 9599 // Attachment delegate 9600 9601 attachmentDidChangeAttributes(attachment) { 9602 var _this$delegate8, _this$delegate8$compo; 9603 this.revision++; 9604 return (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || (_this$delegate8$compo = _this$delegate8.compositionDidEditAttachment) === null || _this$delegate8$compo === void 0 ? void 0 : _this$delegate8$compo.call(_this$delegate8, attachment); 9605 } 9606 attachmentDidChangePreviewURL(attachment) { 9607 var _this$delegate9, _this$delegate9$compo; 9608 this.revision++; 9609 return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || (_this$delegate9$compo = _this$delegate9.compositionDidChangeAttachmentPreviewURL) === null || _this$delegate9$compo === void 0 ? void 0 : _this$delegate9$compo.call(_this$delegate9, attachment); 9610 } 9611 9612 // Attachment editing 9613 9614 editAttachment(attachment, options) { 9615 var _this$delegate10, _this$delegate10$comp; 9616 if (attachment === this.editingAttachment) return; 9617 this.stopEditingAttachment(); 9618 this.editingAttachment = attachment; 9619 return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 || (_this$delegate10$comp = _this$delegate10.compositionDidStartEditingAttachment) === null || _this$delegate10$comp === void 0 ? void 0 : _this$delegate10$comp.call(_this$delegate10, this.editingAttachment, options); 9620 } 9621 stopEditingAttachment() { 9622 var _this$delegate11, _this$delegate11$comp; 9623 if (!this.editingAttachment) return; 9624 (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 || (_this$delegate11$comp = _this$delegate11.compositionDidStopEditingAttachment) === null || _this$delegate11$comp === void 0 || _this$delegate11$comp.call(_this$delegate11, this.editingAttachment); 9625 this.editingAttachment = null; 9626 } 9627 updateAttributesForAttachment(attributes, attachment) { 9628 return this.setDocument(this.document.updateAttributesForAttachment(attributes, attachment)); 9629 } 9630 removeAttributeForAttachment(attribute, attachment) { 9631 return this.setDocument(this.document.removeAttributeForAttachment(attribute, attachment)); 9632 } 9633 9634 // Private 9635 9636 breakFormattedBlock(insertion) { 9637 let { 9638 document 9639 } = insertion; 9640 const { 9641 block 9642 } = insertion; 9643 let position = insertion.startPosition; 9644 let range = [position - 1, position]; 9645 if (block.getBlockBreakPosition() === insertion.startLocation.offset) { 9646 if (block.breaksOnReturn() && insertion.nextCharacter === "\n") { 9647 position += 1; 9648 } else { 9649 document = document.removeTextAtRange(range); 9650 } 9651 range = [position, position]; 9652 } else if (insertion.nextCharacter === "\n") { 9653 if (insertion.previousCharacter === "\n") { 9654 range = [position - 1, position + 1]; 9655 } else { 9656 range = [position, position + 1]; 9657 position += 1; 9658 } 9659 } else if (insertion.startLocation.offset - 1 !== 0) { 9660 position += 1; 9661 } 9662 const newDocument = new Document([block.removeLastAttribute().copyWithoutText()]); 9663 this.setDocument(document.insertDocumentAtRange(newDocument, range)); 9664 return this.setSelection(position); 9665 } 9666 getPreviousBlock() { 9667 const locationRange = this.getLocationRange(); 9668 if (locationRange) { 9669 const { 9670 index 9671 } = locationRange[0]; 9672 if (index > 0) { 9673 return this.document.getBlockAtIndex(index - 1); 9674 } 9675 } 9676 } 9677 getBlock() { 9678 const locationRange = this.getLocationRange(); 9679 if (locationRange) { 9680 return this.document.getBlockAtIndex(locationRange[0].index); 9681 } 9682 } 9683 getAttachmentAtRange(range) { 9684 const document = this.document.getDocumentAtRange(range); 9685 if (document.toString() === "".concat(OBJECT_REPLACEMENT_CHARACTER, "\n")) { 9686 return document.getAttachments()[0]; 9687 } 9688 } 9689 notifyDelegateOfCurrentAttributesChange() { 9690 var _this$delegate12, _this$delegate12$comp; 9691 return (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 || (_this$delegate12$comp = _this$delegate12.compositionDidChangeCurrentAttributes) === null || _this$delegate12$comp === void 0 ? void 0 : _this$delegate12$comp.call(_this$delegate12, this.currentAttributes); 9692 } 9693 notifyDelegateOfInsertionAtRange(range) { 9694 var _this$delegate13, _this$delegate13$comp; 9695 return (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 || (_this$delegate13$comp = _this$delegate13.compositionDidPerformInsertionAtRange) === null || _this$delegate13$comp === void 0 ? void 0 : _this$delegate13$comp.call(_this$delegate13, range); 9696 } 9697 translateUTF16PositionFromOffset(position, offset) { 9698 const utf16string = this.document.toUTF16String(); 9699 const utf16position = utf16string.offsetFromUCS2Offset(position); 9700 return utf16string.offsetToUCS2Offset(utf16position + offset); 9701 } 9702 } 9703 Composition.proxyMethod("getSelectionManager().getPointRange"); 9704 Composition.proxyMethod("getSelectionManager().setLocationRangeFromPointRange"); 9705 Composition.proxyMethod("getSelectionManager().createLocationRangeFromDOMRange"); 9706 Composition.proxyMethod("getSelectionManager().locationIsCursorTarget"); 9707 Composition.proxyMethod("getSelectionManager().selectionIsExpanded"); 9708 Composition.proxyMethod("delegate?.getSelectionManager"); 9709 9710 class UndoManager extends BasicObject { 9711 constructor(composition) { 9712 super(...arguments); 9713 this.composition = composition; 9714 this.undoEntries = []; 9715 this.redoEntries = []; 9716 } 9717 recordUndoEntry(description) { 9718 let { 9719 context, 9720 consolidatable 9721 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 9722 const previousEntry = this.undoEntries.slice(-1)[0]; 9723 if (!consolidatable || !entryHasDescriptionAndContext(previousEntry, description, context)) { 9724 const undoEntry = this.createEntry({ 9725 description, 9726 context 9727 }); 9728 this.undoEntries.push(undoEntry); 9729 this.redoEntries = []; 9730 } 9731 } 9732 undo() { 9733 const undoEntry = this.undoEntries.pop(); 9734 if (undoEntry) { 9735 const redoEntry = this.createEntry(undoEntry); 9736 this.redoEntries.push(redoEntry); 9737 return this.composition.loadSnapshot(undoEntry.snapshot); 9738 } 9739 } 9740 redo() { 9741 const redoEntry = this.redoEntries.pop(); 9742 if (redoEntry) { 9743 const undoEntry = this.createEntry(redoEntry); 9744 this.undoEntries.push(undoEntry); 9745 return this.composition.loadSnapshot(redoEntry.snapshot); 9746 } 9747 } 9748 canUndo() { 9749 return this.undoEntries.length > 0; 9750 } 9751 canRedo() { 9752 return this.redoEntries.length > 0; 9753 } 9754 9755 // Private 9756 9757 createEntry() { 9758 let { 9759 description, 9760 context 9761 } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 9762 return { 9763 description: description === null || description === void 0 ? void 0 : description.toString(), 9764 context: JSON.stringify(context), 9765 snapshot: this.composition.getSnapshot() 9766 }; 9767 } 9768 } 9769 const entryHasDescriptionAndContext = (entry, description, context) => (entry === null || entry === void 0 ? void 0 : entry.description) === (description === null || description === void 0 ? void 0 : description.toString()) && (entry === null || entry === void 0 ? void 0 : entry.context) === JSON.stringify(context); 9770 9771 const BLOCK_ATTRIBUTE_NAME = "attachmentGallery"; 9772 const TEXT_ATTRIBUTE_NAME = "presentation"; 9773 const TEXT_ATTRIBUTE_VALUE = "gallery"; 9774 class Filter { 9775 constructor(snapshot) { 9776 this.document = snapshot.document; 9777 this.selectedRange = snapshot.selectedRange; 9778 } 9779 perform() { 9780 this.removeBlockAttribute(); 9781 return this.applyBlockAttribute(); 9782 } 9783 getSnapshot() { 9784 return { 9785 document: this.document, 9786 selectedRange: this.selectedRange 9787 }; 9788 } 9789 9790 // Private 9791 9792 removeBlockAttribute() { 9793 return this.findRangesOfBlocks().map(range => this.document = this.document.removeAttributeAtRange(BLOCK_ATTRIBUTE_NAME, range)); 9794 } 9795 applyBlockAttribute() { 9796 let offset = 0; 9797 this.findRangesOfPieces().forEach(range => { 9798 if (range[1] - range[0] > 1) { 9799 range[0] += offset; 9800 range[1] += offset; 9801 if (this.document.getCharacterAtPosition(range[1]) !== "\n") { 9802 this.document = this.document.insertBlockBreakAtRange(range[1]); 9803 if (range[1] < this.selectedRange[1]) { 9804 this.moveSelectedRangeForward(); 9805 } 9806 range[1]++; 9807 offset++; 9808 } 9809 if (range[0] !== 0) { 9810 if (this.document.getCharacterAtPosition(range[0] - 1) !== "\n") { 9811 this.document = this.document.insertBlockBreakAtRange(range[0]); 9812 if (range[0] < this.selectedRange[0]) { 9813 this.moveSelectedRangeForward(); 9814 } 9815 range[0]++; 9816 offset++; 9817 } 9818 } 9819 this.document = this.document.applyBlockAttributeAtRange(BLOCK_ATTRIBUTE_NAME, true, range); 9820 } 9821 }); 9822 } 9823 findRangesOfBlocks() { 9824 return this.document.findRangesForBlockAttribute(BLOCK_ATTRIBUTE_NAME); 9825 } 9826 findRangesOfPieces() { 9827 return this.document.findRangesForTextAttribute(TEXT_ATTRIBUTE_NAME, { 9828 withValue: TEXT_ATTRIBUTE_VALUE 9829 }); 9830 } 9831 moveSelectedRangeForward() { 9832 this.selectedRange[0] += 1; 9833 this.selectedRange[1] += 1; 9834 } 9835 } 9836 9837 const attachmentGalleryFilter = function (snapshot) { 9838 const filter = new Filter(snapshot); 9839 filter.perform(); 9840 return filter.getSnapshot(); 9841 }; 9842 9843 const DEFAULT_FILTERS = [attachmentGalleryFilter]; 9844 class Editor { 9845 constructor(composition, selectionManager, element) { 9846 this.insertFiles = this.insertFiles.bind(this); 9847 this.composition = composition; 9848 this.selectionManager = selectionManager; 9849 this.element = element; 9850 this.undoManager = new UndoManager(this.composition); 9851 this.filters = DEFAULT_FILTERS.slice(0); 9852 } 9853 loadDocument(document) { 9854 return this.loadSnapshot({ 9855 document, 9856 selectedRange: [0, 0] 9857 }); 9858 } 9859 loadHTML() { 9860 let html = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; 9861 const document = HTMLParser.parse(html, { 9862 referenceElement: this.element 9863 }).getDocument(); 9864 return this.loadDocument(document); 9865 } 9866 loadJSON(_ref) { 9867 let { 9868 document, 9869 selectedRange 9870 } = _ref; 9871 document = Document.fromJSON(document); 9872 return this.loadSnapshot({ 9873 document, 9874 selectedRange 9875 }); 9876 } 9877 loadSnapshot(snapshot) { 9878 this.undoManager = new UndoManager(this.composition); 9879 return this.composition.loadSnapshot(snapshot); 9880 } 9881 getDocument() { 9882 return this.composition.document; 9883 } 9884 getSelectedDocument() { 9885 return this.composition.getSelectedDocument(); 9886 } 9887 getSnapshot() { 9888 return this.composition.getSnapshot(); 9889 } 9890 toJSON() { 9891 return this.getSnapshot(); 9892 } 9893 9894 // Document manipulation 9895 9896 deleteInDirection(direction) { 9897 return this.composition.deleteInDirection(direction); 9898 } 9899 insertAttachment(attachment) { 9900 return this.composition.insertAttachment(attachment); 9901 } 9902 insertAttachments(attachments) { 9903 return this.composition.insertAttachments(attachments); 9904 } 9905 insertDocument(document) { 9906 return this.composition.insertDocument(document); 9907 } 9908 insertFile(file) { 9909 return this.composition.insertFile(file); 9910 } 9911 insertFiles(files) { 9912 return this.composition.insertFiles(files); 9913 } 9914 insertHTML(html) { 9915 return this.composition.insertHTML(html); 9916 } 9917 insertString(string) { 9918 return this.composition.insertString(string); 9919 } 9920 insertText(text) { 9921 return this.composition.insertText(text); 9922 } 9923 insertLineBreak() { 9924 return this.composition.insertLineBreak(); 9925 } 9926 9927 // Selection 9928 9929 getSelectedRange() { 9930 return this.composition.getSelectedRange(); 9931 } 9932 getPosition() { 9933 return this.composition.getPosition(); 9934 } 9935 getClientRectAtPosition(position) { 9936 const locationRange = this.getDocument().locationRangeFromRange([position, position + 1]); 9937 return this.selectionManager.getClientRectAtLocationRange(locationRange); 9938 } 9939 expandSelectionInDirection(direction) { 9940 return this.composition.expandSelectionInDirection(direction); 9941 } 9942 moveCursorInDirection(direction) { 9943 return this.composition.moveCursorInDirection(direction); 9944 } 9945 setSelectedRange(selectedRange) { 9946 return this.composition.setSelectedRange(selectedRange); 9947 } 9948 9949 // Attributes 9950 9951 activateAttribute(name) { 9952 let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; 9953 return this.composition.setCurrentAttribute(name, value); 9954 } 9955 attributeIsActive(name) { 9956 return this.composition.hasCurrentAttribute(name); 9957 } 9958 canActivateAttribute(name) { 9959 return this.composition.canSetCurrentAttribute(name); 9960 } 9961 deactivateAttribute(name) { 9962 return this.composition.removeCurrentAttribute(name); 9963 } 9964 9965 // HTML attributes 9966 setHTMLAtributeAtPosition(position, name, value) { 9967 this.composition.setHTMLAtributeAtPosition(position, name, value); 9968 } 9969 9970 // Nesting level 9971 9972 canDecreaseNestingLevel() { 9973 return this.composition.canDecreaseNestingLevel(); 9974 } 9975 canIncreaseNestingLevel() { 9976 return this.composition.canIncreaseNestingLevel(); 9977 } 9978 decreaseNestingLevel() { 9979 if (this.canDecreaseNestingLevel()) { 9980 return this.composition.decreaseNestingLevel(); 9981 } 9982 } 9983 increaseNestingLevel() { 9984 if (this.canIncreaseNestingLevel()) { 9985 return this.composition.increaseNestingLevel(); 9986 } 9987 } 9988 9989 // Undo/redo 9990 9991 canRedo() { 9992 return this.undoManager.canRedo(); 9993 } 9994 canUndo() { 9995 return this.undoManager.canUndo(); 9996 } 9997 recordUndoEntry(description) { 9998 let { 9999 context, 10000 consolidatable 10001 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 10002 return this.undoManager.recordUndoEntry(description, { 10003 context, 10004 consolidatable 10005 }); 10006 } 10007 redo() { 10008 if (this.canRedo()) { 10009 return this.undoManager.redo(); 10010 } 10011 } 10012 undo() { 10013 if (this.canUndo()) { 10014 return this.undoManager.undo(); 10015 } 10016 } 10017 } 10018 10019 /* eslint-disable 10020 no-var, 10021 prefer-const, 10022 */ 10023 class LocationMapper { 10024 constructor(element) { 10025 this.element = element; 10026 } 10027 findLocationFromContainerAndOffset(container, offset) { 10028 let { 10029 strict 10030 } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { 10031 strict: true 10032 }; 10033 let childIndex = 0; 10034 let foundBlock = false; 10035 const location = { 10036 index: 0, 10037 offset: 0 10038 }; 10039 const attachmentElement = this.findAttachmentElementParentForNode(container); 10040 if (attachmentElement) { 10041 container = attachmentElement.parentNode; 10042 offset = findChildIndexOfNode(attachmentElement); 10043 } 10044 const walker = walkTree(this.element, { 10045 usingFilter: rejectAttachmentContents 10046 }); 10047 while (walker.nextNode()) { 10048 const node = walker.currentNode; 10049 if (node === container && nodeIsTextNode(container)) { 10050 if (!nodeIsCursorTarget(node)) { 10051 location.offset += offset; 10052 } 10053 break; 10054 } else { 10055 if (node.parentNode === container) { 10056 if (childIndex++ === offset) { 10057 if (!strict && nodeIsBlockStart(node, { 10058 strict 10059 })) { 10060 if (foundBlock) { 10061 location.index++; 10062 } 10063 location.offset = 0; 10064 foundBlock = true; 10065 } 10066 break; 10067 } 10068 } else if (!elementContainsNode(container, node)) { 10069 if (childIndex > 0) { 10070 break; 10071 } 10072 } 10073 if (nodeIsBlockStart(node, { 10074 strict 10075 })) { 10076 if (foundBlock) { 10077 location.index++; 10078 } 10079 location.offset = 0; 10080 foundBlock = true; 10081 } else { 10082 location.offset += nodeLength(node); 10083 } 10084 } 10085 } 10086 return location; 10087 } 10088 findContainerAndOffsetFromLocation(location) { 10089 let container, offset; 10090 if (location.index === 0 && location.offset === 0) { 10091 container = this.element; 10092 offset = 0; 10093 while (container.firstChild) { 10094 container = container.firstChild; 10095 if (nodeIsBlockContainer(container)) { 10096 offset = 1; 10097 break; 10098 } 10099 } 10100 return [container, offset]; 10101 } 10102 let [node, nodeOffset] = this.findNodeAndOffsetFromLocation(location); 10103 if (!node) return; 10104 if (nodeIsTextNode(node)) { 10105 if (nodeLength(node) === 0) { 10106 container = node.parentNode.parentNode; 10107 offset = findChildIndexOfNode(node.parentNode); 10108 if (nodeIsCursorTarget(node, { 10109 name: "right" 10110 })) { 10111 offset++; 10112 } 10113 } else { 10114 container = node; 10115 offset = location.offset - nodeOffset; 10116 } 10117 } else { 10118 container = node.parentNode; 10119 if (!nodeIsBlockStart(node.previousSibling)) { 10120 if (!nodeIsBlockContainer(container)) { 10121 while (node === container.lastChild) { 10122 node = container; 10123 container = container.parentNode; 10124 if (nodeIsBlockContainer(container)) { 10125 break; 10126 } 10127 } 10128 } 10129 } 10130 offset = findChildIndexOfNode(node); 10131 if (location.offset !== 0) { 10132 offset++; 10133 } 10134 } 10135 return [container, offset]; 10136 } 10137 findNodeAndOffsetFromLocation(location) { 10138 let node, nodeOffset; 10139 let offset = 0; 10140 for (const currentNode of this.getSignificantNodesForIndex(location.index)) { 10141 const length = nodeLength(currentNode); 10142 if (location.offset <= offset + length) { 10143 if (nodeIsTextNode(currentNode)) { 10144 node = currentNode; 10145 nodeOffset = offset; 10146 if (location.offset === nodeOffset && nodeIsCursorTarget(node)) { 10147 break; 10148 } 10149 } else if (!node) { 10150 node = currentNode; 10151 nodeOffset = offset; 10152 } 10153 } 10154 offset += length; 10155 if (offset > location.offset) { 10156 break; 10157 } 10158 } 10159 return [node, nodeOffset]; 10160 } 10161 10162 // Private 10163 10164 findAttachmentElementParentForNode(node) { 10165 while (node && node !== this.element) { 10166 if (nodeIsAttachmentElement(node)) { 10167 return node; 10168 } 10169 node = node.parentNode; 10170 } 10171 } 10172 getSignificantNodesForIndex(index) { 10173 const nodes = []; 10174 const walker = walkTree(this.element, { 10175 usingFilter: acceptSignificantNodes 10176 }); 10177 let recordingNodes = false; 10178 while (walker.nextNode()) { 10179 const node = walker.currentNode; 10180 if (nodeIsBlockStartComment(node)) { 10181 var blockIndex; 10182 if (blockIndex != null) { 10183 blockIndex++; 10184 } else { 10185 blockIndex = 0; 10186 } 10187 if (blockIndex === index) { 10188 recordingNodes = true; 10189 } else if (recordingNodes) { 10190 break; 10191 } 10192 } else if (recordingNodes) { 10193 nodes.push(node); 10194 } 10195 } 10196 return nodes; 10197 } 10198 } 10199 const nodeLength = function (node) { 10200 if (node.nodeType === Node.TEXT_NODE) { 10201 if (nodeIsCursorTarget(node)) { 10202 return 0; 10203 } else { 10204 const string = node.textContent; 10205 return string.length; 10206 } 10207 } else if (tagName(node) === "br" || nodeIsAttachmentElement(node)) { 10208 return 1; 10209 } else { 10210 return 0; 10211 } 10212 }; 10213 const acceptSignificantNodes = function (node) { 10214 if (rejectEmptyTextNodes(node) === NodeFilter.FILTER_ACCEPT) { 10215 return rejectAttachmentContents(node); 10216 } else { 10217 return NodeFilter.FILTER_REJECT; 10218 } 10219 }; 10220 const rejectEmptyTextNodes = function (node) { 10221 if (nodeIsEmptyTextNode(node)) { 10222 return NodeFilter.FILTER_REJECT; 10223 } else { 10224 return NodeFilter.FILTER_ACCEPT; 10225 } 10226 }; 10227 const rejectAttachmentContents = function (node) { 10228 if (nodeIsAttachmentElement(node.parentNode)) { 10229 return NodeFilter.FILTER_REJECT; 10230 } else { 10231 return NodeFilter.FILTER_ACCEPT; 10232 } 10233 }; 10234 10235 /* eslint-disable 10236 id-length, 10237 no-empty, 10238 */ 10239 class PointMapper { 10240 createDOMRangeFromPoint(_ref) { 10241 let { 10242 x, 10243 y 10244 } = _ref; 10245 let domRange; 10246 if (document.caretPositionFromPoint) { 10247 const { 10248 offsetNode, 10249 offset 10250 } = document.caretPositionFromPoint(x, y); 10251 domRange = document.createRange(); 10252 domRange.setStart(offsetNode, offset); 10253 return domRange; 10254 } else if (document.caretRangeFromPoint) { 10255 return document.caretRangeFromPoint(x, y); 10256 } else if (document.body.createTextRange) { 10257 const originalDOMRange = getDOMRange(); 10258 try { 10259 // IE 11 throws "Unspecified error" when using moveToPoint 10260 // during a drag-and-drop operation. 10261 const textRange = document.body.createTextRange(); 10262 textRange.moveToPoint(x, y); 10263 textRange.select(); 10264 } catch (error) {} 10265 domRange = getDOMRange(); 10266 setDOMRange(originalDOMRange); 10267 return domRange; 10268 } 10269 } 10270 getClientRectsForDOMRange(domRange) { 10271 const array = Array.from(domRange.getClientRects()); 10272 const start = array[0]; 10273 const end = array[array.length - 1]; 10274 return [start, end]; 10275 } 10276 } 10277 10278 /* eslint-disable 10279 */ 10280 class SelectionManager extends BasicObject { 10281 constructor(element) { 10282 super(...arguments); 10283 this.didMouseDown = this.didMouseDown.bind(this); 10284 this.selectionDidChange = this.selectionDidChange.bind(this); 10285 this.element = element; 10286 this.locationMapper = new LocationMapper(this.element); 10287 this.pointMapper = new PointMapper(); 10288 this.lockCount = 0; 10289 handleEvent("mousedown", { 10290 onElement: this.element, 10291 withCallback: this.didMouseDown 10292 }); 10293 } 10294 getLocationRange() { 10295 let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 10296 if (options.strict === false) { 10297 return this.createLocationRangeFromDOMRange(getDOMRange()); 10298 } else if (options.ignoreLock) { 10299 return this.currentLocationRange; 10300 } else if (this.lockedLocationRange) { 10301 return this.lockedLocationRange; 10302 } else { 10303 return this.currentLocationRange; 10304 } 10305 } 10306 setLocationRange(locationRange) { 10307 if (this.lockedLocationRange) return; 10308 locationRange = normalizeRange(locationRange); 10309 const domRange = this.createDOMRangeFromLocationRange(locationRange); 10310 if (domRange) { 10311 setDOMRange(domRange); 10312 this.updateCurrentLocationRange(locationRange); 10313 } 10314 } 10315 setLocationRangeFromPointRange(pointRange) { 10316 pointRange = normalizeRange(pointRange); 10317 const startLocation = this.getLocationAtPoint(pointRange[0]); 10318 const endLocation = this.getLocationAtPoint(pointRange[1]); 10319 this.setLocationRange([startLocation, endLocation]); 10320 } 10321 getClientRectAtLocationRange(locationRange) { 10322 const domRange = this.createDOMRangeFromLocationRange(locationRange); 10323 if (domRange) { 10324 return this.getClientRectsForDOMRange(domRange)[1]; 10325 } 10326 } 10327 locationIsCursorTarget(location) { 10328 const node = Array.from(this.findNodeAndOffsetFromLocation(location))[0]; 10329 return nodeIsCursorTarget(node); 10330 } 10331 lock() { 10332 if (this.lockCount++ === 0) { 10333 this.updateCurrentLocationRange(); 10334 this.lockedLocationRange = this.getLocationRange(); 10335 } 10336 } 10337 unlock() { 10338 if (--this.lockCount === 0) { 10339 const { 10340 lockedLocationRange 10341 } = this; 10342 this.lockedLocationRange = null; 10343 if (lockedLocationRange != null) { 10344 return this.setLocationRange(lockedLocationRange); 10345 } 10346 } 10347 } 10348 clearSelection() { 10349 var _getDOMSelection; 10350 return (_getDOMSelection = getDOMSelection()) === null || _getDOMSelection === void 0 ? void 0 : _getDOMSelection.removeAllRanges(); 10351 } 10352 selectionIsCollapsed() { 10353 var _getDOMRange; 10354 return ((_getDOMRange = getDOMRange()) === null || _getDOMRange === void 0 ? void 0 : _getDOMRange.collapsed) === true; 10355 } 10356 selectionIsExpanded() { 10357 return !this.selectionIsCollapsed(); 10358 } 10359 createLocationRangeFromDOMRange(domRange, options) { 10360 if (domRange == null || !this.domRangeWithinElement(domRange)) return; 10361 const start = this.findLocationFromContainerAndOffset(domRange.startContainer, domRange.startOffset, options); 10362 if (!start) return; 10363 const end = domRange.collapsed ? undefined : this.findLocationFromContainerAndOffset(domRange.endContainer, domRange.endOffset, options); 10364 return normalizeRange([start, end]); 10365 } 10366 didMouseDown() { 10367 return this.pauseTemporarily(); 10368 } 10369 pauseTemporarily() { 10370 let resumeHandlers; 10371 this.paused = true; 10372 const resume = () => { 10373 this.paused = false; 10374 clearTimeout(resumeTimeout); 10375 Array.from(resumeHandlers).forEach(handler => { 10376 handler.destroy(); 10377 }); 10378 if (elementContainsNode(document, this.element)) { 10379 return this.selectionDidChange(); 10380 } 10381 }; 10382 const resumeTimeout = setTimeout(resume, 200); 10383 resumeHandlers = ["mousemove", "keydown"].map(eventName => handleEvent(eventName, { 10384 onElement: document, 10385 withCallback: resume 10386 })); 10387 } 10388 selectionDidChange() { 10389 if (!this.paused && !innerElementIsActive(this.element)) { 10390 return this.updateCurrentLocationRange(); 10391 } 10392 } 10393 updateCurrentLocationRange(locationRange) { 10394 if (locationRange != null ? locationRange : locationRange = this.createLocationRangeFromDOMRange(getDOMRange())) { 10395 if (!rangesAreEqual(locationRange, this.currentLocationRange)) { 10396 var _this$delegate, _this$delegate$locati; 10397 this.currentLocationRange = locationRange; 10398 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$locati = _this$delegate.locationRangeDidChange) === null || _this$delegate$locati === void 0 ? void 0 : _this$delegate$locati.call(_this$delegate, this.currentLocationRange.slice(0)); 10399 } 10400 } 10401 } 10402 createDOMRangeFromLocationRange(locationRange) { 10403 const rangeStart = this.findContainerAndOffsetFromLocation(locationRange[0]); 10404 const rangeEnd = rangeIsCollapsed(locationRange) ? rangeStart : this.findContainerAndOffsetFromLocation(locationRange[1]) || rangeStart; 10405 if (rangeStart != null && rangeEnd != null) { 10406 const domRange = document.createRange(); 10407 domRange.setStart(...Array.from(rangeStart || [])); 10408 domRange.setEnd(...Array.from(rangeEnd || [])); 10409 return domRange; 10410 } 10411 } 10412 getLocationAtPoint(point) { 10413 const domRange = this.createDOMRangeFromPoint(point); 10414 if (domRange) { 10415 var _this$createLocationR; 10416 return (_this$createLocationR = this.createLocationRangeFromDOMRange(domRange)) === null || _this$createLocationR === void 0 ? void 0 : _this$createLocationR[0]; 10417 } 10418 } 10419 domRangeWithinElement(domRange) { 10420 if (domRange.collapsed) { 10421 return elementContainsNode(this.element, domRange.startContainer); 10422 } else { 10423 return elementContainsNode(this.element, domRange.startContainer) && elementContainsNode(this.element, domRange.endContainer); 10424 } 10425 } 10426 } 10427 SelectionManager.proxyMethod("locationMapper.findLocationFromContainerAndOffset"); 10428 SelectionManager.proxyMethod("locationMapper.findContainerAndOffsetFromLocation"); 10429 SelectionManager.proxyMethod("locationMapper.findNodeAndOffsetFromLocation"); 10430 SelectionManager.proxyMethod("pointMapper.createDOMRangeFromPoint"); 10431 SelectionManager.proxyMethod("pointMapper.getClientRectsForDOMRange"); 10432 10433 var models = /*#__PURE__*/Object.freeze({ 10434 __proto__: null, 10435 Attachment: Attachment, 10436 AttachmentManager: AttachmentManager, 10437 AttachmentPiece: AttachmentPiece, 10438 Block: Block, 10439 Composition: Composition, 10440 Document: Document, 10441 Editor: Editor, 10442 HTMLParser: HTMLParser, 10443 HTMLSanitizer: HTMLSanitizer, 10444 LineBreakInsertion: LineBreakInsertion, 10445 LocationMapper: LocationMapper, 10446 ManagedAttachment: ManagedAttachment, 10447 Piece: Piece, 10448 PointMapper: PointMapper, 10449 SelectionManager: SelectionManager, 10450 SplittableList: SplittableList, 10451 StringPiece: StringPiece, 10452 Text: Text, 10453 UndoManager: UndoManager 10454 }); 10455 10456 var views = /*#__PURE__*/Object.freeze({ 10457 __proto__: null, 10458 ObjectView: ObjectView, 10459 AttachmentView: AttachmentView, 10460 BlockView: BlockView, 10461 DocumentView: DocumentView, 10462 PieceView: PieceView, 10463 PreviewableAttachmentView: PreviewableAttachmentView, 10464 TextView: TextView 10465 }); 10466 10467 const { 10468 lang, 10469 css, 10470 keyNames: keyNames$1 10471 } = config; 10472 const undoable = function (fn) { 10473 return function () { 10474 const commands = fn.apply(this, arguments); 10475 commands.do(); 10476 if (!this.undos) { 10477 this.undos = []; 10478 } 10479 this.undos.push(commands.undo); 10480 }; 10481 }; 10482 class AttachmentEditorController extends BasicObject { 10483 constructor(attachmentPiece, _element, container) { 10484 let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; 10485 super(...arguments); 10486 // Installing and uninstalling 10487 _defineProperty(this, "makeElementMutable", undoable(() => { 10488 return { 10489 do: () => { 10490 this.element.dataset.trixMutable = true; 10491 }, 10492 undo: () => delete this.element.dataset.trixMutable 10493 }; 10494 })); 10495 _defineProperty(this, "addToolbar", undoable(() => { 10496 // <div class="#{css.attachmentMetadataContainer}" data-trix-mutable="true"> 10497 // <div class="trix-button-row"> 10498 // <span class="trix-button-group trix-button-group--actions"> 10499 // <button type="button" class="trix-button trix-button--remove" title="#{lang.remove}" data-trix-action="remove">#{lang.remove}</button> 10500 // </span> 10501 // </div> 10502 // </div> 10503 const element = makeElement({ 10504 tagName: "div", 10505 className: css.attachmentToolbar, 10506 data: { 10507 trixMutable: true 10508 }, 10509 childNodes: makeElement({ 10510 tagName: "div", 10511 className: "trix-button-row", 10512 childNodes: makeElement({ 10513 tagName: "span", 10514 className: "trix-button-group trix-button-group--actions", 10515 childNodes: makeElement({ 10516 tagName: "button", 10517 className: "trix-button trix-button--remove", 10518 textContent: lang.remove, 10519 attributes: { 10520 title: lang.remove 10521 }, 10522 data: { 10523 trixAction: "remove" 10524 } 10525 }) 10526 }) 10527 }) 10528 }); 10529 if (this.attachment.isPreviewable()) { 10530 // <div class="#{css.attachmentMetadataContainer}"> 10531 // <span class="#{css.attachmentMetadata}"> 10532 // <span class="#{css.attachmentName}" title="#{name}">#{name}</span> 10533 // <span class="#{css.attachmentSize}">#{size}</span> 10534 // </span> 10535 // </div> 10536 element.appendChild(makeElement({ 10537 tagName: "div", 10538 className: css.attachmentMetadataContainer, 10539 childNodes: makeElement({ 10540 tagName: "span", 10541 className: css.attachmentMetadata, 10542 childNodes: [makeElement({ 10543 tagName: "span", 10544 className: css.attachmentName, 10545 textContent: this.attachment.getFilename(), 10546 attributes: { 10547 title: this.attachment.getFilename() 10548 } 10549 }), makeElement({ 10550 tagName: "span", 10551 className: css.attachmentSize, 10552 textContent: this.attachment.getFormattedFilesize() 10553 })] 10554 }) 10555 })); 10556 } 10557 handleEvent("click", { 10558 onElement: element, 10559 withCallback: this.didClickToolbar 10560 }); 10561 handleEvent("click", { 10562 onElement: element, 10563 matchingSelector: "[data-trix-action]", 10564 withCallback: this.didClickActionButton 10565 }); 10566 triggerEvent("trix-attachment-before-toolbar", { 10567 onElement: this.element, 10568 attributes: { 10569 toolbar: element, 10570 attachment: this.attachment 10571 } 10572 }); 10573 return { 10574 do: () => this.element.appendChild(element), 10575 undo: () => removeNode(element) 10576 }; 10577 })); 10578 _defineProperty(this, "installCaptionEditor", undoable(() => { 10579 const textarea = makeElement({ 10580 tagName: "textarea", 10581 className: css.attachmentCaptionEditor, 10582 attributes: { 10583 placeholder: lang.captionPlaceholder 10584 }, 10585 data: { 10586 trixMutable: true 10587 } 10588 }); 10589 textarea.value = this.attachmentPiece.getCaption(); 10590 const textareaClone = textarea.cloneNode(); 10591 textareaClone.classList.add("trix-autoresize-clone"); 10592 textareaClone.tabIndex = -1; 10593 const autoresize = function () { 10594 textareaClone.value = textarea.value; 10595 textarea.style.height = textareaClone.scrollHeight + "px"; 10596 }; 10597 handleEvent("input", { 10598 onElement: textarea, 10599 withCallback: autoresize 10600 }); 10601 handleEvent("input", { 10602 onElement: textarea, 10603 withCallback: this.didInputCaption 10604 }); 10605 handleEvent("keydown", { 10606 onElement: textarea, 10607 withCallback: this.didKeyDownCaption 10608 }); 10609 handleEvent("change", { 10610 onElement: textarea, 10611 withCallback: this.didChangeCaption 10612 }); 10613 handleEvent("blur", { 10614 onElement: textarea, 10615 withCallback: this.didBlurCaption 10616 }); 10617 const figcaption = this.element.querySelector("figcaption"); 10618 const editingFigcaption = figcaption.cloneNode(); 10619 return { 10620 do: () => { 10621 figcaption.style.display = "none"; 10622 editingFigcaption.appendChild(textarea); 10623 editingFigcaption.appendChild(textareaClone); 10624 editingFigcaption.classList.add("".concat(css.attachmentCaption, "--editing")); 10625 figcaption.parentElement.insertBefore(editingFigcaption, figcaption); 10626 autoresize(); 10627 if (this.options.editCaption) { 10628 return defer(() => textarea.focus()); 10629 } 10630 }, 10631 undo() { 10632 removeNode(editingFigcaption); 10633 figcaption.style.display = null; 10634 } 10635 }; 10636 })); 10637 this.didClickToolbar = this.didClickToolbar.bind(this); 10638 this.didClickActionButton = this.didClickActionButton.bind(this); 10639 this.didKeyDownCaption = this.didKeyDownCaption.bind(this); 10640 this.didInputCaption = this.didInputCaption.bind(this); 10641 this.didChangeCaption = this.didChangeCaption.bind(this); 10642 this.didBlurCaption = this.didBlurCaption.bind(this); 10643 this.attachmentPiece = attachmentPiece; 10644 this.element = _element; 10645 this.container = container; 10646 this.options = options; 10647 this.attachment = this.attachmentPiece.attachment; 10648 if (tagName(this.element) === "a") { 10649 this.element = this.element.firstChild; 10650 } 10651 this.install(); 10652 } 10653 install() { 10654 this.makeElementMutable(); 10655 this.addToolbar(); 10656 if (this.attachment.isPreviewable()) { 10657 this.installCaptionEditor(); 10658 } 10659 } 10660 uninstall() { 10661 var _this$delegate; 10662 let undo = this.undos.pop(); 10663 this.savePendingCaption(); 10664 while (undo) { 10665 undo(); 10666 undo = this.undos.pop(); 10667 } 10668 (_this$delegate = this.delegate) === null || _this$delegate === void 0 || _this$delegate.didUninstallAttachmentEditor(this); 10669 } 10670 10671 // Private 10672 10673 savePendingCaption() { 10674 if (this.pendingCaption != null) { 10675 const caption = this.pendingCaption; 10676 this.pendingCaption = null; 10677 if (caption) { 10678 var _this$delegate2, _this$delegate2$attac; 10679 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$attac = _this$delegate2.attachmentEditorDidRequestUpdatingAttributesForAttachment) === null || _this$delegate2$attac === void 0 || _this$delegate2$attac.call(_this$delegate2, { 10680 caption 10681 }, this.attachment); 10682 } else { 10683 var _this$delegate3, _this$delegate3$attac; 10684 (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || (_this$delegate3$attac = _this$delegate3.attachmentEditorDidRequestRemovingAttributeForAttachment) === null || _this$delegate3$attac === void 0 || _this$delegate3$attac.call(_this$delegate3, "caption", this.attachment); 10685 } 10686 } 10687 } 10688 // Event handlers 10689 10690 didClickToolbar(event) { 10691 event.preventDefault(); 10692 return event.stopPropagation(); 10693 } 10694 didClickActionButton(event) { 10695 var _this$delegate4; 10696 const action = event.target.getAttribute("data-trix-action"); 10697 switch (action) { 10698 case "remove": 10699 return (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 ? void 0 : _this$delegate4.attachmentEditorDidRequestRemovalOfAttachment(this.attachment); 10700 } 10701 } 10702 didKeyDownCaption(event) { 10703 if (keyNames$1[event.keyCode] === "return") { 10704 var _this$delegate5, _this$delegate5$attac; 10705 event.preventDefault(); 10706 this.savePendingCaption(); 10707 return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || (_this$delegate5$attac = _this$delegate5.attachmentEditorDidRequestDeselectingAttachment) === null || _this$delegate5$attac === void 0 ? void 0 : _this$delegate5$attac.call(_this$delegate5, this.attachment); 10708 } 10709 } 10710 didInputCaption(event) { 10711 this.pendingCaption = event.target.value.replace(/\s/g, " ").trim(); 10712 } 10713 didChangeCaption(event) { 10714 return this.savePendingCaption(); 10715 } 10716 didBlurCaption(event) { 10717 return this.savePendingCaption(); 10718 } 10719 } 10720 10721 class CompositionController extends BasicObject { 10722 constructor(element, composition) { 10723 super(...arguments); 10724 this.didFocus = this.didFocus.bind(this); 10725 this.didBlur = this.didBlur.bind(this); 10726 this.didClickAttachment = this.didClickAttachment.bind(this); 10727 this.element = element; 10728 this.composition = composition; 10729 this.documentView = new DocumentView(this.composition.document, { 10730 element: this.element 10731 }); 10732 handleEvent("focus", { 10733 onElement: this.element, 10734 withCallback: this.didFocus 10735 }); 10736 handleEvent("blur", { 10737 onElement: this.element, 10738 withCallback: this.didBlur 10739 }); 10740 handleEvent("click", { 10741 onElement: this.element, 10742 matchingSelector: "a[contenteditable=false]", 10743 preventDefault: true 10744 }); 10745 handleEvent("mousedown", { 10746 onElement: this.element, 10747 matchingSelector: attachmentSelector, 10748 withCallback: this.didClickAttachment 10749 }); 10750 handleEvent("click", { 10751 onElement: this.element, 10752 matchingSelector: "a".concat(attachmentSelector), 10753 preventDefault: true 10754 }); 10755 } 10756 didFocus(event) { 10757 var _this$blurPromise; 10758 const perform = () => { 10759 if (!this.focused) { 10760 var _this$delegate, _this$delegate$compos; 10761 this.focused = true; 10762 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$compos = _this$delegate.compositionControllerDidFocus) === null || _this$delegate$compos === void 0 ? void 0 : _this$delegate$compos.call(_this$delegate); 10763 } 10764 }; 10765 return ((_this$blurPromise = this.blurPromise) === null || _this$blurPromise === void 0 ? void 0 : _this$blurPromise.then(perform)) || perform(); 10766 } 10767 didBlur(event) { 10768 this.blurPromise = new Promise(resolve => { 10769 return defer(() => { 10770 if (!innerElementIsActive(this.element)) { 10771 var _this$delegate2, _this$delegate2$compo; 10772 this.focused = null; 10773 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$compo = _this$delegate2.compositionControllerDidBlur) === null || _this$delegate2$compo === void 0 || _this$delegate2$compo.call(_this$delegate2); 10774 } 10775 this.blurPromise = null; 10776 return resolve(); 10777 }); 10778 }); 10779 } 10780 didClickAttachment(event, target) { 10781 var _this$delegate3, _this$delegate3$compo; 10782 const attachment = this.findAttachmentForElement(target); 10783 const editCaption = !!findClosestElementFromNode(event.target, { 10784 matchingSelector: "figcaption" 10785 }); 10786 return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || (_this$delegate3$compo = _this$delegate3.compositionControllerDidSelectAttachment) === null || _this$delegate3$compo === void 0 ? void 0 : _this$delegate3$compo.call(_this$delegate3, attachment, { 10787 editCaption 10788 }); 10789 } 10790 getSerializableElement() { 10791 if (this.isEditingAttachment()) { 10792 return this.documentView.shadowElement; 10793 } else { 10794 return this.element; 10795 } 10796 } 10797 render() { 10798 var _this$delegate6, _this$delegate6$compo; 10799 if (this.revision !== this.composition.revision) { 10800 this.documentView.setDocument(this.composition.document); 10801 this.documentView.render(); 10802 this.revision = this.composition.revision; 10803 } 10804 if (this.canSyncDocumentView() && !this.documentView.isSynced()) { 10805 var _this$delegate4, _this$delegate4$compo, _this$delegate5, _this$delegate5$compo; 10806 (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || (_this$delegate4$compo = _this$delegate4.compositionControllerWillSyncDocumentView) === null || _this$delegate4$compo === void 0 || _this$delegate4$compo.call(_this$delegate4); 10807 this.documentView.sync(); 10808 (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || (_this$delegate5$compo = _this$delegate5.compositionControllerDidSyncDocumentView) === null || _this$delegate5$compo === void 0 || _this$delegate5$compo.call(_this$delegate5); 10809 } 10810 return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || (_this$delegate6$compo = _this$delegate6.compositionControllerDidRender) === null || _this$delegate6$compo === void 0 ? void 0 : _this$delegate6$compo.call(_this$delegate6); 10811 } 10812 rerenderViewForObject(object) { 10813 this.invalidateViewForObject(object); 10814 return this.render(); 10815 } 10816 invalidateViewForObject(object) { 10817 return this.documentView.invalidateViewForObject(object); 10818 } 10819 isViewCachingEnabled() { 10820 return this.documentView.isViewCachingEnabled(); 10821 } 10822 enableViewCaching() { 10823 return this.documentView.enableViewCaching(); 10824 } 10825 disableViewCaching() { 10826 return this.documentView.disableViewCaching(); 10827 } 10828 refreshViewCache() { 10829 return this.documentView.garbageCollectCachedViews(); 10830 } 10831 10832 // Attachment editor management 10833 10834 isEditingAttachment() { 10835 return !!this.attachmentEditor; 10836 } 10837 installAttachmentEditorForAttachment(attachment, options) { 10838 var _this$attachmentEdito; 10839 if (((_this$attachmentEdito = this.attachmentEditor) === null || _this$attachmentEdito === void 0 ? void 0 : _this$attachmentEdito.attachment) === attachment) return; 10840 const element = this.documentView.findElementForObject(attachment); 10841 if (!element) return; 10842 this.uninstallAttachmentEditor(); 10843 const attachmentPiece = this.composition.document.getAttachmentPieceForAttachment(attachment); 10844 this.attachmentEditor = new AttachmentEditorController(attachmentPiece, element, this.element, options); 10845 this.attachmentEditor.delegate = this; 10846 } 10847 uninstallAttachmentEditor() { 10848 var _this$attachmentEdito2; 10849 return (_this$attachmentEdito2 = this.attachmentEditor) === null || _this$attachmentEdito2 === void 0 ? void 0 : _this$attachmentEdito2.uninstall(); 10850 } 10851 10852 // Attachment controller delegate 10853 10854 didUninstallAttachmentEditor() { 10855 this.attachmentEditor = null; 10856 return this.render(); 10857 } 10858 attachmentEditorDidRequestUpdatingAttributesForAttachment(attributes, attachment) { 10859 var _this$delegate7, _this$delegate7$compo; 10860 (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || (_this$delegate7$compo = _this$delegate7.compositionControllerWillUpdateAttachment) === null || _this$delegate7$compo === void 0 || _this$delegate7$compo.call(_this$delegate7, attachment); 10861 return this.composition.updateAttributesForAttachment(attributes, attachment); 10862 } 10863 attachmentEditorDidRequestRemovingAttributeForAttachment(attribute, attachment) { 10864 var _this$delegate8, _this$delegate8$compo; 10865 (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || (_this$delegate8$compo = _this$delegate8.compositionControllerWillUpdateAttachment) === null || _this$delegate8$compo === void 0 || _this$delegate8$compo.call(_this$delegate8, attachment); 10866 return this.composition.removeAttributeForAttachment(attribute, attachment); 10867 } 10868 attachmentEditorDidRequestRemovalOfAttachment(attachment) { 10869 var _this$delegate9, _this$delegate9$compo; 10870 return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || (_this$delegate9$compo = _this$delegate9.compositionControllerDidRequestRemovalOfAttachment) === null || _this$delegate9$compo === void 0 ? void 0 : _this$delegate9$compo.call(_this$delegate9, attachment); 10871 } 10872 attachmentEditorDidRequestDeselectingAttachment(attachment) { 10873 var _this$delegate10, _this$delegate10$comp; 10874 return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 || (_this$delegate10$comp = _this$delegate10.compositionControllerDidRequestDeselectingAttachment) === null || _this$delegate10$comp === void 0 ? void 0 : _this$delegate10$comp.call(_this$delegate10, attachment); 10875 } 10876 10877 // Private 10878 10879 canSyncDocumentView() { 10880 return !this.isEditingAttachment(); 10881 } 10882 findAttachmentForElement(element) { 10883 return this.composition.document.getAttachmentById(parseInt(element.dataset.trixId, 10)); 10884 } 10885 } 10886 10887 class Controller extends BasicObject {} 10888 10889 const mutableAttributeName = "data-trix-mutable"; 10890 const mutableSelector = "[".concat(mutableAttributeName, "]"); 10891 const options = { 10892 attributes: true, 10893 childList: true, 10894 characterData: true, 10895 characterDataOldValue: true, 10896 subtree: true 10897 }; 10898 class MutationObserver extends BasicObject { 10899 constructor(element) { 10900 super(element); 10901 this.didMutate = this.didMutate.bind(this); 10902 this.element = element; 10903 this.observer = new window.MutationObserver(this.didMutate); 10904 this.start(); 10905 } 10906 start() { 10907 this.reset(); 10908 return this.observer.observe(this.element, options); 10909 } 10910 stop() { 10911 return this.observer.disconnect(); 10912 } 10913 didMutate(mutations) { 10914 this.mutations.push(...Array.from(this.findSignificantMutations(mutations) || [])); 10915 if (this.mutations.length) { 10916 var _this$delegate, _this$delegate$elemen; 10917 (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$elemen = _this$delegate.elementDidMutate) === null || _this$delegate$elemen === void 0 || _this$delegate$elemen.call(_this$delegate, this.getMutationSummary()); 10918 return this.reset(); 10919 } 10920 } 10921 10922 // Private 10923 10924 reset() { 10925 this.mutations = []; 10926 } 10927 findSignificantMutations(mutations) { 10928 return mutations.filter(mutation => { 10929 return this.mutationIsSignificant(mutation); 10930 }); 10931 } 10932 mutationIsSignificant(mutation) { 10933 if (this.nodeIsMutable(mutation.target)) { 10934 return false; 10935 } 10936 for (const node of Array.from(this.nodesModifiedByMutation(mutation))) { 10937 if (this.nodeIsSignificant(node)) return true; 10938 } 10939 return false; 10940 } 10941 nodeIsSignificant(node) { 10942 return node !== this.element && !this.nodeIsMutable(node) && !nodeIsEmptyTextNode(node); 10943 } 10944 nodeIsMutable(node) { 10945 return findClosestElementFromNode(node, { 10946 matchingSelector: mutableSelector 10947 }); 10948 } 10949 nodesModifiedByMutation(mutation) { 10950 const nodes = []; 10951 switch (mutation.type) { 10952 case "attributes": 10953 if (mutation.attributeName !== mutableAttributeName) { 10954 nodes.push(mutation.target); 10955 } 10956 break; 10957 case "characterData": 10958 // Changes to text nodes should consider the parent element 10959 nodes.push(mutation.target.parentNode); 10960 nodes.push(mutation.target); 10961 break; 10962 case "childList": 10963 // Consider each added or removed node 10964 nodes.push(...Array.from(mutation.addedNodes || [])); 10965 nodes.push(...Array.from(mutation.removedNodes || [])); 10966 break; 10967 } 10968 return nodes; 10969 } 10970 getMutationSummary() { 10971 return this.getTextMutationSummary(); 10972 } 10973 getTextMutationSummary() { 10974 const { 10975 additions, 10976 deletions 10977 } = this.getTextChangesFromCharacterData(); 10978 const textChanges = this.getTextChangesFromChildList(); 10979 Array.from(textChanges.additions).forEach(addition => { 10980 if (!Array.from(additions).includes(addition)) { 10981 additions.push(addition); 10982 } 10983 }); 10984 deletions.push(...Array.from(textChanges.deletions || [])); 10985 const summary = {}; 10986 const added = additions.join(""); 10987 if (added) { 10988 summary.textAdded = added; 10989 } 10990 const deleted = deletions.join(""); 10991 if (deleted) { 10992 summary.textDeleted = deleted; 10993 } 10994 return summary; 10995 } 10996 getMutationsByType(type) { 10997 return Array.from(this.mutations).filter(mutation => mutation.type === type); 10998 } 10999 getTextChangesFromChildList() { 11000 let textAdded, textRemoved; 11001 const addedNodes = []; 11002 const removedNodes = []; 11003 Array.from(this.getMutationsByType("childList")).forEach(mutation => { 11004 addedNodes.push(...Array.from(mutation.addedNodes || [])); 11005 removedNodes.push(...Array.from(mutation.removedNodes || [])); 11006 }); 11007 const singleBlockCommentRemoved = addedNodes.length === 0 && removedNodes.length === 1 && nodeIsBlockStartComment(removedNodes[0]); 11008 if (singleBlockCommentRemoved) { 11009 textAdded = []; 11010 textRemoved = ["\n"]; 11011 } else { 11012 textAdded = getTextForNodes(addedNodes); 11013 textRemoved = getTextForNodes(removedNodes); 11014 } 11015 const additions = textAdded.filter((text, index) => text !== textRemoved[index]).map(normalizeSpaces); 11016 const deletions = textRemoved.filter((text, index) => text !== textAdded[index]).map(normalizeSpaces); 11017 return { 11018 additions, 11019 deletions 11020 }; 11021 } 11022 getTextChangesFromCharacterData() { 11023 let added, removed; 11024 const characterMutations = this.getMutationsByType("characterData"); 11025 if (characterMutations.length) { 11026 const startMutation = characterMutations[0], 11027 endMutation = characterMutations[characterMutations.length - 1]; 11028 const oldString = normalizeSpaces(startMutation.oldValue); 11029 const newString = normalizeSpaces(endMutation.target.data); 11030 const summarized = summarizeStringChange(oldString, newString); 11031 added = summarized.added; 11032 removed = summarized.removed; 11033 } 11034 return { 11035 additions: added ? [added] : [], 11036 deletions: removed ? [removed] : [] 11037 }; 11038 } 11039 } 11040 const getTextForNodes = function () { 11041 let nodes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 11042 const text = []; 11043 for (const node of Array.from(nodes)) { 11044 switch (node.nodeType) { 11045 case Node.TEXT_NODE: 11046 text.push(node.data); 11047 break; 11048 case Node.ELEMENT_NODE: 11049 if (tagName(node) === "br") { 11050 text.push("\n"); 11051 } else { 11052 text.push(...Array.from(getTextForNodes(node.childNodes) || [])); 11053 } 11054 break; 11055 } 11056 } 11057 return text; 11058 }; 11059 11060 /* eslint-disable 11061 no-empty, 11062 */ 11063 class FileVerificationOperation extends Operation { 11064 constructor(file) { 11065 super(...arguments); 11066 this.file = file; 11067 } 11068 perform(callback) { 11069 const reader = new FileReader(); 11070 reader.onerror = () => callback(false); 11071 reader.onload = () => { 11072 reader.onerror = null; 11073 try { 11074 reader.abort(); 11075 } catch (error) {} 11076 return callback(true, this.file); 11077 }; 11078 return reader.readAsArrayBuffer(this.file); 11079 } 11080 } 11081 11082 // Each software keyboard on Android emits its own set of events and some of them can be buggy. 11083 // This class detects when some buggy events are being emitted and lets know the input controller 11084 // that they should be ignored. 11085 class FlakyAndroidKeyboardDetector { 11086 constructor(element) { 11087 this.element = element; 11088 } 11089 shouldIgnore(event) { 11090 if (!browser$1.samsungAndroid) return false; 11091 this.previousEvent = this.event; 11092 this.event = event; 11093 this.checkSamsungKeyboardBuggyModeStart(); 11094 this.checkSamsungKeyboardBuggyModeEnd(); 11095 return this.buggyMode; 11096 } 11097 11098 // private 11099 11100 // The Samsung keyboard on Android can enter a buggy state in which it emits a flurry of confused events that, 11101 // if processed, corrupts the editor. The buggy mode always starts with an insertText event, right after a 11102 // keydown event with for an "Unidentified" key, with the same text as the editor element, except for a few 11103 // extra whitespace, or exotic utf8, characters. 11104 checkSamsungKeyboardBuggyModeStart() { 11105 if (this.insertingLongTextAfterUnidentifiedChar() && differsInWhitespace(this.element.innerText, this.event.data)) { 11106 this.buggyMode = true; 11107 this.event.preventDefault(); 11108 } 11109 } 11110 11111 // The flurry of buggy events are always insertText. If we see any other type, it means it's over. 11112 checkSamsungKeyboardBuggyModeEnd() { 11113 if (this.buggyMode && this.event.inputType !== "insertText") { 11114 this.buggyMode = false; 11115 } 11116 } 11117 insertingLongTextAfterUnidentifiedChar() { 11118 var _this$event$data; 11119 return this.isBeforeInputInsertText() && this.previousEventWasUnidentifiedKeydown() && ((_this$event$data = this.event.data) === null || _this$event$data === void 0 ? void 0 : _this$event$data.length) > 50; 11120 } 11121 isBeforeInputInsertText() { 11122 return this.event.type === "beforeinput" && this.event.inputType === "insertText"; 11123 } 11124 previousEventWasUnidentifiedKeydown() { 11125 var _this$previousEvent, _this$previousEvent2; 11126 return ((_this$previousEvent = this.previousEvent) === null || _this$previousEvent === void 0 ? void 0 : _this$previousEvent.type) === "keydown" && ((_this$previousEvent2 = this.previousEvent) === null || _this$previousEvent2 === void 0 ? void 0 : _this$previousEvent2.key) === "Unidentified"; 11127 } 11128 } 11129 const differsInWhitespace = (text1, text2) => { 11130 return normalize(text1) === normalize(text2); 11131 }; 11132 const whiteSpaceNormalizerRegexp = new RegExp("(".concat(OBJECT_REPLACEMENT_CHARACTER, "|").concat(ZERO_WIDTH_SPACE, "|").concat(NON_BREAKING_SPACE, "|\\s)+"), "g"); 11133 const normalize = text => text.replace(whiteSpaceNormalizerRegexp, " ").trim(); 11134 11135 class InputController extends BasicObject { 11136 constructor(element) { 11137 super(...arguments); 11138 this.element = element; 11139 this.mutationObserver = new MutationObserver(this.element); 11140 this.mutationObserver.delegate = this; 11141 this.flakyKeyboardDetector = new FlakyAndroidKeyboardDetector(this.element); 11142 for (const eventName in this.constructor.events) { 11143 handleEvent(eventName, { 11144 onElement: this.element, 11145 withCallback: this.handlerFor(eventName) 11146 }); 11147 } 11148 } 11149 elementDidMutate(mutationSummary) {} 11150 editorWillSyncDocumentView() { 11151 return this.mutationObserver.stop(); 11152 } 11153 editorDidSyncDocumentView() { 11154 return this.mutationObserver.start(); 11155 } 11156 requestRender() { 11157 var _this$delegate, _this$delegate$inputC; 11158 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$inputC = _this$delegate.inputControllerDidRequestRender) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate); 11159 } 11160 requestReparse() { 11161 var _this$delegate2, _this$delegate2$input; 11162 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$input = _this$delegate2.inputControllerDidRequestReparse) === null || _this$delegate2$input === void 0 || _this$delegate2$input.call(_this$delegate2); 11163 return this.requestRender(); 11164 } 11165 attachFiles(files) { 11166 const operations = Array.from(files).map(file => new FileVerificationOperation(file)); 11167 return Promise.all(operations).then(files => { 11168 this.handleInput(function () { 11169 var _this$delegate3, _this$responder; 11170 (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || _this$delegate3.inputControllerWillAttachFiles(); 11171 (_this$responder = this.responder) === null || _this$responder === void 0 || _this$responder.insertFiles(files); 11172 return this.requestRender(); 11173 }); 11174 }); 11175 } 11176 11177 // Private 11178 11179 handlerFor(eventName) { 11180 return event => { 11181 if (!event.defaultPrevented) { 11182 this.handleInput(() => { 11183 if (!innerElementIsActive(this.element)) { 11184 if (this.flakyKeyboardDetector.shouldIgnore(event)) return; 11185 this.eventName = eventName; 11186 this.constructor.events[eventName].call(this, event); 11187 } 11188 }); 11189 } 11190 }; 11191 } 11192 handleInput(callback) { 11193 try { 11194 var _this$delegate4; 11195 (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.inputControllerWillHandleInput(); 11196 callback.call(this); 11197 } finally { 11198 var _this$delegate5; 11199 (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || _this$delegate5.inputControllerDidHandleInput(); 11200 } 11201 } 11202 createLinkHTML(href, text) { 11203 const link = document.createElement("a"); 11204 link.href = href; 11205 link.textContent = text ? text : href; 11206 return link.outerHTML; 11207 } 11208 } 11209 _defineProperty(InputController, "events", {}); 11210 11211 var _$codePointAt, _; 11212 const { 11213 browser, 11214 keyNames 11215 } = config; 11216 let pastedFileCount = 0; 11217 class Level0InputController extends InputController { 11218 constructor() { 11219 super(...arguments); 11220 this.resetInputSummary(); 11221 } 11222 setInputSummary() { 11223 let summary = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 11224 this.inputSummary.eventName = this.eventName; 11225 for (const key in summary) { 11226 const value = summary[key]; 11227 this.inputSummary[key] = value; 11228 } 11229 return this.inputSummary; 11230 } 11231 resetInputSummary() { 11232 this.inputSummary = {}; 11233 } 11234 reset() { 11235 this.resetInputSummary(); 11236 return selectionChangeObserver.reset(); 11237 } 11238 11239 // Mutation observer delegate 11240 11241 elementDidMutate(mutationSummary) { 11242 if (this.isComposing()) { 11243 var _this$delegate, _this$delegate$inputC; 11244 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$inputC = _this$delegate.inputControllerDidAllowUnhandledInput) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate); 11245 } else { 11246 return this.handleInput(function () { 11247 if (this.mutationIsSignificant(mutationSummary)) { 11248 if (this.mutationIsExpected(mutationSummary)) { 11249 this.requestRender(); 11250 } else { 11251 this.requestReparse(); 11252 } 11253 } 11254 return this.reset(); 11255 }); 11256 } 11257 } 11258 mutationIsExpected(_ref) { 11259 let { 11260 textAdded, 11261 textDeleted 11262 } = _ref; 11263 if (this.inputSummary.preferDocument) { 11264 return true; 11265 } 11266 const mutationAdditionMatchesSummary = textAdded != null ? textAdded === this.inputSummary.textAdded : !this.inputSummary.textAdded; 11267 const mutationDeletionMatchesSummary = textDeleted != null ? this.inputSummary.didDelete : !this.inputSummary.didDelete; 11268 const unexpectedNewlineAddition = ["\n", " \n"].includes(textAdded) && !mutationAdditionMatchesSummary; 11269 const unexpectedNewlineDeletion = textDeleted === "\n" && !mutationDeletionMatchesSummary; 11270 const singleUnexpectedNewline = unexpectedNewlineAddition && !unexpectedNewlineDeletion || unexpectedNewlineDeletion && !unexpectedNewlineAddition; 11271 if (singleUnexpectedNewline) { 11272 const range = this.getSelectedRange(); 11273 if (range) { 11274 var _this$responder; 11275 const offset = unexpectedNewlineAddition ? textAdded.replace(/\n$/, "").length || -1 : (textAdded === null || textAdded === void 0 ? void 0 : textAdded.length) || 1; 11276 if ((_this$responder = this.responder) !== null && _this$responder !== void 0 && _this$responder.positionIsBlockBreak(range[1] + offset)) { 11277 return true; 11278 } 11279 } 11280 } 11281 return mutationAdditionMatchesSummary && mutationDeletionMatchesSummary; 11282 } 11283 mutationIsSignificant(mutationSummary) { 11284 var _this$compositionInpu; 11285 const textChanged = Object.keys(mutationSummary).length > 0; 11286 const composedEmptyString = ((_this$compositionInpu = this.compositionInput) === null || _this$compositionInpu === void 0 ? void 0 : _this$compositionInpu.getEndData()) === ""; 11287 return textChanged || !composedEmptyString; 11288 } 11289 11290 // Private 11291 11292 getCompositionInput() { 11293 if (this.isComposing()) { 11294 return this.compositionInput; 11295 } else { 11296 this.compositionInput = new CompositionInput(this); 11297 } 11298 } 11299 isComposing() { 11300 return this.compositionInput && !this.compositionInput.isEnded(); 11301 } 11302 deleteInDirection(direction, event) { 11303 var _this$responder2; 11304 if (((_this$responder2 = this.responder) === null || _this$responder2 === void 0 ? void 0 : _this$responder2.deleteInDirection(direction)) === false) { 11305 if (event) { 11306 event.preventDefault(); 11307 return this.requestRender(); 11308 } 11309 } else { 11310 return this.setInputSummary({ 11311 didDelete: true 11312 }); 11313 } 11314 } 11315 serializeSelectionToDataTransfer(dataTransfer) { 11316 var _this$responder3; 11317 if (!dataTransferIsWritable(dataTransfer)) return; 11318 const document = (_this$responder3 = this.responder) === null || _this$responder3 === void 0 ? void 0 : _this$responder3.getSelectedDocument().toSerializableDocument(); 11319 dataTransfer.setData("application/x-trix-document", JSON.stringify(document)); 11320 dataTransfer.setData("text/html", DocumentView.render(document).innerHTML); 11321 dataTransfer.setData("text/plain", document.toString().replace(/\n$/, "")); 11322 return true; 11323 } 11324 canAcceptDataTransfer(dataTransfer) { 11325 const types = {}; 11326 Array.from((dataTransfer === null || dataTransfer === void 0 ? void 0 : dataTransfer.types) || []).forEach(type => { 11327 types[type] = true; 11328 }); 11329 return types.Files || types["application/x-trix-document"] || types["text/html"] || types["text/plain"]; 11330 } 11331 getPastedHTMLUsingHiddenElement(callback) { 11332 const selectedRange = this.getSelectedRange(); 11333 const style = { 11334 position: "absolute", 11335 left: "".concat(window.pageXOffset, "px"), 11336 top: "".concat(window.pageYOffset, "px"), 11337 opacity: 0 11338 }; 11339 const element = makeElement({ 11340 style, 11341 tagName: "div", 11342 editable: true 11343 }); 11344 document.body.appendChild(element); 11345 element.focus(); 11346 return requestAnimationFrame(() => { 11347 const html = element.innerHTML; 11348 removeNode(element); 11349 this.setSelectedRange(selectedRange); 11350 return callback(html); 11351 }); 11352 } 11353 } 11354 _defineProperty(Level0InputController, "events", { 11355 keydown(event) { 11356 if (!this.isComposing()) { 11357 this.resetInputSummary(); 11358 } 11359 this.inputSummary.didInput = true; 11360 const keyName = keyNames[event.keyCode]; 11361 if (keyName) { 11362 var _context2; 11363 let context = this.keys; 11364 ["ctrl", "alt", "shift", "meta"].forEach(modifier => { 11365 if (event["".concat(modifier, "Key")]) { 11366 var _context; 11367 if (modifier === "ctrl") { 11368 modifier = "control"; 11369 } 11370 context = (_context = context) === null || _context === void 0 ? void 0 : _context[modifier]; 11371 } 11372 }); 11373 if (((_context2 = context) === null || _context2 === void 0 ? void 0 : _context2[keyName]) != null) { 11374 this.setInputSummary({ 11375 keyName 11376 }); 11377 selectionChangeObserver.reset(); 11378 context[keyName].call(this, event); 11379 } 11380 } 11381 if (keyEventIsKeyboardCommand(event)) { 11382 const character = String.fromCharCode(event.keyCode).toLowerCase(); 11383 if (character) { 11384 var _this$delegate3; 11385 const keys = ["alt", "shift"].map(modifier => { 11386 if (event["".concat(modifier, "Key")]) { 11387 return modifier; 11388 } 11389 }).filter(key => key); 11390 keys.push(character); 11391 if ((_this$delegate3 = this.delegate) !== null && _this$delegate3 !== void 0 && _this$delegate3.inputControllerDidReceiveKeyboardCommand(keys)) { 11392 event.preventDefault(); 11393 } 11394 } 11395 } 11396 }, 11397 keypress(event) { 11398 if (this.inputSummary.eventName != null) return; 11399 if (event.metaKey) return; 11400 if (event.ctrlKey && !event.altKey) return; 11401 const string = stringFromKeyEvent(event); 11402 if (string) { 11403 var _this$delegate4, _this$responder9; 11404 (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.inputControllerWillPerformTyping(); 11405 (_this$responder9 = this.responder) === null || _this$responder9 === void 0 || _this$responder9.insertString(string); 11406 return this.setInputSummary({ 11407 textAdded: string, 11408 didDelete: this.selectionIsExpanded() 11409 }); 11410 } 11411 }, 11412 textInput(event) { 11413 // Handle autocapitalization 11414 const { 11415 data 11416 } = event; 11417 const { 11418 textAdded 11419 } = this.inputSummary; 11420 if (textAdded && textAdded !== data && textAdded.toUpperCase() === data) { 11421 var _this$responder10; 11422 const range = this.getSelectedRange(); 11423 this.setSelectedRange([range[0], range[1] + textAdded.length]); 11424 (_this$responder10 = this.responder) === null || _this$responder10 === void 0 || _this$responder10.insertString(data); 11425 this.setInputSummary({ 11426 textAdded: data 11427 }); 11428 return this.setSelectedRange(range); 11429 } 11430 }, 11431 dragenter(event) { 11432 event.preventDefault(); 11433 }, 11434 dragstart(event) { 11435 var _this$delegate5, _this$delegate5$input; 11436 this.serializeSelectionToDataTransfer(event.dataTransfer); 11437 this.draggedRange = this.getSelectedRange(); 11438 return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || (_this$delegate5$input = _this$delegate5.inputControllerDidStartDrag) === null || _this$delegate5$input === void 0 ? void 0 : _this$delegate5$input.call(_this$delegate5); 11439 }, 11440 dragover(event) { 11441 if (this.draggedRange || this.canAcceptDataTransfer(event.dataTransfer)) { 11442 event.preventDefault(); 11443 const draggingPoint = { 11444 x: event.clientX, 11445 y: event.clientY 11446 }; 11447 if (!objectsAreEqual(draggingPoint, this.draggingPoint)) { 11448 var _this$delegate6, _this$delegate6$input; 11449 this.draggingPoint = draggingPoint; 11450 return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || (_this$delegate6$input = _this$delegate6.inputControllerDidReceiveDragOverPoint) === null || _this$delegate6$input === void 0 ? void 0 : _this$delegate6$input.call(_this$delegate6, this.draggingPoint); 11451 } 11452 } 11453 }, 11454 dragend(event) { 11455 var _this$delegate7, _this$delegate7$input; 11456 (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || (_this$delegate7$input = _this$delegate7.inputControllerDidCancelDrag) === null || _this$delegate7$input === void 0 || _this$delegate7$input.call(_this$delegate7); 11457 this.draggedRange = null; 11458 this.draggingPoint = null; 11459 }, 11460 drop(event) { 11461 var _event$dataTransfer, _this$responder11; 11462 event.preventDefault(); 11463 const files = (_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.files; 11464 const documentJSON = event.dataTransfer.getData("application/x-trix-document"); 11465 const point = { 11466 x: event.clientX, 11467 y: event.clientY 11468 }; 11469 (_this$responder11 = this.responder) === null || _this$responder11 === void 0 || _this$responder11.setLocationRangeFromPointRange(point); 11470 if (files !== null && files !== void 0 && files.length) { 11471 this.attachFiles(files); 11472 } else if (this.draggedRange) { 11473 var _this$delegate8, _this$responder12; 11474 (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || _this$delegate8.inputControllerWillMoveText(); 11475 (_this$responder12 = this.responder) === null || _this$responder12 === void 0 || _this$responder12.moveTextFromRange(this.draggedRange); 11476 this.draggedRange = null; 11477 this.requestRender(); 11478 } else if (documentJSON) { 11479 var _this$responder13; 11480 const document = Document.fromJSONString(documentJSON); 11481 (_this$responder13 = this.responder) === null || _this$responder13 === void 0 || _this$responder13.insertDocument(document); 11482 this.requestRender(); 11483 } 11484 this.draggedRange = null; 11485 this.draggingPoint = null; 11486 }, 11487 cut(event) { 11488 var _this$responder14; 11489 if ((_this$responder14 = this.responder) !== null && _this$responder14 !== void 0 && _this$responder14.selectionIsExpanded()) { 11490 var _this$delegate9; 11491 if (this.serializeSelectionToDataTransfer(event.clipboardData)) { 11492 event.preventDefault(); 11493 } 11494 (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || _this$delegate9.inputControllerWillCutText(); 11495 this.deleteInDirection("backward"); 11496 if (event.defaultPrevented) { 11497 return this.requestRender(); 11498 } 11499 } 11500 }, 11501 copy(event) { 11502 var _this$responder15; 11503 if ((_this$responder15 = this.responder) !== null && _this$responder15 !== void 0 && _this$responder15.selectionIsExpanded()) { 11504 if (this.serializeSelectionToDataTransfer(event.clipboardData)) { 11505 event.preventDefault(); 11506 } 11507 } 11508 }, 11509 paste(event) { 11510 const clipboard = event.clipboardData || event.testClipboardData; 11511 const paste = { 11512 clipboard 11513 }; 11514 if (!clipboard || pasteEventIsCrippledSafariHTMLPaste(event)) { 11515 this.getPastedHTMLUsingHiddenElement(html => { 11516 var _this$delegate10, _this$responder16, _this$delegate11; 11517 paste.type = "text/html"; 11518 paste.html = html; 11519 (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 || _this$delegate10.inputControllerWillPaste(paste); 11520 (_this$responder16 = this.responder) === null || _this$responder16 === void 0 || _this$responder16.insertHTML(paste.html); 11521 this.requestRender(); 11522 return (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 ? void 0 : _this$delegate11.inputControllerDidPaste(paste); 11523 }); 11524 return; 11525 } 11526 const href = clipboard.getData("URL"); 11527 const html = clipboard.getData("text/html"); 11528 const name = clipboard.getData("public.url-name"); 11529 if (href) { 11530 var _this$delegate12, _this$responder17, _this$delegate13; 11531 let string; 11532 paste.type = "text/html"; 11533 if (name) { 11534 string = squishBreakableWhitespace(name).trim(); 11535 } else { 11536 string = href; 11537 } 11538 paste.html = this.createLinkHTML(href, string); 11539 (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 || _this$delegate12.inputControllerWillPaste(paste); 11540 this.setInputSummary({ 11541 textAdded: string, 11542 didDelete: this.selectionIsExpanded() 11543 }); 11544 (_this$responder17 = this.responder) === null || _this$responder17 === void 0 || _this$responder17.insertHTML(paste.html); 11545 this.requestRender(); 11546 (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 || _this$delegate13.inputControllerDidPaste(paste); 11547 } else if (dataTransferIsPlainText(clipboard)) { 11548 var _this$delegate14, _this$responder18, _this$delegate15; 11549 paste.type = "text/plain"; 11550 paste.string = clipboard.getData("text/plain"); 11551 (_this$delegate14 = this.delegate) === null || _this$delegate14 === void 0 || _this$delegate14.inputControllerWillPaste(paste); 11552 this.setInputSummary({ 11553 textAdded: paste.string, 11554 didDelete: this.selectionIsExpanded() 11555 }); 11556 (_this$responder18 = this.responder) === null || _this$responder18 === void 0 || _this$responder18.insertString(paste.string); 11557 this.requestRender(); 11558 (_this$delegate15 = this.delegate) === null || _this$delegate15 === void 0 || _this$delegate15.inputControllerDidPaste(paste); 11559 } else if (html) { 11560 var _this$delegate16, _this$responder19, _this$delegate17; 11561 paste.type = "text/html"; 11562 paste.html = html; 11563 (_this$delegate16 = this.delegate) === null || _this$delegate16 === void 0 || _this$delegate16.inputControllerWillPaste(paste); 11564 (_this$responder19 = this.responder) === null || _this$responder19 === void 0 || _this$responder19.insertHTML(paste.html); 11565 this.requestRender(); 11566 (_this$delegate17 = this.delegate) === null || _this$delegate17 === void 0 || _this$delegate17.inputControllerDidPaste(paste); 11567 } else if (Array.from(clipboard.types).includes("Files")) { 11568 var _clipboard$items, _clipboard$items$getA; 11569 const file = (_clipboard$items = clipboard.items) === null || _clipboard$items === void 0 || (_clipboard$items = _clipboard$items[0]) === null || _clipboard$items === void 0 || (_clipboard$items$getA = _clipboard$items.getAsFile) === null || _clipboard$items$getA === void 0 ? void 0 : _clipboard$items$getA.call(_clipboard$items); 11570 if (file) { 11571 var _this$delegate18, _this$responder20, _this$delegate19; 11572 const extension = extensionForFile(file); 11573 if (!file.name && extension) { 11574 file.name = "pasted-file-".concat(++pastedFileCount, ".").concat(extension); 11575 } 11576 paste.type = "File"; 11577 paste.file = file; 11578 (_this$delegate18 = this.delegate) === null || _this$delegate18 === void 0 || _this$delegate18.inputControllerWillAttachFiles(); 11579 (_this$responder20 = this.responder) === null || _this$responder20 === void 0 || _this$responder20.insertFile(paste.file); 11580 this.requestRender(); 11581 (_this$delegate19 = this.delegate) === null || _this$delegate19 === void 0 || _this$delegate19.inputControllerDidPaste(paste); 11582 } 11583 } 11584 event.preventDefault(); 11585 }, 11586 compositionstart(event) { 11587 return this.getCompositionInput().start(event.data); 11588 }, 11589 compositionupdate(event) { 11590 return this.getCompositionInput().update(event.data); 11591 }, 11592 compositionend(event) { 11593 return this.getCompositionInput().end(event.data); 11594 }, 11595 beforeinput(event) { 11596 this.inputSummary.didInput = true; 11597 }, 11598 input(event) { 11599 this.inputSummary.didInput = true; 11600 return event.stopPropagation(); 11601 } 11602 }); 11603 _defineProperty(Level0InputController, "keys", { 11604 backspace(event) { 11605 var _this$delegate20; 11606 (_this$delegate20 = this.delegate) === null || _this$delegate20 === void 0 || _this$delegate20.inputControllerWillPerformTyping(); 11607 return this.deleteInDirection("backward", event); 11608 }, 11609 delete(event) { 11610 var _this$delegate21; 11611 (_this$delegate21 = this.delegate) === null || _this$delegate21 === void 0 || _this$delegate21.inputControllerWillPerformTyping(); 11612 return this.deleteInDirection("forward", event); 11613 }, 11614 return(event) { 11615 var _this$delegate22, _this$responder21; 11616 this.setInputSummary({ 11617 preferDocument: true 11618 }); 11619 (_this$delegate22 = this.delegate) === null || _this$delegate22 === void 0 || _this$delegate22.inputControllerWillPerformTyping(); 11620 return (_this$responder21 = this.responder) === null || _this$responder21 === void 0 ? void 0 : _this$responder21.insertLineBreak(); 11621 }, 11622 tab(event) { 11623 var _this$responder22; 11624 if ((_this$responder22 = this.responder) !== null && _this$responder22 !== void 0 && _this$responder22.canIncreaseNestingLevel()) { 11625 var _this$responder23; 11626 (_this$responder23 = this.responder) === null || _this$responder23 === void 0 || _this$responder23.increaseNestingLevel(); 11627 this.requestRender(); 11628 event.preventDefault(); 11629 } 11630 }, 11631 left(event) { 11632 if (this.selectionIsInCursorTarget()) { 11633 var _this$responder24; 11634 event.preventDefault(); 11635 return (_this$responder24 = this.responder) === null || _this$responder24 === void 0 ? void 0 : _this$responder24.moveCursorInDirection("backward"); 11636 } 11637 }, 11638 right(event) { 11639 if (this.selectionIsInCursorTarget()) { 11640 var _this$responder25; 11641 event.preventDefault(); 11642 return (_this$responder25 = this.responder) === null || _this$responder25 === void 0 ? void 0 : _this$responder25.moveCursorInDirection("forward"); 11643 } 11644 }, 11645 control: { 11646 d(event) { 11647 var _this$delegate23; 11648 (_this$delegate23 = this.delegate) === null || _this$delegate23 === void 0 || _this$delegate23.inputControllerWillPerformTyping(); 11649 return this.deleteInDirection("forward", event); 11650 }, 11651 h(event) { 11652 var _this$delegate24; 11653 (_this$delegate24 = this.delegate) === null || _this$delegate24 === void 0 || _this$delegate24.inputControllerWillPerformTyping(); 11654 return this.deleteInDirection("backward", event); 11655 }, 11656 o(event) { 11657 var _this$delegate25, _this$responder26; 11658 event.preventDefault(); 11659 (_this$delegate25 = this.delegate) === null || _this$delegate25 === void 0 || _this$delegate25.inputControllerWillPerformTyping(); 11660 (_this$responder26 = this.responder) === null || _this$responder26 === void 0 || _this$responder26.insertString("\n", { 11661 updatePosition: false 11662 }); 11663 return this.requestRender(); 11664 } 11665 }, 11666 shift: { 11667 return(event) { 11668 var _this$delegate26, _this$responder27; 11669 (_this$delegate26 = this.delegate) === null || _this$delegate26 === void 0 || _this$delegate26.inputControllerWillPerformTyping(); 11670 (_this$responder27 = this.responder) === null || _this$responder27 === void 0 || _this$responder27.insertString("\n"); 11671 this.requestRender(); 11672 event.preventDefault(); 11673 }, 11674 tab(event) { 11675 var _this$responder28; 11676 if ((_this$responder28 = this.responder) !== null && _this$responder28 !== void 0 && _this$responder28.canDecreaseNestingLevel()) { 11677 var _this$responder29; 11678 (_this$responder29 = this.responder) === null || _this$responder29 === void 0 || _this$responder29.decreaseNestingLevel(); 11679 this.requestRender(); 11680 event.preventDefault(); 11681 } 11682 }, 11683 left(event) { 11684 if (this.selectionIsInCursorTarget()) { 11685 event.preventDefault(); 11686 return this.expandSelectionInDirection("backward"); 11687 } 11688 }, 11689 right(event) { 11690 if (this.selectionIsInCursorTarget()) { 11691 event.preventDefault(); 11692 return this.expandSelectionInDirection("forward"); 11693 } 11694 } 11695 }, 11696 alt: { 11697 backspace(event) { 11698 var _this$delegate27; 11699 this.setInputSummary({ 11700 preferDocument: false 11701 }); 11702 return (_this$delegate27 = this.delegate) === null || _this$delegate27 === void 0 ? void 0 : _this$delegate27.inputControllerWillPerformTyping(); 11703 } 11704 }, 11705 meta: { 11706 backspace(event) { 11707 var _this$delegate28; 11708 this.setInputSummary({ 11709 preferDocument: false 11710 }); 11711 return (_this$delegate28 = this.delegate) === null || _this$delegate28 === void 0 ? void 0 : _this$delegate28.inputControllerWillPerformTyping(); 11712 } 11713 } 11714 }); 11715 Level0InputController.proxyMethod("responder?.getSelectedRange"); 11716 Level0InputController.proxyMethod("responder?.setSelectedRange"); 11717 Level0InputController.proxyMethod("responder?.expandSelectionInDirection"); 11718 Level0InputController.proxyMethod("responder?.selectionIsInCursorTarget"); 11719 Level0InputController.proxyMethod("responder?.selectionIsExpanded"); 11720 const extensionForFile = file => { 11721 var _file$type; 11722 return (_file$type = file.type) === null || _file$type === void 0 || (_file$type = _file$type.match(/\/(\w+)$/)) === null || _file$type === void 0 ? void 0 : _file$type[1]; 11723 }; 11724 const hasStringCodePointAt = !!((_$codePointAt = (_ = " ").codePointAt) !== null && _$codePointAt !== void 0 && _$codePointAt.call(_, 0)); 11725 const stringFromKeyEvent = function (event) { 11726 if (event.key && hasStringCodePointAt && event.key.codePointAt(0) === event.keyCode) { 11727 return event.key; 11728 } else { 11729 let code; 11730 if (event.which === null) { 11731 code = event.keyCode; 11732 } else if (event.which !== 0 && event.charCode !== 0) { 11733 code = event.charCode; 11734 } 11735 if (code != null && keyNames[code] !== "escape") { 11736 return UTF16String.fromCodepoints([code]).toString(); 11737 } 11738 } 11739 }; 11740 const pasteEventIsCrippledSafariHTMLPaste = function (event) { 11741 const paste = event.clipboardData; 11742 if (paste) { 11743 if (paste.types.includes("text/html")) { 11744 // Answer is yes if there's any possibility of Paste and Match Style in Safari, 11745 // which is nearly impossible to detect confidently: https://bugs.webkit.org/show_bug.cgi?id=174165 11746 for (const type of paste.types) { 11747 const hasPasteboardFlavor = /^CorePasteboardFlavorType/.test(type); 11748 const hasReadableDynamicData = /^dyn\./.test(type) && paste.getData(type); 11749 const mightBePasteAndMatchStyle = hasPasteboardFlavor || hasReadableDynamicData; 11750 if (mightBePasteAndMatchStyle) { 11751 return true; 11752 } 11753 } 11754 return false; 11755 } else { 11756 const isExternalHTMLPaste = paste.types.includes("com.apple.webarchive"); 11757 const isExternalRichTextPaste = paste.types.includes("com.apple.flat-rtfd"); 11758 return isExternalHTMLPaste || isExternalRichTextPaste; 11759 } 11760 } 11761 }; 11762 class CompositionInput extends BasicObject { 11763 constructor(inputController) { 11764 super(...arguments); 11765 this.inputController = inputController; 11766 this.responder = this.inputController.responder; 11767 this.delegate = this.inputController.delegate; 11768 this.inputSummary = this.inputController.inputSummary; 11769 this.data = {}; 11770 } 11771 start(data) { 11772 this.data.start = data; 11773 if (this.isSignificant()) { 11774 var _this$responder5; 11775 if (this.inputSummary.eventName === "keypress" && this.inputSummary.textAdded) { 11776 var _this$responder4; 11777 (_this$responder4 = this.responder) === null || _this$responder4 === void 0 || _this$responder4.deleteInDirection("left"); 11778 } 11779 if (!this.selectionIsExpanded()) { 11780 this.insertPlaceholder(); 11781 this.requestRender(); 11782 } 11783 this.range = (_this$responder5 = this.responder) === null || _this$responder5 === void 0 ? void 0 : _this$responder5.getSelectedRange(); 11784 } 11785 } 11786 update(data) { 11787 this.data.update = data; 11788 if (this.isSignificant()) { 11789 const range = this.selectPlaceholder(); 11790 if (range) { 11791 this.forgetPlaceholder(); 11792 this.range = range; 11793 } 11794 } 11795 } 11796 end(data) { 11797 this.data.end = data; 11798 if (this.isSignificant()) { 11799 this.forgetPlaceholder(); 11800 if (this.canApplyToDocument()) { 11801 var _this$delegate2, _this$responder6, _this$responder7, _this$responder8; 11802 this.setInputSummary({ 11803 preferDocument: true, 11804 didInput: false 11805 }); 11806 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || _this$delegate2.inputControllerWillPerformTyping(); 11807 (_this$responder6 = this.responder) === null || _this$responder6 === void 0 || _this$responder6.setSelectedRange(this.range); 11808 (_this$responder7 = this.responder) === null || _this$responder7 === void 0 || _this$responder7.insertString(this.data.end); 11809 return (_this$responder8 = this.responder) === null || _this$responder8 === void 0 ? void 0 : _this$responder8.setSelectedRange(this.range[0] + this.data.end.length); 11810 } else if (this.data.start != null || this.data.update != null) { 11811 this.requestReparse(); 11812 return this.inputController.reset(); 11813 } 11814 } else { 11815 return this.inputController.reset(); 11816 } 11817 } 11818 getEndData() { 11819 return this.data.end; 11820 } 11821 isEnded() { 11822 return this.getEndData() != null; 11823 } 11824 isSignificant() { 11825 if (browser.composesExistingText) { 11826 return this.inputSummary.didInput; 11827 } else { 11828 return true; 11829 } 11830 } 11831 11832 // Private 11833 11834 canApplyToDocument() { 11835 var _this$data$start, _this$data$end; 11836 return ((_this$data$start = this.data.start) === null || _this$data$start === void 0 ? void 0 : _this$data$start.length) === 0 && ((_this$data$end = this.data.end) === null || _this$data$end === void 0 ? void 0 : _this$data$end.length) > 0 && this.range; 11837 } 11838 } 11839 CompositionInput.proxyMethod("inputController.setInputSummary"); 11840 CompositionInput.proxyMethod("inputController.requestRender"); 11841 CompositionInput.proxyMethod("inputController.requestReparse"); 11842 CompositionInput.proxyMethod("responder?.selectionIsExpanded"); 11843 CompositionInput.proxyMethod("responder?.insertPlaceholder"); 11844 CompositionInput.proxyMethod("responder?.selectPlaceholder"); 11845 CompositionInput.proxyMethod("responder?.forgetPlaceholder"); 11846 11847 class Level2InputController extends InputController { 11848 constructor() { 11849 super(...arguments); 11850 this.render = this.render.bind(this); 11851 } 11852 elementDidMutate() { 11853 if (this.scheduledRender) { 11854 if (this.composing) { 11855 var _this$delegate, _this$delegate$inputC; 11856 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$inputC = _this$delegate.inputControllerDidAllowUnhandledInput) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate); 11857 } 11858 } else { 11859 return this.reparse(); 11860 } 11861 } 11862 scheduleRender() { 11863 return this.scheduledRender ? this.scheduledRender : this.scheduledRender = requestAnimationFrame(this.render); 11864 } 11865 render() { 11866 var _this$afterRender; 11867 cancelAnimationFrame(this.scheduledRender); 11868 this.scheduledRender = null; 11869 if (!this.composing) { 11870 var _this$delegate2; 11871 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || _this$delegate2.render(); 11872 } 11873 (_this$afterRender = this.afterRender) === null || _this$afterRender === void 0 || _this$afterRender.call(this); 11874 this.afterRender = null; 11875 } 11876 reparse() { 11877 var _this$delegate3; 11878 return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 ? void 0 : _this$delegate3.reparse(); 11879 } 11880 11881 // Responder helpers 11882 11883 insertString() { 11884 var _this$delegate4; 11885 let string = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; 11886 let options = arguments.length > 1 ? arguments[1] : undefined; 11887 (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.inputControllerWillPerformTyping(); 11888 return this.withTargetDOMRange(function () { 11889 var _this$responder; 11890 return (_this$responder = this.responder) === null || _this$responder === void 0 ? void 0 : _this$responder.insertString(string, options); 11891 }); 11892 } 11893 toggleAttributeIfSupported(attributeName) { 11894 if (getAllAttributeNames().includes(attributeName)) { 11895 var _this$delegate5; 11896 (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || _this$delegate5.inputControllerWillPerformFormatting(attributeName); 11897 return this.withTargetDOMRange(function () { 11898 var _this$responder2; 11899 return (_this$responder2 = this.responder) === null || _this$responder2 === void 0 ? void 0 : _this$responder2.toggleCurrentAttribute(attributeName); 11900 }); 11901 } 11902 } 11903 activateAttributeIfSupported(attributeName, value) { 11904 if (getAllAttributeNames().includes(attributeName)) { 11905 var _this$delegate6; 11906 (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || _this$delegate6.inputControllerWillPerformFormatting(attributeName); 11907 return this.withTargetDOMRange(function () { 11908 var _this$responder3; 11909 return (_this$responder3 = this.responder) === null || _this$responder3 === void 0 ? void 0 : _this$responder3.setCurrentAttribute(attributeName, value); 11910 }); 11911 } 11912 } 11913 deleteInDirection(direction) { 11914 let { 11915 recordUndoEntry 11916 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { 11917 recordUndoEntry: true 11918 }; 11919 if (recordUndoEntry) { 11920 var _this$delegate7; 11921 (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || _this$delegate7.inputControllerWillPerformTyping(); 11922 } 11923 const perform = () => { 11924 var _this$responder4; 11925 return (_this$responder4 = this.responder) === null || _this$responder4 === void 0 ? void 0 : _this$responder4.deleteInDirection(direction); 11926 }; 11927 const domRange = this.getTargetDOMRange({ 11928 minLength: this.composing ? 1 : 2 11929 }); 11930 if (domRange) { 11931 return this.withTargetDOMRange(domRange, perform); 11932 } else { 11933 return perform(); 11934 } 11935 } 11936 11937 // Selection helpers 11938 11939 withTargetDOMRange(domRange, fn) { 11940 if (typeof domRange === "function") { 11941 fn = domRange; 11942 domRange = this.getTargetDOMRange(); 11943 } 11944 if (domRange) { 11945 var _this$responder5; 11946 return (_this$responder5 = this.responder) === null || _this$responder5 === void 0 ? void 0 : _this$responder5.withTargetDOMRange(domRange, fn.bind(this)); 11947 } else { 11948 selectionChangeObserver.reset(); 11949 return fn.call(this); 11950 } 11951 } 11952 getTargetDOMRange() { 11953 var _this$event$getTarget, _this$event; 11954 let { 11955 minLength 11956 } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { 11957 minLength: 0 11958 }; 11959 const targetRanges = (_this$event$getTarget = (_this$event = this.event).getTargetRanges) === null || _this$event$getTarget === void 0 ? void 0 : _this$event$getTarget.call(_this$event); 11960 if (targetRanges) { 11961 if (targetRanges.length) { 11962 const domRange = staticRangeToRange(targetRanges[0]); 11963 if (minLength === 0 || domRange.toString().length >= minLength) { 11964 return domRange; 11965 } 11966 } 11967 } 11968 } 11969 withEvent(event, fn) { 11970 let result; 11971 this.event = event; 11972 try { 11973 result = fn.call(this); 11974 } finally { 11975 this.event = null; 11976 } 11977 return result; 11978 } 11979 } 11980 _defineProperty(Level2InputController, "events", { 11981 keydown(event) { 11982 if (keyEventIsKeyboardCommand(event)) { 11983 var _this$delegate8; 11984 const command = keyboardCommandFromKeyEvent(event); 11985 if ((_this$delegate8 = this.delegate) !== null && _this$delegate8 !== void 0 && _this$delegate8.inputControllerDidReceiveKeyboardCommand(command)) { 11986 event.preventDefault(); 11987 } 11988 } else { 11989 let name = event.key; 11990 if (event.altKey) { 11991 name += "+Alt"; 11992 } 11993 if (event.shiftKey) { 11994 name += "+Shift"; 11995 } 11996 const handler = this.constructor.keys[name]; 11997 if (handler) { 11998 return this.withEvent(event, handler); 11999 } 12000 } 12001 }, 12002 // Handle paste event to work around beforeinput.insertFromPaste browser bugs. 12003 // Safe to remove each condition once fixed upstream. 12004 paste(event) { 12005 var _event$clipboardData; 12006 // https://bugs.webkit.org/show_bug.cgi?id=194921 12007 let paste; 12008 const href = (_event$clipboardData = event.clipboardData) === null || _event$clipboardData === void 0 ? void 0 : _event$clipboardData.getData("URL"); 12009 if (pasteEventHasFilesOnly(event)) { 12010 event.preventDefault(); 12011 return this.attachFiles(event.clipboardData.files); 12012 12013 // https://bugs.chromium.org/p/chromium/issues/detail?id=934448 12014 } else if (pasteEventHasPlainTextOnly(event)) { 12015 var _this$delegate9, _this$responder6, _this$delegate10; 12016 event.preventDefault(); 12017 paste = { 12018 type: "text/plain", 12019 string: event.clipboardData.getData("text/plain") 12020 }; 12021 (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || _this$delegate9.inputControllerWillPaste(paste); 12022 (_this$responder6 = this.responder) === null || _this$responder6 === void 0 || _this$responder6.insertString(paste.string); 12023 this.render(); 12024 return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 ? void 0 : _this$delegate10.inputControllerDidPaste(paste); 12025 12026 // https://bugs.webkit.org/show_bug.cgi?id=196702 12027 } else if (href) { 12028 var _this$delegate11, _this$responder7, _this$delegate12; 12029 event.preventDefault(); 12030 paste = { 12031 type: "text/html", 12032 html: this.createLinkHTML(href) 12033 }; 12034 (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 || _this$delegate11.inputControllerWillPaste(paste); 12035 (_this$responder7 = this.responder) === null || _this$responder7 === void 0 || _this$responder7.insertHTML(paste.html); 12036 this.render(); 12037 return (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 ? void 0 : _this$delegate12.inputControllerDidPaste(paste); 12038 } 12039 }, 12040 beforeinput(event) { 12041 const handler = this.constructor.inputTypes[event.inputType]; 12042 const immmediateRender = shouldRenderInmmediatelyToDealWithIOSDictation(event); 12043 if (handler) { 12044 this.withEvent(event, handler); 12045 if (!immmediateRender) { 12046 this.scheduleRender(); 12047 } 12048 } 12049 if (immmediateRender) { 12050 this.render(); 12051 } 12052 }, 12053 input(event) { 12054 selectionChangeObserver.reset(); 12055 }, 12056 dragstart(event) { 12057 var _this$responder8; 12058 if ((_this$responder8 = this.responder) !== null && _this$responder8 !== void 0 && _this$responder8.selectionContainsAttachments()) { 12059 var _this$responder9; 12060 event.dataTransfer.setData("application/x-trix-dragging", true); 12061 this.dragging = { 12062 range: (_this$responder9 = this.responder) === null || _this$responder9 === void 0 ? void 0 : _this$responder9.getSelectedRange(), 12063 point: pointFromEvent(event) 12064 }; 12065 } 12066 }, 12067 dragenter(event) { 12068 if (dragEventHasFiles(event)) { 12069 event.preventDefault(); 12070 } 12071 }, 12072 dragover(event) { 12073 if (this.dragging) { 12074 event.preventDefault(); 12075 const point = pointFromEvent(event); 12076 if (!objectsAreEqual(point, this.dragging.point)) { 12077 var _this$responder10; 12078 this.dragging.point = point; 12079 return (_this$responder10 = this.responder) === null || _this$responder10 === void 0 ? void 0 : _this$responder10.setLocationRangeFromPointRange(point); 12080 } 12081 } else if (dragEventHasFiles(event)) { 12082 event.preventDefault(); 12083 } 12084 }, 12085 drop(event) { 12086 if (this.dragging) { 12087 var _this$delegate13, _this$responder11; 12088 event.preventDefault(); 12089 (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 || _this$delegate13.inputControllerWillMoveText(); 12090 (_this$responder11 = this.responder) === null || _this$responder11 === void 0 || _this$responder11.moveTextFromRange(this.dragging.range); 12091 this.dragging = null; 12092 return this.scheduleRender(); 12093 } else if (dragEventHasFiles(event)) { 12094 var _this$responder12; 12095 event.preventDefault(); 12096 const point = pointFromEvent(event); 12097 (_this$responder12 = this.responder) === null || _this$responder12 === void 0 || _this$responder12.setLocationRangeFromPointRange(point); 12098 return this.attachFiles(event.dataTransfer.files); 12099 } 12100 }, 12101 dragend() { 12102 if (this.dragging) { 12103 var _this$responder13; 12104 (_this$responder13 = this.responder) === null || _this$responder13 === void 0 || _this$responder13.setSelectedRange(this.dragging.range); 12105 this.dragging = null; 12106 } 12107 }, 12108 compositionend(event) { 12109 if (this.composing) { 12110 this.composing = false; 12111 if (!browser$1.recentAndroid) this.scheduleRender(); 12112 } 12113 } 12114 }); 12115 _defineProperty(Level2InputController, "keys", { 12116 ArrowLeft() { 12117 var _this$responder14; 12118 if ((_this$responder14 = this.responder) !== null && _this$responder14 !== void 0 && _this$responder14.shouldManageMovingCursorInDirection("backward")) { 12119 var _this$responder15; 12120 this.event.preventDefault(); 12121 return (_this$responder15 = this.responder) === null || _this$responder15 === void 0 ? void 0 : _this$responder15.moveCursorInDirection("backward"); 12122 } 12123 }, 12124 ArrowRight() { 12125 var _this$responder16; 12126 if ((_this$responder16 = this.responder) !== null && _this$responder16 !== void 0 && _this$responder16.shouldManageMovingCursorInDirection("forward")) { 12127 var _this$responder17; 12128 this.event.preventDefault(); 12129 return (_this$responder17 = this.responder) === null || _this$responder17 === void 0 ? void 0 : _this$responder17.moveCursorInDirection("forward"); 12130 } 12131 }, 12132 Backspace() { 12133 var _this$responder18; 12134 if ((_this$responder18 = this.responder) !== null && _this$responder18 !== void 0 && _this$responder18.shouldManageDeletingInDirection("backward")) { 12135 var _this$delegate14, _this$responder19; 12136 this.event.preventDefault(); 12137 (_this$delegate14 = this.delegate) === null || _this$delegate14 === void 0 || _this$delegate14.inputControllerWillPerformTyping(); 12138 (_this$responder19 = this.responder) === null || _this$responder19 === void 0 || _this$responder19.deleteInDirection("backward"); 12139 return this.render(); 12140 } 12141 }, 12142 Tab() { 12143 var _this$responder20; 12144 if ((_this$responder20 = this.responder) !== null && _this$responder20 !== void 0 && _this$responder20.canIncreaseNestingLevel()) { 12145 var _this$responder21; 12146 this.event.preventDefault(); 12147 (_this$responder21 = this.responder) === null || _this$responder21 === void 0 || _this$responder21.increaseNestingLevel(); 12148 return this.render(); 12149 } 12150 }, 12151 "Tab+Shift"() { 12152 var _this$responder22; 12153 if ((_this$responder22 = this.responder) !== null && _this$responder22 !== void 0 && _this$responder22.canDecreaseNestingLevel()) { 12154 var _this$responder23; 12155 this.event.preventDefault(); 12156 (_this$responder23 = this.responder) === null || _this$responder23 === void 0 || _this$responder23.decreaseNestingLevel(); 12157 return this.render(); 12158 } 12159 } 12160 }); 12161 _defineProperty(Level2InputController, "inputTypes", { 12162 deleteByComposition() { 12163 return this.deleteInDirection("backward", { 12164 recordUndoEntry: false 12165 }); 12166 }, 12167 deleteByCut() { 12168 return this.deleteInDirection("backward"); 12169 }, 12170 deleteByDrag() { 12171 this.event.preventDefault(); 12172 return this.withTargetDOMRange(function () { 12173 var _this$responder24; 12174 this.deleteByDragRange = (_this$responder24 = this.responder) === null || _this$responder24 === void 0 ? void 0 : _this$responder24.getSelectedRange(); 12175 }); 12176 }, 12177 deleteCompositionText() { 12178 return this.deleteInDirection("backward", { 12179 recordUndoEntry: false 12180 }); 12181 }, 12182 deleteContent() { 12183 return this.deleteInDirection("backward"); 12184 }, 12185 deleteContentBackward() { 12186 return this.deleteInDirection("backward"); 12187 }, 12188 deleteContentForward() { 12189 return this.deleteInDirection("forward"); 12190 }, 12191 deleteEntireSoftLine() { 12192 return this.deleteInDirection("forward"); 12193 }, 12194 deleteHardLineBackward() { 12195 return this.deleteInDirection("backward"); 12196 }, 12197 deleteHardLineForward() { 12198 return this.deleteInDirection("forward"); 12199 }, 12200 deleteSoftLineBackward() { 12201 return this.deleteInDirection("backward"); 12202 }, 12203 deleteSoftLineForward() { 12204 return this.deleteInDirection("forward"); 12205 }, 12206 deleteWordBackward() { 12207 return this.deleteInDirection("backward"); 12208 }, 12209 deleteWordForward() { 12210 return this.deleteInDirection("forward"); 12211 }, 12212 formatBackColor() { 12213 return this.activateAttributeIfSupported("backgroundColor", this.event.data); 12214 }, 12215 formatBold() { 12216 return this.toggleAttributeIfSupported("bold"); 12217 }, 12218 formatFontColor() { 12219 return this.activateAttributeIfSupported("color", this.event.data); 12220 }, 12221 formatFontName() { 12222 return this.activateAttributeIfSupported("font", this.event.data); 12223 }, 12224 formatIndent() { 12225 var _this$responder25; 12226 if ((_this$responder25 = this.responder) !== null && _this$responder25 !== void 0 && _this$responder25.canIncreaseNestingLevel()) { 12227 return this.withTargetDOMRange(function () { 12228 var _this$responder26; 12229 return (_this$responder26 = this.responder) === null || _this$responder26 === void 0 ? void 0 : _this$responder26.increaseNestingLevel(); 12230 }); 12231 } 12232 }, 12233 formatItalic() { 12234 return this.toggleAttributeIfSupported("italic"); 12235 }, 12236 formatJustifyCenter() { 12237 return this.toggleAttributeIfSupported("justifyCenter"); 12238 }, 12239 formatJustifyFull() { 12240 return this.toggleAttributeIfSupported("justifyFull"); 12241 }, 12242 formatJustifyLeft() { 12243 return this.toggleAttributeIfSupported("justifyLeft"); 12244 }, 12245 formatJustifyRight() { 12246 return this.toggleAttributeIfSupported("justifyRight"); 12247 }, 12248 formatOutdent() { 12249 var _this$responder27; 12250 if ((_this$responder27 = this.responder) !== null && _this$responder27 !== void 0 && _this$responder27.canDecreaseNestingLevel()) { 12251 return this.withTargetDOMRange(function () { 12252 var _this$responder28; 12253 return (_this$responder28 = this.responder) === null || _this$responder28 === void 0 ? void 0 : _this$responder28.decreaseNestingLevel(); 12254 }); 12255 } 12256 }, 12257 formatRemove() { 12258 this.withTargetDOMRange(function () { 12259 for (const attributeName in (_this$responder29 = this.responder) === null || _this$responder29 === void 0 ? void 0 : _this$responder29.getCurrentAttributes()) { 12260 var _this$responder29, _this$responder30; 12261 (_this$responder30 = this.responder) === null || _this$responder30 === void 0 || _this$responder30.removeCurrentAttribute(attributeName); 12262 } 12263 }); 12264 }, 12265 formatSetBlockTextDirection() { 12266 return this.activateAttributeIfSupported("blockDir", this.event.data); 12267 }, 12268 formatSetInlineTextDirection() { 12269 return this.activateAttributeIfSupported("textDir", this.event.data); 12270 }, 12271 formatStrikeThrough() { 12272 return this.toggleAttributeIfSupported("strike"); 12273 }, 12274 formatSubscript() { 12275 return this.toggleAttributeIfSupported("sub"); 12276 }, 12277 formatSuperscript() { 12278 return this.toggleAttributeIfSupported("sup"); 12279 }, 12280 formatUnderline() { 12281 return this.toggleAttributeIfSupported("underline"); 12282 }, 12283 historyRedo() { 12284 var _this$delegate15; 12285 return (_this$delegate15 = this.delegate) === null || _this$delegate15 === void 0 ? void 0 : _this$delegate15.inputControllerWillPerformRedo(); 12286 }, 12287 historyUndo() { 12288 var _this$delegate16; 12289 return (_this$delegate16 = this.delegate) === null || _this$delegate16 === void 0 ? void 0 : _this$delegate16.inputControllerWillPerformUndo(); 12290 }, 12291 insertCompositionText() { 12292 this.composing = true; 12293 return this.insertString(this.event.data); 12294 }, 12295 insertFromComposition() { 12296 this.composing = false; 12297 return this.insertString(this.event.data); 12298 }, 12299 insertFromDrop() { 12300 const range = this.deleteByDragRange; 12301 if (range) { 12302 var _this$delegate17; 12303 this.deleteByDragRange = null; 12304 (_this$delegate17 = this.delegate) === null || _this$delegate17 === void 0 || _this$delegate17.inputControllerWillMoveText(); 12305 return this.withTargetDOMRange(function () { 12306 var _this$responder31; 12307 return (_this$responder31 = this.responder) === null || _this$responder31 === void 0 ? void 0 : _this$responder31.moveTextFromRange(range); 12308 }); 12309 } 12310 }, 12311 insertFromPaste() { 12312 const { 12313 dataTransfer 12314 } = this.event; 12315 const paste = { 12316 dataTransfer 12317 }; 12318 const href = dataTransfer.getData("URL"); 12319 const html = dataTransfer.getData("text/html"); 12320 if (href) { 12321 var _this$delegate18; 12322 let string; 12323 this.event.preventDefault(); 12324 paste.type = "text/html"; 12325 const name = dataTransfer.getData("public.url-name"); 12326 if (name) { 12327 string = squishBreakableWhitespace(name).trim(); 12328 } else { 12329 string = href; 12330 } 12331 paste.html = this.createLinkHTML(href, string); 12332 (_this$delegate18 = this.delegate) === null || _this$delegate18 === void 0 || _this$delegate18.inputControllerWillPaste(paste); 12333 this.withTargetDOMRange(function () { 12334 var _this$responder32; 12335 return (_this$responder32 = this.responder) === null || _this$responder32 === void 0 ? void 0 : _this$responder32.insertHTML(paste.html); 12336 }); 12337 this.afterRender = () => { 12338 var _this$delegate19; 12339 return (_this$delegate19 = this.delegate) === null || _this$delegate19 === void 0 ? void 0 : _this$delegate19.inputControllerDidPaste(paste); 12340 }; 12341 } else if (dataTransferIsPlainText(dataTransfer)) { 12342 var _this$delegate20; 12343 paste.type = "text/plain"; 12344 paste.string = dataTransfer.getData("text/plain"); 12345 (_this$delegate20 = this.delegate) === null || _this$delegate20 === void 0 || _this$delegate20.inputControllerWillPaste(paste); 12346 this.withTargetDOMRange(function () { 12347 var _this$responder33; 12348 return (_this$responder33 = this.responder) === null || _this$responder33 === void 0 ? void 0 : _this$responder33.insertString(paste.string); 12349 }); 12350 this.afterRender = () => { 12351 var _this$delegate21; 12352 return (_this$delegate21 = this.delegate) === null || _this$delegate21 === void 0 ? void 0 : _this$delegate21.inputControllerDidPaste(paste); 12353 }; 12354 } else if (processableFilePaste(this.event)) { 12355 var _this$delegate22; 12356 paste.type = "File"; 12357 paste.file = dataTransfer.files[0]; 12358 (_this$delegate22 = this.delegate) === null || _this$delegate22 === void 0 || _this$delegate22.inputControllerWillPaste(paste); 12359 this.withTargetDOMRange(function () { 12360 var _this$responder34; 12361 return (_this$responder34 = this.responder) === null || _this$responder34 === void 0 ? void 0 : _this$responder34.insertFile(paste.file); 12362 }); 12363 this.afterRender = () => { 12364 var _this$delegate23; 12365 return (_this$delegate23 = this.delegate) === null || _this$delegate23 === void 0 ? void 0 : _this$delegate23.inputControllerDidPaste(paste); 12366 }; 12367 } else if (html) { 12368 var _this$delegate24; 12369 this.event.preventDefault(); 12370 paste.type = "text/html"; 12371 paste.html = html; 12372 (_this$delegate24 = this.delegate) === null || _this$delegate24 === void 0 || _this$delegate24.inputControllerWillPaste(paste); 12373 this.withTargetDOMRange(function () { 12374 var _this$responder35; 12375 return (_this$responder35 = this.responder) === null || _this$responder35 === void 0 ? void 0 : _this$responder35.insertHTML(paste.html); 12376 }); 12377 this.afterRender = () => { 12378 var _this$delegate25; 12379 return (_this$delegate25 = this.delegate) === null || _this$delegate25 === void 0 ? void 0 : _this$delegate25.inputControllerDidPaste(paste); 12380 }; 12381 } 12382 }, 12383 insertFromYank() { 12384 return this.insertString(this.event.data); 12385 }, 12386 insertLineBreak() { 12387 return this.insertString("\n"); 12388 }, 12389 insertLink() { 12390 return this.activateAttributeIfSupported("href", this.event.data); 12391 }, 12392 insertOrderedList() { 12393 return this.toggleAttributeIfSupported("number"); 12394 }, 12395 insertParagraph() { 12396 var _this$delegate26; 12397 (_this$delegate26 = this.delegate) === null || _this$delegate26 === void 0 || _this$delegate26.inputControllerWillPerformTyping(); 12398 return this.withTargetDOMRange(function () { 12399 var _this$responder36; 12400 return (_this$responder36 = this.responder) === null || _this$responder36 === void 0 ? void 0 : _this$responder36.insertLineBreak(); 12401 }); 12402 }, 12403 insertReplacementText() { 12404 const replacement = this.event.dataTransfer.getData("text/plain"); 12405 const domRange = this.event.getTargetRanges()[0]; 12406 this.withTargetDOMRange(domRange, () => { 12407 this.insertString(replacement, { 12408 updatePosition: false 12409 }); 12410 }); 12411 }, 12412 insertText() { 12413 var _this$event$dataTrans; 12414 return this.insertString(this.event.data || ((_this$event$dataTrans = this.event.dataTransfer) === null || _this$event$dataTrans === void 0 ? void 0 : _this$event$dataTrans.getData("text/plain"))); 12415 }, 12416 insertTranspose() { 12417 return this.insertString(this.event.data); 12418 }, 12419 insertUnorderedList() { 12420 return this.toggleAttributeIfSupported("bullet"); 12421 } 12422 }); 12423 const staticRangeToRange = function (staticRange) { 12424 const range = document.createRange(); 12425 range.setStart(staticRange.startContainer, staticRange.startOffset); 12426 range.setEnd(staticRange.endContainer, staticRange.endOffset); 12427 return range; 12428 }; 12429 12430 // Event helpers 12431 12432 const dragEventHasFiles = event => { 12433 var _event$dataTransfer; 12434 return Array.from(((_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.types) || []).includes("Files"); 12435 }; 12436 const processableFilePaste = event => { 12437 var _event$dataTransfer$f; 12438 // Paste events that only have files are handled by the paste event handler, 12439 // to work around Safari not supporting beforeinput.insertFromPaste for files. 12440 12441 // MS Office text pastes include a file with a screenshot of the text, but we should 12442 // handle them as text pastes. 12443 return ((_event$dataTransfer$f = event.dataTransfer.files) === null || _event$dataTransfer$f === void 0 ? void 0 : _event$dataTransfer$f[0]) && !pasteEventHasFilesOnly(event) && !dataTransferIsMsOfficePaste(event); 12444 }; 12445 const pasteEventHasFilesOnly = function (event) { 12446 const clipboard = event.clipboardData; 12447 if (clipboard) { 12448 const fileTypes = Array.from(clipboard.types).filter(type => type.match(/file/i)); // "Files", "application/x-moz-file" 12449 return fileTypes.length === clipboard.types.length && clipboard.files.length >= 1; 12450 } 12451 }; 12452 const pasteEventHasPlainTextOnly = function (event) { 12453 const clipboard = event.clipboardData; 12454 if (clipboard) { 12455 return clipboard.types.includes("text/plain") && clipboard.types.length === 1; 12456 } 12457 }; 12458 const keyboardCommandFromKeyEvent = function (event) { 12459 const command = []; 12460 if (event.altKey) { 12461 command.push("alt"); 12462 } 12463 if (event.shiftKey) { 12464 command.push("shift"); 12465 } 12466 command.push(event.key); 12467 return command; 12468 }; 12469 const pointFromEvent = event => ({ 12470 x: event.clientX, 12471 y: event.clientY 12472 }); 12473 12474 const attributeButtonSelector = "[data-trix-attribute]"; 12475 const actionButtonSelector = "[data-trix-action]"; 12476 const toolbarButtonSelector = "".concat(attributeButtonSelector, ", ").concat(actionButtonSelector); 12477 const dialogSelector = "[data-trix-dialog]"; 12478 const activeDialogSelector = "".concat(dialogSelector, "[data-trix-active]"); 12479 const dialogButtonSelector = "".concat(dialogSelector, " [data-trix-method]"); 12480 const dialogInputSelector = "".concat(dialogSelector, " [data-trix-input]"); 12481 const getInputForDialog = (element, attributeName) => { 12482 if (!attributeName) { 12483 attributeName = getAttributeName(element); 12484 } 12485 return element.querySelector("[data-trix-input][name='".concat(attributeName, "']")); 12486 }; 12487 const getActionName = element => element.getAttribute("data-trix-action"); 12488 const getAttributeName = element => { 12489 return element.getAttribute("data-trix-attribute") || element.getAttribute("data-trix-dialog-attribute"); 12490 }; 12491 const getDialogName = element => element.getAttribute("data-trix-dialog"); 12492 class ToolbarController extends BasicObject { 12493 constructor(element) { 12494 super(element); 12495 this.didClickActionButton = this.didClickActionButton.bind(this); 12496 this.didClickAttributeButton = this.didClickAttributeButton.bind(this); 12497 this.didClickDialogButton = this.didClickDialogButton.bind(this); 12498 this.didKeyDownDialogInput = this.didKeyDownDialogInput.bind(this); 12499 this.element = element; 12500 this.attributes = {}; 12501 this.actions = {}; 12502 this.resetDialogInputs(); 12503 handleEvent("mousedown", { 12504 onElement: this.element, 12505 matchingSelector: actionButtonSelector, 12506 withCallback: this.didClickActionButton 12507 }); 12508 handleEvent("mousedown", { 12509 onElement: this.element, 12510 matchingSelector: attributeButtonSelector, 12511 withCallback: this.didClickAttributeButton 12512 }); 12513 handleEvent("click", { 12514 onElement: this.element, 12515 matchingSelector: toolbarButtonSelector, 12516 preventDefault: true 12517 }); 12518 handleEvent("click", { 12519 onElement: this.element, 12520 matchingSelector: dialogButtonSelector, 12521 withCallback: this.didClickDialogButton 12522 }); 12523 handleEvent("keydown", { 12524 onElement: this.element, 12525 matchingSelector: dialogInputSelector, 12526 withCallback: this.didKeyDownDialogInput 12527 }); 12528 } 12529 12530 // Event handlers 12531 12532 didClickActionButton(event, element) { 12533 var _this$delegate; 12534 (_this$delegate = this.delegate) === null || _this$delegate === void 0 || _this$delegate.toolbarDidClickButton(); 12535 event.preventDefault(); 12536 const actionName = getActionName(element); 12537 if (this.getDialog(actionName)) { 12538 return this.toggleDialog(actionName); 12539 } else { 12540 var _this$delegate2; 12541 return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2.toolbarDidInvokeAction(actionName, element); 12542 } 12543 } 12544 didClickAttributeButton(event, element) { 12545 var _this$delegate3; 12546 (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || _this$delegate3.toolbarDidClickButton(); 12547 event.preventDefault(); 12548 const attributeName = getAttributeName(element); 12549 if (this.getDialog(attributeName)) { 12550 this.toggleDialog(attributeName); 12551 } else { 12552 var _this$delegate4; 12553 (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.toolbarDidToggleAttribute(attributeName); 12554 } 12555 return this.refreshAttributeButtons(); 12556 } 12557 didClickDialogButton(event, element) { 12558 const dialogElement = findClosestElementFromNode(element, { 12559 matchingSelector: dialogSelector 12560 }); 12561 const method = element.getAttribute("data-trix-method"); 12562 return this[method].call(this, dialogElement); 12563 } 12564 didKeyDownDialogInput(event, element) { 12565 if (event.keyCode === 13) { 12566 // Enter key 12567 event.preventDefault(); 12568 const attribute = element.getAttribute("name"); 12569 const dialog = this.getDialog(attribute); 12570 this.setAttribute(dialog); 12571 } 12572 if (event.keyCode === 27) { 12573 // Escape key 12574 event.preventDefault(); 12575 return this.hideDialog(); 12576 } 12577 } 12578 12579 // Action buttons 12580 12581 updateActions(actions) { 12582 this.actions = actions; 12583 return this.refreshActionButtons(); 12584 } 12585 refreshActionButtons() { 12586 return this.eachActionButton((element, actionName) => { 12587 element.disabled = this.actions[actionName] === false; 12588 }); 12589 } 12590 eachActionButton(callback) { 12591 return Array.from(this.element.querySelectorAll(actionButtonSelector)).map(element => callback(element, getActionName(element))); 12592 } 12593 12594 // Attribute buttons 12595 12596 updateAttributes(attributes) { 12597 this.attributes = attributes; 12598 return this.refreshAttributeButtons(); 12599 } 12600 refreshAttributeButtons() { 12601 return this.eachAttributeButton((element, attributeName) => { 12602 element.disabled = this.attributes[attributeName] === false; 12603 if (this.attributes[attributeName] || this.dialogIsVisible(attributeName)) { 12604 element.setAttribute("data-trix-active", ""); 12605 return element.classList.add("trix-active"); 12606 } else { 12607 element.removeAttribute("data-trix-active"); 12608 return element.classList.remove("trix-active"); 12609 } 12610 }); 12611 } 12612 eachAttributeButton(callback) { 12613 return Array.from(this.element.querySelectorAll(attributeButtonSelector)).map(element => callback(element, getAttributeName(element))); 12614 } 12615 applyKeyboardCommand(keys) { 12616 const keyString = JSON.stringify(keys.sort()); 12617 for (const button of Array.from(this.element.querySelectorAll("[data-trix-key]"))) { 12618 const buttonKeys = button.getAttribute("data-trix-key").split("+"); 12619 const buttonKeyString = JSON.stringify(buttonKeys.sort()); 12620 if (buttonKeyString === keyString) { 12621 triggerEvent("mousedown", { 12622 onElement: button 12623 }); 12624 return true; 12625 } 12626 } 12627 return false; 12628 } 12629 12630 // Dialogs 12631 12632 dialogIsVisible(dialogName) { 12633 const element = this.getDialog(dialogName); 12634 if (element) { 12635 return element.hasAttribute("data-trix-active"); 12636 } 12637 } 12638 toggleDialog(dialogName) { 12639 if (this.dialogIsVisible(dialogName)) { 12640 return this.hideDialog(); 12641 } else { 12642 return this.showDialog(dialogName); 12643 } 12644 } 12645 showDialog(dialogName) { 12646 var _this$delegate5, _this$delegate6; 12647 this.hideDialog(); 12648 (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || _this$delegate5.toolbarWillShowDialog(); 12649 const element = this.getDialog(dialogName); 12650 element.setAttribute("data-trix-active", ""); 12651 element.classList.add("trix-active"); 12652 Array.from(element.querySelectorAll("input[disabled]")).forEach(disabledInput => { 12653 disabledInput.removeAttribute("disabled"); 12654 }); 12655 const attributeName = getAttributeName(element); 12656 if (attributeName) { 12657 const input = getInputForDialog(element, dialogName); 12658 if (input) { 12659 input.value = this.attributes[attributeName] || ""; 12660 input.select(); 12661 } 12662 } 12663 return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 ? void 0 : _this$delegate6.toolbarDidShowDialog(dialogName); 12664 } 12665 setAttribute(dialogElement) { 12666 var _this$delegate7; 12667 const attributeName = getAttributeName(dialogElement); 12668 const input = getInputForDialog(dialogElement, attributeName); 12669 if (input.willValidate) { 12670 input.setCustomValidity(""); 12671 if (!input.checkValidity() || !this.isSafeAttribute(input)) { 12672 input.setCustomValidity("Invalid value"); 12673 input.setAttribute("data-trix-validate", ""); 12674 input.classList.add("trix-validate"); 12675 return input.focus(); 12676 } 12677 } 12678 (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || _this$delegate7.toolbarDidUpdateAttribute(attributeName, input.value); 12679 return this.hideDialog(); 12680 } 12681 isSafeAttribute(input) { 12682 if (input.hasAttribute("data-trix-validate-href")) { 12683 return purify.isValidAttribute("a", "href", input.value); 12684 } else { 12685 return true; 12686 } 12687 } 12688 removeAttribute(dialogElement) { 12689 var _this$delegate8; 12690 const attributeName = getAttributeName(dialogElement); 12691 (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || _this$delegate8.toolbarDidRemoveAttribute(attributeName); 12692 return this.hideDialog(); 12693 } 12694 hideDialog() { 12695 const element = this.element.querySelector(activeDialogSelector); 12696 if (element) { 12697 var _this$delegate9; 12698 element.removeAttribute("data-trix-active"); 12699 element.classList.remove("trix-active"); 12700 this.resetDialogInputs(); 12701 return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 ? void 0 : _this$delegate9.toolbarDidHideDialog(getDialogName(element)); 12702 } 12703 } 12704 resetDialogInputs() { 12705 Array.from(this.element.querySelectorAll(dialogInputSelector)).forEach(input => { 12706 input.setAttribute("disabled", "disabled"); 12707 input.removeAttribute("data-trix-validate"); 12708 input.classList.remove("trix-validate"); 12709 }); 12710 } 12711 getDialog(dialogName) { 12712 return this.element.querySelector("[data-trix-dialog=".concat(dialogName, "]")); 12713 } 12714 } 12715 12716 const snapshotsAreEqual = (a, b) => rangesAreEqual(a.selectedRange, b.selectedRange) && a.document.isEqualTo(b.document); 12717 class EditorController extends Controller { 12718 constructor(_ref) { 12719 let { 12720 editorElement, 12721 document, 12722 html 12723 } = _ref; 12724 super(...arguments); 12725 this.editorElement = editorElement; 12726 this.selectionManager = new SelectionManager(this.editorElement); 12727 this.selectionManager.delegate = this; 12728 this.composition = new Composition(); 12729 this.composition.delegate = this; 12730 this.attachmentManager = new AttachmentManager(this.composition.getAttachments()); 12731 this.attachmentManager.delegate = this; 12732 this.inputController = input.getLevel() === 2 ? new Level2InputController(this.editorElement) : new Level0InputController(this.editorElement); 12733 this.inputController.delegate = this; 12734 this.inputController.responder = this.composition; 12735 this.compositionController = new CompositionController(this.editorElement, this.composition); 12736 this.compositionController.delegate = this; 12737 this.toolbarController = new ToolbarController(this.editorElement.toolbarElement); 12738 this.toolbarController.delegate = this; 12739 this.editor = new Editor(this.composition, this.selectionManager, this.editorElement); 12740 if (document) { 12741 this.editor.loadDocument(document); 12742 } else { 12743 this.editor.loadHTML(html); 12744 } 12745 } 12746 registerSelectionManager() { 12747 return selectionChangeObserver.registerSelectionManager(this.selectionManager); 12748 } 12749 unregisterSelectionManager() { 12750 return selectionChangeObserver.unregisterSelectionManager(this.selectionManager); 12751 } 12752 render() { 12753 return this.compositionController.render(); 12754 } 12755 reparse() { 12756 return this.composition.replaceHTML(this.editorElement.innerHTML); 12757 } 12758 12759 // Composition delegate 12760 12761 compositionDidChangeDocument(document) { 12762 this.notifyEditorElement("document-change"); 12763 if (!this.handlingInput) { 12764 return this.render(); 12765 } 12766 } 12767 compositionDidChangeCurrentAttributes(currentAttributes) { 12768 this.currentAttributes = currentAttributes; 12769 this.toolbarController.updateAttributes(this.currentAttributes); 12770 this.updateCurrentActions(); 12771 return this.notifyEditorElement("attributes-change", { 12772 attributes: this.currentAttributes 12773 }); 12774 } 12775 compositionDidPerformInsertionAtRange(range) { 12776 if (this.pasting) { 12777 this.pastedRange = range; 12778 } 12779 } 12780 compositionShouldAcceptFile(file) { 12781 return this.notifyEditorElement("file-accept", { 12782 file 12783 }); 12784 } 12785 compositionDidAddAttachment(attachment) { 12786 const managedAttachment = this.attachmentManager.manageAttachment(attachment); 12787 return this.notifyEditorElement("attachment-add", { 12788 attachment: managedAttachment 12789 }); 12790 } 12791 compositionDidEditAttachment(attachment) { 12792 this.compositionController.rerenderViewForObject(attachment); 12793 const managedAttachment = this.attachmentManager.manageAttachment(attachment); 12794 this.notifyEditorElement("attachment-edit", { 12795 attachment: managedAttachment 12796 }); 12797 return this.notifyEditorElement("change"); 12798 } 12799 compositionDidChangeAttachmentPreviewURL(attachment) { 12800 this.compositionController.invalidateViewForObject(attachment); 12801 return this.notifyEditorElement("change"); 12802 } 12803 compositionDidRemoveAttachment(attachment) { 12804 const managedAttachment = this.attachmentManager.unmanageAttachment(attachment); 12805 return this.notifyEditorElement("attachment-remove", { 12806 attachment: managedAttachment 12807 }); 12808 } 12809 compositionDidStartEditingAttachment(attachment, options) { 12810 this.attachmentLocationRange = this.composition.document.getLocationRangeOfAttachment(attachment); 12811 this.compositionController.installAttachmentEditorForAttachment(attachment, options); 12812 return this.selectionManager.setLocationRange(this.attachmentLocationRange); 12813 } 12814 compositionDidStopEditingAttachment(attachment) { 12815 this.compositionController.uninstallAttachmentEditor(); 12816 this.attachmentLocationRange = null; 12817 } 12818 compositionDidRequestChangingSelectionToLocationRange(locationRange) { 12819 if (this.loadingSnapshot && !this.isFocused()) return; 12820 this.requestedLocationRange = locationRange; 12821 this.compositionRevisionWhenLocationRangeRequested = this.composition.revision; 12822 if (!this.handlingInput) { 12823 return this.render(); 12824 } 12825 } 12826 compositionWillLoadSnapshot() { 12827 this.loadingSnapshot = true; 12828 } 12829 compositionDidLoadSnapshot() { 12830 this.compositionController.refreshViewCache(); 12831 this.render(); 12832 this.loadingSnapshot = false; 12833 } 12834 getSelectionManager() { 12835 return this.selectionManager; 12836 } 12837 12838 // Attachment manager delegate 12839 12840 attachmentManagerDidRequestRemovalOfAttachment(attachment) { 12841 return this.removeAttachment(attachment); 12842 } 12843 12844 // Document controller delegate 12845 12846 compositionControllerWillSyncDocumentView() { 12847 this.inputController.editorWillSyncDocumentView(); 12848 this.selectionManager.lock(); 12849 return this.selectionManager.clearSelection(); 12850 } 12851 compositionControllerDidSyncDocumentView() { 12852 this.inputController.editorDidSyncDocumentView(); 12853 this.selectionManager.unlock(); 12854 this.updateCurrentActions(); 12855 return this.notifyEditorElement("sync"); 12856 } 12857 compositionControllerDidRender() { 12858 if (this.requestedLocationRange) { 12859 if (this.compositionRevisionWhenLocationRangeRequested === this.composition.revision) { 12860 this.selectionManager.setLocationRange(this.requestedLocationRange); 12861 } 12862 this.requestedLocationRange = null; 12863 this.compositionRevisionWhenLocationRangeRequested = null; 12864 } 12865 if (this.renderedCompositionRevision !== this.composition.revision) { 12866 this.runEditorFilters(); 12867 this.composition.updateCurrentAttributes(); 12868 this.notifyEditorElement("render"); 12869 } 12870 this.renderedCompositionRevision = this.composition.revision; 12871 } 12872 compositionControllerDidFocus() { 12873 if (this.isFocusedInvisibly()) { 12874 this.setLocationRange({ 12875 index: 0, 12876 offset: 0 12877 }); 12878 } 12879 this.toolbarController.hideDialog(); 12880 return this.notifyEditorElement("focus"); 12881 } 12882 compositionControllerDidBlur() { 12883 return this.notifyEditorElement("blur"); 12884 } 12885 compositionControllerDidSelectAttachment(attachment, options) { 12886 this.toolbarController.hideDialog(); 12887 return this.composition.editAttachment(attachment, options); 12888 } 12889 compositionControllerDidRequestDeselectingAttachment(attachment) { 12890 const locationRange = this.attachmentLocationRange || this.composition.document.getLocationRangeOfAttachment(attachment); 12891 return this.selectionManager.setLocationRange(locationRange[1]); 12892 } 12893 compositionControllerWillUpdateAttachment(attachment) { 12894 return this.editor.recordUndoEntry("Edit Attachment", { 12895 context: attachment.id, 12896 consolidatable: true 12897 }); 12898 } 12899 compositionControllerDidRequestRemovalOfAttachment(attachment) { 12900 return this.removeAttachment(attachment); 12901 } 12902 12903 // Input controller delegate 12904 12905 inputControllerWillHandleInput() { 12906 this.handlingInput = true; 12907 this.requestedRender = false; 12908 } 12909 inputControllerDidRequestRender() { 12910 this.requestedRender = true; 12911 } 12912 inputControllerDidHandleInput() { 12913 this.handlingInput = false; 12914 if (this.requestedRender) { 12915 this.requestedRender = false; 12916 return this.render(); 12917 } 12918 } 12919 inputControllerDidAllowUnhandledInput() { 12920 return this.notifyEditorElement("change"); 12921 } 12922 inputControllerDidRequestReparse() { 12923 return this.reparse(); 12924 } 12925 inputControllerWillPerformTyping() { 12926 return this.recordTypingUndoEntry(); 12927 } 12928 inputControllerWillPerformFormatting(attributeName) { 12929 return this.recordFormattingUndoEntry(attributeName); 12930 } 12931 inputControllerWillCutText() { 12932 return this.editor.recordUndoEntry("Cut"); 12933 } 12934 inputControllerWillPaste(paste) { 12935 this.editor.recordUndoEntry("Paste"); 12936 this.pasting = true; 12937 return this.notifyEditorElement("before-paste", { 12938 paste 12939 }); 12940 } 12941 inputControllerDidPaste(paste) { 12942 paste.range = this.pastedRange; 12943 this.pastedRange = null; 12944 this.pasting = null; 12945 return this.notifyEditorElement("paste", { 12946 paste 12947 }); 12948 } 12949 inputControllerWillMoveText() { 12950 return this.editor.recordUndoEntry("Move"); 12951 } 12952 inputControllerWillAttachFiles() { 12953 return this.editor.recordUndoEntry("Drop Files"); 12954 } 12955 inputControllerWillPerformUndo() { 12956 return this.editor.undo(); 12957 } 12958 inputControllerWillPerformRedo() { 12959 return this.editor.redo(); 12960 } 12961 inputControllerDidReceiveKeyboardCommand(keys) { 12962 return this.toolbarController.applyKeyboardCommand(keys); 12963 } 12964 inputControllerDidStartDrag() { 12965 this.locationRangeBeforeDrag = this.selectionManager.getLocationRange(); 12966 } 12967 inputControllerDidReceiveDragOverPoint(point) { 12968 return this.selectionManager.setLocationRangeFromPointRange(point); 12969 } 12970 inputControllerDidCancelDrag() { 12971 this.selectionManager.setLocationRange(this.locationRangeBeforeDrag); 12972 this.locationRangeBeforeDrag = null; 12973 } 12974 12975 // Selection manager delegate 12976 12977 locationRangeDidChange(locationRange) { 12978 this.composition.updateCurrentAttributes(); 12979 this.updateCurrentActions(); 12980 if (this.attachmentLocationRange && !rangesAreEqual(this.attachmentLocationRange, locationRange)) { 12981 this.composition.stopEditingAttachment(); 12982 } 12983 return this.notifyEditorElement("selection-change"); 12984 } 12985 12986 // Toolbar controller delegate 12987 12988 toolbarDidClickButton() { 12989 if (!this.getLocationRange()) { 12990 return this.setLocationRange({ 12991 index: 0, 12992 offset: 0 12993 }); 12994 } 12995 } 12996 toolbarDidInvokeAction(actionName, invokingElement) { 12997 return this.invokeAction(actionName, invokingElement); 12998 } 12999 toolbarDidToggleAttribute(attributeName) { 13000 this.recordFormattingUndoEntry(attributeName); 13001 this.composition.toggleCurrentAttribute(attributeName); 13002 this.render(); 13003 if (!this.selectionFrozen) { 13004 return this.editorElement.focus(); 13005 } 13006 } 13007 toolbarDidUpdateAttribute(attributeName, value) { 13008 this.recordFormattingUndoEntry(attributeName); 13009 this.composition.setCurrentAttribute(attributeName, value); 13010 this.render(); 13011 if (!this.selectionFrozen) { 13012 return this.editorElement.focus(); 13013 } 13014 } 13015 toolbarDidRemoveAttribute(attributeName) { 13016 this.recordFormattingUndoEntry(attributeName); 13017 this.composition.removeCurrentAttribute(attributeName); 13018 this.render(); 13019 if (!this.selectionFrozen) { 13020 return this.editorElement.focus(); 13021 } 13022 } 13023 toolbarWillShowDialog(dialogElement) { 13024 this.composition.expandSelectionForEditing(); 13025 return this.freezeSelection(); 13026 } 13027 toolbarDidShowDialog(dialogName) { 13028 return this.notifyEditorElement("toolbar-dialog-show", { 13029 dialogName 13030 }); 13031 } 13032 toolbarDidHideDialog(dialogName) { 13033 this.thawSelection(); 13034 this.editorElement.focus(); 13035 return this.notifyEditorElement("toolbar-dialog-hide", { 13036 dialogName 13037 }); 13038 } 13039 13040 // Selection 13041 13042 freezeSelection() { 13043 if (!this.selectionFrozen) { 13044 this.selectionManager.lock(); 13045 this.composition.freezeSelection(); 13046 this.selectionFrozen = true; 13047 return this.render(); 13048 } 13049 } 13050 thawSelection() { 13051 if (this.selectionFrozen) { 13052 this.composition.thawSelection(); 13053 this.selectionManager.unlock(); 13054 this.selectionFrozen = false; 13055 return this.render(); 13056 } 13057 } 13058 canInvokeAction(actionName) { 13059 if (this.actionIsExternal(actionName)) { 13060 return true; 13061 } else { 13062 var _this$actions$actionN; 13063 return !!((_this$actions$actionN = this.actions[actionName]) !== null && _this$actions$actionN !== void 0 && (_this$actions$actionN = _this$actions$actionN.test) !== null && _this$actions$actionN !== void 0 && _this$actions$actionN.call(this)); 13064 } 13065 } 13066 invokeAction(actionName, invokingElement) { 13067 if (this.actionIsExternal(actionName)) { 13068 return this.notifyEditorElement("action-invoke", { 13069 actionName, 13070 invokingElement 13071 }); 13072 } else { 13073 var _this$actions$actionN2; 13074 return (_this$actions$actionN2 = this.actions[actionName]) === null || _this$actions$actionN2 === void 0 || (_this$actions$actionN2 = _this$actions$actionN2.perform) === null || _this$actions$actionN2 === void 0 ? void 0 : _this$actions$actionN2.call(this); 13075 } 13076 } 13077 actionIsExternal(actionName) { 13078 return /^x-./.test(actionName); 13079 } 13080 getCurrentActions() { 13081 const result = {}; 13082 for (const actionName in this.actions) { 13083 result[actionName] = this.canInvokeAction(actionName); 13084 } 13085 return result; 13086 } 13087 updateCurrentActions() { 13088 const currentActions = this.getCurrentActions(); 13089 if (!objectsAreEqual(currentActions, this.currentActions)) { 13090 this.currentActions = currentActions; 13091 this.toolbarController.updateActions(this.currentActions); 13092 return this.notifyEditorElement("actions-change", { 13093 actions: this.currentActions 13094 }); 13095 } 13096 } 13097 13098 // Editor filters 13099 13100 runEditorFilters() { 13101 let snapshot = this.composition.getSnapshot(); 13102 Array.from(this.editor.filters).forEach(filter => { 13103 const { 13104 document, 13105 selectedRange 13106 } = snapshot; 13107 snapshot = filter.call(this.editor, snapshot) || {}; 13108 if (!snapshot.document) { 13109 snapshot.document = document; 13110 } 13111 if (!snapshot.selectedRange) { 13112 snapshot.selectedRange = selectedRange; 13113 } 13114 }); 13115 if (!snapshotsAreEqual(snapshot, this.composition.getSnapshot())) { 13116 return this.composition.loadSnapshot(snapshot); 13117 } 13118 } 13119 13120 // Private 13121 13122 updateInputElement() { 13123 const element = this.compositionController.getSerializableElement(); 13124 const value = serializeToContentType(element, "text/html"); 13125 return this.editorElement.setFormValue(value); 13126 } 13127 notifyEditorElement(message, data) { 13128 switch (message) { 13129 case "document-change": 13130 this.documentChangedSinceLastRender = true; 13131 break; 13132 case "render": 13133 if (this.documentChangedSinceLastRender) { 13134 this.documentChangedSinceLastRender = false; 13135 this.notifyEditorElement("change"); 13136 } 13137 break; 13138 case "change": 13139 case "attachment-add": 13140 case "attachment-edit": 13141 case "attachment-remove": 13142 this.updateInputElement(); 13143 break; 13144 } 13145 return this.editorElement.notify(message, data); 13146 } 13147 removeAttachment(attachment) { 13148 this.editor.recordUndoEntry("Delete Attachment"); 13149 this.composition.removeAttachment(attachment); 13150 return this.render(); 13151 } 13152 recordFormattingUndoEntry(attributeName) { 13153 const blockConfig = getBlockConfig(attributeName); 13154 const locationRange = this.selectionManager.getLocationRange(); 13155 if (blockConfig || !rangeIsCollapsed(locationRange)) { 13156 return this.editor.recordUndoEntry("Formatting", { 13157 context: this.getUndoContext(), 13158 consolidatable: true 13159 }); 13160 } 13161 } 13162 recordTypingUndoEntry() { 13163 return this.editor.recordUndoEntry("Typing", { 13164 context: this.getUndoContext(this.currentAttributes), 13165 consolidatable: true 13166 }); 13167 } 13168 getUndoContext() { 13169 for (var _len = arguments.length, context = new Array(_len), _key = 0; _key < _len; _key++) { 13170 context[_key] = arguments[_key]; 13171 } 13172 return [this.getLocationContext(), this.getTimeContext(), ...Array.from(context)]; 13173 } 13174 getLocationContext() { 13175 const locationRange = this.selectionManager.getLocationRange(); 13176 if (rangeIsCollapsed(locationRange)) { 13177 return locationRange[0].index; 13178 } else { 13179 return locationRange; 13180 } 13181 } 13182 getTimeContext() { 13183 if (undo.interval > 0) { 13184 return Math.floor(new Date().getTime() / undo.interval); 13185 } else { 13186 return 0; 13187 } 13188 } 13189 isFocused() { 13190 var _this$editorElement$o; 13191 return this.editorElement === ((_this$editorElement$o = this.editorElement.ownerDocument) === null || _this$editorElement$o === void 0 ? void 0 : _this$editorElement$o.activeElement); 13192 } 13193 13194 // Detect "Cursor disappears sporadically" Firefox bug. 13195 // - https://bugzilla.mozilla.org/show_bug.cgi?id=226301 13196 isFocusedInvisibly() { 13197 return this.isFocused() && !this.getLocationRange(); 13198 } 13199 get actions() { 13200 return this.constructor.actions; 13201 } 13202 } 13203 _defineProperty(EditorController, "actions", { 13204 undo: { 13205 test() { 13206 return this.editor.canUndo(); 13207 }, 13208 perform() { 13209 return this.editor.undo(); 13210 } 13211 }, 13212 redo: { 13213 test() { 13214 return this.editor.canRedo(); 13215 }, 13216 perform() { 13217 return this.editor.redo(); 13218 } 13219 }, 13220 link: { 13221 test() { 13222 return this.editor.canActivateAttribute("href"); 13223 } 13224 }, 13225 increaseNestingLevel: { 13226 test() { 13227 return this.editor.canIncreaseNestingLevel(); 13228 }, 13229 perform() { 13230 return this.editor.increaseNestingLevel() && this.render(); 13231 } 13232 }, 13233 decreaseNestingLevel: { 13234 test() { 13235 return this.editor.canDecreaseNestingLevel(); 13236 }, 13237 perform() { 13238 return this.editor.decreaseNestingLevel() && this.render(); 13239 } 13240 }, 13241 attachFiles: { 13242 test() { 13243 return true; 13244 }, 13245 perform() { 13246 return input.pickFiles(this.editor.insertFiles); 13247 } 13248 } 13249 }); 13250 EditorController.proxyMethod("getSelectionManager().setLocationRange"); 13251 EditorController.proxyMethod("getSelectionManager().getLocationRange"); 13252 13253 var controllers = /*#__PURE__*/Object.freeze({ 13254 __proto__: null, 13255 AttachmentEditorController: AttachmentEditorController, 13256 CompositionController: CompositionController, 13257 Controller: Controller, 13258 EditorController: EditorController, 13259 InputController: InputController, 13260 Level0InputController: Level0InputController, 13261 Level2InputController: Level2InputController, 13262 ToolbarController: ToolbarController 13263 }); 13264 13265 var observers = /*#__PURE__*/Object.freeze({ 13266 __proto__: null, 13267 MutationObserver: MutationObserver, 13268 SelectionChangeObserver: SelectionChangeObserver 13269 }); 13270 13271 var operations = /*#__PURE__*/Object.freeze({ 13272 __proto__: null, 13273 FileVerificationOperation: FileVerificationOperation, 13274 ImagePreloadOperation: ImagePreloadOperation 13275 }); 13276 13277 installDefaultCSSForTagName("trix-toolbar", "%t {\n display: block;\n}\n\n%t {\n white-space: nowrap;\n}\n\n%t [data-trix-dialog] {\n display: none;\n}\n\n%t [data-trix-dialog][data-trix-active] {\n display: block;\n}\n\n%t [data-trix-dialog] [data-trix-validate]:invalid {\n background-color: #ffdddd;\n}"); 13278 class TrixToolbarElement extends HTMLElement { 13279 // Element lifecycle 13280 13281 connectedCallback() { 13282 if (this.innerHTML === "") { 13283 this.innerHTML = toolbar.getDefaultHTML(); 13284 } 13285 } 13286 13287 // Properties 13288 13289 get editorElements() { 13290 if (this.id) { 13291 var _this$ownerDocument; 13292 const nodeList = (_this$ownerDocument = this.ownerDocument) === null || _this$ownerDocument === void 0 ? void 0 : _this$ownerDocument.querySelectorAll("trix-editor[toolbar=\"".concat(this.id, "\"]")); 13293 return Array.from(nodeList); 13294 } else { 13295 return []; 13296 } 13297 } 13298 get editorElement() { 13299 const [editorElement] = this.editorElements; 13300 return editorElement; 13301 } 13302 } 13303 13304 let id = 0; 13305 13306 // Contenteditable support helpers 13307 13308 const autofocus = function (element) { 13309 if (!document.querySelector(":focus")) { 13310 if (element.hasAttribute("autofocus") && document.querySelector("[autofocus]") === element) { 13311 return element.focus(); 13312 } 13313 } 13314 }; 13315 const makeEditable = function (element) { 13316 if (element.hasAttribute("contenteditable")) { 13317 return; 13318 } 13319 element.toggleAttribute("contenteditable", !element.disabled); 13320 return handleEventOnce("focus", { 13321 onElement: element, 13322 withCallback() { 13323 return configureContentEditable(element); 13324 } 13325 }); 13326 }; 13327 const configureContentEditable = function (element) { 13328 disableObjectResizing(element); 13329 return setDefaultParagraphSeparator(element); 13330 }; 13331 const disableObjectResizing = function (element) { 13332 var _document$queryComman, _document; 13333 if ((_document$queryComman = (_document = document).queryCommandSupported) !== null && _document$queryComman !== void 0 && _document$queryComman.call(_document, "enableObjectResizing")) { 13334 document.execCommand("enableObjectResizing", false, false); 13335 return handleEvent("mscontrolselect", { 13336 onElement: element, 13337 preventDefault: true 13338 }); 13339 } 13340 }; 13341 const setDefaultParagraphSeparator = function (element) { 13342 var _document$queryComman2, _document2; 13343 if ((_document$queryComman2 = (_document2 = document).queryCommandSupported) !== null && _document$queryComman2 !== void 0 && _document$queryComman2.call(_document2, "DefaultParagraphSeparator")) { 13344 const { 13345 tagName 13346 } = attributes.default; 13347 if (["div", "p"].includes(tagName)) { 13348 return document.execCommand("DefaultParagraphSeparator", false, tagName); 13349 } 13350 } 13351 }; 13352 13353 // Accessibility helpers 13354 13355 const addAccessibilityRole = function (element) { 13356 if (element.hasAttribute("role")) { 13357 return; 13358 } 13359 return element.setAttribute("role", "textbox"); 13360 }; 13361 const ensureAriaLabel = function (element) { 13362 if (element.hasAttribute("aria-label") || element.hasAttribute("aria-labelledby")) { 13363 return; 13364 } 13365 const update = function () { 13366 const texts = Array.from(element.labels).map(label => { 13367 if (!label.contains(element)) return label.textContent; 13368 }).filter(text => text); 13369 const text = texts.join(" "); 13370 if (text) { 13371 return element.setAttribute("aria-label", text); 13372 } else { 13373 return element.removeAttribute("aria-label"); 13374 } 13375 }; 13376 update(); 13377 return handleEvent("focus", { 13378 onElement: element, 13379 withCallback: update 13380 }); 13381 }; 13382 13383 // Style 13384 13385 const cursorTargetStyles = function () { 13386 if (browser$1.forcesObjectResizing) { 13387 return { 13388 display: "inline", 13389 width: "auto" 13390 }; 13391 } else { 13392 return { 13393 display: "inline-block", 13394 width: "1px" 13395 }; 13396 } 13397 }(); 13398 installDefaultCSSForTagName("trix-editor", "%t {\n display: block;\n}\n\n%t:empty::before {\n content: attr(placeholder);\n color: graytext;\n cursor: text;\n pointer-events: none;\n white-space: pre-line;\n}\n\n%t a[contenteditable=false] {\n cursor: text;\n}\n\n%t img {\n max-width: 100%;\n height: auto;\n}\n\n%t ".concat(attachmentSelector, " figcaption textarea {\n resize: none;\n}\n\n%t ").concat(attachmentSelector, " figcaption textarea.trix-autoresize-clone {\n position: absolute;\n left: -9999px;\n max-height: 0px;\n}\n\n%t ").concat(attachmentSelector, " figcaption[data-trix-placeholder]:empty::before {\n content: attr(data-trix-placeholder);\n color: graytext;\n}\n\n%t [data-trix-cursor-target] {\n display: ").concat(cursorTargetStyles.display, " !important;\n width: ").concat(cursorTargetStyles.width, " !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n}\n\n%t [data-trix-cursor-target=left] {\n vertical-align: top !important;\n margin-left: -1px !important;\n}\n\n%t [data-trix-cursor-target=right] {\n vertical-align: bottom !important;\n margin-right: -1px !important;\n}")); 13399 var _internals = /*#__PURE__*/new WeakMap(); 13400 var _formDisabled = /*#__PURE__*/new WeakMap(); 13401 var _validate = /*#__PURE__*/new WeakSet(); 13402 class ElementInternalsDelegate { 13403 constructor(element) { 13404 _classPrivateMethodInitSpec(this, _validate); 13405 _defineProperty(this, "value", ""); 13406 _classPrivateFieldInitSpec(this, _internals, { 13407 writable: true, 13408 value: void 0 13409 }); 13410 _classPrivateFieldInitSpec(this, _formDisabled, { 13411 writable: true, 13412 value: void 0 13413 }); 13414 this.element = element; 13415 _classPrivateFieldSet(this, _internals, element.attachInternals()); 13416 _classPrivateFieldSet(this, _formDisabled, false); 13417 } 13418 connectedCallback() { 13419 _classPrivateMethodGet(this, _validate, _validate2).call(this); 13420 } 13421 disconnectedCallback() {} 13422 get form() { 13423 return _classPrivateFieldGet(this, _internals).form; 13424 } 13425 get name() { 13426 return this.element.getAttribute("name"); 13427 } 13428 set name(value) { 13429 this.element.setAttribute("name", value); 13430 } 13431 get labels() { 13432 return _classPrivateFieldGet(this, _internals).labels; 13433 } 13434 get disabled() { 13435 return _classPrivateFieldGet(this, _formDisabled) || this.element.hasAttribute("disabled"); 13436 } 13437 set disabled(value) { 13438 this.element.toggleAttribute("disabled", value); 13439 } 13440 get required() { 13441 return this.element.hasAttribute("required"); 13442 } 13443 set required(value) { 13444 this.element.toggleAttribute("required", value); 13445 _classPrivateMethodGet(this, _validate, _validate2).call(this); 13446 } 13447 get validity() { 13448 return _classPrivateFieldGet(this, _internals).validity; 13449 } 13450 get validationMessage() { 13451 return _classPrivateFieldGet(this, _internals).validationMessage; 13452 } 13453 get willValidate() { 13454 return _classPrivateFieldGet(this, _internals).willValidate; 13455 } 13456 formDisabledCallback(disabled) { 13457 _classPrivateFieldSet(this, _formDisabled, disabled); 13458 } 13459 setFormValue(value) { 13460 this.value = value; 13461 _classPrivateMethodGet(this, _validate, _validate2).call(this); 13462 _classPrivateFieldGet(this, _internals).setFormValue(this.element.disabled ? undefined : this.value); 13463 } 13464 checkValidity() { 13465 return _classPrivateFieldGet(this, _internals).checkValidity(); 13466 } 13467 reportValidity() { 13468 return _classPrivateFieldGet(this, _internals).reportValidity(); 13469 } 13470 setCustomValidity(validationMessage) { 13471 _classPrivateMethodGet(this, _validate, _validate2).call(this, validationMessage); 13472 } 13473 } 13474 function _validate2() { 13475 let customValidationMessage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; 13476 const { 13477 required, 13478 value 13479 } = this.element; 13480 const valueMissing = required && !value; 13481 const customError = !!customValidationMessage; 13482 const input = makeElement("input", { 13483 required 13484 }); 13485 const validationMessage = customValidationMessage || input.validationMessage; 13486 _classPrivateFieldGet(this, _internals).setValidity({ 13487 valueMissing, 13488 customError 13489 }, validationMessage); 13490 } 13491 var _focusHandler = /*#__PURE__*/new WeakMap(); 13492 var _resetBubbled = /*#__PURE__*/new WeakMap(); 13493 var _clickBubbled = /*#__PURE__*/new WeakMap(); 13494 class LegacyDelegate { 13495 constructor(element) { 13496 _classPrivateFieldInitSpec(this, _focusHandler, { 13497 writable: true, 13498 value: void 0 13499 }); 13500 _classPrivateFieldInitSpec(this, _resetBubbled, { 13501 writable: true, 13502 value: event => { 13503 if (event.defaultPrevented) return; 13504 if (event.target !== this.element.form) return; 13505 this.element.reset(); 13506 } 13507 }); 13508 _classPrivateFieldInitSpec(this, _clickBubbled, { 13509 writable: true, 13510 value: event => { 13511 if (event.defaultPrevented) return; 13512 if (this.element.contains(event.target)) return; 13513 const label = findClosestElementFromNode(event.target, { 13514 matchingSelector: "label" 13515 }); 13516 if (!label) return; 13517 if (!Array.from(this.labels).includes(label)) return; 13518 this.element.focus(); 13519 } 13520 }); 13521 this.element = element; 13522 } 13523 connectedCallback() { 13524 _classPrivateFieldSet(this, _focusHandler, ensureAriaLabel(this.element)); 13525 window.addEventListener("reset", _classPrivateFieldGet(this, _resetBubbled), false); 13526 window.addEventListener("click", _classPrivateFieldGet(this, _clickBubbled), false); 13527 } 13528 disconnectedCallback() { 13529 var _classPrivateFieldGet2; 13530 (_classPrivateFieldGet2 = _classPrivateFieldGet(this, _focusHandler)) === null || _classPrivateFieldGet2 === void 0 || _classPrivateFieldGet2.destroy(); 13531 window.removeEventListener("reset", _classPrivateFieldGet(this, _resetBubbled), false); 13532 window.removeEventListener("click", _classPrivateFieldGet(this, _clickBubbled), false); 13533 } 13534 get labels() { 13535 const labels = []; 13536 if (this.element.id && this.element.ownerDocument) { 13537 labels.push(...Array.from(this.element.ownerDocument.querySelectorAll("label[for='".concat(this.element.id, "']")) || [])); 13538 } 13539 const label = findClosestElementFromNode(this.element, { 13540 matchingSelector: "label" 13541 }); 13542 if (label) { 13543 if ([this.element, null].includes(label.control)) { 13544 labels.push(label); 13545 } 13546 } 13547 return labels; 13548 } 13549 get form() { 13550 console.warn("This browser does not support the .form property for trix-editor elements."); 13551 return null; 13552 } 13553 get name() { 13554 console.warn("This browser does not support the .name property for trix-editor elements."); 13555 return null; 13556 } 13557 set name(value) { 13558 console.warn("This browser does not support the .name property for trix-editor elements."); 13559 } 13560 get disabled() { 13561 console.warn("This browser does not support the [disabled] attribute for trix-editor elements."); 13562 return false; 13563 } 13564 set disabled(value) { 13565 console.warn("This browser does not support the [disabled] attribute for trix-editor elements."); 13566 } 13567 get required() { 13568 console.warn("This browser does not support the [required] attribute for trix-editor elements."); 13569 return false; 13570 } 13571 set required(value) { 13572 console.warn("This browser does not support the [required] attribute for trix-editor elements."); 13573 } 13574 get validity() { 13575 console.warn("This browser does not support the validity property for trix-editor elements."); 13576 return null; 13577 } 13578 get validationMessage() { 13579 console.warn("This browser does not support the validationMessage property for trix-editor elements."); 13580 return ""; 13581 } 13582 get willValidate() { 13583 console.warn("This browser does not support the willValidate property for trix-editor elements."); 13584 return false; 13585 } 13586 formDisabledCallback(value) {} 13587 setFormValue(value) {} 13588 checkValidity() { 13589 console.warn("This browser does not support checkValidity() for trix-editor elements."); 13590 return true; 13591 } 13592 reportValidity() { 13593 console.warn("This browser does not support reportValidity() for trix-editor elements."); 13594 return true; 13595 } 13596 setCustomValidity(validationMessage) { 13597 console.warn("This browser does not support setCustomValidity(validationMessage) for trix-editor elements."); 13598 } 13599 } 13600 var _delegate = /*#__PURE__*/new WeakMap(); 13601 class TrixEditorElement extends HTMLElement { 13602 constructor() { 13603 super(); 13604 _classPrivateFieldInitSpec(this, _delegate, { 13605 writable: true, 13606 value: void 0 13607 }); 13608 this.willCreateInput = true; 13609 _classPrivateFieldSet(this, _delegate, this.constructor.formAssociated ? new ElementInternalsDelegate(this) : new LegacyDelegate(this)); 13610 } 13611 13612 // Properties 13613 13614 get trixId() { 13615 if (this.hasAttribute("trix-id")) { 13616 return this.getAttribute("trix-id"); 13617 } else { 13618 this.setAttribute("trix-id", ++id); 13619 return this.trixId; 13620 } 13621 } 13622 get labels() { 13623 return _classPrivateFieldGet(this, _delegate).labels; 13624 } 13625 get disabled() { 13626 const { 13627 inputElement 13628 } = this; 13629 if (inputElement) { 13630 return inputElement.disabled; 13631 } else { 13632 return _classPrivateFieldGet(this, _delegate).disabled; 13633 } 13634 } 13635 set disabled(value) { 13636 const { 13637 inputElement 13638 } = this; 13639 if (inputElement) { 13640 inputElement.disabled = value; 13641 } 13642 _classPrivateFieldGet(this, _delegate).disabled = value; 13643 } 13644 get required() { 13645 return _classPrivateFieldGet(this, _delegate).required; 13646 } 13647 set required(value) { 13648 _classPrivateFieldGet(this, _delegate).required = value; 13649 } 13650 get validity() { 13651 return _classPrivateFieldGet(this, _delegate).validity; 13652 } 13653 get validationMessage() { 13654 return _classPrivateFieldGet(this, _delegate).validationMessage; 13655 } 13656 get willValidate() { 13657 return _classPrivateFieldGet(this, _delegate).willValidate; 13658 } 13659 get type() { 13660 return this.localName; 13661 } 13662 get toolbarElement() { 13663 if (this.hasAttribute("toolbar")) { 13664 var _this$ownerDocument; 13665 return (_this$ownerDocument = this.ownerDocument) === null || _this$ownerDocument === void 0 ? void 0 : _this$ownerDocument.getElementById(this.getAttribute("toolbar")); 13666 } else if (this.parentNode) { 13667 const toolbarId = "trix-toolbar-".concat(this.trixId); 13668 this.setAttribute("toolbar", toolbarId); 13669 this.internalToolbar = makeElement("trix-toolbar", { 13670 id: toolbarId 13671 }); 13672 this.parentNode.insertBefore(this.internalToolbar, this); 13673 return this.internalToolbar; 13674 } else { 13675 return undefined; 13676 } 13677 } 13678 get form() { 13679 const { 13680 inputElement 13681 } = this; 13682 if (inputElement) { 13683 return inputElement.form; 13684 } else { 13685 return _classPrivateFieldGet(this, _delegate).form; 13686 } 13687 } 13688 get inputElement() { 13689 if (this.hasAttribute("input")) { 13690 var _this$ownerDocument2; 13691 return (_this$ownerDocument2 = this.ownerDocument) === null || _this$ownerDocument2 === void 0 ? void 0 : _this$ownerDocument2.getElementById(this.getAttribute("input")); 13692 } else { 13693 return undefined; 13694 } 13695 } 13696 get editor() { 13697 var _this$editorControlle; 13698 return (_this$editorControlle = this.editorController) === null || _this$editorControlle === void 0 ? void 0 : _this$editorControlle.editor; 13699 } 13700 get name() { 13701 const { 13702 inputElement 13703 } = this; 13704 if (inputElement) { 13705 return inputElement.name; 13706 } else { 13707 return _classPrivateFieldGet(this, _delegate).name; 13708 } 13709 } 13710 set name(value) { 13711 const { 13712 inputElement 13713 } = this; 13714 if (inputElement) { 13715 inputElement.name = value; 13716 } else { 13717 _classPrivateFieldGet(this, _delegate).name = value; 13718 } 13719 } 13720 get value() { 13721 const { 13722 inputElement 13723 } = this; 13724 if (inputElement) { 13725 return inputElement.value; 13726 } else { 13727 return _classPrivateFieldGet(this, _delegate).value; 13728 } 13729 } 13730 set value(defaultValue) { 13731 var _this$editor; 13732 this.defaultValue = defaultValue; 13733 (_this$editor = this.editor) === null || _this$editor === void 0 || _this$editor.loadHTML(this.defaultValue); 13734 } 13735 13736 // Element callbacks 13737 13738 attributeChangedCallback(name, oldValue, newValue) { 13739 if (name === "connected" && this.isConnected && oldValue != null && oldValue !== newValue) { 13740 requestAnimationFrame(() => this.reconnect()); 13741 } 13742 } 13743 13744 // Controller delegate methods 13745 13746 notify(message, data) { 13747 if (this.editorController) { 13748 return triggerEvent("trix-".concat(message), { 13749 onElement: this, 13750 attributes: data 13751 }); 13752 } 13753 } 13754 setFormValue(value) { 13755 const { 13756 inputElement 13757 } = this; 13758 if (inputElement) { 13759 inputElement.value = value; 13760 } 13761 _classPrivateFieldGet(this, _delegate).setFormValue(value); 13762 } 13763 13764 // Element lifecycle 13765 13766 connectedCallback() { 13767 if (!this.hasAttribute("data-trix-internal")) { 13768 makeEditable(this); 13769 addAccessibilityRole(this); 13770 if (!this.editorController) { 13771 triggerEvent("trix-before-initialize", { 13772 onElement: this 13773 }); 13774 this.defaultValue = this.inputElement ? this.inputElement.value : this.innerHTML; 13775 if (!this.hasAttribute("input") && this.parentNode && this.willCreateInput) { 13776 const inputId = "trix-input-".concat(this.trixId); 13777 this.setAttribute("input", inputId); 13778 const element = makeElement("input", { 13779 type: "hidden", 13780 id: inputId 13781 }); 13782 this.parentNode.insertBefore(element, this.nextElementSibling); 13783 } 13784 this.editorController = new EditorController({ 13785 editorElement: this, 13786 html: this.defaultValue 13787 }); 13788 requestAnimationFrame(() => triggerEvent("trix-initialize", { 13789 onElement: this 13790 })); 13791 } 13792 this.editorController.registerSelectionManager(); 13793 _classPrivateFieldGet(this, _delegate).connectedCallback(); 13794 this.toggleAttribute("connected", true); 13795 autofocus(this); 13796 } 13797 } 13798 disconnectedCallback() { 13799 var _this$editorControlle2; 13800 (_this$editorControlle2 = this.editorController) === null || _this$editorControlle2 === void 0 || _this$editorControlle2.unregisterSelectionManager(); 13801 _classPrivateFieldGet(this, _delegate).disconnectedCallback(); 13802 this.toggleAttribute("connected", false); 13803 } 13804 reconnect() { 13805 this.removeInternalToolbar(); 13806 this.disconnectedCallback(); 13807 this.connectedCallback(); 13808 } 13809 removeInternalToolbar() { 13810 var _this$internalToolbar; 13811 (_this$internalToolbar = this.internalToolbar) === null || _this$internalToolbar === void 0 || _this$internalToolbar.remove(); 13812 this.internalToolbar = null; 13813 } 13814 13815 // Form support 13816 13817 checkValidity() { 13818 return _classPrivateFieldGet(this, _delegate).checkValidity(); 13819 } 13820 reportValidity() { 13821 return _classPrivateFieldGet(this, _delegate).reportValidity(); 13822 } 13823 setCustomValidity(validationMessage) { 13824 _classPrivateFieldGet(this, _delegate).setCustomValidity(validationMessage); 13825 } 13826 formDisabledCallback(disabled) { 13827 const { 13828 inputElement 13829 } = this; 13830 if (inputElement) { 13831 inputElement.disabled = disabled; 13832 } 13833 this.toggleAttribute("contenteditable", !disabled); 13834 _classPrivateFieldGet(this, _delegate).formDisabledCallback(disabled); 13835 } 13836 formResetCallback() { 13837 this.reset(); 13838 } 13839 reset() { 13840 this.value = this.defaultValue; 13841 } 13842 } 13843 _defineProperty(TrixEditorElement, "formAssociated", "ElementInternals" in window); 13844 _defineProperty(TrixEditorElement, "observedAttributes", ["connected"]); 13845 13846 var elements = /*#__PURE__*/Object.freeze({ 13847 __proto__: null, 13848 TrixEditorElement: TrixEditorElement, 13849 TrixToolbarElement: TrixToolbarElement 13850 }); 13851 13852 var filters = /*#__PURE__*/Object.freeze({ 13853 __proto__: null, 13854 Filter: Filter, 13855 attachmentGalleryFilter: attachmentGalleryFilter 13856 }); 13857 13858 const Trix = { 13859 VERSION: version, 13860 config, 13861 core, 13862 models, 13863 views, 13864 controllers, 13865 observers, 13866 operations, 13867 elements, 13868 filters 13869 }; 13870 13871 // Expose models under the Trix constant for compatibility with v1 13872 Object.assign(Trix, models); 13873 function start() { 13874 if (!customElements.get("trix-toolbar")) { 13875 customElements.define("trix-toolbar", TrixToolbarElement); 13876 } 13877 if (!customElements.get("trix-editor")) { 13878 customElements.define("trix-editor", TrixEditorElement); 13879 } 13880 } 13881 window.Trix = Trix; 13882 setTimeout(start, 0); 13883 13884 return Trix; 13885 13886}));
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.