From a276a264be6915cd8e4317c36b48cf226a7a61ac Mon Sep 17 00:00:00 2001 From: Alberto Fernandez-Capel Date: Mon, 3 Jan 2022 15:32:31 +0000 Subject: [PATCH] v2.0.0-alpha.0 --- dist/inspector.js | 3632 ++++++ dist/inspector.js.map | 1 + dist/test.js | 24894 ++++++++++++++++++++++++++++++++++++++++ dist/test.js.map | 1 + dist/trix.js | 12746 ++++++++++++++++++++ dist/trix.min.js | 2 + dist/trix.min.js.map | 1 + dist/trix.umd.js | 12754 ++++++++++++++++++++ package.json | 2 +- 9 files changed, 54032 insertions(+), 1 deletion(-) create mode 100644 dist/inspector.js create mode 100644 dist/inspector.js.map create mode 100644 dist/test.js create mode 100644 dist/test.js.map create mode 100644 dist/trix.js create mode 100644 dist/trix.min.js create mode 100644 dist/trix.min.js.map create mode 100644 dist/trix.umd.js diff --git a/dist/inspector.js b/dist/inspector.js new file mode 100644 index 00000000..9ce41867 --- /dev/null +++ b/dist/inspector.js @@ -0,0 +1,3632 @@ +/* +Trix 2.0.0-alpha +Copyright © 2022 Basecamp, LLC + */ +/* eslint-disable + id-length, +*/ +const arraysAreEqual = function () { + let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + + if (a.length !== b.length) { + return false; + } + + for (let index = 0; index < a.length; index++) { + const value = a[index]; + + if (value !== b[index]) { + return false; + } + } + + return true; +}; +const arrayStartsWith = function () { + let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + return arraysAreEqual(a.slice(0, b.length), b); +}; +const spliceArray = function (array) { + const result = array.slice(0); + + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + result.splice(...args); + return result; +}; +const summarizeArrayChange = function () { + let oldArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let newArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + const added = []; + const removed = []; + const existingValues = new Set(); + oldArray.forEach(value => { + existingValues.add(value); + }); + const currentValues = new Set(); + newArray.forEach(value => { + currentValues.add(value); + + if (!existingValues.has(value)) { + added.push(value); + } + }); + oldArray.forEach(value => { + if (!currentValues.has(value)) { + removed.push(value); + } + }); + return { + added, + removed + }; +}; + +const attachmentSelector = "[data-trix-attachment]"; +const attachments = { + preview: { + presentation: "gallery", + caption: { + name: true, + size: true + } + }, + file: { + caption: { + size: true + } + } +}; + +const attributes = { + default: { + tagName: "div", + parse: false + }, + quote: { + tagName: "blockquote", + nestable: true + }, + heading1: { + tagName: "h1", + terminal: true, + breakOnReturn: true, + group: false + }, + code: { + tagName: "pre", + terminal: true, + text: { + plaintext: true + } + }, + bulletList: { + tagName: "ul", + parse: false + }, + bullet: { + tagName: "li", + listAttribute: "bulletList", + group: false, + nestable: true, + + test(element) { + return tagName$1(element.parentNode) === attributes[this.listAttribute].tagName; + } + + }, + numberList: { + tagName: "ol", + parse: false + }, + number: { + tagName: "li", + listAttribute: "numberList", + group: false, + nestable: true, + + test(element) { + return tagName$1(element.parentNode) === attributes[this.listAttribute].tagName; + } + + }, + attachmentGallery: { + tagName: "div", + exclusive: true, + terminal: true, + parse: false, + group: false + } +}; + +const tagName$1 = element => { + var _element$tagName; + + return element === null || element === void 0 ? void 0 : (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase(); +}; + +var browser = { + // Android emits composition events when moving the cursor through existing text + // Introduced in Chrome 65: https://bugs.chromium.org/p/chromium/issues/detail?id=764439#c9 + composesExistingText: /Android.*Chrome/.test(navigator.userAgent), + // IE 11 activates resizing handles on editable elements that have "layout" + forcesObjectResizing: /Trident.*rv:11/.test(navigator.userAgent), + // https://www.w3.org/TR/input-events-1/ + https://www.w3.org/TR/input-events-2/ + supportsInputEvents: function () { + if (typeof InputEvent === "undefined") { + return false; + } + + for (const property of ["data", "getTargetRanges", "inputType"]) { + if (!(property in InputEvent.prototype)) { + return false; + } + } + + return true; + }() +}; + +var css = { + attachment: "attachment", + attachmentCaption: "attachment__caption", + attachmentCaptionEditor: "attachment__caption-editor", + attachmentMetadata: "attachment__metadata", + attachmentMetadataContainer: "attachment__metadata-container", + attachmentName: "attachment__name", + attachmentProgress: "attachment__progress", + attachmentSize: "attachment__size", + attachmentToolbar: "attachment__toolbar", + attachmentGallery: "attachment-gallery" +}; + +var lang = { + attachFiles: "Attach Files", + bold: "Bold", + bullets: "Bullets", + byte: "Byte", + bytes: "Bytes", + captionPlaceholder: "Add a caption…", + code: "Code", + heading1: "Heading", + indent: "Increase Level", + italic: "Italic", + link: "Link", + numbers: "Numbers", + outdent: "Decrease Level", + quote: "Quote", + redo: "Redo", + remove: "Remove", + strike: "Strikethrough", + undo: "Undo", + unlink: "Unlink", + url: "URL", + urlPlaceholder: "Enter a URL…", + GB: "GB", + KB: "KB", + MB: "MB", + PB: "PB", + TB: "TB" +}; + +/* eslint-disable + no-case-declarations, +*/ +const sizes = [lang.bytes, lang.KB, lang.MB, lang.GB, lang.TB, lang.PB]; +var fileSize = { + prefix: "IEC", + precision: 2, + + formatter(number) { + switch (number) { + case 0: + return "0 ".concat(lang.bytes); + + case 1: + return "1 ".concat(lang.byte); + + default: + let base; + + if (this.prefix === "SI") { + base = 1000; + } else if (this.prefix === "IEC") { + base = 1024; + } + + const exp = Math.floor(Math.log(number) / Math.log(base)); + const humanSize = number / Math.pow(base, exp); + const string = humanSize.toFixed(this.precision); + const withoutInsignificantZeros = string.replace(/0*$/, "").replace(/\.$/, ""); + return "".concat(withoutInsignificantZeros, " ").concat(sizes[exp]); + } + } + +}; + +const input = { + level2Enabled: true, + + getLevel() { + if (this.level2Enabled && browser.supportsInputEvents) { + return 2; + } else { + return 0; + } + } + +}; + +var keyNames = { + 8: "backspace", + 9: "tab", + 13: "return", + 27: "escape", + 37: "left", + 39: "right", + 46: "delete", + 68: "d", + 72: "h", + 79: "o" +}; + +var textAttributes = { + bold: { + tagName: "strong", + inheritable: true, + + parser(element) { + const style = window.getComputedStyle(element); + return style.fontWeight === "bold" || style.fontWeight >= 600; + } + + }, + italic: { + tagName: "em", + inheritable: true, + + parser(element) { + const style = window.getComputedStyle(element); + return style.fontStyle === "italic"; + } + + }, + href: { + groupTagName: "a", + + parser(element) { + const matchingSelector = "a:not(".concat(attachmentSelector, ")"); + const link = element.closest(matchingSelector); + + if (link) { + return link.getAttribute("href"); + } + } + + }, + strike: { + tagName: "del", + inheritable: true + }, + frozen: { + style: { + backgroundColor: "highlight" + } + } +}; + +var toolbar = { + getDefaultHTML() { + return "
\n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n\n \n \n \n\n \n\n \n \n \n \n
\n\n
\n
\n \n
\n
"); + } + +}; + +const undoInterval = 5000; + +const config = { + attachments, + blockAttributes: attributes, + browser, + css, + fileSize, + input, + keyNames, + lang, + textAttributes, + toolbar, + undoInterval +}; + +const ZERO_WIDTH_SPACE = "\uFEFF"; +const NON_BREAKING_SPACE = "\u00A0"; +const OBJECT_REPLACEMENT_CHARACTER = "\uFFFC"; + +const extend = function (properties) { + for (const key in properties) { + const value = properties[key]; + this[key] = value; + } + + return this; +}; + +const html = document.documentElement; +const match = html.matches; +const handleEvent = function (eventName) { + let { + onElement, + matchingSelector, + withCallback, + inPhase, + preventDefault, + times + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const element = onElement ? onElement : html; + const selector = matchingSelector; + const useCapture = inPhase === "capturing"; + + const handler = function (event) { + if (times != null && --times === 0) { + handler.destroy(); + } + + const target = findClosestElementFromNode(event.target, { + matchingSelector: selector + }); + + if (target != null) { + withCallback === null || withCallback === void 0 ? void 0 : withCallback.call(target, event, target); + + if (preventDefault) { + event.preventDefault(); + } + } + }; + + handler.destroy = () => element.removeEventListener(eventName, handler, useCapture); + + element.addEventListener(eventName, handler, useCapture); + return handler; +}; +const handleEventOnce = function (eventName) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + options.times = 1; + return handleEvent(eventName, options); +}; +const triggerEvent = function (eventName) { + let { + onElement, + bubbles, + cancelable, + attributes + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const element = onElement != null ? onElement : html; + bubbles = bubbles !== false; + cancelable = cancelable !== false; + const event = document.createEvent("Events"); + event.initEvent(eventName, bubbles, cancelable); + + if (attributes != null) { + extend.call(event, attributes); + } + + return element.dispatchEvent(event); +}; +const elementMatchesSelector = function (element, selector) { + if ((element === null || element === void 0 ? void 0 : element.nodeType) === 1) { + return match.call(element, selector); + } +}; +const findClosestElementFromNode = function (node) { + let { + matchingSelector, + untilNode + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + while (node && node.nodeType !== Node.ELEMENT_NODE) { + node = node.parentNode; + } + + if (node == null) { + return; + } + + if (matchingSelector != null) { + if (node.closest && untilNode == null) { + return node.closest(matchingSelector); + } else { + while (node && node !== untilNode) { + if (elementMatchesSelector(node, matchingSelector)) { + return node; + } + + node = node.parentNode; + } + } + } else { + return node; + } +}; +const findInnerElement = function (element) { + while ((_element = element) !== null && _element !== void 0 && _element.firstElementChild) { + var _element; + + element = element.firstElementChild; + } + + return element; +}; +const innerElementIsActive = element => document.activeElement !== element && elementContainsNode(element, document.activeElement); +const elementContainsNode = function (element, node) { + if (!element || !node) { + return; + } + + while (node) { + if (node === element) { + return true; + } + + node = node.parentNode; + } +}; +const findNodeFromContainerAndOffset = function (container, offset) { + if (!container) { + return; + } + + if (container.nodeType === Node.TEXT_NODE) { + return container; + } else if (offset === 0) { + return container.firstChild != null ? container.firstChild : container; + } else { + return container.childNodes.item(offset - 1); + } +}; +const findElementFromContainerAndOffset = function (container, offset) { + const node = findNodeFromContainerAndOffset(container, offset); + return findClosestElementFromNode(node); +}; +const findChildIndexOfNode = function (node) { + var _node; + + if (!((_node = node) !== null && _node !== void 0 && _node.parentNode)) { + return; + } + + let childIndex = 0; + node = node.previousSibling; + + while (node) { + childIndex++; + node = node.previousSibling; + } + + return childIndex; +}; +const removeNode = node => { + var _node$parentNode; + + return node === null || node === void 0 ? void 0 : (_node$parentNode = node.parentNode) === null || _node$parentNode === void 0 ? void 0 : _node$parentNode.removeChild(node); +}; +const walkTree = function (tree) { + let { + onlyNodesOfType, + usingFilter, + expandEntityReferences + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + const whatToShow = (() => { + switch (onlyNodesOfType) { + case "element": + return NodeFilter.SHOW_ELEMENT; + + case "text": + return NodeFilter.SHOW_TEXT; + + case "comment": + return NodeFilter.SHOW_COMMENT; + + default: + return NodeFilter.SHOW_ALL; + } + })(); + + return document.createTreeWalker(tree, whatToShow, usingFilter != null ? usingFilter : null, expandEntityReferences === true); +}; +const tagName = element => { + var _element$tagName; + + return element === null || element === void 0 ? void 0 : (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase(); +}; +const makeElement = function (tag) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let key, value; + + if (typeof tag === "object") { + options = tag; + tag = options.tagName; + } else { + options = { + attributes: options + }; + } + + const element = document.createElement(tag); + + if (options.editable != null) { + if (options.attributes == null) { + options.attributes = {}; + } + + options.attributes.contenteditable = options.editable; + } + + if (options.attributes) { + for (key in options.attributes) { + value = options.attributes[key]; + element.setAttribute(key, value); + } + } + + if (options.style) { + for (key in options.style) { + value = options.style[key]; + element.style[key] = value; + } + } + + if (options.data) { + for (key in options.data) { + value = options.data[key]; + element.dataset[key] = value; + } + } + + if (options.className) { + options.className.split(" ").forEach(className => { + element.classList.add(className); + }); + } + + if (options.textContent) { + element.textContent = options.textContent; + } + + if (options.childNodes) { + [].concat(options.childNodes).forEach(childNode => { + element.appendChild(childNode); + }); + } + + return element; +}; +let blockTagNames = undefined; +const getBlockTagNames = function () { + if (blockTagNames != null) { + return blockTagNames; + } + + blockTagNames = []; + + for (const key in config.blockAttributes) { + const attributes = config.blockAttributes[key]; + + if (attributes.tagName) { + blockTagNames.push(attributes.tagName); + } + } + + return blockTagNames; +}; +const nodeIsBlockContainer = node => nodeIsBlockStartComment(node === null || node === void 0 ? void 0 : node.firstChild); +const nodeProbablyIsBlockContainer = function (node) { + return getBlockTagNames().includes(tagName(node)) && !getBlockTagNames().includes(tagName(node.firstChild)); +}; +const nodeIsBlockStart = function (node) { + let { + strict + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + strict: true + }; + + if (strict) { + return nodeIsBlockStartComment(node); + } else { + return nodeIsBlockStartComment(node) || !nodeIsBlockStartComment(node.firstChild) && nodeProbablyIsBlockContainer(node); + } +}; +const nodeIsBlockStartComment = node => nodeIsCommentNode(node) && (node === null || node === void 0 ? void 0 : node.data) === "block"; +const nodeIsCommentNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.COMMENT_NODE; +const nodeIsCursorTarget = function (node) { + let { + name + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (!node) { + return; + } + + if (nodeIsTextNode(node)) { + if (node.data === ZERO_WIDTH_SPACE) { + if (name) { + return node.parentNode.dataset.trixCursorTarget === name; + } else { + return true; + } + } + } else { + return nodeIsCursorTarget(node.firstChild); + } +}; +const nodeIsAttachmentElement = node => elementMatchesSelector(node, attachmentSelector); +const nodeIsEmptyTextNode = node => nodeIsTextNode(node) && (node === null || node === void 0 ? void 0 : node.data) === ""; +const nodeIsTextNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.TEXT_NODE; + +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]/; +const getDirection = function () { + const input = makeElement("input", { + dir: "auto", + name: "x", + dirName: "x.dir" + }); + const form = makeElement("form"); + form.appendChild(input); + + const supportsDirName = function () { + try { + return new FormData(form).has(input.dirName); + } catch (error) { + return false; + } + }(); + + const supportsDirSelector = function () { + try { + return input.matches(":dir(ltr),:dir(rtl)"); + } catch (error) { + return false; + } + }(); + + if (supportsDirName) { + return function (string) { + input.value = string; + return new FormData(form).get(input.dirName); + }; + } else if (supportsDirSelector) { + return function (string) { + input.value = string; + + if (input.matches(":dir(rtl)")) { + return "rtl"; + } else { + return "ltr"; + } + }; + } else { + return function (string) { + const char = string.trim().charAt(0); + + if (RTL_PATTERN.test(char)) { + return "rtl"; + } else { + return "ltr"; + } + }; + } +}(); + +let allAttributeNames = null; +let blockAttributeNames = null; +let textAttributeNames = null; +let listAttributeNames = null; +const getAllAttributeNames = () => { + if (!allAttributeNames) { + allAttributeNames = getTextAttributeNames().concat(getBlockAttributeNames()); + } + + return allAttributeNames; +}; +const getBlockConfig = attributeName => config.blockAttributes[attributeName]; +const getBlockAttributeNames = () => { + if (!blockAttributeNames) { + blockAttributeNames = Object.keys(config.blockAttributes); + } + + return blockAttributeNames; +}; +const getTextConfig = attributeName => config.textAttributes[attributeName]; +const getTextAttributeNames = () => { + if (!textAttributeNames) { + textAttributeNames = Object.keys(config.textAttributes); + } + + return textAttributeNames; +}; +const getListAttributeNames = () => { + if (!listAttributeNames) { + listAttributeNames = []; + + for (const key in config.blockAttributes) { + const { + listAttribute + } = config.blockAttributes[key]; + + if (listAttribute != null) { + listAttributeNames.push(listAttribute); + } + } + } + + return listAttributeNames; +}; + +/* eslint-disable +*/ +const installDefaultCSSForTagName = function (tagName, defaultCSS) { + const styleElement = insertStyleElementForTagName(tagName); + styleElement.textContent = defaultCSS.replace(/%t/g, tagName); +}; + +const insertStyleElementForTagName = function (tagName) { + const element = document.createElement("style"); + element.setAttribute("type", "text/css"); + element.setAttribute("data-tag-name", tagName.toLowerCase()); + const nonce = getCSPNonce(); + + if (nonce) { + element.setAttribute("nonce", nonce); + } + + document.head.insertBefore(element, document.head.firstChild); + return element; +}; + +const getCSPNonce = function () { + const element = getMetaElement("trix-csp-nonce") || getMetaElement("csp-nonce"); + + if (element) { + return element.getAttribute("content"); + } +}; + +const getMetaElement = name => document.head.querySelector("meta[name=".concat(name, "]")); + +const testTransferData = { + "application/x-trix-feature-detection": "test" +}; +const dataTransferIsPlainText = function (dataTransfer) { + const text = dataTransfer.getData("text/plain"); + const html = dataTransfer.getData("text/html"); + + if (text && html) { + const { + body + } = new DOMParser().parseFromString(html, "text/html"); + + if (body.textContent === text) { + return !body.querySelector("*"); + } + } else { + return text === null || text === void 0 ? void 0 : text.length; + } +}; +const dataTransferIsWritable = function (dataTransfer) { + if (!(dataTransfer !== null && dataTransfer !== void 0 && dataTransfer.setData)) return false; + + for (const key in testTransferData) { + const value = testTransferData[key]; + + try { + dataTransfer.setData(key, value); + if (!dataTransfer.getData(key) === value) return false; + } catch (error) { + return false; + } + } + + return true; +}; +const keyEventIsKeyboardCommand = function () { + if (/Mac|^iP/.test(navigator.platform)) { + return event => event.metaKey; + } else { + return event => event.ctrlKey; + } +}(); + +const defer = fn => setTimeout(fn, 1); + +/* eslint-disable + id-length, +*/ +const copyObject = function () { + let object = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + const result = {}; + + for (const key in object) { + const value = object[key]; + result[key] = value; + } + + return result; +}; +const objectsAreEqual = function () { + let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (Object.keys(a).length !== Object.keys(b).length) { + return false; + } + + for (const key in a) { + const value = a[key]; + + if (value !== b[key]) { + return false; + } + } + + return true; +}; + +const normalizeRange = function (range) { + if (range == null) return; + + if (!Array.isArray(range)) { + range = [range, range]; + } + + return [copyValue(range[0]), copyValue(range[1] != null ? range[1] : range[0])]; +}; +const rangeIsCollapsed = function (range) { + if (range == null) return; + const [start, end] = normalizeRange(range); + return rangeValuesAreEqual(start, end); +}; +const rangesAreEqual = function (leftRange, rightRange) { + if (leftRange == null || rightRange == null) return; + const [leftStart, leftEnd] = normalizeRange(leftRange); + const [rightStart, rightEnd] = normalizeRange(rightRange); + return rangeValuesAreEqual(leftStart, rightStart) && rangeValuesAreEqual(leftEnd, rightEnd); +}; + +const copyValue = function (value) { + if (typeof value === "number") { + return value; + } else { + return copyObject(value); + } +}; + +const rangeValuesAreEqual = function (left, right) { + if (typeof left === "number") { + return left === right; + } else { + return objectsAreEqual(left, right); + } +}; + +class BasicObject { + static proxyMethod(expression) { + const { + name, + toMethod, + toProperty, + optional + } = parseProxyMethodExpression(expression); + + this.prototype[name] = function () { + let subject; + let object; + + if (toMethod) { + if (optional) { + var _this$toMethod; + + object = (_this$toMethod = this[toMethod]) === null || _this$toMethod === void 0 ? void 0 : _this$toMethod.call(this); + } else { + object = this[toMethod](); + } + } else if (toProperty) { + object = this[toProperty]; + } + + if (optional) { + var _object; + + subject = (_object = object) === null || _object === void 0 ? void 0 : _object[name]; + + if (subject) { + return apply.call(subject, object, arguments); + } + } else { + subject = object[name]; + return apply.call(subject, object, arguments); + } + }; + } + +} + +const parseProxyMethodExpression = function (expression) { + const match = expression.match(proxyMethodExpressionPattern); + + if (!match) { + throw new Error("can't parse @proxyMethod expression: ".concat(expression)); + } + + const args = { + name: match[4] + }; + + if (match[2] != null) { + args.toMethod = match[1]; + } else { + args.toProperty = match[1]; + } + + if (match[3] != null) { + args.optional = true; + } + + return args; +}; + +const { + apply +} = Function.prototype; +const proxyMethodExpressionPattern = new RegExp("\ +^\ +(.+?)\ +(\\(\\))?\ +(\\?)?\ +\\.\ +(.+?)\ +$\ +"); + +/* eslint-disable + id-length, +*/ +class SelectionChangeObserver extends BasicObject { + constructor() { + super(...arguments); + this.update = this.update.bind(this); + this.run = this.run.bind(this); + this.selectionManagers = []; + } + + start() { + if (!this.started) { + this.started = true; + + if ("onselectionchange" in document) { + return document.addEventListener("selectionchange", this.update, true); + } else { + return this.run(); + } + } + } + + stop() { + if (this.started) { + this.started = false; + return document.removeEventListener("selectionchange", this.update, true); + } + } + + registerSelectionManager(selectionManager) { + if (!this.selectionManagers.includes(selectionManager)) { + this.selectionManagers.push(selectionManager); + return this.start(); + } + } + + unregisterSelectionManager(selectionManager) { + this.selectionManagers = this.selectionManagers.filter(s => s !== selectionManager); + + if (this.selectionManagers.length === 0) { + return this.stop(); + } + } + + notifySelectionManagersOfSelectionChange() { + return this.selectionManagers.map(selectionManager => selectionManager.selectionDidChange()); + } + + update() { + const domRange = getDOMRange(); + + if (!domRangesAreEqual(domRange, this.domRange)) { + this.domRange = domRange; + return this.notifySelectionManagersOfSelectionChange(); + } + } + + reset() { + this.domRange = null; + return this.update(); + } // Private + + + run() { + if (this.started) { + this.update(); + return requestAnimationFrame(this.run); + } + } + +} + +const domRangesAreEqual = (left, right) => (left === null || left === void 0 ? void 0 : left.startContainer) === (right === null || right === void 0 ? void 0 : right.startContainer) && (left === null || left === void 0 ? void 0 : left.startOffset) === (right === null || right === void 0 ? void 0 : right.startOffset) && (left === null || left === void 0 ? void 0 : left.endContainer) === (right === null || right === void 0 ? void 0 : right.endContainer) && (left === null || left === void 0 ? void 0 : left.endOffset) === (right === null || right === void 0 ? void 0 : right.endOffset); + +const selectionChangeObserver = new SelectionChangeObserver(); +const getDOMSelection = function () { + const selection = window.getSelection(); + + if (selection.rangeCount > 0) { + return selection; + } +}; +const getDOMRange = function () { + var _getDOMSelection; + + const domRange = (_getDOMSelection = getDOMSelection()) === null || _getDOMSelection === void 0 ? void 0 : _getDOMSelection.getRangeAt(0); + + if (domRange) { + if (!domRangeIsPrivate(domRange)) { + return domRange; + } + } +}; +const setDOMRange = function (domRange) { + const selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(domRange); + return selectionChangeObserver.update(); +}; // In Firefox, clicking certain elements changes the selection to a +// private element used to draw its UI. Attempting to access properties of those +// elements throws an error. +// https://bugzilla.mozilla.org/show_bug.cgi?id=208427 + +const domRangeIsPrivate = domRange => nodeIsPrivate(domRange.startContainer) || nodeIsPrivate(domRange.endContainer); + +const nodeIsPrivate = node => !Object.getPrototypeOf(node); + +var _Array$from, _$codePointAt, _, _String$fromCodePoint; +class UTF16String extends BasicObject { + static box() { + let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + + if (value instanceof this) { + return value; + } else { + return this.fromUCS2String(value === null || value === void 0 ? void 0 : value.toString()); + } + } + + static fromUCS2String(ucs2String) { + return new this(ucs2String, ucs2decode(ucs2String)); + } + + static fromCodepoints(codepoints) { + return new this(ucs2encode(codepoints), codepoints); + } + + constructor(ucs2String, codepoints) { + super(...arguments); + this.ucs2String = ucs2String; + this.codepoints = codepoints; + this.length = this.codepoints.length; + this.ucs2Length = this.ucs2String.length; + } + + offsetToUCS2Offset(offset) { + return ucs2encode(this.codepoints.slice(0, Math.max(0, offset))).length; + } + + offsetFromUCS2Offset(ucs2Offset) { + return ucs2decode(this.ucs2String.slice(0, Math.max(0, ucs2Offset))).length; + } + + slice() { + return this.constructor.fromCodepoints(this.codepoints.slice(...arguments)); + } + + charAt(offset) { + return this.slice(offset, offset + 1); + } + + isEqualTo(value) { + return this.constructor.box(value).ucs2String === this.ucs2String; + } + + toJSON() { + return this.ucs2String; + } + + getCacheKey() { + return this.ucs2String; + } + + toString() { + return this.ucs2String; + } + +} +const hasArrayFrom = ((_Array$from = Array.from) === null || _Array$from === void 0 ? void 0 : _Array$from.call(Array, "\ud83d\udc7c").length) === 1; +const hasStringCodePointAt = ((_$codePointAt = (_ = " ").codePointAt) === null || _$codePointAt === void 0 ? void 0 : _$codePointAt.call(_, 0)) != null; +const hasStringFromCodePoint = ((_String$fromCodePoint = String.fromCodePoint) === null || _String$fromCodePoint === void 0 ? void 0 : _String$fromCodePoint.call(String, 32, 128124)) === " \ud83d\udc7c"; // UCS-2 conversion helpers ported from Mathias Bynens' Punycode.js: +// https://github.com/bestiejs/punycode.js#punycodeucs2 + +let ucs2decode, ucs2encode; // Creates an array containing the numeric code points of each Unicode +// character in the string. While JavaScript uses UCS-2 internally, +// this function will convert a pair of surrogate halves (each of which +// UCS-2 exposes as separate characters) into a single code point, +// matching UTF-16. + +if (hasArrayFrom && hasStringCodePointAt) { + ucs2decode = string => Array.from(string).map(char => char.codePointAt(0)); +} else { + ucs2decode = function (string) { + const output = []; + let counter = 0; + const { + length + } = string; + + while (counter < length) { + let value = string.charCodeAt(counter++); + + if (0xd800 <= value && value <= 0xdbff && counter < length) { + // high surrogate, and there is a next character + const extra = string.charCodeAt(counter++); + + if ((extra & 0xfc00) === 0xdc00) { + // low surrogate + value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; + } else { + // unmatched surrogate; only append this code unit, in case the + // next code unit is the high surrogate of a surrogate pair + counter--; + } + } + + output.push(value); + } + + return output; + }; +} // Creates a string based on an array of numeric code points. + + +if (hasStringFromCodePoint) { + ucs2encode = array => String.fromCodePoint(...Array.from(array || [])); +} else { + ucs2encode = function (array) { + const characters = (() => { + const result = []; + Array.from(array).forEach(value => { + let output = ""; + + if (value > 0xffff) { + value -= 0x10000; + output += String.fromCharCode(value >>> 10 & 0x3ff | 0xd800); + value = 0xdc00 | value & 0x3ff; + } + + result.push(output + String.fromCharCode(value)); + }); + return result; + })(); + + return characters.join(""); + }; +} + +/* eslint-disable + id-length, + no-useless-escape, +*/ +const normalizeSpaces = string => string.replace(new RegExp("".concat(ZERO_WIDTH_SPACE), "g"), "").replace(new RegExp("".concat(NON_BREAKING_SPACE), "g"), " "); +const normalizeNewlines = string => string.replace(/\r\n/g, "\n"); +const breakableWhitespacePattern = new RegExp("[^\\S".concat(NON_BREAKING_SPACE, "]")); +const squishBreakableWhitespace = string => string // Replace all breakable whitespace characters with a space +.replace(new RegExp("".concat(breakableWhitespacePattern.source), "g"), " ") // Replace two or more spaces with a single space +.replace(/\ {2,}/g, " "); +const summarizeStringChange = function (oldString, newString) { + let added, removed; + oldString = UTF16String.box(oldString); + newString = UTF16String.box(newString); + + if (newString.length < oldString.length) { + [removed, added] = utf16StringDifferences(oldString, newString); + } else { + [added, removed] = utf16StringDifferences(newString, oldString); + } + + return { + added, + removed + }; +}; + +const utf16StringDifferences = function (a, b) { + if (a.isEqualTo(b)) { + return ["", ""]; + } + + const diffA = utf16StringDifference(a, b); + const { + length + } = diffA.utf16String; + let diffB; + + if (length) { + const { + offset + } = diffA; + const codepoints = a.codepoints.slice(0, offset).concat(a.codepoints.slice(offset + length)); + diffB = utf16StringDifference(b, UTF16String.fromCodepoints(codepoints)); + } else { + diffB = utf16StringDifference(b, a); + } + + return [diffA.utf16String.toString(), diffB.utf16String.toString()]; +}; + +const utf16StringDifference = function (a, b) { + let leftIndex = 0; + let rightIndexA = a.length; + let rightIndexB = b.length; + + while (leftIndex < rightIndexA && a.charAt(leftIndex).isEqualTo(b.charAt(leftIndex))) { + leftIndex++; + } + + while (rightIndexA > leftIndex + 1 && a.charAt(rightIndexA - 1).isEqualTo(b.charAt(rightIndexB - 1))) { + rightIndexA--; + rightIndexB--; + } + + return { + utf16String: a.slice(leftIndex, rightIndexA), + offset: leftIndex + }; +}; + +/* eslint-disable + id-length, +*/ +installDefaultCSSForTagName("trix-inspector", "%t {\n display: block;\n}\n\n%t {\n position: fixed;\n background: #fff;\n border: 1px solid #444;\n border-radius: 5px;\n padding: 10px;\n font-family: sans-serif;\n font-size: 12px;\n overflow: auto;\n word-wrap: break-word;\n}\n\n%t details {\n margin-bottom: 10px;\n}\n\n%t summary:focus {\n outline: none;\n}\n\n%t details .panel {\n padding: 10px;\n}\n\n%t .performance .metrics {\n margin: 0 0 5px 5px;\n}\n\n%t .selection .characters {\n margin-top: 10px;\n}\n\n%t .selection .character {\n display: inline-block;\n font-size: 8px;\n font-family: courier, monospace;\n line-height: 10px;\n vertical-align: middle;\n text-align: center;\n width: 10px;\n height: 10px;\n margin: 0 1px 1px 0;\n border: 1px solid #333;\n border-radius: 1px;\n background: #676666;\n color: #fff;\n}\n\n%t .selection .character.selected {\n background: yellow;\n color: #000;\n}"); +class TrixInspector extends HTMLElement { + connectedCallback() { + this.editorElement = document.querySelector("trix-editor[trix-id='".concat(this.dataset.trixId, "']")); + this.views = this.createViews(); + this.views.forEach(view => { + view.render(); + this.appendChild(view.element); + }); + this.reposition(); + this.resizeHandler = this.reposition.bind(this); + addEventListener("resize", this.resizeHandler); + } + + disconnectedCallback() { + removeEventListener("resize", this.resizeHandler); + } + + createViews() { + const views = Trix.Inspector.views.map(View => new View(this.editorElement)); + return views.sort((a, b) => a.title.toLowerCase() > b.title.toLowerCase()); + } + + reposition() { + const { + top, + right + } = this.editorElement.getBoundingClientRect(); + this.style.top = "".concat(top, "px"); + this.style.left = "".concat(right + 10, "px"); + this.style.maxWidth = "".concat(window.innerWidth - right - 40, "px"); + this.style.maxHeight = "".concat(window.innerHeight - top - 30, "px"); + } + +} +window.customElements.define("trix-inspector", TrixInspector); + +window.Trix.Inspector = { + views: [], + + registerView(constructor) { + return this.views.push(constructor); + }, + + install(editorElement) { + this.editorElement = editorElement; + const element = document.createElement("trix-inspector"); + element.dataset.trixId = this.editorElement.trixId; + return document.body.appendChild(element); + } + +}; + +if (!window.JST) { + window.JST = {}; +} + +window.JST["trix/inspector/templates/debug"] = function () { + return "

\n \n

\n\n

\n \n

\n\n

\n \n

"); +}; + +if (!window.JST) { + window.JST = {}; +} + +window.JST["trix/inspector/templates/document"] = function () { + const details = this.document.getBlocks().map((block, index) => { + const { + text + } = block; + const pieces = text.pieceList.toArray(); + return "
\n \n Block ".concat(block.id, ", Index: ").concat(index, "\n \n
\n Attributes: ").concat(JSON.stringify(block.attributes), "\n
\n\n
\n
\n Text: ").concat(text.id, ", Pieces: ").concat(pieces.length, ", Length: ").concat(text.getLength(), "\n
\n
\n ").concat(piecePartials(pieces).join("\n"), "\n
\n
\n
"); + }); + return details.join("\n"); +}; + +const piecePartials = pieces => pieces.map((piece, index) => "
\n
\n Piece ".concat(piece.id, ", Index: ").concat(index, "\n
\n
\n Attributes: ").concat(JSON.stringify(piece.attributes), "\n
\n
\n ").concat(JSON.stringify(piece.toString()), "\n
\n
")); + +if (!window.JST) { + window.JST = {}; +} + +window.JST["trix/inspector/templates/performance"] = function () { + return Object.keys(this.data).map(name => { + const data = this.data[name]; + return dataMetrics(name, data, this.round); + }).join("\n"); +}; + +const dataMetrics = function (name, data, round) { + let item = "".concat(name, " (").concat(data.calls, ")
"); + + if (data.calls > 0) { + item += "
\n Mean: ".concat(round(data.mean), "ms
\n Max: ").concat(round(data.max), "ms
\n Last: ").concat(round(data.last), "ms\n
"); + return item; + } +}; + +if (!window.JST) { + window.JST = {}; +} + +window.JST["trix/inspector/templates/render"] = function () { + return "Syncs: ".concat(this.syncCount); +}; + +if (!window.JST) { + window.JST = {}; +} + +window.JST["trix/inspector/templates/selection"] = function () { + return "\nLocation range: [".concat(this.locationRange[0].index, ":").concat(this.locationRange[0].offset, ", ").concat(this.locationRange[1].index, ":").concat(this.locationRange[1].offset, "]\n\n").concat(charSpans(this.characters).join("\n")); +}; + +const charSpans = characters => Array.from(characters).map(char => "").concat(char.string, "")); + +if (!window.JST) { + window.JST = {}; +} + +window.JST["trix/inspector/templates/undo"] = function () { + return "

Undo stack

\n
    \n ".concat(entryList(this.undoEntries), "\n
\n\n

Redo stack

\n
    \n ").concat(entryList(this.redoEntries), "\n
"); +}; + +const entryList = entries => entries.map(entry => "
  • ".concat(entry.description, " ").concat(JSON.stringify({ + selectedRange: entry.snapshot.selectedRange, + context: entry.context +}), "
  • ")); + +const KEY_EVENTS = "keydown keypress input".split(" "); +const COMPOSITION_EVENTS = "compositionstart compositionupdate compositionend textInput".split(" "); +const OBSERVER_OPTIONS = { + attributes: true, + childList: true, + characterData: true, + characterDataOldValue: true, + subtree: true +}; +class ControlElement { + constructor(editorElement) { + this.didMutate = this.didMutate.bind(this); + this.editorElement = editorElement; + this.install(); + } + + install() { + this.createElement(); + this.logInputEvents(); + this.logMutations(); + } + + uninstall() { + this.observer.disconnect(); + this.element.parentNode.removeChild(this.element); + } + + createElement() { + this.element = document.createElement("div"); + this.element.setAttribute("contenteditable", ""); + this.element.style.width = getComputedStyle(this.editorElement).width; + this.element.style.minHeight = "50px"; + this.element.style.border = "1px solid green"; + this.editorElement.parentNode.insertBefore(this.element, this.editorElement.nextSibling); + } + + logInputEvents() { + KEY_EVENTS.forEach(eventName => { + this.element.addEventListener(eventName, event => console.log("".concat(event.type, ": keyCode = ").concat(event.keyCode))); + }); + COMPOSITION_EVENTS.forEach(eventName => { + this.element.addEventListener(eventName, event => console.log("".concat(event.type, ": data = ").concat(JSON.stringify(event.data)))); + }); + } + + logMutations() { + this.observer = new window.MutationObserver(this.didMutate); + this.observer.observe(this.element, OBSERVER_OPTIONS); + } + + didMutate(mutations) { + console.log("Mutations (".concat(mutations.length, "):")); + + for (let index = 0; index < mutations.length; index++) { + const mutation = mutations[index]; + console.log(" ".concat(index + 1, ". ").concat(mutation.type, ":")); + + switch (mutation.type) { + case "characterData": + console.log(" oldValue = ".concat(JSON.stringify(mutation.oldValue), ", newValue = ").concat(JSON.stringify(mutation.target.data))); + break; + + case "childList": + Array.from(mutation.addedNodes).forEach(node => { + console.log(" node added ".concat(inspectNode(node))); + }); + Array.from(mutation.removedNodes).forEach(node => { + console.log(" node removed ".concat(inspectNode(node))); + }); + } + } + } + +} + +const inspectNode = function (node) { + if (node.data) { + return JSON.stringify(node.data); + } else { + return JSON.stringify(node.outerHTML); + } +}; + +function _asyncIterator(iterable) { + var method, + async, + sync, + retry = 2; + + if (typeof Symbol !== "undefined") { + async = Symbol.asyncIterator; + sync = Symbol.iterator; + } + + while (retry--) { + if (async && (method = iterable[async]) != null) { + return method.call(iterable); + } + + if (sync && (method = iterable[sync]) != null) { + return new AsyncFromSyncIterator(method.call(iterable)); + } + + async = "@@asyncIterator"; + sync = "@@iterator"; + } + + throw new TypeError("Object is not async iterable"); +} + +function AsyncFromSyncIterator(s) { + AsyncFromSyncIterator = function (s) { + this.s = s; + this.n = s.next; + }; + + AsyncFromSyncIterator.prototype = { + s: null, + n: null, + next: function () { + return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); + }, + return: function (value) { + var ret = this.s.return; + + if (ret === undefined) { + return Promise.resolve({ + value: value, + done: true + }); + } + + return AsyncFromSyncIteratorContinuation(ret.apply(this.s, arguments)); + }, + throw: function (value) { + var thr = this.s.return; + if (thr === undefined) return Promise.reject(value); + return AsyncFromSyncIteratorContinuation(thr.apply(this.s, arguments)); + } + }; + + function AsyncFromSyncIteratorContinuation(r) { + if (Object(r) !== r) { + return Promise.reject(new TypeError(r + " is not an object.")); + } + + var done = r.done; + return Promise.resolve(r.value).then(function (value) { + return { + value: value, + done: done + }; + }); + } + + return new AsyncFromSyncIterator(s); +} + +var REACT_ELEMENT_TYPE; + +function _jsx(type, props, key, children) { + if (!REACT_ELEMENT_TYPE) { + REACT_ELEMENT_TYPE = typeof Symbol === "function" && Symbol["for"] && Symbol["for"]("react.element") || 0xeac7; + } + + var defaultProps = type && type.defaultProps; + var childrenLength = arguments.length - 3; + + if (!props && childrenLength !== 0) { + props = { + children: void 0 + }; + } + + if (childrenLength === 1) { + props.children = children; + } else if (childrenLength > 1) { + var childArray = new Array(childrenLength); + + for (var i = 0; i < childrenLength; i++) { + childArray[i] = arguments[i + 3]; + } + + props.children = childArray; + } + + if (props && defaultProps) { + for (var propName in defaultProps) { + if (props[propName] === void 0) { + props[propName] = defaultProps[propName]; + } + } + } else if (!props) { + props = defaultProps || {}; + } + + return { + $$typeof: REACT_ELEMENT_TYPE, + type: type, + key: key === undefined ? null : "" + key, + ref: null, + props: props, + _owner: null + }; +} + +function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + + if (enumerableOnly) { + symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + }); + } + + keys.push.apply(keys, symbols); + } + + return keys; +} + +function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + + if (i % 2) { + ownKeys(Object(source), true).forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } else if (Object.getOwnPropertyDescriptors) { + Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); + } else { + ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + } + + return target; +} + +function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); +} + +function _wrapRegExp() { + _wrapRegExp = function (re, groups) { + return new BabelRegExp(re, undefined, groups); + }; + + var _super = RegExp.prototype; + + var _groups = new WeakMap(); + + function BabelRegExp(re, flags, groups) { + var _this = new RegExp(re, flags); + + _groups.set(_this, groups || _groups.get(re)); + + return _setPrototypeOf(_this, BabelRegExp.prototype); + } + + _inherits(BabelRegExp, RegExp); + + BabelRegExp.prototype.exec = function (str) { + var result = _super.exec.call(this, str); + + if (result) result.groups = buildGroups(result, this); + return result; + }; + + BabelRegExp.prototype[Symbol.replace] = function (str, substitution) { + if (typeof substitution === "string") { + var groups = _groups.get(this); + + return _super[Symbol.replace].call(this, str, substitution.replace(/\$<([^>]+)>/g, function (_, name) { + return "$" + groups[name]; + })); + } else if (typeof substitution === "function") { + var _this = this; + + return _super[Symbol.replace].call(this, str, function () { + var args = arguments; + + if (typeof args[args.length - 1] !== "object") { + args = [].slice.call(args); + args.push(buildGroups(args, _this)); + } + + return substitution.apply(this, args); + }); + } else { + return _super[Symbol.replace].call(this, str, substitution); + } + }; + + function buildGroups(result, re) { + var g = _groups.get(re); + + return Object.keys(g).reduce(function (groups, name) { + groups[name] = result[g[name]]; + return groups; + }, Object.create(null)); + } + + return _wrapRegExp.apply(this, arguments); +} + +function _AwaitValue(value) { + this.wrapped = value; +} + +function _AsyncGenerator(gen) { + var front, back; + + function send(key, arg) { + return new Promise(function (resolve, reject) { + var request = { + key: key, + arg: arg, + resolve: resolve, + reject: reject, + next: null + }; + + if (back) { + back = back.next = request; + } else { + front = back = request; + resume(key, arg); + } + }); + } + + function resume(key, arg) { + try { + var result = gen[key](arg); + var value = result.value; + var wrappedAwait = value instanceof _AwaitValue; + Promise.resolve(wrappedAwait ? value.wrapped : value).then(function (arg) { + if (wrappedAwait) { + resume(key === "return" ? "return" : "next", arg); + return; + } + + settle(result.done ? "return" : "normal", arg); + }, function (err) { + resume("throw", err); + }); + } catch (err) { + settle("throw", err); + } + } + + function settle(type, value) { + switch (type) { + case "return": + front.resolve({ + value: value, + done: true + }); + break; + + case "throw": + front.reject(value); + break; + + default: + front.resolve({ + value: value, + done: false + }); + break; + } + + front = front.next; + + if (front) { + resume(front.key, front.arg); + } else { + back = null; + } + } + + this._invoke = send; + + if (typeof gen.return !== "function") { + this.return = undefined; + } +} + +_AsyncGenerator.prototype[typeof Symbol === "function" && Symbol.asyncIterator || "@@asyncIterator"] = function () { + return this; +}; + +_AsyncGenerator.prototype.next = function (arg) { + return this._invoke("next", arg); +}; + +_AsyncGenerator.prototype.throw = function (arg) { + return this._invoke("throw", arg); +}; + +_AsyncGenerator.prototype.return = function (arg) { + return this._invoke("return", arg); +}; + +function _wrapAsyncGenerator(fn) { + return function () { + return new _AsyncGenerator(fn.apply(this, arguments)); + }; +} + +function _awaitAsyncGenerator(value) { + return new _AwaitValue(value); +} + +function _asyncGeneratorDelegate(inner, awaitWrap) { + var iter = {}, + waiting = false; + + function pump(key, value) { + waiting = true; + value = new Promise(function (resolve) { + resolve(inner[key](value)); + }); + return { + done: false, + value: awaitWrap(value) + }; + } + + ; + + iter[typeof Symbol !== "undefined" && Symbol.iterator || "@@iterator"] = function () { + return this; + }; + + iter.next = function (value) { + if (waiting) { + waiting = false; + return value; + } + + return pump("next", value); + }; + + if (typeof inner.throw === "function") { + iter.throw = function (value) { + if (waiting) { + waiting = false; + throw value; + } + + return pump("throw", value); + }; + } + + if (typeof inner.return === "function") { + iter.return = function (value) { + if (waiting) { + waiting = false; + return value; + } + + return pump("return", value); + }; + } + + return iter; +} + +function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + + if (info.done) { + resolve(value); + } else { + Promise.resolve(value).then(_next, _throw); + } +} + +function _asyncToGenerator(fn) { + return function () { + var self = this, + args = arguments; + return new Promise(function (resolve, reject) { + var gen = fn.apply(self, args); + + function _next(value) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); + } + + function _throw(err) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); + } + + _next(undefined); + }); + }; +} + +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } +} + +function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; +} + +function _defineEnumerableProperties(obj, descs) { + for (var key in descs) { + var desc = descs[key]; + desc.configurable = desc.enumerable = true; + if ("value" in desc) desc.writable = true; + Object.defineProperty(obj, key, desc); + } + + if (Object.getOwnPropertySymbols) { + var objectSymbols = Object.getOwnPropertySymbols(descs); + + for (var i = 0; i < objectSymbols.length; i++) { + var sym = objectSymbols[i]; + var desc = descs[sym]; + desc.configurable = desc.enumerable = true; + if ("value" in desc) desc.writable = true; + Object.defineProperty(obj, sym, desc); + } + } + + return obj; +} + +function _defaults(obj, defaults) { + var keys = Object.getOwnPropertyNames(defaults); + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var value = Object.getOwnPropertyDescriptor(defaults, key); + + if (value && value.configurable && obj[key] === undefined) { + Object.defineProperty(obj, key, value); + } + } + + return obj; +} + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +function _extends() { + _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + return _extends.apply(this, arguments); +} + +function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? Object(arguments[i]) : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys.push.apply(ownKeys, Object.getOwnPropertySymbols(source).filter(function (sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + + ownKeys.forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } + + return target; +} + +function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); +} + +function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + + _setPrototypeOf(subClass, superClass); +} + +function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); +} + +function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); +} + +function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } +} + +function _construct(Parent, args, Class) { + if (_isNativeReflectConstruct()) { + _construct = Reflect.construct; + } else { + _construct = function _construct(Parent, args, Class) { + var a = [null]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + if (Class) _setPrototypeOf(instance, Class.prototype); + return instance; + }; + } + + return _construct.apply(null, arguments); +} + +function _isNativeFunction(fn) { + return Function.toString.call(fn).indexOf("[native code]") !== -1; +} + +function _wrapNativeSuper(Class) { + var _cache = typeof Map === "function" ? new Map() : undefined; + + _wrapNativeSuper = function _wrapNativeSuper(Class) { + if (Class === null || !_isNativeFunction(Class)) return Class; + + if (typeof Class !== "function") { + throw new TypeError("Super expression must either be null or a function"); + } + + if (typeof _cache !== "undefined") { + if (_cache.has(Class)) return _cache.get(Class); + + _cache.set(Class, Wrapper); + } + + function Wrapper() { + return _construct(Class, arguments, _getPrototypeOf(this).constructor); + } + + Wrapper.prototype = Object.create(Class.prototype, { + constructor: { + value: Wrapper, + enumerable: false, + writable: true, + configurable: true + } + }); + return _setPrototypeOf(Wrapper, Class); + }; + + return _wrapNativeSuper(Class); +} + +function _instanceof(left, right) { + if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { + return !!right[Symbol.hasInstance](left); + } else { + return left instanceof right; + } +} + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; +} + +function _getRequireWildcardCache(nodeInterop) { + if (typeof WeakMap !== "function") return null; + var cacheBabelInterop = new WeakMap(); + var cacheNodeInterop = new WeakMap(); + return (_getRequireWildcardCache = function (nodeInterop) { + return nodeInterop ? cacheNodeInterop : cacheBabelInterop; + })(nodeInterop); +} + +function _interopRequireWildcard(obj, nodeInterop) { + if (!nodeInterop && obj && obj.__esModule) { + return obj; + } + + if (obj === null || typeof obj !== "object" && typeof obj !== "function") { + return { + default: obj + }; + } + + var cache = _getRequireWildcardCache(nodeInterop); + + if (cache && cache.has(obj)) { + return cache.get(obj); + } + + var newObj = {}; + var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; + + for (var key in obj) { + if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { + var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; + + if (desc && (desc.get || desc.set)) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + + newObj.default = obj; + + if (cache) { + cache.set(obj, newObj); + } + + return newObj; +} + +function _newArrowCheck(innerThis, boundThis) { + if (innerThis !== boundThis) { + throw new TypeError("Cannot instantiate an arrow function"); + } +} + +function _objectDestructuringEmpty(obj) { + if (obj == null) throw new TypeError("Cannot destructure undefined"); +} + +function _objectWithoutPropertiesLoose(source, excluded) { + if (source == null) return {}; + var target = {}; + var sourceKeys = Object.keys(source); + var key, i; + + for (i = 0; i < sourceKeys.length; i++) { + key = sourceKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + target[key] = source[key]; + } + + return target; +} + +function _objectWithoutProperties(source, excluded) { + if (source == null) return {}; + + var target = _objectWithoutPropertiesLoose(source, excluded); + + var key, i; + + if (Object.getOwnPropertySymbols) { + var sourceSymbolKeys = Object.getOwnPropertySymbols(source); + + for (i = 0; i < sourceSymbolKeys.length; i++) { + key = sourceSymbolKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; + target[key] = source[key]; + } + } + + return target; +} + +function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; +} + +function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } else if (call !== void 0) { + throw new TypeError("Derived constructors may only return object or undefined"); + } + + return _assertThisInitialized(self); +} + +function _createSuper(Derived) { + var hasNativeReflectConstruct = _isNativeReflectConstruct(); + + return function _createSuperInternal() { + var Super = _getPrototypeOf(Derived), + result; + + if (hasNativeReflectConstruct) { + var NewTarget = _getPrototypeOf(this).constructor; + + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + + return _possibleConstructorReturn(this, result); + }; +} + +function _superPropBase(object, property) { + while (!Object.prototype.hasOwnProperty.call(object, property)) { + object = _getPrototypeOf(object); + if (object === null) break; + } + + return object; +} + +function _get() { + if (typeof Reflect !== "undefined" && Reflect.get) { + _get = Reflect.get; + } else { + _get = function _get(target, property, receiver) { + var base = _superPropBase(target, property); + + if (!base) return; + var desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.get) { + return desc.get.call(arguments.length < 3 ? target : receiver); + } + + return desc.value; + }; + } + + return _get.apply(this, arguments); +} + +function set(target, property, value, receiver) { + if (typeof Reflect !== "undefined" && Reflect.set) { + set = Reflect.set; + } else { + set = function set(target, property, value, receiver) { + var base = _superPropBase(target, property); + + var desc; + + if (base) { + desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.set) { + desc.set.call(receiver, value); + return true; + } else if (!desc.writable) { + return false; + } + } + + desc = Object.getOwnPropertyDescriptor(receiver, property); + + if (desc) { + if (!desc.writable) { + return false; + } + + desc.value = value; + Object.defineProperty(receiver, property, desc); + } else { + _defineProperty(receiver, property, value); + } + + return true; + }; + } + + return set(target, property, value, receiver); +} + +function _set(target, property, value, receiver, isStrict) { + var s = set(target, property, value, receiver || target); + + if (!s && isStrict) { + throw new Error('failed to set property'); + } + + return value; +} + +function _taggedTemplateLiteral(strings, raw) { + if (!raw) { + raw = strings.slice(0); + } + + return Object.freeze(Object.defineProperties(strings, { + raw: { + value: Object.freeze(raw) + } + })); +} + +function _taggedTemplateLiteralLoose(strings, raw) { + if (!raw) { + raw = strings.slice(0); + } + + strings.raw = raw; + return strings; +} + +function _readOnlyError(name) { + throw new TypeError("\"" + name + "\" is read-only"); +} + +function _writeOnlyError(name) { + throw new TypeError("\"" + name + "\" is write-only"); +} + +function _classNameTDZError(name) { + throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); +} + +function _temporalUndefined() {} + +function _tdz(name) { + throw new ReferenceError(name + " is not defined - temporal dead zone"); +} + +function _temporalRef(val, name) { + return val === _temporalUndefined ? _tdz(name) : val; +} + +function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); +} + +function _slicedToArrayLoose(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimitLoose(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); +} + +function _toArray(arr) { + return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); +} + +function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); +} + +function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); +} + +function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; +} + +function _maybeArrayLike(next, arr, i) { + if (arr && !Array.isArray(arr) && typeof arr.length === "number") { + var len = arr.length; + return _arrayLikeToArray(arr, i !== void 0 && i < len ? i : len); + } + + return next(arr, i); +} + +function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); +} + +function _iterableToArrayLimit(arr, i) { + var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; + + if (_i == null) return; + var _arr = []; + var _n = true; + var _d = false; + + var _s, _e; + + try { + for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; +} + +function _iterableToArrayLimitLoose(arr, i) { + var _i = arr && (typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]); + + if (_i == null) return; + var _arr = []; + + for (_i = _i.call(arr), _step; !(_step = _i.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; +} + +function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); +} + +function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; +} + +function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} + +function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} + +function _createForOfIteratorHelper(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + + if (!it) { + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + + var F = function () {}; + + return { + s: F, + n: function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = it.call(o); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; +} + +function _createForOfIteratorHelperLoose(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + if (it) return (it = it.call(o)).next.bind(it); + + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + return function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} + +function _skipFirstGeneratorNext(fn) { + return function () { + var it = fn.apply(this, arguments); + it.next(); + return it; + }; +} + +function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + + return (hint === "string" ? String : Number)(input); +} + +function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + + return typeof key === "symbol" ? key : String(key); +} + +function _initializerWarningHelper(descriptor, context) { + throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and runs after the decorators transform.'); +} + +function _initializerDefineProperty(target, property, descriptor, context) { + if (!descriptor) return; + Object.defineProperty(target, property, { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + writable: descriptor.writable, + value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 + }); +} + +function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { + var desc = {}; + Object.keys(descriptor).forEach(function (key) { + desc[key] = descriptor[key]; + }); + desc.enumerable = !!desc.enumerable; + desc.configurable = !!desc.configurable; + + if ('value' in desc || desc.initializer) { + desc.writable = true; + } + + desc = decorators.slice().reverse().reduce(function (desc, decorator) { + return decorator(target, property, desc) || desc; + }, desc); + + if (context && desc.initializer !== void 0) { + desc.value = desc.initializer ? desc.initializer.call(context) : void 0; + desc.initializer = undefined; + } + + if (desc.initializer === void 0) { + Object.defineProperty(target, property, desc); + desc = null; + } + + return desc; +} + +var id = 0; + +function _classPrivateFieldLooseKey(name) { + return "__private_" + id++ + "_" + name; +} + +function _classPrivateFieldLooseBase(receiver, privateKey) { + if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { + throw new TypeError("attempted to use private field on non-instance"); + } + + return receiver; +} + +function _classPrivateFieldGet(receiver, privateMap) { + var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); + + return _classApplyDescriptorGet(receiver, descriptor); +} + +function _classPrivateFieldSet(receiver, privateMap, value) { + var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); + + _classApplyDescriptorSet(receiver, descriptor, value); + + return value; +} + +function _classPrivateFieldDestructureSet(receiver, privateMap) { + var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); + + return _classApplyDescriptorDestructureSet(receiver, descriptor); +} + +function _classExtractFieldDescriptor(receiver, privateMap, action) { + if (!privateMap.has(receiver)) { + throw new TypeError("attempted to " + action + " private field on non-instance"); + } + + return privateMap.get(receiver); +} + +function _classStaticPrivateFieldSpecGet(receiver, classConstructor, descriptor) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + + _classCheckPrivateStaticFieldDescriptor(descriptor, "get"); + + return _classApplyDescriptorGet(receiver, descriptor); +} + +function _classStaticPrivateFieldSpecSet(receiver, classConstructor, descriptor, value) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + + _classCheckPrivateStaticFieldDescriptor(descriptor, "set"); + + _classApplyDescriptorSet(receiver, descriptor, value); + + return value; +} + +function _classStaticPrivateMethodGet(receiver, classConstructor, method) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + + return method; +} + +function _classStaticPrivateMethodSet() { + throw new TypeError("attempted to set read only static private field"); +} + +function _classApplyDescriptorGet(receiver, descriptor) { + if (descriptor.get) { + return descriptor.get.call(receiver); + } + + return descriptor.value; +} + +function _classApplyDescriptorSet(receiver, descriptor, value) { + if (descriptor.set) { + descriptor.set.call(receiver, value); + } else { + if (!descriptor.writable) { + throw new TypeError("attempted to set read only private field"); + } + + descriptor.value = value; + } +} + +function _classApplyDescriptorDestructureSet(receiver, descriptor) { + if (descriptor.set) { + if (!("__destrObj" in descriptor)) { + descriptor.__destrObj = { + set value(v) { + descriptor.set.call(receiver, v); + } + + }; + } + + return descriptor.__destrObj; + } else { + if (!descriptor.writable) { + throw new TypeError("attempted to set read only private field"); + } + + return descriptor; + } +} + +function _classStaticPrivateFieldDestructureSet(receiver, classConstructor, descriptor) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + + _classCheckPrivateStaticFieldDescriptor(descriptor, "set"); + + return _classApplyDescriptorDestructureSet(receiver, descriptor); +} + +function _classCheckPrivateStaticAccess(receiver, classConstructor) { + if (receiver !== classConstructor) { + throw new TypeError("Private static access of wrong provenance"); + } +} + +function _classCheckPrivateStaticFieldDescriptor(descriptor, action) { + if (descriptor === undefined) { + throw new TypeError("attempted to " + action + " private static field before its declaration"); + } +} + +function _decorate(decorators, factory, superClass, mixins) { + var api = _getDecoratorsApi(); + + if (mixins) { + for (var i = 0; i < mixins.length; i++) { + api = mixins[i](api); + } + } + + var r = factory(function initialize(O) { + api.initializeInstanceElements(O, decorated.elements); + }, superClass); + var decorated = api.decorateClass(_coalesceClassElements(r.d.map(_createElementDescriptor)), decorators); + api.initializeClassElements(r.F, decorated.elements); + return api.runClassFinishers(r.F, decorated.finishers); +} + +function _getDecoratorsApi() { + _getDecoratorsApi = function () { + return api; + }; + + var api = { + elementsDefinitionOrder: [["method"], ["field"]], + initializeInstanceElements: function (O, elements) { + ["method", "field"].forEach(function (kind) { + elements.forEach(function (element) { + if (element.kind === kind && element.placement === "own") { + this.defineClassElement(O, element); + } + }, this); + }, this); + }, + initializeClassElements: function (F, elements) { + var proto = F.prototype; + ["method", "field"].forEach(function (kind) { + elements.forEach(function (element) { + var placement = element.placement; + + if (element.kind === kind && (placement === "static" || placement === "prototype")) { + var receiver = placement === "static" ? F : proto; + this.defineClassElement(receiver, element); + } + }, this); + }, this); + }, + defineClassElement: function (receiver, element) { + var descriptor = element.descriptor; + + if (element.kind === "field") { + var initializer = element.initializer; + descriptor = { + enumerable: descriptor.enumerable, + writable: descriptor.writable, + configurable: descriptor.configurable, + value: initializer === void 0 ? void 0 : initializer.call(receiver) + }; + } + + Object.defineProperty(receiver, element.key, descriptor); + }, + decorateClass: function (elements, decorators) { + var newElements = []; + var finishers = []; + var placements = { + static: [], + prototype: [], + own: [] + }; + elements.forEach(function (element) { + this.addElementPlacement(element, placements); + }, this); + elements.forEach(function (element) { + if (!_hasDecorators(element)) return newElements.push(element); + var elementFinishersExtras = this.decorateElement(element, placements); + newElements.push(elementFinishersExtras.element); + newElements.push.apply(newElements, elementFinishersExtras.extras); + finishers.push.apply(finishers, elementFinishersExtras.finishers); + }, this); + + if (!decorators) { + return { + elements: newElements, + finishers: finishers + }; + } + + var result = this.decorateConstructor(newElements, decorators); + finishers.push.apply(finishers, result.finishers); + result.finishers = finishers; + return result; + }, + addElementPlacement: function (element, placements, silent) { + var keys = placements[element.placement]; + + if (!silent && keys.indexOf(element.key) !== -1) { + throw new TypeError("Duplicated element (" + element.key + ")"); + } + + keys.push(element.key); + }, + decorateElement: function (element, placements) { + var extras = []; + var finishers = []; + + for (var decorators = element.decorators, i = decorators.length - 1; i >= 0; i--) { + var keys = placements[element.placement]; + keys.splice(keys.indexOf(element.key), 1); + var elementObject = this.fromElementDescriptor(element); + var elementFinisherExtras = this.toElementFinisherExtras((0, decorators[i])(elementObject) || elementObject); + element = elementFinisherExtras.element; + this.addElementPlacement(element, placements); + + if (elementFinisherExtras.finisher) { + finishers.push(elementFinisherExtras.finisher); + } + + var newExtras = elementFinisherExtras.extras; + + if (newExtras) { + for (var j = 0; j < newExtras.length; j++) { + this.addElementPlacement(newExtras[j], placements); + } + + extras.push.apply(extras, newExtras); + } + } + + return { + element: element, + finishers: finishers, + extras: extras + }; + }, + decorateConstructor: function (elements, decorators) { + var finishers = []; + + for (var i = decorators.length - 1; i >= 0; i--) { + var obj = this.fromClassDescriptor(elements); + var elementsAndFinisher = this.toClassDescriptor((0, decorators[i])(obj) || obj); + + if (elementsAndFinisher.finisher !== undefined) { + finishers.push(elementsAndFinisher.finisher); + } + + if (elementsAndFinisher.elements !== undefined) { + elements = elementsAndFinisher.elements; + + for (var j = 0; j < elements.length - 1; j++) { + for (var k = j + 1; k < elements.length; k++) { + if (elements[j].key === elements[k].key && elements[j].placement === elements[k].placement) { + throw new TypeError("Duplicated element (" + elements[j].key + ")"); + } + } + } + } + } + + return { + elements: elements, + finishers: finishers + }; + }, + fromElementDescriptor: function (element) { + var obj = { + kind: element.kind, + key: element.key, + placement: element.placement, + descriptor: element.descriptor + }; + var desc = { + value: "Descriptor", + configurable: true + }; + Object.defineProperty(obj, Symbol.toStringTag, desc); + if (element.kind === "field") obj.initializer = element.initializer; + return obj; + }, + toElementDescriptors: function (elementObjects) { + if (elementObjects === undefined) return; + return _toArray(elementObjects).map(function (elementObject) { + var element = this.toElementDescriptor(elementObject); + this.disallowProperty(elementObject, "finisher", "An element descriptor"); + this.disallowProperty(elementObject, "extras", "An element descriptor"); + return element; + }, this); + }, + toElementDescriptor: function (elementObject) { + var kind = String(elementObject.kind); + + if (kind !== "method" && kind !== "field") { + 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 + '"'); + } + + var key = _toPropertyKey(elementObject.key); + + var placement = String(elementObject.placement); + + if (placement !== "static" && placement !== "prototype" && placement !== "own") { + 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 + '"'); + } + + var descriptor = elementObject.descriptor; + this.disallowProperty(elementObject, "elements", "An element descriptor"); + var element = { + kind: kind, + key: key, + placement: placement, + descriptor: Object.assign({}, descriptor) + }; + + if (kind !== "field") { + this.disallowProperty(elementObject, "initializer", "A method descriptor"); + } else { + this.disallowProperty(descriptor, "get", "The property descriptor of a field descriptor"); + this.disallowProperty(descriptor, "set", "The property descriptor of a field descriptor"); + this.disallowProperty(descriptor, "value", "The property descriptor of a field descriptor"); + element.initializer = elementObject.initializer; + } + + return element; + }, + toElementFinisherExtras: function (elementObject) { + var element = this.toElementDescriptor(elementObject); + + var finisher = _optionalCallableProperty(elementObject, "finisher"); + + var extras = this.toElementDescriptors(elementObject.extras); + return { + element: element, + finisher: finisher, + extras: extras + }; + }, + fromClassDescriptor: function (elements) { + var obj = { + kind: "class", + elements: elements.map(this.fromElementDescriptor, this) + }; + var desc = { + value: "Descriptor", + configurable: true + }; + Object.defineProperty(obj, Symbol.toStringTag, desc); + return obj; + }, + toClassDescriptor: function (obj) { + var kind = String(obj.kind); + + if (kind !== "class") { + throw new TypeError('A class descriptor\'s .kind property must be "class", but a decorator' + ' created a class descriptor with .kind "' + kind + '"'); + } + + this.disallowProperty(obj, "key", "A class descriptor"); + this.disallowProperty(obj, "placement", "A class descriptor"); + this.disallowProperty(obj, "descriptor", "A class descriptor"); + this.disallowProperty(obj, "initializer", "A class descriptor"); + this.disallowProperty(obj, "extras", "A class descriptor"); + + var finisher = _optionalCallableProperty(obj, "finisher"); + + var elements = this.toElementDescriptors(obj.elements); + return { + elements: elements, + finisher: finisher + }; + }, + runClassFinishers: function (constructor, finishers) { + for (var i = 0; i < finishers.length; i++) { + var newConstructor = (0, finishers[i])(constructor); + + if (newConstructor !== undefined) { + if (typeof newConstructor !== "function") { + throw new TypeError("Finishers must return a constructor."); + } + + constructor = newConstructor; + } + } + + return constructor; + }, + disallowProperty: function (obj, name, objectType) { + if (obj[name] !== undefined) { + throw new TypeError(objectType + " can't have a ." + name + " property."); + } + } + }; + return api; +} + +function _createElementDescriptor(def) { + var key = _toPropertyKey(def.key); + + var descriptor; + + if (def.kind === "method") { + descriptor = { + value: def.value, + writable: true, + configurable: true, + enumerable: false + }; + } else if (def.kind === "get") { + descriptor = { + get: def.value, + configurable: true, + enumerable: false + }; + } else if (def.kind === "set") { + descriptor = { + set: def.value, + configurable: true, + enumerable: false + }; + } else if (def.kind === "field") { + descriptor = { + configurable: true, + writable: true, + enumerable: true + }; + } + + var element = { + kind: def.kind === "field" ? "field" : "method", + key: key, + placement: def.static ? "static" : def.kind === "field" ? "own" : "prototype", + descriptor: descriptor + }; + if (def.decorators) element.decorators = def.decorators; + if (def.kind === "field") element.initializer = def.value; + return element; +} + +function _coalesceGetterSetter(element, other) { + if (element.descriptor.get !== undefined) { + other.descriptor.get = element.descriptor.get; + } else { + other.descriptor.set = element.descriptor.set; + } +} + +function _coalesceClassElements(elements) { + var newElements = []; + + var isSameElement = function (other) { + return other.kind === "method" && other.key === element.key && other.placement === element.placement; + }; + + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + var other; + + if (element.kind === "method" && (other = newElements.find(isSameElement))) { + if (_isDataDescriptor(element.descriptor) || _isDataDescriptor(other.descriptor)) { + if (_hasDecorators(element) || _hasDecorators(other)) { + throw new ReferenceError("Duplicated methods (" + element.key + ") can't be decorated."); + } + + other.descriptor = element.descriptor; + } else { + if (_hasDecorators(element)) { + if (_hasDecorators(other)) { + throw new ReferenceError("Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ")."); + } + + other.decorators = element.decorators; + } + + _coalesceGetterSetter(element, other); + } + } else { + newElements.push(element); + } + } + + return newElements; +} + +function _hasDecorators(element) { + return element.decorators && element.decorators.length; +} + +function _isDataDescriptor(desc) { + return desc !== undefined && !(desc.value === undefined && desc.writable === undefined); +} + +function _optionalCallableProperty(obj, name) { + var value = obj[name]; + + if (value !== undefined && typeof value !== "function") { + throw new TypeError("Expected '" + name + "' to be a function"); + } + + return value; +} + +function _classPrivateMethodGet(receiver, privateSet, fn) { + if (!privateSet.has(receiver)) { + throw new TypeError("attempted to get private field on non-instance"); + } + + return fn; +} + +function _checkPrivateRedeclaration(obj, privateCollection) { + if (privateCollection.has(obj)) { + throw new TypeError("Cannot initialize the same private elements twice on an object"); + } +} + +function _classPrivateFieldInitSpec(obj, privateMap, value) { + _checkPrivateRedeclaration(obj, privateMap); + + privateMap.set(obj, value); +} + +function _classPrivateMethodInitSpec(obj, privateSet) { + _checkPrivateRedeclaration(obj, privateSet); + + privateSet.add(obj); +} + +function _classPrivateMethodSet() { + throw new TypeError("attempted to reassign private method"); +} + +/* eslint-disable + no-undef, +*/ +class View { + constructor(editorElement) { + this.editorElement = editorElement; + this.editorController = this.editorElement.editorController; + this.editor = this.editorElement.editor; + this.compositionController = this.editorController.compositionController; + this.composition = this.editorController.composition; + this.element = document.createElement("details"); + + if (this.getSetting("open") === "true") { + this.element.open = true; + } + + this.element.classList.add(this.constructor.template); + this.titleElement = document.createElement("summary"); + this.element.appendChild(this.titleElement); + this.panelElement = document.createElement("div"); + this.panelElement.classList.add("panel"); + this.element.appendChild(this.panelElement); + this.element.addEventListener("toggle", event => { + if (event.target === this.element) { + return this.didToggle(); + } + }); + + if (this.events) { + this.installEventHandlers(); + } + } + + installEventHandlers() { + for (const eventName in this.events) { + const handler = this.events[eventName]; + + const callback = event => { + requestAnimationFrame(() => { + handler.call(this, event); + }); + }; + + handleEvent(eventName, { + onElement: this.editorElement, + withCallback: callback + }); + } + } + + didToggle(event) { + this.saveSetting("open", this.isOpen()); + return this.render(); + } + + isOpen() { + return this.element.hasAttribute("open"); + } + + getTitle() { + return this.title || ""; + } + + render() { + this.renderTitle(); + + if (this.isOpen()) { + this.panelElement.innerHTML = JST["trix/inspector/templates/".concat(this.constructor.template)].apply(this); + } + } + + renderTitle() { + this.titleElement.innerHTML = this.getTitle(); + } + + getSetting(key) { + var _window$sessionStorag; + + key = this.getSettingsKey(key); + return (_window$sessionStorag = window.sessionStorage) === null || _window$sessionStorag === void 0 ? void 0 : _window$sessionStorag[key]; + } + + saveSetting(key, value) { + key = this.getSettingsKey(key); + + if (window.sessionStorage) { + window.sessionStorage[key] = value; + } + } + + getSettingsKey(key) { + return "trix/inspector/".concat(this.template, "/").concat(key); + } + + get title() { + return this.constructor.title; + } + + get template() { + return this.constructor.template; + } + + get events() { + return this.constructor.events; + } + +} + +class DebugView extends View { + constructor() { + super(...arguments); + this.didToggleViewCaching = this.didToggleViewCaching.bind(this); + this.didClickRenderButton = this.didClickRenderButton.bind(this); + this.didClickParseButton = this.didClickParseButton.bind(this); + this.didToggleControlElement = this.didToggleControlElement.bind(this); + handleEvent("change", { + onElement: this.element, + matchingSelector: "input[name=viewCaching]", + withCallback: this.didToggleViewCaching + }); + handleEvent("click", { + onElement: this.element, + matchingSelector: "button[data-action=render]", + withCallback: this.didClickRenderButton + }); + handleEvent("click", { + onElement: this.element, + matchingSelector: "button[data-action=parse]", + withCallback: this.didClickParseButton + }); + handleEvent("change", { + onElement: this.element, + matchingSelector: "input[name=controlElement]", + withCallback: this.didToggleControlElement + }); + } + + didToggleViewCaching(_ref) { + let { + target + } = _ref; + + if (target.checked) { + return this.compositionController.enableViewCaching(); + } else { + return this.compositionController.disableViewCaching(); + } + } + + didClickRenderButton() { + return this.editorController.render(); + } + + didClickParseButton() { + return this.editorController.reparse(); + } + + didToggleControlElement(_ref2) { + let { + target + } = _ref2; + + if (target.checked) { + this.control = new Trix.Inspector.ControlElement(this.editorElement); + } else { + var _this$control; + + (_this$control = this.control) === null || _this$control === void 0 ? void 0 : _this$control.uninstall(); + this.control = null; + } + } + +} + +_defineProperty(DebugView, "title", "Debug"); + +_defineProperty(DebugView, "template", "debug"); + +Trix.Inspector.registerView(DebugView); + +class DocumentView extends View { + render() { + this.document = this.editor.getDocument(); + return super.render(...arguments); + } + +} + +_defineProperty(DocumentView, "title", "Document"); + +_defineProperty(DocumentView, "template", "document"); + +_defineProperty(DocumentView, "events", { + "trix-change": function () { + return this.render(); + } +}); + +Trix.Inspector.registerView(DocumentView); + +var _window$performance; +const now = (_window$performance = window.performance) !== null && _window$performance !== void 0 && _window$performance.now ? () => performance.now() : () => new Date().getTime(); + +class PerformanceView extends View { + constructor() { + super(...arguments); + this.documentView = this.compositionController.documentView; + this.data = {}; + this.track("documentView.render"); + this.track("documentView.sync"); + this.track("documentView.garbageCollectCachedViews"); + this.track("composition.replaceHTML"); + this.render(); + } + + track(methodPath) { + this.data[methodPath] = { + calls: 0, + total: 0, + mean: 0, + max: 0, + last: 0 + }; + const parts = methodPath.split("."); + const propertyNames = parts.slice(0, parts.length - 1); + const methodName = parts[parts.length - 1]; + let object = this; + propertyNames.forEach(propertyName => { + object = object[propertyName]; + }); + const original = object[methodName]; + + object[methodName] = function () { + const started = now(); + const result = original.apply(object, arguments); + const timing = now() - started; + this.record(methodPath, timing); + return result; + }.bind(this); + } + + record(methodPath, timing) { + const data = this.data[methodPath]; + data.calls += 1; + data.total += timing; + data.mean = data.total / data.calls; + + if (timing > data.max) { + data.max = timing; + } + + data.last = timing; + return this.render(); + } + + round(ms) { + return Math.round(ms * 1000) / 1000; + } + +} + +_defineProperty(PerformanceView, "title", "Performance"); + +_defineProperty(PerformanceView, "template", "performance"); + +Trix.Inspector.registerView(PerformanceView); + +class RenderView extends View { + constructor() { + super(...arguments); + this.renderCount = 0; + this.syncCount = 0; + } + + getTitle() { + return "".concat(this.title, " (").concat(this.renderCount, ")"); + } + +} + +_defineProperty(RenderView, "title", "Renders"); + +_defineProperty(RenderView, "template", "render"); + +_defineProperty(RenderView, "events", { + "trix-render": function () { + this.renderCount++; + return this.render(); + }, + "trix-sync": function () { + this.syncCount++; + return this.render(); + } +}); + +Trix.Inspector.registerView(RenderView); + +class SelectionView extends View { + render() { + this.document = this.editor.getDocument(); + this.range = this.editor.getSelectedRange(); + this.locationRange = this.composition.getLocationRange(); + this.characters = this.getCharacters(); + return super.render(...arguments); + } + + getCharacters() { + const chars = []; + const utf16string = UTF16String.box(this.document.toString()); + const rangeIsExpanded = this.range[0] !== this.range[1]; + let position = 0; + + while (position < utf16string.length) { + let string = utf16string.charAt(position).toString(); + + if (string === "\n") { + string = "⏎"; + } + + const selected = rangeIsExpanded && position >= this.range[0] && position < this.range[1]; + chars.push({ + string, + selected + }); + position++; + } + + return chars; + } + + getTitle() { + return "".concat(this.title, " (").concat(this.range.join(), ")"); + } + +} + +_defineProperty(SelectionView, "title", "Selection"); + +_defineProperty(SelectionView, "template", "selection"); + +_defineProperty(SelectionView, "events", { + "trix-selection-change": function () { + return this.render(); + }, + "trix-render": function () { + return this.render(); + } +}); + +Trix.Inspector.registerView(SelectionView); + +class UndoView extends View { + render() { + this.undoEntries = this.editor.undoManager.undoEntries; + this.redoEntries = this.editor.undoManager.redoEntries; + return super.render(...arguments); + } + +} + +_defineProperty(UndoView, "title", "Undo"); + +_defineProperty(UndoView, "template", "undo"); + +_defineProperty(UndoView, "events", { + "trix-change": function () { + return this.render(); + } +}); + +Trix.Inspector.registerView(UndoView); +//# sourceMappingURL=inspector.js.map diff --git a/dist/inspector.js.map b/dist/inspector.js.map new file mode 100644 index 00000000..5fafd68f --- /dev/null +++ b/dist/inspector.js.map @@ -0,0 +1 @@ +{"version":3,"file":"inspector.js","sources":["../src/trix/core/helpers/arrays.js","../src/trix/config/attachments.js","../src/trix/config/block_attributes.js","../src/trix/config/browser.js","../src/trix/config/css.js","../src/trix/config/lang.js","../src/trix/config/file_size_formatting.js","../src/trix/config/input.js","../src/trix/config/key_names.js","../src/trix/config/text_attributes.js","../src/trix/config/toolbar.js","../src/trix/config/undo_interval.js","../src/trix/config.js","../src/trix/constants.js","../src/trix/core/helpers/extend.js","../src/trix/core/helpers/dom.js","../src/trix/core/helpers/bidi.js","../src/trix/core/helpers/config.js","../src/trix/core/helpers/custom_elements.js","../src/trix/core/helpers/events.js","../src/trix/core/helpers/functions.js","../src/trix/core/helpers/objects.js","../src/trix/core/helpers/ranges.js","../src/trix/core/basic_object.js","../src/trix/observers/selection_change_observer.js","../src/trix/core/utilities/utf16_string.js","../src/trix/core/helpers/strings.js","../src/inspector/element.js","../src/inspector/global.js","../src/inspector/templates/debug.js","../src/inspector/templates/document.js","../src/inspector/templates/performance.js","../src/inspector/templates/render.js","../src/inspector/templates/selection.js","../src/inspector/templates/undo.js","../src/inspector/control_element.js","../src/inspector/view.js","../src/inspector/views/debug_view.js","../src/inspector/views/document_view.js","../src/inspector/views/performance_view.js","../src/inspector/views/render_view.js","../src/inspector/views/selection_view.js","../src/inspector/views/undo_view.js"],"sourcesContent":["/* eslint-disable\n id-length,\n*/\nexport const arraysAreEqual = function(a = [], b = []) {\n if (a.length !== b.length) {\n return false\n }\n for (let index = 0; index < a.length; index++) {\n const value = a[index]\n if (value !== b[index]) {\n return false\n }\n }\n return true\n}\n\nexport const arrayStartsWith = (a = [], b = []) => arraysAreEqual(a.slice(0, b.length), b)\n\nexport const spliceArray = function(array, ...args) {\n const result = array.slice(0)\n result.splice(...args)\n return result\n}\n\nexport const summarizeArrayChange = function(oldArray = [], newArray = []) {\n const added = []\n const removed = []\n\n const existingValues = new Set()\n\n oldArray.forEach((value) => {\n existingValues.add(value)\n })\n\n const currentValues = new Set()\n\n newArray.forEach((value) => {\n currentValues.add(value)\n if (!existingValues.has(value)) {\n added.push(value)\n }\n })\n\n oldArray.forEach((value) => {\n if (!currentValues.has(value)) {\n removed.push(value)\n }\n })\n\n return { added, removed }\n}\n","export const attachmentSelector = \"[data-trix-attachment]\"\n\nconst attachments = {\n preview: {\n presentation: \"gallery\",\n caption: {\n name: true,\n size: true,\n },\n },\n file: {\n caption: {\n size: true,\n },\n },\n}\nexport default attachments\n","const attributes = {\n default: {\n tagName: \"div\",\n parse: false,\n },\n quote: {\n tagName: \"blockquote\",\n nestable: true,\n },\n heading1: {\n tagName: \"h1\",\n terminal: true,\n breakOnReturn: true,\n group: false,\n },\n code: {\n tagName: \"pre\",\n terminal: true,\n text: {\n plaintext: true,\n },\n },\n bulletList: {\n tagName: \"ul\",\n parse: false,\n },\n bullet: {\n tagName: \"li\",\n listAttribute: \"bulletList\",\n group: false,\n nestable: true,\n test(element) {\n return tagName(element.parentNode) === attributes[this.listAttribute].tagName\n },\n },\n numberList: {\n tagName: \"ol\",\n parse: false,\n },\n number: {\n tagName: \"li\",\n listAttribute: \"numberList\",\n group: false,\n nestable: true,\n test(element) {\n return tagName(element.parentNode) === attributes[this.listAttribute].tagName\n },\n },\n attachmentGallery: {\n tagName: \"div\",\n exclusive: true,\n terminal: true,\n parse: false,\n group: false,\n },\n}\n\nconst tagName = (element) => element?.tagName?.toLowerCase()\n\nexport default attributes\n","export default {\n // Android emits composition events when moving the cursor through existing text\n // Introduced in Chrome 65: https://bugs.chromium.org/p/chromium/issues/detail?id=764439#c9\n composesExistingText: /Android.*Chrome/.test(navigator.userAgent),\n // IE 11 activates resizing handles on editable elements that have \"layout\"\n forcesObjectResizing: /Trident.*rv:11/.test(navigator.userAgent),\n // https://www.w3.org/TR/input-events-1/ + https://www.w3.org/TR/input-events-2/\n supportsInputEvents: (function() {\n if (typeof InputEvent === \"undefined\") {\n return false\n }\n for (const property of [ \"data\", \"getTargetRanges\", \"inputType\" ]) {\n if (!(property in InputEvent.prototype)) {\n return false\n }\n }\n return true\n })(),\n}\n","export default {\n attachment: \"attachment\",\n attachmentCaption: \"attachment__caption\",\n attachmentCaptionEditor: \"attachment__caption-editor\",\n attachmentMetadata: \"attachment__metadata\",\n attachmentMetadataContainer: \"attachment__metadata-container\",\n attachmentName: \"attachment__name\",\n attachmentProgress: \"attachment__progress\",\n attachmentSize: \"attachment__size\",\n attachmentToolbar: \"attachment__toolbar\",\n attachmentGallery: \"attachment-gallery\",\n}\n","export default {\n attachFiles: \"Attach Files\",\n bold: \"Bold\",\n bullets: \"Bullets\",\n byte: \"Byte\",\n bytes: \"Bytes\",\n captionPlaceholder: \"Add a caption…\",\n code: \"Code\",\n heading1: \"Heading\",\n indent: \"Increase Level\",\n italic: \"Italic\",\n link: \"Link\",\n numbers: \"Numbers\",\n outdent: \"Decrease Level\",\n quote: \"Quote\",\n redo: \"Redo\",\n remove: \"Remove\",\n strike: \"Strikethrough\",\n undo: \"Undo\",\n unlink: \"Unlink\",\n url: \"URL\",\n urlPlaceholder: \"Enter a URL…\",\n GB: \"GB\",\n KB: \"KB\",\n MB: \"MB\",\n PB: \"PB\",\n TB: \"TB\",\n}\n","/* eslint-disable\n no-case-declarations,\n*/\nimport lang from \"trix/config/lang\"\n\nconst sizes = [ lang.bytes, lang.KB, lang.MB, lang.GB, lang.TB, lang.PB ]\n\nexport default {\n prefix: \"IEC\",\n precision: 2,\n\n formatter(number) {\n switch (number) {\n case 0:\n return `0 ${lang.bytes}`\n case 1:\n return `1 ${lang.byte}`\n default:\n let base\n\n if (this.prefix === \"SI\") {\n base = 1000\n } else if (this.prefix === \"IEC\") {\n base = 1024\n }\n\n const exp = Math.floor(Math.log(number) / Math.log(base))\n const humanSize = number / Math.pow(base, exp)\n const string = humanSize.toFixed(this.precision)\n const withoutInsignificantZeros = string.replace(/0*$/, \"\").replace(/\\.$/, \"\")\n return `${withoutInsignificantZeros} ${sizes[exp]}`\n }\n },\n}\n","import browser from \"trix/config/browser\"\n\nconst input = {\n level2Enabled: true,\n\n getLevel() {\n if (this.level2Enabled && browser.supportsInputEvents) {\n return 2\n } else {\n return 0\n }\n },\n}\n\nexport default input\n","export default {\n 8: \"backspace\",\n 9: \"tab\",\n 13: \"return\",\n 27: \"escape\",\n 37: \"left\",\n 39: \"right\",\n 46: \"delete\",\n 68: \"d\",\n 72: \"h\",\n 79: \"o\",\n}\n","import { attachmentSelector } from \"trix/config/attachments\"\n\nexport default {\n bold: {\n tagName: \"strong\",\n inheritable: true,\n parser(element) {\n const style = window.getComputedStyle(element)\n return style.fontWeight === \"bold\" || style.fontWeight >= 600\n },\n },\n italic: {\n tagName: \"em\",\n inheritable: true,\n parser(element) {\n const style = window.getComputedStyle(element)\n return style.fontStyle === \"italic\"\n },\n },\n href: {\n groupTagName: \"a\",\n parser(element) {\n const matchingSelector = `a:not(${attachmentSelector})`\n const link = element.closest(matchingSelector)\n if (link) {\n return link.getAttribute(\"href\")\n }\n },\n },\n strike: {\n tagName: \"del\",\n inheritable: true,\n },\n frozen: {\n style: { backgroundColor: \"highlight\" },\n },\n}\n","import lang from \"trix/config/lang\"\n\nexport default {\n getDefaultHTML() {\n return `\\\n
    \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n\n \n \n \n\n \n\n \n \n \n \n
    \n\n
    \n
    \n \n
    \n
    \\\n`\n },\n}\n","const undoInterval = 5000\nexport default undoInterval\n","import attachments from \"trix/config/attachments\"\nimport blockAttributes from \"trix/config/block_attributes\"\nimport browser from \"trix/config/browser\"\nimport css from \"trix/config/css\"\nimport fileSize from \"trix/config/file_size_formatting\"\nimport input from \"trix/config/input\"\nimport keyNames from \"trix/config/key_names\"\nimport lang from \"trix/config/lang\"\nimport textAttributes from \"trix/config/text_attributes\"\nimport toolbar from \"trix/config/toolbar\"\nimport undoInterval from \"trix/config/undo_interval\"\n\nconst config = {\n attachments,\n blockAttributes,\n browser,\n css,\n fileSize,\n input,\n keyNames,\n lang,\n textAttributes,\n toolbar,\n undoInterval,\n}\n\nexport default config\n","export const ZERO_WIDTH_SPACE = \"\\uFEFF\"\nexport const NON_BREAKING_SPACE = \"\\u00A0\"\nexport const OBJECT_REPLACEMENT_CHARACTER = \"\\uFFFC\"\n","export const extend = function(properties) {\n for (const key in properties) {\n const value = properties[key]\n this[key] = value\n }\n return this\n}\n","import config from \"trix/config\"\nimport { ZERO_WIDTH_SPACE } from \"trix/constants\"\nimport { extend } from \"./extend\"\nimport { attachmentSelector } from \"trix/config/attachments\"\n\nconst html = document.documentElement\nconst match = html.matches\n\nexport const handleEvent = function(eventName, { onElement, matchingSelector, withCallback, inPhase, preventDefault, times } = {}) {\n const element = onElement ? onElement : html\n const selector = matchingSelector\n const useCapture = inPhase === \"capturing\"\n\n const handler = function(event) {\n if (times != null && --times === 0) {\n handler.destroy()\n }\n const target = findClosestElementFromNode(event.target, { matchingSelector: selector })\n if (target != null) {\n withCallback?.call(target, event, target)\n if (preventDefault) {\n event.preventDefault()\n }\n }\n }\n\n handler.destroy = () => element.removeEventListener(eventName, handler, useCapture)\n\n element.addEventListener(eventName, handler, useCapture)\n return handler\n}\n\nexport const handleEventOnce = function(eventName, options = {}) {\n options.times = 1\n return handleEvent(eventName, options)\n}\n\nexport const triggerEvent = function(eventName, { onElement, bubbles, cancelable, attributes } = {}) {\n const element = onElement != null ? onElement : html\n bubbles = bubbles !== false\n cancelable = cancelable !== false\n\n const event = document.createEvent(\"Events\")\n event.initEvent(eventName, bubbles, cancelable)\n if (attributes != null) {\n extend.call(event, attributes)\n }\n return element.dispatchEvent(event)\n}\n\nexport const elementMatchesSelector = function(element, selector) {\n if (element?.nodeType === 1) {\n return match.call(element, selector)\n }\n}\n\nexport const findClosestElementFromNode = function(node, { matchingSelector, untilNode } = {}) {\n while (node && node.nodeType !== Node.ELEMENT_NODE) {\n node = node.parentNode\n }\n if (node == null) {\n return\n }\n\n if (matchingSelector != null) {\n if (node.closest && untilNode == null) {\n return node.closest(matchingSelector)\n } else {\n while (node && node !== untilNode) {\n if (elementMatchesSelector(node, matchingSelector)) {\n return node\n }\n node = node.parentNode\n }\n }\n } else {\n return node\n }\n}\n\nexport const findInnerElement = function(element) {\n while (element?.firstElementChild) {\n element = element.firstElementChild\n }\n return element\n}\n\nexport const innerElementIsActive = (element) =>\n document.activeElement !== element && elementContainsNode(element, document.activeElement)\n\nexport const elementContainsNode = function(element, node) {\n if (!element || !node) {\n return\n }\n while (node) {\n if (node === element) {\n return true\n }\n node = node.parentNode\n }\n}\n\nexport const findNodeFromContainerAndOffset = function(container, offset) {\n if (!container) {\n return\n }\n if (container.nodeType === Node.TEXT_NODE) {\n return container\n } else if (offset === 0) {\n return container.firstChild != null ? container.firstChild : container\n } else {\n return container.childNodes.item(offset - 1)\n }\n}\n\nexport const findElementFromContainerAndOffset = function(container, offset) {\n const node = findNodeFromContainerAndOffset(container, offset)\n return findClosestElementFromNode(node)\n}\n\nexport const findChildIndexOfNode = function(node) {\n if (!node?.parentNode) {\n return\n }\n let childIndex = 0\n node = node.previousSibling\n while (node) {\n childIndex++\n node = node.previousSibling\n }\n return childIndex\n}\n\nexport const removeNode = (node) => node?.parentNode?.removeChild(node)\n\nexport const walkTree = function(tree, { onlyNodesOfType, usingFilter, expandEntityReferences } = {}) {\n const whatToShow = (() => {\n switch (onlyNodesOfType) {\n case \"element\":\n return NodeFilter.SHOW_ELEMENT\n case \"text\":\n return NodeFilter.SHOW_TEXT\n case \"comment\":\n return NodeFilter.SHOW_COMMENT\n default:\n return NodeFilter.SHOW_ALL\n }\n })()\n\n return document.createTreeWalker(\n tree,\n whatToShow,\n usingFilter != null ? usingFilter : null,\n expandEntityReferences === true\n )\n}\n\nexport const tagName = (element) => element?.tagName?.toLowerCase()\n\nexport const makeElement = function(tag, options = {}) {\n let key, value\n if (typeof tag === \"object\") {\n options = tag\n tag = options.tagName\n } else {\n options = { attributes: options }\n }\n\n const element = document.createElement(tag)\n\n if (options.editable != null) {\n if (options.attributes == null) {\n options.attributes = {}\n }\n options.attributes.contenteditable = options.editable\n }\n\n if (options.attributes) {\n for (key in options.attributes) {\n value = options.attributes[key]\n element.setAttribute(key, value)\n }\n }\n\n if (options.style) {\n for (key in options.style) {\n value = options.style[key]\n element.style[key] = value\n }\n }\n\n if (options.data) {\n for (key in options.data) {\n value = options.data[key]\n element.dataset[key] = value\n }\n }\n\n if (options.className) {\n options.className.split(\" \").forEach((className) => {\n element.classList.add(className)\n })\n }\n\n if (options.textContent) {\n element.textContent = options.textContent\n }\n\n if (options.childNodes) {\n [].concat(options.childNodes).forEach((childNode) => {\n element.appendChild(childNode)\n })\n }\n\n return element\n}\n\nlet blockTagNames = undefined\n\nexport const getBlockTagNames = function() {\n if (blockTagNames != null) {\n return blockTagNames\n }\n\n blockTagNames = []\n for (const key in config.blockAttributes) {\n const attributes = config.blockAttributes[key]\n if (attributes.tagName) {\n blockTagNames.push(attributes.tagName)\n }\n }\n\n return blockTagNames\n}\n\nexport const nodeIsBlockContainer = (node) => nodeIsBlockStartComment(node?.firstChild)\n\nexport const nodeProbablyIsBlockContainer = function(node) {\n return getBlockTagNames().includes(tagName(node)) && !getBlockTagNames().includes(tagName(node.firstChild))\n}\n\nexport const nodeIsBlockStart = function(node, { strict } = { strict: true }) {\n if (strict) {\n return nodeIsBlockStartComment(node)\n } else {\n return (\n nodeIsBlockStartComment(node) || !nodeIsBlockStartComment(node.firstChild) && nodeProbablyIsBlockContainer(node)\n )\n }\n}\n\nexport const nodeIsBlockStartComment = (node) => nodeIsCommentNode(node) && node?.data === \"block\"\n\nexport const nodeIsCommentNode = (node) => node?.nodeType === Node.COMMENT_NODE\n\nexport const nodeIsCursorTarget = function(node, { name } = {}) {\n if (!node) {\n return\n }\n if (nodeIsTextNode(node)) {\n if (node.data === ZERO_WIDTH_SPACE) {\n if (name) {\n return node.parentNode.dataset.trixCursorTarget === name\n } else {\n return true\n }\n }\n } else {\n return nodeIsCursorTarget(node.firstChild)\n }\n}\n\nexport const nodeIsAttachmentElement = (node) => elementMatchesSelector(node, attachmentSelector)\n\nexport const nodeIsEmptyTextNode = (node) => nodeIsTextNode(node) && node?.data === \"\"\n\nexport const nodeIsTextNode = (node) => node?.nodeType === Node.TEXT_NODE\n","import { makeElement } from \"trix/core/helpers/dom\"\n\n// https://github.com/mathiasbynens/unicode-2.1.8/blob/master/Bidi_Class/Right_To_Left/regex.js\nconst RTL_PATTERN =\n /[\\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]/\n\nexport const getDirection = (function() {\n const input = makeElement(\"input\", { dir: \"auto\", name: \"x\", dirName: \"x.dir\" })\n const form = makeElement(\"form\")\n form.appendChild(input)\n\n const supportsDirName = (function() {\n try {\n return new FormData(form).has(input.dirName)\n } catch (error) {\n return false\n }\n })()\n\n const supportsDirSelector = (function() {\n try {\n return input.matches(\":dir(ltr),:dir(rtl)\")\n } catch (error) {\n return false\n }\n })()\n\n if (supportsDirName) {\n return function(string) {\n input.value = string\n return new FormData(form).get(input.dirName)\n }\n } else if (supportsDirSelector) {\n return function(string) {\n input.value = string\n if (input.matches(\":dir(rtl)\")) {\n return \"rtl\"\n } else {\n return \"ltr\"\n }\n }\n } else {\n return function(string) {\n const char = string.trim().charAt(0)\n if (RTL_PATTERN.test(char)) {\n return \"rtl\"\n } else {\n return \"ltr\"\n }\n }\n }\n})()\n","import config from \"trix/config\"\n\nlet allAttributeNames = null\nlet blockAttributeNames = null\nlet textAttributeNames = null\nlet listAttributeNames = null\n\nexport const getAllAttributeNames = () => {\n if (!allAttributeNames) {\n allAttributeNames = getTextAttributeNames().concat(getBlockAttributeNames())\n }\n return allAttributeNames\n}\n\nexport const getBlockConfig = (attributeName) => config.blockAttributes[attributeName]\n\nexport const getBlockAttributeNames = () => {\n if (!blockAttributeNames) {\n blockAttributeNames = Object.keys(config.blockAttributes)\n }\n return blockAttributeNames\n}\n\nexport const getTextConfig = (attributeName) => config.textAttributes[attributeName]\n\nexport const getTextAttributeNames = () => {\n if (!textAttributeNames) {\n textAttributeNames = Object.keys(config.textAttributes)\n }\n return textAttributeNames\n}\n\nexport const getListAttributeNames = () => {\n if (!listAttributeNames) {\n listAttributeNames = []\n for (const key in config.blockAttributes) {\n const { listAttribute } = config.blockAttributes[key]\n if (listAttribute != null) {\n listAttributeNames.push(listAttribute)\n }\n }\n }\n return listAttributeNames\n}\n","/* eslint-disable\n*/\nexport const installDefaultCSSForTagName = function(tagName, defaultCSS) {\n const styleElement = insertStyleElementForTagName(tagName)\n styleElement.textContent = defaultCSS.replace(/%t/g, tagName)\n}\n\nconst insertStyleElementForTagName = function(tagName) {\n const element = document.createElement(\"style\")\n element.setAttribute(\"type\", \"text/css\")\n element.setAttribute(\"data-tag-name\", tagName.toLowerCase())\n const nonce = getCSPNonce()\n if (nonce) {\n element.setAttribute(\"nonce\", nonce)\n }\n document.head.insertBefore(element, document.head.firstChild)\n return element\n}\n\nconst getCSPNonce = function() {\n const element = getMetaElement(\"trix-csp-nonce\") || getMetaElement(\"csp-nonce\")\n if (element) {\n return element.getAttribute(\"content\")\n }\n}\n\nconst getMetaElement = (name) => document.head.querySelector(`meta[name=${name}]`)\n","const testTransferData = { \"application/x-trix-feature-detection\": \"test\" }\n\nexport const dataTransferIsPlainText = function(dataTransfer) {\n const text = dataTransfer.getData(\"text/plain\")\n const html = dataTransfer.getData(\"text/html\")\n\n if (text && html) {\n const { body } = new DOMParser().parseFromString(html, \"text/html\")\n if (body.textContent === text) {\n return !body.querySelector(\"*\")\n }\n } else {\n return text?.length\n }\n}\n\nexport const dataTransferIsWritable = function(dataTransfer) {\n if (!dataTransfer?.setData) return false\n\n for (const key in testTransferData) {\n const value = testTransferData[key]\n\n try {\n dataTransfer.setData(key, value)\n if (!dataTransfer.getData(key) === value) return false\n } catch (error) {\n return false\n }\n }\n return true\n}\n\nexport const keyEventIsKeyboardCommand = (function() {\n if (/Mac|^iP/.test(navigator.platform)) {\n return (event) => event.metaKey\n } else {\n return (event) => event.ctrlKey\n }\n})()\n","export const defer = (fn) => setTimeout(fn, 1)\n","/* eslint-disable\n id-length,\n*/\nexport const copyObject = function(object = {}) {\n const result = {}\n for (const key in object) {\n const value = object[key]\n result[key] = value\n }\n return result\n}\n\nexport const objectsAreEqual = function(a = {}, b = {}) {\n if (Object.keys(a).length !== Object.keys(b).length) {\n return false\n }\n for (const key in a) {\n const value = a[key]\n if (value !== b[key]) {\n return false\n }\n }\n return true\n}\n","import { copyObject, objectsAreEqual } from \"trix/core/helpers/objects\"\n\nexport const normalizeRange = function(range) {\n if (range == null) return\n\n if (!Array.isArray(range)) {\n range = [ range, range ]\n }\n return [ copyValue(range[0]), copyValue(range[1] != null ? range[1] : range[0]) ]\n}\n\nexport const rangeIsCollapsed = function(range) {\n if (range == null) return\n\n const [ start, end ] = normalizeRange(range)\n return rangeValuesAreEqual(start, end)\n}\n\nexport const rangesAreEqual = function(leftRange, rightRange) {\n if (leftRange == null || rightRange == null) return\n\n const [ leftStart, leftEnd ] = normalizeRange(leftRange)\n const [ rightStart, rightEnd ] = normalizeRange(rightRange)\n return rangeValuesAreEqual(leftStart, rightStart) && rangeValuesAreEqual(leftEnd, rightEnd)\n}\n\nconst copyValue = function(value) {\n if (typeof value === \"number\") {\n return value\n } else {\n return copyObject(value)\n }\n}\n\nconst rangeValuesAreEqual = function(left, right) {\n if (typeof left === \"number\") {\n return left === right\n } else {\n return objectsAreEqual(left, right)\n }\n}\n","export default class BasicObject {\n static proxyMethod(expression) {\n const { name, toMethod, toProperty, optional } = parseProxyMethodExpression(expression)\n\n this.prototype[name] = function() {\n let subject\n let object\n\n if (toMethod) {\n if (optional) {\n object = this[toMethod]?.()\n } else {\n object = this[toMethod]()\n }\n } else if (toProperty) {\n object = this[toProperty]\n }\n\n if (optional) {\n subject = object?.[name]\n if (subject) {\n return apply.call(subject, object, arguments)\n }\n } else {\n subject = object[name]\n return apply.call(subject, object, arguments)\n }\n }\n }\n}\n\nconst parseProxyMethodExpression = function(expression) {\n const match = expression.match(proxyMethodExpressionPattern)\n if (!match) {\n throw new Error(`can't parse @proxyMethod expression: ${expression}`)\n }\n\n const args = { name: match[4] }\n\n if (match[2] != null) {\n args.toMethod = match[1]\n } else {\n args.toProperty = match[1]\n }\n\n if (match[3] != null) {\n args.optional = true\n }\n\n return args\n}\n\nconst { apply } = Function.prototype\n\nconst proxyMethodExpressionPattern = new RegExp(\"\\\n^\\\n(.+?)\\\n(\\\\(\\\\))?\\\n(\\\\?)?\\\n\\\\.\\\n(.+?)\\\n$\\\n\")\n","/* eslint-disable\n id-length,\n*/\nimport BasicObject from \"trix/core/basic_object\"\n\nexport default class SelectionChangeObserver extends BasicObject {\n constructor() {\n super(...arguments)\n this.update = this.update.bind(this)\n this.run = this.run.bind(this)\n this.selectionManagers = []\n }\n\n start() {\n if (!this.started) {\n this.started = true\n if (\"onselectionchange\" in document) {\n return document.addEventListener(\"selectionchange\", this.update, true)\n } else {\n return this.run()\n }\n }\n }\n\n stop() {\n if (this.started) {\n this.started = false\n return document.removeEventListener(\"selectionchange\", this.update, true)\n }\n }\n\n registerSelectionManager(selectionManager) {\n if (!this.selectionManagers.includes(selectionManager)) {\n this.selectionManagers.push(selectionManager)\n return this.start()\n }\n }\n\n unregisterSelectionManager(selectionManager) {\n this.selectionManagers = this.selectionManagers.filter((s) => s !== selectionManager)\n if (this.selectionManagers.length === 0) {\n return this.stop()\n }\n }\n\n notifySelectionManagersOfSelectionChange() {\n return this.selectionManagers.map((selectionManager) => selectionManager.selectionDidChange())\n }\n\n update() {\n const domRange = getDOMRange()\n if (!domRangesAreEqual(domRange, this.domRange)) {\n this.domRange = domRange\n return this.notifySelectionManagersOfSelectionChange()\n }\n }\n\n reset() {\n this.domRange = null\n return this.update()\n }\n\n // Private\n\n run() {\n if (this.started) {\n this.update()\n return requestAnimationFrame(this.run)\n }\n }\n}\n\nconst domRangesAreEqual = (left, right) =>\n left?.startContainer === right?.startContainer &&\n left?.startOffset === right?.startOffset &&\n left?.endContainer === right?.endContainer &&\n left?.endOffset === right?.endOffset\n\nexport const selectionChangeObserver = new SelectionChangeObserver()\n\nexport const getDOMSelection = function() {\n const selection = window.getSelection()\n if (selection.rangeCount > 0) {\n return selection\n }\n}\n\nexport const getDOMRange = function() {\n const domRange = getDOMSelection()?.getRangeAt(0)\n if (domRange) {\n if (!domRangeIsPrivate(domRange)) {\n return domRange\n }\n }\n}\n\nexport const setDOMRange = function(domRange) {\n const selection = window.getSelection()\n selection.removeAllRanges()\n selection.addRange(domRange)\n return selectionChangeObserver.update()\n}\n\n// In Firefox, clicking certain elements changes the selection to a\n// private element used to draw its UI. Attempting to access properties of those\n// elements throws an error.\n// https://bugzilla.mozilla.org/show_bug.cgi?id=208427\nconst domRangeIsPrivate = (domRange) => nodeIsPrivate(domRange.startContainer) || nodeIsPrivate(domRange.endContainer)\n\nconst nodeIsPrivate = (node) => !Object.getPrototypeOf(node)\n","import BasicObject from \"trix/core/basic_object\"\n\nexport default class UTF16String extends BasicObject {\n static box(value = \"\") {\n if (value instanceof this) {\n return value\n } else {\n return this.fromUCS2String(value?.toString())\n }\n }\n\n static fromUCS2String(ucs2String) {\n return new this(ucs2String, ucs2decode(ucs2String))\n }\n\n static fromCodepoints(codepoints) {\n return new this(ucs2encode(codepoints), codepoints)\n }\n\n constructor(ucs2String, codepoints) {\n super(...arguments)\n this.ucs2String = ucs2String\n this.codepoints = codepoints\n this.length = this.codepoints.length\n this.ucs2Length = this.ucs2String.length\n }\n\n offsetToUCS2Offset(offset) {\n return ucs2encode(this.codepoints.slice(0, Math.max(0, offset))).length\n }\n\n offsetFromUCS2Offset(ucs2Offset) {\n return ucs2decode(this.ucs2String.slice(0, Math.max(0, ucs2Offset))).length\n }\n\n slice() {\n return this.constructor.fromCodepoints(this.codepoints.slice(...arguments))\n }\n\n charAt(offset) {\n return this.slice(offset, offset + 1)\n }\n\n isEqualTo(value) {\n return this.constructor.box(value).ucs2String === this.ucs2String\n }\n\n toJSON() {\n return this.ucs2String\n }\n\n getCacheKey() {\n return this.ucs2String\n }\n\n toString() {\n return this.ucs2String\n }\n}\n\nconst hasArrayFrom = Array.from?.(\"\\ud83d\\udc7c\").length === 1\nconst hasStringCodePointAt = \" \".codePointAt?.(0) != null\nconst hasStringFromCodePoint = String.fromCodePoint?.(32, 128124) === \" \\ud83d\\udc7c\"\n\n// UCS-2 conversion helpers ported from Mathias Bynens' Punycode.js:\n// https://github.com/bestiejs/punycode.js#punycodeucs2\n\nlet ucs2decode, ucs2encode\n\n// Creates an array containing the numeric code points of each Unicode\n// character in the string. While JavaScript uses UCS-2 internally,\n// this function will convert a pair of surrogate halves (each of which\n// UCS-2 exposes as separate characters) into a single code point,\n// matching UTF-16.\nif (hasArrayFrom && hasStringCodePointAt) {\n ucs2decode = (string) => Array.from(string).map((char) => char.codePointAt(0))\n} else {\n ucs2decode = function(string) {\n const output = []\n let counter = 0\n const { length } = string\n\n while (counter < length) {\n let value = string.charCodeAt(counter++)\n if (0xd800 <= value && value <= 0xdbff && counter < length) {\n // high surrogate, and there is a next character\n const extra = string.charCodeAt(counter++)\n if ((extra & 0xfc00) === 0xdc00) {\n // low surrogate\n value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000\n } else {\n // unmatched surrogate; only append this code unit, in case the\n // next code unit is the high surrogate of a surrogate pair\n counter--\n }\n }\n output.push(value)\n }\n\n return output\n }\n}\n\n// Creates a string based on an array of numeric code points.\nif (hasStringFromCodePoint) {\n ucs2encode = (array) => String.fromCodePoint(...Array.from(array || []))\n} else {\n ucs2encode = function(array) {\n const characters = (() => {\n const result = []\n\n Array.from(array).forEach((value) => {\n let output = \"\"\n if (value > 0xffff) {\n value -= 0x10000\n output += String.fromCharCode(value >>> 10 & 0x3ff | 0xd800)\n value = 0xdc00 | value & 0x3ff\n }\n result.push(output + String.fromCharCode(value))\n })\n\n return result\n })()\n\n return characters.join(\"\")\n }\n}\n","/* eslint-disable\n id-length,\n no-useless-escape,\n*/\nimport { NON_BREAKING_SPACE, ZERO_WIDTH_SPACE } from \"trix/constants\"\nimport UTF16String from \"trix/core/utilities/utf16_string\"\n\nexport const normalizeSpaces = (string) =>\n string.replace(new RegExp(`${ZERO_WIDTH_SPACE}`, \"g\"), \"\").replace(new RegExp(`${NON_BREAKING_SPACE}`, \"g\"), \" \")\n\nexport const normalizeNewlines = (string) => string.replace(/\\r\\n/g, \"\\n\")\n\nexport const breakableWhitespacePattern = new RegExp(`[^\\\\S${NON_BREAKING_SPACE}]`)\n\nexport const squishBreakableWhitespace = (string) =>\n string\n // Replace all breakable whitespace characters with a space\n .replace(new RegExp(`${breakableWhitespacePattern.source}`, \"g\"), \" \")\n // Replace two or more spaces with a single space\n .replace(/\\ {2,}/g, \" \")\n\nexport const summarizeStringChange = function(oldString, newString) {\n let added, removed\n oldString = UTF16String.box(oldString)\n newString = UTF16String.box(newString)\n\n if (newString.length < oldString.length) {\n [ removed, added ] = utf16StringDifferences(oldString, newString)\n } else {\n [ added, removed ] = utf16StringDifferences(newString, oldString)\n }\n\n return { added, removed }\n}\n\nconst utf16StringDifferences = function(a, b) {\n if (a.isEqualTo(b)) {\n return [ \"\", \"\" ]\n }\n\n const diffA = utf16StringDifference(a, b)\n const { length } = diffA.utf16String\n\n let diffB\n\n if (length) {\n const { offset } = diffA\n const codepoints = a.codepoints.slice(0, offset).concat(a.codepoints.slice(offset + length))\n diffB = utf16StringDifference(b, UTF16String.fromCodepoints(codepoints))\n } else {\n diffB = utf16StringDifference(b, a)\n }\n\n return [ diffA.utf16String.toString(), diffB.utf16String.toString() ]\n}\n\nconst utf16StringDifference = function(a, b) {\n let leftIndex = 0\n let rightIndexA = a.length\n let rightIndexB = b.length\n\n while (leftIndex < rightIndexA && a.charAt(leftIndex).isEqualTo(b.charAt(leftIndex))) {\n leftIndex++\n }\n\n while (rightIndexA > leftIndex + 1 && a.charAt(rightIndexA - 1).isEqualTo(b.charAt(rightIndexB - 1))) {\n rightIndexA--\n rightIndexB--\n }\n\n return {\n utf16String: a.slice(leftIndex, rightIndexA),\n offset: leftIndex,\n }\n}\n","/* eslint-disable\n id-length,\n*/\nimport { installDefaultCSSForTagName } from \"trix/core/helpers\"\n\ninstallDefaultCSSForTagName(\"trix-inspector\", `\\\n%t {\n display: block;\n}\n\n%t {\n position: fixed;\n background: #fff;\n border: 1px solid #444;\n border-radius: 5px;\n padding: 10px;\n font-family: sans-serif;\n font-size: 12px;\n overflow: auto;\n word-wrap: break-word;\n}\n\n%t details {\n margin-bottom: 10px;\n}\n\n%t summary:focus {\n outline: none;\n}\n\n%t details .panel {\n padding: 10px;\n}\n\n%t .performance .metrics {\n margin: 0 0 5px 5px;\n}\n\n%t .selection .characters {\n margin-top: 10px;\n}\n\n%t .selection .character {\n display: inline-block;\n font-size: 8px;\n font-family: courier, monospace;\n line-height: 10px;\n vertical-align: middle;\n text-align: center;\n width: 10px;\n height: 10px;\n margin: 0 1px 1px 0;\n border: 1px solid #333;\n border-radius: 1px;\n background: #676666;\n color: #fff;\n}\n\n%t .selection .character.selected {\n background: yellow;\n color: #000;\n}\\\n`)\n\nexport default class TrixInspector extends HTMLElement {\n connectedCallback() {\n this.editorElement = document.querySelector(`trix-editor[trix-id='${this.dataset.trixId}']`)\n this.views = this.createViews()\n\n this.views.forEach((view) => {\n view.render()\n this.appendChild(view.element)\n })\n\n this.reposition()\n\n this.resizeHandler = this.reposition.bind(this)\n addEventListener(\"resize\", this.resizeHandler)\n }\n\n disconnectedCallback() {\n removeEventListener(\"resize\", this.resizeHandler)\n }\n\n createViews() {\n const views = Trix.Inspector.views.map((View) => new View(this.editorElement))\n\n return views.sort((a, b) => a.title.toLowerCase() > b.title.toLowerCase())\n }\n\n reposition() {\n const { top, right } = this.editorElement.getBoundingClientRect()\n\n this.style.top = `${top}px`\n this.style.left = `${right + 10}px`\n this.style.maxWidth = `${window.innerWidth - right - 40}px`\n this.style.maxHeight = `${window.innerHeight - top - 30}px`\n }\n}\n\nwindow.customElements.define(\"trix-inspector\", TrixInspector)\n","window.Trix.Inspector = {\n views: [],\n\n registerView(constructor) {\n return this.views.push(constructor)\n },\n\n install(editorElement) {\n this.editorElement = editorElement\n const element = document.createElement(\"trix-inspector\")\n element.dataset.trixId = this.editorElement.trixId\n return document.body.appendChild(element)\n },\n}\n","if (!window.JST) {\n window.JST = {}\n}\n\nwindow.JST[\"trix/inspector/templates/debug\"] = function() {\n return `\\\n

    \n \n

    \n\n

    \n \n

    \n\n

    \n \n

    \\\n`\n}\n","if (!window.JST) {\n window.JST = {}\n}\n\nwindow.JST[\"trix/inspector/templates/document\"] = function() {\n const details = this.document.getBlocks().map((block, index) => {\n const { text } = block\n const pieces = text.pieceList.toArray()\n\n return `
    \n \n Block ${block.id}, Index: ${index}\n \n
    \n Attributes: ${JSON.stringify(block.attributes)}\n
    \n\n
    \n
    \n Text: ${text.id}, Pieces: ${pieces.length}, Length: ${text.getLength()}\n
    \n
    \n ${piecePartials(pieces).join(\"\\n\")}\n
    \n
    \n
    `\n })\n\n return details.join(\"\\n\")\n}\n\nconst piecePartials = (pieces) =>\n pieces.map((piece, index) =>`
    \n
    \n Piece ${piece.id}, Index: ${index}\n
    \n
    \n Attributes: ${JSON.stringify(piece.attributes)}\n
    \n
    \n ${JSON.stringify(piece.toString())}\n
    \n
    `)\n","if (!window.JST) {\n window.JST = {}\n}\n\nwindow.JST[\"trix/inspector/templates/performance\"] = function() {\n return Object.keys(this.data).map((name) => {\n const data = this.data[name]\n return dataMetrics(name, data, this.round)\n }).join(\"\\n\")\n}\n\nconst dataMetrics = function(name, data, round) {\n let item = `${name} (${data.calls})
    `\n\n if (data.calls > 0) {\n item += `
    \n Mean: ${round(data.mean)}ms
    \n Max: ${round(data.max)}ms
    \n Last: ${round(data.last)}ms\n
    `\n\n return item\n }\n}\n","if (!window.JST) {\n window.JST = {}\n}\n\nwindow.JST[\"trix/inspector/templates/render\"] = function() {\n return `\\\nSyncs: ${this.syncCount}\\\n`\n}\n","if (!window.JST) {\n window.JST = {}\n}\n\nwindow.JST[\"trix/inspector/templates/selection\"] = function() {\n return `\nLocation range: [${this.locationRange[0].index}:${this.locationRange[0].offset}, ${this.locationRange[1].index}:${\n this.locationRange[1].offset\n }]\n\n${charSpans(this.characters).join(\"\\n\")}\\\n`\n}\n\nconst charSpans = (characters) =>\n Array.from(characters).map(\n (char) => `${char.string}`\n )\n","if (!window.JST) {\n window.JST = {}\n}\n\nwindow.JST[\"trix/inspector/templates/undo\"] = function() {\n return `\\\n

    Undo stack

    \n
      \n ${entryList(this.undoEntries)}\n
    \n\n

    Redo stack

    \n
      \n ${entryList(this.redoEntries)}\n
    \\\n`\n}\n\nconst entryList = (entries) =>\n entries.map((entry) =>\n `
  • ${entry.description} ${JSON.stringify({\n selectedRange: entry.snapshot.selectedRange,\n context: entry.context,\n })}
  • `)\n","const KEY_EVENTS = \"keydown keypress input\".split(\" \")\nconst COMPOSITION_EVENTS = \"compositionstart compositionupdate compositionend textInput\".split(\" \")\nconst OBSERVER_OPTIONS = {\n attributes: true,\n childList: true,\n characterData: true,\n characterDataOldValue: true,\n subtree: true,\n}\n\nexport default class ControlElement {\n constructor(editorElement) {\n this.didMutate = this.didMutate.bind(this)\n this.editorElement = editorElement\n this.install()\n }\n\n install() {\n this.createElement()\n this.logInputEvents()\n this.logMutations()\n }\n\n uninstall() {\n this.observer.disconnect()\n this.element.parentNode.removeChild(this.element)\n }\n\n createElement() {\n this.element = document.createElement(\"div\")\n this.element.setAttribute(\"contenteditable\", \"\")\n this.element.style.width = getComputedStyle(this.editorElement).width\n this.element.style.minHeight = \"50px\"\n this.element.style.border = \"1px solid green\"\n this.editorElement.parentNode.insertBefore(this.element, this.editorElement.nextSibling)\n }\n\n logInputEvents() {\n KEY_EVENTS.forEach((eventName) => {\n this.element.addEventListener(eventName, (event) => console.log(`${event.type}: keyCode = ${event.keyCode}`))\n })\n\n COMPOSITION_EVENTS.forEach((eventName) => {\n this.element.addEventListener(eventName, (event) =>\n console.log(`${event.type}: data = ${JSON.stringify(event.data)}`)\n )\n })\n }\n\n logMutations() {\n this.observer = new window.MutationObserver(this.didMutate)\n this.observer.observe(this.element, OBSERVER_OPTIONS)\n }\n\n didMutate(mutations) {\n console.log(`Mutations (${mutations.length}):`)\n for (let index = 0; index < mutations.length; index++) {\n const mutation = mutations[index]\n console.log(` ${index + 1}. ${mutation.type}:`)\n switch (mutation.type) {\n case \"characterData\":\n console.log(` oldValue = ${JSON.stringify(mutation.oldValue)}, newValue = ${JSON.stringify(mutation.target.data)}`)\n break\n case \"childList\":\n Array.from(mutation.addedNodes).forEach((node) => {\n console.log(` node added ${inspectNode(node)}`)\n })\n\n Array.from(mutation.removedNodes).forEach((node) => {\n console.log(` node removed ${inspectNode(node)}`)\n })\n }\n }\n }\n}\n\nconst inspectNode = function(node) {\n if (node.data) {\n return JSON.stringify(node.data)\n } else {\n return JSON.stringify(node.outerHTML)\n }\n}\n","/* eslint-disable\n no-undef,\n*/\nimport { handleEvent } from \"trix/core/helpers\"\n\nexport default class View {\n constructor(editorElement) {\n this.editorElement = editorElement\n this.editorController = this.editorElement.editorController\n this.editor = this.editorElement.editor\n this.compositionController = this.editorController.compositionController\n this.composition = this.editorController.composition\n\n this.element = document.createElement(\"details\")\n if (this.getSetting(\"open\") === \"true\") {\n this.element.open = true\n }\n this.element.classList.add(this.constructor.template)\n\n this.titleElement = document.createElement(\"summary\")\n this.element.appendChild(this.titleElement)\n\n this.panelElement = document.createElement(\"div\")\n this.panelElement.classList.add(\"panel\")\n this.element.appendChild(this.panelElement)\n\n this.element.addEventListener(\"toggle\", (event) => {\n if (event.target === this.element) {\n return this.didToggle()\n }\n })\n\n if (this.events) {\n this.installEventHandlers()\n }\n }\n\n installEventHandlers() {\n for (const eventName in this.events) {\n const handler = this.events[eventName]\n const callback = (event) => {\n requestAnimationFrame(() => {\n handler.call(this, event)\n })\n }\n\n handleEvent(eventName, { onElement: this.editorElement, withCallback: callback })\n }\n }\n\n didToggle(event) {\n this.saveSetting(\"open\", this.isOpen())\n return this.render()\n }\n\n isOpen() {\n return this.element.hasAttribute(\"open\")\n }\n\n getTitle() {\n return this.title || \"\"\n }\n\n render() {\n this.renderTitle()\n if (this.isOpen()) {\n this.panelElement.innerHTML = JST[`trix/inspector/templates/${this.constructor.template}`].apply(this)\n }\n }\n\n renderTitle() {\n this.titleElement.innerHTML = this.getTitle()\n }\n\n getSetting(key) {\n key = this.getSettingsKey(key)\n return window.sessionStorage?.[key]\n }\n\n saveSetting(key, value) {\n key = this.getSettingsKey(key)\n if (window.sessionStorage) {\n window.sessionStorage[key] = value\n }\n }\n\n getSettingsKey(key) {\n return `trix/inspector/${this.template}/${key}`\n }\n\n get title() {\n return this.constructor.title\n }\n\n get template() {\n return this.constructor.template\n }\n\n get events() {\n return this.constructor.events\n }\n}\n","import View from \"inspector/view\"\n\nimport { handleEvent } from \"trix/core/helpers\"\n\nclass DebugView extends View {\n static title = \"Debug\"\n static template = \"debug\"\n\n constructor() {\n super(...arguments)\n this.didToggleViewCaching = this.didToggleViewCaching.bind(this)\n this.didClickRenderButton = this.didClickRenderButton.bind(this)\n this.didClickParseButton = this.didClickParseButton.bind(this)\n this.didToggleControlElement = this.didToggleControlElement.bind(this)\n\n handleEvent(\"change\", {\n onElement: this.element,\n matchingSelector: \"input[name=viewCaching]\",\n withCallback: this.didToggleViewCaching,\n })\n handleEvent(\"click\", {\n onElement: this.element,\n matchingSelector: \"button[data-action=render]\",\n withCallback: this.didClickRenderButton,\n })\n handleEvent(\"click\", {\n onElement: this.element,\n matchingSelector: \"button[data-action=parse]\",\n withCallback: this.didClickParseButton,\n })\n handleEvent(\"change\", {\n onElement: this.element,\n matchingSelector: \"input[name=controlElement]\",\n withCallback: this.didToggleControlElement,\n })\n }\n\n didToggleViewCaching({ target }) {\n if (target.checked) {\n return this.compositionController.enableViewCaching()\n } else {\n return this.compositionController.disableViewCaching()\n }\n }\n\n didClickRenderButton() {\n return this.editorController.render()\n }\n\n didClickParseButton() {\n return this.editorController.reparse()\n }\n\n didToggleControlElement({ target }) {\n if (target.checked) {\n this.control = new Trix.Inspector.ControlElement(this.editorElement)\n } else {\n this.control?.uninstall()\n this.control = null\n }\n }\n}\n\nTrix.Inspector.registerView(DebugView)\n","import View from \"inspector/view\"\n\nclass DocumentView extends View {\n static title = \"Document\"\n static template = \"document\"\n static events = {\n \"trix-change\": function() {\n return this.render()\n },\n }\n\n render() {\n this.document = this.editor.getDocument()\n return super.render(...arguments)\n }\n}\n\nTrix.Inspector.registerView(DocumentView)\n","import View from \"inspector/view\"\nconst now = window.performance?.now ? () => performance.now() : () => new Date().getTime()\n\nclass PerformanceView extends View {\n static title = \"Performance\"\n static template = \"performance\"\n\n constructor() {\n super(...arguments)\n this.documentView = this.compositionController.documentView\n\n this.data = {}\n this.track(\"documentView.render\")\n this.track(\"documentView.sync\")\n this.track(\"documentView.garbageCollectCachedViews\")\n this.track(\"composition.replaceHTML\")\n\n this.render()\n }\n\n track(methodPath) {\n this.data[methodPath] = { calls: 0, total: 0, mean: 0, max: 0, last: 0 }\n const parts = methodPath.split(\".\")\n const propertyNames = parts.slice(0, parts.length - 1)\n const methodName = parts[parts.length - 1]\n\n let object = this\n\n propertyNames.forEach((propertyName) => {\n object = object[propertyName]\n })\n\n const original = object[methodName]\n\n object[methodName] = function() {\n const started = now()\n const result = original.apply(object, arguments)\n const timing = now() - started\n this.record(methodPath, timing)\n return result\n }.bind(this)\n }\n\n record(methodPath, timing) {\n const data = this.data[methodPath]\n data.calls += 1\n data.total += timing\n data.mean = data.total / data.calls\n if (timing > data.max) {\n data.max = timing\n }\n data.last = timing\n return this.render()\n }\n\n round(ms) {\n return Math.round(ms * 1000) / 1000\n }\n}\n\nTrix.Inspector.registerView(PerformanceView)\n","import View from \"inspector/view\"\n\nexport default class RenderView extends View {\n static title = \"Renders\"\n static template = \"render\"\n static events = {\n \"trix-render\": function() {\n this.renderCount++\n return this.render()\n },\n\n \"trix-sync\": function() {\n this.syncCount++\n return this.render()\n },\n }\n\n constructor() {\n super(...arguments)\n this.renderCount = 0\n this.syncCount = 0\n }\n\n getTitle() {\n return `${this.title} (${this.renderCount})`\n }\n}\n\nTrix.Inspector.registerView(RenderView)\n","import View from \"inspector/view\"\nimport UTF16String from \"trix/core/utilities/utf16_string\"\n\nclass SelectionView extends View {\n static title = \"Selection\"\n static template = \"selection\"\n static events = {\n \"trix-selection-change\": function() {\n return this.render()\n },\n \"trix-render\": function() {\n return this.render()\n },\n }\n\n render() {\n this.document = this.editor.getDocument()\n this.range = this.editor.getSelectedRange()\n this.locationRange = this.composition.getLocationRange()\n this.characters = this.getCharacters()\n return super.render(...arguments)\n }\n\n getCharacters() {\n const chars = []\n const utf16string = UTF16String.box(this.document.toString())\n const rangeIsExpanded = this.range[0] !== this.range[1]\n let position = 0\n while (position < utf16string.length) {\n let string = utf16string.charAt(position).toString()\n if (string === \"\\n\") {\n string = \"⏎\"\n }\n const selected = rangeIsExpanded && position >= this.range[0] && position < this.range[1]\n chars.push({ string, selected })\n position++\n }\n return chars\n }\n\n getTitle() {\n return `${this.title} (${this.range.join()})`\n }\n}\n\nTrix.Inspector.registerView(SelectionView)\n","import View from \"inspector/view\"\n\nclass UndoView extends View {\n static title = \"Undo\"\n static template = \"undo\"\n static events = {\n \"trix-change\": function() {\n return this.render()\n },\n }\n\n render() {\n this.undoEntries = this.editor.undoManager.undoEntries\n this.redoEntries = this.editor.undoManager.redoEntries\n return super.render(...arguments)\n }\n}\n\nTrix.Inspector.registerView(UndoView)\n"],"names":["arraysAreEqual","a","b","length","index","value","arrayStartsWith","slice","spliceArray","array","result","args","splice","summarizeArrayChange","oldArray","newArray","added","removed","existingValues","Set","forEach","add","currentValues","has","push","attachmentSelector","attachments","preview","presentation","caption","name","size","file","attributes","default","tagName","parse","quote","nestable","heading1","terminal","breakOnReturn","group","code","text","plaintext","bulletList","bullet","listAttribute","test","element","parentNode","numberList","number","attachmentGallery","exclusive","toLowerCase","composesExistingText","navigator","userAgent","forcesObjectResizing","supportsInputEvents","InputEvent","property","prototype","attachment","attachmentCaption","attachmentCaptionEditor","attachmentMetadata","attachmentMetadataContainer","attachmentName","attachmentProgress","attachmentSize","attachmentToolbar","attachFiles","bold","bullets","byte","bytes","captionPlaceholder","indent","italic","link","numbers","outdent","redo","remove","strike","undo","unlink","url","urlPlaceholder","GB","KB","MB","PB","TB","sizes","lang","prefix","precision","formatter","base","exp","Math","floor","log","humanSize","pow","string","toFixed","withoutInsignificantZeros","replace","input","level2Enabled","getLevel","browser","inheritable","parser","style","window","getComputedStyle","fontWeight","fontStyle","href","groupTagName","matchingSelector","closest","getAttribute","frozen","backgroundColor","getDefaultHTML","undoInterval","config","blockAttributes","css","fileSize","keyNames","textAttributes","toolbar","ZERO_WIDTH_SPACE","NON_BREAKING_SPACE","OBJECT_REPLACEMENT_CHARACTER","extend","properties","key","html","document","documentElement","match","matches","handleEvent","eventName","onElement","withCallback","inPhase","preventDefault","times","selector","useCapture","handler","event","destroy","target","findClosestElementFromNode","call","removeEventListener","addEventListener","handleEventOnce","options","triggerEvent","bubbles","cancelable","createEvent","initEvent","dispatchEvent","elementMatchesSelector","nodeType","node","untilNode","Node","ELEMENT_NODE","findInnerElement","firstElementChild","innerElementIsActive","activeElement","elementContainsNode","findNodeFromContainerAndOffset","container","offset","TEXT_NODE","firstChild","childNodes","item","findElementFromContainerAndOffset","findChildIndexOfNode","childIndex","previousSibling","removeNode","removeChild","walkTree","tree","onlyNodesOfType","usingFilter","expandEntityReferences","whatToShow","NodeFilter","SHOW_ELEMENT","SHOW_TEXT","SHOW_COMMENT","SHOW_ALL","createTreeWalker","makeElement","tag","createElement","editable","contenteditable","setAttribute","data","dataset","className","split","classList","textContent","concat","childNode","appendChild","blockTagNames","undefined","getBlockTagNames","nodeIsBlockContainer","nodeIsBlockStartComment","nodeProbablyIsBlockContainer","includes","nodeIsBlockStart","strict","nodeIsCommentNode","COMMENT_NODE","nodeIsCursorTarget","nodeIsTextNode","trixCursorTarget","nodeIsAttachmentElement","nodeIsEmptyTextNode","RTL_PATTERN","getDirection","dir","dirName","form","supportsDirName","FormData","error","supportsDirSelector","get","char","trim","charAt","allAttributeNames","blockAttributeNames","textAttributeNames","listAttributeNames","getAllAttributeNames","getTextAttributeNames","getBlockAttributeNames","getBlockConfig","attributeName","Object","keys","getTextConfig","getListAttributeNames","installDefaultCSSForTagName","defaultCSS","styleElement","insertStyleElementForTagName","nonce","getCSPNonce","head","insertBefore","getMetaElement","querySelector","testTransferData","dataTransferIsPlainText","dataTransfer","getData","body","DOMParser","parseFromString","dataTransferIsWritable","setData","keyEventIsKeyboardCommand","platform","metaKey","ctrlKey","defer","fn","setTimeout","copyObject","object","objectsAreEqual","normalizeRange","range","Array","isArray","copyValue","rangeIsCollapsed","start","end","rangeValuesAreEqual","rangesAreEqual","leftRange","rightRange","leftStart","leftEnd","rightStart","rightEnd","left","right","BasicObject","proxyMethod","expression","toMethod","toProperty","optional","parseProxyMethodExpression","subject","apply","arguments","proxyMethodExpressionPattern","Error","Function","RegExp","SelectionChangeObserver","constructor","update","bind","run","selectionManagers","started","stop","registerSelectionManager","selectionManager","unregisterSelectionManager","filter","s","notifySelectionManagersOfSelectionChange","map","selectionDidChange","domRange","getDOMRange","domRangesAreEqual","reset","requestAnimationFrame","startContainer","startOffset","endContainer","endOffset","selectionChangeObserver","getDOMSelection","selection","getSelection","rangeCount","getRangeAt","domRangeIsPrivate","setDOMRange","removeAllRanges","addRange","nodeIsPrivate","getPrototypeOf","UTF16String","box","fromUCS2String","toString","ucs2String","ucs2decode","fromCodepoints","codepoints","ucs2encode","ucs2Length","offsetToUCS2Offset","max","offsetFromUCS2Offset","ucs2Offset","isEqualTo","toJSON","getCacheKey","hasArrayFrom","from","hasStringCodePointAt","codePointAt","hasStringFromCodePoint","String","fromCodePoint","output","counter","charCodeAt","extra","characters","fromCharCode","join","normalizeSpaces","normalizeNewlines","breakableWhitespacePattern","squishBreakableWhitespace","source","summarizeStringChange","oldString","newString","utf16StringDifferences","diffA","utf16StringDifference","utf16String","diffB","leftIndex","rightIndexA","rightIndexB","TrixInspector","HTMLElement","connectedCallback","editorElement","trixId","views","createViews","view","render","reposition","resizeHandler","disconnectedCallback","Trix","Inspector","View","sort","title","top","getBoundingClientRect","maxWidth","innerWidth","maxHeight","innerHeight","customElements","define","registerView","install","JST","compositionController","isViewCachingEnabled","details","getBlocks","block","pieces","pieceList","toArray","id","JSON","stringify","getLength","piecePartials","piece","dataMetrics","round","calls","mean","last","syncCount","locationRange","charSpans","selected","entryList","undoEntries","redoEntries","entries","entry","description","selectedRange","snapshot","context","KEY_EVENTS","COMPOSITION_EVENTS","OBSERVER_OPTIONS","childList","characterData","characterDataOldValue","subtree","ControlElement","didMutate","logInputEvents","logMutations","uninstall","observer","disconnect","width","minHeight","border","nextSibling","console","type","keyCode","MutationObserver","observe","mutations","mutation","oldValue","addedNodes","inspectNode","removedNodes","outerHTML","editorController","editor","composition","getSetting","open","template","titleElement","panelElement","didToggle","events","installEventHandlers","callback","saveSetting","isOpen","hasAttribute","getTitle","renderTitle","innerHTML","getSettingsKey","sessionStorage","DebugView","didToggleViewCaching","didClickRenderButton","didClickParseButton","didToggleControlElement","checked","enableViewCaching","disableViewCaching","reparse","control","DocumentView","getDocument","now","performance","Date","getTime","PerformanceView","documentView","track","methodPath","total","parts","propertyNames","methodName","propertyName","original","timing","record","ms","RenderView","renderCount","SelectionView","getSelectedRange","getLocationRange","getCharacters","chars","utf16string","rangeIsExpanded","position","UndoView","undoManager"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"} \ No newline at end of file diff --git a/dist/test.js b/dist/test.js new file mode 100644 index 00000000..8fbfd30a --- /dev/null +++ b/dist/test.js @@ -0,0 +1,24894 @@ +/* +Trix 2.0.0-alpha +Copyright © 2022 Basecamp, LLC + */ +var name = "trix"; +var version = "2.0.0-alpha"; +var description = "A rich text editor for everyday writing"; +var main = "dist/trix.umd.js"; +var module = "dist/trix.js"; +var style = "dist/trix.css"; +var files = [ + "dist/*.css", + "dist/*.js" +]; +var repository = { + type: "git", + url: "git+https://github.com/basecamp/trix.git" +}; +var keywords = [ + "rich text", + "wysiwyg", + "editor" +]; +var author = "Basecamp, LLC"; +var license = "MIT"; +var bugs = { + url: "https://github.com/basecamp/trix/issues" +}; +var homepage = "https://trix-editor.org/"; +var devDependencies = { + "@babel/core": "^7.16.0", + "@babel/preset-env": "^7.16.4", + "@rollup/plugin-babel": "^5.3.0", + "@rollup/plugin-json": "^4.1.0", + "babel-eslint": "^10.1.0", + eslint: "^7.32.0", + esm: "^3.2.25", + karma: "5.0.2", + "karma-chrome-launcher": "3.1.0", + "karma-qunit": "^4.1.2", + "karma-sauce-launcher": "^4.3.6", + "node-sass": "^6.0.1", + qunit: "2.9.3", + rangy: "^1.3.0", + rollup: "^2.56.3", + "rollup-plugin-commonjs": "^10.1.0", + "rollup-plugin-includepaths": "^0.2.4", + "rollup-plugin-node-resolve": "^5.2.0", + "rollup-plugin-terser": "^7.0.2", + svgo: "^2.8.0" +}; +var scripts = { + "build-css": "node-sass --functions=./assets/trix/stylesheets/functions assets/trix.scss dist/trix.css", + "build-js": "rollup -c", + "build-assets": "cp -f assets/*.html dist/", + build: "yarn run build-js && yarn run build-css && yarn run build-assets", + watch: "rollup -c -w", + lint: "eslint .", + pretest: "yarn run lint && yarn run build-js", + test: "karma start", + preversion: "yarn test", + version: "git add -A -f dist/" +}; +var dependencies = { +}; +var _package = { + name: name, + version: version, + description: description, + main: main, + module: module, + style: style, + files: files, + repository: repository, + keywords: keywords, + author: author, + license: license, + bugs: bugs, + homepage: homepage, + devDependencies: devDependencies, + scripts: scripts, + dependencies: dependencies +}; + +const attachmentSelector = "[data-trix-attachment]"; +const attachments = { + preview: { + presentation: "gallery", + caption: { + name: true, + size: true + } + }, + file: { + caption: { + size: true + } + } +}; + +const attributes = { + default: { + tagName: "div", + parse: false + }, + quote: { + tagName: "blockquote", + nestable: true + }, + heading1: { + tagName: "h1", + terminal: true, + breakOnReturn: true, + group: false + }, + code: { + tagName: "pre", + terminal: true, + text: { + plaintext: true + } + }, + bulletList: { + tagName: "ul", + parse: false + }, + bullet: { + tagName: "li", + listAttribute: "bulletList", + group: false, + nestable: true, + + test(element) { + return tagName$1(element.parentNode) === attributes[this.listAttribute].tagName; + } + + }, + numberList: { + tagName: "ol", + parse: false + }, + number: { + tagName: "li", + listAttribute: "numberList", + group: false, + nestable: true, + + test(element) { + return tagName$1(element.parentNode) === attributes[this.listAttribute].tagName; + } + + }, + attachmentGallery: { + tagName: "div", + exclusive: true, + terminal: true, + parse: false, + group: false + } +}; + +const tagName$1 = element => { + var _element$tagName; + + return element === null || element === void 0 ? void 0 : (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase(); +}; + +var browser$1 = { + // Android emits composition events when moving the cursor through existing text + // Introduced in Chrome 65: https://bugs.chromium.org/p/chromium/issues/detail?id=764439#c9 + composesExistingText: /Android.*Chrome/.test(navigator.userAgent), + // IE 11 activates resizing handles on editable elements that have "layout" + forcesObjectResizing: /Trident.*rv:11/.test(navigator.userAgent), + // https://www.w3.org/TR/input-events-1/ + https://www.w3.org/TR/input-events-2/ + supportsInputEvents: function () { + if (typeof InputEvent === "undefined") { + return false; + } + + for (const property of ["data", "getTargetRanges", "inputType"]) { + if (!(property in InputEvent.prototype)) { + return false; + } + } + + return true; + }() +}; + +var css$4 = { + attachment: "attachment", + attachmentCaption: "attachment__caption", + attachmentCaptionEditor: "attachment__caption-editor", + attachmentMetadata: "attachment__metadata", + attachmentMetadataContainer: "attachment__metadata-container", + attachmentName: "attachment__name", + attachmentProgress: "attachment__progress", + attachmentSize: "attachment__size", + attachmentToolbar: "attachment__toolbar", + attachmentGallery: "attachment-gallery" +}; + +var lang$1 = { + attachFiles: "Attach Files", + bold: "Bold", + bullets: "Bullets", + byte: "Byte", + bytes: "Bytes", + captionPlaceholder: "Add a caption…", + code: "Code", + heading1: "Heading", + indent: "Increase Level", + italic: "Italic", + link: "Link", + numbers: "Numbers", + outdent: "Decrease Level", + quote: "Quote", + redo: "Redo", + remove: "Remove", + strike: "Strikethrough", + undo: "Undo", + unlink: "Unlink", + url: "URL", + urlPlaceholder: "Enter a URL…", + GB: "GB", + KB: "KB", + MB: "MB", + PB: "PB", + TB: "TB" +}; + +/* eslint-disable + no-case-declarations, +*/ +const sizes = [lang$1.bytes, lang$1.KB, lang$1.MB, lang$1.GB, lang$1.TB, lang$1.PB]; +var fileSize = { + prefix: "IEC", + precision: 2, + + formatter(number) { + switch (number) { + case 0: + return "0 ".concat(lang$1.bytes); + + case 1: + return "1 ".concat(lang$1.byte); + + default: + let base; + + if (this.prefix === "SI") { + base = 1000; + } else if (this.prefix === "IEC") { + base = 1024; + } + + const exp = Math.floor(Math.log(number) / Math.log(base)); + const humanSize = number / Math.pow(base, exp); + const string = humanSize.toFixed(this.precision); + const withoutInsignificantZeros = string.replace(/0*$/, "").replace(/\.$/, ""); + return "".concat(withoutInsignificantZeros, " ").concat(sizes[exp]); + } + } + +}; + +const input = { + level2Enabled: true, + + getLevel() { + if (this.level2Enabled && browser$1.supportsInputEvents) { + return 2; + } else { + return 0; + } + } + +}; + +var keyNames$2 = { + 8: "backspace", + 9: "tab", + 13: "return", + 27: "escape", + 37: "left", + 39: "right", + 46: "delete", + 68: "d", + 72: "h", + 79: "o" +}; + +var textAttributes = { + bold: { + tagName: "strong", + inheritable: true, + + parser(element) { + const style = window.getComputedStyle(element); + return style.fontWeight === "bold" || style.fontWeight >= 600; + } + + }, + italic: { + tagName: "em", + inheritable: true, + + parser(element) { + const style = window.getComputedStyle(element); + return style.fontStyle === "italic"; + } + + }, + href: { + groupTagName: "a", + + parser(element) { + const matchingSelector = "a:not(".concat(attachmentSelector, ")"); + const link = element.closest(matchingSelector); + + if (link) { + return link.getAttribute("href"); + } + } + + }, + strike: { + tagName: "del", + inheritable: true + }, + frozen: { + style: { + backgroundColor: "highlight" + } + } +}; + +var toolbar = { + getDefaultHTML() { + return "
    \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n\n \n \n \n\n \n\n \n \n \n \n
    \n\n
    \n
    \n \n
    \n
    "); + } + +}; + +const undoInterval = 5000; + +const config = { + attachments, + blockAttributes: attributes, + browser: browser$1, + css: css$4, + fileSize, + input, + keyNames: keyNames$2, + lang: lang$1, + textAttributes, + toolbar, + undoInterval +}; + +const Trix = { + VERSION: version, + config +}; +window.Trix = Trix; + +class BasicObject { + static proxyMethod(expression) { + const { + name, + toMethod, + toProperty, + optional + } = parseProxyMethodExpression(expression); + + this.prototype[name] = function () { + let subject; + let object; + + if (toMethod) { + if (optional) { + var _this$toMethod; + + object = (_this$toMethod = this[toMethod]) === null || _this$toMethod === void 0 ? void 0 : _this$toMethod.call(this); + } else { + object = this[toMethod](); + } + } else if (toProperty) { + object = this[toProperty]; + } + + if (optional) { + var _object; + + subject = (_object = object) === null || _object === void 0 ? void 0 : _object[name]; + + if (subject) { + return apply.call(subject, object, arguments); + } + } else { + subject = object[name]; + return apply.call(subject, object, arguments); + } + }; + } + +} + +const parseProxyMethodExpression = function (expression) { + const match = expression.match(proxyMethodExpressionPattern); + + if (!match) { + throw new Error("can't parse @proxyMethod expression: ".concat(expression)); + } + + const args = { + name: match[4] + }; + + if (match[2] != null) { + args.toMethod = match[1]; + } else { + args.toProperty = match[1]; + } + + if (match[3] != null) { + args.optional = true; + } + + return args; +}; + +const { + apply +} = Function.prototype; +const proxyMethodExpressionPattern = new RegExp("\ +^\ +(.+?)\ +(\\(\\))?\ +(\\?)?\ +\\.\ +(.+?)\ +$\ +"); + +var _Array$from, _$codePointAt$1, _$1, _String$fromCodePoint; +class UTF16String extends BasicObject { + static box() { + let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + + if (value instanceof this) { + return value; + } else { + return this.fromUCS2String(value === null || value === void 0 ? void 0 : value.toString()); + } + } + + static fromUCS2String(ucs2String) { + return new this(ucs2String, ucs2decode(ucs2String)); + } + + static fromCodepoints(codepoints) { + return new this(ucs2encode(codepoints), codepoints); + } + + constructor(ucs2String, codepoints) { + super(...arguments); + this.ucs2String = ucs2String; + this.codepoints = codepoints; + this.length = this.codepoints.length; + this.ucs2Length = this.ucs2String.length; + } + + offsetToUCS2Offset(offset) { + return ucs2encode(this.codepoints.slice(0, Math.max(0, offset))).length; + } + + offsetFromUCS2Offset(ucs2Offset) { + return ucs2decode(this.ucs2String.slice(0, Math.max(0, ucs2Offset))).length; + } + + slice() { + return this.constructor.fromCodepoints(this.codepoints.slice(...arguments)); + } + + charAt(offset) { + return this.slice(offset, offset + 1); + } + + isEqualTo(value) { + return this.constructor.box(value).ucs2String === this.ucs2String; + } + + toJSON() { + return this.ucs2String; + } + + getCacheKey() { + return this.ucs2String; + } + + toString() { + return this.ucs2String; + } + +} +const hasArrayFrom = ((_Array$from = Array.from) === null || _Array$from === void 0 ? void 0 : _Array$from.call(Array, "\ud83d\udc7c").length) === 1; +const hasStringCodePointAt$1 = ((_$codePointAt$1 = (_$1 = " ").codePointAt) === null || _$codePointAt$1 === void 0 ? void 0 : _$codePointAt$1.call(_$1, 0)) != null; +const hasStringFromCodePoint = ((_String$fromCodePoint = String.fromCodePoint) === null || _String$fromCodePoint === void 0 ? void 0 : _String$fromCodePoint.call(String, 32, 128124)) === " \ud83d\udc7c"; // UCS-2 conversion helpers ported from Mathias Bynens' Punycode.js: +// https://github.com/bestiejs/punycode.js#punycodeucs2 + +let ucs2decode, ucs2encode; // Creates an array containing the numeric code points of each Unicode +// character in the string. While JavaScript uses UCS-2 internally, +// this function will convert a pair of surrogate halves (each of which +// UCS-2 exposes as separate characters) into a single code point, +// matching UTF-16. + +if (hasArrayFrom && hasStringCodePointAt$1) { + ucs2decode = string => Array.from(string).map(char => char.codePointAt(0)); +} else { + ucs2decode = function (string) { + const output = []; + let counter = 0; + const { + length + } = string; + + while (counter < length) { + let value = string.charCodeAt(counter++); + + if (0xd800 <= value && value <= 0xdbff && counter < length) { + // high surrogate, and there is a next character + const extra = string.charCodeAt(counter++); + + if ((extra & 0xfc00) === 0xdc00) { + // low surrogate + value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; + } else { + // unmatched surrogate; only append this code unit, in case the + // next code unit is the high surrogate of a surrogate pair + counter--; + } + } + + output.push(value); + } + + return output; + }; +} // Creates a string based on an array of numeric code points. + + +if (hasStringFromCodePoint) { + ucs2encode = array => String.fromCodePoint(...Array.from(array || [])); +} else { + ucs2encode = function (array) { + const characters = (() => { + const result = []; + Array.from(array).forEach(value => { + let output = ""; + + if (value > 0xffff) { + value -= 0x10000; + output += String.fromCharCode(value >>> 10 & 0x3ff | 0xd800); + value = 0xdc00 | value & 0x3ff; + } + + result.push(output + String.fromCharCode(value)); + }); + return result; + })(); + + return characters.join(""); + }; +} + +let id$2 = 0; +class TrixObject extends BasicObject { + static fromJSONString(jsonString) { + return this.fromJSON(JSON.parse(jsonString)); + } + + constructor() { + super(...arguments); + this.id = ++id$2; + } + + hasSameConstructorAs(object) { + return this.constructor === (object === null || object === void 0 ? void 0 : object.constructor); + } + + isEqualTo(object) { + return this === object; + } + + inspect() { + const parts = []; + const contents = this.contentsForInspection() || {}; + + for (const key in contents) { + const value = contents[key]; + parts.push("".concat(key, "=").concat(value)); + } + + return "#<".concat(this.constructor.name, ":").concat(this.id).concat(parts.length ? " ".concat(parts.join(", ")) : "", ">"); + } + + contentsForInspection() {} + + toJSONString() { + return JSON.stringify(this); + } + + toUTF16String() { + return UTF16String.box(this); + } + + getCacheKey() { + return this.id.toString(); + } + +} + +/* eslint-disable + id-length, +*/ +const arraysAreEqual = function () { + let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + + if (a.length !== b.length) { + return false; + } + + for (let index = 0; index < a.length; index++) { + const value = a[index]; + + if (value !== b[index]) { + return false; + } + } + + return true; +}; +const arrayStartsWith = function () { + let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + return arraysAreEqual(a.slice(0, b.length), b); +}; +const spliceArray = function (array) { + const result = array.slice(0); + + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + result.splice(...args); + return result; +}; +const summarizeArrayChange = function () { + let oldArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let newArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + const added = []; + const removed = []; + const existingValues = new Set(); + oldArray.forEach(value => { + existingValues.add(value); + }); + const currentValues = new Set(); + newArray.forEach(value => { + currentValues.add(value); + + if (!existingValues.has(value)) { + added.push(value); + } + }); + oldArray.forEach(value => { + if (!currentValues.has(value)) { + removed.push(value); + } + }); + return { + added, + removed + }; +}; + +const ZERO_WIDTH_SPACE = "\uFEFF"; +const NON_BREAKING_SPACE = "\u00A0"; +const OBJECT_REPLACEMENT_CHARACTER = "\uFFFC"; + +const extend$1 = function (properties) { + for (const key in properties) { + const value = properties[key]; + this[key] = value; + } + + return this; +}; + +const html = document.documentElement; +const match = html.matches; +const handleEvent = function (eventName) { + let { + onElement, + matchingSelector, + withCallback, + inPhase, + preventDefault, + times + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const element = onElement ? onElement : html; + const selector = matchingSelector; + const useCapture = inPhase === "capturing"; + + const handler = function (event) { + if (times != null && --times === 0) { + handler.destroy(); + } + + const target = findClosestElementFromNode(event.target, { + matchingSelector: selector + }); + + if (target != null) { + withCallback === null || withCallback === void 0 ? void 0 : withCallback.call(target, event, target); + + if (preventDefault) { + event.preventDefault(); + } + } + }; + + handler.destroy = () => element.removeEventListener(eventName, handler, useCapture); + + element.addEventListener(eventName, handler, useCapture); + return handler; +}; +const handleEventOnce = function (eventName) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + options.times = 1; + return handleEvent(eventName, options); +}; +const triggerEvent$1 = function (eventName) { + let { + onElement, + bubbles, + cancelable, + attributes + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const element = onElement != null ? onElement : html; + bubbles = bubbles !== false; + cancelable = cancelable !== false; + const event = document.createEvent("Events"); + event.initEvent(eventName, bubbles, cancelable); + + if (attributes != null) { + extend$1.call(event, attributes); + } + + return element.dispatchEvent(event); +}; +const elementMatchesSelector = function (element, selector) { + if ((element === null || element === void 0 ? void 0 : element.nodeType) === 1) { + return match.call(element, selector); + } +}; +const findClosestElementFromNode = function (node) { + let { + matchingSelector, + untilNode + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + while (node && node.nodeType !== Node.ELEMENT_NODE) { + node = node.parentNode; + } + + if (node == null) { + return; + } + + if (matchingSelector != null) { + if (node.closest && untilNode == null) { + return node.closest(matchingSelector); + } else { + while (node && node !== untilNode) { + if (elementMatchesSelector(node, matchingSelector)) { + return node; + } + + node = node.parentNode; + } + } + } else { + return node; + } +}; +const findInnerElement = function (element) { + while ((_element = element) !== null && _element !== void 0 && _element.firstElementChild) { + var _element; + + element = element.firstElementChild; + } + + return element; +}; +const innerElementIsActive = element => document.activeElement !== element && elementContainsNode(element, document.activeElement); +const elementContainsNode = function (element, node) { + if (!element || !node) { + return; + } + + while (node) { + if (node === element) { + return true; + } + + node = node.parentNode; + } +}; +const findNodeFromContainerAndOffset = function (container, offset) { + if (!container) { + return; + } + + if (container.nodeType === Node.TEXT_NODE) { + return container; + } else if (offset === 0) { + return container.firstChild != null ? container.firstChild : container; + } else { + return container.childNodes.item(offset - 1); + } +}; +const findElementFromContainerAndOffset = function (container, offset) { + const node = findNodeFromContainerAndOffset(container, offset); + return findClosestElementFromNode(node); +}; +const findChildIndexOfNode = function (node) { + var _node; + + if (!((_node = node) !== null && _node !== void 0 && _node.parentNode)) { + return; + } + + let childIndex = 0; + node = node.previousSibling; + + while (node) { + childIndex++; + node = node.previousSibling; + } + + return childIndex; +}; +const removeNode = node => { + var _node$parentNode; + + return node === null || node === void 0 ? void 0 : (_node$parentNode = node.parentNode) === null || _node$parentNode === void 0 ? void 0 : _node$parentNode.removeChild(node); +}; +const walkTree = function (tree) { + let { + onlyNodesOfType, + usingFilter, + expandEntityReferences + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + const whatToShow = (() => { + switch (onlyNodesOfType) { + case "element": + return NodeFilter.SHOW_ELEMENT; + + case "text": + return NodeFilter.SHOW_TEXT; + + case "comment": + return NodeFilter.SHOW_COMMENT; + + default: + return NodeFilter.SHOW_ALL; + } + })(); + + return document.createTreeWalker(tree, whatToShow, usingFilter != null ? usingFilter : null, expandEntityReferences === true); +}; +const tagName = element => { + var _element$tagName; + + return element === null || element === void 0 ? void 0 : (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase(); +}; +const makeElement = function (tag) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let key, value; + + if (typeof tag === "object") { + options = tag; + tag = options.tagName; + } else { + options = { + attributes: options + }; + } + + const element = document.createElement(tag); + + if (options.editable != null) { + if (options.attributes == null) { + options.attributes = {}; + } + + options.attributes.contenteditable = options.editable; + } + + if (options.attributes) { + for (key in options.attributes) { + value = options.attributes[key]; + element.setAttribute(key, value); + } + } + + if (options.style) { + for (key in options.style) { + value = options.style[key]; + element.style[key] = value; + } + } + + if (options.data) { + for (key in options.data) { + value = options.data[key]; + element.dataset[key] = value; + } + } + + if (options.className) { + options.className.split(" ").forEach(className => { + element.classList.add(className); + }); + } + + if (options.textContent) { + element.textContent = options.textContent; + } + + if (options.childNodes) { + [].concat(options.childNodes).forEach(childNode => { + element.appendChild(childNode); + }); + } + + return element; +}; +let blockTagNames = undefined; +const getBlockTagNames = function () { + if (blockTagNames != null) { + return blockTagNames; + } + + blockTagNames = []; + + for (const key in config.blockAttributes) { + const attributes = config.blockAttributes[key]; + + if (attributes.tagName) { + blockTagNames.push(attributes.tagName); + } + } + + return blockTagNames; +}; +const nodeIsBlockContainer = node => nodeIsBlockStartComment(node === null || node === void 0 ? void 0 : node.firstChild); +const nodeProbablyIsBlockContainer = function (node) { + return getBlockTagNames().includes(tagName(node)) && !getBlockTagNames().includes(tagName(node.firstChild)); +}; +const nodeIsBlockStart = function (node) { + let { + strict + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + strict: true + }; + + if (strict) { + return nodeIsBlockStartComment(node); + } else { + return nodeIsBlockStartComment(node) || !nodeIsBlockStartComment(node.firstChild) && nodeProbablyIsBlockContainer(node); + } +}; +const nodeIsBlockStartComment = node => nodeIsCommentNode(node) && (node === null || node === void 0 ? void 0 : node.data) === "block"; +const nodeIsCommentNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.COMMENT_NODE; +const nodeIsCursorTarget = function (node) { + let { + name + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (!node) { + return; + } + + if (nodeIsTextNode(node)) { + if (node.data === ZERO_WIDTH_SPACE) { + if (name) { + return node.parentNode.dataset.trixCursorTarget === name; + } else { + return true; + } + } + } else { + return nodeIsCursorTarget(node.firstChild); + } +}; +const nodeIsAttachmentElement = node => elementMatchesSelector(node, attachmentSelector); +const nodeIsEmptyTextNode = node => nodeIsTextNode(node) && (node === null || node === void 0 ? void 0 : node.data) === ""; +const nodeIsTextNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.TEXT_NODE; + +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]/; +const getDirection = function () { + const input = makeElement("input", { + dir: "auto", + name: "x", + dirName: "x.dir" + }); + const form = makeElement("form"); + form.appendChild(input); + + const supportsDirName = function () { + try { + return new FormData(form).has(input.dirName); + } catch (error) { + return false; + } + }(); + + const supportsDirSelector = function () { + try { + return input.matches(":dir(ltr),:dir(rtl)"); + } catch (error) { + return false; + } + }(); + + if (supportsDirName) { + return function (string) { + input.value = string; + return new FormData(form).get(input.dirName); + }; + } else if (supportsDirSelector) { + return function (string) { + input.value = string; + + if (input.matches(":dir(rtl)")) { + return "rtl"; + } else { + return "ltr"; + } + }; + } else { + return function (string) { + const char = string.trim().charAt(0); + + if (RTL_PATTERN.test(char)) { + return "rtl"; + } else { + return "ltr"; + } + }; + } +}(); + +let allAttributeNames = null; +let blockAttributeNames = null; +let textAttributeNames = null; +let listAttributeNames = null; +const getAllAttributeNames = () => { + if (!allAttributeNames) { + allAttributeNames = getTextAttributeNames().concat(getBlockAttributeNames()); + } + + return allAttributeNames; +}; +const getBlockConfig = attributeName => config.blockAttributes[attributeName]; +const getBlockAttributeNames = () => { + if (!blockAttributeNames) { + blockAttributeNames = Object.keys(config.blockAttributes); + } + + return blockAttributeNames; +}; +const getTextConfig = attributeName => config.textAttributes[attributeName]; +const getTextAttributeNames = () => { + if (!textAttributeNames) { + textAttributeNames = Object.keys(config.textAttributes); + } + + return textAttributeNames; +}; +const getListAttributeNames = () => { + if (!listAttributeNames) { + listAttributeNames = []; + + for (const key in config.blockAttributes) { + const { + listAttribute + } = config.blockAttributes[key]; + + if (listAttribute != null) { + listAttributeNames.push(listAttribute); + } + } + } + + return listAttributeNames; +}; + +/* eslint-disable +*/ +const installDefaultCSSForTagName = function (tagName, defaultCSS) { + const styleElement = insertStyleElementForTagName(tagName); + styleElement.textContent = defaultCSS.replace(/%t/g, tagName); +}; + +const insertStyleElementForTagName = function (tagName) { + const element = document.createElement("style"); + element.setAttribute("type", "text/css"); + element.setAttribute("data-tag-name", tagName.toLowerCase()); + const nonce = getCSPNonce(); + + if (nonce) { + element.setAttribute("nonce", nonce); + } + + document.head.insertBefore(element, document.head.firstChild); + return element; +}; + +const getCSPNonce = function () { + const element = getMetaElement("trix-csp-nonce") || getMetaElement("csp-nonce"); + + if (element) { + return element.getAttribute("content"); + } +}; + +const getMetaElement = name => document.head.querySelector("meta[name=".concat(name, "]")); + +const testTransferData = { + "application/x-trix-feature-detection": "test" +}; +const dataTransferIsPlainText = function (dataTransfer) { + const text = dataTransfer.getData("text/plain"); + const html = dataTransfer.getData("text/html"); + + if (text && html) { + const { + body + } = new DOMParser().parseFromString(html, "text/html"); + + if (body.textContent === text) { + return !body.querySelector("*"); + } + } else { + return text === null || text === void 0 ? void 0 : text.length; + } +}; +const dataTransferIsWritable = function (dataTransfer) { + if (!(dataTransfer !== null && dataTransfer !== void 0 && dataTransfer.setData)) return false; + + for (const key in testTransferData) { + const value = testTransferData[key]; + + try { + dataTransfer.setData(key, value); + if (!dataTransfer.getData(key) === value) return false; + } catch (error) { + return false; + } + } + + return true; +}; +const keyEventIsKeyboardCommand = function () { + if (/Mac|^iP/.test(navigator.platform)) { + return event => event.metaKey; + } else { + return event => event.ctrlKey; + } +}(); + +const defer = fn => setTimeout(fn, 1); + +/* eslint-disable + id-length, +*/ +const copyObject = function () { + let object = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + const result = {}; + + for (const key in object) { + const value = object[key]; + result[key] = value; + } + + return result; +}; +const objectsAreEqual = function () { + let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (Object.keys(a).length !== Object.keys(b).length) { + return false; + } + + for (const key in a) { + const value = a[key]; + + if (value !== b[key]) { + return false; + } + } + + return true; +}; + +const normalizeRange = function (range) { + if (range == null) return; + + if (!Array.isArray(range)) { + range = [range, range]; + } + + return [copyValue(range[0]), copyValue(range[1] != null ? range[1] : range[0])]; +}; +const rangeIsCollapsed = function (range) { + if (range == null) return; + const [start, end] = normalizeRange(range); + return rangeValuesAreEqual(start, end); +}; +const rangesAreEqual = function (leftRange, rightRange) { + if (leftRange == null || rightRange == null) return; + const [leftStart, leftEnd] = normalizeRange(leftRange); + const [rightStart, rightEnd] = normalizeRange(rightRange); + return rangeValuesAreEqual(leftStart, rightStart) && rangeValuesAreEqual(leftEnd, rightEnd); +}; + +const copyValue = function (value) { + if (typeof value === "number") { + return value; + } else { + return copyObject(value); + } +}; + +const rangeValuesAreEqual = function (left, right) { + if (typeof left === "number") { + return left === right; + } else { + return objectsAreEqual(left, right); + } +}; + +/* eslint-disable + id-length, +*/ +class SelectionChangeObserver extends BasicObject { + constructor() { + super(...arguments); + this.update = this.update.bind(this); + this.run = this.run.bind(this); + this.selectionManagers = []; + } + + start() { + if (!this.started) { + this.started = true; + + if ("onselectionchange" in document) { + return document.addEventListener("selectionchange", this.update, true); + } else { + return this.run(); + } + } + } + + stop() { + if (this.started) { + this.started = false; + return document.removeEventListener("selectionchange", this.update, true); + } + } + + registerSelectionManager(selectionManager) { + if (!this.selectionManagers.includes(selectionManager)) { + this.selectionManagers.push(selectionManager); + return this.start(); + } + } + + unregisterSelectionManager(selectionManager) { + this.selectionManagers = this.selectionManagers.filter(s => s !== selectionManager); + + if (this.selectionManagers.length === 0) { + return this.stop(); + } + } + + notifySelectionManagersOfSelectionChange() { + return this.selectionManagers.map(selectionManager => selectionManager.selectionDidChange()); + } + + update() { + const domRange = getDOMRange(); + + if (!domRangesAreEqual(domRange, this.domRange)) { + this.domRange = domRange; + return this.notifySelectionManagersOfSelectionChange(); + } + } + + reset() { + this.domRange = null; + return this.update(); + } // Private + + + run() { + if (this.started) { + this.update(); + return requestAnimationFrame(this.run); + } + } + +} + +const domRangesAreEqual = (left, right) => (left === null || left === void 0 ? void 0 : left.startContainer) === (right === null || right === void 0 ? void 0 : right.startContainer) && (left === null || left === void 0 ? void 0 : left.startOffset) === (right === null || right === void 0 ? void 0 : right.startOffset) && (left === null || left === void 0 ? void 0 : left.endContainer) === (right === null || right === void 0 ? void 0 : right.endContainer) && (left === null || left === void 0 ? void 0 : left.endOffset) === (right === null || right === void 0 ? void 0 : right.endOffset); + +const selectionChangeObserver = new SelectionChangeObserver(); +const getDOMSelection = function () { + const selection = window.getSelection(); + + if (selection.rangeCount > 0) { + return selection; + } +}; +const getDOMRange = function () { + var _getDOMSelection; + + const domRange = (_getDOMSelection = getDOMSelection()) === null || _getDOMSelection === void 0 ? void 0 : _getDOMSelection.getRangeAt(0); + + if (domRange) { + if (!domRangeIsPrivate(domRange)) { + return domRange; + } + } +}; +const setDOMRange = function (domRange) { + const selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(domRange); + return selectionChangeObserver.update(); +}; // In Firefox, clicking certain elements changes the selection to a +// private element used to draw its UI. Attempting to access properties of those +// elements throws an error. +// https://bugzilla.mozilla.org/show_bug.cgi?id=208427 + +const domRangeIsPrivate = domRange => nodeIsPrivate(domRange.startContainer) || nodeIsPrivate(domRange.endContainer); + +const nodeIsPrivate = node => !Object.getPrototypeOf(node); + +/* eslint-disable + id-length, + no-useless-escape, +*/ +const normalizeSpaces = string => string.replace(new RegExp("".concat(ZERO_WIDTH_SPACE), "g"), "").replace(new RegExp("".concat(NON_BREAKING_SPACE), "g"), " "); +const normalizeNewlines = string => string.replace(/\r\n/g, "\n"); +const breakableWhitespacePattern = new RegExp("[^\\S".concat(NON_BREAKING_SPACE, "]")); +const squishBreakableWhitespace = string => string // Replace all breakable whitespace characters with a space +.replace(new RegExp("".concat(breakableWhitespacePattern.source), "g"), " ") // Replace two or more spaces with a single space +.replace(/\ {2,}/g, " "); +const summarizeStringChange = function (oldString, newString) { + let added, removed; + oldString = UTF16String.box(oldString); + newString = UTF16String.box(newString); + + if (newString.length < oldString.length) { + [removed, added] = utf16StringDifferences(oldString, newString); + } else { + [added, removed] = utf16StringDifferences(newString, oldString); + } + + return { + added, + removed + }; +}; + +const utf16StringDifferences = function (a, b) { + if (a.isEqualTo(b)) { + return ["", ""]; + } + + const diffA = utf16StringDifference(a, b); + const { + length + } = diffA.utf16String; + let diffB; + + if (length) { + const { + offset + } = diffA; + const codepoints = a.codepoints.slice(0, offset).concat(a.codepoints.slice(offset + length)); + diffB = utf16StringDifference(b, UTF16String.fromCodepoints(codepoints)); + } else { + diffB = utf16StringDifference(b, a); + } + + return [diffA.utf16String.toString(), diffB.utf16String.toString()]; +}; + +const utf16StringDifference = function (a, b) { + let leftIndex = 0; + let rightIndexA = a.length; + let rightIndexB = b.length; + + while (leftIndex < rightIndexA && a.charAt(leftIndex).isEqualTo(b.charAt(leftIndex))) { + leftIndex++; + } + + while (rightIndexA > leftIndex + 1 && a.charAt(rightIndexA - 1).isEqualTo(b.charAt(rightIndexB - 1))) { + rightIndexA--; + rightIndexB--; + } + + return { + utf16String: a.slice(leftIndex, rightIndexA), + offset: leftIndex + }; +}; + +class Hash extends TrixObject { + static fromCommonAttributesOfObjects() { + let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + + if (!objects.length) { + return new this(); + } + + let hash = box(objects[0]); + let keys = hash.getKeys(); + objects.slice(1).forEach(object => { + keys = hash.getKeysCommonToHash(box(object)); + hash = hash.slice(keys); + }); + return hash; + } + + static box(values) { + return box(values); + } + + constructor() { + let values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + super(...arguments); + this.values = copy(values); + } + + add(key, value) { + return this.merge(object(key, value)); + } + + remove(key) { + return new Hash(copy(this.values, key)); + } + + get(key) { + return this.values[key]; + } + + has(key) { + return key in this.values; + } + + merge(values) { + return new Hash(merge(this.values, unbox(values))); + } + + slice(keys) { + const values = {}; + keys.forEach(key => { + if (this.has(key)) { + values[key] = this.values[key]; + } + }); + return new Hash(values); + } + + getKeys() { + return Object.keys(this.values); + } + + getKeysCommonToHash(hash) { + hash = box(hash); + return this.getKeys().filter(key => this.values[key] === hash.values[key]); + } + + isEqualTo(values) { + return arraysAreEqual(this.toArray(), box(values).toArray()); + } + + isEmpty() { + return this.getKeys().length === 0; + } + + toArray() { + if (!this.array) { + const result = []; + + for (const key in this.values) { + const value = this.values[key]; + result.push(result.push(key, value)); + } + + this.array = result.slice(0); + } + + return this.array; + } + + toObject() { + return copy(this.values); + } + + toJSON() { + return this.toObject(); + } + + contentsForInspection() { + return { + values: JSON.stringify(this.values) + }; + } + +} + +const object = function (key, value) { + const result = {}; + result[key] = value; + return result; +}; + +const merge = function (object, values) { + const result = copy(object); + + for (const key in values) { + const value = values[key]; + result[key] = value; + } + + return result; +}; + +const copy = function (object, keyToRemove) { + const result = {}; + const sortedKeys = Object.keys(object).sort(); + sortedKeys.forEach(key => { + if (key !== keyToRemove) { + result[key] = object[key]; + } + }); + return result; +}; + +const box = function (object) { + if (object instanceof Hash) { + return object; + } else { + return new Hash(object); + } +}; + +const unbox = function (object) { + if (object instanceof Hash) { + return object.values; + } else { + return object; + } +}; + +class ObjectGroup { + static groupObjects() { + let ungroupedObjects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let { + depth, + asTree + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let group; + + if (asTree) { + if (depth == null) { + depth = 0; + } + } + + const objects = []; + Array.from(ungroupedObjects).forEach(object => { + var _object$canBeGrouped2; + + if (group) { + var _object$canBeGrouped, _group$canBeGroupedWi, _group; + + 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)) { + group.push(object); + return; + } else { + objects.push(new this(group, { + depth, + asTree + })); + group = null; + } + } + + if ((_object$canBeGrouped2 = object.canBeGrouped) !== null && _object$canBeGrouped2 !== void 0 && _object$canBeGrouped2.call(object, depth)) { + group = [object]; + } else { + objects.push(object); + } + }); + + if (group) { + objects.push(new this(group, { + depth, + asTree + })); + } + + return objects; + } + + constructor() { + let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let { + depth, + asTree + } = arguments.length > 1 ? arguments[1] : undefined; + this.objects = objects; + + if (asTree) { + this.depth = depth; + this.objects = this.constructor.groupObjects(this.objects, { + asTree, + depth: this.depth + 1 + }); + } + } + + getObjects() { + return this.objects; + } + + getDepth() { + return this.depth; + } + + getCacheKey() { + const keys = ["objectGroup"]; + Array.from(this.getObjects()).forEach(object => { + keys.push(object.getCacheKey()); + }); + return keys.join("/"); + } + +} + +class ObjectMap extends BasicObject { + constructor() { + let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + super(...arguments); + this.objects = {}; + Array.from(objects).forEach(object => { + const hash = JSON.stringify(object); + + if (this.objects[hash] == null) { + this.objects[hash] = object; + } + }); + } + + find(object) { + const hash = JSON.stringify(object); + return this.objects[hash]; + } + +} + +class ElementStore { + constructor(elements) { + this.reset(elements); + } + + add(element) { + const key = getKey(element); + this.elements[key] = element; + } + + remove(element) { + const key = getKey(element); + const value = this.elements[key]; + + if (value) { + delete this.elements[key]; + return value; + } + } + + reset() { + let elements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + this.elements = {}; + Array.from(elements).forEach(element => { + this.add(element); + }); + return elements; + } + +} + +const getKey = element => element.dataset.trixStoreKey; + +class Operation extends BasicObject { + isPerforming() { + return this.performing === true; + } + + hasPerformed() { + return this.performed === true; + } + + hasSucceeded() { + return this.performed && this.succeeded; + } + + hasFailed() { + return this.performed && !this.succeeded; + } + + getPromise() { + if (!this.promise) { + this.promise = new Promise((resolve, reject) => { + this.performing = true; + return this.perform((succeeded, result) => { + this.succeeded = succeeded; + this.performing = false; + this.performed = true; + + if (this.succeeded) { + resolve(result); + } else { + reject(result); + } + }); + }); + } + + return this.promise; + } + + perform(callback) { + return callback(false); + } + + release() { + var _this$promise, _this$promise$cancel; + + (_this$promise = this.promise) === null || _this$promise === void 0 ? void 0 : (_this$promise$cancel = _this$promise.cancel) === null || _this$promise$cancel === void 0 ? void 0 : _this$promise$cancel.call(_this$promise); + this.promise = null; + this.performing = null; + this.performed = null; + this.succeeded = null; + } + +} +Operation.proxyMethod("getPromise().then"); +Operation.proxyMethod("getPromise().catch"); + +class ObjectView extends BasicObject { + constructor(object) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + super(...arguments); + this.object = object; + this.options = options; + this.childViews = []; + this.rootView = this; + } + + getNodes() { + if (!this.nodes) { + this.nodes = this.createNodes(); + } + + return this.nodes.map(node => node.cloneNode(true)); + } + + invalidate() { + var _this$parentView; + + this.nodes = null; + this.childViews = []; + return (_this$parentView = this.parentView) === null || _this$parentView === void 0 ? void 0 : _this$parentView.invalidate(); + } + + invalidateViewForObject(object) { + var _this$findViewForObje; + + return (_this$findViewForObje = this.findViewForObject(object)) === null || _this$findViewForObje === void 0 ? void 0 : _this$findViewForObje.invalidate(); + } + + findOrCreateCachedChildView(viewClass, object, options) { + let view = this.getCachedViewForObject(object); + + if (view) { + this.recordChildView(view); + } else { + view = this.createChildView(...arguments); + this.cacheViewForObject(view, object); + } + + return view; + } + + createChildView(viewClass, object) { + let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + if (object instanceof ObjectGroup) { + options.viewClass = viewClass; + viewClass = ObjectGroupView; + } + + const view = new viewClass(object, options); + return this.recordChildView(view); + } + + recordChildView(view) { + view.parentView = this; + view.rootView = this.rootView; + this.childViews.push(view); + return view; + } + + getAllChildViews() { + let views = []; + this.childViews.forEach(childView => { + views.push(childView); + views = views.concat(childView.getAllChildViews()); + }); + return views; + } + + findElement() { + return this.findElementForObject(this.object); + } + + findElementForObject(object) { + const id = object === null || object === void 0 ? void 0 : object.id; + + if (id) { + return this.rootView.element.querySelector("[data-trix-id='".concat(id, "']")); + } + } + + findViewForObject(object) { + for (const view of this.getAllChildViews()) { + if (view.object === object) { + return view; + } + } + } + + getViewCache() { + if (this.rootView === this) { + if (this.isViewCachingEnabled()) { + if (!this.viewCache) { + this.viewCache = {}; + } + + return this.viewCache; + } + } else { + return this.rootView.getViewCache(); + } + } + + isViewCachingEnabled() { + return this.shouldCacheViews !== false; + } + + enableViewCaching() { + this.shouldCacheViews = true; + } + + disableViewCaching() { + this.shouldCacheViews = false; + } + + getCachedViewForObject(object) { + var _this$getViewCache; + + return (_this$getViewCache = this.getViewCache()) === null || _this$getViewCache === void 0 ? void 0 : _this$getViewCache[object.getCacheKey()]; + } + + cacheViewForObject(view, object) { + const cache = this.getViewCache(); + + if (cache) { + cache[object.getCacheKey()] = view; + } + } + + garbageCollectCachedViews() { + const cache = this.getViewCache(); + + if (cache) { + const views = this.getAllChildViews().concat(this); + const objectKeys = views.map(view => view.object.getCacheKey()); + + for (const key in cache) { + if (!objectKeys.includes(key)) { + delete cache[key]; + } + } + } + } + +} +class ObjectGroupView extends ObjectView { + constructor() { + super(...arguments); + this.objectGroup = this.object; + this.viewClass = this.options.viewClass; + delete this.options.viewClass; + } + + getChildViews() { + if (!this.childViews.length) { + Array.from(this.objectGroup.getObjects()).forEach(object => { + this.findOrCreateCachedChildView(this.viewClass, object, this.options); + }); + } + + return this.childViews; + } + + createNodes() { + const element = this.createContainerElement(); + this.getChildViews().forEach(view => { + Array.from(view.getNodes()).forEach(node => { + element.appendChild(node); + }); + }); + return [element]; + } + + createContainerElement() { + let depth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.objectGroup.getDepth(); + return this.getChildViews()[0].createContainerElement(depth); + } + +} + +const { + css: css$3 +} = config; +class AttachmentView extends ObjectView { + constructor() { + super(...arguments); + this.attachment = this.object; + this.attachment.uploadProgressDelegate = this; + this.attachmentPiece = this.options.piece; + } + + createContentNodes() { + return []; + } + + createNodes() { + let innerElement; + const figure = innerElement = makeElement({ + tagName: "figure", + className: this.getClassName(), + data: this.getData(), + editable: false + }); + const href = this.getHref(); + + if (href) { + innerElement = makeElement({ + tagName: "a", + editable: false, + attributes: { + href, + tabindex: -1 + } + }); + figure.appendChild(innerElement); + } + + if (this.attachment.hasContent()) { + innerElement.innerHTML = this.attachment.getContent(); + } else { + this.createContentNodes().forEach(node => { + innerElement.appendChild(node); + }); + } + + innerElement.appendChild(this.createCaptionElement()); + + if (this.attachment.isPending()) { + this.progressElement = makeElement({ + tagName: "progress", + attributes: { + class: css$3.attachmentProgress, + value: this.attachment.getUploadProgress(), + max: 100 + }, + data: { + trixMutable: true, + trixStoreKey: ["progressElement", this.attachment.id].join("/") + } + }); + figure.appendChild(this.progressElement); + } + + return [createCursorTarget$1("left"), figure, createCursorTarget$1("right")]; + } + + createCaptionElement() { + const figcaption = makeElement({ + tagName: "figcaption", + className: css$3.attachmentCaption + }); + const caption = this.attachmentPiece.getCaption(); + + if (caption) { + figcaption.classList.add("".concat(css$3.attachmentCaption, "--edited")); + figcaption.textContent = caption; + } else { + let name, size; + const captionConfig = this.getCaptionConfig(); + + if (captionConfig.name) { + name = this.attachment.getFilename(); + } + + if (captionConfig.size) { + size = this.attachment.getFormattedFilesize(); + } + + if (name) { + const nameElement = makeElement({ + tagName: "span", + className: css$3.attachmentName, + textContent: name + }); + figcaption.appendChild(nameElement); + } + + if (size) { + if (name) { + figcaption.appendChild(document.createTextNode(" ")); + } + + const sizeElement = makeElement({ + tagName: "span", + className: css$3.attachmentSize, + textContent: size + }); + figcaption.appendChild(sizeElement); + } + } + + return figcaption; + } + + getClassName() { + const names = [css$3.attachment, "".concat(css$3.attachment, "--").concat(this.attachment.getType())]; + const extension = this.attachment.getExtension(); + + if (extension) { + names.push("".concat(css$3.attachment, "--").concat(extension)); + } + + return names.join(" "); + } + + getData() { + const data = { + trixAttachment: JSON.stringify(this.attachment), + trixContentType: this.attachment.getContentType(), + trixId: this.attachment.id + }; + const { + attributes + } = this.attachmentPiece; + + if (!attributes.isEmpty()) { + data.trixAttributes = JSON.stringify(attributes); + } + + if (this.attachment.isPending()) { + data.trixSerialize = false; + } + + return data; + } + + getHref() { + if (!htmlContainsTagName(this.attachment.getContent(), "a")) { + return this.attachment.getHref(); + } + } + + getCaptionConfig() { + var _config$attachments$t; + + const type = this.attachment.getType(); + const captionConfig = copyObject((_config$attachments$t = config.attachments[type]) === null || _config$attachments$t === void 0 ? void 0 : _config$attachments$t.caption); + + if (type === "file") { + captionConfig.name = true; + } + + return captionConfig; + } + + findProgressElement() { + var _this$findElement; + + return (_this$findElement = this.findElement()) === null || _this$findElement === void 0 ? void 0 : _this$findElement.querySelector("progress"); + } // Attachment delegate + + + attachmentDidChangeUploadProgress() { + const value = this.attachment.getUploadProgress(); + const progressElement = this.findProgressElement(); + + if (progressElement) { + progressElement.value = value; + } + } + +} + +const createCursorTarget$1 = name => makeElement({ + tagName: "span", + textContent: ZERO_WIDTH_SPACE, + data: { + trixCursorTarget: name, + trixSerialize: false + } +}); + +const htmlContainsTagName = function (html, tagName) { + const div = makeElement("div"); + div.innerHTML = html || ""; + return div.querySelector(tagName); +}; + +class PreviewableAttachmentView extends AttachmentView { + constructor() { + super(...arguments); + this.attachment.previewDelegate = this; + } + + createContentNodes() { + this.image = makeElement({ + tagName: "img", + attributes: { + src: "" + }, + data: { + trixMutable: true + } + }); + this.refresh(this.image); + return [this.image]; + } + + createCaptionElement() { + const figcaption = super.createCaptionElement(...arguments); + + if (!figcaption.textContent) { + figcaption.setAttribute("data-trix-placeholder", config.lang.captionPlaceholder); + } + + return figcaption; + } + + refresh(image) { + if (!image) { + var _this$findElement; + + image = (_this$findElement = this.findElement()) === null || _this$findElement === void 0 ? void 0 : _this$findElement.querySelector("img"); + } + + if (image) { + return this.updateAttributesForImage(image); + } + } + + updateAttributesForImage(image) { + const url = this.attachment.getURL(); + const previewURL = this.attachment.getPreviewURL(); + image.src = previewURL || url; + + if (previewURL === url) { + image.removeAttribute("data-trix-serialized-attributes"); + } else { + const serializedAttributes = JSON.stringify({ + src: url + }); + image.setAttribute("data-trix-serialized-attributes", serializedAttributes); + } + + const width = this.attachment.getWidth(); + const height = this.attachment.getHeight(); + + if (width != null) { + image.width = width; + } + + if (height != null) { + image.height = height; + } + + const storeKey = ["imageElement", this.attachment.id, image.src, image.width, image.height].join("/"); + image.dataset.trixStoreKey = storeKey; + } // Attachment delegate + + + attachmentDidChangeAttributes() { + this.refresh(this.image); + return this.refresh(); + } + +} + +/* eslint-disable + no-useless-escape, + no-var, +*/ +class PieceView extends ObjectView { + constructor() { + super(...arguments); + this.piece = this.object; + this.attributes = this.piece.getAttributes(); + this.textConfig = this.options.textConfig; + this.context = this.options.context; + + if (this.piece.attachment) { + this.attachment = this.piece.attachment; + } else { + this.string = this.piece.toString(); + } + } + + createNodes() { + let nodes = this.attachment ? this.createAttachmentNodes() : this.createStringNodes(); + const element = this.createElement(); + + if (element) { + const innerElement = findInnerElement(element); + Array.from(nodes).forEach(node => { + innerElement.appendChild(node); + }); + nodes = [element]; + } + + return nodes; + } + + createAttachmentNodes() { + const constructor = this.attachment.isPreviewable() ? PreviewableAttachmentView : AttachmentView; + const view = this.createChildView(constructor, this.piece.attachment, { + piece: this.piece + }); + return view.getNodes(); + } + + createStringNodes() { + var _this$textConfig; + + if ((_this$textConfig = this.textConfig) !== null && _this$textConfig !== void 0 && _this$textConfig.plaintext) { + return [document.createTextNode(this.string)]; + } else { + const nodes = []; + const iterable = this.string.split("\n"); + + for (let index = 0; index < iterable.length; index++) { + const substring = iterable[index]; + + if (index > 0) { + const element = makeElement("br"); + nodes.push(element); + } + + if (substring.length) { + const node = document.createTextNode(this.preserveSpaces(substring)); + nodes.push(node); + } + } + + return nodes; + } + } + + createElement() { + let element, key, value; + const styles = {}; + + for (key in this.attributes) { + value = this.attributes[key]; + const config = getTextConfig(key); + + if (config) { + if (config.tagName) { + var innerElement; + const pendingElement = makeElement(config.tagName); + + if (innerElement) { + innerElement.appendChild(pendingElement); + innerElement = pendingElement; + } else { + element = innerElement = pendingElement; + } + } + + if (config.styleProperty) { + styles[config.styleProperty] = value; + } + + if (config.style) { + for (key in config.style) { + value = config.style[key]; + styles[key] = value; + } + } + } + } + + if (Object.keys(styles).length) { + if (!element) { + element = makeElement("span"); + } + + for (key in styles) { + value = styles[key]; + element.style[key] = value; + } + } + + return element; + } + + createContainerElement() { + for (const key in this.attributes) { + const value = this.attributes[key]; + const config = getTextConfig(key); + + if (config) { + if (config.groupTagName) { + const attributes = {}; + attributes[key] = value; + return makeElement(config.groupTagName, attributes); + } + } + } + } + + preserveSpaces(string) { + if (this.context.isLast) { + string = string.replace(/\ $/, NON_BREAKING_SPACE); + } + + 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)); + + if (this.context.isFirst || this.context.followsWhitespace) { + string = string.replace(/^\ /, NON_BREAKING_SPACE); + } + + return string; + } + +} + +/* eslint-disable + no-var, +*/ +class TextView extends ObjectView { + constructor() { + super(...arguments); + this.text = this.object; + this.textConfig = this.options.textConfig; + } + + createNodes() { + const nodes = []; + const pieces = ObjectGroup.groupObjects(this.getPieces()); + const lastIndex = pieces.length - 1; + + for (let index = 0; index < pieces.length; index++) { + const piece = pieces[index]; + const context = {}; + + if (index === 0) { + context.isFirst = true; + } + + if (index === lastIndex) { + context.isLast = true; + } + + if (endsWithWhitespace(previousPiece)) { + context.followsWhitespace = true; + } + + const view = this.findOrCreateCachedChildView(PieceView, piece, { + textConfig: this.textConfig, + context + }); + nodes.push(...Array.from(view.getNodes() || [])); + var previousPiece = piece; + } + + return nodes; + } + + getPieces() { + return Array.from(this.text.getPieces()).filter(piece => !piece.hasAttribute("blockBreak")); + } + +} + +const endsWithWhitespace = piece => /\s$/.test(piece === null || piece === void 0 ? void 0 : piece.toString()); + +const { + css: css$2 +} = config; +class BlockView extends ObjectView { + constructor() { + super(...arguments); + this.block = this.object; + this.attributes = this.block.getAttributes(); + } + + createNodes() { + const comment = document.createComment("block"); + const nodes = [comment]; + + if (this.block.isEmpty()) { + nodes.push(makeElement("br")); + } else { + var _getBlockConfig; + + const textConfig = (_getBlockConfig = getBlockConfig(this.block.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.text; + const textView = this.findOrCreateCachedChildView(TextView, this.block.text, { + textConfig + }); + nodes.push(...Array.from(textView.getNodes() || [])); + + if (this.shouldAddExtraNewlineElement()) { + nodes.push(makeElement("br")); + } + } + + if (this.attributes.length) { + return nodes; + } else { + let attributes; + const { + tagName + } = config.blockAttributes.default; + + if (this.block.isRTL()) { + attributes = { + dir: "rtl" + }; + } + + const element = makeElement({ + tagName, + attributes + }); + nodes.forEach(node => element.appendChild(node)); + return [element]; + } + } + + createContainerElement(depth) { + let attributes, className; + const attributeName = this.attributes[depth]; + const { + tagName + } = getBlockConfig(attributeName); + + if (depth === 0 && this.block.isRTL()) { + attributes = { + dir: "rtl" + }; + } + + if (attributeName === "attachmentGallery") { + const size = this.block.getBlockBreakPosition(); + className = "".concat(css$2.attachmentGallery, " ").concat(css$2.attachmentGallery, "--").concat(size); + } + + return makeElement({ + tagName, + className, + attributes + }); + } // A single
    at the end of a block element has no visual representation + // so add an extra one. + + + shouldAddExtraNewlineElement() { + return /\n\n$/.test(this.block.toString()); + } + +} + +class DocumentView extends ObjectView { + static render(document) { + const element = makeElement("div"); + const view = new this(document, { + element + }); + view.render(); + view.sync(); + return element; + } + + constructor() { + super(...arguments); + this.element = this.options.element; + this.elementStore = new ElementStore(); + this.setDocument(this.object); + } + + setDocument(document) { + if (!document.isEqualTo(this.document)) { + this.document = this.object = document; + } + } + + render() { + this.childViews = []; + this.shadowElement = makeElement("div"); + + if (!this.document.isEmpty()) { + const objects = ObjectGroup.groupObjects(this.document.getBlocks(), { + asTree: true + }); + Array.from(objects).forEach(object => { + const view = this.findOrCreateCachedChildView(BlockView, object); + Array.from(view.getNodes()).map(node => this.shadowElement.appendChild(node)); + }); + } + } + + isSynced() { + return elementsHaveEqualHTML(this.shadowElement, this.element); + } + + sync() { + const fragment = this.createDocumentFragmentForSync(); + + while (this.element.lastChild) { + this.element.removeChild(this.element.lastChild); + } + + this.element.appendChild(fragment); + return this.didSync(); + } // Private + + + didSync() { + this.elementStore.reset(findStoredElements(this.element)); + return defer(() => this.garbageCollectCachedViews()); + } + + createDocumentFragmentForSync() { + const fragment = document.createDocumentFragment(); + Array.from(this.shadowElement.childNodes).forEach(node => { + fragment.appendChild(node.cloneNode(true)); + }); + Array.from(findStoredElements(fragment)).forEach(element => { + const storedElement = this.elementStore.remove(element); + + if (storedElement) { + element.parentNode.replaceChild(storedElement, element); + } + }); + return fragment; + } + +} + +const findStoredElements = element => element.querySelectorAll("[data-trix-store-key]"); + +const elementsHaveEqualHTML = (element, otherElement) => ignoreSpaces(element.innerHTML) === ignoreSpaces(otherElement.innerHTML); + +const ignoreSpaces = html => html.replace(/ /g, " "); + +function _asyncIterator(iterable) { + var method, + async, + sync, + retry = 2; + + if (typeof Symbol !== "undefined") { + async = Symbol.asyncIterator; + sync = Symbol.iterator; + } + + while (retry--) { + if (async && (method = iterable[async]) != null) { + return method.call(iterable); + } + + if (sync && (method = iterable[sync]) != null) { + return new AsyncFromSyncIterator(method.call(iterable)); + } + + async = "@@asyncIterator"; + sync = "@@iterator"; + } + + throw new TypeError("Object is not async iterable"); +} + +function AsyncFromSyncIterator(s) { + AsyncFromSyncIterator = function (s) { + this.s = s; + this.n = s.next; + }; + + AsyncFromSyncIterator.prototype = { + s: null, + n: null, + next: function () { + return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); + }, + return: function (value) { + var ret = this.s.return; + + if (ret === undefined) { + return Promise.resolve({ + value: value, + done: true + }); + } + + return AsyncFromSyncIteratorContinuation(ret.apply(this.s, arguments)); + }, + throw: function (value) { + var thr = this.s.return; + if (thr === undefined) return Promise.reject(value); + return AsyncFromSyncIteratorContinuation(thr.apply(this.s, arguments)); + } + }; + + function AsyncFromSyncIteratorContinuation(r) { + if (Object(r) !== r) { + return Promise.reject(new TypeError(r + " is not an object.")); + } + + var done = r.done; + return Promise.resolve(r.value).then(function (value) { + return { + value: value, + done: done + }; + }); + } + + return new AsyncFromSyncIterator(s); +} + +var REACT_ELEMENT_TYPE; + +function _jsx(type, props, key, children) { + if (!REACT_ELEMENT_TYPE) { + REACT_ELEMENT_TYPE = typeof Symbol === "function" && Symbol["for"] && Symbol["for"]("react.element") || 0xeac7; + } + + var defaultProps = type && type.defaultProps; + var childrenLength = arguments.length - 3; + + if (!props && childrenLength !== 0) { + props = { + children: void 0 + }; + } + + if (childrenLength === 1) { + props.children = children; + } else if (childrenLength > 1) { + var childArray = new Array(childrenLength); + + for (var i = 0; i < childrenLength; i++) { + childArray[i] = arguments[i + 3]; + } + + props.children = childArray; + } + + if (props && defaultProps) { + for (var propName in defaultProps) { + if (props[propName] === void 0) { + props[propName] = defaultProps[propName]; + } + } + } else if (!props) { + props = defaultProps || {}; + } + + return { + $$typeof: REACT_ELEMENT_TYPE, + type: type, + key: key === undefined ? null : "" + key, + ref: null, + props: props, + _owner: null + }; +} + +function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + + if (enumerableOnly) { + symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + }); + } + + keys.push.apply(keys, symbols); + } + + return keys; +} + +function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + + if (i % 2) { + ownKeys(Object(source), true).forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } else if (Object.getOwnPropertyDescriptors) { + Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); + } else { + ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + } + + return target; +} + +function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); +} + +function _wrapRegExp() { + _wrapRegExp = function (re, groups) { + return new BabelRegExp(re, undefined, groups); + }; + + var _super = RegExp.prototype; + + var _groups = new WeakMap(); + + function BabelRegExp(re, flags, groups) { + var _this = new RegExp(re, flags); + + _groups.set(_this, groups || _groups.get(re)); + + return _setPrototypeOf(_this, BabelRegExp.prototype); + } + + _inherits(BabelRegExp, RegExp); + + BabelRegExp.prototype.exec = function (str) { + var result = _super.exec.call(this, str); + + if (result) result.groups = buildGroups(result, this); + return result; + }; + + BabelRegExp.prototype[Symbol.replace] = function (str, substitution) { + if (typeof substitution === "string") { + var groups = _groups.get(this); + + return _super[Symbol.replace].call(this, str, substitution.replace(/\$<([^>]+)>/g, function (_, name) { + return "$" + groups[name]; + })); + } else if (typeof substitution === "function") { + var _this = this; + + return _super[Symbol.replace].call(this, str, function () { + var args = arguments; + + if (typeof args[args.length - 1] !== "object") { + args = [].slice.call(args); + args.push(buildGroups(args, _this)); + } + + return substitution.apply(this, args); + }); + } else { + return _super[Symbol.replace].call(this, str, substitution); + } + }; + + function buildGroups(result, re) { + var g = _groups.get(re); + + return Object.keys(g).reduce(function (groups, name) { + groups[name] = result[g[name]]; + return groups; + }, Object.create(null)); + } + + return _wrapRegExp.apply(this, arguments); +} + +function _AwaitValue(value) { + this.wrapped = value; +} + +function _AsyncGenerator(gen) { + var front, back; + + function send(key, arg) { + return new Promise(function (resolve, reject) { + var request = { + key: key, + arg: arg, + resolve: resolve, + reject: reject, + next: null + }; + + if (back) { + back = back.next = request; + } else { + front = back = request; + resume(key, arg); + } + }); + } + + function resume(key, arg) { + try { + var result = gen[key](arg); + var value = result.value; + var wrappedAwait = value instanceof _AwaitValue; + Promise.resolve(wrappedAwait ? value.wrapped : value).then(function (arg) { + if (wrappedAwait) { + resume(key === "return" ? "return" : "next", arg); + return; + } + + settle(result.done ? "return" : "normal", arg); + }, function (err) { + resume("throw", err); + }); + } catch (err) { + settle("throw", err); + } + } + + function settle(type, value) { + switch (type) { + case "return": + front.resolve({ + value: value, + done: true + }); + break; + + case "throw": + front.reject(value); + break; + + default: + front.resolve({ + value: value, + done: false + }); + break; + } + + front = front.next; + + if (front) { + resume(front.key, front.arg); + } else { + back = null; + } + } + + this._invoke = send; + + if (typeof gen.return !== "function") { + this.return = undefined; + } +} + +_AsyncGenerator.prototype[typeof Symbol === "function" && Symbol.asyncIterator || "@@asyncIterator"] = function () { + return this; +}; + +_AsyncGenerator.prototype.next = function (arg) { + return this._invoke("next", arg); +}; + +_AsyncGenerator.prototype.throw = function (arg) { + return this._invoke("throw", arg); +}; + +_AsyncGenerator.prototype.return = function (arg) { + return this._invoke("return", arg); +}; + +function _wrapAsyncGenerator(fn) { + return function () { + return new _AsyncGenerator(fn.apply(this, arguments)); + }; +} + +function _awaitAsyncGenerator(value) { + return new _AwaitValue(value); +} + +function _asyncGeneratorDelegate(inner, awaitWrap) { + var iter = {}, + waiting = false; + + function pump(key, value) { + waiting = true; + value = new Promise(function (resolve) { + resolve(inner[key](value)); + }); + return { + done: false, + value: awaitWrap(value) + }; + } + + ; + + iter[typeof Symbol !== "undefined" && Symbol.iterator || "@@iterator"] = function () { + return this; + }; + + iter.next = function (value) { + if (waiting) { + waiting = false; + return value; + } + + return pump("next", value); + }; + + if (typeof inner.throw === "function") { + iter.throw = function (value) { + if (waiting) { + waiting = false; + throw value; + } + + return pump("throw", value); + }; + } + + if (typeof inner.return === "function") { + iter.return = function (value) { + if (waiting) { + waiting = false; + return value; + } + + return pump("return", value); + }; + } + + return iter; +} + +function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + + if (info.done) { + resolve(value); + } else { + Promise.resolve(value).then(_next, _throw); + } +} + +function _asyncToGenerator(fn) { + return function () { + var self = this, + args = arguments; + return new Promise(function (resolve, reject) { + var gen = fn.apply(self, args); + + function _next(value) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); + } + + function _throw(err) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); + } + + _next(undefined); + }); + }; +} + +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } +} + +function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; +} + +function _defineEnumerableProperties(obj, descs) { + for (var key in descs) { + var desc = descs[key]; + desc.configurable = desc.enumerable = true; + if ("value" in desc) desc.writable = true; + Object.defineProperty(obj, key, desc); + } + + if (Object.getOwnPropertySymbols) { + var objectSymbols = Object.getOwnPropertySymbols(descs); + + for (var i = 0; i < objectSymbols.length; i++) { + var sym = objectSymbols[i]; + var desc = descs[sym]; + desc.configurable = desc.enumerable = true; + if ("value" in desc) desc.writable = true; + Object.defineProperty(obj, sym, desc); + } + } + + return obj; +} + +function _defaults(obj, defaults) { + var keys = Object.getOwnPropertyNames(defaults); + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var value = Object.getOwnPropertyDescriptor(defaults, key); + + if (value && value.configurable && obj[key] === undefined) { + Object.defineProperty(obj, key, value); + } + } + + return obj; +} + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +function _extends() { + _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + return _extends.apply(this, arguments); +} + +function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? Object(arguments[i]) : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys.push.apply(ownKeys, Object.getOwnPropertySymbols(source).filter(function (sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + + ownKeys.forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } + + return target; +} + +function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); +} + +function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + + _setPrototypeOf(subClass, superClass); +} + +function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); +} + +function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); +} + +function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } +} + +function _construct(Parent, args, Class) { + if (_isNativeReflectConstruct()) { + _construct = Reflect.construct; + } else { + _construct = function _construct(Parent, args, Class) { + var a = [null]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + if (Class) _setPrototypeOf(instance, Class.prototype); + return instance; + }; + } + + return _construct.apply(null, arguments); +} + +function _isNativeFunction(fn) { + return Function.toString.call(fn).indexOf("[native code]") !== -1; +} + +function _wrapNativeSuper(Class) { + var _cache = typeof Map === "function" ? new Map() : undefined; + + _wrapNativeSuper = function _wrapNativeSuper(Class) { + if (Class === null || !_isNativeFunction(Class)) return Class; + + if (typeof Class !== "function") { + throw new TypeError("Super expression must either be null or a function"); + } + + if (typeof _cache !== "undefined") { + if (_cache.has(Class)) return _cache.get(Class); + + _cache.set(Class, Wrapper); + } + + function Wrapper() { + return _construct(Class, arguments, _getPrototypeOf(this).constructor); + } + + Wrapper.prototype = Object.create(Class.prototype, { + constructor: { + value: Wrapper, + enumerable: false, + writable: true, + configurable: true + } + }); + return _setPrototypeOf(Wrapper, Class); + }; + + return _wrapNativeSuper(Class); +} + +function _instanceof(left, right) { + if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { + return !!right[Symbol.hasInstance](left); + } else { + return left instanceof right; + } +} + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; +} + +function _getRequireWildcardCache(nodeInterop) { + if (typeof WeakMap !== "function") return null; + var cacheBabelInterop = new WeakMap(); + var cacheNodeInterop = new WeakMap(); + return (_getRequireWildcardCache = function (nodeInterop) { + return nodeInterop ? cacheNodeInterop : cacheBabelInterop; + })(nodeInterop); +} + +function _interopRequireWildcard(obj, nodeInterop) { + if (!nodeInterop && obj && obj.__esModule) { + return obj; + } + + if (obj === null || typeof obj !== "object" && typeof obj !== "function") { + return { + default: obj + }; + } + + var cache = _getRequireWildcardCache(nodeInterop); + + if (cache && cache.has(obj)) { + return cache.get(obj); + } + + var newObj = {}; + var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; + + for (var key in obj) { + if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { + var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; + + if (desc && (desc.get || desc.set)) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + + newObj.default = obj; + + if (cache) { + cache.set(obj, newObj); + } + + return newObj; +} + +function _newArrowCheck(innerThis, boundThis) { + if (innerThis !== boundThis) { + throw new TypeError("Cannot instantiate an arrow function"); + } +} + +function _objectDestructuringEmpty(obj) { + if (obj == null) throw new TypeError("Cannot destructure undefined"); +} + +function _objectWithoutPropertiesLoose(source, excluded) { + if (source == null) return {}; + var target = {}; + var sourceKeys = Object.keys(source); + var key, i; + + for (i = 0; i < sourceKeys.length; i++) { + key = sourceKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + target[key] = source[key]; + } + + return target; +} + +function _objectWithoutProperties(source, excluded) { + if (source == null) return {}; + + var target = _objectWithoutPropertiesLoose(source, excluded); + + var key, i; + + if (Object.getOwnPropertySymbols) { + var sourceSymbolKeys = Object.getOwnPropertySymbols(source); + + for (i = 0; i < sourceSymbolKeys.length; i++) { + key = sourceSymbolKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; + target[key] = source[key]; + } + } + + return target; +} + +function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; +} + +function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } else if (call !== void 0) { + throw new TypeError("Derived constructors may only return object or undefined"); + } + + return _assertThisInitialized(self); +} + +function _createSuper(Derived) { + var hasNativeReflectConstruct = _isNativeReflectConstruct(); + + return function _createSuperInternal() { + var Super = _getPrototypeOf(Derived), + result; + + if (hasNativeReflectConstruct) { + var NewTarget = _getPrototypeOf(this).constructor; + + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + + return _possibleConstructorReturn(this, result); + }; +} + +function _superPropBase(object, property) { + while (!Object.prototype.hasOwnProperty.call(object, property)) { + object = _getPrototypeOf(object); + if (object === null) break; + } + + return object; +} + +function _get() { + if (typeof Reflect !== "undefined" && Reflect.get) { + _get = Reflect.get; + } else { + _get = function _get(target, property, receiver) { + var base = _superPropBase(target, property); + + if (!base) return; + var desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.get) { + return desc.get.call(arguments.length < 3 ? target : receiver); + } + + return desc.value; + }; + } + + return _get.apply(this, arguments); +} + +function set(target, property, value, receiver) { + if (typeof Reflect !== "undefined" && Reflect.set) { + set = Reflect.set; + } else { + set = function set(target, property, value, receiver) { + var base = _superPropBase(target, property); + + var desc; + + if (base) { + desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.set) { + desc.set.call(receiver, value); + return true; + } else if (!desc.writable) { + return false; + } + } + + desc = Object.getOwnPropertyDescriptor(receiver, property); + + if (desc) { + if (!desc.writable) { + return false; + } + + desc.value = value; + Object.defineProperty(receiver, property, desc); + } else { + _defineProperty(receiver, property, value); + } + + return true; + }; + } + + return set(target, property, value, receiver); +} + +function _set(target, property, value, receiver, isStrict) { + var s = set(target, property, value, receiver || target); + + if (!s && isStrict) { + throw new Error('failed to set property'); + } + + return value; +} + +function _taggedTemplateLiteral(strings, raw) { + if (!raw) { + raw = strings.slice(0); + } + + return Object.freeze(Object.defineProperties(strings, { + raw: { + value: Object.freeze(raw) + } + })); +} + +function _taggedTemplateLiteralLoose(strings, raw) { + if (!raw) { + raw = strings.slice(0); + } + + strings.raw = raw; + return strings; +} + +function _readOnlyError(name) { + throw new TypeError("\"" + name + "\" is read-only"); +} + +function _writeOnlyError(name) { + throw new TypeError("\"" + name + "\" is write-only"); +} + +function _classNameTDZError(name) { + throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); +} + +function _temporalUndefined() {} + +function _tdz(name) { + throw new ReferenceError(name + " is not defined - temporal dead zone"); +} + +function _temporalRef(val, name) { + return val === _temporalUndefined ? _tdz(name) : val; +} + +function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); +} + +function _slicedToArrayLoose(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimitLoose(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); +} + +function _toArray(arr) { + return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); +} + +function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); +} + +function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); +} + +function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; +} + +function _maybeArrayLike(next, arr, i) { + if (arr && !Array.isArray(arr) && typeof arr.length === "number") { + var len = arr.length; + return _arrayLikeToArray(arr, i !== void 0 && i < len ? i : len); + } + + return next(arr, i); +} + +function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); +} + +function _iterableToArrayLimit(arr, i) { + var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; + + if (_i == null) return; + var _arr = []; + var _n = true; + var _d = false; + + var _s, _e; + + try { + for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; +} + +function _iterableToArrayLimitLoose(arr, i) { + var _i = arr && (typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]); + + if (_i == null) return; + var _arr = []; + + for (_i = _i.call(arr), _step; !(_step = _i.next()).done;) { + _arr.push(_step.value); + + if (i && _arr.length === i) break; + } + + return _arr; +} + +function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); +} + +function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; +} + +function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} + +function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} + +function _createForOfIteratorHelper(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + + if (!it) { + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + + var F = function () {}; + + return { + s: F, + n: function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = it.call(o); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; +} + +function _createForOfIteratorHelperLoose(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + if (it) return (it = it.call(o)).next.bind(it); + + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + return function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} + +function _skipFirstGeneratorNext(fn) { + return function () { + var it = fn.apply(this, arguments); + it.next(); + return it; + }; +} + +function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + + return (hint === "string" ? String : Number)(input); +} + +function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + + return typeof key === "symbol" ? key : String(key); +} + +function _initializerWarningHelper(descriptor, context) { + throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and runs after the decorators transform.'); +} + +function _initializerDefineProperty(target, property, descriptor, context) { + if (!descriptor) return; + Object.defineProperty(target, property, { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + writable: descriptor.writable, + value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 + }); +} + +function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { + var desc = {}; + Object.keys(descriptor).forEach(function (key) { + desc[key] = descriptor[key]; + }); + desc.enumerable = !!desc.enumerable; + desc.configurable = !!desc.configurable; + + if ('value' in desc || desc.initializer) { + desc.writable = true; + } + + desc = decorators.slice().reverse().reduce(function (desc, decorator) { + return decorator(target, property, desc) || desc; + }, desc); + + if (context && desc.initializer !== void 0) { + desc.value = desc.initializer ? desc.initializer.call(context) : void 0; + desc.initializer = undefined; + } + + if (desc.initializer === void 0) { + Object.defineProperty(target, property, desc); + desc = null; + } + + return desc; +} + +var id$1 = 0; + +function _classPrivateFieldLooseKey(name) { + return "__private_" + id$1++ + "_" + name; +} + +function _classPrivateFieldLooseBase(receiver, privateKey) { + if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { + throw new TypeError("attempted to use private field on non-instance"); + } + + return receiver; +} + +function _classPrivateFieldGet(receiver, privateMap) { + var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); + + return _classApplyDescriptorGet(receiver, descriptor); +} + +function _classPrivateFieldSet(receiver, privateMap, value) { + var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); + + _classApplyDescriptorSet(receiver, descriptor, value); + + return value; +} + +function _classPrivateFieldDestructureSet(receiver, privateMap) { + var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); + + return _classApplyDescriptorDestructureSet(receiver, descriptor); +} + +function _classExtractFieldDescriptor(receiver, privateMap, action) { + if (!privateMap.has(receiver)) { + throw new TypeError("attempted to " + action + " private field on non-instance"); + } + + return privateMap.get(receiver); +} + +function _classStaticPrivateFieldSpecGet(receiver, classConstructor, descriptor) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + + _classCheckPrivateStaticFieldDescriptor(descriptor, "get"); + + return _classApplyDescriptorGet(receiver, descriptor); +} + +function _classStaticPrivateFieldSpecSet(receiver, classConstructor, descriptor, value) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + + _classCheckPrivateStaticFieldDescriptor(descriptor, "set"); + + _classApplyDescriptorSet(receiver, descriptor, value); + + return value; +} + +function _classStaticPrivateMethodGet(receiver, classConstructor, method) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + + return method; +} + +function _classStaticPrivateMethodSet() { + throw new TypeError("attempted to set read only static private field"); +} + +function _classApplyDescriptorGet(receiver, descriptor) { + if (descriptor.get) { + return descriptor.get.call(receiver); + } + + return descriptor.value; +} + +function _classApplyDescriptorSet(receiver, descriptor, value) { + if (descriptor.set) { + descriptor.set.call(receiver, value); + } else { + if (!descriptor.writable) { + throw new TypeError("attempted to set read only private field"); + } + + descriptor.value = value; + } +} + +function _classApplyDescriptorDestructureSet(receiver, descriptor) { + if (descriptor.set) { + if (!("__destrObj" in descriptor)) { + descriptor.__destrObj = { + set value(v) { + descriptor.set.call(receiver, v); + } + + }; + } + + return descriptor.__destrObj; + } else { + if (!descriptor.writable) { + throw new TypeError("attempted to set read only private field"); + } + + return descriptor; + } +} + +function _classStaticPrivateFieldDestructureSet(receiver, classConstructor, descriptor) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + + _classCheckPrivateStaticFieldDescriptor(descriptor, "set"); + + return _classApplyDescriptorDestructureSet(receiver, descriptor); +} + +function _classCheckPrivateStaticAccess(receiver, classConstructor) { + if (receiver !== classConstructor) { + throw new TypeError("Private static access of wrong provenance"); + } +} + +function _classCheckPrivateStaticFieldDescriptor(descriptor, action) { + if (descriptor === undefined) { + throw new TypeError("attempted to " + action + " private static field before its declaration"); + } +} + +function _decorate(decorators, factory, superClass, mixins) { + var api = _getDecoratorsApi(); + + if (mixins) { + for (var i = 0; i < mixins.length; i++) { + api = mixins[i](api); + } + } + + var r = factory(function initialize(O) { + api.initializeInstanceElements(O, decorated.elements); + }, superClass); + var decorated = api.decorateClass(_coalesceClassElements(r.d.map(_createElementDescriptor)), decorators); + api.initializeClassElements(r.F, decorated.elements); + return api.runClassFinishers(r.F, decorated.finishers); +} + +function _getDecoratorsApi() { + _getDecoratorsApi = function () { + return api; + }; + + var api = { + elementsDefinitionOrder: [["method"], ["field"]], + initializeInstanceElements: function (O, elements) { + ["method", "field"].forEach(function (kind) { + elements.forEach(function (element) { + if (element.kind === kind && element.placement === "own") { + this.defineClassElement(O, element); + } + }, this); + }, this); + }, + initializeClassElements: function (F, elements) { + var proto = F.prototype; + ["method", "field"].forEach(function (kind) { + elements.forEach(function (element) { + var placement = element.placement; + + if (element.kind === kind && (placement === "static" || placement === "prototype")) { + var receiver = placement === "static" ? F : proto; + this.defineClassElement(receiver, element); + } + }, this); + }, this); + }, + defineClassElement: function (receiver, element) { + var descriptor = element.descriptor; + + if (element.kind === "field") { + var initializer = element.initializer; + descriptor = { + enumerable: descriptor.enumerable, + writable: descriptor.writable, + configurable: descriptor.configurable, + value: initializer === void 0 ? void 0 : initializer.call(receiver) + }; + } + + Object.defineProperty(receiver, element.key, descriptor); + }, + decorateClass: function (elements, decorators) { + var newElements = []; + var finishers = []; + var placements = { + static: [], + prototype: [], + own: [] + }; + elements.forEach(function (element) { + this.addElementPlacement(element, placements); + }, this); + elements.forEach(function (element) { + if (!_hasDecorators(element)) return newElements.push(element); + var elementFinishersExtras = this.decorateElement(element, placements); + newElements.push(elementFinishersExtras.element); + newElements.push.apply(newElements, elementFinishersExtras.extras); + finishers.push.apply(finishers, elementFinishersExtras.finishers); + }, this); + + if (!decorators) { + return { + elements: newElements, + finishers: finishers + }; + } + + var result = this.decorateConstructor(newElements, decorators); + finishers.push.apply(finishers, result.finishers); + result.finishers = finishers; + return result; + }, + addElementPlacement: function (element, placements, silent) { + var keys = placements[element.placement]; + + if (!silent && keys.indexOf(element.key) !== -1) { + throw new TypeError("Duplicated element (" + element.key + ")"); + } + + keys.push(element.key); + }, + decorateElement: function (element, placements) { + var extras = []; + var finishers = []; + + for (var decorators = element.decorators, i = decorators.length - 1; i >= 0; i--) { + var keys = placements[element.placement]; + keys.splice(keys.indexOf(element.key), 1); + var elementObject = this.fromElementDescriptor(element); + var elementFinisherExtras = this.toElementFinisherExtras((0, decorators[i])(elementObject) || elementObject); + element = elementFinisherExtras.element; + this.addElementPlacement(element, placements); + + if (elementFinisherExtras.finisher) { + finishers.push(elementFinisherExtras.finisher); + } + + var newExtras = elementFinisherExtras.extras; + + if (newExtras) { + for (var j = 0; j < newExtras.length; j++) { + this.addElementPlacement(newExtras[j], placements); + } + + extras.push.apply(extras, newExtras); + } + } + + return { + element: element, + finishers: finishers, + extras: extras + }; + }, + decorateConstructor: function (elements, decorators) { + var finishers = []; + + for (var i = decorators.length - 1; i >= 0; i--) { + var obj = this.fromClassDescriptor(elements); + var elementsAndFinisher = this.toClassDescriptor((0, decorators[i])(obj) || obj); + + if (elementsAndFinisher.finisher !== undefined) { + finishers.push(elementsAndFinisher.finisher); + } + + if (elementsAndFinisher.elements !== undefined) { + elements = elementsAndFinisher.elements; + + for (var j = 0; j < elements.length - 1; j++) { + for (var k = j + 1; k < elements.length; k++) { + if (elements[j].key === elements[k].key && elements[j].placement === elements[k].placement) { + throw new TypeError("Duplicated element (" + elements[j].key + ")"); + } + } + } + } + } + + return { + elements: elements, + finishers: finishers + }; + }, + fromElementDescriptor: function (element) { + var obj = { + kind: element.kind, + key: element.key, + placement: element.placement, + descriptor: element.descriptor + }; + var desc = { + value: "Descriptor", + configurable: true + }; + Object.defineProperty(obj, Symbol.toStringTag, desc); + if (element.kind === "field") obj.initializer = element.initializer; + return obj; + }, + toElementDescriptors: function (elementObjects) { + if (elementObjects === undefined) return; + return _toArray(elementObjects).map(function (elementObject) { + var element = this.toElementDescriptor(elementObject); + this.disallowProperty(elementObject, "finisher", "An element descriptor"); + this.disallowProperty(elementObject, "extras", "An element descriptor"); + return element; + }, this); + }, + toElementDescriptor: function (elementObject) { + var kind = String(elementObject.kind); + + if (kind !== "method" && kind !== "field") { + 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 + '"'); + } + + var key = _toPropertyKey(elementObject.key); + + var placement = String(elementObject.placement); + + if (placement !== "static" && placement !== "prototype" && placement !== "own") { + 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 + '"'); + } + + var descriptor = elementObject.descriptor; + this.disallowProperty(elementObject, "elements", "An element descriptor"); + var element = { + kind: kind, + key: key, + placement: placement, + descriptor: Object.assign({}, descriptor) + }; + + if (kind !== "field") { + this.disallowProperty(elementObject, "initializer", "A method descriptor"); + } else { + this.disallowProperty(descriptor, "get", "The property descriptor of a field descriptor"); + this.disallowProperty(descriptor, "set", "The property descriptor of a field descriptor"); + this.disallowProperty(descriptor, "value", "The property descriptor of a field descriptor"); + element.initializer = elementObject.initializer; + } + + return element; + }, + toElementFinisherExtras: function (elementObject) { + var element = this.toElementDescriptor(elementObject); + + var finisher = _optionalCallableProperty(elementObject, "finisher"); + + var extras = this.toElementDescriptors(elementObject.extras); + return { + element: element, + finisher: finisher, + extras: extras + }; + }, + fromClassDescriptor: function (elements) { + var obj = { + kind: "class", + elements: elements.map(this.fromElementDescriptor, this) + }; + var desc = { + value: "Descriptor", + configurable: true + }; + Object.defineProperty(obj, Symbol.toStringTag, desc); + return obj; + }, + toClassDescriptor: function (obj) { + var kind = String(obj.kind); + + if (kind !== "class") { + throw new TypeError('A class descriptor\'s .kind property must be "class", but a decorator' + ' created a class descriptor with .kind "' + kind + '"'); + } + + this.disallowProperty(obj, "key", "A class descriptor"); + this.disallowProperty(obj, "placement", "A class descriptor"); + this.disallowProperty(obj, "descriptor", "A class descriptor"); + this.disallowProperty(obj, "initializer", "A class descriptor"); + this.disallowProperty(obj, "extras", "A class descriptor"); + + var finisher = _optionalCallableProperty(obj, "finisher"); + + var elements = this.toElementDescriptors(obj.elements); + return { + elements: elements, + finisher: finisher + }; + }, + runClassFinishers: function (constructor, finishers) { + for (var i = 0; i < finishers.length; i++) { + var newConstructor = (0, finishers[i])(constructor); + + if (newConstructor !== undefined) { + if (typeof newConstructor !== "function") { + throw new TypeError("Finishers must return a constructor."); + } + + constructor = newConstructor; + } + } + + return constructor; + }, + disallowProperty: function (obj, name, objectType) { + if (obj[name] !== undefined) { + throw new TypeError(objectType + " can't have a ." + name + " property."); + } + } + }; + return api; +} + +function _createElementDescriptor(def) { + var key = _toPropertyKey(def.key); + + var descriptor; + + if (def.kind === "method") { + descriptor = { + value: def.value, + writable: true, + configurable: true, + enumerable: false + }; + } else if (def.kind === "get") { + descriptor = { + get: def.value, + configurable: true, + enumerable: false + }; + } else if (def.kind === "set") { + descriptor = { + set: def.value, + configurable: true, + enumerable: false + }; + } else if (def.kind === "field") { + descriptor = { + configurable: true, + writable: true, + enumerable: true + }; + } + + var element = { + kind: def.kind === "field" ? "field" : "method", + key: key, + placement: def.static ? "static" : def.kind === "field" ? "own" : "prototype", + descriptor: descriptor + }; + if (def.decorators) element.decorators = def.decorators; + if (def.kind === "field") element.initializer = def.value; + return element; +} + +function _coalesceGetterSetter(element, other) { + if (element.descriptor.get !== undefined) { + other.descriptor.get = element.descriptor.get; + } else { + other.descriptor.set = element.descriptor.set; + } +} + +function _coalesceClassElements(elements) { + var newElements = []; + + var isSameElement = function (other) { + return other.kind === "method" && other.key === element.key && other.placement === element.placement; + }; + + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + var other; + + if (element.kind === "method" && (other = newElements.find(isSameElement))) { + if (_isDataDescriptor(element.descriptor) || _isDataDescriptor(other.descriptor)) { + if (_hasDecorators(element) || _hasDecorators(other)) { + throw new ReferenceError("Duplicated methods (" + element.key + ") can't be decorated."); + } + + other.descriptor = element.descriptor; + } else { + if (_hasDecorators(element)) { + if (_hasDecorators(other)) { + throw new ReferenceError("Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ")."); + } + + other.decorators = element.decorators; + } + + _coalesceGetterSetter(element, other); + } + } else { + newElements.push(element); + } + } + + return newElements; +} + +function _hasDecorators(element) { + return element.decorators && element.decorators.length; +} + +function _isDataDescriptor(desc) { + return desc !== undefined && !(desc.value === undefined && desc.writable === undefined); +} + +function _optionalCallableProperty(obj, name) { + var value = obj[name]; + + if (value !== undefined && typeof value !== "function") { + throw new TypeError("Expected '" + name + "' to be a function"); + } + + return value; +} + +function _classPrivateMethodGet(receiver, privateSet, fn) { + if (!privateSet.has(receiver)) { + throw new TypeError("attempted to get private field on non-instance"); + } + + return fn; +} + +function _checkPrivateRedeclaration(obj, privateCollection) { + if (privateCollection.has(obj)) { + throw new TypeError("Cannot initialize the same private elements twice on an object"); + } +} + +function _classPrivateFieldInitSpec(obj, privateMap, value) { + _checkPrivateRedeclaration(obj, privateMap); + + privateMap.set(obj, value); +} + +function _classPrivateMethodInitSpec(obj, privateSet) { + _checkPrivateRedeclaration(obj, privateSet); + + privateSet.add(obj); +} + +function _classPrivateMethodSet() { + throw new TypeError("attempted to reassign private method"); +} + +class Piece extends TrixObject { + static registerType(type, constructor) { + constructor.type = type; + this.types[type] = constructor; + } + + static fromJSON(pieceJSON) { + const constructor = this.types[pieceJSON.type]; + + if (constructor) { + return constructor.fromJSON(pieceJSON); + } + } + + constructor(value) { + let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + super(...arguments); + this.attributes = Hash.box(attributes); + } + + copyWithAttributes(attributes) { + return new this.constructor(this.getValue(), attributes); + } + + copyWithAdditionalAttributes(attributes) { + return this.copyWithAttributes(this.attributes.merge(attributes)); + } + + copyWithoutAttribute(attribute) { + return this.copyWithAttributes(this.attributes.remove(attribute)); + } + + copy() { + return this.copyWithAttributes(this.attributes); + } + + getAttribute(attribute) { + return this.attributes.get(attribute); + } + + getAttributesHash() { + return this.attributes; + } + + getAttributes() { + return this.attributes.toObject(); + } + + getCommonAttributes() { + const piece = pieceList.getPieceAtIndex(0); + if (!piece) return {}; + let { + attributes + } = piece; + let keys = attributes.getKeys(); + pieceList.eachPiece(function (piece) { + keys = attributes.getKeysCommonToHash(piece.attributes); + attributes = attributes.slice(keys); + }); + return attributes.toObject(); + } + + hasAttribute(attribute) { + return this.attributes.has(attribute); + } + + hasSameStringValueAsPiece(piece) { + return piece && this.toString() === piece.toString(); + } + + hasSameAttributesAsPiece(piece) { + return piece && (this.attributes === piece.attributes || this.attributes.isEqualTo(piece.attributes)); + } + + isBlockBreak() { + return false; + } + + isEqualTo(piece) { + return super.isEqualTo(...arguments) || this.hasSameConstructorAs(piece) && this.hasSameStringValueAsPiece(piece) && this.hasSameAttributesAsPiece(piece); + } + + isEmpty() { + return this.length === 0; + } + + isSerializable() { + return true; + } + + toJSON() { + return { + type: this.constructor.type, + attributes: this.getAttributes() + }; + } + + contentsForInspection() { + return { + type: this.constructor.type, + attributes: this.attributes.inspect() + }; + } // Grouping + + + canBeGrouped() { + return this.hasAttribute("href"); + } + + canBeGroupedWith(piece) { + return this.getAttribute("href") === piece.getAttribute("href"); + } // Splittable + + + getLength() { + return this.length; + } + + canBeConsolidatedWith(piece) { + return false; + } + +} + +_defineProperty(Piece, "types", {}); + +class ImagePreloadOperation extends Operation { + constructor(url) { + super(...arguments); + this.url = url; + } + + perform(callback) { + const image = new Image(); + + image.onload = () => { + image.width = this.width = image.naturalWidth; + image.height = this.height = image.naturalHeight; + return callback(true, image); + }; + + image.onerror = () => callback(false); + + image.src = this.url; + } + +} + +class Attachment extends TrixObject { + static attachmentForFile(file) { + const attributes = this.attributesForFile(file); + const attachment = new this(attributes); + attachment.setFile(file); + return attachment; + } + + static attributesForFile(file) { + return new Hash({ + filename: file.name, + filesize: file.size, + contentType: file.type + }); + } + + static fromJSON(attachmentJSON) { + return new this(attachmentJSON); + } + + constructor() { + let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + super(attributes); + this.releaseFile = this.releaseFile.bind(this); + this.attributes = Hash.box(attributes); + this.didChangeAttributes(); + } + + getAttribute(attribute) { + return this.attributes.get(attribute); + } + + hasAttribute(attribute) { + return this.attributes.has(attribute); + } + + getAttributes() { + return this.attributes.toObject(); + } + + setAttributes() { + let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + const newAttributes = this.attributes.merge(attributes); + + if (!this.attributes.isEqualTo(newAttributes)) { + var _this$previewDelegate, _this$previewDelegate2, _this$delegate, _this$delegate$attach; + + this.attributes = newAttributes; + this.didChangeAttributes(); + (_this$previewDelegate = this.previewDelegate) === null || _this$previewDelegate === void 0 ? void 0 : (_this$previewDelegate2 = _this$previewDelegate.attachmentDidChangeAttributes) === null || _this$previewDelegate2 === void 0 ? void 0 : _this$previewDelegate2.call(_this$previewDelegate, this); + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? void 0 : (_this$delegate$attach = _this$delegate.attachmentDidChangeAttributes) === null || _this$delegate$attach === void 0 ? void 0 : _this$delegate$attach.call(_this$delegate, this); + } + } + + didChangeAttributes() { + if (this.isPreviewable()) { + return this.preloadURL(); + } + } + + isPending() { + return this.file != null && !(this.getURL() || this.getHref()); + } + + isPreviewable() { + if (this.attributes.has("previewable")) { + return this.attributes.get("previewable"); + } else { + return Attachment.previewablePattern.test(this.getContentType()); + } + } + + getType() { + if (this.hasContent()) { + return "content"; + } else if (this.isPreviewable()) { + return "preview"; + } else { + return "file"; + } + } + + getURL() { + return this.attributes.get("url"); + } + + getHref() { + return this.attributes.get("href"); + } + + getFilename() { + return this.attributes.get("filename") || ""; + } + + getFilesize() { + return this.attributes.get("filesize"); + } + + getFormattedFilesize() { + const filesize = this.attributes.get("filesize"); + + if (typeof filesize === "number") { + return config.fileSize.formatter(filesize); + } else { + return ""; + } + } + + getExtension() { + var _this$getFilename$mat; + + return (_this$getFilename$mat = this.getFilename().match(/\.(\w+)$/)) === null || _this$getFilename$mat === void 0 ? void 0 : _this$getFilename$mat[1].toLowerCase(); + } + + getContentType() { + return this.attributes.get("contentType"); + } + + hasContent() { + return this.attributes.has("content"); + } + + getContent() { + return this.attributes.get("content"); + } + + getWidth() { + return this.attributes.get("width"); + } + + getHeight() { + return this.attributes.get("height"); + } + + getFile() { + return this.file; + } + + setFile(file) { + this.file = file; + + if (this.isPreviewable()) { + return this.preloadFile(); + } + } + + releaseFile() { + this.releasePreloadedFile(); + this.file = null; + } + + getUploadProgress() { + return this.uploadProgress != null ? this.uploadProgress : 0; + } + + setUploadProgress(value) { + if (this.uploadProgress !== value) { + var _this$uploadProgressD, _this$uploadProgressD2; + + this.uploadProgress = value; + return (_this$uploadProgressD = this.uploadProgressDelegate) === null || _this$uploadProgressD === void 0 ? void 0 : (_this$uploadProgressD2 = _this$uploadProgressD.attachmentDidChangeUploadProgress) === null || _this$uploadProgressD2 === void 0 ? void 0 : _this$uploadProgressD2.call(_this$uploadProgressD, this); + } + } + + toJSON() { + return this.getAttributes(); + } + + getCacheKey() { + return [super.getCacheKey(...arguments), this.attributes.getCacheKey(), this.getPreviewURL()].join("/"); + } // Previewable + + + getPreviewURL() { + return this.previewURL || this.preloadingURL; + } + + setPreviewURL(url) { + if (url !== this.getPreviewURL()) { + var _this$previewDelegate3, _this$previewDelegate4, _this$delegate2, _this$delegate2$attac; + + this.previewURL = url; + (_this$previewDelegate3 = this.previewDelegate) === null || _this$previewDelegate3 === void 0 ? void 0 : (_this$previewDelegate4 = _this$previewDelegate3.attachmentDidChangeAttributes) === null || _this$previewDelegate4 === void 0 ? void 0 : _this$previewDelegate4.call(_this$previewDelegate3, this); + return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : (_this$delegate2$attac = _this$delegate2.attachmentDidChangePreviewURL) === null || _this$delegate2$attac === void 0 ? void 0 : _this$delegate2$attac.call(_this$delegate2, this); + } + } + + preloadURL() { + return this.preload(this.getURL(), this.releaseFile); + } + + preloadFile() { + if (this.file) { + this.fileObjectURL = URL.createObjectURL(this.file); + return this.preload(this.fileObjectURL); + } + } + + releasePreloadedFile() { + if (this.fileObjectURL) { + URL.revokeObjectURL(this.fileObjectURL); + this.fileObjectURL = null; + } + } + + preload(url, callback) { + if (url && url !== this.getPreviewURL()) { + this.preloadingURL = url; + const operation = new ImagePreloadOperation(url); + return operation.then(_ref => { + let { + width, + height + } = _ref; + + if (!this.getWidth() || !this.getHeight()) { + this.setAttributes({ + width, + height + }); + } + + this.preloadingURL = null; + this.setPreviewURL(url); + return callback === null || callback === void 0 ? void 0 : callback(); + }).catch(() => { + this.preloadingURL = null; + return callback === null || callback === void 0 ? void 0 : callback(); + }); + } + } + +} + +_defineProperty(Attachment, "previewablePattern", /^image(\/(gif|png|jpe?g)|$)/); + +class AttachmentPiece extends Piece { + static fromJSON(pieceJSON) { + return new this(Attachment.fromJSON(pieceJSON.attachment), pieceJSON.attributes); + } + + constructor(attachment) { + super(...arguments); + this.attachment = attachment; + this.length = 1; + this.ensureAttachmentExclusivelyHasAttribute("href"); + + if (!this.attachment.hasContent()) { + this.removeProhibitedAttributes(); + } + } + + ensureAttachmentExclusivelyHasAttribute(attribute) { + if (this.hasAttribute(attribute)) { + if (!this.attachment.hasAttribute(attribute)) { + this.attachment.setAttributes(this.attributes.slice(attribute)); + } + + this.attributes = this.attributes.remove(attribute); + } + } + + removeProhibitedAttributes() { + const attributes = this.attributes.slice(AttachmentPiece.permittedAttributes); + + if (!attributes.isEqualTo(this.attributes)) { + this.attributes = attributes; + } + } + + getValue() { + return this.attachment; + } + + isSerializable() { + return !this.attachment.isPending(); + } + + getCaption() { + return this.attributes.get("caption") || ""; + } + + isEqualTo(piece) { + var _piece$attachment; + + return super.isEqualTo(piece) && this.attachment.id === (piece === null || piece === void 0 ? void 0 : (_piece$attachment = piece.attachment) === null || _piece$attachment === void 0 ? void 0 : _piece$attachment.id); + } + + toString() { + return OBJECT_REPLACEMENT_CHARACTER; + } + + toJSON() { + const json = super.toJSON(...arguments); + json.attachment = this.attachment; + return json; + } + + getCacheKey() { + return [super.getCacheKey(...arguments), this.attachment.getCacheKey()].join("/"); + } + + toConsole() { + return JSON.stringify(this.toString()); + } + +} + +_defineProperty(AttachmentPiece, "permittedAttributes", ["caption", "presentation"]); + +Piece.registerType("attachment", AttachmentPiece); + +class StringPiece extends Piece { + static fromJSON(pieceJSON) { + return new this(pieceJSON.string, pieceJSON.attributes); + } + + constructor(string) { + super(...arguments); + this.string = normalizeNewlines(string); + this.length = this.string.length; + } + + getValue() { + return this.string; + } + + toString() { + return this.string.toString(); + } + + isBlockBreak() { + return this.toString() === "\n" && this.getAttribute("blockBreak") === true; + } + + toJSON() { + const result = super.toJSON(...arguments); + result.string = this.string; + return result; + } // Splittable + + + canBeConsolidatedWith(piece) { + return piece && this.hasSameConstructorAs(piece) && this.hasSameAttributesAsPiece(piece); + } + + consolidateWith(piece) { + return new this.constructor(this.toString() + piece.toString(), this.attributes); + } + + splitAtOffset(offset) { + let left, right; + + if (offset === 0) { + left = null; + right = this; + } else if (offset === this.length) { + left = this; + right = null; + } else { + left = new this.constructor(this.string.slice(0, offset), this.attributes); + right = new this.constructor(this.string.slice(offset), this.attributes); + } + + return [left, right]; + } + + toConsole() { + let { + string + } = this; + + if (string.length > 15) { + string = string.slice(0, 14) + "…"; + } + + return JSON.stringify(string.toString()); + } + +} +Piece.registerType("string", StringPiece); + +/* eslint-disable + prefer-const, +*/ +class SplittableList extends TrixObject { + static box(objects) { + if (objects instanceof this) { + return objects; + } else { + return new this(objects); + } + } + + constructor() { + let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + super(...arguments); + this.objects = objects.slice(0); + this.length = this.objects.length; + } + + indexOf(object) { + return this.objects.indexOf(object); + } + + splice() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return new this.constructor(spliceArray(this.objects, ...args)); + } + + eachObject(callback) { + return this.objects.map((object, index) => callback(object, index)); + } + + insertObjectAtIndex(object, index) { + return this.splice(index, 0, object); + } + + insertSplittableListAtIndex(splittableList, index) { + return this.splice(index, 0, ...splittableList.objects); + } + + insertSplittableListAtPosition(splittableList, position) { + const [objects, index] = this.splitObjectAtPosition(position); + return new this.constructor(objects).insertSplittableListAtIndex(splittableList, index); + } + + editObjectAtIndex(index, callback) { + return this.replaceObjectAtIndex(callback(this.objects[index]), index); + } + + replaceObjectAtIndex(object, index) { + return this.splice(index, 1, object); + } + + removeObjectAtIndex(index) { + return this.splice(index, 1); + } + + getObjectAtIndex(index) { + return this.objects[index]; + } + + getSplittableListInRange(range) { + const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range); + return new this.constructor(objects.slice(leftIndex, rightIndex + 1)); + } + + selectSplittableList(test) { + const objects = this.objects.filter(object => test(object)); + return new this.constructor(objects); + } + + removeObjectsInRange(range) { + const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range); + return new this.constructor(objects).splice(leftIndex, rightIndex - leftIndex + 1); + } + + transformObjectsInRange(range, transform) { + const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range); + const transformedObjects = objects.map((object, index) => leftIndex <= index && index <= rightIndex ? transform(object) : object); + return new this.constructor(transformedObjects); + } + + splitObjectsAtRange(range) { + let rightOuterIndex; + let [objects, leftInnerIndex, offset] = this.splitObjectAtPosition(startOfRange(range)); + [objects, rightOuterIndex] = new this.constructor(objects).splitObjectAtPosition(endOfRange(range) + offset); + return [objects, leftInnerIndex, rightOuterIndex - 1]; + } + + getObjectAtPosition(position) { + const { + index + } = this.findIndexAndOffsetAtPosition(position); + return this.objects[index]; + } + + splitObjectAtPosition(position) { + let splitIndex, splitOffset; + const { + index, + offset + } = this.findIndexAndOffsetAtPosition(position); + const objects = this.objects.slice(0); + + if (index != null) { + if (offset === 0) { + splitIndex = index; + splitOffset = 0; + } else { + const object = this.getObjectAtIndex(index); + const [leftObject, rightObject] = object.splitAtOffset(offset); + objects.splice(index, 1, leftObject, rightObject); + splitIndex = index + 1; + splitOffset = leftObject.getLength() - offset; + } + } else { + splitIndex = objects.length; + splitOffset = 0; + } + + return [objects, splitIndex, splitOffset]; + } + + consolidate() { + const objects = []; + let pendingObject = this.objects[0]; + this.objects.slice(1).forEach(object => { + var _pendingObject$canBeC, _pendingObject; + + if ((_pendingObject$canBeC = (_pendingObject = pendingObject).canBeConsolidatedWith) !== null && _pendingObject$canBeC !== void 0 && _pendingObject$canBeC.call(_pendingObject, object)) { + pendingObject = pendingObject.consolidateWith(object); + } else { + objects.push(pendingObject); + pendingObject = object; + } + }); + + if (pendingObject) { + objects.push(pendingObject); + } + + return new this.constructor(objects); + } + + consolidateFromIndexToIndex(startIndex, endIndex) { + const objects = this.objects.slice(0); + const objectsInRange = objects.slice(startIndex, endIndex + 1); + const consolidatedInRange = new this.constructor(objectsInRange).consolidate().toArray(); + return this.splice(startIndex, objectsInRange.length, ...consolidatedInRange); + } + + findIndexAndOffsetAtPosition(position) { + let index; + let currentPosition = 0; + + for (index = 0; index < this.objects.length; index++) { + const object = this.objects[index]; + const nextPosition = currentPosition + object.getLength(); + + if (currentPosition <= position && position < nextPosition) { + return { + index, + offset: position - currentPosition + }; + } + + currentPosition = nextPosition; + } + + return { + index: null, + offset: null + }; + } + + findPositionAtIndexAndOffset(index, offset) { + let position = 0; + + for (let currentIndex = 0; currentIndex < this.objects.length; currentIndex++) { + const object = this.objects[currentIndex]; + + if (currentIndex < index) { + position += object.getLength(); + } else if (currentIndex === index) { + position += offset; + break; + } + } + + return position; + } + + getEndPosition() { + if (this.endPosition == null) { + this.endPosition = 0; + this.objects.forEach(object => this.endPosition += object.getLength()); + } + + return this.endPosition; + } + + toString() { + return this.objects.join(""); + } + + toArray() { + return this.objects.slice(0); + } + + toJSON() { + return this.toArray(); + } + + isEqualTo(splittableList) { + return super.isEqualTo(...arguments) || objectArraysAreEqual(this.objects, splittableList === null || splittableList === void 0 ? void 0 : splittableList.objects); + } + + contentsForInspection() { + return { + objects: "[".concat(this.objects.map(object => object.inspect()).join(", "), "]") + }; + } + +} + +const objectArraysAreEqual = function (left) { + let right = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + + if (left.length !== right.length) { + return false; + } + + let result = true; + + for (let index = 0; index < left.length; index++) { + const object = left[index]; + + if (result && !object.isEqualTo(right[index])) { + result = false; + } + } + + return result; +}; + +const startOfRange = range => range[0]; + +const endOfRange = range => range[1]; + +class Text extends TrixObject { + static textForAttachmentWithAttributes(attachment, attributes) { + const piece = new AttachmentPiece(attachment, attributes); + return new this([piece]); + } + + static textForStringWithAttributes(string, attributes) { + const piece = new StringPiece(string, attributes); + return new this([piece]); + } + + static fromJSON(textJSON) { + const pieces = Array.from(textJSON).map(pieceJSON => Piece.fromJSON(pieceJSON)); + return new this(pieces); + } + + constructor() { + let pieces = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + super(...arguments); + const notEmpty = pieces.filter(piece => !piece.isEmpty()); + this.pieceList = new SplittableList(notEmpty); + } + + copy() { + return this.copyWithPieceList(this.pieceList); + } + + copyWithPieceList(pieceList) { + return new this.constructor(pieceList.consolidate().toArray()); + } + + copyUsingObjectMap(objectMap) { + const pieces = this.getPieces().map(piece => objectMap.find(piece) || piece); + return new this.constructor(pieces); + } + + appendText(text) { + return this.insertTextAtPosition(text, this.getLength()); + } + + insertTextAtPosition(text, position) { + return this.copyWithPieceList(this.pieceList.insertSplittableListAtPosition(text.pieceList, position)); + } + + removeTextAtRange(range) { + return this.copyWithPieceList(this.pieceList.removeObjectsInRange(range)); + } + + replaceTextAtRange(text, range) { + return this.removeTextAtRange(range).insertTextAtPosition(text, range[0]); + } + + moveTextFromRangeToPosition(range, position) { + if (range[0] <= position && position <= range[1]) { + return; + } + + const text = this.getTextAtRange(range); + const length = text.getLength(); + + if (range[0] < position) { + position -= length; + } + + return this.removeTextAtRange(range).insertTextAtPosition(text, position); + } + + addAttributeAtRange(attribute, value, range) { + const attributes = {}; + attributes[attribute] = value; + return this.addAttributesAtRange(attributes, range); + } + + addAttributesAtRange(attributes, range) { + return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithAdditionalAttributes(attributes))); + } + + removeAttributeAtRange(attribute, range) { + return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithoutAttribute(attribute))); + } + + setAttributesAtRange(attributes, range) { + return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithAttributes(attributes))); + } + + getAttributesAtPosition(position) { + var _this$pieceList$getOb; + + return ((_this$pieceList$getOb = this.pieceList.getObjectAtPosition(position)) === null || _this$pieceList$getOb === void 0 ? void 0 : _this$pieceList$getOb.getAttributes()) || {}; + } + + getCommonAttributes() { + const objects = Array.from(this.pieceList.toArray()).map(piece => piece.getAttributes()); + return Hash.fromCommonAttributesOfObjects(objects).toObject(); + } + + getCommonAttributesAtRange(range) { + return this.getTextAtRange(range).getCommonAttributes() || {}; + } + + getExpandedRangeForAttributeAtOffset(attributeName, offset) { + let right; + let left = right = offset; + const length = this.getLength(); + + while (left > 0 && this.getCommonAttributesAtRange([left - 1, right])[attributeName]) { + left--; + } + + while (right < length && this.getCommonAttributesAtRange([offset, right + 1])[attributeName]) { + right++; + } + + return [left, right]; + } + + getTextAtRange(range) { + return this.copyWithPieceList(this.pieceList.getSplittableListInRange(range)); + } + + getStringAtRange(range) { + return this.pieceList.getSplittableListInRange(range).toString(); + } + + getStringAtPosition(position) { + return this.getStringAtRange([position, position + 1]); + } + + startsWithString(string) { + return this.getStringAtRange([0, string.length]) === string; + } + + endsWithString(string) { + const length = this.getLength(); + return this.getStringAtRange([length - string.length, length]) === string; + } + + getAttachmentPieces() { + return this.pieceList.toArray().filter(piece => !!piece.attachment); + } + + getAttachments() { + return this.getAttachmentPieces().map(piece => piece.attachment); + } + + getAttachmentAndPositionById(attachmentId) { + let position = 0; + + for (const piece of this.pieceList.toArray()) { + var _piece$attachment; + + if (((_piece$attachment = piece.attachment) === null || _piece$attachment === void 0 ? void 0 : _piece$attachment.id) === attachmentId) { + return { + attachment: piece.attachment, + position + }; + } + + position += piece.length; + } + + return { + attachment: null, + position: null + }; + } + + getAttachmentById(attachmentId) { + const { + attachment + } = this.getAttachmentAndPositionById(attachmentId); + return attachment; + } + + getRangeOfAttachment(attachment) { + const attachmentAndPosition = this.getAttachmentAndPositionById(attachment.id); + const position = attachmentAndPosition.position; + attachment = attachmentAndPosition.attachment; + + if (attachment) { + return [position, position + 1]; + } + } + + updateAttributesForAttachment(attributes, attachment) { + const range = this.getRangeOfAttachment(attachment); + + if (range) { + return this.addAttributesAtRange(attributes, range); + } else { + return this; + } + } + + getLength() { + return this.pieceList.getEndPosition(); + } + + isEmpty() { + return this.getLength() === 0; + } + + isEqualTo(text) { + var _text$pieceList; + + return super.isEqualTo(text) || (text === null || text === void 0 ? void 0 : (_text$pieceList = text.pieceList) === null || _text$pieceList === void 0 ? void 0 : _text$pieceList.isEqualTo(this.pieceList)); + } + + isBlockBreak() { + return this.getLength() === 1 && this.pieceList.getObjectAtIndex(0).isBlockBreak(); + } + + eachPiece(callback) { + return this.pieceList.eachObject(callback); + } + + getPieces() { + return this.pieceList.toArray(); + } + + getPieceAtPosition(position) { + return this.pieceList.getObjectAtPosition(position); + } + + contentsForInspection() { + return { + pieceList: this.pieceList.inspect() + }; + } + + toSerializableText() { + const pieceList = this.pieceList.selectSplittableList(piece => piece.isSerializable()); + return this.copyWithPieceList(pieceList); + } + + toString() { + return this.pieceList.toString(); + } + + toJSON() { + return this.pieceList.toJSON(); + } + + toConsole() { + return JSON.stringify(this.pieceList.toArray().map(piece => JSON.parse(piece.toConsole()))); + } // BIDI + + + getDirection() { + return getDirection(this.toString()); + } + + isRTL() { + return this.getDirection() === "rtl"; + } + +} + +class Block extends TrixObject { + static fromJSON(blockJSON) { + const text = Text.fromJSON(blockJSON.text); + return new this(text, blockJSON.attributes); + } + + constructor(text, attributes) { + super(...arguments); + this.text = applyBlockBreakToText(text || new Text()); + this.attributes = attributes || []; + } + + isEmpty() { + return this.text.isBlockBreak(); + } + + isEqualTo(block) { + if (super.isEqualTo(block)) return true; + 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); + } + + copyWithText(text) { + return new Block(text, this.attributes); + } + + copyWithoutText() { + return this.copyWithText(null); + } + + copyWithAttributes(attributes) { + return new Block(this.text, attributes); + } + + copyWithoutAttributes() { + return this.copyWithAttributes(null); + } + + copyUsingObjectMap(objectMap) { + const mappedText = objectMap.find(this.text); + + if (mappedText) { + return this.copyWithText(mappedText); + } else { + return this.copyWithText(this.text.copyUsingObjectMap(objectMap)); + } + } + + addAttribute(attribute) { + const attributes = this.attributes.concat(expandAttribute(attribute)); + return this.copyWithAttributes(attributes); + } + + removeAttribute(attribute) { + const { + listAttribute + } = getBlockConfig(attribute); + const attributes = removeLastValue(removeLastValue(this.attributes, attribute), listAttribute); + return this.copyWithAttributes(attributes); + } + + removeLastAttribute() { + return this.removeAttribute(this.getLastAttribute()); + } + + getLastAttribute() { + return getLastElement(this.attributes); + } + + getAttributes() { + return this.attributes.slice(0); + } + + getAttributeLevel() { + return this.attributes.length; + } + + getAttributeAtLevel(level) { + return this.attributes[level - 1]; + } + + hasAttribute(attributeName) { + return this.attributes.includes(attributeName); + } + + hasAttributes() { + return this.getAttributeLevel() > 0; + } + + getLastNestableAttribute() { + return getLastElement(this.getNestableAttributes()); + } + + getNestableAttributes() { + return this.attributes.filter(attribute => getBlockConfig(attribute).nestable); + } + + getNestingLevel() { + return this.getNestableAttributes().length; + } + + decreaseNestingLevel() { + const attribute = this.getLastNestableAttribute(); + + if (attribute) { + return this.removeAttribute(attribute); + } else { + return this; + } + } + + increaseNestingLevel() { + const attribute = this.getLastNestableAttribute(); + + if (attribute) { + const index = this.attributes.lastIndexOf(attribute); + const attributes = spliceArray(this.attributes, index + 1, 0, ...expandAttribute(attribute)); + return this.copyWithAttributes(attributes); + } else { + return this; + } + } + + getListItemAttributes() { + return this.attributes.filter(attribute => getBlockConfig(attribute).listAttribute); + } + + isListItem() { + var _getBlockConfig; + + return (_getBlockConfig = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.listAttribute; + } + + isTerminalBlock() { + var _getBlockConfig2; + + return (_getBlockConfig2 = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig2 === void 0 ? void 0 : _getBlockConfig2.terminal; + } + + breaksOnReturn() { + var _getBlockConfig3; + + return (_getBlockConfig3 = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig3 === void 0 ? void 0 : _getBlockConfig3.breakOnReturn; + } + + findLineBreakInDirectionFromPosition(direction, position) { + const string = this.toString(); + let result; + + switch (direction) { + case "forward": + result = string.indexOf("\n", position); + break; + + case "backward": + result = string.slice(0, position).lastIndexOf("\n"); + } + + if (result !== -1) { + return result; + } + } + + contentsForInspection() { + return { + text: this.text.inspect(), + attributes: this.attributes + }; + } + + toString() { + return this.text.toString(); + } + + toJSON() { + return { + text: this.text, + attributes: this.attributes + }; + } // BIDI + + + getDirection() { + return this.text.getDirection(); + } + + isRTL() { + return this.text.isRTL(); + } // Splittable + + + getLength() { + return this.text.getLength(); + } + + canBeConsolidatedWith(block) { + return !this.hasAttributes() && !block.hasAttributes() && this.getDirection() === block.getDirection(); + } + + consolidateWith(block) { + const newlineText = Text.textForStringWithAttributes("\n"); + const text = this.getTextWithoutBlockBreak().appendText(newlineText); + return this.copyWithText(text.appendText(block.text)); + } + + splitAtOffset(offset) { + let left, right; + + if (offset === 0) { + left = null; + right = this; + } else if (offset === this.getLength()) { + left = this; + right = null; + } else { + left = this.copyWithText(this.text.getTextAtRange([0, offset])); + right = this.copyWithText(this.text.getTextAtRange([offset, this.getLength()])); + } + + return [left, right]; + } + + getBlockBreakPosition() { + return this.text.getLength() - 1; + } + + getTextWithoutBlockBreak() { + if (textEndsInBlockBreak(this.text)) { + return this.text.getTextAtRange([0, this.getBlockBreakPosition()]); + } else { + return this.text.copy(); + } + } // Grouping + + + canBeGrouped(depth) { + return this.attributes[depth]; + } + + canBeGroupedWith(otherBlock, depth) { + const otherAttributes = otherBlock.getAttributes(); + const otherAttribute = otherAttributes[depth]; + const attribute = this.attributes[depth]; + return attribute === otherAttribute && !(getBlockConfig(attribute).group === false && !getListAttributeNames().includes(otherAttributes[depth + 1])) && (this.getDirection() === otherBlock.getDirection() || otherBlock.isEmpty()); + } + +} // Block breaks + +const applyBlockBreakToText = function (text) { + text = unmarkExistingInnerBlockBreaksInText(text); + text = addBlockBreakToText(text); + return text; +}; + +const unmarkExistingInnerBlockBreaksInText = function (text) { + let modified = false; + const pieces = text.getPieces(); + let innerPieces = pieces.slice(0, pieces.length - 1); + const lastPiece = pieces[pieces.length - 1]; + if (!lastPiece) return text; + innerPieces = innerPieces.map(piece => { + if (piece.isBlockBreak()) { + modified = true; + return unmarkBlockBreakPiece(piece); + } else { + return piece; + } + }); + + if (modified) { + return new Text([...innerPieces, lastPiece]); + } else { + return text; + } +}; + +const blockBreakText = Text.textForStringWithAttributes("\n", { + blockBreak: true +}); + +const addBlockBreakToText = function (text) { + if (textEndsInBlockBreak(text)) { + return text; + } else { + return text.appendText(blockBreakText); + } +}; + +const textEndsInBlockBreak = function (text) { + const length = text.getLength(); + + if (length === 0) { + return false; + } + + const endText = text.getTextAtRange([length - 1, length]); + return endText.isBlockBreak(); +}; + +const unmarkBlockBreakPiece = piece => piece.copyWithoutAttribute("blockBreak"); // Attributes + + +const expandAttribute = function (attribute) { + const { + listAttribute + } = getBlockConfig(attribute); + + if (listAttribute) { + return [listAttribute, attribute]; + } else { + return [attribute]; + } +}; // Array helpers + + +const getLastElement = array => array.slice(-1)[0]; + +const removeLastValue = function (array, value) { + const index = array.lastIndexOf(value); + + if (index === -1) { + return array; + } else { + return spliceArray(array, index, 1); + } +}; + +class Document extends TrixObject { + static fromJSON(documentJSON) { + const blocks = Array.from(documentJSON).map(blockJSON => Block.fromJSON(blockJSON)); + return new this(blocks); + } + + static fromString(string, textAttributes) { + const text = Text.textForStringWithAttributes(string, textAttributes); + return new this([new Block(text)]); + } + + constructor() { + let blocks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + super(...arguments); + + if (blocks.length === 0) { + blocks = [new Block()]; + } + + this.blockList = SplittableList.box(blocks); + } + + isEmpty() { + const block = this.getBlockAtIndex(0); + return this.blockList.length === 1 && block.isEmpty() && !block.hasAttributes(); + } + + copy() { + let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + const blocks = options.consolidateBlocks ? this.blockList.consolidate().toArray() : this.blockList.toArray(); + return new this.constructor(blocks); + } + + copyUsingObjectsFromDocument(sourceDocument) { + const objectMap = new ObjectMap(sourceDocument.getObjects()); + return this.copyUsingObjectMap(objectMap); + } + + copyUsingObjectMap(objectMap) { + const blocks = this.getBlocks().map(block => { + const mappedBlock = objectMap.find(block); + return mappedBlock || block.copyUsingObjectMap(objectMap); + }); + return new this.constructor(blocks); + } + + copyWithBaseBlockAttributes() { + let blockAttributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + const blocks = this.getBlocks().map(block => { + const attributes = blockAttributes.concat(block.getAttributes()); + return block.copyWithAttributes(attributes); + }); + return new this.constructor(blocks); + } + + replaceBlock(oldBlock, newBlock) { + const index = this.blockList.indexOf(oldBlock); + + if (index === -1) { + return this; + } + + return new this.constructor(this.blockList.replaceObjectAtIndex(newBlock, index)); + } + + insertDocumentAtRange(document, range) { + const { + blockList + } = document; + range = normalizeRange(range); + let [position] = range; + const { + index, + offset + } = this.locationFromPosition(position); + let result = this; + const block = this.getBlockAtPosition(position); + + if (rangeIsCollapsed(range) && block.isEmpty() && !block.hasAttributes()) { + result = new this.constructor(result.blockList.removeObjectAtIndex(index)); + } else if (block.getBlockBreakPosition() === offset) { + position++; + } + + result = result.removeTextAtRange(range); + return new this.constructor(result.blockList.insertSplittableListAtPosition(blockList, position)); + } + + mergeDocumentAtRange(document, range) { + let formattedDocument, result; + range = normalizeRange(range); + const [startPosition] = range; + const startLocation = this.locationFromPosition(startPosition); + const blockAttributes = this.getBlockAtIndex(startLocation.index).getAttributes(); + const baseBlockAttributes = document.getBaseBlockAttributes(); + const trailingBlockAttributes = blockAttributes.slice(-baseBlockAttributes.length); + + if (arraysAreEqual(baseBlockAttributes, trailingBlockAttributes)) { + const leadingBlockAttributes = blockAttributes.slice(0, -baseBlockAttributes.length); + formattedDocument = document.copyWithBaseBlockAttributes(leadingBlockAttributes); + } else { + formattedDocument = document.copy({ + consolidateBlocks: true + }).copyWithBaseBlockAttributes(blockAttributes); + } + + const blockCount = formattedDocument.getBlockCount(); + const firstBlock = formattedDocument.getBlockAtIndex(0); + + if (arraysAreEqual(blockAttributes, firstBlock.getAttributes())) { + const firstText = firstBlock.getTextWithoutBlockBreak(); + result = this.insertTextAtRange(firstText, range); + + if (blockCount > 1) { + formattedDocument = new this.constructor(formattedDocument.getBlocks().slice(1)); + const position = startPosition + firstText.getLength(); + result = result.insertDocumentAtRange(formattedDocument, position); + } + } else { + result = this.insertDocumentAtRange(formattedDocument, range); + } + + return result; + } + + insertTextAtRange(text, range) { + range = normalizeRange(range); + const [startPosition] = range; + const { + index, + offset + } = this.locationFromPosition(startPosition); + const document = this.removeTextAtRange(range); + return new this.constructor(document.blockList.editObjectAtIndex(index, block => block.copyWithText(block.text.insertTextAtPosition(text, offset)))); + } + + removeTextAtRange(range) { + let blocks; + range = normalizeRange(range); + const [leftPosition, rightPosition] = range; + + if (rangeIsCollapsed(range)) { + return this; + } + + const [leftLocation, rightLocation] = Array.from(this.locationRangeFromRange(range)); + const leftIndex = leftLocation.index; + const leftOffset = leftLocation.offset; + const leftBlock = this.getBlockAtIndex(leftIndex); + const rightIndex = rightLocation.index; + const rightOffset = rightLocation.offset; + const rightBlock = this.getBlockAtIndex(rightIndex); + const removeRightNewline = rightPosition - leftPosition === 1 && leftBlock.getBlockBreakPosition() === leftOffset && rightBlock.getBlockBreakPosition() !== rightOffset && rightBlock.text.getStringAtPosition(rightOffset) === "\n"; + + if (removeRightNewline) { + blocks = this.blockList.editObjectAtIndex(rightIndex, block => block.copyWithText(block.text.removeTextAtRange([rightOffset, rightOffset + 1]))); + } else { + let block; + const leftText = leftBlock.text.getTextAtRange([0, leftOffset]); + const rightText = rightBlock.text.getTextAtRange([rightOffset, rightBlock.getLength()]); + const text = leftText.appendText(rightText); + const removingLeftBlock = leftIndex !== rightIndex && leftOffset === 0; + const useRightBlock = removingLeftBlock && leftBlock.getAttributeLevel() >= rightBlock.getAttributeLevel(); + + if (useRightBlock) { + block = rightBlock.copyWithText(text); + } else { + block = leftBlock.copyWithText(text); + } + + const affectedBlockCount = rightIndex + 1 - leftIndex; + blocks = this.blockList.splice(leftIndex, affectedBlockCount, block); + } + + return new this.constructor(blocks); + } + + moveTextFromRangeToPosition(range, position) { + let text; + range = normalizeRange(range); + const [startPosition, endPosition] = range; + + if (startPosition <= position && position <= endPosition) { + return this; + } + + let document = this.getDocumentAtRange(range); + let result = this.removeTextAtRange(range); + const movingRightward = startPosition < position; + + if (movingRightward) { + position -= document.getLength(); + } + + const [firstBlock, ...blocks] = document.getBlocks(); + + if (blocks.length === 0) { + text = firstBlock.getTextWithoutBlockBreak(); + + if (movingRightward) { + position += 1; + } + } else { + text = firstBlock.text; + } + + result = result.insertTextAtRange(text, position); + + if (blocks.length === 0) { + return result; + } + + document = new this.constructor(blocks); + position += text.getLength(); + return result.insertDocumentAtRange(document, position); + } + + addAttributeAtRange(attribute, value, range) { + let { + blockList + } = this; + this.eachBlockAtRange(range, (block, textRange, index) => blockList = blockList.editObjectAtIndex(index, function () { + if (getBlockConfig(attribute)) { + return block.addAttribute(attribute, value); + } else { + if (textRange[0] === textRange[1]) { + return block; + } else { + return block.copyWithText(block.text.addAttributeAtRange(attribute, value, textRange)); + } + } + })); + return new this.constructor(blockList); + } + + addAttribute(attribute, value) { + let { + blockList + } = this; + this.eachBlock((block, index) => blockList = blockList.editObjectAtIndex(index, () => block.addAttribute(attribute, value))); + return new this.constructor(blockList); + } + + removeAttributeAtRange(attribute, range) { + let { + blockList + } = this; + this.eachBlockAtRange(range, function (block, textRange, index) { + if (getBlockConfig(attribute)) { + blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(attribute)); + } else if (textRange[0] !== textRange[1]) { + blockList = blockList.editObjectAtIndex(index, () => block.copyWithText(block.text.removeAttributeAtRange(attribute, textRange))); + } + }); + return new this.constructor(blockList); + } + + updateAttributesForAttachment(attributes, attachment) { + const range = this.getRangeOfAttachment(attachment); + const [startPosition] = Array.from(range); + const { + index + } = this.locationFromPosition(startPosition); + const text = this.getTextAtIndex(index); + return new this.constructor(this.blockList.editObjectAtIndex(index, block => block.copyWithText(text.updateAttributesForAttachment(attributes, attachment)))); + } + + removeAttributeForAttachment(attribute, attachment) { + const range = this.getRangeOfAttachment(attachment); + return this.removeAttributeAtRange(attribute, range); + } + + insertBlockBreakAtRange(range) { + let blocks; + range = normalizeRange(range); + const [startPosition] = range; + const { + offset + } = this.locationFromPosition(startPosition); + const document = this.removeTextAtRange(range); + + if (offset === 0) { + blocks = [new Block()]; + } + + return new this.constructor(document.blockList.insertSplittableListAtPosition(new SplittableList(blocks), startPosition)); + } + + applyBlockAttributeAtRange(attributeName, value, range) { + const expanded = this.expandRangeToLineBreaksAndSplitBlocks(range); + let document = expanded.document; + range = expanded.range; + const blockConfig = getBlockConfig(attributeName); + + if (blockConfig.listAttribute) { + document = document.removeLastListAttributeAtRange(range, { + exceptAttributeName: attributeName + }); + const converted = document.convertLineBreaksToBlockBreaksInRange(range); + document = converted.document; + range = converted.range; + } else if (blockConfig.exclusive) { + document = document.removeBlockAttributesAtRange(range); + } else if (blockConfig.terminal) { + document = document.removeLastTerminalAttributeAtRange(range); + } else { + document = document.consolidateBlocksAtRange(range); + } + + return document.addAttributeAtRange(attributeName, value, range); + } + + removeLastListAttributeAtRange(range) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let { + blockList + } = this; + this.eachBlockAtRange(range, function (block, textRange, index) { + const lastAttributeName = block.getLastAttribute(); + + if (!lastAttributeName) { + return; + } + + if (!getBlockConfig(lastAttributeName).listAttribute) { + return; + } + + if (lastAttributeName === options.exceptAttributeName) { + return; + } + + blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(lastAttributeName)); + }); + return new this.constructor(blockList); + } + + removeLastTerminalAttributeAtRange(range) { + let { + blockList + } = this; + this.eachBlockAtRange(range, function (block, textRange, index) { + const lastAttributeName = block.getLastAttribute(); + + if (!lastAttributeName) { + return; + } + + if (!getBlockConfig(lastAttributeName).terminal) { + return; + } + + blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(lastAttributeName)); + }); + return new this.constructor(blockList); + } + + removeBlockAttributesAtRange(range) { + let { + blockList + } = this; + this.eachBlockAtRange(range, function (block, textRange, index) { + if (block.hasAttributes()) { + blockList = blockList.editObjectAtIndex(index, () => block.copyWithoutAttributes()); + } + }); + return new this.constructor(blockList); + } + + expandRangeToLineBreaksAndSplitBlocks(range) { + let position; + range = normalizeRange(range); + let [startPosition, endPosition] = range; + const startLocation = this.locationFromPosition(startPosition); + const endLocation = this.locationFromPosition(endPosition); + let document = this; + const startBlock = document.getBlockAtIndex(startLocation.index); + startLocation.offset = startBlock.findLineBreakInDirectionFromPosition("backward", startLocation.offset); + + if (startLocation.offset != null) { + position = document.positionFromLocation(startLocation); + document = document.insertBlockBreakAtRange([position, position + 1]); + endLocation.index += 1; + endLocation.offset -= document.getBlockAtIndex(startLocation.index).getLength(); + startLocation.index += 1; + } + + startLocation.offset = 0; + + if (endLocation.offset === 0 && endLocation.index > startLocation.index) { + endLocation.index -= 1; + endLocation.offset = document.getBlockAtIndex(endLocation.index).getBlockBreakPosition(); + } else { + const endBlock = document.getBlockAtIndex(endLocation.index); + + if (endBlock.text.getStringAtRange([endLocation.offset - 1, endLocation.offset]) === "\n") { + endLocation.offset -= 1; + } else { + endLocation.offset = endBlock.findLineBreakInDirectionFromPosition("forward", endLocation.offset); + } + + if (endLocation.offset !== endBlock.getBlockBreakPosition()) { + position = document.positionFromLocation(endLocation); + document = document.insertBlockBreakAtRange([position, position + 1]); + } + } + + startPosition = document.positionFromLocation(startLocation); + endPosition = document.positionFromLocation(endLocation); + range = normalizeRange([startPosition, endPosition]); + return { + document, + range + }; + } + + convertLineBreaksToBlockBreaksInRange(range) { + range = normalizeRange(range); + let [position] = range; + const string = this.getStringAtRange(range).slice(0, -1); + let document = this; + string.replace(/.*?\n/g, function (match) { + position += match.length; + document = document.insertBlockBreakAtRange([position - 1, position]); + }); + return { + document, + range + }; + } + + consolidateBlocksAtRange(range) { + range = normalizeRange(range); + const [startPosition, endPosition] = range; + const startIndex = this.locationFromPosition(startPosition).index; + const endIndex = this.locationFromPosition(endPosition).index; + return new this.constructor(this.blockList.consolidateFromIndexToIndex(startIndex, endIndex)); + } + + getDocumentAtRange(range) { + range = normalizeRange(range); + const blocks = this.blockList.getSplittableListInRange(range).toArray(); + return new this.constructor(blocks); + } + + getStringAtRange(range) { + let endIndex; + const array = range = normalizeRange(range), + endPosition = array[array.length - 1]; + + if (endPosition !== this.getLength()) { + endIndex = -1; + } + + return this.getDocumentAtRange(range).toString().slice(0, endIndex); + } + + getBlockAtIndex(index) { + return this.blockList.getObjectAtIndex(index); + } + + getBlockAtPosition(position) { + const { + index + } = this.locationFromPosition(position); + return this.getBlockAtIndex(index); + } + + getTextAtIndex(index) { + var _this$getBlockAtIndex; + + return (_this$getBlockAtIndex = this.getBlockAtIndex(index)) === null || _this$getBlockAtIndex === void 0 ? void 0 : _this$getBlockAtIndex.text; + } + + getTextAtPosition(position) { + const { + index + } = this.locationFromPosition(position); + return this.getTextAtIndex(index); + } + + getPieceAtPosition(position) { + const { + index, + offset + } = this.locationFromPosition(position); + return this.getTextAtIndex(index).getPieceAtPosition(offset); + } + + getCharacterAtPosition(position) { + const { + index, + offset + } = this.locationFromPosition(position); + return this.getTextAtIndex(index).getStringAtRange([offset, offset + 1]); + } + + getLength() { + return this.blockList.getEndPosition(); + } + + getBlocks() { + return this.blockList.toArray(); + } + + getBlockCount() { + return this.blockList.length; + } + + getEditCount() { + return this.editCount; + } + + eachBlock(callback) { + return this.blockList.eachObject(callback); + } + + eachBlockAtRange(range, callback) { + let block, textRange; + range = normalizeRange(range); + const [startPosition, endPosition] = range; + const startLocation = this.locationFromPosition(startPosition); + const endLocation = this.locationFromPosition(endPosition); + + if (startLocation.index === endLocation.index) { + block = this.getBlockAtIndex(startLocation.index); + textRange = [startLocation.offset, endLocation.offset]; + return callback(block, textRange, startLocation.index); + } else { + for (let index = startLocation.index; index <= endLocation.index; index++) { + block = this.getBlockAtIndex(index); + + if (block) { + switch (index) { + case startLocation.index: + textRange = [startLocation.offset, block.text.getLength()]; + break; + + case endLocation.index: + textRange = [0, endLocation.offset]; + break; + + default: + textRange = [0, block.text.getLength()]; + } + + callback(block, textRange, index); + } + } + } + } + + getCommonAttributesAtRange(range) { + range = normalizeRange(range); + const [startPosition] = range; + + if (rangeIsCollapsed(range)) { + return this.getCommonAttributesAtPosition(startPosition); + } else { + const textAttributes = []; + const blockAttributes = []; + this.eachBlockAtRange(range, function (block, textRange) { + if (textRange[0] !== textRange[1]) { + textAttributes.push(block.text.getCommonAttributesAtRange(textRange)); + return blockAttributes.push(attributesForBlock(block)); + } + }); + return Hash.fromCommonAttributesOfObjects(textAttributes).merge(Hash.fromCommonAttributesOfObjects(blockAttributes)).toObject(); + } + } + + getCommonAttributesAtPosition(position) { + let key, value; + const { + index, + offset + } = this.locationFromPosition(position); + const block = this.getBlockAtIndex(index); + + if (!block) { + return {}; + } + + const commonAttributes = attributesForBlock(block); + const attributes = block.text.getAttributesAtPosition(offset); + const attributesLeft = block.text.getAttributesAtPosition(offset - 1); + const inheritableAttributes = Object.keys(config.textAttributes).filter(key => { + return config.textAttributes[key].inheritable; + }); + + for (key in attributesLeft) { + value = attributesLeft[key]; + + if (value === attributes[key] || inheritableAttributes.includes(key)) { + commonAttributes[key] = value; + } + } + + return commonAttributes; + } + + getRangeOfCommonAttributeAtPosition(attributeName, position) { + const { + index, + offset + } = this.locationFromPosition(position); + const text = this.getTextAtIndex(index); + const [startOffset, endOffset] = Array.from(text.getExpandedRangeForAttributeAtOffset(attributeName, offset)); + const start = this.positionFromLocation({ + index, + offset: startOffset + }); + const end = this.positionFromLocation({ + index, + offset: endOffset + }); + return normalizeRange([start, end]); + } + + getBaseBlockAttributes() { + let baseBlockAttributes = this.getBlockAtIndex(0).getAttributes(); + + for (let blockIndex = 1; blockIndex < this.getBlockCount(); blockIndex++) { + const blockAttributes = this.getBlockAtIndex(blockIndex).getAttributes(); + const lastAttributeIndex = Math.min(baseBlockAttributes.length, blockAttributes.length); + + baseBlockAttributes = (() => { + const result = []; + + for (let index = 0; index < lastAttributeIndex; index++) { + if (blockAttributes[index] !== baseBlockAttributes[index]) { + break; + } + + result.push(blockAttributes[index]); + } + + return result; + })(); + } + + return baseBlockAttributes; + } + + getAttachmentById(attachmentId) { + for (const attachment of this.getAttachments()) { + if (attachment.id === attachmentId) { + return attachment; + } + } + } + + getAttachmentPieces() { + let attachmentPieces = []; + this.blockList.eachObject(_ref => { + let { + text + } = _ref; + return attachmentPieces = attachmentPieces.concat(text.getAttachmentPieces()); + }); + return attachmentPieces; + } + + getAttachments() { + return this.getAttachmentPieces().map(piece => piece.attachment); + } + + getRangeOfAttachment(attachment) { + let position = 0; + const iterable = this.blockList.toArray(); + + for (let index = 0; index < iterable.length; index++) { + const { + text + } = iterable[index]; + const textRange = text.getRangeOfAttachment(attachment); + + if (textRange) { + return normalizeRange([position + textRange[0], position + textRange[1]]); + } + + position += text.getLength(); + } + } + + getLocationRangeOfAttachment(attachment) { + const range = this.getRangeOfAttachment(attachment); + return this.locationRangeFromRange(range); + } + + getAttachmentPieceForAttachment(attachment) { + for (const piece of this.getAttachmentPieces()) { + if (piece.attachment === attachment) { + return piece; + } + } + } + + findRangesForBlockAttribute(attributeName) { + let position = 0; + const ranges = []; + this.getBlocks().forEach(block => { + const length = block.getLength(); + + if (block.hasAttribute(attributeName)) { + ranges.push([position, position + length]); + } + + position += length; + }); + return ranges; + } + + findRangesForTextAttribute(attributeName) { + let { + withValue + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let position = 0; + let range = []; + const ranges = []; + + const match = function (piece) { + if (withValue) { + return piece.getAttribute(attributeName) === withValue; + } else { + return piece.hasAttribute(attributeName); + } + }; + + this.getPieces().forEach(piece => { + const length = piece.getLength(); + + if (match(piece)) { + if (range[1] === position) { + range[1] = position + length; + } else { + ranges.push(range = [position, position + length]); + } + } + + position += length; + }); + return ranges; + } + + locationFromPosition(position) { + const location = this.blockList.findIndexAndOffsetAtPosition(Math.max(0, position)); + + if (location.index != null) { + return location; + } else { + const blocks = this.getBlocks(); + return { + index: blocks.length - 1, + offset: blocks[blocks.length - 1].getLength() + }; + } + } + + positionFromLocation(location) { + return this.blockList.findPositionAtIndexAndOffset(location.index, location.offset); + } + + locationRangeFromPosition(position) { + return normalizeRange(this.locationFromPosition(position)); + } + + locationRangeFromRange(range) { + range = normalizeRange(range); + if (!range) return; + const [startPosition, endPosition] = Array.from(range); + const startLocation = this.locationFromPosition(startPosition); + const endLocation = this.locationFromPosition(endPosition); + return normalizeRange([startLocation, endLocation]); + } + + rangeFromLocationRange(locationRange) { + let rightPosition; + locationRange = normalizeRange(locationRange); + const leftPosition = this.positionFromLocation(locationRange[0]); + + if (!rangeIsCollapsed(locationRange)) { + rightPosition = this.positionFromLocation(locationRange[1]); + } + + return normalizeRange([leftPosition, rightPosition]); + } + + isEqualTo(document) { + return this.blockList.isEqualTo(document === null || document === void 0 ? void 0 : document.blockList); + } + + getTexts() { + return this.getBlocks().map(block => block.text); + } + + getPieces() { + const pieces = []; + Array.from(this.getTexts()).forEach(text => { + pieces.push(...Array.from(text.getPieces() || [])); + }); + return pieces; + } + + getObjects() { + return this.getBlocks().concat(this.getTexts()).concat(this.getPieces()); + } + + toSerializableDocument() { + const blocks = []; + this.blockList.eachObject(block => blocks.push(block.copyWithText(block.text.toSerializableText()))); + return new this.constructor(blocks); + } + + toString() { + return this.blockList.toString(); + } + + toJSON() { + return this.blockList.toJSON(); + } + + toConsole() { + return JSON.stringify(this.blockList.toArray()).map(block => JSON.parse(block.text.toConsole())); + } + +} + +const attributesForBlock = function (block) { + const attributes = {}; + const attributeName = block.getLastAttribute(); + + if (attributeName) { + attributes[attributeName] = true; + } + + return attributes; +}; + +/* eslint-disable + no-undef, +*/ +const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height class".split(" "); +const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" "); +const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe".split(" "); +class HTMLSanitizer extends BasicObject { + static sanitize(html, options) { + const sanitizer = new this(html, options); + sanitizer.sanitize(); + return sanitizer; + } + + constructor(html) { + let { + allowedAttributes, + forbiddenProtocols, + forbiddenElements + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + super(...arguments); + this.allowedAttributes = allowedAttributes || DEFAULT_ALLOWED_ATTRIBUTES; + this.forbiddenProtocols = forbiddenProtocols || DEFAULT_FORBIDDEN_PROTOCOLS; + this.forbiddenElements = forbiddenElements || DEFAULT_FORBIDDEN_ELEMENTS; + this.body = createBodyElementForHTML(html); + } + + sanitize() { + this.sanitizeElements(); + return this.normalizeListElementNesting(); + } + + getHTML() { + return this.body.innerHTML; + } + + getBody() { + return this.body; + } // Private + + + sanitizeElements() { + const walker = walkTree(this.body); + const nodesToRemove = []; + + while (walker.nextNode()) { + const node = walker.currentNode; + + switch (node.nodeType) { + case Node.ELEMENT_NODE: + if (this.elementIsRemovable(node)) { + nodesToRemove.push(node); + } else { + this.sanitizeElement(node); + } + + break; + + case Node.COMMENT_NODE: + nodesToRemove.push(node); + break; + } + } + + nodesToRemove.forEach(node => removeNode(node)); + return this.body; + } + + sanitizeElement(element) { + if (element.hasAttribute("href")) { + if (this.forbiddenProtocols.includes(element.protocol)) { + element.removeAttribute("href"); + } + } + + Array.from(element.attributes).forEach(_ref => { + let { + name + } = _ref; + + if (!this.allowedAttributes.includes(name) && name.indexOf("data-trix") !== 0) { + element.removeAttribute(name); + } + }); + return element; + } + + normalizeListElementNesting() { + Array.from(this.body.querySelectorAll("ul,ol")).forEach(listElement => { + const previousElement = listElement.previousElementSibling; + + if (previousElement) { + if (tagName(previousElement) === "li") { + previousElement.appendChild(listElement); + } + } + }); + return this.body; + } + + elementIsRemovable(element) { + if ((element === null || element === void 0 ? void 0 : element.nodeType) !== Node.ELEMENT_NODE) { + return; + } + + return this.elementIsForbidden(element) || this.elementIsntSerializable(element); + } + + elementIsForbidden(element) { + return this.forbiddenElements.includes(tagName(element)); + } + + elementIsntSerializable(element) { + return element.getAttribute("data-trix-serialize") === "false" && !nodeIsAttachmentElement(element); + } + +} + +const createBodyElementForHTML = function () { + let html = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + // Remove everything after + html = html.replace(/<\/html[^>]*>[^]*$/i, ""); + const doc = document.implementation.createHTMLDocument(""); + doc.documentElement.innerHTML = html; + Array.from(doc.head.querySelectorAll("style")).forEach(element => { + doc.body.appendChild(element); + }); + return doc.body; +}; + +/* eslint-disable + no-case-declarations, + no-irregular-whitespace, +*/ + +const pieceForString = function (string) { + let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const type = "string"; + string = normalizeSpaces(string); + return { + string, + attributes, + type + }; +}; + +const pieceForAttachment = function (attachment) { + let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const type = "attachment"; + return { + attachment, + attributes, + type + }; +}; + +const blockForAttributes = function () { + let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + const text = []; + return { + text, + attributes + }; +}; + +const parseTrixDataAttribute = (element, name) => { + try { + return JSON.parse(element.getAttribute("data-trix-".concat(name))); + } catch (error) { + return {}; + } +}; + +const getImageDimensions = element => { + const width = element.getAttribute("width"); + const height = element.getAttribute("height"); + const dimensions = {}; + + if (width) { + dimensions.width = parseInt(width, 10); + } + + if (height) { + dimensions.height = parseInt(height, 10); + } + + return dimensions; +}; + +class HTMLParser extends BasicObject { + static parse(html, options) { + const parser = new this(html, options); + parser.parse(); + return parser; + } + + constructor(html) { + let { + referenceElement + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + super(...arguments); + this.html = html; + this.referenceElement = referenceElement; + this.blocks = []; + this.blockElements = []; + this.processedElements = []; + } + + getDocument() { + return Document.fromJSON(this.blocks); + } // HTML parsing + + + parse() { + try { + this.createHiddenContainer(); + const html = HTMLSanitizer.sanitize(this.html).getHTML(); + this.containerElement.innerHTML = html; + const walker = walkTree(this.containerElement, { + usingFilter: nodeFilter + }); + + while (walker.nextNode()) { + this.processNode(walker.currentNode); + } + + return this.translateBlockElementMarginsToNewlines(); + } finally { + this.removeHiddenContainer(); + } + } + + createHiddenContainer() { + if (this.referenceElement) { + this.containerElement = this.referenceElement.cloneNode(false); + this.containerElement.removeAttribute("id"); + this.containerElement.setAttribute("data-trix-internal", ""); + this.containerElement.style.display = "none"; + return this.referenceElement.parentNode.insertBefore(this.containerElement, this.referenceElement.nextSibling); + } else { + this.containerElement = makeElement({ + tagName: "div", + style: { + display: "none" + } + }); + return document.body.appendChild(this.containerElement); + } + } + + removeHiddenContainer() { + return removeNode(this.containerElement); + } + + processNode(node) { + switch (node.nodeType) { + case Node.TEXT_NODE: + if (!this.isInsignificantTextNode(node)) { + this.appendBlockForTextNode(node); + return this.processTextNode(node); + } + + break; + + case Node.ELEMENT_NODE: + this.appendBlockForElement(node); + return this.processElement(node); + } + } + + appendBlockForTextNode(node) { + const element = node.parentNode; + + if (element === this.currentBlockElement && this.isBlockElement(node.previousSibling)) { + return this.appendStringWithAttributes("\n"); + } else if (element === this.containerElement || this.isBlockElement(element)) { + var _this$currentBlock; + + const attributes = this.getBlockAttributes(element); + + if (!arraysAreEqual(attributes, (_this$currentBlock = this.currentBlock) === null || _this$currentBlock === void 0 ? void 0 : _this$currentBlock.attributes)) { + this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element); + this.currentBlockElement = element; + } + } + } + + appendBlockForElement(element) { + const elementIsBlockElement = this.isBlockElement(element); + const currentBlockContainsElement = elementContainsNode(this.currentBlockElement, element); + + if (elementIsBlockElement && !this.isBlockElement(element.firstChild)) { + if (!this.isInsignificantTextNode(element.firstChild) || !this.isBlockElement(element.firstElementChild)) { + const attributes = this.getBlockAttributes(element); + + if (element.firstChild) { + if (!(currentBlockContainsElement && arraysAreEqual(attributes, this.currentBlock.attributes))) { + this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element); + this.currentBlockElement = element; + } else { + return this.appendStringWithAttributes("\n"); + } + } + } + } else if (this.currentBlockElement && !currentBlockContainsElement && !elementIsBlockElement) { + const parentBlockElement = this.findParentBlockElement(element); + + if (parentBlockElement) { + return this.appendBlockForElement(parentBlockElement); + } else { + this.currentBlock = this.appendEmptyBlock(); + this.currentBlockElement = null; + } + } + } + + findParentBlockElement(element) { + let { + parentElement + } = element; + + while (parentElement && parentElement !== this.containerElement) { + if (this.isBlockElement(parentElement) && this.blockElements.includes(parentElement)) { + return parentElement; + } else { + parentElement = parentElement.parentElement; + } + } + + return null; + } + + processTextNode(node) { + let string = node.data; + + if (!elementCanDisplayPreformattedText(node.parentNode)) { + var _node$previousSibling; + + string = squishBreakableWhitespace(string); + + if (stringEndsWithWhitespace((_node$previousSibling = node.previousSibling) === null || _node$previousSibling === void 0 ? void 0 : _node$previousSibling.textContent)) { + string = leftTrimBreakableWhitespace(string); + } + } + + return this.appendStringWithAttributes(string, this.getTextAttributes(node.parentNode)); + } + + processElement(element) { + let attributes; + + if (nodeIsAttachmentElement(element)) { + attributes = parseTrixDataAttribute(element, "attachment"); + + if (Object.keys(attributes).length) { + const textAttributes = this.getTextAttributes(element); + this.appendAttachmentWithAttributes(attributes, textAttributes); // We have everything we need so avoid processing inner nodes + + element.innerHTML = ""; + } + + return this.processedElements.push(element); + } else { + switch (tagName(element)) { + case "br": + if (!this.isExtraBR(element) && !this.isBlockElement(element.nextSibling)) { + this.appendStringWithAttributes("\n", this.getTextAttributes(element)); + } + + return this.processedElements.push(element); + + case "img": + attributes = { + url: element.getAttribute("src"), + contentType: "image" + }; + const object = getImageDimensions(element); + + for (const key in object) { + const value = object[key]; + attributes[key] = value; + } + + this.appendAttachmentWithAttributes(attributes, this.getTextAttributes(element)); + return this.processedElements.push(element); + + case "tr": + if (element.parentNode.firstChild !== element) { + return this.appendStringWithAttributes("\n"); + } + + break; + + case "td": + if (element.parentNode.firstChild !== element) { + return this.appendStringWithAttributes(" | "); + } + + break; + } + } + } // Document construction + + + appendBlockForAttributesWithElement(attributes, element) { + this.blockElements.push(element); + const block = blockForAttributes(attributes); + this.blocks.push(block); + return block; + } + + appendEmptyBlock() { + return this.appendBlockForAttributesWithElement([], null); + } + + appendStringWithAttributes(string, attributes) { + return this.appendPiece(pieceForString(string, attributes)); + } + + appendAttachmentWithAttributes(attachment, attributes) { + return this.appendPiece(pieceForAttachment(attachment, attributes)); + } + + appendPiece(piece) { + if (this.blocks.length === 0) { + this.appendEmptyBlock(); + } + + return this.blocks[this.blocks.length - 1].text.push(piece); + } + + appendStringToTextAtIndex(string, index) { + const { + text + } = this.blocks[index]; + const piece = text[text.length - 1]; + + if ((piece === null || piece === void 0 ? void 0 : piece.type) === "string") { + piece.string += string; + } else { + return text.push(pieceForString(string)); + } + } + + prependStringToTextAtIndex(string, index) { + const { + text + } = this.blocks[index]; + const piece = text[0]; + + if ((piece === null || piece === void 0 ? void 0 : piece.type) === "string") { + piece.string = string + piece.string; + } else { + return text.unshift(pieceForString(string)); + } + } // Attribute parsing + + + getTextAttributes(element) { + let value; + const attributes = {}; + + for (const attribute in config.textAttributes) { + const configAttr = config.textAttributes[attribute]; + + if (configAttr.tagName && findClosestElementFromNode(element, { + matchingSelector: configAttr.tagName, + untilNode: this.containerElement + })) { + attributes[attribute] = true; + } else if (configAttr.parser) { + value = configAttr.parser(element); + + if (value) { + let attributeInheritedFromBlock = false; + + for (const blockElement of this.findBlockElementAncestors(element)) { + if (configAttr.parser(blockElement) === value) { + attributeInheritedFromBlock = true; + break; + } + } + + if (!attributeInheritedFromBlock) { + attributes[attribute] = value; + } + } + } else if (configAttr.styleProperty) { + value = element.style[configAttr.styleProperty]; + + if (value) { + attributes[attribute] = value; + } + } + } + + if (nodeIsAttachmentElement(element)) { + const object = parseTrixDataAttribute(element, "attributes"); + + for (const key in object) { + value = object[key]; + attributes[key] = value; + } + } + + return attributes; + } + + getBlockAttributes(element) { + const attributes = []; + + while (element && element !== this.containerElement) { + for (const attribute in config.blockAttributes) { + const attrConfig = config.blockAttributes[attribute]; + + if (attrConfig.parse !== false) { + if (tagName(element) === attrConfig.tagName) { + var _attrConfig$test; + + if ((_attrConfig$test = attrConfig.test) !== null && _attrConfig$test !== void 0 && _attrConfig$test.call(attrConfig, element) || !attrConfig.test) { + attributes.push(attribute); + + if (attrConfig.listAttribute) { + attributes.push(attrConfig.listAttribute); + } + } + } + } + } + + element = element.parentNode; + } + + return attributes.reverse(); + } + + findBlockElementAncestors(element) { + const ancestors = []; + + while (element && element !== this.containerElement) { + const tag = tagName(element); + + if (getBlockTagNames().includes(tag)) { + ancestors.push(element); + } + + element = element.parentNode; + } + + return ancestors; + } // Element inspection + + + isBlockElement(element) { + if ((element === null || element === void 0 ? void 0 : element.nodeType) !== Node.ELEMENT_NODE) { + return; + } + + if (nodeIsAttachmentElement(element)) { + return; + } + + if (findClosestElementFromNode(element, { + matchingSelector: "td", + untilNode: this.containerElement + })) { + return; + } + + return getBlockTagNames().includes(tagName(element)) || window.getComputedStyle(element).display === "block"; + } + + isInsignificantTextNode(node) { + if ((node === null || node === void 0 ? void 0 : node.nodeType) !== Node.TEXT_NODE) { + return; + } + + if (!stringIsAllBreakableWhitespace(node.data)) { + return; + } + + const { + parentNode, + previousSibling, + nextSibling + } = node; + + if (nodeEndsWithNonWhitespace(parentNode.previousSibling) && !this.isBlockElement(parentNode.previousSibling)) { + return; + } + + if (elementCanDisplayPreformattedText(parentNode)) { + return; + } + + return !previousSibling || this.isBlockElement(previousSibling) || !nextSibling || this.isBlockElement(nextSibling); + } + + isExtraBR(element) { + return tagName(element) === "br" && this.isBlockElement(element.parentNode) && element.parentNode.lastChild === element; + } // Margin translation + + + translateBlockElementMarginsToNewlines() { + const defaultMargin = this.getMarginOfDefaultBlockElement(); + + for (let index = 0; index < this.blocks.length; index++) { + const margin = this.getMarginOfBlockElementAtIndex(index); + + if (margin) { + if (margin.top > defaultMargin.top * 2) { + this.prependStringToTextAtIndex("\n", index); + } + + if (margin.bottom > defaultMargin.bottom * 2) { + this.appendStringToTextAtIndex("\n", index); + } + } + } + } + + getMarginOfBlockElementAtIndex(index) { + const element = this.blockElements[index]; + + if (element) { + if (element.textContent) { + if (!getBlockTagNames().includes(tagName(element)) && !this.processedElements.includes(element)) { + return getBlockElementMargin(element); + } + } + } + } + + getMarginOfDefaultBlockElement() { + const element = makeElement(config.blockAttributes.default.tagName); + this.containerElement.appendChild(element); + return getBlockElementMargin(element); + } + +} // Helpers + +const elementCanDisplayPreformattedText = function (element) { + const { + whiteSpace + } = window.getComputedStyle(element); + return ["pre", "pre-wrap", "pre-line"].includes(whiteSpace); +}; + +const nodeEndsWithNonWhitespace = node => node && !stringEndsWithWhitespace(node.textContent); + +const getBlockElementMargin = function (element) { + const style = window.getComputedStyle(element); + + if (style.display === "block") { + return { + top: parseInt(style.marginTop), + bottom: parseInt(style.marginBottom) + }; + } +}; + +const nodeFilter = function (node) { + if (tagName(node) === "style") { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } +}; // Whitespace + + +const leftTrimBreakableWhitespace = string => string.replace(new RegExp("^".concat(breakableWhitespacePattern.source, "+")), ""); + +const stringIsAllBreakableWhitespace = string => new RegExp("^".concat(breakableWhitespacePattern.source, "*$")).test(string); + +const stringEndsWithWhitespace = string => /\s$/.test(string); + +/* eslint-disable + no-empty, +*/ +const unserializableElementSelector = "[data-trix-serialize=false]"; +const unserializableAttributeNames = ["contenteditable", "data-trix-id", "data-trix-store-key", "data-trix-mutable", "data-trix-placeholder", "tabindex"]; +const serializedAttributesAttribute = "data-trix-serialized-attributes"; +const serializedAttributesSelector = "[".concat(serializedAttributesAttribute, "]"); +const blockCommentPattern = new RegExp("", "g"); +const serializers = { + "application/json": function (serializable) { + let document; + + if (serializable instanceof Document) { + document = serializable; + } else if (serializable instanceof HTMLElement) { + document = HTMLParser.parse(serializable.innerHTML).getDocument(); + } else { + throw new Error("unserializable object"); + } + + return document.toSerializableDocument().toJSONString(); + }, + "text/html": function (serializable) { + let element; + + if (serializable instanceof Document) { + element = DocumentView.render(serializable); + } else if (serializable instanceof HTMLElement) { + element = serializable.cloneNode(true); + } else { + throw new Error("unserializable object"); + } // Remove unserializable elements + + + Array.from(element.querySelectorAll(unserializableElementSelector)).forEach(el => { + removeNode(el); + }); // Remove unserializable attributes + + unserializableAttributeNames.forEach(attribute => { + Array.from(element.querySelectorAll("[".concat(attribute, "]"))).forEach(el => { + el.removeAttribute(attribute); + }); + }); // Rewrite elements with serialized attribute overrides + + Array.from(element.querySelectorAll(serializedAttributesSelector)).forEach(el => { + try { + const attributes = JSON.parse(el.getAttribute(serializedAttributesAttribute)); + el.removeAttribute(serializedAttributesAttribute); + + for (const name in attributes) { + const value = attributes[name]; + el.setAttribute(name, value); + } + } catch (error) {} + }); + return element.innerHTML.replace(blockCommentPattern, ""); + } +}; +const deserializers = { + "application/json": function (string) { + return Document.fromJSONString(string); + }, + "text/html": function (string) { + return HTMLParser.parse(string).getDocument(); + } +}; +const serializeToContentType = function (serializable, contentType) { + const serializer = serializers[contentType]; + + if (serializer) { + return serializer(serializable); + } else { + throw new Error("unknown content type: ".concat(contentType)); + } +}; +const deserializeFromContentType = function (string, contentType) { + const deserializer = deserializers[contentType]; + + if (deserializer) { + return deserializer(string); + } else { + throw new Error("unknown content type: ".concat(contentType)); + } +}; + +const mutableAttributeName = "data-trix-mutable"; +const mutableSelector = "[".concat(mutableAttributeName, "]"); +const options = { + attributes: true, + childList: true, + characterData: true, + characterDataOldValue: true, + subtree: true +}; +class MutationObserver extends BasicObject { + constructor(element) { + super(element); + this.didMutate = this.didMutate.bind(this); + this.element = element; + this.observer = new window.MutationObserver(this.didMutate); + this.start(); + } + + start() { + this.reset(); + return this.observer.observe(this.element, options); + } + + stop() { + return this.observer.disconnect(); + } + + didMutate(mutations) { + this.mutations.push(...Array.from(this.findSignificantMutations(mutations) || [])); + + if (this.mutations.length) { + var _this$delegate, _this$delegate$elemen; + + (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? void 0 : (_this$delegate$elemen = _this$delegate.elementDidMutate) === null || _this$delegate$elemen === void 0 ? void 0 : _this$delegate$elemen.call(_this$delegate, this.getMutationSummary()); + return this.reset(); + } + } // Private + + + reset() { + this.mutations = []; + } + + findSignificantMutations(mutations) { + return mutations.filter(mutation => { + return this.mutationIsSignificant(mutation); + }); + } + + mutationIsSignificant(mutation) { + if (this.nodeIsMutable(mutation.target)) { + return false; + } + + for (const node of Array.from(this.nodesModifiedByMutation(mutation))) { + if (this.nodeIsSignificant(node)) return true; + } + + return false; + } + + nodeIsSignificant(node) { + return node !== this.element && !this.nodeIsMutable(node) && !nodeIsEmptyTextNode(node); + } + + nodeIsMutable(node) { + return findClosestElementFromNode(node, { + matchingSelector: mutableSelector + }); + } + + nodesModifiedByMutation(mutation) { + const nodes = []; + + switch (mutation.type) { + case "attributes": + if (mutation.attributeName !== mutableAttributeName) { + nodes.push(mutation.target); + } + + break; + + case "characterData": + // Changes to text nodes should consider the parent element + nodes.push(mutation.target.parentNode); + nodes.push(mutation.target); + break; + + case "childList": + // Consider each added or removed node + nodes.push(...Array.from(mutation.addedNodes || [])); + nodes.push(...Array.from(mutation.removedNodes || [])); + break; + } + + return nodes; + } + + getMutationSummary() { + return this.getTextMutationSummary(); + } + + getTextMutationSummary() { + const { + additions, + deletions + } = this.getTextChangesFromCharacterData(); + const textChanges = this.getTextChangesFromChildList(); + Array.from(textChanges.additions).forEach(addition => { + if (!Array.from(additions).includes(addition)) { + additions.push(addition); + } + }); + deletions.push(...Array.from(textChanges.deletions || [])); + const summary = {}; + const added = additions.join(""); + + if (added) { + summary.textAdded = added; + } + + const deleted = deletions.join(""); + + if (deleted) { + summary.textDeleted = deleted; + } + + return summary; + } + + getMutationsByType(type) { + return Array.from(this.mutations).filter(mutation => mutation.type === type); + } + + getTextChangesFromChildList() { + let textAdded, textRemoved; + const addedNodes = []; + const removedNodes = []; + Array.from(this.getMutationsByType("childList")).forEach(mutation => { + addedNodes.push(...Array.from(mutation.addedNodes || [])); + removedNodes.push(...Array.from(mutation.removedNodes || [])); + }); + const singleBlockCommentRemoved = addedNodes.length === 0 && removedNodes.length === 1 && nodeIsBlockStartComment(removedNodes[0]); + + if (singleBlockCommentRemoved) { + textAdded = []; + textRemoved = ["\n"]; + } else { + textAdded = getTextForNodes(addedNodes); + textRemoved = getTextForNodes(removedNodes); + } + + const additions = textAdded.filter((text, index) => text !== textRemoved[index]).map(normalizeSpaces); + const deletions = textRemoved.filter((text, index) => text !== textAdded[index]).map(normalizeSpaces); + return { + additions, + deletions + }; + } + + getTextChangesFromCharacterData() { + let added, removed; + const characterMutations = this.getMutationsByType("characterData"); + + if (characterMutations.length) { + const startMutation = characterMutations[0], + endMutation = characterMutations[characterMutations.length - 1]; + const oldString = normalizeSpaces(startMutation.oldValue); + const newString = normalizeSpaces(endMutation.target.data); + const summarized = summarizeStringChange(oldString, newString); + added = summarized.added; + removed = summarized.removed; + } + + return { + additions: added ? [added] : [], + deletions: removed ? [removed] : [] + }; + } + +} + +const getTextForNodes = function () { + let nodes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + const text = []; + + for (const node of Array.from(nodes)) { + switch (node.nodeType) { + case Node.TEXT_NODE: + text.push(node.data); + break; + + case Node.ELEMENT_NODE: + if (tagName(node) === "br") { + text.push("\n"); + } else { + text.push(...Array.from(getTextForNodes(node.childNodes) || [])); + } + + break; + } + } + + return text; +}; + +class Controller extends BasicObject {} + +/* eslint-disable + no-empty, +*/ +class FileVerificationOperation extends Operation { + constructor(file) { + super(...arguments); + this.file = file; + } + + perform(callback) { + const reader = new FileReader(); + + reader.onerror = () => callback(false); + + reader.onload = () => { + reader.onerror = null; + + try { + reader.abort(); + } catch (error) {} + + return callback(true, this.file); + }; + + return reader.readAsArrayBuffer(this.file); + } + +} + +class InputController extends BasicObject { + constructor(element) { + super(...arguments); + this.element = element; + this.mutationObserver = new MutationObserver(this.element); + this.mutationObserver.delegate = this; + + for (const eventName in this.constructor.events) { + handleEvent(eventName, { + onElement: this.element, + withCallback: this.handlerFor(eventName) + }); + } + } + + elementDidMutate(mutationSummary) {} + + editorWillSyncDocumentView() { + return this.mutationObserver.stop(); + } + + editorDidSyncDocumentView() { + return this.mutationObserver.start(); + } + + requestRender() { + var _this$delegate, _this$delegate$inputC; + + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? void 0 : (_this$delegate$inputC = _this$delegate.inputControllerDidRequestRender) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate); + } + + requestReparse() { + var _this$delegate2, _this$delegate2$input; + + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : (_this$delegate2$input = _this$delegate2.inputControllerDidRequestReparse) === null || _this$delegate2$input === void 0 ? void 0 : _this$delegate2$input.call(_this$delegate2); + return this.requestRender(); + } + + attachFiles(files) { + const operations = Array.from(files).map(file => new FileVerificationOperation(file)); + return Promise.all(operations).then(files => { + this.handleInput(function () { + var _this$delegate3, _this$responder; + + (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 ? void 0 : _this$delegate3.inputControllerWillAttachFiles(); + (_this$responder = this.responder) === null || _this$responder === void 0 ? void 0 : _this$responder.insertFiles(files); + return this.requestRender(); + }); + }); + } // Private + + + handlerFor(eventName) { + return event => { + if (!event.defaultPrevented) { + this.handleInput(() => { + if (!innerElementIsActive(this.element)) { + this.eventName = eventName; + this.constructor.events[eventName].call(this, event); + } + }); + } + }; + } + + handleInput(callback) { + try { + var _this$delegate4; + + (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 ? void 0 : _this$delegate4.inputControllerWillHandleInput(); + callback.call(this); + } finally { + var _this$delegate5; + + (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 ? void 0 : _this$delegate5.inputControllerDidHandleInput(); + } + } + + createLinkHTML(href, text) { + const link = document.createElement("a"); + link.href = href; + link.textContent = text ? text : href; + return link.outerHTML; + } + +} + +_defineProperty(InputController, "events", {}); + +var _$codePointAt, _; +const { + browser, + keyNames: keyNames$1 +} = config; +let pastedFileCount = 0; +class Level0InputController extends InputController { + constructor() { + super(...arguments); + this.resetInputSummary(); + } + + setInputSummary() { + let summary = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + this.inputSummary.eventName = this.eventName; + + for (const key in summary) { + const value = summary[key]; + this.inputSummary[key] = value; + } + + return this.inputSummary; + } + + resetInputSummary() { + this.inputSummary = {}; + } + + reset() { + this.resetInputSummary(); + return selectionChangeObserver.reset(); + } // Mutation observer delegate + + + elementDidMutate(mutationSummary) { + if (this.isComposing()) { + var _this$delegate, _this$delegate$inputC; + + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? void 0 : (_this$delegate$inputC = _this$delegate.inputControllerDidAllowUnhandledInput) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate); + } else { + return this.handleInput(function () { + if (this.mutationIsSignificant(mutationSummary)) { + if (this.mutationIsExpected(mutationSummary)) { + this.requestRender(); + } else { + this.requestReparse(); + } + } + + return this.reset(); + }); + } + } + + mutationIsExpected(_ref) { + let { + textAdded, + textDeleted + } = _ref; + + if (this.inputSummary.preferDocument) { + return true; + } + + const mutationAdditionMatchesSummary = textAdded != null ? textAdded === this.inputSummary.textAdded : !this.inputSummary.textAdded; + const mutationDeletionMatchesSummary = textDeleted != null ? this.inputSummary.didDelete : !this.inputSummary.didDelete; + const unexpectedNewlineAddition = ["\n", " \n"].includes(textAdded) && !mutationAdditionMatchesSummary; + const unexpectedNewlineDeletion = textDeleted === "\n" && !mutationDeletionMatchesSummary; + const singleUnexpectedNewline = unexpectedNewlineAddition && !unexpectedNewlineDeletion || unexpectedNewlineDeletion && !unexpectedNewlineAddition; + + if (singleUnexpectedNewline) { + const range = this.getSelectedRange(); + + if (range) { + var _this$responder; + + const offset = unexpectedNewlineAddition ? textAdded.replace(/\n$/, "").length || -1 : (textAdded === null || textAdded === void 0 ? void 0 : textAdded.length) || 1; + + if ((_this$responder = this.responder) !== null && _this$responder !== void 0 && _this$responder.positionIsBlockBreak(range[1] + offset)) { + return true; + } + } + } + + return mutationAdditionMatchesSummary && mutationDeletionMatchesSummary; + } + + mutationIsSignificant(mutationSummary) { + var _this$compositionInpu; + + const textChanged = Object.keys(mutationSummary).length > 0; + const composedEmptyString = ((_this$compositionInpu = this.compositionInput) === null || _this$compositionInpu === void 0 ? void 0 : _this$compositionInpu.getEndData()) === ""; + return textChanged || !composedEmptyString; + } // Private + + + getCompositionInput() { + if (this.isComposing()) { + return this.compositionInput; + } else { + this.compositionInput = new CompositionInput(this); + } + } + + isComposing() { + return this.compositionInput && !this.compositionInput.isEnded(); + } + + deleteInDirection(direction, event) { + var _this$responder2; + + if (((_this$responder2 = this.responder) === null || _this$responder2 === void 0 ? void 0 : _this$responder2.deleteInDirection(direction)) === false) { + if (event) { + event.preventDefault(); + return this.requestRender(); + } + } else { + return this.setInputSummary({ + didDelete: true + }); + } + } + + serializeSelectionToDataTransfer(dataTransfer) { + var _this$responder3; + + if (!dataTransferIsWritable(dataTransfer)) { + return; + } + + const document = (_this$responder3 = this.responder) === null || _this$responder3 === void 0 ? void 0 : _this$responder3.getSelectedDocument().toSerializableDocument(); + dataTransfer.setData("application/x-trix-document", JSON.stringify(document)); + dataTransfer.setData("text/html", DocumentView.render(document).innerHTML); + dataTransfer.setData("text/plain", document.toString().replace(/\n$/, "")); + return true; + } + + canAcceptDataTransfer(dataTransfer) { + const types = {}; + Array.from((dataTransfer === null || dataTransfer === void 0 ? void 0 : dataTransfer.types) || []).forEach(type => { + types[type] = true; + }); + return types.Files || types["application/x-trix-document"] || types["text/html"] || types["text/plain"]; + } + + getPastedHTMLUsingHiddenElement(callback) { + const selectedRange = this.getSelectedRange(); + const style = { + position: "absolute", + left: "".concat(window.pageXOffset, "px"), + top: "".concat(window.pageYOffset, "px"), + opacity: 0 + }; + const element = makeElement({ + style, + tagName: "div", + editable: true + }); + document.body.appendChild(element); + element.focus(); + return requestAnimationFrame(() => { + const html = element.innerHTML; + removeNode(element); + this.setSelectedRange(selectedRange); + return callback(html); + }); + } + +} + +_defineProperty(Level0InputController, "events", { + keydown(event) { + if (!this.isComposing()) { + this.resetInputSummary(); + } + + this.inputSummary.didInput = true; + const keyName = keyNames$1[event.keyCode]; + + if (keyName) { + var _context2; + + let context = this.keys; + ["ctrl", "alt", "shift", "meta"].forEach(modifier => { + if (event["".concat(modifier, "Key")]) { + var _context; + + if (modifier === "ctrl") { + modifier = "control"; + } + + context = (_context = context) === null || _context === void 0 ? void 0 : _context[modifier]; + } + }); + + if (((_context2 = context) === null || _context2 === void 0 ? void 0 : _context2[keyName]) != null) { + this.setInputSummary({ + keyName + }); + selectionChangeObserver.reset(); + context[keyName].call(this, event); + } + } + + if (keyEventIsKeyboardCommand(event)) { + const character = String.fromCharCode(event.keyCode).toLowerCase(); + + if (character) { + var _this$delegate3; + + const keys = ["alt", "shift"].map(modifier => { + if (event["".concat(modifier, "Key")]) { + return modifier; + } + }).filter(key => key); + keys.push(character); + + if ((_this$delegate3 = this.delegate) !== null && _this$delegate3 !== void 0 && _this$delegate3.inputControllerDidReceiveKeyboardCommand(keys)) { + event.preventDefault(); + } + } + } + }, + + keypress(event) { + if (this.inputSummary.eventName != null) return; + if (event.metaKey) return; + if (event.ctrlKey && !event.altKey) return; + const string = stringFromKeyEvent(event); + + if (string) { + var _this$delegate4, _this$responder9; + + (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 ? void 0 : _this$delegate4.inputControllerWillPerformTyping(); + (_this$responder9 = this.responder) === null || _this$responder9 === void 0 ? void 0 : _this$responder9.insertString(string); + return this.setInputSummary({ + textAdded: string, + didDelete: this.selectionIsExpanded() + }); + } + }, + + textInput(event) { + // Handle autocapitalization + const { + data + } = event; + const { + textAdded + } = this.inputSummary; + + if (textAdded && textAdded !== data && textAdded.toUpperCase() === data) { + var _this$responder10; + + const range = this.getSelectedRange(); + this.setSelectedRange([range[0], range[1] + textAdded.length]); + (_this$responder10 = this.responder) === null || _this$responder10 === void 0 ? void 0 : _this$responder10.insertString(data); + this.setInputSummary({ + textAdded: data + }); + return this.setSelectedRange(range); + } + }, + + dragenter(event) { + event.preventDefault(); + }, + + dragstart(event) { + var _this$delegate5, _this$delegate5$input; + + this.serializeSelectionToDataTransfer(event.dataTransfer); + this.draggedRange = this.getSelectedRange(); + return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 ? void 0 : (_this$delegate5$input = _this$delegate5.inputControllerDidStartDrag) === null || _this$delegate5$input === void 0 ? void 0 : _this$delegate5$input.call(_this$delegate5); + }, + + dragover(event) { + if (this.draggedRange || this.canAcceptDataTransfer(event.dataTransfer)) { + event.preventDefault(); + const draggingPoint = { + x: event.clientX, + y: event.clientY + }; + + if (!objectsAreEqual(draggingPoint, this.draggingPoint)) { + var _this$delegate6, _this$delegate6$input; + + this.draggingPoint = draggingPoint; + return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 ? void 0 : (_this$delegate6$input = _this$delegate6.inputControllerDidReceiveDragOverPoint) === null || _this$delegate6$input === void 0 ? void 0 : _this$delegate6$input.call(_this$delegate6, this.draggingPoint); + } + } + }, + + dragend(event) { + var _this$delegate7, _this$delegate7$input; + + (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 ? void 0 : (_this$delegate7$input = _this$delegate7.inputControllerDidCancelDrag) === null || _this$delegate7$input === void 0 ? void 0 : _this$delegate7$input.call(_this$delegate7); + this.draggedRange = null; + this.draggingPoint = null; + }, + + drop(event) { + var _event$dataTransfer, _this$responder11; + + event.preventDefault(); + const files = (_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.files; + const documentJSON = event.dataTransfer.getData("application/x-trix-document"); + const point = { + x: event.clientX, + y: event.clientY + }; + (_this$responder11 = this.responder) === null || _this$responder11 === void 0 ? void 0 : _this$responder11.setLocationRangeFromPointRange(point); + + if (files !== null && files !== void 0 && files.length) { + this.attachFiles(files); + } else if (this.draggedRange) { + var _this$delegate8, _this$responder12; + + (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 ? void 0 : _this$delegate8.inputControllerWillMoveText(); + (_this$responder12 = this.responder) === null || _this$responder12 === void 0 ? void 0 : _this$responder12.moveTextFromRange(this.draggedRange); + this.draggedRange = null; + this.requestRender(); + } else if (documentJSON) { + var _this$responder13; + + const document = Document.fromJSONString(documentJSON); + (_this$responder13 = this.responder) === null || _this$responder13 === void 0 ? void 0 : _this$responder13.insertDocument(document); + this.requestRender(); + } + + this.draggedRange = null; + this.draggingPoint = null; + }, + + cut(event) { + var _this$responder14; + + if ((_this$responder14 = this.responder) !== null && _this$responder14 !== void 0 && _this$responder14.selectionIsExpanded()) { + var _this$delegate9; + + if (this.serializeSelectionToDataTransfer(event.clipboardData)) { + event.preventDefault(); + } + + (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 ? void 0 : _this$delegate9.inputControllerWillCutText(); + this.deleteInDirection("backward"); + + if (event.defaultPrevented) { + return this.requestRender(); + } + } + }, + + copy(event) { + var _this$responder15; + + if ((_this$responder15 = this.responder) !== null && _this$responder15 !== void 0 && _this$responder15.selectionIsExpanded()) { + if (this.serializeSelectionToDataTransfer(event.clipboardData)) { + event.preventDefault(); + } + } + }, + + paste(event) { + const clipboard = event.clipboardData || event.testClipboardData; + const paste = { + clipboard + }; + + if (!clipboard || pasteEventIsCrippledSafariHTMLPaste(event)) { + this.getPastedHTMLUsingHiddenElement(html => { + var _this$delegate10, _this$responder16, _this$delegate11; + + paste.type = "text/html"; + paste.html = html; + (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 ? void 0 : _this$delegate10.inputControllerWillPaste(paste); + (_this$responder16 = this.responder) === null || _this$responder16 === void 0 ? void 0 : _this$responder16.insertHTML(paste.html); + this.requestRender(); + return (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 ? void 0 : _this$delegate11.inputControllerDidPaste(paste); + }); + return; + } + + const href = clipboard.getData("URL"); + const html = clipboard.getData("text/html"); + const name = clipboard.getData("public.url-name"); + + if (href) { + var _this$delegate12, _this$responder17, _this$delegate13; + + let string; + paste.type = "text/html"; + + if (name) { + string = squishBreakableWhitespace(name).trim(); + } else { + string = href; + } + + paste.html = this.createLinkHTML(href, string); + (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 ? void 0 : _this$delegate12.inputControllerWillPaste(paste); + this.setInputSummary({ + textAdded: string, + didDelete: this.selectionIsExpanded() + }); + (_this$responder17 = this.responder) === null || _this$responder17 === void 0 ? void 0 : _this$responder17.insertHTML(paste.html); + this.requestRender(); + (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 ? void 0 : _this$delegate13.inputControllerDidPaste(paste); + } else if (dataTransferIsPlainText(clipboard)) { + var _this$delegate14, _this$responder18, _this$delegate15; + + paste.type = "text/plain"; + paste.string = clipboard.getData("text/plain"); + (_this$delegate14 = this.delegate) === null || _this$delegate14 === void 0 ? void 0 : _this$delegate14.inputControllerWillPaste(paste); + this.setInputSummary({ + textAdded: paste.string, + didDelete: this.selectionIsExpanded() + }); + (_this$responder18 = this.responder) === null || _this$responder18 === void 0 ? void 0 : _this$responder18.insertString(paste.string); + this.requestRender(); + (_this$delegate15 = this.delegate) === null || _this$delegate15 === void 0 ? void 0 : _this$delegate15.inputControllerDidPaste(paste); + } else if (html) { + var _this$delegate16, _this$responder19, _this$delegate17; + + paste.type = "text/html"; + paste.html = html; + (_this$delegate16 = this.delegate) === null || _this$delegate16 === void 0 ? void 0 : _this$delegate16.inputControllerWillPaste(paste); + (_this$responder19 = this.responder) === null || _this$responder19 === void 0 ? void 0 : _this$responder19.insertHTML(paste.html); + this.requestRender(); + (_this$delegate17 = this.delegate) === null || _this$delegate17 === void 0 ? void 0 : _this$delegate17.inputControllerDidPaste(paste); + } else if (Array.from(clipboard.types).includes("Files")) { + var _clipboard$items, _clipboard$items$, _clipboard$items$$get; + + const file = (_clipboard$items = clipboard.items) === null || _clipboard$items === void 0 ? void 0 : (_clipboard$items$ = _clipboard$items[0]) === null || _clipboard$items$ === void 0 ? void 0 : (_clipboard$items$$get = _clipboard$items$.getAsFile) === null || _clipboard$items$$get === void 0 ? void 0 : _clipboard$items$$get.call(_clipboard$items$); + + if (file) { + var _this$delegate18, _this$responder20, _this$delegate19; + + const extension = extensionForFile(file); + + if (!file.name && extension) { + file.name = "pasted-file-".concat(++pastedFileCount, ".").concat(extension); + } + + paste.type = "File"; + paste.file = file; + (_this$delegate18 = this.delegate) === null || _this$delegate18 === void 0 ? void 0 : _this$delegate18.inputControllerWillAttachFiles(); + (_this$responder20 = this.responder) === null || _this$responder20 === void 0 ? void 0 : _this$responder20.insertFile(paste.file); + this.requestRender(); + (_this$delegate19 = this.delegate) === null || _this$delegate19 === void 0 ? void 0 : _this$delegate19.inputControllerDidPaste(paste); + } + } + + event.preventDefault(); + }, + + compositionstart(event) { + return this.getCompositionInput().start(event.data); + }, + + compositionupdate(event) { + return this.getCompositionInput().update(event.data); + }, + + compositionend(event) { + return this.getCompositionInput().end(event.data); + }, + + beforeinput(event) { + this.inputSummary.didInput = true; + }, + + input(event) { + this.inputSummary.didInput = true; + return event.stopPropagation(); + } + +}); + +_defineProperty(Level0InputController, "keys", { + backspace(event) { + var _this$delegate20; + + (_this$delegate20 = this.delegate) === null || _this$delegate20 === void 0 ? void 0 : _this$delegate20.inputControllerWillPerformTyping(); + return this.deleteInDirection("backward", event); + }, + + delete(event) { + var _this$delegate21; + + (_this$delegate21 = this.delegate) === null || _this$delegate21 === void 0 ? void 0 : _this$delegate21.inputControllerWillPerformTyping(); + return this.deleteInDirection("forward", event); + }, + + return(event) { + var _this$delegate22, _this$responder21; + + this.setInputSummary({ + preferDocument: true + }); + (_this$delegate22 = this.delegate) === null || _this$delegate22 === void 0 ? void 0 : _this$delegate22.inputControllerWillPerformTyping(); + return (_this$responder21 = this.responder) === null || _this$responder21 === void 0 ? void 0 : _this$responder21.insertLineBreak(); + }, + + tab(event) { + var _this$responder22; + + if ((_this$responder22 = this.responder) !== null && _this$responder22 !== void 0 && _this$responder22.canIncreaseNestingLevel()) { + var _this$responder23; + + (_this$responder23 = this.responder) === null || _this$responder23 === void 0 ? void 0 : _this$responder23.increaseNestingLevel(); + this.requestRender(); + event.preventDefault(); + } + }, + + left(event) { + if (this.selectionIsInCursorTarget()) { + var _this$responder24; + + event.preventDefault(); + return (_this$responder24 = this.responder) === null || _this$responder24 === void 0 ? void 0 : _this$responder24.moveCursorInDirection("backward"); + } + }, + + right(event) { + if (this.selectionIsInCursorTarget()) { + var _this$responder25; + + event.preventDefault(); + return (_this$responder25 = this.responder) === null || _this$responder25 === void 0 ? void 0 : _this$responder25.moveCursorInDirection("forward"); + } + }, + + control: { + d(event) { + var _this$delegate23; + + (_this$delegate23 = this.delegate) === null || _this$delegate23 === void 0 ? void 0 : _this$delegate23.inputControllerWillPerformTyping(); + return this.deleteInDirection("forward", event); + }, + + h(event) { + var _this$delegate24; + + (_this$delegate24 = this.delegate) === null || _this$delegate24 === void 0 ? void 0 : _this$delegate24.inputControllerWillPerformTyping(); + return this.deleteInDirection("backward", event); + }, + + o(event) { + var _this$delegate25, _this$responder26; + + event.preventDefault(); + (_this$delegate25 = this.delegate) === null || _this$delegate25 === void 0 ? void 0 : _this$delegate25.inputControllerWillPerformTyping(); + (_this$responder26 = this.responder) === null || _this$responder26 === void 0 ? void 0 : _this$responder26.insertString("\n", { + updatePosition: false + }); + return this.requestRender(); + } + + }, + shift: { + return(event) { + var _this$delegate26, _this$responder27; + + (_this$delegate26 = this.delegate) === null || _this$delegate26 === void 0 ? void 0 : _this$delegate26.inputControllerWillPerformTyping(); + (_this$responder27 = this.responder) === null || _this$responder27 === void 0 ? void 0 : _this$responder27.insertString("\n"); + this.requestRender(); + event.preventDefault(); + }, + + tab(event) { + var _this$responder28; + + if ((_this$responder28 = this.responder) !== null && _this$responder28 !== void 0 && _this$responder28.canDecreaseNestingLevel()) { + var _this$responder29; + + (_this$responder29 = this.responder) === null || _this$responder29 === void 0 ? void 0 : _this$responder29.decreaseNestingLevel(); + this.requestRender(); + event.preventDefault(); + } + }, + + left(event) { + if (this.selectionIsInCursorTarget()) { + event.preventDefault(); + return this.expandSelectionInDirection("backward"); + } + }, + + right(event) { + if (this.selectionIsInCursorTarget()) { + event.preventDefault(); + return this.expandSelectionInDirection("forward"); + } + } + + }, + alt: { + backspace(event) { + var _this$delegate27; + + this.setInputSummary({ + preferDocument: false + }); + return (_this$delegate27 = this.delegate) === null || _this$delegate27 === void 0 ? void 0 : _this$delegate27.inputControllerWillPerformTyping(); + } + + }, + meta: { + backspace(event) { + var _this$delegate28; + + this.setInputSummary({ + preferDocument: false + }); + return (_this$delegate28 = this.delegate) === null || _this$delegate28 === void 0 ? void 0 : _this$delegate28.inputControllerWillPerformTyping(); + } + + } +}); + +Level0InputController.proxyMethod("responder?.getSelectedRange"); +Level0InputController.proxyMethod("responder?.setSelectedRange"); +Level0InputController.proxyMethod("responder?.expandSelectionInDirection"); +Level0InputController.proxyMethod("responder?.selectionIsInCursorTarget"); +Level0InputController.proxyMethod("responder?.selectionIsExpanded"); + +const extensionForFile = file => { + var _file$type, _file$type$match; + + return (_file$type = file.type) === null || _file$type === void 0 ? void 0 : (_file$type$match = _file$type.match(/\/(\w+)$/)) === null || _file$type$match === void 0 ? void 0 : _file$type$match[1]; +}; + +const hasStringCodePointAt = !!((_$codePointAt = (_ = " ").codePointAt) !== null && _$codePointAt !== void 0 && _$codePointAt.call(_, 0)); + +const stringFromKeyEvent = function (event) { + if (event.key && hasStringCodePointAt && event.key.codePointAt(0) === event.keyCode) { + return event.key; + } else { + let code; + + if (event.which === null) { + code = event.keyCode; + } else if (event.which !== 0 && event.charCode !== 0) { + code = event.charCode; + } + + if (code != null && keyNames$1[code] !== "escape") { + return UTF16String.fromCodepoints([code]).toString(); + } + } +}; + +const pasteEventIsCrippledSafariHTMLPaste = function (event) { + const paste = event.clipboardData; + + if (paste) { + if (paste.types.includes("text/html")) { + // Answer is yes if there's any possibility of Paste and Match Style in Safari, + // which is nearly impossible to detect confidently: https://bugs.webkit.org/show_bug.cgi?id=174165 + for (const type of paste.types) { + const hasPasteboardFlavor = /^CorePasteboardFlavorType/.test(type); + const hasReadableDynamicData = /^dyn\./.test(type) && paste.getData(type); + const mightBePasteAndMatchStyle = hasPasteboardFlavor || hasReadableDynamicData; + + if (mightBePasteAndMatchStyle) { + return true; + } + } + + return false; + } else { + const isExternalHTMLPaste = paste.types.includes("com.apple.webarchive"); + const isExternalRichTextPaste = paste.types.includes("com.apple.flat-rtfd"); + return isExternalHTMLPaste || isExternalRichTextPaste; + } + } +}; + +class CompositionInput extends BasicObject { + constructor(inputController) { + super(...arguments); + this.inputController = inputController; + this.responder = this.inputController.responder; + this.delegate = this.inputController.delegate; + this.inputSummary = this.inputController.inputSummary; + this.data = {}; + } + + start(data) { + this.data.start = data; + + if (this.isSignificant()) { + var _this$responder5; + + if (this.inputSummary.eventName === "keypress" && this.inputSummary.textAdded) { + var _this$responder4; + + (_this$responder4 = this.responder) === null || _this$responder4 === void 0 ? void 0 : _this$responder4.deleteInDirection("left"); + } + + if (!this.selectionIsExpanded()) { + this.insertPlaceholder(); + this.requestRender(); + } + + this.range = (_this$responder5 = this.responder) === null || _this$responder5 === void 0 ? void 0 : _this$responder5.getSelectedRange(); + } + } + + update(data) { + this.data.update = data; + + if (this.isSignificant()) { + const range = this.selectPlaceholder(); + + if (range) { + this.forgetPlaceholder(); + this.range = range; + } + } + } + + end(data) { + this.data.end = data; + + if (this.isSignificant()) { + this.forgetPlaceholder(); + + if (this.canApplyToDocument()) { + var _this$delegate2, _this$responder6, _this$responder7, _this$responder8; + + this.setInputSummary({ + preferDocument: true, + didInput: false + }); + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2.inputControllerWillPerformTyping(); + (_this$responder6 = this.responder) === null || _this$responder6 === void 0 ? void 0 : _this$responder6.setSelectedRange(this.range); + (_this$responder7 = this.responder) === null || _this$responder7 === void 0 ? void 0 : _this$responder7.insertString(this.data.end); + return (_this$responder8 = this.responder) === null || _this$responder8 === void 0 ? void 0 : _this$responder8.setSelectedRange(this.range[0] + this.data.end.length); + } else if (this.data.start != null || this.data.update != null) { + this.requestReparse(); + return this.inputController.reset(); + } + } else { + return this.inputController.reset(); + } + } + + getEndData() { + return this.data.end; + } + + isEnded() { + return this.getEndData() != null; + } + + isSignificant() { + if (browser.composesExistingText) { + return this.inputSummary.didInput; + } else { + return true; + } + } // Private + + + canApplyToDocument() { + var _this$data$start, _this$data$end; + + 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; + } + +} + +CompositionInput.proxyMethod("inputController.setInputSummary"); +CompositionInput.proxyMethod("inputController.requestRender"); +CompositionInput.proxyMethod("inputController.requestReparse"); +CompositionInput.proxyMethod("responder?.selectionIsExpanded"); +CompositionInput.proxyMethod("responder?.insertPlaceholder"); +CompositionInput.proxyMethod("responder?.selectPlaceholder"); +CompositionInput.proxyMethod("responder?.forgetPlaceholder"); + +class Level2InputController extends InputController { + constructor() { + super(...arguments); + this.render = this.render.bind(this); + } + + elementDidMutate() { + if (this.scheduledRender) { + if (this.composing) { + var _this$delegate, _this$delegate$inputC; + + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? void 0 : (_this$delegate$inputC = _this$delegate.inputControllerDidAllowUnhandledInput) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate); + } + } else { + return this.reparse(); + } + } + + scheduleRender() { + return this.scheduledRender ? this.scheduledRender : this.scheduledRender = requestAnimationFrame(this.render); + } + + render() { + var _this$afterRender; + + cancelAnimationFrame(this.scheduledRender); + this.scheduledRender = null; + + if (!this.composing) { + var _this$delegate2; + + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2.render(); + } + + (_this$afterRender = this.afterRender) === null || _this$afterRender === void 0 ? void 0 : _this$afterRender.call(this); + this.afterRender = null; + } + + reparse() { + var _this$delegate3; + + return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 ? void 0 : _this$delegate3.reparse(); + } // Responder helpers + + + insertString() { + var _this$delegate4; + + let string = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + let options = arguments.length > 1 ? arguments[1] : undefined; + (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 ? void 0 : _this$delegate4.inputControllerWillPerformTyping(); + return this.withTargetDOMRange(function () { + var _this$responder; + + return (_this$responder = this.responder) === null || _this$responder === void 0 ? void 0 : _this$responder.insertString(string, options); + }); + } + + toggleAttributeIfSupported(attributeName) { + if (getAllAttributeNames().includes(attributeName)) { + var _this$delegate5; + + (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 ? void 0 : _this$delegate5.inputControllerWillPerformFormatting(attributeName); + return this.withTargetDOMRange(function () { + var _this$responder2; + + return (_this$responder2 = this.responder) === null || _this$responder2 === void 0 ? void 0 : _this$responder2.toggleCurrentAttribute(attributeName); + }); + } + } + + activateAttributeIfSupported(attributeName, value) { + if (getAllAttributeNames().includes(attributeName)) { + var _this$delegate6; + + (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 ? void 0 : _this$delegate6.inputControllerWillPerformFormatting(attributeName); + return this.withTargetDOMRange(function () { + var _this$responder3; + + return (_this$responder3 = this.responder) === null || _this$responder3 === void 0 ? void 0 : _this$responder3.setCurrentAttribute(attributeName, value); + }); + } + } + + deleteInDirection(direction) { + let { + recordUndoEntry + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + recordUndoEntry: true + }; + + if (recordUndoEntry) { + var _this$delegate7; + + (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 ? void 0 : _this$delegate7.inputControllerWillPerformTyping(); + } + + const perform = () => { + var _this$responder4; + + return (_this$responder4 = this.responder) === null || _this$responder4 === void 0 ? void 0 : _this$responder4.deleteInDirection(direction); + }; + + const domRange = this.getTargetDOMRange({ + minLength: 2 + }); + + if (domRange) { + return this.withTargetDOMRange(domRange, perform); + } else { + return perform(); + } + } // Selection helpers + + + withTargetDOMRange(domRange, fn) { + if (typeof domRange === "function") { + fn = domRange; + domRange = this.getTargetDOMRange(); + } + + if (domRange) { + var _this$responder5; + + return (_this$responder5 = this.responder) === null || _this$responder5 === void 0 ? void 0 : _this$responder5.withTargetDOMRange(domRange, fn.bind(this)); + } else { + selectionChangeObserver.reset(); + return fn.call(this); + } + } + + getTargetDOMRange() { + var _this$event$getTarget, _this$event; + + let { + minLength + } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { + minLength: 0 + }; + const targetRanges = (_this$event$getTarget = (_this$event = this.event).getTargetRanges) === null || _this$event$getTarget === void 0 ? void 0 : _this$event$getTarget.call(_this$event); + + if (targetRanges) { + if (targetRanges.length) { + const domRange = staticRangeToRange(targetRanges[0]); + + if (minLength === 0 || domRange.toString().length >= minLength) { + return domRange; + } + } + } + } + + withEvent(event, fn) { + let result; + this.event = event; + + try { + result = fn.call(this); + } finally { + this.event = null; + } + + return result; + } + +} + +_defineProperty(Level2InputController, "events", { + keydown(event) { + if (keyEventIsKeyboardCommand(event)) { + var _this$delegate8; + + const command = keyboardCommandFromKeyEvent(event); + + if ((_this$delegate8 = this.delegate) !== null && _this$delegate8 !== void 0 && _this$delegate8.inputControllerDidReceiveKeyboardCommand(command)) { + event.preventDefault(); + } + } else { + let name = event.key; + + if (event.altKey) { + name += "+Alt"; + } + + if (event.shiftKey) { + name += "+Shift"; + } + + const handler = this.constructor.keys[name]; + + if (handler) { + return this.withEvent(event, handler); + } + } + }, + + // Handle paste event to work around beforeinput.insertFromPaste browser bugs. + // Safe to remove each condition once fixed upstream. + paste(event) { + var _event$clipboardData; + + // https://bugs.webkit.org/show_bug.cgi?id=194921 + let paste; + const href = (_event$clipboardData = event.clipboardData) === null || _event$clipboardData === void 0 ? void 0 : _event$clipboardData.getData("URL"); + + if (pasteEventHasFilesOnly(event)) { + event.preventDefault(); + return this.attachFiles(event.clipboardData.files); // https://bugs.chromium.org/p/chromium/issues/detail?id=934448 + } else if (pasteEventHasPlainTextOnly(event)) { + var _this$delegate9, _this$responder6, _this$delegate10; + + event.preventDefault(); + paste = { + type: "text/plain", + string: event.clipboardData.getData("text/plain") + }; + (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 ? void 0 : _this$delegate9.inputControllerWillPaste(paste); + (_this$responder6 = this.responder) === null || _this$responder6 === void 0 ? void 0 : _this$responder6.insertString(paste.string); + this.render(); + return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 ? void 0 : _this$delegate10.inputControllerDidPaste(paste); // https://bugs.webkit.org/show_bug.cgi?id=196702 + } else if (href) { + var _this$delegate11, _this$responder7, _this$delegate12; + + event.preventDefault(); + paste = { + type: "text/html", + html: this.createLinkHTML(href) + }; + (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 ? void 0 : _this$delegate11.inputControllerWillPaste(paste); + (_this$responder7 = this.responder) === null || _this$responder7 === void 0 ? void 0 : _this$responder7.insertHTML(paste.html); + this.render(); + return (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 ? void 0 : _this$delegate12.inputControllerDidPaste(paste); + } + }, + + beforeinput(event) { + const handler = this.constructor.inputTypes[event.inputType]; + + if (handler) { + this.withEvent(event, handler); + return this.scheduleRender(); + } + }, + + input(event) { + return selectionChangeObserver.reset(); + }, + + dragstart(event) { + var _this$responder8; + + if ((_this$responder8 = this.responder) !== null && _this$responder8 !== void 0 && _this$responder8.selectionContainsAttachments()) { + var _this$responder9; + + event.dataTransfer.setData("application/x-trix-dragging", true); + this.dragging = { + range: (_this$responder9 = this.responder) === null || _this$responder9 === void 0 ? void 0 : _this$responder9.getSelectedRange(), + point: pointFromEvent(event) + }; + } + }, + + dragenter(event) { + if (dragEventHasFiles(event)) { + event.preventDefault(); + } + }, + + dragover(event) { + if (this.dragging) { + event.preventDefault(); + const point = pointFromEvent(event); + + if (!objectsAreEqual(point, this.dragging.point)) { + var _this$responder10; + + this.dragging.point = point; + return (_this$responder10 = this.responder) === null || _this$responder10 === void 0 ? void 0 : _this$responder10.setLocationRangeFromPointRange(point); + } + } else if (dragEventHasFiles(event)) { + event.preventDefault(); + } + }, + + drop(event) { + if (this.dragging) { + var _this$delegate13, _this$responder11; + + event.preventDefault(); + (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 ? void 0 : _this$delegate13.inputControllerWillMoveText(); + (_this$responder11 = this.responder) === null || _this$responder11 === void 0 ? void 0 : _this$responder11.moveTextFromRange(this.dragging.range); + this.dragging = null; + return this.scheduleRender(); + } else if (dragEventHasFiles(event)) { + var _this$responder12; + + event.preventDefault(); + const point = pointFromEvent(event); + (_this$responder12 = this.responder) === null || _this$responder12 === void 0 ? void 0 : _this$responder12.setLocationRangeFromPointRange(point); + return this.attachFiles(event.dataTransfer.files); + } + }, + + dragend() { + if (this.dragging) { + var _this$responder13; + + (_this$responder13 = this.responder) === null || _this$responder13 === void 0 ? void 0 : _this$responder13.setSelectedRange(this.dragging.range); + this.dragging = null; + } + }, + + compositionend(event) { + if (this.composing) { + this.composing = false; + return this.scheduleRender(); + } + } + +}); + +_defineProperty(Level2InputController, "keys", { + ArrowLeft() { + var _this$responder14; + + if ((_this$responder14 = this.responder) !== null && _this$responder14 !== void 0 && _this$responder14.shouldManageMovingCursorInDirection("backward")) { + var _this$responder15; + + this.event.preventDefault(); + return (_this$responder15 = this.responder) === null || _this$responder15 === void 0 ? void 0 : _this$responder15.moveCursorInDirection("backward"); + } + }, + + ArrowRight() { + var _this$responder16; + + if ((_this$responder16 = this.responder) !== null && _this$responder16 !== void 0 && _this$responder16.shouldManageMovingCursorInDirection("forward")) { + var _this$responder17; + + this.event.preventDefault(); + return (_this$responder17 = this.responder) === null || _this$responder17 === void 0 ? void 0 : _this$responder17.moveCursorInDirection("forward"); + } + }, + + Backspace() { + var _this$responder18; + + if ((_this$responder18 = this.responder) !== null && _this$responder18 !== void 0 && _this$responder18.shouldManageDeletingInDirection("backward")) { + var _this$delegate14, _this$responder19; + + this.event.preventDefault(); + (_this$delegate14 = this.delegate) === null || _this$delegate14 === void 0 ? void 0 : _this$delegate14.inputControllerWillPerformTyping(); + (_this$responder19 = this.responder) === null || _this$responder19 === void 0 ? void 0 : _this$responder19.deleteInDirection("backward"); + return this.render(); + } + }, + + Tab() { + var _this$responder20; + + if ((_this$responder20 = this.responder) !== null && _this$responder20 !== void 0 && _this$responder20.canIncreaseNestingLevel()) { + var _this$responder21; + + this.event.preventDefault(); + (_this$responder21 = this.responder) === null || _this$responder21 === void 0 ? void 0 : _this$responder21.increaseNestingLevel(); + return this.render(); + } + }, + + "Tab+Shift"() { + var _this$responder22; + + if ((_this$responder22 = this.responder) !== null && _this$responder22 !== void 0 && _this$responder22.canDecreaseNestingLevel()) { + var _this$responder23; + + this.event.preventDefault(); + (_this$responder23 = this.responder) === null || _this$responder23 === void 0 ? void 0 : _this$responder23.decreaseNestingLevel(); + return this.render(); + } + } + +}); + +_defineProperty(Level2InputController, "inputTypes", { + deleteByComposition() { + return this.deleteInDirection("backward", { + recordUndoEntry: false + }); + }, + + deleteByCut() { + return this.deleteInDirection("backward"); + }, + + deleteByDrag() { + this.event.preventDefault(); + return this.withTargetDOMRange(function () { + var _this$responder24; + + this.deleteByDragRange = (_this$responder24 = this.responder) === null || _this$responder24 === void 0 ? void 0 : _this$responder24.getSelectedRange(); + }); + }, + + deleteCompositionText() { + return this.deleteInDirection("backward", { + recordUndoEntry: false + }); + }, + + deleteContent() { + return this.deleteInDirection("backward"); + }, + + deleteContentBackward() { + return this.deleteInDirection("backward"); + }, + + deleteContentForward() { + return this.deleteInDirection("forward"); + }, + + deleteEntireSoftLine() { + return this.deleteInDirection("forward"); + }, + + deleteHardLineBackward() { + return this.deleteInDirection("backward"); + }, + + deleteHardLineForward() { + return this.deleteInDirection("forward"); + }, + + deleteSoftLineBackward() { + return this.deleteInDirection("backward"); + }, + + deleteSoftLineForward() { + return this.deleteInDirection("forward"); + }, + + deleteWordBackward() { + return this.deleteInDirection("backward"); + }, + + deleteWordForward() { + return this.deleteInDirection("forward"); + }, + + formatBackColor() { + return this.activateAttributeIfSupported("backgroundColor", this.event.data); + }, + + formatBold() { + return this.toggleAttributeIfSupported("bold"); + }, + + formatFontColor() { + return this.activateAttributeIfSupported("color", this.event.data); + }, + + formatFontName() { + return this.activateAttributeIfSupported("font", this.event.data); + }, + + formatIndent() { + var _this$responder25; + + if ((_this$responder25 = this.responder) !== null && _this$responder25 !== void 0 && _this$responder25.canIncreaseNestingLevel()) { + return this.withTargetDOMRange(function () { + var _this$responder26; + + return (_this$responder26 = this.responder) === null || _this$responder26 === void 0 ? void 0 : _this$responder26.increaseNestingLevel(); + }); + } + }, + + formatItalic() { + return this.toggleAttributeIfSupported("italic"); + }, + + formatJustifyCenter() { + return this.toggleAttributeIfSupported("justifyCenter"); + }, + + formatJustifyFull() { + return this.toggleAttributeIfSupported("justifyFull"); + }, + + formatJustifyLeft() { + return this.toggleAttributeIfSupported("justifyLeft"); + }, + + formatJustifyRight() { + return this.toggleAttributeIfSupported("justifyRight"); + }, + + formatOutdent() { + var _this$responder27; + + if ((_this$responder27 = this.responder) !== null && _this$responder27 !== void 0 && _this$responder27.canDecreaseNestingLevel()) { + return this.withTargetDOMRange(function () { + var _this$responder28; + + return (_this$responder28 = this.responder) === null || _this$responder28 === void 0 ? void 0 : _this$responder28.decreaseNestingLevel(); + }); + } + }, + + formatRemove() { + this.withTargetDOMRange(function () { + for (const attributeName in (_this$responder29 = this.responder) === null || _this$responder29 === void 0 ? void 0 : _this$responder29.getCurrentAttributes()) { + var _this$responder29, _this$responder30; + + (_this$responder30 = this.responder) === null || _this$responder30 === void 0 ? void 0 : _this$responder30.removeCurrentAttribute(attributeName); + } + }); + }, + + formatSetBlockTextDirection() { + return this.activateAttributeIfSupported("blockDir", this.event.data); + }, + + formatSetInlineTextDirection() { + return this.activateAttributeIfSupported("textDir", this.event.data); + }, + + formatStrikeThrough() { + return this.toggleAttributeIfSupported("strike"); + }, + + formatSubscript() { + return this.toggleAttributeIfSupported("sub"); + }, + + formatSuperscript() { + return this.toggleAttributeIfSupported("sup"); + }, + + formatUnderline() { + return this.toggleAttributeIfSupported("underline"); + }, + + historyRedo() { + var _this$delegate15; + + return (_this$delegate15 = this.delegate) === null || _this$delegate15 === void 0 ? void 0 : _this$delegate15.inputControllerWillPerformRedo(); + }, + + historyUndo() { + var _this$delegate16; + + return (_this$delegate16 = this.delegate) === null || _this$delegate16 === void 0 ? void 0 : _this$delegate16.inputControllerWillPerformUndo(); + }, + + insertCompositionText() { + this.composing = true; + return this.insertString(this.event.data); + }, + + insertFromComposition() { + this.composing = false; + return this.insertString(this.event.data); + }, + + insertFromDrop() { + const range = this.deleteByDragRange; + + if (range) { + var _this$delegate17; + + this.deleteByDragRange = null; + (_this$delegate17 = this.delegate) === null || _this$delegate17 === void 0 ? void 0 : _this$delegate17.inputControllerWillMoveText(); + return this.withTargetDOMRange(function () { + var _this$responder31; + + return (_this$responder31 = this.responder) === null || _this$responder31 === void 0 ? void 0 : _this$responder31.moveTextFromRange(range); + }); + } + }, + + insertFromPaste() { + var _dataTransfer$files; + + const { + dataTransfer + } = this.event; + const paste = { + dataTransfer + }; + const href = dataTransfer.getData("URL"); + const html = dataTransfer.getData("text/html"); + + if (href) { + var _this$delegate18; + + let string; + this.event.preventDefault(); + paste.type = "text/html"; + const name = dataTransfer.getData("public.url-name"); + + if (name) { + string = squishBreakableWhitespace(name).trim(); + } else { + string = href; + } + + paste.html = this.createLinkHTML(href, string); + (_this$delegate18 = this.delegate) === null || _this$delegate18 === void 0 ? void 0 : _this$delegate18.inputControllerWillPaste(paste); + this.withTargetDOMRange(function () { + var _this$responder32; + + return (_this$responder32 = this.responder) === null || _this$responder32 === void 0 ? void 0 : _this$responder32.insertHTML(paste.html); + }); + + this.afterRender = () => { + var _this$delegate19; + + return (_this$delegate19 = this.delegate) === null || _this$delegate19 === void 0 ? void 0 : _this$delegate19.inputControllerDidPaste(paste); + }; + } else if (dataTransferIsPlainText(dataTransfer)) { + var _this$delegate20; + + paste.type = "text/plain"; + paste.string = dataTransfer.getData("text/plain"); + (_this$delegate20 = this.delegate) === null || _this$delegate20 === void 0 ? void 0 : _this$delegate20.inputControllerWillPaste(paste); + this.withTargetDOMRange(function () { + var _this$responder33; + + return (_this$responder33 = this.responder) === null || _this$responder33 === void 0 ? void 0 : _this$responder33.insertString(paste.string); + }); + + this.afterRender = () => { + var _this$delegate21; + + return (_this$delegate21 = this.delegate) === null || _this$delegate21 === void 0 ? void 0 : _this$delegate21.inputControllerDidPaste(paste); + }; + } else if (html) { + var _this$delegate22; + + this.event.preventDefault(); + paste.type = "text/html"; + paste.html = html; + (_this$delegate22 = this.delegate) === null || _this$delegate22 === void 0 ? void 0 : _this$delegate22.inputControllerWillPaste(paste); + this.withTargetDOMRange(function () { + var _this$responder34; + + return (_this$responder34 = this.responder) === null || _this$responder34 === void 0 ? void 0 : _this$responder34.insertHTML(paste.html); + }); + + this.afterRender = () => { + var _this$delegate23; + + return (_this$delegate23 = this.delegate) === null || _this$delegate23 === void 0 ? void 0 : _this$delegate23.inputControllerDidPaste(paste); + }; + } else if ((_dataTransfer$files = dataTransfer.files) !== null && _dataTransfer$files !== void 0 && _dataTransfer$files.length) { + var _this$delegate24; + + paste.type = "File"; + paste.file = dataTransfer.files[0]; + (_this$delegate24 = this.delegate) === null || _this$delegate24 === void 0 ? void 0 : _this$delegate24.inputControllerWillPaste(paste); + this.withTargetDOMRange(function () { + var _this$responder35; + + return (_this$responder35 = this.responder) === null || _this$responder35 === void 0 ? void 0 : _this$responder35.insertFile(paste.file); + }); + + this.afterRender = () => { + var _this$delegate25; + + return (_this$delegate25 = this.delegate) === null || _this$delegate25 === void 0 ? void 0 : _this$delegate25.inputControllerDidPaste(paste); + }; + } + }, + + insertFromYank() { + return this.insertString(this.event.data); + }, + + insertLineBreak() { + return this.insertString("\n"); + }, + + insertLink() { + return this.activateAttributeIfSupported("href", this.event.data); + }, + + insertOrderedList() { + return this.toggleAttributeIfSupported("number"); + }, + + insertParagraph() { + var _this$delegate26; + + (_this$delegate26 = this.delegate) === null || _this$delegate26 === void 0 ? void 0 : _this$delegate26.inputControllerWillPerformTyping(); + return this.withTargetDOMRange(function () { + var _this$responder36; + + return (_this$responder36 = this.responder) === null || _this$responder36 === void 0 ? void 0 : _this$responder36.insertLineBreak(); + }); + }, + + insertReplacementText() { + return this.insertString(this.event.dataTransfer.getData("text/plain"), { + updatePosition: false + }); + }, + + insertText() { + var _this$event$dataTrans; + + 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"))); + }, + + insertTranspose() { + return this.insertString(this.event.data); + }, + + insertUnorderedList() { + return this.toggleAttributeIfSupported("bullet"); + } + +}); + +const staticRangeToRange = function (staticRange) { + const range = document.createRange(); + range.setStart(staticRange.startContainer, staticRange.startOffset); + range.setEnd(staticRange.endContainer, staticRange.endOffset); + return range; +}; // Event helpers + + +const dragEventHasFiles = event => { + var _event$dataTransfer; + + return Array.from(((_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.types) || []).includes("Files"); +}; + +const pasteEventHasFilesOnly = function (event) { + const clipboard = event.clipboardData; + + if (clipboard) { + return clipboard.types.includes("Files") && clipboard.types.length === 1 && clipboard.files.length >= 1; + } +}; + +const pasteEventHasPlainTextOnly = function (event) { + const clipboard = event.clipboardData; + + if (clipboard) { + return clipboard.types.includes("text/plain") && clipboard.types.length === 1; + } +}; + +const keyboardCommandFromKeyEvent = function (event) { + const command = []; + + if (event.altKey) { + command.push("alt"); + } + + if (event.shiftKey) { + command.push("shift"); + } + + command.push(event.key); + return command; +}; + +const pointFromEvent = event => ({ + x: event.clientX, + y: event.clientY +}); + +const { + lang, + css: css$1, + keyNames +} = config; + +const undoable = function (fn) { + return function () { + const commands = fn.apply(this, arguments); + commands.do(); + + if (!this.undos) { + this.undos = []; + } + + this.undos.push(commands.undo); + }; +}; + +class AttachmentEditorController extends BasicObject { + constructor(attachmentPiece, _element, container) { + let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + super(...arguments); + + _defineProperty(this, "makeElementMutable", undoable(() => { + return { + do: () => { + this.element.dataset.trixMutable = true; + }, + undo: () => delete this.element.dataset.trixMutable + }; + })); + + _defineProperty(this, "addToolbar", undoable(() => { + //
    + //
    + // + // + // + //
    + //
    + const element = makeElement({ + tagName: "div", + className: css$1.attachmentToolbar, + data: { + trixMutable: true + }, + childNodes: makeElement({ + tagName: "div", + className: "trix-button-row", + childNodes: makeElement({ + tagName: "span", + className: "trix-button-group trix-button-group--actions", + childNodes: makeElement({ + tagName: "button", + className: "trix-button trix-button--remove", + textContent: lang.remove, + attributes: { + title: lang.remove + }, + data: { + trixAction: "remove" + } + }) + }) + }) + }); + + if (this.attachment.isPreviewable()) { + //
    + // + // #{name} + // #{size} + // + //
    + element.appendChild(makeElement({ + tagName: "div", + className: css$1.attachmentMetadataContainer, + childNodes: makeElement({ + tagName: "span", + className: css$1.attachmentMetadata, + childNodes: [makeElement({ + tagName: "span", + className: css$1.attachmentName, + textContent: this.attachment.getFilename(), + attributes: { + title: this.attachment.getFilename() + } + }), makeElement({ + tagName: "span", + className: css$1.attachmentSize, + textContent: this.attachment.getFormattedFilesize() + })] + }) + })); + } + + handleEvent("click", { + onElement: element, + withCallback: this.didClickToolbar + }); + handleEvent("click", { + onElement: element, + matchingSelector: "[data-trix-action]", + withCallback: this.didClickActionButton + }); + return { + do: () => this.element.appendChild(element), + undo: () => removeNode(element) + }; + })); + + _defineProperty(this, "installCaptionEditor", undoable(() => { + const textarea = makeElement({ + tagName: "textarea", + className: css$1.attachmentCaptionEditor, + attributes: { + placeholder: lang.captionPlaceholder + }, + data: { + trixMutable: true + } + }); + textarea.value = this.attachmentPiece.getCaption(); + const textareaClone = textarea.cloneNode(); + textareaClone.classList.add("trix-autoresize-clone"); + textareaClone.tabIndex = -1; + + const autoresize = function () { + textareaClone.value = textarea.value; + textarea.style.height = textareaClone.scrollHeight + "px"; + }; + + handleEvent("input", { + onElement: textarea, + withCallback: autoresize + }); + handleEvent("input", { + onElement: textarea, + withCallback: this.didInputCaption + }); + handleEvent("keydown", { + onElement: textarea, + withCallback: this.didKeyDownCaption + }); + handleEvent("change", { + onElement: textarea, + withCallback: this.didChangeCaption + }); + handleEvent("blur", { + onElement: textarea, + withCallback: this.didBlurCaption + }); + const figcaption = this.element.querySelector("figcaption"); + const editingFigcaption = figcaption.cloneNode(); + return { + do: () => { + figcaption.style.display = "none"; + editingFigcaption.appendChild(textarea); + editingFigcaption.appendChild(textareaClone); + editingFigcaption.classList.add("".concat(css$1.attachmentCaption, "--editing")); + figcaption.parentElement.insertBefore(editingFigcaption, figcaption); + autoresize(); + + if (this.options.editCaption) { + return defer(() => textarea.focus()); + } + }, + + undo() { + removeNode(editingFigcaption); + figcaption.style.display = null; + } + + }; + })); + + this.didClickToolbar = this.didClickToolbar.bind(this); + this.didClickActionButton = this.didClickActionButton.bind(this); + this.didKeyDownCaption = this.didKeyDownCaption.bind(this); + this.didInputCaption = this.didInputCaption.bind(this); + this.didChangeCaption = this.didChangeCaption.bind(this); + this.didBlurCaption = this.didBlurCaption.bind(this); + this.attachmentPiece = attachmentPiece; + this.element = _element; + this.container = container; + this.options = options; + this.attachment = this.attachmentPiece.attachment; + + if (tagName(this.element) === "a") { + this.element = this.element.firstChild; + } + + this.install(); + } + + install() { + this.makeElementMutable(); + this.addToolbar(); + + if (this.attachment.isPreviewable()) { + this.installCaptionEditor(); + } + } + + uninstall() { + var _this$delegate; + + let undo = this.undos.pop(); + this.savePendingCaption(); + + while (undo) { + undo(); + undo = this.undos.pop(); + } + + (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? void 0 : _this$delegate.didUninstallAttachmentEditor(this); + } // Private + + + savePendingCaption() { + if (this.pendingCaption) { + const caption = this.pendingCaption; + this.pendingCaption = null; + + if (caption) { + var _this$delegate2, _this$delegate2$attac; + + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : (_this$delegate2$attac = _this$delegate2.attachmentEditorDidRequestUpdatingAttributesForAttachment) === null || _this$delegate2$attac === void 0 ? void 0 : _this$delegate2$attac.call(_this$delegate2, { + caption + }, this.attachment); + } else { + var _this$delegate3, _this$delegate3$attac; + + (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 ? void 0 : (_this$delegate3$attac = _this$delegate3.attachmentEditorDidRequestRemovingAttributeForAttachment) === null || _this$delegate3$attac === void 0 ? void 0 : _this$delegate3$attac.call(_this$delegate3, "caption", this.attachment); + } + } + } // Installing and uninstalling + + + // Event handlers + didClickToolbar(event) { + event.preventDefault(); + return event.stopPropagation(); + } + + didClickActionButton(event) { + var _this$delegate4; + + const action = event.target.getAttribute("data-trix-action"); + + switch (action) { + case "remove": + return (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 ? void 0 : _this$delegate4.attachmentEditorDidRequestRemovalOfAttachment(this.attachment); + } + } + + didKeyDownCaption(event) { + if (keyNames[event.keyCode] === "return") { + var _this$delegate5, _this$delegate5$attac; + + event.preventDefault(); + this.savePendingCaption(); + return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 ? void 0 : (_this$delegate5$attac = _this$delegate5.attachmentEditorDidRequestDeselectingAttachment) === null || _this$delegate5$attac === void 0 ? void 0 : _this$delegate5$attac.call(_this$delegate5, this.attachment); + } + } + + didInputCaption(event) { + this.pendingCaption = event.target.value.replace(/\s/g, " ").trim(); + } + + didChangeCaption(event) { + return this.savePendingCaption(); + } + + didBlurCaption(event) { + return this.savePendingCaption(); + } + +} + +class CompositionController extends BasicObject { + constructor(element, composition) { + super(...arguments); + this.didFocus = this.didFocus.bind(this); + this.didBlur = this.didBlur.bind(this); + this.didClickAttachment = this.didClickAttachment.bind(this); + this.element = element; + this.composition = composition; + this.documentView = new DocumentView(this.composition.document, { + element: this.element + }); + handleEvent("focus", { + onElement: this.element, + withCallback: this.didFocus + }); + handleEvent("blur", { + onElement: this.element, + withCallback: this.didBlur + }); + handleEvent("click", { + onElement: this.element, + matchingSelector: "a[contenteditable=false]", + preventDefault: true + }); + handleEvent("mousedown", { + onElement: this.element, + matchingSelector: attachmentSelector, + withCallback: this.didClickAttachment + }); + handleEvent("click", { + onElement: this.element, + matchingSelector: "a".concat(attachmentSelector), + preventDefault: true + }); + } + + didFocus(event) { + var _this$blurPromise; + + const perform = () => { + if (!this.focused) { + var _this$delegate, _this$delegate$compos; + + this.focused = true; + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? void 0 : (_this$delegate$compos = _this$delegate.compositionControllerDidFocus) === null || _this$delegate$compos === void 0 ? void 0 : _this$delegate$compos.call(_this$delegate); + } + }; + + return ((_this$blurPromise = this.blurPromise) === null || _this$blurPromise === void 0 ? void 0 : _this$blurPromise.then(perform)) || perform(); + } + + didBlur(event) { + this.blurPromise = new Promise(resolve => { + return defer(() => { + if (!innerElementIsActive(this.element)) { + var _this$delegate2, _this$delegate2$compo; + + this.focused = null; + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : (_this$delegate2$compo = _this$delegate2.compositionControllerDidBlur) === null || _this$delegate2$compo === void 0 ? void 0 : _this$delegate2$compo.call(_this$delegate2); + } + + this.blurPromise = null; + return resolve(); + }); + }); + } + + didClickAttachment(event, target) { + var _this$delegate3, _this$delegate3$compo; + + const attachment = this.findAttachmentForElement(target); + const editCaption = !!findClosestElementFromNode(event.target, { + matchingSelector: "figcaption" + }); + return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 ? void 0 : (_this$delegate3$compo = _this$delegate3.compositionControllerDidSelectAttachment) === null || _this$delegate3$compo === void 0 ? void 0 : _this$delegate3$compo.call(_this$delegate3, attachment, { + editCaption + }); + } + + getSerializableElement() { + if (this.isEditingAttachment()) { + return this.documentView.shadowElement; + } else { + return this.element; + } + } + + render() { + var _this$delegate6, _this$delegate6$compo; + + if (this.revision !== this.composition.revision) { + this.documentView.setDocument(this.composition.document); + this.documentView.render(); + this.revision = this.composition.revision; + } + + if (this.canSyncDocumentView() && !this.documentView.isSynced()) { + var _this$delegate4, _this$delegate4$compo, _this$delegate5, _this$delegate5$compo; + + (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 ? void 0 : (_this$delegate4$compo = _this$delegate4.compositionControllerWillSyncDocumentView) === null || _this$delegate4$compo === void 0 ? void 0 : _this$delegate4$compo.call(_this$delegate4); + this.documentView.sync(); + (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 ? void 0 : (_this$delegate5$compo = _this$delegate5.compositionControllerDidSyncDocumentView) === null || _this$delegate5$compo === void 0 ? void 0 : _this$delegate5$compo.call(_this$delegate5); + } + + return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 ? void 0 : (_this$delegate6$compo = _this$delegate6.compositionControllerDidRender) === null || _this$delegate6$compo === void 0 ? void 0 : _this$delegate6$compo.call(_this$delegate6); + } + + rerenderViewForObject(object) { + this.invalidateViewForObject(object); + return this.render(); + } + + invalidateViewForObject(object) { + return this.documentView.invalidateViewForObject(object); + } + + isViewCachingEnabled() { + return this.documentView.isViewCachingEnabled(); + } + + enableViewCaching() { + return this.documentView.enableViewCaching(); + } + + disableViewCaching() { + return this.documentView.disableViewCaching(); + } + + refreshViewCache() { + return this.documentView.garbageCollectCachedViews(); + } // Attachment editor management + + + isEditingAttachment() { + return !!this.attachmentEditor; + } + + installAttachmentEditorForAttachment(attachment, options) { + var _this$attachmentEdito; + + if (((_this$attachmentEdito = this.attachmentEditor) === null || _this$attachmentEdito === void 0 ? void 0 : _this$attachmentEdito.attachment) === attachment) { + return; + } + + const element = this.documentView.findElementForObject(attachment); + if (!element) return; + this.uninstallAttachmentEditor(); + const attachmentPiece = this.composition.document.getAttachmentPieceForAttachment(attachment); + this.attachmentEditor = new AttachmentEditorController(attachmentPiece, element, this.element, options); + this.attachmentEditor.delegate = this; + } + + uninstallAttachmentEditor() { + var _this$attachmentEdito2; + + return (_this$attachmentEdito2 = this.attachmentEditor) === null || _this$attachmentEdito2 === void 0 ? void 0 : _this$attachmentEdito2.uninstall(); + } // Attachment controller delegate + + + didUninstallAttachmentEditor() { + this.attachmentEditor = null; + return this.render(); + } + + attachmentEditorDidRequestUpdatingAttributesForAttachment(attributes, attachment) { + var _this$delegate7, _this$delegate7$compo; + + (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 ? void 0 : (_this$delegate7$compo = _this$delegate7.compositionControllerWillUpdateAttachment) === null || _this$delegate7$compo === void 0 ? void 0 : _this$delegate7$compo.call(_this$delegate7, attachment); + return this.composition.updateAttributesForAttachment(attributes, attachment); + } + + attachmentEditorDidRequestRemovingAttributeForAttachment(attribute, attachment) { + var _this$delegate8, _this$delegate8$compo; + + (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 ? void 0 : (_this$delegate8$compo = _this$delegate8.compositionControllerWillUpdateAttachment) === null || _this$delegate8$compo === void 0 ? void 0 : _this$delegate8$compo.call(_this$delegate8, attachment); + return this.composition.removeAttributeForAttachment(attribute, attachment); + } + + attachmentEditorDidRequestRemovalOfAttachment(attachment) { + var _this$delegate9, _this$delegate9$compo; + + return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 ? void 0 : (_this$delegate9$compo = _this$delegate9.compositionControllerDidRequestRemovalOfAttachment) === null || _this$delegate9$compo === void 0 ? void 0 : _this$delegate9$compo.call(_this$delegate9, attachment); + } + + attachmentEditorDidRequestDeselectingAttachment(attachment) { + var _this$delegate10, _this$delegate10$comp; + + return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 ? void 0 : (_this$delegate10$comp = _this$delegate10.compositionControllerDidRequestDeselectingAttachment) === null || _this$delegate10$comp === void 0 ? void 0 : _this$delegate10$comp.call(_this$delegate10, attachment); + } // Private + + + canSyncDocumentView() { + return !this.isEditingAttachment(); + } + + findAttachmentForElement(element) { + return this.composition.document.getAttachmentById(parseInt(element.dataset.trixId, 10)); + } + +} + +const attributeButtonSelector = "[data-trix-attribute]"; +const actionButtonSelector = "[data-trix-action]"; +const toolbarButtonSelector = "".concat(attributeButtonSelector, ", ").concat(actionButtonSelector); +const dialogSelector = "[data-trix-dialog]"; +const activeDialogSelector = "".concat(dialogSelector, "[data-trix-active]"); +const dialogButtonSelector = "".concat(dialogSelector, " [data-trix-method]"); +const dialogInputSelector = "".concat(dialogSelector, " [data-trix-input]"); + +const getInputForDialog = (element, attributeName) => { + if (!attributeName) { + attributeName = getAttributeName(element); + } + + return element.querySelector("[data-trix-input][name='".concat(attributeName, "']")); +}; + +const getActionName = element => element.getAttribute("data-trix-action"); + +const getAttributeName = element => { + return element.getAttribute("data-trix-attribute") || element.getAttribute("data-trix-dialog-attribute"); +}; + +const getDialogName = element => element.getAttribute("data-trix-dialog"); + +class ToolbarController extends BasicObject { + constructor(element) { + super(element); + this.didClickActionButton = this.didClickActionButton.bind(this); + this.didClickAttributeButton = this.didClickAttributeButton.bind(this); + this.didClickDialogButton = this.didClickDialogButton.bind(this); + this.didKeyDownDialogInput = this.didKeyDownDialogInput.bind(this); + this.element = element; + this.attributes = {}; + this.actions = {}; + this.resetDialogInputs(); + handleEvent("mousedown", { + onElement: this.element, + matchingSelector: actionButtonSelector, + withCallback: this.didClickActionButton + }); + handleEvent("mousedown", { + onElement: this.element, + matchingSelector: attributeButtonSelector, + withCallback: this.didClickAttributeButton + }); + handleEvent("click", { + onElement: this.element, + matchingSelector: toolbarButtonSelector, + preventDefault: true + }); + handleEvent("click", { + onElement: this.element, + matchingSelector: dialogButtonSelector, + withCallback: this.didClickDialogButton + }); + handleEvent("keydown", { + onElement: this.element, + matchingSelector: dialogInputSelector, + withCallback: this.didKeyDownDialogInput + }); + } // Event handlers + + + didClickActionButton(event, element) { + var _this$delegate; + + (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? void 0 : _this$delegate.toolbarDidClickButton(); + event.preventDefault(); + const actionName = getActionName(element); + + if (this.getDialog(actionName)) { + return this.toggleDialog(actionName); + } else { + var _this$delegate2; + + return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2.toolbarDidInvokeAction(actionName); + } + } + + didClickAttributeButton(event, element) { + var _this$delegate3; + + (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 ? void 0 : _this$delegate3.toolbarDidClickButton(); + event.preventDefault(); + const attributeName = getAttributeName(element); + + if (this.getDialog(attributeName)) { + this.toggleDialog(attributeName); + } else { + var _this$delegate4; + + (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 ? void 0 : _this$delegate4.toolbarDidToggleAttribute(attributeName); + } + + return this.refreshAttributeButtons(); + } + + didClickDialogButton(event, element) { + const dialogElement = findClosestElementFromNode(element, { + matchingSelector: dialogSelector + }); + const method = element.getAttribute("data-trix-method"); + return this[method].call(this, dialogElement); + } + + didKeyDownDialogInput(event, element) { + if (event.keyCode === 13) { + // Enter key + event.preventDefault(); + const attribute = element.getAttribute("name"); + const dialog = this.getDialog(attribute); + this.setAttribute(dialog); + } + + if (event.keyCode === 27) { + // Escape key + event.preventDefault(); + return this.hideDialog(); + } + } // Action buttons + + + updateActions(actions) { + this.actions = actions; + return this.refreshActionButtons(); + } + + refreshActionButtons() { + return this.eachActionButton((element, actionName) => { + element.disabled = this.actions[actionName] === false; + }); + } + + eachActionButton(callback) { + return Array.from(this.element.querySelectorAll(actionButtonSelector)).map(element => callback(element, getActionName(element))); + } // Attribute buttons + + + updateAttributes(attributes) { + this.attributes = attributes; + return this.refreshAttributeButtons(); + } + + refreshAttributeButtons() { + return this.eachAttributeButton((element, attributeName) => { + element.disabled = this.attributes[attributeName] === false; + + if (this.attributes[attributeName] || this.dialogIsVisible(attributeName)) { + element.setAttribute("data-trix-active", ""); + return element.classList.add("trix-active"); + } else { + element.removeAttribute("data-trix-active"); + return element.classList.remove("trix-active"); + } + }); + } + + eachAttributeButton(callback) { + return Array.from(this.element.querySelectorAll(attributeButtonSelector)).map(element => callback(element, getAttributeName(element))); + } + + applyKeyboardCommand(keys) { + const keyString = JSON.stringify(keys.sort()); + + for (const button of Array.from(this.element.querySelectorAll("[data-trix-key]"))) { + const buttonKeys = button.getAttribute("data-trix-key").split("+"); + const buttonKeyString = JSON.stringify(buttonKeys.sort()); + + if (buttonKeyString === keyString) { + triggerEvent$1("mousedown", { + onElement: button + }); + return true; + } + } + + return false; + } // Dialogs + + + dialogIsVisible(dialogName) { + const element = this.getDialog(dialogName); + + if (element) { + return element.hasAttribute("data-trix-active"); + } + } + + toggleDialog(dialogName) { + if (this.dialogIsVisible(dialogName)) { + return this.hideDialog(); + } else { + return this.showDialog(dialogName); + } + } + + showDialog(dialogName) { + var _this$delegate5, _this$delegate6; + + this.hideDialog(); + (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 ? void 0 : _this$delegate5.toolbarWillShowDialog(); + const element = this.getDialog(dialogName); + element.setAttribute("data-trix-active", ""); + element.classList.add("trix-active"); + Array.from(element.querySelectorAll("input[disabled]")).forEach(disabledInput => { + disabledInput.removeAttribute("disabled"); + }); + const attributeName = getAttributeName(element); + + if (attributeName) { + const input = getInputForDialog(element, dialogName); + + if (input) { + input.value = this.attributes[attributeName] || ""; + input.select(); + } + } + + return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 ? void 0 : _this$delegate6.toolbarDidShowDialog(dialogName); + } + + setAttribute(dialogElement) { + const attributeName = getAttributeName(dialogElement); + const input = getInputForDialog(dialogElement, attributeName); + + if (input.willValidate && !input.checkValidity()) { + input.setAttribute("data-trix-validate", ""); + input.classList.add("trix-validate"); + return input.focus(); + } else { + var _this$delegate7; + + (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 ? void 0 : _this$delegate7.toolbarDidUpdateAttribute(attributeName, input.value); + return this.hideDialog(); + } + } + + removeAttribute(dialogElement) { + var _this$delegate8; + + const attributeName = getAttributeName(dialogElement); + (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 ? void 0 : _this$delegate8.toolbarDidRemoveAttribute(attributeName); + return this.hideDialog(); + } + + hideDialog() { + const element = this.element.querySelector(activeDialogSelector); + + if (element) { + var _this$delegate9; + + element.removeAttribute("data-trix-active"); + element.classList.remove("trix-active"); + this.resetDialogInputs(); + return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 ? void 0 : _this$delegate9.toolbarDidHideDialog(getDialogName(element)); + } + } + + resetDialogInputs() { + Array.from(this.element.querySelectorAll(dialogInputSelector)).forEach(input => { + input.setAttribute("disabled", "disabled"); + input.removeAttribute("data-trix-validate"); + input.classList.remove("trix-validate"); + }); + } + + getDialog(dialogName) { + return this.element.querySelector("[data-trix-dialog=".concat(dialogName, "]")); + } + +} + +class LineBreakInsertion { + constructor(composition) { + this.composition = composition; + this.document = this.composition.document; + const selectedRange = this.composition.getSelectedRange(); + this.startPosition = selectedRange[0]; + this.endPosition = selectedRange[1]; + this.startLocation = this.document.locationFromPosition(this.startPosition); + this.endLocation = this.document.locationFromPosition(this.endPosition); + this.block = this.document.getBlockAtIndex(this.endLocation.index); + this.breaksOnReturn = this.block.breaksOnReturn(); + this.previousCharacter = this.block.text.getStringAtPosition(this.endLocation.offset - 1); + this.nextCharacter = this.block.text.getStringAtPosition(this.endLocation.offset); + } + + shouldInsertBlockBreak() { + if (this.block.hasAttributes() && this.block.isListItem() && !this.block.isEmpty()) { + return this.startLocation.offset !== 0; + } else { + return this.breaksOnReturn && this.nextCharacter !== "\n"; + } + } + + shouldBreakFormattedBlock() { + return this.block.hasAttributes() && !this.block.isListItem() && (this.breaksOnReturn && this.nextCharacter === "\n" || this.previousCharacter === "\n"); + } + + shouldDecreaseListLevel() { + return this.block.hasAttributes() && this.block.isListItem() && this.block.isEmpty(); + } + + shouldPrependListItem() { + return this.block.isListItem() && this.startLocation.offset === 0 && !this.block.isEmpty(); + } + + shouldRemoveLastBlockAttribute() { + return this.block.hasAttributes() && !this.block.isListItem() && this.block.isEmpty(); + } + +} + +const PLACEHOLDER = " "; +class Composition extends BasicObject { + constructor() { + super(...arguments); + this.document = new Document(); + this.attachments = []; + this.currentAttributes = {}; + this.revision = 0; + } + + setDocument(document) { + if (!document.isEqualTo(this.document)) { + var _this$delegate, _this$delegate$compos; + + this.document = document; + this.refreshAttachments(); + this.revision++; + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? void 0 : (_this$delegate$compos = _this$delegate.compositionDidChangeDocument) === null || _this$delegate$compos === void 0 ? void 0 : _this$delegate$compos.call(_this$delegate, document); + } + } // Snapshots + + + getSnapshot() { + return { + document: this.document, + selectedRange: this.getSelectedRange() + }; + } + + loadSnapshot(_ref) { + var _this$delegate2, _this$delegate2$compo, _this$delegate3, _this$delegate3$compo; + + let { + document, + selectedRange + } = _ref; + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : (_this$delegate2$compo = _this$delegate2.compositionWillLoadSnapshot) === null || _this$delegate2$compo === void 0 ? void 0 : _this$delegate2$compo.call(_this$delegate2); + this.setDocument(document != null ? document : new Document()); + this.setSelection(selectedRange != null ? selectedRange : [0, 0]); + return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 ? void 0 : (_this$delegate3$compo = _this$delegate3.compositionDidLoadSnapshot) === null || _this$delegate3$compo === void 0 ? void 0 : _this$delegate3$compo.call(_this$delegate3); + } // Responder protocol + + + insertText(text) { + let { + updatePosition + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + updatePosition: true + }; + const selectedRange = this.getSelectedRange(); + this.setDocument(this.document.insertTextAtRange(text, selectedRange)); + const startPosition = selectedRange[0]; + const endPosition = startPosition + text.getLength(); + + if (updatePosition) { + this.setSelection(endPosition); + } + + return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); + } + + insertBlock() { + let block = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Block(); + const document = new Document([block]); + return this.insertDocument(document); + } + + insertDocument() { + let document = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Document(); + const selectedRange = this.getSelectedRange(); + this.setDocument(this.document.insertDocumentAtRange(document, selectedRange)); + const startPosition = selectedRange[0]; + const endPosition = startPosition + document.getLength(); + this.setSelection(endPosition); + return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); + } + + insertString(string, options) { + const attributes = this.getCurrentTextAttributes(); + const text = Text.textForStringWithAttributes(string, attributes); + return this.insertText(text, options); + } + + insertBlockBreak() { + const selectedRange = this.getSelectedRange(); + this.setDocument(this.document.insertBlockBreakAtRange(selectedRange)); + const startPosition = selectedRange[0]; + const endPosition = startPosition + 1; + this.setSelection(endPosition); + return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); + } + + insertLineBreak() { + const insertion = new LineBreakInsertion(this); + + if (insertion.shouldDecreaseListLevel()) { + this.decreaseListLevel(); + return this.setSelection(insertion.startPosition); + } else if (insertion.shouldPrependListItem()) { + const document = new Document([insertion.block.copyWithoutText()]); + return this.insertDocument(document); + } else if (insertion.shouldInsertBlockBreak()) { + return this.insertBlockBreak(); + } else if (insertion.shouldRemoveLastBlockAttribute()) { + return this.removeLastBlockAttribute(); + } else if (insertion.shouldBreakFormattedBlock()) { + return this.breakFormattedBlock(insertion); + } else { + return this.insertString("\n"); + } + } + + insertHTML(html) { + const document = HTMLParser.parse(html).getDocument(); + const selectedRange = this.getSelectedRange(); + this.setDocument(this.document.mergeDocumentAtRange(document, selectedRange)); + const startPosition = selectedRange[0]; + const endPosition = startPosition + document.getLength() - 1; + this.setSelection(endPosition); + return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); + } + + replaceHTML(html) { + const document = HTMLParser.parse(html).getDocument().copyUsingObjectsFromDocument(this.document); + const locationRange = this.getLocationRange({ + strict: false + }); + const selectedRange = this.document.rangeFromLocationRange(locationRange); + this.setDocument(document); + return this.setSelection(selectedRange); + } + + insertFile(file) { + return this.insertFiles([file]); + } + + insertFiles(files) { + const attachments = []; + Array.from(files).forEach(file => { + var _this$delegate4; + + if ((_this$delegate4 = this.delegate) !== null && _this$delegate4 !== void 0 && _this$delegate4.compositionShouldAcceptFile(file)) { + const attachment = Attachment.attachmentForFile(file); + attachments.push(attachment); + } + }); + return this.insertAttachments(attachments); + } + + insertAttachment(attachment) { + return this.insertAttachments([attachment]); + } + + insertAttachments(attachments) { + let text = new Text(); + Array.from(attachments).forEach(attachment => { + var _config$attachments$t; + + const type = attachment.getType(); + const presentation = (_config$attachments$t = config.attachments[type]) === null || _config$attachments$t === void 0 ? void 0 : _config$attachments$t.presentation; + const attributes = this.getCurrentTextAttributes(); + + if (presentation) { + attributes.presentation = presentation; + } + + const attachmentText = Text.textForAttachmentWithAttributes(attachment, attributes); + text = text.appendText(attachmentText); + }); + return this.insertText(text); + } + + shouldManageDeletingInDirection(direction) { + const locationRange = this.getLocationRange(); + + if (rangeIsCollapsed(locationRange)) { + if (direction === "backward" && locationRange[0].offset === 0) { + return true; + } + + if (this.shouldManageMovingCursorInDirection(direction)) { + return true; + } + } else { + if (locationRange[0].index !== locationRange[1].index) { + return true; + } + } + + return false; + } + + deleteInDirection(direction) { + let { + length + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let attachment, deletingIntoPreviousBlock, selectionSpansBlocks; + const locationRange = this.getLocationRange(); + let range = this.getSelectedRange(); + const selectionIsCollapsed = rangeIsCollapsed(range); + + if (selectionIsCollapsed) { + deletingIntoPreviousBlock = direction === "backward" && locationRange[0].offset === 0; + } else { + selectionSpansBlocks = locationRange[0].index !== locationRange[1].index; + } + + if (deletingIntoPreviousBlock) { + if (this.canDecreaseBlockAttributeLevel()) { + const block = this.getBlock(); + + if (block.isListItem()) { + this.decreaseListLevel(); + } else { + this.decreaseBlockAttributeLevel(); + } + + this.setSelection(range[0]); + + if (block.isEmpty()) { + return false; + } + } + } + + if (selectionIsCollapsed) { + range = this.getExpandedRangeInDirection(direction, { + length + }); + + if (direction === "backward") { + attachment = this.getAttachmentAtRange(range); + } + } + + if (attachment) { + this.editAttachment(attachment); + return false; + } else { + this.setDocument(this.document.removeTextAtRange(range)); + this.setSelection(range[0]); + + if (deletingIntoPreviousBlock || selectionSpansBlocks) { + return false; + } + } + } + + moveTextFromRange(range) { + const [position] = Array.from(this.getSelectedRange()); + this.setDocument(this.document.moveTextFromRangeToPosition(range, position)); + return this.setSelection(position); + } + + removeAttachment(attachment) { + const range = this.document.getRangeOfAttachment(attachment); + + if (range) { + this.stopEditingAttachment(); + this.setDocument(this.document.removeTextAtRange(range)); + return this.setSelection(range[0]); + } + } + + removeLastBlockAttribute() { + const [startPosition, endPosition] = Array.from(this.getSelectedRange()); + const block = this.document.getBlockAtPosition(endPosition); + this.removeCurrentAttribute(block.getLastAttribute()); + return this.setSelection(startPosition); + } + + insertPlaceholder() { + this.placeholderPosition = this.getPosition(); + return this.insertString(PLACEHOLDER); + } + + selectPlaceholder() { + if (this.placeholderPosition != null) { + this.setSelectedRange([this.placeholderPosition, this.placeholderPosition + PLACEHOLDER.length]); + return this.getSelectedRange(); + } + } + + forgetPlaceholder() { + this.placeholderPosition = null; + } // Current attributes + + + hasCurrentAttribute(attributeName) { + const value = this.currentAttributes[attributeName]; + return value != null && value !== false; + } + + toggleCurrentAttribute(attributeName) { + const value = !this.currentAttributes[attributeName]; + + if (value) { + return this.setCurrentAttribute(attributeName, value); + } else { + return this.removeCurrentAttribute(attributeName); + } + } + + canSetCurrentAttribute(attributeName) { + if (getBlockConfig(attributeName)) { + return this.canSetCurrentBlockAttribute(attributeName); + } else { + return this.canSetCurrentTextAttribute(attributeName); + } + } + + canSetCurrentTextAttribute(attributeName) { + const document = this.getSelectedDocument(); + if (!document) return; + + for (const attachment of Array.from(document.getAttachments())) { + if (!attachment.hasContent()) { + return false; + } + } + + return true; + } + + canSetCurrentBlockAttribute(attributeName) { + const block = this.getBlock(); + if (!block) return; + return !block.isTerminalBlock(); + } + + setCurrentAttribute(attributeName, value) { + if (getBlockConfig(attributeName)) { + return this.setBlockAttribute(attributeName, value); + } else { + this.setTextAttribute(attributeName, value); + this.currentAttributes[attributeName] = value; + return this.notifyDelegateOfCurrentAttributesChange(); + } + } + + setTextAttribute(attributeName, value) { + const selectedRange = this.getSelectedRange(); + if (!selectedRange) return; + const [startPosition, endPosition] = Array.from(selectedRange); + + if (startPosition === endPosition) { + if (attributeName === "href") { + const text = Text.textForStringWithAttributes(value, { + href: value + }); + return this.insertText(text); + } + } else { + return this.setDocument(this.document.addAttributeAtRange(attributeName, value, selectedRange)); + } + } + + setBlockAttribute(attributeName, value) { + const selectedRange = this.getSelectedRange(); + + if (this.canSetCurrentAttribute(attributeName)) { + this.setDocument(this.document.applyBlockAttributeAtRange(attributeName, value, selectedRange)); + return this.setSelection(selectedRange); + } + } + + removeCurrentAttribute(attributeName) { + if (getBlockConfig(attributeName)) { + this.removeBlockAttribute(attributeName); + return this.updateCurrentAttributes(); + } else { + this.removeTextAttribute(attributeName); + delete this.currentAttributes[attributeName]; + return this.notifyDelegateOfCurrentAttributesChange(); + } + } + + removeTextAttribute(attributeName) { + const selectedRange = this.getSelectedRange(); + if (!selectedRange) return; + return this.setDocument(this.document.removeAttributeAtRange(attributeName, selectedRange)); + } + + removeBlockAttribute(attributeName) { + const selectedRange = this.getSelectedRange(); + if (!selectedRange) return; + return this.setDocument(this.document.removeAttributeAtRange(attributeName, selectedRange)); + } + + canDecreaseNestingLevel() { + var _this$getBlock; + + return ((_this$getBlock = this.getBlock()) === null || _this$getBlock === void 0 ? void 0 : _this$getBlock.getNestingLevel()) > 0; + } + + canIncreaseNestingLevel() { + var _getBlockConfig; + + const block = this.getBlock(); + if (!block) return; + + if ((_getBlockConfig = getBlockConfig(block.getLastNestableAttribute())) !== null && _getBlockConfig !== void 0 && _getBlockConfig.listAttribute) { + const previousBlock = this.getPreviousBlock(); + + if (previousBlock) { + return arrayStartsWith(previousBlock.getListItemAttributes(), block.getListItemAttributes()); + } + } else { + return block.getNestingLevel() > 0; + } + } + + decreaseNestingLevel() { + const block = this.getBlock(); + if (!block) return; + return this.setDocument(this.document.replaceBlock(block, block.decreaseNestingLevel())); + } + + increaseNestingLevel() { + const block = this.getBlock(); + if (!block) return; + return this.setDocument(this.document.replaceBlock(block, block.increaseNestingLevel())); + } + + canDecreaseBlockAttributeLevel() { + var _this$getBlock2; + + return ((_this$getBlock2 = this.getBlock()) === null || _this$getBlock2 === void 0 ? void 0 : _this$getBlock2.getAttributeLevel()) > 0; + } + + decreaseBlockAttributeLevel() { + var _this$getBlock3; + + const attribute = (_this$getBlock3 = this.getBlock()) === null || _this$getBlock3 === void 0 ? void 0 : _this$getBlock3.getLastAttribute(); + + if (attribute) { + return this.removeCurrentAttribute(attribute); + } + } + + decreaseListLevel() { + let [startPosition] = Array.from(this.getSelectedRange()); + const { + index + } = this.document.locationFromPosition(startPosition); + let endIndex = index; + const attributeLevel = this.getBlock().getAttributeLevel(); + let block = this.document.getBlockAtIndex(endIndex + 1); + + while (block) { + if (!block.isListItem() || block.getAttributeLevel() <= attributeLevel) { + break; + } + + endIndex++; + block = this.document.getBlockAtIndex(endIndex + 1); + } + + startPosition = this.document.positionFromLocation({ + index, + offset: 0 + }); + const endPosition = this.document.positionFromLocation({ + index: endIndex, + offset: 0 + }); + return this.setDocument(this.document.removeLastListAttributeAtRange([startPosition, endPosition])); + } + + updateCurrentAttributes() { + const selectedRange = this.getSelectedRange({ + ignoreLock: true + }); + + if (selectedRange) { + const currentAttributes = this.document.getCommonAttributesAtRange(selectedRange); + Array.from(getAllAttributeNames()).forEach(attributeName => { + if (!currentAttributes[attributeName]) { + if (!this.canSetCurrentAttribute(attributeName)) { + currentAttributes[attributeName] = false; + } + } + }); + + if (!objectsAreEqual(currentAttributes, this.currentAttributes)) { + this.currentAttributes = currentAttributes; + return this.notifyDelegateOfCurrentAttributesChange(); + } + } + } + + getCurrentAttributes() { + return extend$1.call({}, this.currentAttributes); + } + + getCurrentTextAttributes() { + const attributes = {}; + + for (const key in this.currentAttributes) { + const value = this.currentAttributes[key]; + + if (value !== false) { + if (getTextConfig(key)) { + attributes[key] = value; + } + } + } + + return attributes; + } // Selection freezing + + + freezeSelection() { + return this.setCurrentAttribute("frozen", true); + } + + thawSelection() { + return this.removeCurrentAttribute("frozen"); + } + + hasFrozenSelection() { + return this.hasCurrentAttribute("frozen"); + } + + setSelection(selectedRange) { + var _this$delegate5; + + const locationRange = this.document.locationRangeFromRange(selectedRange); + return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 ? void 0 : _this$delegate5.compositionDidRequestChangingSelectionToLocationRange(locationRange); + } + + getSelectedRange() { + const locationRange = this.getLocationRange(); + + if (locationRange) { + return this.document.rangeFromLocationRange(locationRange); + } + } + + setSelectedRange(selectedRange) { + const locationRange = this.document.locationRangeFromRange(selectedRange); + return this.getSelectionManager().setLocationRange(locationRange); + } + + getPosition() { + const locationRange = this.getLocationRange(); + + if (locationRange) { + return this.document.positionFromLocation(locationRange[0]); + } + } + + getLocationRange(options) { + return (this.targetLocationRange != null ? this.targetLocationRange : this.getSelectionManager().getLocationRange(options)) || normalizeRange({ + index: 0, + offset: 0 + }); + } + + withTargetLocationRange(locationRange, fn) { + let result; + this.targetLocationRange = locationRange; + + try { + result = fn(); + } finally { + this.targetLocationRange = null; + } + + return result; + } + + withTargetRange(range, fn) { + const locationRange = this.document.locationRangeFromRange(range); + return this.withTargetLocationRange(locationRange, fn); + } + + withTargetDOMRange(domRange, fn) { + const locationRange = this.createLocationRangeFromDOMRange(domRange, { + strict: false + }); + return this.withTargetLocationRange(locationRange, fn); + } + + getExpandedRangeInDirection(direction) { + let { + length + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let [startPosition, endPosition] = Array.from(this.getSelectedRange()); + + if (direction === "backward") { + if (length) { + startPosition -= length; + } else { + startPosition = this.translateUTF16PositionFromOffset(startPosition, -1); + } + } else { + if (length) { + endPosition += length; + } else { + endPosition = this.translateUTF16PositionFromOffset(endPosition, 1); + } + } + + return normalizeRange([startPosition, endPosition]); + } + + shouldManageMovingCursorInDirection(direction) { + if (this.editingAttachment) { + return true; + } + + const range = this.getExpandedRangeInDirection(direction); + return this.getAttachmentAtRange(range) != null; + } + + moveCursorInDirection(direction) { + let canEditAttachment, range; + + if (this.editingAttachment) { + range = this.document.getRangeOfAttachment(this.editingAttachment); + } else { + const selectedRange = this.getSelectedRange(); + range = this.getExpandedRangeInDirection(direction); + canEditAttachment = !rangesAreEqual(selectedRange, range); + } + + if (direction === "backward") { + this.setSelectedRange(range[0]); + } else { + this.setSelectedRange(range[1]); + } + + if (canEditAttachment) { + const attachment = this.getAttachmentAtRange(range); + + if (attachment) { + return this.editAttachment(attachment); + } + } + } + + expandSelectionInDirection(direction) { + let { + length + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const range = this.getExpandedRangeInDirection(direction, { + length + }); + return this.setSelectedRange(range); + } + + expandSelectionForEditing() { + if (this.hasCurrentAttribute("href")) { + return this.expandSelectionAroundCommonAttribute("href"); + } + } + + expandSelectionAroundCommonAttribute(attributeName) { + const position = this.getPosition(); + const range = this.document.getRangeOfCommonAttributeAtPosition(attributeName, position); + return this.setSelectedRange(range); + } + + selectionContainsAttachments() { + var _this$getSelectedAtta; + + return ((_this$getSelectedAtta = this.getSelectedAttachments()) === null || _this$getSelectedAtta === void 0 ? void 0 : _this$getSelectedAtta.length) > 0; + } + + selectionIsInCursorTarget() { + return this.editingAttachment || this.positionIsCursorTarget(this.getPosition()); + } + + positionIsCursorTarget(position) { + const location = this.document.locationFromPosition(position); + + if (location) { + return this.locationIsCursorTarget(location); + } + } + + positionIsBlockBreak(position) { + var _this$document$getPie; + + return (_this$document$getPie = this.document.getPieceAtPosition(position)) === null || _this$document$getPie === void 0 ? void 0 : _this$document$getPie.isBlockBreak(); + } + + getSelectedDocument() { + const selectedRange = this.getSelectedRange(); + + if (selectedRange) { + return this.document.getDocumentAtRange(selectedRange); + } + } + + getSelectedAttachments() { + var _this$getSelectedDocu; + + return (_this$getSelectedDocu = this.getSelectedDocument()) === null || _this$getSelectedDocu === void 0 ? void 0 : _this$getSelectedDocu.getAttachments(); + } // Attachments + + + getAttachments() { + return this.attachments.slice(0); + } + + refreshAttachments() { + const attachments = this.document.getAttachments(); + const { + added, + removed + } = summarizeArrayChange(this.attachments, attachments); + this.attachments = attachments; + Array.from(removed).forEach(attachment => { + var _this$delegate6, _this$delegate6$compo; + + attachment.delegate = null; + (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 ? void 0 : (_this$delegate6$compo = _this$delegate6.compositionDidRemoveAttachment) === null || _this$delegate6$compo === void 0 ? void 0 : _this$delegate6$compo.call(_this$delegate6, attachment); + }); + return (() => { + const result = []; + Array.from(added).forEach(attachment => { + var _this$delegate7, _this$delegate7$compo; + + attachment.delegate = this; + result.push((_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 ? void 0 : (_this$delegate7$compo = _this$delegate7.compositionDidAddAttachment) === null || _this$delegate7$compo === void 0 ? void 0 : _this$delegate7$compo.call(_this$delegate7, attachment)); + }); + return result; + })(); + } // Attachment delegate + + + attachmentDidChangeAttributes(attachment) { + var _this$delegate8, _this$delegate8$compo; + + this.revision++; + return (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 ? void 0 : (_this$delegate8$compo = _this$delegate8.compositionDidEditAttachment) === null || _this$delegate8$compo === void 0 ? void 0 : _this$delegate8$compo.call(_this$delegate8, attachment); + } + + attachmentDidChangePreviewURL(attachment) { + var _this$delegate9, _this$delegate9$compo; + + this.revision++; + return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 ? void 0 : (_this$delegate9$compo = _this$delegate9.compositionDidChangeAttachmentPreviewURL) === null || _this$delegate9$compo === void 0 ? void 0 : _this$delegate9$compo.call(_this$delegate9, attachment); + } // Attachment editing + + + editAttachment(attachment, options) { + var _this$delegate10, _this$delegate10$comp; + + if (attachment === this.editingAttachment) { + return; + } + + this.stopEditingAttachment(); + this.editingAttachment = attachment; + return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 ? 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); + } + + stopEditingAttachment() { + var _this$delegate11, _this$delegate11$comp; + + if (!this.editingAttachment) { + return; + } + + (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 ? void 0 : (_this$delegate11$comp = _this$delegate11.compositionDidStopEditingAttachment) === null || _this$delegate11$comp === void 0 ? void 0 : _this$delegate11$comp.call(_this$delegate11, this.editingAttachment); + this.editingAttachment = null; + } + + updateAttributesForAttachment(attributes, attachment) { + return this.setDocument(this.document.updateAttributesForAttachment(attributes, attachment)); + } + + removeAttributeForAttachment(attribute, attachment) { + return this.setDocument(this.document.removeAttributeForAttachment(attribute, attachment)); + } // Private + + + breakFormattedBlock(insertion) { + let { + document + } = insertion; + const { + block + } = insertion; + let position = insertion.startPosition; + let range = [position - 1, position]; + + if (block.getBlockBreakPosition() === insertion.startLocation.offset) { + if (block.breaksOnReturn() && insertion.nextCharacter === "\n") { + position += 1; + } else { + document = document.removeTextAtRange(range); + } + + range = [position, position]; + } else if (insertion.nextCharacter === "\n") { + if (insertion.previousCharacter === "\n") { + range = [position - 1, position + 1]; + } else { + range = [position, position + 1]; + position += 1; + } + } else if (insertion.startLocation.offset - 1 !== 0) { + position += 1; + } + + const newDocument = new Document([block.removeLastAttribute().copyWithoutText()]); + this.setDocument(document.insertDocumentAtRange(newDocument, range)); + return this.setSelection(position); + } + + getPreviousBlock() { + const locationRange = this.getLocationRange(); + + if (locationRange) { + const { + index + } = locationRange[0]; + + if (index > 0) { + return this.document.getBlockAtIndex(index - 1); + } + } + } + + getBlock() { + const locationRange = this.getLocationRange(); + + if (locationRange) { + return this.document.getBlockAtIndex(locationRange[0].index); + } + } + + getAttachmentAtRange(range) { + const document = this.document.getDocumentAtRange(range); + + if (document.toString() === "".concat(OBJECT_REPLACEMENT_CHARACTER, "\n")) { + return document.getAttachments()[0]; + } + } + + notifyDelegateOfCurrentAttributesChange() { + var _this$delegate12, _this$delegate12$comp; + + return (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 ? void 0 : (_this$delegate12$comp = _this$delegate12.compositionDidChangeCurrentAttributes) === null || _this$delegate12$comp === void 0 ? void 0 : _this$delegate12$comp.call(_this$delegate12, this.currentAttributes); + } + + notifyDelegateOfInsertionAtRange(range) { + var _this$delegate13, _this$delegate13$comp; + + return (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 ? void 0 : (_this$delegate13$comp = _this$delegate13.compositionDidPerformInsertionAtRange) === null || _this$delegate13$comp === void 0 ? void 0 : _this$delegate13$comp.call(_this$delegate13, range); + } + + translateUTF16PositionFromOffset(position, offset) { + const utf16string = this.document.toUTF16String(); + const utf16position = utf16string.offsetFromUCS2Offset(position); + return utf16string.offsetToUCS2Offset(utf16position + offset); + } + +} +Composition.proxyMethod("getSelectionManager().getPointRange"); +Composition.proxyMethod("getSelectionManager().setLocationRangeFromPointRange"); +Composition.proxyMethod("getSelectionManager().createLocationRangeFromDOMRange"); +Composition.proxyMethod("getSelectionManager().locationIsCursorTarget"); +Composition.proxyMethod("getSelectionManager().selectionIsExpanded"); +Composition.proxyMethod("delegate?.getSelectionManager"); + +class UndoManager extends BasicObject { + constructor(composition) { + super(...arguments); + this.composition = composition; + this.undoEntries = []; + this.redoEntries = []; + } + + recordUndoEntry(description) { + let { + context, + consolidatable + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const previousEntry = this.undoEntries.slice(-1)[0]; + + if (!consolidatable || !entryHasDescriptionAndContext(previousEntry, description, context)) { + const undoEntry = this.createEntry({ + description, + context + }); + this.undoEntries.push(undoEntry); + this.redoEntries = []; + } + } + + undo() { + const undoEntry = this.undoEntries.pop(); + + if (undoEntry) { + const redoEntry = this.createEntry(undoEntry); + this.redoEntries.push(redoEntry); + return this.composition.loadSnapshot(undoEntry.snapshot); + } + } + + redo() { + const redoEntry = this.redoEntries.pop(); + + if (redoEntry) { + const undoEntry = this.createEntry(redoEntry); + this.undoEntries.push(undoEntry); + return this.composition.loadSnapshot(redoEntry.snapshot); + } + } + + canUndo() { + return this.undoEntries.length > 0; + } + + canRedo() { + return this.redoEntries.length > 0; + } // Private + + + createEntry() { + let { + description, + context + } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + return { + description: description === null || description === void 0 ? void 0 : description.toString(), + context: JSON.stringify(context), + snapshot: this.composition.getSnapshot() + }; + } + +} + +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); + +const attachmentGalleryFilter = function (snapshot) { + const filter = new Filter(snapshot); + filter.perform(); + return filter.getSnapshot(); +}; +const BLOCK_ATTRIBUTE_NAME = "attachmentGallery"; +const TEXT_ATTRIBUTE_NAME = "presentation"; +const TEXT_ATTRIBUTE_VALUE = "gallery"; + +class Filter { + constructor(snapshot) { + this.document = snapshot.document; + this.selectedRange = snapshot.selectedRange; + } + + perform() { + this.removeBlockAttribute(); + return this.applyBlockAttribute(); + } + + getSnapshot() { + return { + document: this.document, + selectedRange: this.selectedRange + }; + } // Private + + + removeBlockAttribute() { + return this.findRangesOfBlocks().map(range => this.document = this.document.removeAttributeAtRange(BLOCK_ATTRIBUTE_NAME, range)); + } + + applyBlockAttribute() { + let offset = 0; + this.findRangesOfPieces().forEach(range => { + if (range[1] - range[0] > 1) { + range[0] += offset; + range[1] += offset; + + if (this.document.getCharacterAtPosition(range[1]) !== "\n") { + this.document = this.document.insertBlockBreakAtRange(range[1]); + + if (range[1] < this.selectedRange[1]) { + this.moveSelectedRangeForward(); + } + + range[1]++; + offset++; + } + + if (range[0] !== 0) { + if (this.document.getCharacterAtPosition(range[0] - 1) !== "\n") { + this.document = this.document.insertBlockBreakAtRange(range[0]); + + if (range[0] < this.selectedRange[0]) { + this.moveSelectedRangeForward(); + } + + range[0]++; + offset++; + } + } + + this.document = this.document.applyBlockAttributeAtRange(BLOCK_ATTRIBUTE_NAME, true, range); + } + }); + } + + findRangesOfBlocks() { + return this.document.findRangesForBlockAttribute(BLOCK_ATTRIBUTE_NAME); + } + + findRangesOfPieces() { + return this.document.findRangesForTextAttribute(TEXT_ATTRIBUTE_NAME, { + withValue: TEXT_ATTRIBUTE_VALUE + }); + } + + moveSelectedRangeForward() { + this.selectedRange[0] += 1; + this.selectedRange[1] += 1; + } + +} + +const DEFAULT_FILTERS = [attachmentGalleryFilter]; +class Editor { + constructor(composition, selectionManager, element) { + this.insertFiles = this.insertFiles.bind(this); + this.composition = composition; + this.selectionManager = selectionManager; + this.element = element; + this.undoManager = new UndoManager(this.composition); + this.filters = DEFAULT_FILTERS.slice(0); + } + + loadDocument(document) { + return this.loadSnapshot({ + document, + selectedRange: [0, 0] + }); + } + + loadHTML() { + let html = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + const document = HTMLParser.parse(html, { + referenceElement: this.element + }).getDocument(); + return this.loadDocument(document); + } + + loadJSON(_ref) { + let { + document, + selectedRange + } = _ref; + document = Document.fromJSON(document); + return this.loadSnapshot({ + document, + selectedRange + }); + } + + loadSnapshot(snapshot) { + this.undoManager = new UndoManager(this.composition); + return this.composition.loadSnapshot(snapshot); + } + + getDocument() { + return this.composition.document; + } + + getSelectedDocument() { + return this.composition.getSelectedDocument(); + } + + getSnapshot() { + return this.composition.getSnapshot(); + } + + toJSON() { + return this.getSnapshot(); + } // Document manipulation + + + deleteInDirection(direction) { + return this.composition.deleteInDirection(direction); + } + + insertAttachment(attachment) { + return this.composition.insertAttachment(attachment); + } + + insertAttachments(attachments) { + return this.composition.insertAttachments(attachments); + } + + insertDocument(document) { + return this.composition.insertDocument(document); + } + + insertFile(file) { + return this.composition.insertFile(file); + } + + insertFiles(files) { + return this.composition.insertFiles(files); + } + + insertHTML(html) { + return this.composition.insertHTML(html); + } + + insertString(string) { + return this.composition.insertString(string); + } + + insertText(text) { + return this.composition.insertText(text); + } + + insertLineBreak() { + return this.composition.insertLineBreak(); + } // Selection + + + getSelectedRange() { + return this.composition.getSelectedRange(); + } + + getPosition() { + return this.composition.getPosition(); + } + + getClientRectAtPosition(position) { + const locationRange = this.getDocument().locationRangeFromRange([position, position + 1]); + return this.selectionManager.getClientRectAtLocationRange(locationRange); + } + + expandSelectionInDirection(direction) { + return this.composition.expandSelectionInDirection(direction); + } + + moveCursorInDirection(direction) { + return this.composition.moveCursorInDirection(direction); + } + + setSelectedRange(selectedRange) { + return this.composition.setSelectedRange(selectedRange); + } // Attributes + + + activateAttribute(name) { + let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + return this.composition.setCurrentAttribute(name, value); + } + + attributeIsActive(name) { + return this.composition.hasCurrentAttribute(name); + } + + canActivateAttribute(name) { + return this.composition.canSetCurrentAttribute(name); + } + + deactivateAttribute(name) { + return this.composition.removeCurrentAttribute(name); + } // Nesting level + + + canDecreaseNestingLevel() { + return this.composition.canDecreaseNestingLevel(); + } + + canIncreaseNestingLevel() { + return this.composition.canIncreaseNestingLevel(); + } + + decreaseNestingLevel() { + if (this.canDecreaseNestingLevel()) { + return this.composition.decreaseNestingLevel(); + } + } + + increaseNestingLevel() { + if (this.canIncreaseNestingLevel()) { + return this.composition.increaseNestingLevel(); + } + } // Undo/redo + + + canRedo() { + return this.undoManager.canRedo(); + } + + canUndo() { + return this.undoManager.canUndo(); + } + + recordUndoEntry(description) { + let { + context, + consolidatable + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.undoManager.recordUndoEntry(description, { + context, + consolidatable + }); + } + + redo() { + if (this.canRedo()) { + return this.undoManager.redo(); + } + } + + undo() { + if (this.canUndo()) { + return this.undoManager.undo(); + } + } + +} + +class ManagedAttachment extends BasicObject { + constructor(attachmentManager, attachment) { + super(...arguments); + this.attachmentManager = attachmentManager; + this.attachment = attachment; + this.id = this.attachment.id; + this.file = this.attachment.file; + } + + remove() { + return this.attachmentManager.requestRemovalOfAttachment(this.attachment); + } + +} +ManagedAttachment.proxyMethod("attachment.getAttribute"); +ManagedAttachment.proxyMethod("attachment.hasAttribute"); +ManagedAttachment.proxyMethod("attachment.setAttribute"); +ManagedAttachment.proxyMethod("attachment.getAttributes"); +ManagedAttachment.proxyMethod("attachment.setAttributes"); +ManagedAttachment.proxyMethod("attachment.isPending"); +ManagedAttachment.proxyMethod("attachment.isPreviewable"); +ManagedAttachment.proxyMethod("attachment.getURL"); +ManagedAttachment.proxyMethod("attachment.getHref"); +ManagedAttachment.proxyMethod("attachment.getFilename"); +ManagedAttachment.proxyMethod("attachment.getFilesize"); +ManagedAttachment.proxyMethod("attachment.getFormattedFilesize"); +ManagedAttachment.proxyMethod("attachment.getExtension"); +ManagedAttachment.proxyMethod("attachment.getContentType"); +ManagedAttachment.proxyMethod("attachment.getFile"); +ManagedAttachment.proxyMethod("attachment.setFile"); +ManagedAttachment.proxyMethod("attachment.releaseFile"); +ManagedAttachment.proxyMethod("attachment.getUploadProgress"); +ManagedAttachment.proxyMethod("attachment.setUploadProgress"); + +class AttachmentManager extends BasicObject { + constructor() { + let attachments = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + super(...arguments); + this.managedAttachments = {}; + Array.from(attachments).forEach(attachment => { + this.manageAttachment(attachment); + }); + } + + getAttachments() { + const result = []; + + for (const id in this.managedAttachments) { + const attachment = this.managedAttachments[id]; + result.push(attachment); + } + + return result; + } + + manageAttachment(attachment) { + if (!this.managedAttachments[attachment.id]) { + this.managedAttachments[attachment.id] = new ManagedAttachment(this, attachment); + } + + return this.managedAttachments[attachment.id]; + } + + attachmentIsManaged(attachment) { + return attachment.id in this.managedAttachments; + } + + requestRemovalOfAttachment(attachment) { + if (this.attachmentIsManaged(attachment)) { + var _this$delegate, _this$delegate$attach; + + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? void 0 : (_this$delegate$attach = _this$delegate.attachmentManagerDidRequestRemovalOfAttachment) === null || _this$delegate$attach === void 0 ? void 0 : _this$delegate$attach.call(_this$delegate, attachment); + } + } + + unmanageAttachment(attachment) { + const managedAttachment = this.managedAttachments[attachment.id]; + delete this.managedAttachments[attachment.id]; + return managedAttachment; + } + +} + +/* eslint-disable + no-var, + prefer-const, +*/ +class LocationMapper { + constructor(element) { + this.element = element; + } + + findLocationFromContainerAndOffset(container, offset) { + let { + strict + } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { + strict: true + }; + let childIndex = 0; + let foundBlock = false; + const location = { + index: 0, + offset: 0 + }; + const attachmentElement = this.findAttachmentElementParentForNode(container); + + if (attachmentElement) { + container = attachmentElement.parentNode; + offset = findChildIndexOfNode(attachmentElement); + } + + const walker = walkTree(this.element, { + usingFilter: rejectAttachmentContents + }); + + while (walker.nextNode()) { + const node = walker.currentNode; + + if (node === container && nodeIsTextNode(container)) { + if (!nodeIsCursorTarget(node)) { + location.offset += offset; + } + + break; + } else { + if (node.parentNode === container) { + if (childIndex++ === offset) { + break; + } + } else if (!elementContainsNode(container, node)) { + if (childIndex > 0) { + break; + } + } + + if (nodeIsBlockStart(node, { + strict + })) { + if (foundBlock) { + location.index++; + } + + location.offset = 0; + foundBlock = true; + } else { + location.offset += nodeLength(node); + } + } + } + + return location; + } + + findContainerAndOffsetFromLocation(location) { + let container, offset; + + if (location.index === 0 && location.offset === 0) { + container = this.element; + offset = 0; + + while (container.firstChild) { + container = container.firstChild; + + if (nodeIsBlockContainer(container)) { + offset = 1; + break; + } + } + + return [container, offset]; + } + + let [node, nodeOffset] = this.findNodeAndOffsetFromLocation(location); + + if (!node) { + return; + } + + if (nodeIsTextNode(node)) { + if (nodeLength(node) === 0) { + container = node.parentNode.parentNode; + offset = findChildIndexOfNode(node.parentNode); + + if (nodeIsCursorTarget(node, { + name: "right" + })) { + offset++; + } + } else { + container = node; + offset = location.offset - nodeOffset; + } + } else { + container = node.parentNode; + + if (!nodeIsBlockStart(node.previousSibling)) { + if (!nodeIsBlockContainer(container)) { + while (node === container.lastChild) { + node = container; + container = container.parentNode; + + if (nodeIsBlockContainer(container)) { + break; + } + } + } + } + + offset = findChildIndexOfNode(node); + + if (location.offset !== 0) { + offset++; + } + } + + return [container, offset]; + } + + findNodeAndOffsetFromLocation(location) { + let node, nodeOffset; + let offset = 0; + + for (const currentNode of this.getSignificantNodesForIndex(location.index)) { + const length = nodeLength(currentNode); + + if (location.offset <= offset + length) { + if (nodeIsTextNode(currentNode)) { + node = currentNode; + nodeOffset = offset; + + if (location.offset === nodeOffset && nodeIsCursorTarget(node)) { + break; + } + } else if (!node) { + node = currentNode; + nodeOffset = offset; + } + } + + offset += length; + + if (offset > location.offset) { + break; + } + } + + return [node, nodeOffset]; + } // Private + + + findAttachmentElementParentForNode(node) { + while (node && node !== this.element) { + if (nodeIsAttachmentElement(node)) { + return node; + } + + node = node.parentNode; + } + } + + getSignificantNodesForIndex(index) { + const nodes = []; + const walker = walkTree(this.element, { + usingFilter: acceptSignificantNodes + }); + let recordingNodes = false; + + while (walker.nextNode()) { + const node = walker.currentNode; + + if (nodeIsBlockStartComment(node)) { + var blockIndex; + + if (blockIndex != null) { + blockIndex++; + } else { + blockIndex = 0; + } + + if (blockIndex === index) { + recordingNodes = true; + } else if (recordingNodes) { + break; + } + } else if (recordingNodes) { + nodes.push(node); + } + } + + return nodes; + } + +} + +const nodeLength = function (node) { + if (node.nodeType === Node.TEXT_NODE) { + if (nodeIsCursorTarget(node)) { + return 0; + } else { + const string = node.textContent; + return string.length; + } + } else if (tagName(node) === "br" || nodeIsAttachmentElement(node)) { + return 1; + } else { + return 0; + } +}; + +const acceptSignificantNodes = function (node) { + if (rejectEmptyTextNodes(node) === NodeFilter.FILTER_ACCEPT) { + return rejectAttachmentContents(node); + } else { + return NodeFilter.FILTER_REJECT; + } +}; + +const rejectEmptyTextNodes = function (node) { + if (nodeIsEmptyTextNode(node)) { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } +}; + +const rejectAttachmentContents = function (node) { + if (nodeIsAttachmentElement(node.parentNode)) { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } +}; + +/* eslint-disable + id-length, + no-empty, +*/ +class PointMapper { + createDOMRangeFromPoint(_ref) { + let { + x, + y + } = _ref; + let domRange; + + if (document.caretPositionFromPoint) { + const { + offsetNode, + offset + } = document.caretPositionFromPoint(x, y); + domRange = document.createRange(); + domRange.setStart(offsetNode, offset); + return domRange; + } else if (document.caretRangeFromPoint) { + return document.caretRangeFromPoint(x, y); + } else if (document.body.createTextRange) { + const originalDOMRange = getDOMRange(); + + try { + // IE 11 throws "Unspecified error" when using moveToPoint + // during a drag-and-drop operation. + const textRange = document.body.createTextRange(); + textRange.moveToPoint(x, y); + textRange.select(); + } catch (error) {} + + domRange = getDOMRange(); + setDOMRange(originalDOMRange); + return domRange; + } + } + + getClientRectsForDOMRange(domRange) { + const array = Array.from(domRange.getClientRects()); + const start = array[0]; + const end = array[array.length - 1]; + return [start, end]; + } + +} + +/* eslint-disable +*/ +class SelectionManager extends BasicObject { + constructor(element) { + super(...arguments); + this.didMouseDown = this.didMouseDown.bind(this); + this.selectionDidChange = this.selectionDidChange.bind(this); + this.element = element; + this.locationMapper = new LocationMapper(this.element); + this.pointMapper = new PointMapper(); + this.lockCount = 0; + handleEvent("mousedown", { + onElement: this.element, + withCallback: this.didMouseDown + }); + } + + getLocationRange() { + let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + if (options.strict === false) { + return this.createLocationRangeFromDOMRange(getDOMRange()); + } else if (options.ignoreLock) { + return this.currentLocationRange; + } else if (this.lockedLocationRange) { + return this.lockedLocationRange; + } else { + return this.currentLocationRange; + } + } + + setLocationRange(locationRange) { + if (this.lockedLocationRange) { + return; + } + + locationRange = normalizeRange(locationRange); + const domRange = this.createDOMRangeFromLocationRange(locationRange); + + if (domRange) { + setDOMRange(domRange); + this.updateCurrentLocationRange(locationRange); + } + } + + setLocationRangeFromPointRange(pointRange) { + pointRange = normalizeRange(pointRange); + const startLocation = this.getLocationAtPoint(pointRange[0]); + const endLocation = this.getLocationAtPoint(pointRange[1]); + this.setLocationRange([startLocation, endLocation]); + } + + getClientRectAtLocationRange(locationRange) { + const domRange = this.createDOMRangeFromLocationRange(locationRange); + + if (domRange) { + return this.getClientRectsForDOMRange(domRange)[1]; + } + } + + locationIsCursorTarget(location) { + const node = Array.from(this.findNodeAndOffsetFromLocation(location))[0]; + return nodeIsCursorTarget(node); + } + + lock() { + if (this.lockCount++ === 0) { + this.updateCurrentLocationRange(); + this.lockedLocationRange = this.getLocationRange(); + } + } + + unlock() { + if (--this.lockCount === 0) { + const { + lockedLocationRange + } = this; + this.lockedLocationRange = null; + + if (lockedLocationRange != null) { + return this.setLocationRange(lockedLocationRange); + } + } + } + + clearSelection() { + var _getDOMSelection; + + return (_getDOMSelection = getDOMSelection()) === null || _getDOMSelection === void 0 ? void 0 : _getDOMSelection.removeAllRanges(); + } + + selectionIsCollapsed() { + var _getDOMRange; + + return ((_getDOMRange = getDOMRange()) === null || _getDOMRange === void 0 ? void 0 : _getDOMRange.collapsed) === true; + } + + selectionIsExpanded() { + return !this.selectionIsCollapsed(); + } + + createLocationRangeFromDOMRange(domRange, options) { + if (domRange == null || !this.domRangeWithinElement(domRange)) return; + const start = this.findLocationFromContainerAndOffset(domRange.startContainer, domRange.startOffset, options); + if (!start) return; + const end = domRange.collapsed ? undefined : this.findLocationFromContainerAndOffset(domRange.endContainer, domRange.endOffset, options); + return normalizeRange([start, end]); + } + + didMouseDown() { + return this.pauseTemporarily(); + } + + pauseTemporarily() { + let resumeHandlers; + this.paused = true; + + const resume = () => { + this.paused = false; + clearTimeout(resumeTimeout); + Array.from(resumeHandlers).forEach(handler => { + handler.destroy(); + }); + + if (elementContainsNode(document, this.element)) { + return this.selectionDidChange(); + } + }; + + const resumeTimeout = setTimeout(resume, 200); + resumeHandlers = ["mousemove", "keydown"].map(eventName => handleEvent(eventName, { + onElement: document, + withCallback: resume + })); + } + + selectionDidChange() { + if (!this.paused && !innerElementIsActive(this.element)) { + return this.updateCurrentLocationRange(); + } + } + + updateCurrentLocationRange(locationRange) { + if (locationRange != null ? locationRange : locationRange = this.createLocationRangeFromDOMRange(getDOMRange())) { + if (!rangesAreEqual(locationRange, this.currentLocationRange)) { + var _this$delegate, _this$delegate$locati; + + this.currentLocationRange = locationRange; + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 ? 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)); + } + } + } + + createDOMRangeFromLocationRange(locationRange) { + const rangeStart = this.findContainerAndOffsetFromLocation(locationRange[0]); + const rangeEnd = rangeIsCollapsed(locationRange) ? rangeStart : this.findContainerAndOffsetFromLocation(locationRange[1]) || rangeStart; + + if (rangeStart != null && rangeEnd != null) { + const domRange = document.createRange(); + domRange.setStart(...Array.from(rangeStart || [])); + domRange.setEnd(...Array.from(rangeEnd || [])); + return domRange; + } + } + + getLocationAtPoint(point) { + const domRange = this.createDOMRangeFromPoint(point); + + if (domRange) { + var _this$createLocationR; + + return (_this$createLocationR = this.createLocationRangeFromDOMRange(domRange)) === null || _this$createLocationR === void 0 ? void 0 : _this$createLocationR[0]; + } + } + + domRangeWithinElement(domRange) { + if (domRange.collapsed) { + return elementContainsNode(this.element, domRange.startContainer); + } else { + return elementContainsNode(this.element, domRange.startContainer) && elementContainsNode(this.element, domRange.endContainer); + } + } + +} +SelectionManager.proxyMethod("locationMapper.findLocationFromContainerAndOffset"); +SelectionManager.proxyMethod("locationMapper.findContainerAndOffsetFromLocation"); +SelectionManager.proxyMethod("locationMapper.findNodeAndOffsetFromLocation"); +SelectionManager.proxyMethod("pointMapper.createDOMRangeFromPoint"); +SelectionManager.proxyMethod("pointMapper.getClientRectsForDOMRange"); + +const snapshotsAreEqual = (a, b) => rangesAreEqual(a.selectedRange, b.selectedRange) && a.document.isEqualTo(b.document); + +class EditorController extends Controller { + constructor(_ref) { + let { + editorElement, + document, + html + } = _ref; + super(...arguments); + this.editorElement = editorElement; + this.selectionManager = new SelectionManager(this.editorElement); + this.selectionManager.delegate = this; + this.composition = new Composition(); + this.composition.delegate = this; + this.attachmentManager = new AttachmentManager(this.composition.getAttachments()); + this.attachmentManager.delegate = this; + this.inputController = config.input.getLevel() === 2 ? new Level2InputController(this.editorElement) : new Level0InputController(this.editorElement); + this.inputController.delegate = this; + this.inputController.responder = this.composition; + this.compositionController = new CompositionController(this.editorElement, this.composition); + this.compositionController.delegate = this; + this.toolbarController = new ToolbarController(this.editorElement.toolbarElement); + this.toolbarController.delegate = this; + this.editor = new Editor(this.composition, this.selectionManager, this.editorElement); + + if (document) { + this.editor.loadDocument(document); + } else { + this.editor.loadHTML(html); + } + } + + registerSelectionManager() { + return selectionChangeObserver.registerSelectionManager(this.selectionManager); + } + + unregisterSelectionManager() { + return selectionChangeObserver.unregisterSelectionManager(this.selectionManager); + } + + render() { + return this.compositionController.render(); + } + + reparse() { + return this.composition.replaceHTML(this.editorElement.innerHTML); + } // Composition delegate + + + compositionDidChangeDocument(document) { + this.notifyEditorElement("document-change"); + + if (!this.handlingInput) { + return this.render(); + } + } + + compositionDidChangeCurrentAttributes(currentAttributes) { + this.currentAttributes = currentAttributes; + this.toolbarController.updateAttributes(this.currentAttributes); + this.updateCurrentActions(); + return this.notifyEditorElement("attributes-change", { + attributes: this.currentAttributes + }); + } + + compositionDidPerformInsertionAtRange(range) { + if (this.pasting) { + this.pastedRange = range; + } + } + + compositionShouldAcceptFile(file) { + return this.notifyEditorElement("file-accept", { + file + }); + } + + compositionDidAddAttachment(attachment) { + const managedAttachment = this.attachmentManager.manageAttachment(attachment); + return this.notifyEditorElement("attachment-add", { + attachment: managedAttachment + }); + } + + compositionDidEditAttachment(attachment) { + this.compositionController.rerenderViewForObject(attachment); + const managedAttachment = this.attachmentManager.manageAttachment(attachment); + this.notifyEditorElement("attachment-edit", { + attachment: managedAttachment + }); + return this.notifyEditorElement("change"); + } + + compositionDidChangeAttachmentPreviewURL(attachment) { + this.compositionController.invalidateViewForObject(attachment); + return this.notifyEditorElement("change"); + } + + compositionDidRemoveAttachment(attachment) { + const managedAttachment = this.attachmentManager.unmanageAttachment(attachment); + return this.notifyEditorElement("attachment-remove", { + attachment: managedAttachment + }); + } + + compositionDidStartEditingAttachment(attachment, options) { + this.attachmentLocationRange = this.composition.document.getLocationRangeOfAttachment(attachment); + this.compositionController.installAttachmentEditorForAttachment(attachment, options); + return this.selectionManager.setLocationRange(this.attachmentLocationRange); + } + + compositionDidStopEditingAttachment(attachment) { + this.compositionController.uninstallAttachmentEditor(); + this.attachmentLocationRange = null; + } + + compositionDidRequestChangingSelectionToLocationRange(locationRange) { + if (this.loadingSnapshot && !this.isFocused()) { + return; + } + + this.requestedLocationRange = locationRange; + this.compositionRevisionWhenLocationRangeRequested = this.composition.revision; + + if (!this.handlingInput) { + return this.render(); + } + } + + compositionWillLoadSnapshot() { + this.loadingSnapshot = true; + } + + compositionDidLoadSnapshot() { + this.compositionController.refreshViewCache(); + this.render(); + this.loadingSnapshot = false; + } + + getSelectionManager() { + return this.selectionManager; + } // Attachment manager delegate + + + attachmentManagerDidRequestRemovalOfAttachment(attachment) { + return this.removeAttachment(attachment); + } // Document controller delegate + + + compositionControllerWillSyncDocumentView() { + this.inputController.editorWillSyncDocumentView(); + this.selectionManager.lock(); + return this.selectionManager.clearSelection(); + } + + compositionControllerDidSyncDocumentView() { + this.inputController.editorDidSyncDocumentView(); + this.selectionManager.unlock(); + this.updateCurrentActions(); + return this.notifyEditorElement("sync"); + } + + compositionControllerDidRender() { + if (this.requestedLocationRange) { + if (this.compositionRevisionWhenLocationRangeRequested === this.composition.revision) { + this.selectionManager.setLocationRange(this.requestedLocationRange); + } + + this.requestedLocationRange = null; + this.compositionRevisionWhenLocationRangeRequested = null; + } + + if (this.renderedCompositionRevision !== this.composition.revision) { + this.runEditorFilters(); + this.composition.updateCurrentAttributes(); + this.notifyEditorElement("render"); + } + + this.renderedCompositionRevision = this.composition.revision; + } + + compositionControllerDidFocus() { + if (this.isFocusedInvisibly()) { + this.setLocationRange({ + index: 0, + offset: 0 + }); + } + + this.toolbarController.hideDialog(); + return this.notifyEditorElement("focus"); + } + + compositionControllerDidBlur() { + return this.notifyEditorElement("blur"); + } + + compositionControllerDidSelectAttachment(attachment, options) { + this.toolbarController.hideDialog(); + return this.composition.editAttachment(attachment, options); + } + + compositionControllerDidRequestDeselectingAttachment(attachment) { + const locationRange = this.attachmentLocationRange || this.composition.document.getLocationRangeOfAttachment(attachment); + return this.selectionManager.setLocationRange(locationRange[1]); + } + + compositionControllerWillUpdateAttachment(attachment) { + return this.editor.recordUndoEntry("Edit Attachment", { + context: attachment.id, + consolidatable: true + }); + } + + compositionControllerDidRequestRemovalOfAttachment(attachment) { + return this.removeAttachment(attachment); + } // Input controller delegate + + + inputControllerWillHandleInput() { + this.handlingInput = true; + this.requestedRender = false; + } + + inputControllerDidRequestRender() { + this.requestedRender = true; + } + + inputControllerDidHandleInput() { + this.handlingInput = false; + + if (this.requestedRender) { + this.requestedRender = false; + return this.render(); + } + } + + inputControllerDidAllowUnhandledInput() { + return this.notifyEditorElement("change"); + } + + inputControllerDidRequestReparse() { + return this.reparse(); + } + + inputControllerWillPerformTyping() { + return this.recordTypingUndoEntry(); + } + + inputControllerWillPerformFormatting(attributeName) { + return this.recordFormattingUndoEntry(attributeName); + } + + inputControllerWillCutText() { + return this.editor.recordUndoEntry("Cut"); + } + + inputControllerWillPaste(paste) { + this.editor.recordUndoEntry("Paste"); + this.pasting = true; + return this.notifyEditorElement("before-paste", { + paste + }); + } + + inputControllerDidPaste(paste) { + paste.range = this.pastedRange; + this.pastedRange = null; + this.pasting = null; + return this.notifyEditorElement("paste", { + paste + }); + } + + inputControllerWillMoveText() { + return this.editor.recordUndoEntry("Move"); + } + + inputControllerWillAttachFiles() { + return this.editor.recordUndoEntry("Drop Files"); + } + + inputControllerWillPerformUndo() { + return this.editor.undo(); + } + + inputControllerWillPerformRedo() { + return this.editor.redo(); + } + + inputControllerDidReceiveKeyboardCommand(keys) { + return this.toolbarController.applyKeyboardCommand(keys); + } + + inputControllerDidStartDrag() { + this.locationRangeBeforeDrag = this.selectionManager.getLocationRange(); + } + + inputControllerDidReceiveDragOverPoint(point) { + return this.selectionManager.setLocationRangeFromPointRange(point); + } + + inputControllerDidCancelDrag() { + this.selectionManager.setLocationRange(this.locationRangeBeforeDrag); + this.locationRangeBeforeDrag = null; + } // Selection manager delegate + + + locationRangeDidChange(locationRange) { + this.composition.updateCurrentAttributes(); + this.updateCurrentActions(); + + if (this.attachmentLocationRange && !rangesAreEqual(this.attachmentLocationRange, locationRange)) { + this.composition.stopEditingAttachment(); + } + + return this.notifyEditorElement("selection-change"); + } // Toolbar controller delegate + + + toolbarDidClickButton() { + if (!this.getLocationRange()) { + return this.setLocationRange({ + index: 0, + offset: 0 + }); + } + } + + toolbarDidInvokeAction(actionName) { + return this.invokeAction(actionName); + } + + toolbarDidToggleAttribute(attributeName) { + this.recordFormattingUndoEntry(attributeName); + this.composition.toggleCurrentAttribute(attributeName); + this.render(); + + if (!this.selectionFrozen) { + return this.editorElement.focus(); + } + } + + toolbarDidUpdateAttribute(attributeName, value) { + this.recordFormattingUndoEntry(attributeName); + this.composition.setCurrentAttribute(attributeName, value); + this.render(); + + if (!this.selectionFrozen) { + return this.editorElement.focus(); + } + } + + toolbarDidRemoveAttribute(attributeName) { + this.recordFormattingUndoEntry(attributeName); + this.composition.removeCurrentAttribute(attributeName); + this.render(); + + if (!this.selectionFrozen) { + return this.editorElement.focus(); + } + } + + toolbarWillShowDialog(dialogElement) { + this.composition.expandSelectionForEditing(); + return this.freezeSelection(); + } + + toolbarDidShowDialog(dialogName) { + return this.notifyEditorElement("toolbar-dialog-show", { + dialogName + }); + } + + toolbarDidHideDialog(dialogName) { + this.thawSelection(); + this.editorElement.focus(); + return this.notifyEditorElement("toolbar-dialog-hide", { + dialogName + }); + } // Selection + + + freezeSelection() { + if (!this.selectionFrozen) { + this.selectionManager.lock(); + this.composition.freezeSelection(); + this.selectionFrozen = true; + return this.render(); + } + } + + thawSelection() { + if (this.selectionFrozen) { + this.composition.thawSelection(); + this.selectionManager.unlock(); + this.selectionFrozen = false; + return this.render(); + } + } + + canInvokeAction(actionName) { + if (this.actionIsExternal(actionName)) { + return true; + } else { + var _this$actions$actionN, _this$actions$actionN2; + + return !!((_this$actions$actionN = this.actions[actionName]) !== null && _this$actions$actionN !== void 0 && (_this$actions$actionN2 = _this$actions$actionN.test) !== null && _this$actions$actionN2 !== void 0 && _this$actions$actionN2.call(this)); + } + } + + invokeAction(actionName) { + if (this.actionIsExternal(actionName)) { + return this.notifyEditorElement("action-invoke", { + actionName + }); + } else { + var _this$actions$actionN3, _this$actions$actionN4; + + return (_this$actions$actionN3 = this.actions[actionName]) === null || _this$actions$actionN3 === void 0 ? void 0 : (_this$actions$actionN4 = _this$actions$actionN3.perform) === null || _this$actions$actionN4 === void 0 ? void 0 : _this$actions$actionN4.call(this); + } + } + + actionIsExternal(actionName) { + return /^x-./.test(actionName); + } + + getCurrentActions() { + const result = {}; + + for (const actionName in this.actions) { + result[actionName] = this.canInvokeAction(actionName); + } + + return result; + } + + updateCurrentActions() { + const currentActions = this.getCurrentActions(); + + if (!objectsAreEqual(currentActions, this.currentActions)) { + this.currentActions = currentActions; + this.toolbarController.updateActions(this.currentActions); + return this.notifyEditorElement("actions-change", { + actions: this.currentActions + }); + } + } // Editor filters + + + runEditorFilters() { + let snapshot = this.composition.getSnapshot(); + Array.from(this.editor.filters).forEach(filter => { + const { + document, + selectedRange + } = snapshot; + snapshot = filter.call(this.editor, snapshot) || {}; + + if (!snapshot.document) { + snapshot.document = document; + } + + if (!snapshot.selectedRange) { + snapshot.selectedRange = selectedRange; + } + }); + + if (!snapshotsAreEqual(snapshot, this.composition.getSnapshot())) { + return this.composition.loadSnapshot(snapshot); + } + } // Private + + + updateInputElement() { + const element = this.compositionController.getSerializableElement(); + const value = serializeToContentType(element, "text/html"); + return this.editorElement.setInputElementValue(value); + } + + notifyEditorElement(message, data) { + switch (message) { + case "document-change": + this.documentChangedSinceLastRender = true; + break; + + case "render": + if (this.documentChangedSinceLastRender) { + this.documentChangedSinceLastRender = false; + this.notifyEditorElement("change"); + } + + break; + + case "change": + case "attachment-add": + case "attachment-edit": + case "attachment-remove": + this.updateInputElement(); + break; + } + + return this.editorElement.notify(message, data); + } + + removeAttachment(attachment) { + this.editor.recordUndoEntry("Delete Attachment"); + this.composition.removeAttachment(attachment); + return this.render(); + } + + recordFormattingUndoEntry(attributeName) { + const blockConfig = getBlockConfig(attributeName); + const locationRange = this.selectionManager.getLocationRange(); + + if (blockConfig || !rangeIsCollapsed(locationRange)) { + return this.editor.recordUndoEntry("Formatting", { + context: this.getUndoContext(), + consolidatable: true + }); + } + } + + recordTypingUndoEntry() { + return this.editor.recordUndoEntry("Typing", { + context: this.getUndoContext(this.currentAttributes), + consolidatable: true + }); + } + + getUndoContext() { + for (var _len = arguments.length, context = new Array(_len), _key = 0; _key < _len; _key++) { + context[_key] = arguments[_key]; + } + + return [this.getLocationContext(), this.getTimeContext(), ...Array.from(context)]; + } + + getLocationContext() { + const locationRange = this.selectionManager.getLocationRange(); + + if (rangeIsCollapsed(locationRange)) { + return locationRange[0].index; + } else { + return locationRange; + } + } + + getTimeContext() { + if (config.undoInterval > 0) { + return Math.floor(new Date().getTime() / config.undoInterval); + } else { + return 0; + } + } + + isFocused() { + var _this$editorElement$o; + + return this.editorElement === ((_this$editorElement$o = this.editorElement.ownerDocument) === null || _this$editorElement$o === void 0 ? void 0 : _this$editorElement$o.activeElement); + } // Detect "Cursor disappears sporadically" Firefox bug. + // - https://bugzilla.mozilla.org/show_bug.cgi?id=226301 + + + isFocusedInvisibly() { + return this.isFocused() && !this.getLocationRange(); + } + + get actions() { + return this.constructor.actions; + } + +} + +_defineProperty(EditorController, "actions", { + undo: { + test() { + return this.editor.canUndo(); + }, + + perform() { + return this.editor.undo(); + } + + }, + redo: { + test() { + return this.editor.canRedo(); + }, + + perform() { + return this.editor.redo(); + } + + }, + link: { + test() { + return this.editor.canActivateAttribute("href"); + } + + }, + increaseNestingLevel: { + test() { + return this.editor.canIncreaseNestingLevel(); + }, + + perform() { + return this.editor.increaseNestingLevel() && this.render(); + } + + }, + decreaseNestingLevel: { + test() { + return this.editor.canDecreaseNestingLevel(); + }, + + perform() { + return this.editor.decreaseNestingLevel() && this.render(); + } + + }, + attachFiles: { + test() { + return true; + }, + + perform() { + return config.input.pickFiles(this.editor.insertFiles); + } + + } +}); + +EditorController.proxyMethod("getSelectionManager().setLocationRange"); +EditorController.proxyMethod("getSelectionManager().getLocationRange"); + +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}"); +class TrixToolbarElement extends HTMLElement { + // Element lifecycle + connectedCallback() { + if (this.innerHTML === "") { + this.innerHTML = config.toolbar.getDefaultHTML(); + } + } + +} +window.customElements.define("trix-toolbar", TrixToolbarElement); + +let id = 0; // Contenteditable support helpers + +const autofocus = function (element) { + if (!document.querySelector(":focus")) { + if (element.hasAttribute("autofocus") && document.querySelector("[autofocus]") === element) { + return element.focus(); + } + } +}; + +const makeEditable = function (element) { + if (element.hasAttribute("contenteditable")) { + return; + } + + element.setAttribute("contenteditable", ""); + return handleEventOnce("focus", { + onElement: element, + + withCallback() { + return configureContentEditable(element); + } + + }); +}; + +const configureContentEditable = function (element) { + disableObjectResizing(element); + return setDefaultParagraphSeparator(element); +}; + +const disableObjectResizing = function (element) { + var _document$queryComman, _document; + + if ((_document$queryComman = (_document = document).queryCommandSupported) !== null && _document$queryComman !== void 0 && _document$queryComman.call(_document, "enableObjectResizing")) { + document.execCommand("enableObjectResizing", false, false); + return handleEvent("mscontrolselect", { + onElement: element, + preventDefault: true + }); + } +}; + +const setDefaultParagraphSeparator = function (element) { + var _document$queryComman2, _document2; + + if ((_document$queryComman2 = (_document2 = document).queryCommandSupported) !== null && _document$queryComman2 !== void 0 && _document$queryComman2.call(_document2, "DefaultParagraphSeparator")) { + const { + tagName + } = config.blockAttributes.default; + + if (["div", "p"].includes(tagName)) { + return document.execCommand("DefaultParagraphSeparator", false, tagName); + } + } +}; // Accessibility helpers + + +const addAccessibilityRole = function (element) { + if (element.hasAttribute("role")) { + return; + } + + return element.setAttribute("role", "textbox"); +}; + +const ensureAriaLabel = function (element) { + if (element.hasAttribute("aria-label") || element.hasAttribute("aria-labelledby")) { + return; + } + + const update = function () { + const texts = Array.from(element.labels).map(label => { + if (!label.contains(element)) return label.textContent; + }).filter(text => text); + const text = texts.join(" "); + + if (text) { + return element.setAttribute("aria-label", text); + } else { + return element.removeAttribute("aria-label"); + } + }; + + update(); + return handleEvent("focus", { + onElement: element, + withCallback: update + }); +}; // Style + + +const cursorTargetStyles = function () { + if (config.browser.forcesObjectResizing) { + return { + display: "inline", + width: "auto" + }; + } else { + return { + display: "inline-block", + width: "1px" + }; + } +}(); + +installDefaultCSSForTagName("trix-editor", "%t {\n display: block;\n}\n\n%t:empty:not(:focus)::before {\n content: attr(placeholder);\n color: graytext;\n cursor: text;\n pointer-events: none;\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}")); +class TrixEditorElement extends HTMLElement { + // Properties + get trixId() { + if (this.hasAttribute("trix-id")) { + return this.getAttribute("trix-id"); + } else { + this.setAttribute("trix-id", ++id); + return this.trixId; + } + } + + get labels() { + const labels = []; + + if (this.id && this.ownerDocument) { + labels.push(...Array.from(this.ownerDocument.querySelectorAll("label[for='".concat(this.id, "']")) || [])); + } + + const label = findClosestElementFromNode(this, { + matchingSelector: "label" + }); + + if (label) { + if ([this, null].includes(label.control)) { + labels.push(label); + } + } + + return labels; + } + + get toolbarElement() { + if (this.hasAttribute("toolbar")) { + var _this$ownerDocument; + + return (_this$ownerDocument = this.ownerDocument) === null || _this$ownerDocument === void 0 ? void 0 : _this$ownerDocument.getElementById(this.getAttribute("toolbar")); + } else if (this.parentNode) { + const toolbarId = "trix-toolbar-".concat(this.trixId); + this.setAttribute("toolbar", toolbarId); + const element = makeElement("trix-toolbar", { + id: toolbarId + }); + this.parentNode.insertBefore(element, this); + return element; + } else { + return undefined; + } + } + + get form() { + var _this$inputElement; + + return (_this$inputElement = this.inputElement) === null || _this$inputElement === void 0 ? void 0 : _this$inputElement.form; + } + + get inputElement() { + if (this.hasAttribute("input")) { + var _this$ownerDocument2; + + return (_this$ownerDocument2 = this.ownerDocument) === null || _this$ownerDocument2 === void 0 ? void 0 : _this$ownerDocument2.getElementById(this.getAttribute("input")); + } else if (this.parentNode) { + const inputId = "trix-input-".concat(this.trixId); + this.setAttribute("input", inputId); + const element = makeElement("input", { + type: "hidden", + id: inputId + }); + this.parentNode.insertBefore(element, this.nextElementSibling); + return element; + } else { + return undefined; + } + } + + get editor() { + var _this$editorControlle; + + return (_this$editorControlle = this.editorController) === null || _this$editorControlle === void 0 ? void 0 : _this$editorControlle.editor; + } + + get name() { + var _this$inputElement2; + + return (_this$inputElement2 = this.inputElement) === null || _this$inputElement2 === void 0 ? void 0 : _this$inputElement2.name; + } + + get value() { + var _this$inputElement3; + + return (_this$inputElement3 = this.inputElement) === null || _this$inputElement3 === void 0 ? void 0 : _this$inputElement3.value; + } + + set value(defaultValue) { + var _this$editor; + + this.defaultValue = defaultValue; + (_this$editor = this.editor) === null || _this$editor === void 0 ? void 0 : _this$editor.loadHTML(this.defaultValue); + } // Controller delegate methods + + + notify(message, data) { + if (this.editorController) { + return triggerEvent$1("trix-".concat(message), { + onElement: this, + attributes: data + }); + } + } + + setInputElementValue(value) { + if (this.inputElement) { + this.inputElement.value = value; + } + } // Element lifecycle + + + connectedCallback() { + if (!this.hasAttribute("data-trix-internal")) { + makeEditable(this); + addAccessibilityRole(this); + ensureAriaLabel(this); + + if (!this.editorController) { + triggerEvent$1("trix-before-initialize", { + onElement: this + }); + this.editorController = new EditorController({ + editorElement: this, + html: this.defaultValue = this.value + }); + requestAnimationFrame(() => triggerEvent$1("trix-initialize", { + onElement: this + })); + } + + this.editorController.registerSelectionManager(); + this.registerResetListener(); + this.registerClickListener(); + autofocus(this); + } + } + + disconnectedCallback() { + var _this$editorControlle2; + + (_this$editorControlle2 = this.editorController) === null || _this$editorControlle2 === void 0 ? void 0 : _this$editorControlle2.unregisterSelectionManager(); + this.unregisterResetListener(); + return this.unregisterClickListener(); + } // Form support + + + registerResetListener() { + this.resetListener = this.resetBubbled.bind(this); + return window.addEventListener("reset", this.resetListener, false); + } + + unregisterResetListener() { + return window.removeEventListener("reset", this.resetListener, false); + } + + registerClickListener() { + this.clickListener = this.clickBubbled.bind(this); + return window.addEventListener("click", this.clickListener, false); + } + + unregisterClickListener() { + return window.removeEventListener("click", this.clickListener, false); + } + + resetBubbled(event) { + if (event.defaultPrevented) { + return; + } + + if (event.target !== this.form) { + return; + } + + return this.reset(); + } + + clickBubbled(event) { + if (event.defaultPrevented) return; + if (this.contains(event.target)) return; + const label = findClosestElementFromNode(event.target, { + matchingSelector: "label" + }); + if (!label) return; + if (!Array.from(this.labels).includes(label)) return; + return this.focus(); + } + + reset() { + this.value = this.defaultValue; + } + +} +window.customElements.define("trix-editor", TrixEditorElement); + +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function commonjsRequire () { + throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs'); +} + +function unwrapExports (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; +} + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +function getCjsExportFromNamespace (n) { + return n && n['default'] || n; +} + +// Trix bundle) to install the following global helpers. + +commonjsGlobal.getEditorElement = () => document.querySelector("trix-editor"); + +commonjsGlobal.getToolbarElement = () => getEditorElement().toolbarElement; + +commonjsGlobal.getEditorController = () => getEditorElement().editorController; + +commonjsGlobal.getEditor = () => getEditorController().editor; + +commonjsGlobal.getComposition = () => getEditorController().composition; + +commonjsGlobal.getDocument = () => getComposition().document; + +commonjsGlobal.getSelectionManager = () => getEditorController().selectionManager; + +var global$1 = {}; + +const createEvent$1 = function (type) { + let properties = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const event = document.createEvent("Events"); + event.initEvent(type, true, true); + + for (const key in properties) { + const value = properties[key]; + event[key] = value; + } + + return event; +}; +const triggerEvent = (element, type, properties) => element.dispatchEvent(createEvent$1(type, properties)); + +const { + assert +} = QUnit; + +assert.locationRange = function (start, end) { + const expectedLocationRange = normalizeRange([start, end]); + const actualLocationRange = getEditorController().getLocationRange(); + this.deepEqual(actualLocationRange, expectedLocationRange); +}; + +assert.selectedRange = function (range) { + const expectedRange = normalizeRange(range); + const actualRange = getEditor().getSelectedRange(); + this.deepEqual(actualRange, expectedRange); +}; + +assert.textAttributes = function (range, attributes) { + const document = window.getDocument().getDocumentAtRange(range); + const blocks = document.getBlocks(); + + if (blocks.length !== 1) { + throw "range ".concat(JSON.stringify(range), " spans more than one block"); + } + + const locationRange = window.getDocument().locationRangeFromRange(range); + const textIndex = locationRange[0].index; + const textRange = [locationRange[0].offset, locationRange[1].offset]; + const text = window.getDocument().getTextAtIndex(textIndex).getTextAtRange(textRange); + const pieces = text.getPieces(); + + if (pieces.length !== 1) { + throw "range ".concat(JSON.stringify(range), " must only span one piece"); + } + + const piece = pieces[0]; + this.deepEqual(piece.getAttributes(), attributes); +}; + +assert.blockAttributes = function (range, attributes) { + const document = window.getDocument().getDocumentAtRange(range); + const blocks = document.getBlocks(); + + if (blocks.length !== 1) { + throw "range ".concat(JSON.stringify(range), " spans more than one block"); + } + + const block = blocks[0]; + this.deepEqual(block.getAttributes(), attributes); +}; + +assert.documentHTMLEqual = function (trixDocument, html) { + this.equal(getHTML(trixDocument), html); +}; + +const getHTML = trixDocument => DocumentView.render(trixDocument).innerHTML; + +var editorDefaultAriaLabel = (() => "\n\n\n\n\nARIA Labelledby\n\n\n\n\n\n\n\n\n\n"); + +var editorEmpty = (() => ""); + +var editorHtml = (() => "\n`"); + +var editorInTable = (() => "\n \n \n \n
    \n \n
    "); + +var editorWithBlockStyles = (() => "\n\n"); + +var editorWithBoldStyles = (() => "\n\n"); + +const TEST_IMAGE_URL = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs="; + +var editorWithImage = (() => "\n")); + +var editorWithLabels = (() => "\n\n"); + +var editorWithStyledContent = (() => "\n\n"); + +var editorWithToolbarAndInput = (() => ""); + +var editorsWithForms = (() => "
    \n \n
    \n\n
    \n \n
    \n\n\n"); + +const fixtureTemplates = { + "editor_default_aria_label": editorDefaultAriaLabel, + "editor_empty": editorEmpty, + "editor_html": editorHtml, + "editor_in_table": editorInTable, + "editor_with_block_styles": editorWithBlockStyles, + "editor_with_bold_styles": editorWithBoldStyles, + "editor_with_image": editorWithImage, + "editor_with_labels": editorWithLabels, + "editor_with_styled_content": editorWithStyledContent, + "editor_with_toolbar_and_input": editorWithToolbarAndInput, + "editors_with_forms": editorsWithForms +}; +const { + css +} = config; + +const createDocument = function () { + for (var _len = arguments.length, parts = new Array(_len), _key = 0; _key < _len; _key++) { + parts[_key] = arguments[_key]; + } + + const blocks = (() => { + const result = []; + Array.from(parts).forEach(part => { + const [string, textAttributes, blockAttributes] = Array.from(part); + const text = Text.textForStringWithAttributes(string, textAttributes); + result.push(new Block(text, blockAttributes)); + }); + return result; + })(); + + return new Document(blocks); +}; + +const createCursorTarget = name => makeElement({ + tagName: "span", + textContent: ZERO_WIDTH_SPACE, + data: { + trixCursorTarget: name, + trixSerialize: false + } +}); +const cursorTargetLeft$1 = createCursorTarget("left").outerHTML; +const cursorTargetRight$1 = createCursorTarget("right").outerHTML; +const blockComment = ""; + +const removeWhitespace = string => string.replace(/\s/g, ""); + +const fixtures = { + "bold text": { + document: createDocument(["abc", { + bold: true + }]), + html: "
    ".concat(blockComment, "abc
    "), + serializedHTML: "
    abc
    " + }, + "bold, italic text": { + document: createDocument(["abc", { + bold: true, + italic: true + }]), + html: "
    ".concat(blockComment, "abc
    ") + }, + "text with newline": { + document: createDocument(["ab\nc"]), + html: "
    ".concat(blockComment, "ab
    c
    ") + }, + "text with link": { + document: createDocument(["abc", { + href: "http://example.com" + }]), + html: "
    ".concat(blockComment, "abc
    ") + }, + "text with link and formatting": { + document: createDocument(["abc", { + italic: true, + href: "http://example.com" + }]), + html: "
    ".concat(blockComment, "abc
    ") + }, + "partially formatted link": { + document: new Document([new Block(new Text([new StringPiece("ab", { + href: "http://example.com" + }), new StringPiece("c", { + href: "http://example.com", + italic: true + })]))]), + html: "
    ".concat(blockComment, "abc
    ") + }, + "spaces 1": { + document: createDocument([" a"]), + html: "
    ".concat(blockComment, " a
    ") + }, + "spaces 2": { + document: createDocument([" a"]), + html: "
    ".concat(blockComment, "  a
    ") + }, + "spaces 3": { + document: createDocument([" a"]), + html: "
    ".concat(blockComment, "   a
    ") + }, + "spaces 4": { + document: createDocument([" a "]), + html: "
    ".concat(blockComment, " a 
    ") + }, + "spaces 5": { + document: createDocument(["a b"]), + html: "
    ".concat(blockComment, "a  b
    ") + }, + "spaces 6": { + document: createDocument(["a b"]), + html: "
    ".concat(blockComment, "a   b
    ") + }, + "spaces 7": { + document: createDocument(["a b"]), + html: "
    ".concat(blockComment, "a    b
    ") + }, + "spaces 8": { + document: createDocument(["a b "]), + html: "
    ".concat(blockComment, "a b 
    ") + }, + "spaces 9": { + document: createDocument(["a b c"]), + html: "
    ".concat(blockComment, "a b c
    ") + }, + "spaces 10": { + document: createDocument(["a "]), + html: "
    ".concat(blockComment, "a 
    ") + }, + "spaces 11": { + document: createDocument(["a "]), + html: "
    ".concat(blockComment, "a  
    ") + }, + "spaces and formatting": { + document: new Document([new Block(new Text([new StringPiece(" a "), new StringPiece("b", { + href: "http://b.com" + }), new StringPiece(" "), new StringPiece("c", { + bold: true + }), new StringPiece(" d"), new StringPiece(" e ", { + italic: true + }), new StringPiece(" f ")]))]), + html: "
    ".concat(blockComment, " a b c d e  f  
    ") + }, + "quote formatted block": { + document: createDocument(["abc", {}, ["quote"]]), + html: "
    ".concat(blockComment, "abc
    ") + }, + "code formatted block": { + document: createDocument(["123", {}, ["code"]]), + html: "
    ".concat(blockComment, "123
    ") + }, + "code with newline": { + document: createDocument(["12\n3", {}, ["code"]]), + html: "
    ".concat(blockComment, "12\n3
    ") + }, + "multiple blocks with block comments in their text": { + document: createDocument(["a".concat(blockComment, "b"), {}, ["quote"]], ["".concat(blockComment, "c"), {}, ["code"]]), + html: "
    ".concat(blockComment, "a<!--block-->b
    ").concat(blockComment, "<!--block-->c
    "), + serializedHTML: "
    a<!--block-->b
    <!--block-->c
    " + }, + "unordered list with one item": { + document: createDocument(["a", {}, ["bulletList", "bullet"]]), + html: "") + }, + "unordered list with bold text": { + document: createDocument(["a", { + bold: true + }, ["bulletList", "bullet"]]), + html: "") + }, + "unordered list with partially formatted text": { + document: new Document([new Block(new Text([new StringPiece("a"), new StringPiece("b", { + italic: true + })]), ["bulletList", "bullet"])]), + html: "") + }, + "unordered list with two items": { + document: createDocument(["a", {}, ["bulletList", "bullet"]], ["b", {}, ["bulletList", "bullet"]]), + html: "") + }, + "unordered list surrounded by unformatted blocks": { + document: createDocument(["a"], ["b", {}, ["bulletList", "bullet"]], ["c"]), + html: "
    ".concat(blockComment, "a
    ").concat(blockComment, "c
    ") + }, + "ordered list": { + document: createDocument(["a", {}, ["numberList", "number"]]), + html: "
    1. ".concat(blockComment, "a
    ") + }, + "ordered list and an unordered list": { + document: createDocument(["a", {}, ["bulletList", "bullet"]], ["b", {}, ["numberList", "number"]]), + html: "
    1. ").concat(blockComment, "b
    ") + }, + "empty block with attributes": { + document: createDocument(["", {}, ["quote"]]), + html: "
    ".concat(blockComment, "
    ") + }, + "image attachment": (() => { + const attrs = { + url: TEST_IMAGE_URL, + filename: "example.png", + filesize: 98203, + contentType: "image/png", + width: 1, + height: 1 + }; + const attachment = new Attachment(attrs); + const text = Text.textForAttachmentWithAttributes(attachment); + const image = makeElement("img", { + src: attrs.url, + "data-trix-mutable": true, + width: 1, + height: 1 + }); + image.dataset.trixStoreKey = ["imageElement", attachment.id, image.src, image.width, image.height].join("/"); + const caption = makeElement({ + tagName: "figcaption", + className: css.attachmentCaption + }); + caption.innerHTML = "").concat(attrs.filename, " 95.9 KB"); + const figure = makeElement({ + tagName: "figure", + className: "attachment attachment--preview attachment--png", + editable: false, + data: { + trixAttachment: JSON.stringify(attachment), + trixContentType: "image/png", + trixId: attachment.id + } + }); + figure.setAttribute("contenteditable", false); + figure.appendChild(image); + figure.appendChild(caption); + const serializedFigure = figure.cloneNode(true); + ["data-trix-id", "data-trix-mutable", "data-trix-store-key", "contenteditable"].forEach(attribute => { + serializedFigure.removeAttribute(attribute); + Array.from(serializedFigure.querySelectorAll("[".concat(attribute, "]"))).forEach(element => { + element.removeAttribute(attribute); + }); + }); + return { + html: "
    ".concat(blockComment).concat(cursorTargetLeft$1).concat(figure.outerHTML).concat(cursorTargetRight$1, "
    "), + serializedHTML: "
    ".concat(serializedFigure.outerHTML, "
    "), + document: new Document([new Block(text)]) + }; + })(), + "text with newlines and image attachment": (() => { + const stringText = Text.textForStringWithAttributes("a\nb"); + const attrs = { + url: TEST_IMAGE_URL, + filename: "example.png", + filesize: 98203, + contentType: "image/png", + width: 1, + height: 1 + }; + const attachment = new Attachment(attrs); + const attachmentText = Text.textForAttachmentWithAttributes(attachment); + const image = makeElement("img", { + src: attrs.url, + "data-trix-mutable": true, + width: 1, + height: 1 + }); + image.dataset.trixStoreKey = ["imageElement", attachment.id, image.src, image.width, image.height].join("/"); + const caption = makeElement({ + tagName: "figcaption", + className: css.attachmentCaption + }); + caption.innerHTML = "").concat(attrs.filename, " 95.9 KB"); + const figure = makeElement({ + tagName: "figure", + className: "attachment attachment--preview attachment--png", + editable: false, + data: { + trixAttachment: JSON.stringify(attachment), + trixContentType: "image/png", + trixId: attachment.id + } + }); + figure.appendChild(image); + figure.appendChild(caption); + const serializedFigure = figure.cloneNode(true); + ["data-trix-id", "data-trix-mutable", "data-trix-store-key", "contenteditable"].forEach(attribute => { + serializedFigure.removeAttribute(attribute); + Array.from(serializedFigure.querySelectorAll("[".concat(attribute, "]"))).forEach(element => { + element.removeAttribute(attribute); + }); + }); + const text = stringText.appendText(attachmentText); + return { + html: "
    ".concat(blockComment, "a
    b").concat(cursorTargetLeft$1).concat(figure.outerHTML).concat(cursorTargetRight$1, "
    "), + serializedHTML: "
    a
    b".concat(serializedFigure.outerHTML, "
    "), + document: new Document([new Block(text)]) + }; + })(), + "image attachment with edited caption": (() => { + const attrs = { + url: TEST_IMAGE_URL, + filename: "example.png", + filesize: 123, + contentType: "image/png", + width: 1, + height: 1 + }; + const attachment = new Attachment(attrs); + const textAttrs = { + caption: "Example" + }; + const text = Text.textForAttachmentWithAttributes(attachment, textAttrs); + const image = makeElement("img", { + src: attrs.url, + "data-trix-mutable": true, + width: 1, + height: 1 + }); + image.dataset.trixStoreKey = ["imageElement", attachment.id, image.src, image.width, image.height].join("/"); + const caption = makeElement({ + tagName: "figcaption", + className: "".concat(css.attachmentCaption, " ").concat(css.attachmentCaption, "--edited"), + textContent: "Example" + }); + const figure = makeElement({ + tagName: "figure", + className: "attachment attachment--preview attachment--png", + editable: false, + data: { + trixAttachment: JSON.stringify(attachment), + trixContentType: "image/png", + trixId: attachment.id, + trixAttributes: JSON.stringify(textAttrs) + } + }); + figure.appendChild(image); + figure.appendChild(caption); + return { + html: "
    ".concat(blockComment).concat(cursorTargetLeft$1).concat(figure.outerHTML).concat(cursorTargetRight$1, "
    "), + document: new Document([new Block(text)]) + }; + })(), + "file attachment": (() => { + const attrs = { + href: "http://example.com/example.pdf", + filename: "example.pdf", + filesize: 34038769, + contentType: "application/pdf" + }; + const attachment = new Attachment(attrs); + const text = Text.textForAttachmentWithAttributes(attachment); + const figure = makeElement({ + tagName: "figure", + className: "attachment attachment--file attachment--pdf", + editable: false, + data: { + trixAttachment: JSON.stringify(attachment), + trixContentType: "application/pdf", + trixId: attachment.id + } + }); + const caption = "
    ").concat(attrs.filename, " 32.46 MB
    "); + figure.innerHTML = caption; + const link = makeElement({ + tagName: "a", + editable: false, + attributes: { + href: attrs.href, + tabindex: -1 + } + }); + Array.from(figure.childNodes).forEach(node => { + link.appendChild(node); + }); + figure.appendChild(link); + return { + html: "
    ".concat(blockComment).concat(cursorTargetLeft$1).concat(figure.outerHTML).concat(cursorTargetRight$1, "
    "), + document: new Document([new Block(text)]) + }; + })(), + "pending file attachment": (() => { + const attrs = { + filename: "example.pdf", + filesize: 34038769, + contentType: "application/pdf" + }; + const attachment = new Attachment(attrs); + attachment.file = {}; + const text = Text.textForAttachmentWithAttributes(attachment); + const figure = makeElement({ + tagName: "figure", + className: "attachment attachment--file attachment--pdf", + editable: false, + data: { + trixAttachment: JSON.stringify(attachment), + trixContentType: "application/pdf", + trixId: attachment.id, + trixSerialize: false + } + }); + const progress = makeElement({ + tagName: "progress", + attributes: { + class: "attachment__progress", + value: 0, + max: 100 + }, + data: { + trixMutable: true, + trixStoreKey: ["progressElement", attachment.id].join("/") + } + }); + const caption = "
    ").concat(attrs.filename, " 32.46 MB
    "); + figure.innerHTML = caption + progress.outerHTML; + return { + html: "
    ".concat(blockComment).concat(cursorTargetLeft$1).concat(figure.outerHTML).concat(cursorTargetRight$1, "
    "), + document: new Document([new Block(text)]) + }; + })(), + "content attachment": (() => { + const content = "

    ruby-build 20150413 is out, with definitions for 2.2.2, 2.1.6, and 2.0.0-p645 to address recent security issues: https://t.co/YEwV6NtRD8

    — Sam Stephenson (@sstephenson) April 13, 2015
    "; + const href = "https://twitter.com/sstephenson/status/587715996783218688"; + const contentType = "embed/twitter"; + const attachment = new Attachment({ + content, + contentType, + href + }); + const text = Text.textForAttachmentWithAttributes(attachment); + const figure = makeElement({ + tagName: "figure", + className: "attachment attachment--content", + editable: false, + data: { + trixAttachment: JSON.stringify(attachment), + trixContentType: contentType, + trixId: attachment.id + } + }); + figure.innerHTML = content; + const caption = makeElement({ + tagName: "figcaption", + className: css.attachmentCaption + }); + figure.appendChild(caption); + return { + html: "
    ".concat(blockComment).concat(cursorTargetLeft$1).concat(figure.outerHTML).concat(cursorTargetRight$1, "
    "), + document: new Document([new Block(text)]) + }; + })(), + "nested quote and code formatted block": { + document: createDocument(["ab3", {}, ["quote", "code"]]), + html: "
    ".concat(blockComment, "ab3
    ") + }, + "nested code and quote formatted block": { + document: createDocument(["ab3", {}, ["code", "quote"]]), + html: "
    ".concat(blockComment, "ab3
    ") + }, + "nested code blocks in quote": { + document: createDocument(["a\n", {}, ["quote"]], ["b", {}, ["quote", "code"]], ["\nc\n", {}, ["quote"]], ["d", {}, ["quote", "code"]]), + html: removeWhitespace("
    \n ".concat(blockComment, "\n a\n
    \n
    \n
    \n    ").concat(blockComment, "\n    b\n  
    \n ").concat(blockComment, "\n
    \n c\n
    \n
    \n
    \n    ").concat(blockComment, "\n    d\n  
    \n
    ")), + serializedHTML: removeWhitespace("
    \n a\n
    \n
    \n
    \n    b\n  
    \n
    \n c\n
    \n
    \n
    \n    d\n  
    \n
    ") + }, + "nested code, quote, and list in quote": { + document: createDocument(["a\n", {}, ["quote"]], ["b", {}, ["quote", "code"]], ["\nc\n", {}, ["quote"]], ["d", {}, ["quote", "quote"]], ["\ne\n", {}, ["quote"]], ["f", {}, ["quote", "bulletList", "bullet"]]), + html: removeWhitespace("
    \n ".concat(blockComment, "\n a\n
    \n
    \n
    \n    ").concat(blockComment, "\n    b\n  
    \n ").concat(blockComment, "\n
    \n c\n
    \n
    \n
    \n ").concat(blockComment, "\n d\n
    \n ").concat(blockComment, "\n
    \n e\n
    \n
    \n \n
    ")), + serializedHTML: removeWhitespace("
    \n a\n
    \n
    \n
    \n    b\n  
    \n
    \n c\n
    \n
    \n
    \n d\n
    \n
    \n e\n
    \n
    \n \n
    ") + }, + "nested quotes at different nesting levels": { + document: createDocument(["a", {}, ["quote", "quote", "quote"]], ["b", {}, ["quote", "quote"]], ["c", {}, ["quote"]], ["d", {}, ["quote", "quote"]]), + html: removeWhitespace("
    \n
    \n
    \n ".concat(blockComment, "\n a\n
    \n ").concat(blockComment, "\n b\n
    \n ").concat(blockComment, "\n c\n
    \n ").concat(blockComment, "\n d\n
    \n
    ")), + serializedHTML: removeWhitespace("
    \n
    \n
    \n a\n
    \n b\n
    \n c\n
    \n d\n
    \n
    ") + }, + "nested quote and list": { + document: createDocument(["ab3", {}, ["quote", "bulletList", "bullet"]]), + html: "
    ") + }, + "nested list and quote": { + document: createDocument(["ab3", {}, ["bulletList", "bullet", "quote"]]), + html: "") + }, + "nested lists and quotes": { + document: createDocument(["a", {}, ["bulletList", "bullet", "quote"]], ["b", {}, ["bulletList", "bullet", "quote"]]), + html: "") + }, + "nested quote and list with two items": { + document: createDocument(["a", {}, ["quote", "bulletList", "bullet"]], ["b", {}, ["quote", "bulletList", "bullet"]]), + html: "
    ") + }, + "nested unordered lists": { + document: createDocument(["a", {}, ["bulletList", "bullet"]], ["b", {}, ["bulletList", "bullet", "bulletList", "bullet"]], ["c", {}, ["bulletList", "bullet", "bulletList", "bullet"]]), + html: "") + }, + "nested lists": { + document: createDocument(["a", {}, ["numberList", "number"]], ["b", {}, ["numberList", "number", "bulletList", "bullet"]], ["c", {}, ["numberList", "number", "bulletList", "bullet"]]), + html: "
    1. ".concat(blockComment, "a
      • ").concat(blockComment, "b
      • ").concat(blockComment, "c
    ") + }, + "blocks beginning with newlines": { + document: createDocument(["\na", {}, ["quote"]], ["\nb", {}, []], ["\nc", {}, ["quote"]]), + html: "
    ".concat(blockComment, "
    a
    ").concat(blockComment, "
    b
    ").concat(blockComment, "
    c
    ") + }, + "blocks beginning with formatted text": { + document: createDocument(["a", { + bold: true + }, ["quote"]], ["b", { + italic: true + }, []], ["c", { + bold: true + }, ["quote"]]), + html: "
    ".concat(blockComment, "a
    ").concat(blockComment, "b
    ").concat(blockComment, "c
    ") + }, + "text with newlines before block": { + document: createDocument(["a\nb"], ["c", {}, ["quote"]]), + html: "
    ".concat(blockComment, "a
    b
    ").concat(blockComment, "c
    ") + }, + "empty heading block": { + document: createDocument(["", {}, ["heading1"]]), + html: "

    ".concat(blockComment, "

    ") + }, + "two adjacent headings": { + document: createDocument(["a", {}, ["heading1"]], ["b", {}, ["heading1"]]), + html: "

    ".concat(blockComment, "a

    ").concat(blockComment, "b

    ") + }, + "heading in ordered list": { + document: createDocument(["a", {}, ["numberList", "number", "heading1"]]), + html: "
    1. ".concat(blockComment, "a

    ") + }, + "headings with formatted text": { + document: createDocument(["a", { + bold: true + }, ["heading1"]], ["b", { + italic: true, + bold: true + }, ["heading1"]]), + html: "

    ".concat(blockComment, "a

    ").concat(blockComment, "b

    ") + }, + "bidrectional text": { + document: createDocument(["a"], ["ل", {}, ["quote"]], ["b", {}, ["bulletList", "bullet"]], ["ל", {}, ["bulletList", "bullet"]], ["", {}, ["bulletList", "bullet"]], ["cید"], ["\n گ"]), + html: "
    ".concat(blockComment, "a
    ").concat(blockComment, "\u0644
    ").concat(blockComment, "c\u06CC\u062F
    ").concat(blockComment, "
     \u06AF
    "), + serializedHTML: "\ +
    a
    \ +
    ل
    \ +\ +\ +
    cید
    \ +

     گ
    \ +" + } +}; +const eachFixture = callback => { + for (const name in fixtures) { + const details = fixtures[name]; + callback(name, details); + } +}; + +const setFixtureHTML = function (html) { + let container = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "form"; + let element = document.getElementById("trix-container"); + + if (element != null) { + removeNode(element); + } + + element = document.createElement(container); + element.id = "trix-container"; + element.innerHTML = html; + return document.body.insertAdjacentElement("afterbegin", element); +}; + +let ready = null; +const testGroup = function (name, options, callback) { + let container, setup, teardown, template; + + if (callback != null) { + ({ + container, + template, + setup, + teardown + } = options); + } else { + callback = options; + } + + const beforeEach = () => { + // Ensure window is active on CI so focus and blur events are natively dispatched + window.focus(); + + ready = function (callback) { + if (template != null) { + let handler; + addEventListener("trix-initialize", handler = function (_ref) { + let { + target + } = _ref; + removeEventListener("trix-initialize", handler); + + if (target.hasAttribute("autofocus")) { + target.editor.setSelectedRange(0); + } + + callback(target); + }); + return setFixtureHTML(fixtureTemplates[template](), container); + } else { + callback(); + } + }; + + if (setup) setup(); + }; + + const afterEach = () => { + var _teardown; + + if (template != null) { + setFixtureHTML(""); + } + + return (_teardown = teardown) === null || _teardown === void 0 ? void 0 : _teardown(); + }; + + if (callback != null) { + return QUnit.module(name, function (hooks) { + hooks.beforeEach(beforeEach); + hooks.afterEach(afterEach); + callback(); + }); + } else { + return QUnit.module(name, { + beforeEach, + afterEach + }); + } +}; +const test$3 = (name, callback) => QUnit.test(name, function (assert) { + const doneAsync = assert.async(); + return ready(function (element) { + const done = function (expectedDocumentValue) { + if (element != null) { + if (expectedDocumentValue) { + assert.equal(element.editor.getDocument().toString(), expectedDocumentValue); + } + + requestAnimationFrame(doneAsync); + } else { + return doneAsync(); + } + }; + + if (callback.length === 0) { + callback(); + return done(); + } else { + callback(done); + } + }); +}); +const testIf = function (condition) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + if (condition) { + test$3(...Array.from(args || [])); + } else { + skip(...Array.from(args || [])); + } +}; +const { + skip +} = QUnit; + +class TestCompositionDelegate { + compositionDidRequestChangingSelectionToLocationRange() { + return this.getSelectionManager().setLocationRange(...arguments); + } + + getSelectionManager() { + if (!this.selectionManager) this.selectionManager = new TestSelectionManager(); + return this.selectionManager; + } + +} +class TestSelectionManager { + constructor() { + this.setLocationRange({ + index: 0, + offset: 0 + }); + } + + getLocationRange() { + return this.locationRange; + } + + setLocationRange(locationRange) { + this.locationRange = normalizeRange(locationRange); + } + + preserveSelection(block) { + const locationRange = this.getLocationRange(); + block(); + this.locationRange = locationRange; + } + + setLocationRangeFromPoint(point) {} + + locationIsCursorTarget() { + return false; + } + + selectionIsExpanded() { + return !rangeIsCollapsed(this.getLocationRange()); + } + +} + +const extend = function (properties) { + for (const key in properties) { + const value = properties[key]; + this[key] = value; + } + + return this; +}; +const after$1 = (delay, callback) => setTimeout(callback, delay); + +var rangyCore = createCommonjsModule(function (module, exports) { + /** + * Rangy, a cross-browser JavaScript range and selection library + * https://github.com/timdown/rangy + * + * Copyright 2015, Tim Down + * Licensed under the MIT license. + * Version: 1.3.0 + * Build date: 10 May 2015 + */ + (function (factory, root) { + if (typeof undefined == "function" && undefined.amd) { + // AMD. Register as an anonymous module. + undefined(factory); + } else if ('object' != "undefined" && 'object' == "object") { + // Node/CommonJS style + module.exports = factory(); + } else { + // No AMD or CommonJS support so we place Rangy in (probably) the global variable + root.rangy = factory(); + } + })(function () { + var OBJECT = "object", + FUNCTION = "function", + UNDEFINED = "undefined"; // Minimal set of properties required for DOM Level 2 Range compliance. Comparison constants such as START_TO_START + // are omitted because ranges in KHTML do not have them but otherwise work perfectly well. See issue 113. + + var domRangeProperties = ["startContainer", "startOffset", "endContainer", "endOffset", "collapsed", "commonAncestorContainer"]; // Minimal set of methods required for DOM Level 2 Range compliance + + var domRangeMethods = ["setStart", "setStartBefore", "setStartAfter", "setEnd", "setEndBefore", "setEndAfter", "collapse", "selectNode", "selectNodeContents", "compareBoundaryPoints", "deleteContents", "extractContents", "cloneContents", "insertNode", "surroundContents", "cloneRange", "toString", "detach"]; + var textRangeProperties = ["boundingHeight", "boundingLeft", "boundingTop", "boundingWidth", "htmlText", "text"]; // Subset of TextRange's full set of methods that we're interested in + + var textRangeMethods = ["collapse", "compareEndPoints", "duplicate", "moveToElementText", "parentElement", "select", "setEndPoint", "getBoundingClientRect"]; + /*----------------------------------------------------------------------------------------------------------------*/ + // Trio of functions taken from Peter Michaux's article: + // http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting + + function isHostMethod(o, p) { + var t = typeof o[p]; + return t == FUNCTION || !!(t == OBJECT && o[p]) || t == "unknown"; + } + + function isHostObject(o, p) { + return !!(typeof o[p] == OBJECT && o[p]); + } + + function isHostProperty(o, p) { + return typeof o[p] != UNDEFINED; + } // Creates a convenience function to save verbose repeated calls to tests functions + + + function createMultiplePropertyTest(testFunc) { + return function (o, props) { + var i = props.length; + + while (i--) { + if (!testFunc(o, props[i])) { + return false; + } + } + + return true; + }; + } // Next trio of functions are a convenience to save verbose repeated calls to previous two functions + + + var areHostMethods = createMultiplePropertyTest(isHostMethod); + var areHostObjects = createMultiplePropertyTest(isHostObject); + var areHostProperties = createMultiplePropertyTest(isHostProperty); + + function isTextRange(range) { + return range && areHostMethods(range, textRangeMethods) && areHostProperties(range, textRangeProperties); + } + + function getBody(doc) { + return isHostObject(doc, "body") ? doc.body : doc.getElementsByTagName("body")[0]; + } + + var forEach = [].forEach ? function (arr, func) { + arr.forEach(func); + } : function (arr, func) { + for (var i = 0, len = arr.length; i < len; ++i) { + func(arr[i], i); + } + }; + var modules = {}; + var isBrowser = typeof window != UNDEFINED && typeof document != UNDEFINED; + var util = { + isHostMethod: isHostMethod, + isHostObject: isHostObject, + isHostProperty: isHostProperty, + areHostMethods: areHostMethods, + areHostObjects: areHostObjects, + areHostProperties: areHostProperties, + isTextRange: isTextRange, + getBody: getBody, + forEach: forEach + }; + var api = { + version: "1.3.0", + initialized: false, + isBrowser: isBrowser, + supported: true, + util: util, + features: {}, + modules: modules, + config: { + alertOnFail: false, + alertOnWarn: false, + preferTextRange: false, + autoInitialize: typeof rangyAutoInitialize == UNDEFINED ? true : rangyAutoInitialize + } + }; + + function consoleLog(msg) { + if (typeof console != UNDEFINED && isHostMethod(console, "log")) { + console.log(msg); + } + } + + function alertOrLog(msg, shouldAlert) { + if (isBrowser && shouldAlert) { + alert(msg); + } else { + consoleLog(msg); + } + } + + function fail(reason) { + api.initialized = true; + api.supported = false; + alertOrLog("Rangy is not supported in this environment. Reason: " + reason, api.config.alertOnFail); + } + + api.fail = fail; + + function warn(msg) { + alertOrLog("Rangy warning: " + msg, api.config.alertOnWarn); + } + + api.warn = warn; // Add utility extend() method + + var extend; + + if ({}.hasOwnProperty) { + util.extend = extend = function (obj, props, deep) { + var o, p; + + for (var i in props) { + if (props.hasOwnProperty(i)) { + o = obj[i]; + p = props[i]; + + if (deep && o !== null && typeof o == "object" && p !== null && typeof p == "object") { + extend(o, p, true); + } + + obj[i] = p; + } + } // Special case for toString, which does not show up in for...in loops in IE <= 8 + + + if (props.hasOwnProperty("toString")) { + obj.toString = props.toString; + } + + return obj; + }; + + util.createOptions = function (optionsParam, defaults) { + var options = {}; + extend(options, defaults); + + if (optionsParam) { + extend(options, optionsParam); + } + + return options; + }; + } else { + fail("hasOwnProperty not supported"); + } // Test whether we're in a browser and bail out if not + + + if (!isBrowser) { + fail("Rangy can only run in a browser"); + } // Test whether Array.prototype.slice can be relied on for NodeLists and use an alternative toArray() if not + + + (function () { + var toArray; + + if (isBrowser) { + var el = document.createElement("div"); + el.appendChild(document.createElement("span")); + var slice = [].slice; + + try { + if (slice.call(el.childNodes, 0)[0].nodeType == 1) { + toArray = function (arrayLike) { + return slice.call(arrayLike, 0); + }; + } + } catch (e) {} + } + + if (!toArray) { + toArray = function (arrayLike) { + var arr = []; + + for (var i = 0, len = arrayLike.length; i < len; ++i) { + arr[i] = arrayLike[i]; + } + + return arr; + }; + } + + util.toArray = toArray; + })(); // Very simple event handler wrapper function that doesn't attempt to solve issues such as "this" handling or + // normalization of event properties + + + var addListener; + + if (isBrowser) { + if (isHostMethod(document, "addEventListener")) { + addListener = function (obj, eventType, listener) { + obj.addEventListener(eventType, listener, false); + }; + } else if (isHostMethod(document, "attachEvent")) { + addListener = function (obj, eventType, listener) { + obj.attachEvent("on" + eventType, listener); + }; + } else { + fail("Document does not have required addEventListener or attachEvent method"); + } + + util.addListener = addListener; + } + + var initListeners = []; + + function getErrorDesc(ex) { + return ex.message || ex.description || String(ex); + } // Initialization + + + function init() { + if (!isBrowser || api.initialized) { + return; + } + + var testRange; + var implementsDomRange = false, + implementsTextRange = false; // First, perform basic feature tests + + if (isHostMethod(document, "createRange")) { + testRange = document.createRange(); + + if (areHostMethods(testRange, domRangeMethods) && areHostProperties(testRange, domRangeProperties)) { + implementsDomRange = true; + } + } + + var body = getBody(document); + + if (!body || body.nodeName.toLowerCase() != "body") { + fail("No body element found"); + return; + } + + if (body && isHostMethod(body, "createTextRange")) { + testRange = body.createTextRange(); + + if (isTextRange(testRange)) { + implementsTextRange = true; + } + } + + if (!implementsDomRange && !implementsTextRange) { + fail("Neither Range nor TextRange are available"); + return; + } + + api.initialized = true; + api.features = { + implementsDomRange: implementsDomRange, + implementsTextRange: implementsTextRange + }; // Initialize modules + + var module, errorMessage; + + for (var moduleName in modules) { + if ((module = modules[moduleName]) instanceof Module) { + module.init(module, api); + } + } // Call init listeners + + + for (var i = 0, len = initListeners.length; i < len; ++i) { + try { + initListeners[i](api); + } catch (ex) { + errorMessage = "Rangy init listener threw an exception. Continuing. Detail: " + getErrorDesc(ex); + consoleLog(errorMessage); + } + } + } + + function deprecationNotice(deprecated, replacement, module) { + if (module) { + deprecated += " in module " + module.name; + } + + api.warn("DEPRECATED: " + deprecated + " is deprecated. Please use " + replacement + " instead."); + } + + function createAliasForDeprecatedMethod(owner, deprecated, replacement, module) { + owner[deprecated] = function () { + deprecationNotice(deprecated, replacement, module); + return owner[replacement].apply(owner, util.toArray(arguments)); + }; + } + + util.deprecationNotice = deprecationNotice; + util.createAliasForDeprecatedMethod = createAliasForDeprecatedMethod; // Allow external scripts to initialize this library in case it's loaded after the document has loaded + + api.init = init; // Execute listener immediately if already initialized + + api.addInitListener = function (listener) { + if (api.initialized) { + listener(api); + } else { + initListeners.push(listener); + } + }; + + var shimListeners = []; + + api.addShimListener = function (listener) { + shimListeners.push(listener); + }; + + function shim(win) { + win = win || window; + init(); // Notify listeners + + for (var i = 0, len = shimListeners.length; i < len; ++i) { + shimListeners[i](win); + } + } + + if (isBrowser) { + api.shim = api.createMissingNativeApi = shim; + createAliasForDeprecatedMethod(api, "createMissingNativeApi", "shim"); + } + + function Module(name, dependencies, initializer) { + this.name = name; + this.dependencies = dependencies; + this.initialized = false; + this.supported = false; + this.initializer = initializer; + } + + Module.prototype = { + init: function () { + var requiredModuleNames = this.dependencies || []; + + for (var i = 0, len = requiredModuleNames.length, requiredModule, moduleName; i < len; ++i) { + moduleName = requiredModuleNames[i]; + requiredModule = modules[moduleName]; + + if (!requiredModule || !(requiredModule instanceof Module)) { + throw new Error("required module '" + moduleName + "' not found"); + } + + requiredModule.init(); + + if (!requiredModule.supported) { + throw new Error("required module '" + moduleName + "' not supported"); + } + } // Now run initializer + + + this.initializer(this); + }, + fail: function (reason) { + this.initialized = true; + this.supported = false; + throw new Error(reason); + }, + warn: function (msg) { + api.warn("Module " + this.name + ": " + msg); + }, + deprecationNotice: function (deprecated, replacement) { + api.warn("DEPRECATED: " + deprecated + " in module " + this.name + " is deprecated. Please use " + replacement + " instead"); + }, + createError: function (msg) { + return new Error("Error in Rangy " + this.name + " module: " + msg); + } + }; + + function createModule(name, dependencies, initFunc) { + var newModule = new Module(name, dependencies, function (module) { + if (!module.initialized) { + module.initialized = true; + + try { + initFunc(api, module); + module.supported = true; + } catch (ex) { + var errorMessage = "Module '" + name + "' failed to load: " + getErrorDesc(ex); + consoleLog(errorMessage); + + if (ex.stack) { + consoleLog(ex.stack); + } + } + } + }); + modules[name] = newModule; + return newModule; + } + + api.createModule = function (name) { + // Allow 2 or 3 arguments (second argument is an optional array of dependencies) + var initFunc, dependencies; + + if (arguments.length == 2) { + initFunc = arguments[1]; + dependencies = []; + } else { + initFunc = arguments[2]; + dependencies = arguments[1]; + } + + var module = createModule(name, dependencies, initFunc); // Initialize the module immediately if the core is already initialized + + if (api.initialized && api.supported) { + module.init(); + } + }; + + api.createCoreModule = function (name, dependencies, initFunc) { + createModule(name, dependencies, initFunc); + }; + /*----------------------------------------------------------------------------------------------------------------*/ + // Ensure rangy.rangePrototype and rangy.selectionPrototype are available immediately + + + function RangePrototype() {} + + api.RangePrototype = RangePrototype; + api.rangePrototype = new RangePrototype(); + + function SelectionPrototype() {} + + api.selectionPrototype = new SelectionPrototype(); + /*----------------------------------------------------------------------------------------------------------------*/ + // DOM utility methods used by Rangy + + api.createCoreModule("DomUtil", [], function (api, module) { + var UNDEF = "undefined"; + var util = api.util; + var getBody = util.getBody; // Perform feature tests + + if (!util.areHostMethods(document, ["createDocumentFragment", "createElement", "createTextNode"])) { + module.fail("document missing a Node creation method"); + } + + if (!util.isHostMethod(document, "getElementsByTagName")) { + module.fail("document missing getElementsByTagName method"); + } + + var el = document.createElement("div"); + + if (!util.areHostMethods(el, ["insertBefore", "appendChild", "cloneNode"] || !util.areHostObjects(el, ["previousSibling", "nextSibling", "childNodes", "parentNode"]))) { + module.fail("Incomplete Element implementation"); + } // innerHTML is required for Range's createContextualFragment method + + + if (!util.isHostProperty(el, "innerHTML")) { + module.fail("Element is missing innerHTML property"); + } + + var textNode = document.createTextNode("test"); + + if (!util.areHostMethods(textNode, ["splitText", "deleteData", "insertData", "appendData", "cloneNode"] || !util.areHostObjects(el, ["previousSibling", "nextSibling", "childNodes", "parentNode"]) || !util.areHostProperties(textNode, ["data"]))) { + module.fail("Incomplete Text Node implementation"); + } + /*----------------------------------------------------------------------------------------------------------------*/ + // Removed use of indexOf because of a bizarre bug in Opera that is thrown in one of the Acid3 tests. I haven't been + // able to replicate it outside of the test. The bug is that indexOf returns -1 when called on an Array that + // contains just the document as a single element and the value searched for is the document. + + + var arrayContains = + /*Array.prototype.indexOf ? + function(arr, val) { + return arr.indexOf(val) > -1; + }:*/ + function (arr, val) { + var i = arr.length; + + while (i--) { + if (arr[i] === val) { + return true; + } + } + + return false; + }; // Opera 11 puts HTML elements in the null namespace, it seems, and IE 7 has undefined namespaceURI + + + function isHtmlNamespace(node) { + var ns; + return typeof node.namespaceURI == UNDEF || (ns = node.namespaceURI) === null || ns == "http://www.w3.org/1999/xhtml"; + } + + function parentElement(node) { + var parent = node.parentNode; + return parent.nodeType == 1 ? parent : null; + } + + function getNodeIndex(node) { + var i = 0; + + while (node = node.previousSibling) { + ++i; + } + + return i; + } + + function getNodeLength(node) { + switch (node.nodeType) { + case 7: + case 10: + return 0; + + case 3: + case 8: + return node.length; + + default: + return node.childNodes.length; + } + } + + function getCommonAncestor(node1, node2) { + var ancestors = [], + n; + + for (n = node1; n; n = n.parentNode) { + ancestors.push(n); + } + + for (n = node2; n; n = n.parentNode) { + if (arrayContains(ancestors, n)) { + return n; + } + } + + return null; + } + + function isAncestorOf(ancestor, descendant, selfIsAncestor) { + var n = selfIsAncestor ? descendant : descendant.parentNode; + + while (n) { + if (n === ancestor) { + return true; + } else { + n = n.parentNode; + } + } + + return false; + } + + function isOrIsAncestorOf(ancestor, descendant) { + return isAncestorOf(ancestor, descendant, true); + } + + function getClosestAncestorIn(node, ancestor, selfIsAncestor) { + var p, + n = selfIsAncestor ? node : node.parentNode; + + while (n) { + p = n.parentNode; + + if (p === ancestor) { + return n; + } + + n = p; + } + + return null; + } + + function isCharacterDataNode(node) { + var t = node.nodeType; + return t == 3 || t == 4 || t == 8; // Text, CDataSection or Comment + } + + function isTextOrCommentNode(node) { + if (!node) { + return false; + } + + var t = node.nodeType; + return t == 3 || t == 8; // Text or Comment + } + + function insertAfter(node, precedingNode) { + var nextNode = precedingNode.nextSibling, + parent = precedingNode.parentNode; + + if (nextNode) { + parent.insertBefore(node, nextNode); + } else { + parent.appendChild(node); + } + + return node; + } // Note that we cannot use splitText() because it is bugridden in IE 9. + + + function splitDataNode(node, index, positionsToPreserve) { + var newNode = node.cloneNode(false); + newNode.deleteData(0, index); + node.deleteData(index, node.length - index); + insertAfter(newNode, node); // Preserve positions + + if (positionsToPreserve) { + for (var i = 0, position; position = positionsToPreserve[i++];) { + // Handle case where position was inside the portion of node after the split point + if (position.node == node && position.offset > index) { + position.node = newNode; + position.offset -= index; + } // Handle the case where the position is a node offset within node's parent + else if (position.node == node.parentNode && position.offset > getNodeIndex(node)) { + ++position.offset; + } + } + } + + return newNode; + } + + function getDocument(node) { + if (node.nodeType == 9) { + return node; + } else if (typeof node.ownerDocument != UNDEF) { + return node.ownerDocument; + } else if (typeof node.document != UNDEF) { + return node.document; + } else if (node.parentNode) { + return getDocument(node.parentNode); + } else { + throw module.createError("getDocument: no document found for node"); + } + } + + function getWindow(node) { + var doc = getDocument(node); + + if (typeof doc.defaultView != UNDEF) { + return doc.defaultView; + } else if (typeof doc.parentWindow != UNDEF) { + return doc.parentWindow; + } else { + throw module.createError("Cannot get a window object for node"); + } + } + + function getIframeDocument(iframeEl) { + if (typeof iframeEl.contentDocument != UNDEF) { + return iframeEl.contentDocument; + } else if (typeof iframeEl.contentWindow != UNDEF) { + return iframeEl.contentWindow.document; + } else { + throw module.createError("getIframeDocument: No Document object found for iframe element"); + } + } + + function getIframeWindow(iframeEl) { + if (typeof iframeEl.contentWindow != UNDEF) { + return iframeEl.contentWindow; + } else if (typeof iframeEl.contentDocument != UNDEF) { + return iframeEl.contentDocument.defaultView; + } else { + throw module.createError("getIframeWindow: No Window object found for iframe element"); + } + } // This looks bad. Is it worth it? + + + function isWindow(obj) { + return obj && util.isHostMethod(obj, "setTimeout") && util.isHostObject(obj, "document"); + } + + function getContentDocument(obj, module, methodName) { + var doc; + + if (!obj) { + doc = document; + } // Test if a DOM node has been passed and obtain a document object for it if so + else if (util.isHostProperty(obj, "nodeType")) { + doc = obj.nodeType == 1 && obj.tagName.toLowerCase() == "iframe" ? getIframeDocument(obj) : getDocument(obj); + } // Test if the doc parameter appears to be a Window object + else if (isWindow(obj)) { + doc = obj.document; + } + + if (!doc) { + throw module.createError(methodName + "(): Parameter must be a Window object or DOM node"); + } + + return doc; + } + + function getRootContainer(node) { + var parent; + + while (parent = node.parentNode) { + node = parent; + } + + return node; + } + + function comparePoints(nodeA, offsetA, nodeB, offsetB) { + // See http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Comparing + var nodeC, root, childA, childB, n; + + if (nodeA == nodeB) { + // Case 1: nodes are the same + return offsetA === offsetB ? 0 : offsetA < offsetB ? -1 : 1; + } else if (nodeC = getClosestAncestorIn(nodeB, nodeA, true)) { + // Case 2: node C (container B or an ancestor) is a child node of A + return offsetA <= getNodeIndex(nodeC) ? -1 : 1; + } else if (nodeC = getClosestAncestorIn(nodeA, nodeB, true)) { + // Case 3: node C (container A or an ancestor) is a child node of B + return getNodeIndex(nodeC) < offsetB ? -1 : 1; + } else { + root = getCommonAncestor(nodeA, nodeB); + + if (!root) { + throw new Error("comparePoints error: nodes have no common ancestor"); + } // Case 4: containers are siblings or descendants of siblings + + + childA = nodeA === root ? root : getClosestAncestorIn(nodeA, root, true); + childB = nodeB === root ? root : getClosestAncestorIn(nodeB, root, true); + + if (childA === childB) { + // This shouldn't be possible + throw module.createError("comparePoints got to case 4 and childA and childB are the same!"); + } else { + n = root.firstChild; + + while (n) { + if (n === childA) { + return -1; + } else if (n === childB) { + return 1; + } + + n = n.nextSibling; + } + } + } + } + /*----------------------------------------------------------------------------------------------------------------*/ + // Test for IE's crash (IE 6/7) or exception (IE >= 8) when a reference to garbage-collected text node is queried + + + var crashyTextNodes = false; + + function isBrokenNode(node) { + var n; + + try { + n = node.parentNode; + return false; + } catch (e) { + return true; + } + } + + (function () { + var el = document.createElement("b"); + el.innerHTML = "1"; + var textNode = el.firstChild; + el.innerHTML = "
    "; + crashyTextNodes = isBrokenNode(textNode); + api.features.crashyTextNodes = crashyTextNodes; + })(); + /*----------------------------------------------------------------------------------------------------------------*/ + + + function inspectNode(node) { + if (!node) { + return "[No node]"; + } + + if (crashyTextNodes && isBrokenNode(node)) { + return "[Broken node]"; + } + + if (isCharacterDataNode(node)) { + return '"' + node.data + '"'; + } + + if (node.nodeType == 1) { + var idAttr = node.id ? ' id="' + node.id + '"' : ""; + return "<" + node.nodeName + idAttr + ">[index:" + getNodeIndex(node) + ",length:" + node.childNodes.length + "][" + (node.innerHTML || "[innerHTML not supported]").slice(0, 25) + "]"; + } + + return node.nodeName; + } + + function fragmentFromNodeChildren(node) { + var fragment = getDocument(node).createDocumentFragment(), + child; + + while (child = node.firstChild) { + fragment.appendChild(child); + } + + return fragment; + } + + var getComputedStyleProperty; + + if (typeof window.getComputedStyle != UNDEF) { + getComputedStyleProperty = function (el, propName) { + return getWindow(el).getComputedStyle(el, null)[propName]; + }; + } else if (typeof document.documentElement.currentStyle != UNDEF) { + getComputedStyleProperty = function (el, propName) { + return el.currentStyle ? el.currentStyle[propName] : ""; + }; + } else { + module.fail("No means of obtaining computed style properties found"); + } + + function createTestElement(doc, html, contentEditable) { + var body = getBody(doc); + var el = doc.createElement("div"); + el.contentEditable = "" + !!contentEditable; + + if (html) { + el.innerHTML = html; + } // Insert the test element at the start of the body to prevent scrolling to the bottom in iOS (issue #292) + + + var bodyFirstChild = body.firstChild; + + if (bodyFirstChild) { + body.insertBefore(el, bodyFirstChild); + } else { + body.appendChild(el); + } + + return el; + } + + function removeNode(node) { + return node.parentNode.removeChild(node); + } + + function NodeIterator(root) { + this.root = root; + this._next = root; + } + + NodeIterator.prototype = { + _current: null, + hasNext: function () { + return !!this._next; + }, + next: function () { + var n = this._current = this._next; + var child, next; + + if (this._current) { + child = n.firstChild; + + if (child) { + this._next = child; + } else { + next = null; + + while (n !== this.root && !(next = n.nextSibling)) { + n = n.parentNode; + } + + this._next = next; + } + } + + return this._current; + }, + detach: function () { + this._current = this._next = this.root = null; + } + }; + + function createIterator(root) { + return new NodeIterator(root); + } + + function DomPosition(node, offset) { + this.node = node; + this.offset = offset; + } + + DomPosition.prototype = { + equals: function (pos) { + return !!pos && this.node === pos.node && this.offset == pos.offset; + }, + inspect: function () { + return "[DomPosition(" + inspectNode(this.node) + ":" + this.offset + ")]"; + }, + toString: function () { + return this.inspect(); + } + }; + + function DOMException(codeName) { + this.code = this[codeName]; + this.codeName = codeName; + this.message = "DOMException: " + this.codeName; + } + + DOMException.prototype = { + INDEX_SIZE_ERR: 1, + HIERARCHY_REQUEST_ERR: 3, + WRONG_DOCUMENT_ERR: 4, + NO_MODIFICATION_ALLOWED_ERR: 7, + NOT_FOUND_ERR: 8, + NOT_SUPPORTED_ERR: 9, + INVALID_STATE_ERR: 11, + INVALID_NODE_TYPE_ERR: 24 + }; + + DOMException.prototype.toString = function () { + return this.message; + }; + + api.dom = { + arrayContains: arrayContains, + isHtmlNamespace: isHtmlNamespace, + parentElement: parentElement, + getNodeIndex: getNodeIndex, + getNodeLength: getNodeLength, + getCommonAncestor: getCommonAncestor, + isAncestorOf: isAncestorOf, + isOrIsAncestorOf: isOrIsAncestorOf, + getClosestAncestorIn: getClosestAncestorIn, + isCharacterDataNode: isCharacterDataNode, + isTextOrCommentNode: isTextOrCommentNode, + insertAfter: insertAfter, + splitDataNode: splitDataNode, + getDocument: getDocument, + getWindow: getWindow, + getIframeWindow: getIframeWindow, + getIframeDocument: getIframeDocument, + getBody: getBody, + isWindow: isWindow, + getContentDocument: getContentDocument, + getRootContainer: getRootContainer, + comparePoints: comparePoints, + isBrokenNode: isBrokenNode, + inspectNode: inspectNode, + getComputedStyleProperty: getComputedStyleProperty, + createTestElement: createTestElement, + removeNode: removeNode, + fragmentFromNodeChildren: fragmentFromNodeChildren, + createIterator: createIterator, + DomPosition: DomPosition + }; + api.DOMException = DOMException; + }); + /*----------------------------------------------------------------------------------------------------------------*/ + // Pure JavaScript implementation of DOM Range + + api.createCoreModule("DomRange", ["DomUtil"], function (api, module) { + var dom = api.dom; + var util = api.util; + var DomPosition = dom.DomPosition; + var DOMException = api.DOMException; + var isCharacterDataNode = dom.isCharacterDataNode; + var getNodeIndex = dom.getNodeIndex; + var isOrIsAncestorOf = dom.isOrIsAncestorOf; + var getDocument = dom.getDocument; + var comparePoints = dom.comparePoints; + var splitDataNode = dom.splitDataNode; + var getClosestAncestorIn = dom.getClosestAncestorIn; + var getNodeLength = dom.getNodeLength; + var arrayContains = dom.arrayContains; + var getRootContainer = dom.getRootContainer; + var crashyTextNodes = api.features.crashyTextNodes; + var removeNode = dom.removeNode; + /*----------------------------------------------------------------------------------------------------------------*/ + // Utility functions + + function isNonTextPartiallySelected(node, range) { + return node.nodeType != 3 && (isOrIsAncestorOf(node, range.startContainer) || isOrIsAncestorOf(node, range.endContainer)); + } + + function getRangeDocument(range) { + return range.document || getDocument(range.startContainer); + } + + function getRangeRoot(range) { + return getRootContainer(range.startContainer); + } + + function getBoundaryBeforeNode(node) { + return new DomPosition(node.parentNode, getNodeIndex(node)); + } + + function getBoundaryAfterNode(node) { + return new DomPosition(node.parentNode, getNodeIndex(node) + 1); + } + + function insertNodeAtPosition(node, n, o) { + var firstNodeInserted = node.nodeType == 11 ? node.firstChild : node; + + if (isCharacterDataNode(n)) { + if (o == n.length) { + dom.insertAfter(node, n); + } else { + n.parentNode.insertBefore(node, o == 0 ? n : splitDataNode(n, o)); + } + } else if (o >= n.childNodes.length) { + n.appendChild(node); + } else { + n.insertBefore(node, n.childNodes[o]); + } + + return firstNodeInserted; + } + + function rangesIntersect(rangeA, rangeB, touchingIsIntersecting) { + assertRangeValid(rangeA); + assertRangeValid(rangeB); + + if (getRangeDocument(rangeB) != getRangeDocument(rangeA)) { + throw new DOMException("WRONG_DOCUMENT_ERR"); + } + + var startComparison = comparePoints(rangeA.startContainer, rangeA.startOffset, rangeB.endContainer, rangeB.endOffset), + endComparison = comparePoints(rangeA.endContainer, rangeA.endOffset, rangeB.startContainer, rangeB.startOffset); + return touchingIsIntersecting ? startComparison <= 0 && endComparison >= 0 : startComparison < 0 && endComparison > 0; + } + + function cloneSubtree(iterator) { + var partiallySelected; + + for (var node, frag = getRangeDocument(iterator.range).createDocumentFragment(), subIterator; node = iterator.next();) { + partiallySelected = iterator.isPartiallySelectedSubtree(); + node = node.cloneNode(!partiallySelected); + + if (partiallySelected) { + subIterator = iterator.getSubtreeIterator(); + node.appendChild(cloneSubtree(subIterator)); + subIterator.detach(); + } + + if (node.nodeType == 10) { + // DocumentType + throw new DOMException("HIERARCHY_REQUEST_ERR"); + } + + frag.appendChild(node); + } + + return frag; + } + + function iterateSubtree(rangeIterator, func, iteratorState) { + var it, n; + iteratorState = iteratorState || { + stop: false + }; + + for (var node, subRangeIterator; node = rangeIterator.next();) { + if (rangeIterator.isPartiallySelectedSubtree()) { + if (func(node) === false) { + iteratorState.stop = true; + return; + } else { + // The node is partially selected by the Range, so we can use a new RangeIterator on the portion of + // the node selected by the Range. + subRangeIterator = rangeIterator.getSubtreeIterator(); + iterateSubtree(subRangeIterator, func, iteratorState); + subRangeIterator.detach(); + + if (iteratorState.stop) { + return; + } + } + } else { + // The whole node is selected, so we can use efficient DOM iteration to iterate over the node and its + // descendants + it = dom.createIterator(node); + + while (n = it.next()) { + if (func(n) === false) { + iteratorState.stop = true; + return; + } + } + } + } + } + + function deleteSubtree(iterator) { + var subIterator; + + while (iterator.next()) { + if (iterator.isPartiallySelectedSubtree()) { + subIterator = iterator.getSubtreeIterator(); + deleteSubtree(subIterator); + subIterator.detach(); + } else { + iterator.remove(); + } + } + } + + function extractSubtree(iterator) { + for (var node, frag = getRangeDocument(iterator.range).createDocumentFragment(), subIterator; node = iterator.next();) { + if (iterator.isPartiallySelectedSubtree()) { + node = node.cloneNode(false); + subIterator = iterator.getSubtreeIterator(); + node.appendChild(extractSubtree(subIterator)); + subIterator.detach(); + } else { + iterator.remove(); + } + + if (node.nodeType == 10) { + // DocumentType + throw new DOMException("HIERARCHY_REQUEST_ERR"); + } + + frag.appendChild(node); + } + + return frag; + } + + function getNodesInRange(range, nodeTypes, filter) { + var filterNodeTypes = !!(nodeTypes && nodeTypes.length), + regex; + var filterExists = !!filter; + + if (filterNodeTypes) { + regex = new RegExp("^(" + nodeTypes.join("|") + ")$"); + } + + var nodes = []; + iterateSubtree(new RangeIterator(range, false), function (node) { + if (filterNodeTypes && !regex.test(node.nodeType)) { + return; + } + + if (filterExists && !filter(node)) { + return; + } // Don't include a boundary container if it is a character data node and the range does not contain any + // of its character data. See issue 190. + + + var sc = range.startContainer; + + if (node == sc && isCharacterDataNode(sc) && range.startOffset == sc.length) { + return; + } + + var ec = range.endContainer; + + if (node == ec && isCharacterDataNode(ec) && range.endOffset == 0) { + return; + } + + nodes.push(node); + }); + return nodes; + } + + function inspect(range) { + var name = typeof range.getName == "undefined" ? "Range" : range.getName(); + return "[" + name + "(" + dom.inspectNode(range.startContainer) + ":" + range.startOffset + ", " + dom.inspectNode(range.endContainer) + ":" + range.endOffset + ")]"; + } + /*----------------------------------------------------------------------------------------------------------------*/ + // RangeIterator code partially borrows from IERange by Tim Ryan (http://github.com/timcameronryan/IERange) + + + function RangeIterator(range, clonePartiallySelectedTextNodes) { + this.range = range; + this.clonePartiallySelectedTextNodes = clonePartiallySelectedTextNodes; + + if (!range.collapsed) { + this.sc = range.startContainer; + this.so = range.startOffset; + this.ec = range.endContainer; + this.eo = range.endOffset; + var root = range.commonAncestorContainer; + + if (this.sc === this.ec && isCharacterDataNode(this.sc)) { + this.isSingleCharacterDataNode = true; + this._first = this._last = this._next = this.sc; + } else { + this._first = this._next = this.sc === root && !isCharacterDataNode(this.sc) ? this.sc.childNodes[this.so] : getClosestAncestorIn(this.sc, root, true); + this._last = this.ec === root && !isCharacterDataNode(this.ec) ? this.ec.childNodes[this.eo - 1] : getClosestAncestorIn(this.ec, root, true); + } + } + } + + RangeIterator.prototype = { + _current: null, + _next: null, + _first: null, + _last: null, + isSingleCharacterDataNode: false, + reset: function () { + this._current = null; + this._next = this._first; + }, + hasNext: function () { + return !!this._next; + }, + next: function () { + // Move to next node + var current = this._current = this._next; + + if (current) { + this._next = current !== this._last ? current.nextSibling : null; // Check for partially selected text nodes + + if (isCharacterDataNode(current) && this.clonePartiallySelectedTextNodes) { + if (current === this.ec) { + (current = current.cloneNode(true)).deleteData(this.eo, current.length - this.eo); + } + + if (this._current === this.sc) { + (current = current.cloneNode(true)).deleteData(0, this.so); + } + } + } + + return current; + }, + remove: function () { + var current = this._current, + start, + end; + + if (isCharacterDataNode(current) && (current === this.sc || current === this.ec)) { + start = current === this.sc ? this.so : 0; + end = current === this.ec ? this.eo : current.length; + + if (start != end) { + current.deleteData(start, end - start); + } + } else { + if (current.parentNode) { + removeNode(current); + } else {} + } + }, + // Checks if the current node is partially selected + isPartiallySelectedSubtree: function () { + var current = this._current; + return isNonTextPartiallySelected(current, this.range); + }, + getSubtreeIterator: function () { + var subRange; + + if (this.isSingleCharacterDataNode) { + subRange = this.range.cloneRange(); + subRange.collapse(false); + } else { + subRange = new Range(getRangeDocument(this.range)); + var current = this._current; + var startContainer = current, + startOffset = 0, + endContainer = current, + endOffset = getNodeLength(current); + + if (isOrIsAncestorOf(current, this.sc)) { + startContainer = this.sc; + startOffset = this.so; + } + + if (isOrIsAncestorOf(current, this.ec)) { + endContainer = this.ec; + endOffset = this.eo; + } + + updateBoundaries(subRange, startContainer, startOffset, endContainer, endOffset); + } + + return new RangeIterator(subRange, this.clonePartiallySelectedTextNodes); + }, + detach: function () { + this.range = this._current = this._next = this._first = this._last = this.sc = this.so = this.ec = this.eo = null; + } + }; + /*----------------------------------------------------------------------------------------------------------------*/ + + var beforeAfterNodeTypes = [1, 3, 4, 5, 7, 8, 10]; + var rootContainerNodeTypes = [2, 9, 11]; + var readonlyNodeTypes = [5, 6, 10, 12]; + var insertableNodeTypes = [1, 3, 4, 5, 7, 8, 10, 11]; + var surroundNodeTypes = [1, 3, 4, 5, 7, 8]; + + function createAncestorFinder(nodeTypes) { + return function (node, selfIsAncestor) { + var t, + n = selfIsAncestor ? node : node.parentNode; + + while (n) { + t = n.nodeType; + + if (arrayContains(nodeTypes, t)) { + return n; + } + + n = n.parentNode; + } + + return null; + }; + } + + var getDocumentOrFragmentContainer = createAncestorFinder([9, 11]); + var getReadonlyAncestor = createAncestorFinder(readonlyNodeTypes); + var getDocTypeNotationEntityAncestor = createAncestorFinder([6, 10, 12]); + + function assertNoDocTypeNotationEntityAncestor(node, allowSelf) { + if (getDocTypeNotationEntityAncestor(node, allowSelf)) { + throw new DOMException("INVALID_NODE_TYPE_ERR"); + } + } + + function assertValidNodeType(node, invalidTypes) { + if (!arrayContains(invalidTypes, node.nodeType)) { + throw new DOMException("INVALID_NODE_TYPE_ERR"); + } + } + + function assertValidOffset(node, offset) { + if (offset < 0 || offset > (isCharacterDataNode(node) ? node.length : node.childNodes.length)) { + throw new DOMException("INDEX_SIZE_ERR"); + } + } + + function assertSameDocumentOrFragment(node1, node2) { + if (getDocumentOrFragmentContainer(node1, true) !== getDocumentOrFragmentContainer(node2, true)) { + throw new DOMException("WRONG_DOCUMENT_ERR"); + } + } + + function assertNodeNotReadOnly(node) { + if (getReadonlyAncestor(node, true)) { + throw new DOMException("NO_MODIFICATION_ALLOWED_ERR"); + } + } + + function assertNode(node, codeName) { + if (!node) { + throw new DOMException(codeName); + } + } + + function isValidOffset(node, offset) { + return offset <= (isCharacterDataNode(node) ? node.length : node.childNodes.length); + } + + function isRangeValid(range) { + return !!range.startContainer && !!range.endContainer && !(crashyTextNodes && (dom.isBrokenNode(range.startContainer) || dom.isBrokenNode(range.endContainer))) && getRootContainer(range.startContainer) == getRootContainer(range.endContainer) && isValidOffset(range.startContainer, range.startOffset) && isValidOffset(range.endContainer, range.endOffset); + } + + function assertRangeValid(range) { + if (!isRangeValid(range)) { + throw new Error("Range error: Range is not valid. This usually happens after DOM mutation. Range: (" + range.inspect() + ")"); + } + } + /*----------------------------------------------------------------------------------------------------------------*/ + // Test the browser's innerHTML support to decide how to implement createContextualFragment + + + var styleEl = document.createElement("style"); + var htmlParsingConforms = false; + + try { + styleEl.innerHTML = "x"; + htmlParsingConforms = styleEl.firstChild.nodeType == 3; // Opera incorrectly creates an element node + } catch (e) {// IE 6 and 7 throw + } + + api.features.htmlParsingConforms = htmlParsingConforms; + var createContextualFragment = htmlParsingConforms ? // Implementation as per HTML parsing spec, trusting in the browser's implementation of innerHTML. See + // discussion and base code for this implementation at issue 67. + // Spec: http://html5.org/specs/dom-parsing.html#extensions-to-the-range-interface + // Thanks to Aleks Williams. + function (fragmentStr) { + // "Let node the context object's start's node." + var node = this.startContainer; + var doc = getDocument(node); // "If the context object's start's node is null, raise an INVALID_STATE_ERR + // exception and abort these steps." + + if (!node) { + throw new DOMException("INVALID_STATE_ERR"); + } // "Let element be as follows, depending on node's interface:" + // Document, Document Fragment: null + + + var el = null; // "Element: node" + + if (node.nodeType == 1) { + el = node; // "Text, Comment: node's parentElement" + } else if (isCharacterDataNode(node)) { + el = dom.parentElement(node); + } // "If either element is null or element's ownerDocument is an HTML document + // and element's local name is "html" and element's namespace is the HTML + // namespace" + + + if (el === null || el.nodeName == "HTML" && dom.isHtmlNamespace(getDocument(el).documentElement) && dom.isHtmlNamespace(el)) { + // "let element be a new Element with "body" as its local name and the HTML + // namespace as its namespace."" + el = doc.createElement("body"); + } else { + el = el.cloneNode(false); + } // "If the node's document is an HTML document: Invoke the HTML fragment parsing algorithm." + // "If the node's document is an XML document: Invoke the XML fragment parsing algorithm." + // "In either case, the algorithm must be invoked with fragment as the input + // and element as the context element." + + + el.innerHTML = fragmentStr; // "If this raises an exception, then abort these steps. Otherwise, let new + // children be the nodes returned." + // "Let fragment be a new DocumentFragment." + // "Append all new children to fragment." + // "Return fragment." + + return dom.fragmentFromNodeChildren(el); + } : // In this case, innerHTML cannot be trusted, so fall back to a simpler, non-conformant implementation that + // previous versions of Rangy used (with the exception of using a body element rather than a div) + function (fragmentStr) { + var doc = getRangeDocument(this); + var el = doc.createElement("body"); + el.innerHTML = fragmentStr; + return dom.fragmentFromNodeChildren(el); + }; + + function splitRangeBoundaries(range, positionsToPreserve) { + assertRangeValid(range); + var sc = range.startContainer, + so = range.startOffset, + ec = range.endContainer, + eo = range.endOffset; + var startEndSame = sc === ec; + + if (isCharacterDataNode(ec) && eo > 0 && eo < ec.length) { + splitDataNode(ec, eo, positionsToPreserve); + } + + if (isCharacterDataNode(sc) && so > 0 && so < sc.length) { + sc = splitDataNode(sc, so, positionsToPreserve); + + if (startEndSame) { + eo -= so; + ec = sc; + } else if (ec == sc.parentNode && eo >= getNodeIndex(sc)) { + eo++; + } + + so = 0; + } + + range.setStartAndEnd(sc, so, ec, eo); + } + + function rangeToHtml(range) { + assertRangeValid(range); + var container = range.commonAncestorContainer.parentNode.cloneNode(false); + container.appendChild(range.cloneContents()); + return container.innerHTML; + } + /*----------------------------------------------------------------------------------------------------------------*/ + + + var rangeProperties = ["startContainer", "startOffset", "endContainer", "endOffset", "collapsed", "commonAncestorContainer"]; + var s2s = 0, + s2e = 1, + e2e = 2, + e2s = 3; + var n_b = 0, + n_a = 1, + n_b_a = 2, + n_i = 3; + util.extend(api.rangePrototype, { + compareBoundaryPoints: function (how, range) { + assertRangeValid(this); + assertSameDocumentOrFragment(this.startContainer, range.startContainer); + var nodeA, offsetA, nodeB, offsetB; + var prefixA = how == e2s || how == s2s ? "start" : "end"; + var prefixB = how == s2e || how == s2s ? "start" : "end"; + nodeA = this[prefixA + "Container"]; + offsetA = this[prefixA + "Offset"]; + nodeB = range[prefixB + "Container"]; + offsetB = range[prefixB + "Offset"]; + return comparePoints(nodeA, offsetA, nodeB, offsetB); + }, + insertNode: function (node) { + assertRangeValid(this); + assertValidNodeType(node, insertableNodeTypes); + assertNodeNotReadOnly(this.startContainer); + + if (isOrIsAncestorOf(node, this.startContainer)) { + throw new DOMException("HIERARCHY_REQUEST_ERR"); + } // No check for whether the container of the start of the Range is of a type that does not allow + // children of the type of node: the browser's DOM implementation should do this for us when we attempt + // to add the node + + + var firstNodeInserted = insertNodeAtPosition(node, this.startContainer, this.startOffset); + this.setStartBefore(firstNodeInserted); + }, + cloneContents: function () { + assertRangeValid(this); + var clone, frag; + + if (this.collapsed) { + return getRangeDocument(this).createDocumentFragment(); + } else { + if (this.startContainer === this.endContainer && isCharacterDataNode(this.startContainer)) { + clone = this.startContainer.cloneNode(true); + clone.data = clone.data.slice(this.startOffset, this.endOffset); + frag = getRangeDocument(this).createDocumentFragment(); + frag.appendChild(clone); + return frag; + } else { + var iterator = new RangeIterator(this, true); + clone = cloneSubtree(iterator); + iterator.detach(); + } + + return clone; + } + }, + canSurroundContents: function () { + assertRangeValid(this); + assertNodeNotReadOnly(this.startContainer); + assertNodeNotReadOnly(this.endContainer); // Check if the contents can be surrounded. Specifically, this means whether the range partially selects + // no non-text nodes. + + var iterator = new RangeIterator(this, true); + var boundariesInvalid = iterator._first && isNonTextPartiallySelected(iterator._first, this) || iterator._last && isNonTextPartiallySelected(iterator._last, this); + iterator.detach(); + return !boundariesInvalid; + }, + surroundContents: function (node) { + assertValidNodeType(node, surroundNodeTypes); + + if (!this.canSurroundContents()) { + throw new DOMException("INVALID_STATE_ERR"); + } // Extract the contents + + + var content = this.extractContents(); // Clear the children of the node + + if (node.hasChildNodes()) { + while (node.lastChild) { + node.removeChild(node.lastChild); + } + } // Insert the new node and add the extracted contents + + + insertNodeAtPosition(node, this.startContainer, this.startOffset); + node.appendChild(content); + this.selectNode(node); + }, + cloneRange: function () { + assertRangeValid(this); + var range = new Range(getRangeDocument(this)); + var i = rangeProperties.length, + prop; + + while (i--) { + prop = rangeProperties[i]; + range[prop] = this[prop]; + } + + return range; + }, + toString: function () { + assertRangeValid(this); + var sc = this.startContainer; + + if (sc === this.endContainer && isCharacterDataNode(sc)) { + return sc.nodeType == 3 || sc.nodeType == 4 ? sc.data.slice(this.startOffset, this.endOffset) : ""; + } else { + var textParts = [], + iterator = new RangeIterator(this, true); + iterateSubtree(iterator, function (node) { + // Accept only text or CDATA nodes, not comments + if (node.nodeType == 3 || node.nodeType == 4) { + textParts.push(node.data); + } + }); + iterator.detach(); + return textParts.join(""); + } + }, + // The methods below are all non-standard. The following batch were introduced by Mozilla but have since + // been removed from Mozilla. + compareNode: function (node) { + assertRangeValid(this); + var parent = node.parentNode; + var nodeIndex = getNodeIndex(node); + + if (!parent) { + throw new DOMException("NOT_FOUND_ERR"); + } + + var startComparison = this.comparePoint(parent, nodeIndex), + endComparison = this.comparePoint(parent, nodeIndex + 1); + + if (startComparison < 0) { + // Node starts before + return endComparison > 0 ? n_b_a : n_b; + } else { + return endComparison > 0 ? n_a : n_i; + } + }, + comparePoint: function (node, offset) { + assertRangeValid(this); + assertNode(node, "HIERARCHY_REQUEST_ERR"); + assertSameDocumentOrFragment(node, this.startContainer); + + if (comparePoints(node, offset, this.startContainer, this.startOffset) < 0) { + return -1; + } else if (comparePoints(node, offset, this.endContainer, this.endOffset) > 0) { + return 1; + } + + return 0; + }, + createContextualFragment: createContextualFragment, + toHtml: function () { + return rangeToHtml(this); + }, + // touchingIsIntersecting determines whether this method considers a node that borders a range intersects + // with it (as in WebKit) or not (as in Gecko pre-1.9, and the default) + intersectsNode: function (node, touchingIsIntersecting) { + assertRangeValid(this); + + if (getRootContainer(node) != getRangeRoot(this)) { + return false; + } + + var parent = node.parentNode, + offset = getNodeIndex(node); + + if (!parent) { + return true; + } + + var startComparison = comparePoints(parent, offset, this.endContainer, this.endOffset), + endComparison = comparePoints(parent, offset + 1, this.startContainer, this.startOffset); + return touchingIsIntersecting ? startComparison <= 0 && endComparison >= 0 : startComparison < 0 && endComparison > 0; + }, + isPointInRange: function (node, offset) { + assertRangeValid(this); + assertNode(node, "HIERARCHY_REQUEST_ERR"); + assertSameDocumentOrFragment(node, this.startContainer); + return comparePoints(node, offset, this.startContainer, this.startOffset) >= 0 && comparePoints(node, offset, this.endContainer, this.endOffset) <= 0; + }, + // The methods below are non-standard and invented by me. + // Sharing a boundary start-to-end or end-to-start does not count as intersection. + intersectsRange: function (range) { + return rangesIntersect(this, range, false); + }, + // Sharing a boundary start-to-end or end-to-start does count as intersection. + intersectsOrTouchesRange: function (range) { + return rangesIntersect(this, range, true); + }, + intersection: function (range) { + if (this.intersectsRange(range)) { + var startComparison = comparePoints(this.startContainer, this.startOffset, range.startContainer, range.startOffset), + endComparison = comparePoints(this.endContainer, this.endOffset, range.endContainer, range.endOffset); + var intersectionRange = this.cloneRange(); + + if (startComparison == -1) { + intersectionRange.setStart(range.startContainer, range.startOffset); + } + + if (endComparison == 1) { + intersectionRange.setEnd(range.endContainer, range.endOffset); + } + + return intersectionRange; + } + + return null; + }, + union: function (range) { + if (this.intersectsOrTouchesRange(range)) { + var unionRange = this.cloneRange(); + + if (comparePoints(range.startContainer, range.startOffset, this.startContainer, this.startOffset) == -1) { + unionRange.setStart(range.startContainer, range.startOffset); + } + + if (comparePoints(range.endContainer, range.endOffset, this.endContainer, this.endOffset) == 1) { + unionRange.setEnd(range.endContainer, range.endOffset); + } + + return unionRange; + } else { + throw new DOMException("Ranges do not intersect"); + } + }, + containsNode: function (node, allowPartial) { + if (allowPartial) { + return this.intersectsNode(node, false); + } else { + return this.compareNode(node) == n_i; + } + }, + containsNodeContents: function (node) { + return this.comparePoint(node, 0) >= 0 && this.comparePoint(node, getNodeLength(node)) <= 0; + }, + containsRange: function (range) { + var intersection = this.intersection(range); + return intersection !== null && range.equals(intersection); + }, + containsNodeText: function (node) { + var nodeRange = this.cloneRange(); + nodeRange.selectNode(node); + var textNodes = nodeRange.getNodes([3]); + + if (textNodes.length > 0) { + nodeRange.setStart(textNodes[0], 0); + var lastTextNode = textNodes.pop(); + nodeRange.setEnd(lastTextNode, lastTextNode.length); + return this.containsRange(nodeRange); + } else { + return this.containsNodeContents(node); + } + }, + getNodes: function (nodeTypes, filter) { + assertRangeValid(this); + return getNodesInRange(this, nodeTypes, filter); + }, + getDocument: function () { + return getRangeDocument(this); + }, + collapseBefore: function (node) { + this.setEndBefore(node); + this.collapse(false); + }, + collapseAfter: function (node) { + this.setStartAfter(node); + this.collapse(true); + }, + getBookmark: function (containerNode) { + var doc = getRangeDocument(this); + var preSelectionRange = api.createRange(doc); + containerNode = containerNode || dom.getBody(doc); + preSelectionRange.selectNodeContents(containerNode); + var range = this.intersection(preSelectionRange); + var start = 0, + end = 0; + + if (range) { + preSelectionRange.setEnd(range.startContainer, range.startOffset); + start = preSelectionRange.toString().length; + end = start + range.toString().length; + } + + return { + start: start, + end: end, + containerNode: containerNode + }; + }, + moveToBookmark: function (bookmark) { + var containerNode = bookmark.containerNode; + var charIndex = 0; + this.setStart(containerNode, 0); + this.collapse(true); + var nodeStack = [containerNode], + node, + foundStart = false, + stop = false; + var nextCharIndex, i, childNodes; + + while (!stop && (node = nodeStack.pop())) { + if (node.nodeType == 3) { + nextCharIndex = charIndex + node.length; + + if (!foundStart && bookmark.start >= charIndex && bookmark.start <= nextCharIndex) { + this.setStart(node, bookmark.start - charIndex); + foundStart = true; + } + + if (foundStart && bookmark.end >= charIndex && bookmark.end <= nextCharIndex) { + this.setEnd(node, bookmark.end - charIndex); + stop = true; + } + + charIndex = nextCharIndex; + } else { + childNodes = node.childNodes; + i = childNodes.length; + + while (i--) { + nodeStack.push(childNodes[i]); + } + } + } + }, + getName: function () { + return "DomRange"; + }, + equals: function (range) { + return Range.rangesEqual(this, range); + }, + isValid: function () { + return isRangeValid(this); + }, + inspect: function () { + return inspect(this); + }, + detach: function () {// In DOM4, detach() is now a no-op. + } + }); + + function copyComparisonConstantsToObject(obj) { + obj.START_TO_START = s2s; + obj.START_TO_END = s2e; + obj.END_TO_END = e2e; + obj.END_TO_START = e2s; + obj.NODE_BEFORE = n_b; + obj.NODE_AFTER = n_a; + obj.NODE_BEFORE_AND_AFTER = n_b_a; + obj.NODE_INSIDE = n_i; + } + + function copyComparisonConstants(constructor) { + copyComparisonConstantsToObject(constructor); + copyComparisonConstantsToObject(constructor.prototype); + } + + function createRangeContentRemover(remover, boundaryUpdater) { + return function () { + assertRangeValid(this); + var sc = this.startContainer, + so = this.startOffset, + root = this.commonAncestorContainer; + var iterator = new RangeIterator(this, true); // Work out where to position the range after content removal + + var node, boundary; + + if (sc !== root) { + node = getClosestAncestorIn(sc, root, true); + boundary = getBoundaryAfterNode(node); + sc = boundary.node; + so = boundary.offset; + } // Check none of the range is read-only + + + iterateSubtree(iterator, assertNodeNotReadOnly); + iterator.reset(); // Remove the content + + var returnValue = remover(iterator); + iterator.detach(); // Move to the new position + + boundaryUpdater(this, sc, so, sc, so); + return returnValue; + }; + } + + function createPrototypeRange(constructor, boundaryUpdater) { + function createBeforeAfterNodeSetter(isBefore, isStart) { + return function (node) { + assertValidNodeType(node, beforeAfterNodeTypes); + assertValidNodeType(getRootContainer(node), rootContainerNodeTypes); + var boundary = (isBefore ? getBoundaryBeforeNode : getBoundaryAfterNode)(node); + (isStart ? setRangeStart : setRangeEnd)(this, boundary.node, boundary.offset); + }; + } + + function setRangeStart(range, node, offset) { + var ec = range.endContainer, + eo = range.endOffset; + + if (node !== range.startContainer || offset !== range.startOffset) { + // Check the root containers of the range and the new boundary, and also check whether the new boundary + // is after the current end. In either case, collapse the range to the new position + if (getRootContainer(node) != getRootContainer(ec) || comparePoints(node, offset, ec, eo) == 1) { + ec = node; + eo = offset; + } + + boundaryUpdater(range, node, offset, ec, eo); + } + } + + function setRangeEnd(range, node, offset) { + var sc = range.startContainer, + so = range.startOffset; + + if (node !== range.endContainer || offset !== range.endOffset) { + // Check the root containers of the range and the new boundary, and also check whether the new boundary + // is after the current end. In either case, collapse the range to the new position + if (getRootContainer(node) != getRootContainer(sc) || comparePoints(node, offset, sc, so) == -1) { + sc = node; + so = offset; + } + + boundaryUpdater(range, sc, so, node, offset); + } + } // Set up inheritance + + + var F = function () {}; + + F.prototype = api.rangePrototype; + constructor.prototype = new F(); + util.extend(constructor.prototype, { + setStart: function (node, offset) { + assertNoDocTypeNotationEntityAncestor(node, true); + assertValidOffset(node, offset); + setRangeStart(this, node, offset); + }, + setEnd: function (node, offset) { + assertNoDocTypeNotationEntityAncestor(node, true); + assertValidOffset(node, offset); + setRangeEnd(this, node, offset); + }, + + /** + * Convenience method to set a range's start and end boundaries. Overloaded as follows: + * - Two parameters (node, offset) creates a collapsed range at that position + * - Three parameters (node, startOffset, endOffset) creates a range contained with node starting at + * startOffset and ending at endOffset + * - Four parameters (startNode, startOffset, endNode, endOffset) creates a range starting at startOffset in + * startNode and ending at endOffset in endNode + */ + setStartAndEnd: function () { + var args = arguments; + var sc = args[0], + so = args[1], + ec = sc, + eo = so; + + switch (args.length) { + case 3: + eo = args[2]; + break; + + case 4: + ec = args[2]; + eo = args[3]; + break; + } + + boundaryUpdater(this, sc, so, ec, eo); + }, + setBoundary: function (node, offset, isStart) { + this["set" + (isStart ? "Start" : "End")](node, offset); + }, + setStartBefore: createBeforeAfterNodeSetter(true, true), + setStartAfter: createBeforeAfterNodeSetter(false, true), + setEndBefore: createBeforeAfterNodeSetter(true, false), + setEndAfter: createBeforeAfterNodeSetter(false, false), + collapse: function (isStart) { + assertRangeValid(this); + + if (isStart) { + boundaryUpdater(this, this.startContainer, this.startOffset, this.startContainer, this.startOffset); + } else { + boundaryUpdater(this, this.endContainer, this.endOffset, this.endContainer, this.endOffset); + } + }, + selectNodeContents: function (node) { + assertNoDocTypeNotationEntityAncestor(node, true); + boundaryUpdater(this, node, 0, node, getNodeLength(node)); + }, + selectNode: function (node) { + assertNoDocTypeNotationEntityAncestor(node, false); + assertValidNodeType(node, beforeAfterNodeTypes); + var start = getBoundaryBeforeNode(node), + end = getBoundaryAfterNode(node); + boundaryUpdater(this, start.node, start.offset, end.node, end.offset); + }, + extractContents: createRangeContentRemover(extractSubtree, boundaryUpdater), + deleteContents: createRangeContentRemover(deleteSubtree, boundaryUpdater), + canSurroundContents: function () { + assertRangeValid(this); + assertNodeNotReadOnly(this.startContainer); + assertNodeNotReadOnly(this.endContainer); // Check if the contents can be surrounded. Specifically, this means whether the range partially selects + // no non-text nodes. + + var iterator = new RangeIterator(this, true); + var boundariesInvalid = iterator._first && isNonTextPartiallySelected(iterator._first, this) || iterator._last && isNonTextPartiallySelected(iterator._last, this); + iterator.detach(); + return !boundariesInvalid; + }, + splitBoundaries: function () { + splitRangeBoundaries(this); + }, + splitBoundariesPreservingPositions: function (positionsToPreserve) { + splitRangeBoundaries(this, positionsToPreserve); + }, + normalizeBoundaries: function () { + assertRangeValid(this); + var sc = this.startContainer, + so = this.startOffset, + ec = this.endContainer, + eo = this.endOffset; + + var mergeForward = function (node) { + var sibling = node.nextSibling; + + if (sibling && sibling.nodeType == node.nodeType) { + ec = node; + eo = node.length; + node.appendData(sibling.data); + removeNode(sibling); + } + }; + + var mergeBackward = function (node) { + var sibling = node.previousSibling; + + if (sibling && sibling.nodeType == node.nodeType) { + sc = node; + var nodeLength = node.length; + so = sibling.length; + node.insertData(0, sibling.data); + removeNode(sibling); + + if (sc == ec) { + eo += so; + ec = sc; + } else if (ec == node.parentNode) { + var nodeIndex = getNodeIndex(node); + + if (eo == nodeIndex) { + ec = node; + eo = nodeLength; + } else if (eo > nodeIndex) { + eo--; + } + } + } + }; + + var normalizeStart = true; + var sibling; + + if (isCharacterDataNode(ec)) { + if (eo == ec.length) { + mergeForward(ec); + } else if (eo == 0) { + sibling = ec.previousSibling; + + if (sibling && sibling.nodeType == ec.nodeType) { + eo = sibling.length; + + if (sc == ec) { + normalizeStart = false; + } + + sibling.appendData(ec.data); + removeNode(ec); + ec = sibling; + } + } + } else { + if (eo > 0) { + var endNode = ec.childNodes[eo - 1]; + + if (endNode && isCharacterDataNode(endNode)) { + mergeForward(endNode); + } + } + + normalizeStart = !this.collapsed; + } + + if (normalizeStart) { + if (isCharacterDataNode(sc)) { + if (so == 0) { + mergeBackward(sc); + } else if (so == sc.length) { + sibling = sc.nextSibling; + + if (sibling && sibling.nodeType == sc.nodeType) { + if (ec == sibling) { + ec = sc; + eo += sc.length; + } + + sc.appendData(sibling.data); + removeNode(sibling); + } + } + } else { + if (so < sc.childNodes.length) { + var startNode = sc.childNodes[so]; + + if (startNode && isCharacterDataNode(startNode)) { + mergeBackward(startNode); + } + } + } + } else { + sc = ec; + so = eo; + } + + boundaryUpdater(this, sc, so, ec, eo); + }, + collapseToPoint: function (node, offset) { + assertNoDocTypeNotationEntityAncestor(node, true); + assertValidOffset(node, offset); + this.setStartAndEnd(node, offset); + } + }); + copyComparisonConstants(constructor); + } + /*----------------------------------------------------------------------------------------------------------------*/ + // Updates commonAncestorContainer and collapsed after boundary change + + + function updateCollapsedAndCommonAncestor(range) { + range.collapsed = range.startContainer === range.endContainer && range.startOffset === range.endOffset; + range.commonAncestorContainer = range.collapsed ? range.startContainer : dom.getCommonAncestor(range.startContainer, range.endContainer); + } + + function updateBoundaries(range, startContainer, startOffset, endContainer, endOffset) { + range.startContainer = startContainer; + range.startOffset = startOffset; + range.endContainer = endContainer; + range.endOffset = endOffset; + range.document = dom.getDocument(startContainer); + updateCollapsedAndCommonAncestor(range); + } + + function Range(doc) { + this.startContainer = doc; + this.startOffset = 0; + this.endContainer = doc; + this.endOffset = 0; + this.document = doc; + updateCollapsedAndCommonAncestor(this); + } + + createPrototypeRange(Range, updateBoundaries); + util.extend(Range, { + rangeProperties: rangeProperties, + RangeIterator: RangeIterator, + copyComparisonConstants: copyComparisonConstants, + createPrototypeRange: createPrototypeRange, + inspect: inspect, + toHtml: rangeToHtml, + getRangeDocument: getRangeDocument, + rangesEqual: function (r1, r2) { + return r1.startContainer === r2.startContainer && r1.startOffset === r2.startOffset && r1.endContainer === r2.endContainer && r1.endOffset === r2.endOffset; + } + }); + api.DomRange = Range; + }); + /*----------------------------------------------------------------------------------------------------------------*/ + // Wrappers for the browser's native DOM Range and/or TextRange implementation + + api.createCoreModule("WrappedRange", ["DomRange"], function (api, module) { + var WrappedRange, WrappedTextRange; + var dom = api.dom; + var util = api.util; + var DomPosition = dom.DomPosition; + var DomRange = api.DomRange; + var getBody = dom.getBody; + var getContentDocument = dom.getContentDocument; + var isCharacterDataNode = dom.isCharacterDataNode; + /*----------------------------------------------------------------------------------------------------------------*/ + + if (api.features.implementsDomRange) { + // This is a wrapper around the browser's native DOM Range. It has two aims: + // - Provide workarounds for specific browser bugs + // - provide convenient extensions, which are inherited from Rangy's DomRange + (function () { + var rangeProto; + var rangeProperties = DomRange.rangeProperties; + + function updateRangeProperties(range) { + var i = rangeProperties.length, + prop; + + while (i--) { + prop = rangeProperties[i]; + range[prop] = range.nativeRange[prop]; + } // Fix for broken collapsed property in IE 9. + + + range.collapsed = range.startContainer === range.endContainer && range.startOffset === range.endOffset; + } + + function updateNativeRange(range, startContainer, startOffset, endContainer, endOffset) { + var startMoved = range.startContainer !== startContainer || range.startOffset != startOffset; + var endMoved = range.endContainer !== endContainer || range.endOffset != endOffset; + var nativeRangeDifferent = !range.equals(range.nativeRange); // Always set both boundaries for the benefit of IE9 (see issue 35) + + if (startMoved || endMoved || nativeRangeDifferent) { + range.setEnd(endContainer, endOffset); + range.setStart(startContainer, startOffset); + } + } + + var createBeforeAfterNodeSetter; + + WrappedRange = function (range) { + if (!range) { + throw module.createError("WrappedRange: Range must be specified"); + } + + this.nativeRange = range; + updateRangeProperties(this); + }; + + DomRange.createPrototypeRange(WrappedRange, updateNativeRange); + rangeProto = WrappedRange.prototype; + + rangeProto.selectNode = function (node) { + this.nativeRange.selectNode(node); + updateRangeProperties(this); + }; + + rangeProto.cloneContents = function () { + return this.nativeRange.cloneContents(); + }; // Due to a long-standing Firefox bug that I have not been able to find a reliable way to detect, + // insertNode() is never delegated to the native range. + + + rangeProto.surroundContents = function (node) { + this.nativeRange.surroundContents(node); + updateRangeProperties(this); + }; + + rangeProto.collapse = function (isStart) { + this.nativeRange.collapse(isStart); + updateRangeProperties(this); + }; + + rangeProto.cloneRange = function () { + return new WrappedRange(this.nativeRange.cloneRange()); + }; + + rangeProto.refresh = function () { + updateRangeProperties(this); + }; + + rangeProto.toString = function () { + return this.nativeRange.toString(); + }; // Create test range and node for feature detection + + + var testTextNode = document.createTextNode("test"); + getBody(document).appendChild(testTextNode); + var range = document.createRange(); + /*--------------------------------------------------------------------------------------------------------*/ + // Test for Firefox 2 bug that prevents moving the start of a Range to a point after its current end and + // correct for it + + range.setStart(testTextNode, 0); + range.setEnd(testTextNode, 0); + + try { + range.setStart(testTextNode, 1); + + rangeProto.setStart = function (node, offset) { + this.nativeRange.setStart(node, offset); + updateRangeProperties(this); + }; + + rangeProto.setEnd = function (node, offset) { + this.nativeRange.setEnd(node, offset); + updateRangeProperties(this); + }; + + createBeforeAfterNodeSetter = function (name) { + return function (node) { + this.nativeRange[name](node); + updateRangeProperties(this); + }; + }; + } catch (ex) { + rangeProto.setStart = function (node, offset) { + try { + this.nativeRange.setStart(node, offset); + } catch (ex) { + this.nativeRange.setEnd(node, offset); + this.nativeRange.setStart(node, offset); + } + + updateRangeProperties(this); + }; + + rangeProto.setEnd = function (node, offset) { + try { + this.nativeRange.setEnd(node, offset); + } catch (ex) { + this.nativeRange.setStart(node, offset); + this.nativeRange.setEnd(node, offset); + } + + updateRangeProperties(this); + }; + + createBeforeAfterNodeSetter = function (name, oppositeName) { + return function (node) { + try { + this.nativeRange[name](node); + } catch (ex) { + this.nativeRange[oppositeName](node); + this.nativeRange[name](node); + } + + updateRangeProperties(this); + }; + }; + } + + rangeProto.setStartBefore = createBeforeAfterNodeSetter("setStartBefore", "setEndBefore"); + rangeProto.setStartAfter = createBeforeAfterNodeSetter("setStartAfter", "setEndAfter"); + rangeProto.setEndBefore = createBeforeAfterNodeSetter("setEndBefore", "setStartBefore"); + rangeProto.setEndAfter = createBeforeAfterNodeSetter("setEndAfter", "setStartAfter"); + /*--------------------------------------------------------------------------------------------------------*/ + // Always use DOM4-compliant selectNodeContents implementation: it's simpler and less code than testing + // whether the native implementation can be trusted + + rangeProto.selectNodeContents = function (node) { + this.setStartAndEnd(node, 0, dom.getNodeLength(node)); + }; + /*--------------------------------------------------------------------------------------------------------*/ + // Test for and correct WebKit bug that has the behaviour of compareBoundaryPoints round the wrong way for + // constants START_TO_END and END_TO_START: https://bugs.webkit.org/show_bug.cgi?id=20738 + + + range.selectNodeContents(testTextNode); + range.setEnd(testTextNode, 3); + var range2 = document.createRange(); + range2.selectNodeContents(testTextNode); + range2.setEnd(testTextNode, 4); + range2.setStart(testTextNode, 2); + + if (range.compareBoundaryPoints(range.START_TO_END, range2) == -1 && range.compareBoundaryPoints(range.END_TO_START, range2) == 1) { + // This is the wrong way round, so correct for it + rangeProto.compareBoundaryPoints = function (type, range) { + range = range.nativeRange || range; + + if (type == range.START_TO_END) { + type = range.END_TO_START; + } else if (type == range.END_TO_START) { + type = range.START_TO_END; + } + + return this.nativeRange.compareBoundaryPoints(type, range); + }; + } else { + rangeProto.compareBoundaryPoints = function (type, range) { + return this.nativeRange.compareBoundaryPoints(type, range.nativeRange || range); + }; + } + /*--------------------------------------------------------------------------------------------------------*/ + // Test for IE deleteContents() and extractContents() bug and correct it. See issue 107. + + + var el = document.createElement("div"); + el.innerHTML = "123"; + var textNode = el.firstChild; + var body = getBody(document); + body.appendChild(el); + range.setStart(textNode, 1); + range.setEnd(textNode, 2); + range.deleteContents(); + + if (textNode.data == "13") { + // Behaviour is correct per DOM4 Range so wrap the browser's implementation of deleteContents() and + // extractContents() + rangeProto.deleteContents = function () { + this.nativeRange.deleteContents(); + updateRangeProperties(this); + }; + + rangeProto.extractContents = function () { + var frag = this.nativeRange.extractContents(); + updateRangeProperties(this); + return frag; + }; + } else {} + + body.removeChild(el); + body = null; + /*--------------------------------------------------------------------------------------------------------*/ + // Test for existence of createContextualFragment and delegate to it if it exists + + if (util.isHostMethod(range, "createContextualFragment")) { + rangeProto.createContextualFragment = function (fragmentStr) { + return this.nativeRange.createContextualFragment(fragmentStr); + }; + } + /*--------------------------------------------------------------------------------------------------------*/ + // Clean up + + + getBody(document).removeChild(testTextNode); + + rangeProto.getName = function () { + return "WrappedRange"; + }; + + api.WrappedRange = WrappedRange; + + api.createNativeRange = function (doc) { + doc = getContentDocument(doc, module, "createNativeRange"); + return doc.createRange(); + }; + })(); + } + + if (api.features.implementsTextRange) { + /* + This is a workaround for a bug where IE returns the wrong container element from the TextRange's parentElement() + method. For example, in the following (where pipes denote the selection boundaries): + + var range = document.selection.createRange(); + alert(range.parentElement().id); // Should alert "ul" but alerts "b" + This method returns the common ancestor node of the following: + - the parentElement() of the textRange + - the parentElement() of the textRange after calling collapse(true) + - the parentElement() of the textRange after calling collapse(false) + */ + var getTextRangeContainerElement = function (textRange) { + var parentEl = textRange.parentElement(); + var range = textRange.duplicate(); + range.collapse(true); + var startEl = range.parentElement(); + range = textRange.duplicate(); + range.collapse(false); + var endEl = range.parentElement(); + var startEndContainer = startEl == endEl ? startEl : dom.getCommonAncestor(startEl, endEl); + return startEndContainer == parentEl ? startEndContainer : dom.getCommonAncestor(parentEl, startEndContainer); + }; + + var textRangeIsCollapsed = function (textRange) { + return textRange.compareEndPoints("StartToEnd", textRange) == 0; + }; // Gets the boundary of a TextRange expressed as a node and an offset within that node. This function started + // out as an improved version of code found in Tim Cameron Ryan's IERange (http://code.google.com/p/ierange/) + // but has grown, fixing problems with line breaks in preformatted text, adding workaround for IE TextRange + // bugs, handling for inputs and images, plus optimizations. + + + var getTextRangeBoundaryPosition = function (textRange, wholeRangeContainerElement, isStart, isCollapsed, startInfo) { + var workingRange = textRange.duplicate(); + workingRange.collapse(isStart); + var containerElement = workingRange.parentElement(); // Sometimes collapsing a TextRange that's at the start of a text node can move it into the previous node, so + // check for that + + if (!dom.isOrIsAncestorOf(wholeRangeContainerElement, containerElement)) { + containerElement = wholeRangeContainerElement; + } // Deal with nodes that cannot "contain rich HTML markup". In practice, this means form inputs, images and + // similar. See http://msdn.microsoft.com/en-us/library/aa703950%28VS.85%29.aspx + + + if (!containerElement.canHaveHTML) { + var pos = new DomPosition(containerElement.parentNode, dom.getNodeIndex(containerElement)); + return { + boundaryPosition: pos, + nodeInfo: { + nodeIndex: pos.offset, + containerElement: pos.node + } + }; + } + + var workingNode = dom.getDocument(containerElement).createElement("span"); // Workaround for HTML5 Shiv's insane violation of document.createElement(). See Rangy issue 104 and HTML5 + // Shiv issue 64: https://github.com/aFarkas/html5shiv/issues/64 + + if (workingNode.parentNode) { + dom.removeNode(workingNode); + } + + var comparison, + workingComparisonType = isStart ? "StartToStart" : "StartToEnd"; + var previousNode, nextNode, boundaryPosition, boundaryNode; + var start = startInfo && startInfo.containerElement == containerElement ? startInfo.nodeIndex : 0; + var childNodeCount = containerElement.childNodes.length; + var end = childNodeCount; // Check end first. Code within the loop assumes that the endth child node of the container is definitely + // after the range boundary. + + var nodeIndex = end; + + while (true) { + if (nodeIndex == childNodeCount) { + containerElement.appendChild(workingNode); + } else { + containerElement.insertBefore(workingNode, containerElement.childNodes[nodeIndex]); + } + + workingRange.moveToElementText(workingNode); + comparison = workingRange.compareEndPoints(workingComparisonType, textRange); + + if (comparison == 0 || start == end) { + break; + } else if (comparison == -1) { + if (end == start + 1) { + // We know the endth child node is after the range boundary, so we must be done. + break; + } else { + start = nodeIndex; + } + } else { + end = end == start + 1 ? start : nodeIndex; + } + + nodeIndex = Math.floor((start + end) / 2); + containerElement.removeChild(workingNode); + } // We've now reached or gone past the boundary of the text range we're interested in + // so have identified the node we want + + + boundaryNode = workingNode.nextSibling; + + if (comparison == -1 && boundaryNode && isCharacterDataNode(boundaryNode)) { + // This is a character data node (text, comment, cdata). The working range is collapsed at the start of + // the node containing the text range's boundary, so we move the end of the working range to the + // boundary point and measure the length of its text to get the boundary's offset within the node. + workingRange.setEndPoint(isStart ? "EndToStart" : "EndToEnd", textRange); + var offset; + + if (/[\r\n]/.test(boundaryNode.data)) { + /* + For the particular case of a boundary within a text node containing rendered line breaks (within a +
     element, for example), we need a slightly complicated approach to get the boundary's offset in
    +              IE. The facts:
    +               - Each line break is represented as \r in the text node's data/nodeValue properties
    +              - Each line break is represented as \r\n in the TextRange's 'text' property
    +              - The 'text' property of the TextRange does not contain trailing line breaks
    +               To get round the problem presented by the final fact above, we can use the fact that TextRange's
    +              moveStart() and moveEnd() methods return the actual number of characters moved, which is not
    +              necessarily the same as the number of characters it was instructed to move. The simplest approach is
    +              to use this to store the characters moved when moving both the start and end of the range to the
    +              start of the document body and subtracting the start offset from the end offset (the
    +              "move-negative-gazillion" method). However, this is extremely slow when the document is large and
    +              the range is near the end of it. Clearly doing the mirror image (i.e. moving the range boundaries to
    +              the end of the document) has the same problem.
    +               Another approach that works is to use moveStart() to move the start boundary of the range up to the
    +              end boundary one character at a time and incrementing a counter with the value returned by the
    +              moveStart() call. However, the check for whether the start boundary has reached the end boundary is
    +              expensive, so this method is slow (although unlike "move-negative-gazillion" is largely unaffected
    +              by the location of the range within the document).
    +               The approach used below is a hybrid of the two methods above. It uses the fact that a string
    +              containing the TextRange's 'text' property with each \r\n converted to a single \r character cannot
    +              be longer than the text of the TextRange, so the start of the range is moved that length initially
    +              and then a character at a time to make up for any trailing line breaks not contained in the 'text'
    +              property. This has good performance in most situations compared to the previous two methods.
    +              */
    +              var tempRange = workingRange.duplicate();
    +              var rangeLength = tempRange.text.replace(/\r\n/g, "\r").length;
    +              offset = tempRange.moveStart("character", rangeLength);
    +
    +              while ((comparison = tempRange.compareEndPoints("StartToEnd", tempRange)) == -1) {
    +                offset++;
    +                tempRange.moveStart("character", 1);
    +              }
    +            } else {
    +              offset = workingRange.text.length;
    +            }
    +
    +            boundaryPosition = new DomPosition(boundaryNode, offset);
    +          } else {
    +            // If the boundary immediately follows a character data node and this is the end boundary, we should favour
    +            // a position within that, and likewise for a start boundary preceding a character data node
    +            previousNode = (isCollapsed || !isStart) && workingNode.previousSibling;
    +            nextNode = (isCollapsed || isStart) && workingNode.nextSibling;
    +
    +            if (nextNode && isCharacterDataNode(nextNode)) {
    +              boundaryPosition = new DomPosition(nextNode, 0);
    +            } else if (previousNode && isCharacterDataNode(previousNode)) {
    +              boundaryPosition = new DomPosition(previousNode, previousNode.data.length);
    +            } else {
    +              boundaryPosition = new DomPosition(containerElement, dom.getNodeIndex(workingNode));
    +            }
    +          } // Clean up
    +
    +
    +          dom.removeNode(workingNode);
    +          return {
    +            boundaryPosition: boundaryPosition,
    +            nodeInfo: {
    +              nodeIndex: nodeIndex,
    +              containerElement: containerElement
    +            }
    +          };
    +        }; // Returns a TextRange representing the boundary of a TextRange expressed as a node and an offset within that
    +        // node. This function started out as an optimized version of code found in Tim Cameron Ryan's IERange
    +        // (http://code.google.com/p/ierange/)
    +
    +
    +        var createBoundaryTextRange = function (boundaryPosition, isStart) {
    +          var boundaryNode,
    +              boundaryParent,
    +              boundaryOffset = boundaryPosition.offset;
    +          var doc = dom.getDocument(boundaryPosition.node);
    +          var workingNode,
    +              childNodes,
    +              workingRange = getBody(doc).createTextRange();
    +          var nodeIsDataNode = isCharacterDataNode(boundaryPosition.node);
    +
    +          if (nodeIsDataNode) {
    +            boundaryNode = boundaryPosition.node;
    +            boundaryParent = boundaryNode.parentNode;
    +          } else {
    +            childNodes = boundaryPosition.node.childNodes;
    +            boundaryNode = boundaryOffset < childNodes.length ? childNodes[boundaryOffset] : null;
    +            boundaryParent = boundaryPosition.node;
    +          } // Position the range immediately before the node containing the boundary
    +
    +
    +          workingNode = doc.createElement("span"); // Making the working element non-empty element persuades IE to consider the TextRange boundary to be within
    +          // the element rather than immediately before or after it
    +
    +          workingNode.innerHTML = "&#feff;"; // insertBefore is supposed to work like appendChild if the second parameter is null. However, a bug report
    +          // for IERange suggests that it can crash the browser: http://code.google.com/p/ierange/issues/detail?id=12
    +
    +          if (boundaryNode) {
    +            boundaryParent.insertBefore(workingNode, boundaryNode);
    +          } else {
    +            boundaryParent.appendChild(workingNode);
    +          }
    +
    +          workingRange.moveToElementText(workingNode);
    +          workingRange.collapse(!isStart); // Clean up
    +
    +          boundaryParent.removeChild(workingNode); // Move the working range to the text offset, if required
    +
    +          if (nodeIsDataNode) {
    +            workingRange[isStart ? "moveStart" : "moveEnd"]("character", boundaryOffset);
    +          }
    +
    +          return workingRange;
    +        };
    +        /*------------------------------------------------------------------------------------------------------------*/
    +        // This is a wrapper around a TextRange, providing full DOM Range functionality using rangy's DomRange as a
    +        // prototype
    +
    +
    +        WrappedTextRange = function (textRange) {
    +          this.textRange = textRange;
    +          this.refresh();
    +        };
    +
    +        WrappedTextRange.prototype = new DomRange(document);
    +
    +        WrappedTextRange.prototype.refresh = function () {
    +          var start, end, startBoundary; // TextRange's parentElement() method cannot be trusted. getTextRangeContainerElement() works around that.
    +
    +          var rangeContainerElement = getTextRangeContainerElement(this.textRange);
    +
    +          if (textRangeIsCollapsed(this.textRange)) {
    +            end = start = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, true, true).boundaryPosition;
    +          } else {
    +            startBoundary = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, true, false);
    +            start = startBoundary.boundaryPosition; // An optimization used here is that if the start and end boundaries have the same parent element, the
    +            // search scope for the end boundary can be limited to exclude the portion of the element that precedes
    +            // the start boundary
    +
    +            end = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, false, false, startBoundary.nodeInfo).boundaryPosition;
    +          }
    +
    +          this.setStart(start.node, start.offset);
    +          this.setEnd(end.node, end.offset);
    +        };
    +
    +        WrappedTextRange.prototype.getName = function () {
    +          return "WrappedTextRange";
    +        };
    +
    +        DomRange.copyComparisonConstants(WrappedTextRange);
    +
    +        var rangeToTextRange = function (range) {
    +          if (range.collapsed) {
    +            return createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
    +          } else {
    +            var startRange = createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
    +            var endRange = createBoundaryTextRange(new DomPosition(range.endContainer, range.endOffset), false);
    +            var textRange = getBody(DomRange.getRangeDocument(range)).createTextRange();
    +            textRange.setEndPoint("StartToStart", startRange);
    +            textRange.setEndPoint("EndToEnd", endRange);
    +            return textRange;
    +          }
    +        };
    +
    +        WrappedTextRange.rangeToTextRange = rangeToTextRange;
    +
    +        WrappedTextRange.prototype.toTextRange = function () {
    +          return rangeToTextRange(this);
    +        };
    +
    +        api.WrappedTextRange = WrappedTextRange; // IE 9 and above have both implementations and Rangy makes both available. The next few lines sets which
    +        // implementation to use by default.
    +
    +        if (!api.features.implementsDomRange || api.config.preferTextRange) {
    +          // Add WrappedTextRange as the Range property of the global object to allow expression like Range.END_TO_END to work
    +          var globalObj = function (f) {
    +            return f("return this;")();
    +          }(Function);
    +
    +          if (typeof globalObj.Range == "undefined") {
    +            globalObj.Range = WrappedTextRange;
    +          }
    +
    +          api.createNativeRange = function (doc) {
    +            doc = getContentDocument(doc, module, "createNativeRange");
    +            return getBody(doc).createTextRange();
    +          };
    +
    +          api.WrappedRange = WrappedTextRange;
    +        }
    +      }
    +
    +      api.createRange = function (doc) {
    +        doc = getContentDocument(doc, module, "createRange");
    +        return new api.WrappedRange(api.createNativeRange(doc));
    +      };
    +
    +      api.createRangyRange = function (doc) {
    +        doc = getContentDocument(doc, module, "createRangyRange");
    +        return new DomRange(doc);
    +      };
    +
    +      util.createAliasForDeprecatedMethod(api, "createIframeRange", "createRange");
    +      util.createAliasForDeprecatedMethod(api, "createIframeRangyRange", "createRangyRange");
    +      api.addShimListener(function (win) {
    +        var doc = win.document;
    +
    +        if (typeof doc.createRange == "undefined") {
    +          doc.createRange = function () {
    +            return api.createRange(doc);
    +          };
    +        }
    +
    +        doc = win = null;
    +      });
    +    });
    +    /*----------------------------------------------------------------------------------------------------------------*/
    +    // This module creates a selection object wrapper that conforms as closely as possible to the Selection specification
    +    // in the HTML Editing spec (http://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#selections)
    +
    +    api.createCoreModule("WrappedSelection", ["DomRange", "WrappedRange"], function (api, module) {
    +      api.config.checkSelectionRanges = true;
    +      var BOOLEAN = "boolean";
    +      var NUMBER = "number";
    +      var dom = api.dom;
    +      var util = api.util;
    +      var isHostMethod = util.isHostMethod;
    +      var DomRange = api.DomRange;
    +      var WrappedRange = api.WrappedRange;
    +      var DOMException = api.DOMException;
    +      var DomPosition = dom.DomPosition;
    +      var getNativeSelection;
    +      var selectionIsCollapsed;
    +      var features = api.features;
    +      var CONTROL = "Control";
    +      var getDocument = dom.getDocument;
    +      var getBody = dom.getBody;
    +      var rangesEqual = DomRange.rangesEqual; // Utility function to support direction parameters in the API that may be a string ("backward", "backwards",
    +      // "forward" or "forwards") or a Boolean (true for backwards).
    +
    +      function isDirectionBackward(dir) {
    +        return typeof dir == "string" ? /^backward(s)?$/i.test(dir) : !!dir;
    +      }
    +
    +      function getWindow(win, methodName) {
    +        if (!win) {
    +          return window;
    +        } else if (dom.isWindow(win)) {
    +          return win;
    +        } else if (win instanceof WrappedSelection) {
    +          return win.win;
    +        } else {
    +          var doc = dom.getContentDocument(win, module, methodName);
    +          return dom.getWindow(doc);
    +        }
    +      }
    +
    +      function getWinSelection(winParam) {
    +        return getWindow(winParam, "getWinSelection").getSelection();
    +      }
    +
    +      function getDocSelection(winParam) {
    +        return getWindow(winParam, "getDocSelection").document.selection;
    +      }
    +
    +      function winSelectionIsBackward(sel) {
    +        var backward = false;
    +
    +        if (sel.anchorNode) {
    +          backward = dom.comparePoints(sel.anchorNode, sel.anchorOffset, sel.focusNode, sel.focusOffset) == 1;
    +        }
    +
    +        return backward;
    +      } // Test for the Range/TextRange and Selection features required
    +      // Test for ability to retrieve selection
    +
    +
    +      var implementsWinGetSelection = isHostMethod(window, "getSelection"),
    +          implementsDocSelection = util.isHostObject(document, "selection");
    +      features.implementsWinGetSelection = implementsWinGetSelection;
    +      features.implementsDocSelection = implementsDocSelection;
    +      var useDocumentSelection = implementsDocSelection && (!implementsWinGetSelection || api.config.preferTextRange);
    +
    +      if (useDocumentSelection) {
    +        getNativeSelection = getDocSelection;
    +
    +        api.isSelectionValid = function (winParam) {
    +          var doc = getWindow(winParam, "isSelectionValid").document,
    +              nativeSel = doc.selection; // Check whether the selection TextRange is actually contained within the correct document
    +
    +          return nativeSel.type != "None" || getDocument(nativeSel.createRange().parentElement()) == doc;
    +        };
    +      } else if (implementsWinGetSelection) {
    +        getNativeSelection = getWinSelection;
    +
    +        api.isSelectionValid = function () {
    +          return true;
    +        };
    +      } else {
    +        module.fail("Neither document.selection or window.getSelection() detected.");
    +        return false;
    +      }
    +
    +      api.getNativeSelection = getNativeSelection;
    +      var testSelection = getNativeSelection(); // In Firefox, the selection is null in an iframe with display: none. See issue #138.
    +
    +      if (!testSelection) {
    +        module.fail("Native selection was null (possibly issue 138?)");
    +        return false;
    +      }
    +
    +      var testRange = api.createNativeRange(document);
    +      var body = getBody(document); // Obtaining a range from a selection
    +
    +      var selectionHasAnchorAndFocus = util.areHostProperties(testSelection, ["anchorNode", "focusNode", "anchorOffset", "focusOffset"]);
    +      features.selectionHasAnchorAndFocus = selectionHasAnchorAndFocus; // Test for existence of native selection extend() method
    +
    +      var selectionHasExtend = isHostMethod(testSelection, "extend");
    +      features.selectionHasExtend = selectionHasExtend; // Test if rangeCount exists
    +
    +      var selectionHasRangeCount = typeof testSelection.rangeCount == NUMBER;
    +      features.selectionHasRangeCount = selectionHasRangeCount;
    +      var selectionSupportsMultipleRanges = false;
    +      var collapsedNonEditableSelectionsSupported = true;
    +      var addRangeBackwardToNative = selectionHasExtend ? function (nativeSelection, range) {
    +        var doc = DomRange.getRangeDocument(range);
    +        var endRange = api.createRange(doc);
    +        endRange.collapseToPoint(range.endContainer, range.endOffset);
    +        nativeSelection.addRange(getNativeRange(endRange));
    +        nativeSelection.extend(range.startContainer, range.startOffset);
    +      } : null;
    +
    +      if (util.areHostMethods(testSelection, ["addRange", "getRangeAt", "removeAllRanges"]) && typeof testSelection.rangeCount == NUMBER && features.implementsDomRange) {
    +        (function () {
    +          // Previously an iframe was used but this caused problems in some circumstances in IE, so tests are
    +          // performed on the current document's selection. See issue 109.
    +          // Note also that if a selection previously existed, it is wiped and later restored by these tests. This
    +          // will result in the selection direction begin reversed if the original selection was backwards and the
    +          // browser does not support setting backwards selections (Internet Explorer, I'm looking at you).
    +          var sel = window.getSelection();
    +
    +          if (sel) {
    +            // Store the current selection
    +            var originalSelectionRangeCount = sel.rangeCount;
    +            var selectionHasMultipleRanges = originalSelectionRangeCount > 1;
    +            var originalSelectionRanges = [];
    +            var originalSelectionBackward = winSelectionIsBackward(sel);
    +
    +            for (var i = 0; i < originalSelectionRangeCount; ++i) {
    +              originalSelectionRanges[i] = sel.getRangeAt(i);
    +            } // Create some test elements
    +
    +
    +            var testEl = dom.createTestElement(document, "", false);
    +            var textNode = testEl.appendChild(document.createTextNode("\u00a0\u00a0\u00a0")); // Test whether the native selection will allow a collapsed selection within a non-editable element
    +
    +            var r1 = document.createRange();
    +            r1.setStart(textNode, 1);
    +            r1.collapse(true);
    +            sel.removeAllRanges();
    +            sel.addRange(r1);
    +            collapsedNonEditableSelectionsSupported = sel.rangeCount == 1;
    +            sel.removeAllRanges(); // Test whether the native selection is capable of supporting multiple ranges.
    +
    +            if (!selectionHasMultipleRanges) {
    +              // Doing the original feature test here in Chrome 36 (and presumably later versions) prints a
    +              // console error of "Discontiguous selection is not supported." that cannot be suppressed. There's
    +              // nothing we can do about this while retaining the feature test so we have to resort to a browser
    +              // sniff. I'm not happy about it. See
    +              // https://code.google.com/p/chromium/issues/detail?id=399791
    +              var chromeMatch = window.navigator.appVersion.match(/Chrome\/(.*?) /);
    +
    +              if (chromeMatch && parseInt(chromeMatch[1]) >= 36) {
    +                selectionSupportsMultipleRanges = false;
    +              } else {
    +                var r2 = r1.cloneRange();
    +                r1.setStart(textNode, 0);
    +                r2.setEnd(textNode, 3);
    +                r2.setStart(textNode, 2);
    +                sel.addRange(r1);
    +                sel.addRange(r2);
    +                selectionSupportsMultipleRanges = sel.rangeCount == 2;
    +              }
    +            } // Clean up
    +
    +
    +            dom.removeNode(testEl);
    +            sel.removeAllRanges();
    +
    +            for (i = 0; i < originalSelectionRangeCount; ++i) {
    +              if (i == 0 && originalSelectionBackward) {
    +                if (addRangeBackwardToNative) {
    +                  addRangeBackwardToNative(sel, originalSelectionRanges[i]);
    +                } else {
    +                  api.warn("Rangy initialization: original selection was backwards but selection has been restored forwards because the browser does not support Selection.extend");
    +                  sel.addRange(originalSelectionRanges[i]);
    +                }
    +              } else {
    +                sel.addRange(originalSelectionRanges[i]);
    +              }
    +            }
    +          }
    +        })();
    +      }
    +
    +      features.selectionSupportsMultipleRanges = selectionSupportsMultipleRanges;
    +      features.collapsedNonEditableSelectionsSupported = collapsedNonEditableSelectionsSupported; // ControlRanges
    +
    +      var implementsControlRange = false,
    +          testControlRange;
    +
    +      if (body && isHostMethod(body, "createControlRange")) {
    +        testControlRange = body.createControlRange();
    +
    +        if (util.areHostProperties(testControlRange, ["item", "add"])) {
    +          implementsControlRange = true;
    +        }
    +      }
    +
    +      features.implementsControlRange = implementsControlRange; // Selection collapsedness
    +
    +      if (selectionHasAnchorAndFocus) {
    +        selectionIsCollapsed = function (sel) {
    +          return sel.anchorNode === sel.focusNode && sel.anchorOffset === sel.focusOffset;
    +        };
    +      } else {
    +        selectionIsCollapsed = function (sel) {
    +          return sel.rangeCount ? sel.getRangeAt(sel.rangeCount - 1).collapsed : false;
    +        };
    +      }
    +
    +      function updateAnchorAndFocusFromRange(sel, range, backward) {
    +        var anchorPrefix = backward ? "end" : "start",
    +            focusPrefix = backward ? "start" : "end";
    +        sel.anchorNode = range[anchorPrefix + "Container"];
    +        sel.anchorOffset = range[anchorPrefix + "Offset"];
    +        sel.focusNode = range[focusPrefix + "Container"];
    +        sel.focusOffset = range[focusPrefix + "Offset"];
    +      }
    +
    +      function updateAnchorAndFocusFromNativeSelection(sel) {
    +        var nativeSel = sel.nativeSelection;
    +        sel.anchorNode = nativeSel.anchorNode;
    +        sel.anchorOffset = nativeSel.anchorOffset;
    +        sel.focusNode = nativeSel.focusNode;
    +        sel.focusOffset = nativeSel.focusOffset;
    +      }
    +
    +      function updateEmptySelection(sel) {
    +        sel.anchorNode = sel.focusNode = null;
    +        sel.anchorOffset = sel.focusOffset = 0;
    +        sel.rangeCount = 0;
    +        sel.isCollapsed = true;
    +        sel._ranges.length = 0;
    +      }
    +
    +      function getNativeRange(range) {
    +        var nativeRange;
    +
    +        if (range instanceof DomRange) {
    +          nativeRange = api.createNativeRange(range.getDocument());
    +          nativeRange.setEnd(range.endContainer, range.endOffset);
    +          nativeRange.setStart(range.startContainer, range.startOffset);
    +        } else if (range instanceof WrappedRange) {
    +          nativeRange = range.nativeRange;
    +        } else if (features.implementsDomRange && range instanceof dom.getWindow(range.startContainer).Range) {
    +          nativeRange = range;
    +        }
    +
    +        return nativeRange;
    +      }
    +
    +      function rangeContainsSingleElement(rangeNodes) {
    +        if (!rangeNodes.length || rangeNodes[0].nodeType != 1) {
    +          return false;
    +        }
    +
    +        for (var i = 1, len = rangeNodes.length; i < len; ++i) {
    +          if (!dom.isAncestorOf(rangeNodes[0], rangeNodes[i])) {
    +            return false;
    +          }
    +        }
    +
    +        return true;
    +      }
    +
    +      function getSingleElementFromRange(range) {
    +        var nodes = range.getNodes();
    +
    +        if (!rangeContainsSingleElement(nodes)) {
    +          throw module.createError("getSingleElementFromRange: range " + range.inspect() + " did not consist of a single element");
    +        }
    +
    +        return nodes[0];
    +      } // Simple, quick test which only needs to distinguish between a TextRange and a ControlRange
    +
    +
    +      function isTextRange(range) {
    +        return !!range && typeof range.text != "undefined";
    +      }
    +
    +      function updateFromTextRange(sel, range) {
    +        // Create a Range from the selected TextRange
    +        var wrappedRange = new WrappedRange(range);
    +        sel._ranges = [wrappedRange];
    +        updateAnchorAndFocusFromRange(sel, wrappedRange, false);
    +        sel.rangeCount = 1;
    +        sel.isCollapsed = wrappedRange.collapsed;
    +      }
    +
    +      function updateControlSelection(sel) {
    +        // Update the wrapped selection based on what's now in the native selection
    +        sel._ranges.length = 0;
    +
    +        if (sel.docSelection.type == "None") {
    +          updateEmptySelection(sel);
    +        } else {
    +          var controlRange = sel.docSelection.createRange();
    +
    +          if (isTextRange(controlRange)) {
    +            // This case (where the selection type is "Control" and calling createRange() on the selection returns
    +            // a TextRange) can happen in IE 9. It happens, for example, when all elements in the selected
    +            // ControlRange have been removed from the ControlRange and removed from the document.
    +            updateFromTextRange(sel, controlRange);
    +          } else {
    +            sel.rangeCount = controlRange.length;
    +            var range,
    +                doc = getDocument(controlRange.item(0));
    +
    +            for (var i = 0; i < sel.rangeCount; ++i) {
    +              range = api.createRange(doc);
    +              range.selectNode(controlRange.item(i));
    +
    +              sel._ranges.push(range);
    +            }
    +
    +            sel.isCollapsed = sel.rangeCount == 1 && sel._ranges[0].collapsed;
    +            updateAnchorAndFocusFromRange(sel, sel._ranges[sel.rangeCount - 1], false);
    +          }
    +        }
    +      }
    +
    +      function addRangeToControlSelection(sel, range) {
    +        var controlRange = sel.docSelection.createRange();
    +        var rangeElement = getSingleElementFromRange(range); // Create a new ControlRange containing all the elements in the selected ControlRange plus the element
    +        // contained by the supplied range
    +
    +        var doc = getDocument(controlRange.item(0));
    +        var newControlRange = getBody(doc).createControlRange();
    +
    +        for (var i = 0, len = controlRange.length; i < len; ++i) {
    +          newControlRange.add(controlRange.item(i));
    +        }
    +
    +        try {
    +          newControlRange.add(rangeElement);
    +        } catch (ex) {
    +          throw module.createError("addRange(): Element within the specified Range could not be added to control selection (does it have layout?)");
    +        }
    +
    +        newControlRange.select(); // Update the wrapped selection based on what's now in the native selection
    +
    +        updateControlSelection(sel);
    +      }
    +
    +      var getSelectionRangeAt;
    +
    +      if (isHostMethod(testSelection, "getRangeAt")) {
    +        // try/catch is present because getRangeAt() must have thrown an error in some browser and some situation.
    +        // Unfortunately, I didn't write a comment about the specifics and am now scared to take it out. Let that be a
    +        // lesson to us all, especially me.
    +        getSelectionRangeAt = function (sel, index) {
    +          try {
    +            return sel.getRangeAt(index);
    +          } catch (ex) {
    +            return null;
    +          }
    +        };
    +      } else if (selectionHasAnchorAndFocus) {
    +        getSelectionRangeAt = function (sel) {
    +          var doc = getDocument(sel.anchorNode);
    +          var range = api.createRange(doc);
    +          range.setStartAndEnd(sel.anchorNode, sel.anchorOffset, sel.focusNode, sel.focusOffset); // Handle the case when the selection was selected backwards (from the end to the start in the
    +          // document)
    +
    +          if (range.collapsed !== this.isCollapsed) {
    +            range.setStartAndEnd(sel.focusNode, sel.focusOffset, sel.anchorNode, sel.anchorOffset);
    +          }
    +
    +          return range;
    +        };
    +      }
    +
    +      function WrappedSelection(selection, docSelection, win) {
    +        this.nativeSelection = selection;
    +        this.docSelection = docSelection;
    +        this._ranges = [];
    +        this.win = win;
    +        this.refresh();
    +      }
    +
    +      WrappedSelection.prototype = api.selectionPrototype;
    +
    +      function deleteProperties(sel) {
    +        sel.win = sel.anchorNode = sel.focusNode = sel._ranges = null;
    +        sel.rangeCount = sel.anchorOffset = sel.focusOffset = 0;
    +        sel.detached = true;
    +      }
    +
    +      var cachedRangySelections = [];
    +
    +      function actOnCachedSelection(win, action) {
    +        var i = cachedRangySelections.length,
    +            cached,
    +            sel;
    +
    +        while (i--) {
    +          cached = cachedRangySelections[i];
    +          sel = cached.selection;
    +
    +          if (action == "deleteAll") {
    +            deleteProperties(sel);
    +          } else if (cached.win == win) {
    +            if (action == "delete") {
    +              cachedRangySelections.splice(i, 1);
    +              return true;
    +            } else {
    +              return sel;
    +            }
    +          }
    +        }
    +
    +        if (action == "deleteAll") {
    +          cachedRangySelections.length = 0;
    +        }
    +
    +        return null;
    +      }
    +
    +      var getSelection = function (win) {
    +        // Check if the parameter is a Rangy Selection object
    +        if (win && win instanceof WrappedSelection) {
    +          win.refresh();
    +          return win;
    +        }
    +
    +        win = getWindow(win, "getNativeSelection");
    +        var sel = actOnCachedSelection(win);
    +        var nativeSel = getNativeSelection(win),
    +            docSel = implementsDocSelection ? getDocSelection(win) : null;
    +
    +        if (sel) {
    +          sel.nativeSelection = nativeSel;
    +          sel.docSelection = docSel;
    +          sel.refresh();
    +        } else {
    +          sel = new WrappedSelection(nativeSel, docSel, win);
    +          cachedRangySelections.push({
    +            win: win,
    +            selection: sel
    +          });
    +        }
    +
    +        return sel;
    +      };
    +
    +      api.getSelection = getSelection;
    +      util.createAliasForDeprecatedMethod(api, "getIframeSelection", "getSelection");
    +      var selProto = WrappedSelection.prototype;
    +
    +      function createControlSelection(sel, ranges) {
    +        // Ensure that the selection becomes of type "Control"
    +        var doc = getDocument(ranges[0].startContainer);
    +        var controlRange = getBody(doc).createControlRange();
    +
    +        for (var i = 0, el, len = ranges.length; i < len; ++i) {
    +          el = getSingleElementFromRange(ranges[i]);
    +
    +          try {
    +            controlRange.add(el);
    +          } catch (ex) {
    +            throw module.createError("setRanges(): Element within one of the specified Ranges could not be added to control selection (does it have layout?)");
    +          }
    +        }
    +
    +        controlRange.select(); // Update the wrapped selection based on what's now in the native selection
    +
    +        updateControlSelection(sel);
    +      } // Selecting a range
    +
    +
    +      if (!useDocumentSelection && selectionHasAnchorAndFocus && util.areHostMethods(testSelection, ["removeAllRanges", "addRange"])) {
    +        selProto.removeAllRanges = function () {
    +          this.nativeSelection.removeAllRanges();
    +          updateEmptySelection(this);
    +        };
    +
    +        var addRangeBackward = function (sel, range) {
    +          addRangeBackwardToNative(sel.nativeSelection, range);
    +          sel.refresh();
    +        };
    +
    +        if (selectionHasRangeCount) {
    +          selProto.addRange = function (range, direction) {
    +            if (implementsControlRange && implementsDocSelection && this.docSelection.type == CONTROL) {
    +              addRangeToControlSelection(this, range);
    +            } else {
    +              if (isDirectionBackward(direction) && selectionHasExtend) {
    +                addRangeBackward(this, range);
    +              } else {
    +                var previousRangeCount;
    +
    +                if (selectionSupportsMultipleRanges) {
    +                  previousRangeCount = this.rangeCount;
    +                } else {
    +                  this.removeAllRanges();
    +                  previousRangeCount = 0;
    +                } // Clone the native range so that changing the selected range does not affect the selection.
    +                // This is contrary to the spec but is the only way to achieve consistency between browsers. See
    +                // issue 80.
    +
    +
    +                var clonedNativeRange = getNativeRange(range).cloneRange();
    +
    +                try {
    +                  this.nativeSelection.addRange(clonedNativeRange);
    +                } catch (ex) {} // Check whether adding the range was successful
    +
    +
    +                this.rangeCount = this.nativeSelection.rangeCount;
    +
    +                if (this.rangeCount == previousRangeCount + 1) {
    +                  // The range was added successfully
    +                  // Check whether the range that we added to the selection is reflected in the last range extracted from
    +                  // the selection
    +                  if (api.config.checkSelectionRanges) {
    +                    var nativeRange = getSelectionRangeAt(this.nativeSelection, this.rangeCount - 1);
    +
    +                    if (nativeRange && !rangesEqual(nativeRange, range)) {
    +                      // Happens in WebKit with, for example, a selection placed at the start of a text node
    +                      range = new WrappedRange(nativeRange);
    +                    }
    +                  }
    +
    +                  this._ranges[this.rangeCount - 1] = range;
    +                  updateAnchorAndFocusFromRange(this, range, selectionIsBackward(this.nativeSelection));
    +                  this.isCollapsed = selectionIsCollapsed(this);
    +                } else {
    +                  // The range was not added successfully. The simplest thing is to refresh
    +                  this.refresh();
    +                }
    +              }
    +            }
    +          };
    +        } else {
    +          selProto.addRange = function (range, direction) {
    +            if (isDirectionBackward(direction) && selectionHasExtend) {
    +              addRangeBackward(this, range);
    +            } else {
    +              this.nativeSelection.addRange(getNativeRange(range));
    +              this.refresh();
    +            }
    +          };
    +        }
    +
    +        selProto.setRanges = function (ranges) {
    +          if (implementsControlRange && implementsDocSelection && ranges.length > 1) {
    +            createControlSelection(this, ranges);
    +          } else {
    +            this.removeAllRanges();
    +
    +            for (var i = 0, len = ranges.length; i < len; ++i) {
    +              this.addRange(ranges[i]);
    +            }
    +          }
    +        };
    +      } else if (isHostMethod(testSelection, "empty") && isHostMethod(testRange, "select") && implementsControlRange && useDocumentSelection) {
    +        selProto.removeAllRanges = function () {
    +          // Added try/catch as fix for issue #21
    +          try {
    +            this.docSelection.empty(); // Check for empty() not working (issue #24)
    +
    +            if (this.docSelection.type != "None") {
    +              // Work around failure to empty a control selection by instead selecting a TextRange and then
    +              // calling empty()
    +              var doc;
    +
    +              if (this.anchorNode) {
    +                doc = getDocument(this.anchorNode);
    +              } else if (this.docSelection.type == CONTROL) {
    +                var controlRange = this.docSelection.createRange();
    +
    +                if (controlRange.length) {
    +                  doc = getDocument(controlRange.item(0));
    +                }
    +              }
    +
    +              if (doc) {
    +                var textRange = getBody(doc).createTextRange();
    +                textRange.select();
    +                this.docSelection.empty();
    +              }
    +            }
    +          } catch (ex) {}
    +
    +          updateEmptySelection(this);
    +        };
    +
    +        selProto.addRange = function (range) {
    +          if (this.docSelection.type == CONTROL) {
    +            addRangeToControlSelection(this, range);
    +          } else {
    +            api.WrappedTextRange.rangeToTextRange(range).select();
    +            this._ranges[0] = range;
    +            this.rangeCount = 1;
    +            this.isCollapsed = this._ranges[0].collapsed;
    +            updateAnchorAndFocusFromRange(this, range, false);
    +          }
    +        };
    +
    +        selProto.setRanges = function (ranges) {
    +          this.removeAllRanges();
    +          var rangeCount = ranges.length;
    +
    +          if (rangeCount > 1) {
    +            createControlSelection(this, ranges);
    +          } else if (rangeCount) {
    +            this.addRange(ranges[0]);
    +          }
    +        };
    +      } else {
    +        module.fail("No means of selecting a Range or TextRange was found");
    +        return false;
    +      }
    +
    +      selProto.getRangeAt = function (index) {
    +        if (index < 0 || index >= this.rangeCount) {
    +          throw new DOMException("INDEX_SIZE_ERR");
    +        } else {
    +          // Clone the range to preserve selection-range independence. See issue 80.
    +          return this._ranges[index].cloneRange();
    +        }
    +      };
    +
    +      var refreshSelection;
    +
    +      if (useDocumentSelection) {
    +        refreshSelection = function (sel) {
    +          var range;
    +
    +          if (api.isSelectionValid(sel.win)) {
    +            range = sel.docSelection.createRange();
    +          } else {
    +            range = getBody(sel.win.document).createTextRange();
    +            range.collapse(true);
    +          }
    +
    +          if (sel.docSelection.type == CONTROL) {
    +            updateControlSelection(sel);
    +          } else if (isTextRange(range)) {
    +            updateFromTextRange(sel, range);
    +          } else {
    +            updateEmptySelection(sel);
    +          }
    +        };
    +      } else if (isHostMethod(testSelection, "getRangeAt") && typeof testSelection.rangeCount == NUMBER) {
    +        refreshSelection = function (sel) {
    +          if (implementsControlRange && implementsDocSelection && sel.docSelection.type == CONTROL) {
    +            updateControlSelection(sel);
    +          } else {
    +            sel._ranges.length = sel.rangeCount = sel.nativeSelection.rangeCount;
    +
    +            if (sel.rangeCount) {
    +              for (var i = 0, len = sel.rangeCount; i < len; ++i) {
    +                sel._ranges[i] = new api.WrappedRange(sel.nativeSelection.getRangeAt(i));
    +              }
    +
    +              updateAnchorAndFocusFromRange(sel, sel._ranges[sel.rangeCount - 1], selectionIsBackward(sel.nativeSelection));
    +              sel.isCollapsed = selectionIsCollapsed(sel);
    +            } else {
    +              updateEmptySelection(sel);
    +            }
    +          }
    +        };
    +      } else if (selectionHasAnchorAndFocus && typeof testSelection.isCollapsed == BOOLEAN && typeof testRange.collapsed == BOOLEAN && features.implementsDomRange) {
    +        refreshSelection = function (sel) {
    +          var range,
    +              nativeSel = sel.nativeSelection;
    +
    +          if (nativeSel.anchorNode) {
    +            range = getSelectionRangeAt(nativeSel, 0);
    +            sel._ranges = [range];
    +            sel.rangeCount = 1;
    +            updateAnchorAndFocusFromNativeSelection(sel);
    +            sel.isCollapsed = selectionIsCollapsed(sel);
    +          } else {
    +            updateEmptySelection(sel);
    +          }
    +        };
    +      } else {
    +        module.fail("No means of obtaining a Range or TextRange from the user's selection was found");
    +        return false;
    +      }
    +
    +      selProto.refresh = function (checkForChanges) {
    +        var oldRanges = checkForChanges ? this._ranges.slice(0) : null;
    +        var oldAnchorNode = this.anchorNode,
    +            oldAnchorOffset = this.anchorOffset;
    +        refreshSelection(this);
    +
    +        if (checkForChanges) {
    +          // Check the range count first
    +          var i = oldRanges.length;
    +
    +          if (i != this._ranges.length) {
    +            return true;
    +          } // Now check the direction. Checking the anchor position is the same is enough since we're checking all the
    +          // ranges after this
    +
    +
    +          if (this.anchorNode != oldAnchorNode || this.anchorOffset != oldAnchorOffset) {
    +            return true;
    +          } // Finally, compare each range in turn
    +
    +
    +          while (i--) {
    +            if (!rangesEqual(oldRanges[i], this._ranges[i])) {
    +              return true;
    +            }
    +          }
    +
    +          return false;
    +        }
    +      }; // Removal of a single range
    +
    +
    +      var removeRangeManually = function (sel, range) {
    +        var ranges = sel.getAllRanges();
    +        sel.removeAllRanges();
    +
    +        for (var i = 0, len = ranges.length; i < len; ++i) {
    +          if (!rangesEqual(range, ranges[i])) {
    +            sel.addRange(ranges[i]);
    +          }
    +        }
    +
    +        if (!sel.rangeCount) {
    +          updateEmptySelection(sel);
    +        }
    +      };
    +
    +      if (implementsControlRange && implementsDocSelection) {
    +        selProto.removeRange = function (range) {
    +          if (this.docSelection.type == CONTROL) {
    +            var controlRange = this.docSelection.createRange();
    +            var rangeElement = getSingleElementFromRange(range); // Create a new ControlRange containing all the elements in the selected ControlRange minus the
    +            // element contained by the supplied range
    +
    +            var doc = getDocument(controlRange.item(0));
    +            var newControlRange = getBody(doc).createControlRange();
    +            var el,
    +                removed = false;
    +
    +            for (var i = 0, len = controlRange.length; i < len; ++i) {
    +              el = controlRange.item(i);
    +
    +              if (el !== rangeElement || removed) {
    +                newControlRange.add(controlRange.item(i));
    +              } else {
    +                removed = true;
    +              }
    +            }
    +
    +            newControlRange.select(); // Update the wrapped selection based on what's now in the native selection
    +
    +            updateControlSelection(this);
    +          } else {
    +            removeRangeManually(this, range);
    +          }
    +        };
    +      } else {
    +        selProto.removeRange = function (range) {
    +          removeRangeManually(this, range);
    +        };
    +      } // Detecting if a selection is backward
    +
    +
    +      var selectionIsBackward;
    +
    +      if (!useDocumentSelection && selectionHasAnchorAndFocus && features.implementsDomRange) {
    +        selectionIsBackward = winSelectionIsBackward;
    +
    +        selProto.isBackward = function () {
    +          return selectionIsBackward(this);
    +        };
    +      } else {
    +        selectionIsBackward = selProto.isBackward = function () {
    +          return false;
    +        };
    +      } // Create an alias for backwards compatibility. From 1.3, everything is "backward" rather than "backwards"
    +
    +
    +      selProto.isBackwards = selProto.isBackward; // Selection stringifier
    +      // This is conformant to the old HTML5 selections draft spec but differs from WebKit and Mozilla's implementation.
    +      // The current spec does not yet define this method.
    +
    +      selProto.toString = function () {
    +        var rangeTexts = [];
    +
    +        for (var i = 0, len = this.rangeCount; i < len; ++i) {
    +          rangeTexts[i] = "" + this._ranges[i];
    +        }
    +
    +        return rangeTexts.join("");
    +      };
    +
    +      function assertNodeInSameDocument(sel, node) {
    +        if (sel.win.document != getDocument(node)) {
    +          throw new DOMException("WRONG_DOCUMENT_ERR");
    +        }
    +      } // No current browser conforms fully to the spec for this method, so Rangy's own method is always used
    +
    +
    +      selProto.collapse = function (node, offset) {
    +        assertNodeInSameDocument(this, node);
    +        var range = api.createRange(node);
    +        range.collapseToPoint(node, offset);
    +        this.setSingleRange(range);
    +        this.isCollapsed = true;
    +      };
    +
    +      selProto.collapseToStart = function () {
    +        if (this.rangeCount) {
    +          var range = this._ranges[0];
    +          this.collapse(range.startContainer, range.startOffset);
    +        } else {
    +          throw new DOMException("INVALID_STATE_ERR");
    +        }
    +      };
    +
    +      selProto.collapseToEnd = function () {
    +        if (this.rangeCount) {
    +          var range = this._ranges[this.rangeCount - 1];
    +          this.collapse(range.endContainer, range.endOffset);
    +        } else {
    +          throw new DOMException("INVALID_STATE_ERR");
    +        }
    +      }; // The spec is very specific on how selectAllChildren should be implemented and not all browsers implement it as
    +      // specified so the native implementation is never used by Rangy.
    +
    +
    +      selProto.selectAllChildren = function (node) {
    +        assertNodeInSameDocument(this, node);
    +        var range = api.createRange(node);
    +        range.selectNodeContents(node);
    +        this.setSingleRange(range);
    +      };
    +
    +      selProto.deleteFromDocument = function () {
    +        // Sepcial behaviour required for IE's control selections
    +        if (implementsControlRange && implementsDocSelection && this.docSelection.type == CONTROL) {
    +          var controlRange = this.docSelection.createRange();
    +          var element;
    +
    +          while (controlRange.length) {
    +            element = controlRange.item(0);
    +            controlRange.remove(element);
    +            dom.removeNode(element);
    +          }
    +
    +          this.refresh();
    +        } else if (this.rangeCount) {
    +          var ranges = this.getAllRanges();
    +
    +          if (ranges.length) {
    +            this.removeAllRanges();
    +
    +            for (var i = 0, len = ranges.length; i < len; ++i) {
    +              ranges[i].deleteContents();
    +            } // The spec says nothing about what the selection should contain after calling deleteContents on each
    +            // range. Firefox moves the selection to where the final selected range was, so we emulate that
    +
    +
    +            this.addRange(ranges[len - 1]);
    +          }
    +        }
    +      }; // The following are non-standard extensions
    +
    +
    +      selProto.eachRange = function (func, returnValue) {
    +        for (var i = 0, len = this._ranges.length; i < len; ++i) {
    +          if (func(this.getRangeAt(i))) {
    +            return returnValue;
    +          }
    +        }
    +      };
    +
    +      selProto.getAllRanges = function () {
    +        var ranges = [];
    +        this.eachRange(function (range) {
    +          ranges.push(range);
    +        });
    +        return ranges;
    +      };
    +
    +      selProto.setSingleRange = function (range, direction) {
    +        this.removeAllRanges();
    +        this.addRange(range, direction);
    +      };
    +
    +      selProto.callMethodOnEachRange = function (methodName, params) {
    +        var results = [];
    +        this.eachRange(function (range) {
    +          results.push(range[methodName].apply(range, params || []));
    +        });
    +        return results;
    +      };
    +
    +      function createStartOrEndSetter(isStart) {
    +        return function (node, offset) {
    +          var range;
    +
    +          if (this.rangeCount) {
    +            range = this.getRangeAt(0);
    +            range["set" + (isStart ? "Start" : "End")](node, offset);
    +          } else {
    +            range = api.createRange(this.win.document);
    +            range.setStartAndEnd(node, offset);
    +          }
    +
    +          this.setSingleRange(range, this.isBackward());
    +        };
    +      }
    +
    +      selProto.setStart = createStartOrEndSetter(true);
    +      selProto.setEnd = createStartOrEndSetter(false); // Add select() method to Range prototype. Any existing selection will be removed.
    +
    +      api.rangePrototype.select = function (direction) {
    +        getSelection(this.getDocument()).setSingleRange(this, direction);
    +      };
    +
    +      selProto.changeEachRange = function (func) {
    +        var ranges = [];
    +        var backward = this.isBackward();
    +        this.eachRange(function (range) {
    +          func(range);
    +          ranges.push(range);
    +        });
    +        this.removeAllRanges();
    +
    +        if (backward && ranges.length == 1) {
    +          this.addRange(ranges[0], "backward");
    +        } else {
    +          this.setRanges(ranges);
    +        }
    +      };
    +
    +      selProto.containsNode = function (node, allowPartial) {
    +        return this.eachRange(function (range) {
    +          return range.containsNode(node, allowPartial);
    +        }, true) || false;
    +      };
    +
    +      selProto.getBookmark = function (containerNode) {
    +        return {
    +          backward: this.isBackward(),
    +          rangeBookmarks: this.callMethodOnEachRange("getBookmark", [containerNode])
    +        };
    +      };
    +
    +      selProto.moveToBookmark = function (bookmark) {
    +        var selRanges = [];
    +
    +        for (var i = 0, rangeBookmark, range; rangeBookmark = bookmark.rangeBookmarks[i++];) {
    +          range = api.createRange(this.win);
    +          range.moveToBookmark(rangeBookmark);
    +          selRanges.push(range);
    +        }
    +
    +        if (bookmark.backward) {
    +          this.setSingleRange(selRanges[0], "backward");
    +        } else {
    +          this.setRanges(selRanges);
    +        }
    +      };
    +
    +      selProto.saveRanges = function () {
    +        return {
    +          backward: this.isBackward(),
    +          ranges: this.callMethodOnEachRange("cloneRange")
    +        };
    +      };
    +
    +      selProto.restoreRanges = function (selRanges) {
    +        this.removeAllRanges();
    +
    +        for (var i = 0, range; range = selRanges.ranges[i]; ++i) {
    +          this.addRange(range, selRanges.backward && i == 0);
    +        }
    +      };
    +
    +      selProto.toHtml = function () {
    +        var rangeHtmls = [];
    +        this.eachRange(function (range) {
    +          rangeHtmls.push(DomRange.toHtml(range));
    +        });
    +        return rangeHtmls.join("");
    +      };
    +
    +      if (features.implementsTextRange) {
    +        selProto.getNativeTextRange = function () {
    +          var sel, textRange;
    +
    +          if (sel = this.docSelection) {
    +            var range = sel.createRange();
    +
    +            if (isTextRange(range)) {
    +              return range;
    +            } else {
    +              throw module.createError("getNativeTextRange: selection is a control selection");
    +            }
    +          } else if (this.rangeCount > 0) {
    +            return api.WrappedTextRange.rangeToTextRange(this.getRangeAt(0));
    +          } else {
    +            throw module.createError("getNativeTextRange: selection contains no range");
    +          }
    +        };
    +      }
    +
    +      function inspect(sel) {
    +        var rangeInspects = [];
    +        var anchor = new DomPosition(sel.anchorNode, sel.anchorOffset);
    +        var focus = new DomPosition(sel.focusNode, sel.focusOffset);
    +        var name = typeof sel.getName == "function" ? sel.getName() : "Selection";
    +
    +        if (typeof sel.rangeCount != "undefined") {
    +          for (var i = 0, len = sel.rangeCount; i < len; ++i) {
    +            rangeInspects[i] = DomRange.inspect(sel.getRangeAt(i));
    +          }
    +        }
    +
    +        return "[" + name + "(Ranges: " + rangeInspects.join(", ") + ")(anchor: " + anchor.inspect() + ", focus: " + focus.inspect() + "]";
    +      }
    +
    +      selProto.getName = function () {
    +        return "WrappedSelection";
    +      };
    +
    +      selProto.inspect = function () {
    +        return inspect(this);
    +      };
    +
    +      selProto.detach = function () {
    +        actOnCachedSelection(this.win, "delete");
    +        deleteProperties(this);
    +      };
    +
    +      WrappedSelection.detachAll = function () {
    +        actOnCachedSelection(null, "deleteAll");
    +      };
    +
    +      WrappedSelection.inspect = inspect;
    +      WrappedSelection.isDirectionBackward = isDirectionBackward;
    +      api.Selection = WrappedSelection;
    +      api.selectionPrototype = selProto;
    +      api.addShimListener(function (win) {
    +        if (typeof win.getSelection == "undefined") {
    +          win.getSelection = function () {
    +            return getSelection(win);
    +          };
    +        }
    +
    +        win = null;
    +      });
    +    });
    +    /*----------------------------------------------------------------------------------------------------------------*/
    +    // Wait for document to load before initializing
    +
    +    var docReady = false;
    +
    +    var loadHandler = function (e) {
    +      if (!docReady) {
    +        docReady = true;
    +
    +        if (!api.initialized && api.config.autoInitialize) {
    +          init();
    +        }
    +      }
    +    };
    +
    +    if (isBrowser) {
    +      // Test whether the document has already been loaded and initialize immediately if so
    +      if (document.readyState == "complete") {
    +        loadHandler();
    +      } else {
    +        if (isHostMethod(document, "addEventListener")) {
    +          document.addEventListener("DOMContentLoaded", loadHandler, false);
    +        } // Add a fallback in case the DOMContentLoaded event isn't supported
    +
    +
    +        addListener(window, "load", loadHandler);
    +      }
    +    }
    +
    +    return api;
    +  }, commonjsGlobal);
    +});
    +
    +var rangyTextrange = createCommonjsModule(function (module, exports) {
    +  /**
    +   * Text range module for Rangy.
    +   * Text-based manipulation and searching of ranges and selections.
    +   *
    +   * Features
    +   *
    +   * - Ability to move range boundaries by character or word offsets
    +   * - Customizable word tokenizer
    +   * - Ignores text nodes inside ";
    +    const expectedHTML = "
    a
    "; + assert.documentHTMLEqual(HTMLParser.parse(html).getDocument(), expectedHTML); + }); + test$3("ignores iframe elements", () => { + const html = "
    a
    "; + const expectedHTML = "
    a
    "; + assert.documentHTMLEqual(HTMLParser.parse(html).getDocument(), expectedHTML); + }); + test$3("sanitizes unsafe html", done => { + window.unsanitized = []; + HTMLParser.parse("\n \n \n ")); + after$1(20, () => { + assert.deepEqual(window.unsanitized, []); + delete window.unsanitized; + done(); + }); + }); + test$3("forbids href attributes with javascript: protocol", () => { + const html = "a b c"; + const expectedHTML = "
    a b c
    "; + assert.documentHTMLEqual(HTMLParser.parse(html).getDocument(), expectedHTML); + }); + test$3("ignores attachment elements with malformed JSON", () => { + const html = "
    a
    " + "
    " + "
    " + "
    b
    "; + const expectedHTML = "
    a

    b
    "; + assert.documentHTMLEqual(HTMLParser.parse(html).getDocument(), expectedHTML); + }); + test$3("parses attachment caption from large html string", done => { + let { + html + } = fixtures["image attachment with edited caption"]; + + for (let i = 1; i <= 30; i++) { + html += fixtures["image attachment"].html; + } + + for (let n = 1; n <= 3; n++) { + const attachmentPiece = HTMLParser.parse(html).getDocument().getAttachmentPieces()[0]; + assert.equal(attachmentPiece.getCaption(), "Example"); + } + + done(); + }); + test$3("parses foreground color when configured", () => { + const attrConfig = { + foregroundColor: { + styleProperty: "color" + } + }; + withTextAttributeConfig(attrConfig, () => { + const html = "green"; + const expectedHTML = "
    green
    "; + const document = HTMLParser.parse(html).getDocument(); + assert.documentHTMLEqual(document, expectedHTML); + }); + }); + test$3("parses background color when configured", () => { + const attrConfig = { + backgroundColor: { + styleProperty: "backgroundColor" + } + }; + withTextAttributeConfig(attrConfig, () => { + const html = "on yellow"; + const expectedHTML = "
    on yellow
    "; + const document = HTMLParser.parse(html).getDocument(); + assert.documentHTMLEqual(document, expectedHTML); + }); + }); + test$3("parses configured foreground color on formatted text", () => { + const attrConfig = { + foregroundColor: { + styleProperty: "color" + } + }; + withTextAttributeConfig(attrConfig, () => { + const html = "GREEN"; + const expectedHTML = "
    GREEN
    "; + const document = HTMLParser.parse(html).getDocument(); + assert.documentHTMLEqual(document, expectedHTML); + }); + }); + test$3("parses foreground color using configured parser function", () => { + const attrConfig = { + foregroundColor: { + styleProperty: "color", + + parser(element) { + const { + color + } = element.style; + + if (color === "rgb(60, 179, 113)") { + return color; + } + } + + } + }; + withTextAttributeConfig(attrConfig, () => { + const html = "greennot yellow"; + const expectedHTML = "
    greennot yellow
    "; + const document = HTMLParser.parse(html).getDocument(); + assert.documentHTMLEqual(document, expectedHTML); + }); + }); +}); + +const withTextAttributeConfig = function () { + let attrConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + let fn = arguments.length > 1 ? arguments[1] : undefined; + const originalConfig = {}; + + for (const [key, value] of Object.entries(attrConfig)) { + originalConfig[key] = config.textAttributes[key]; + config.textAttributes[key] = value; + } + + try { + fn(); + } finally { + for (const [key, value] of Object.entries(originalConfig)) { + if (value) { + config.textAttributes[key] = value; + } else { + delete config.textAttributes[key]; + } + } + } +}; + +const getOrigin = () => { + const { + protocol, + hostname, + port + } = window.location; + return "".concat(protocol, "//").concat(hostname).concat(port ? ":".concat(port) : ""); +}; + +testGroup("LocationMapper", () => { + test$3("findLocationFromContainerAndOffset", () => { + setDocument([// + // 0
    + // 0 + // 1 + // 0 a + // 1
    + //
    + // 2
    + //
    + // 1
    + // 0 + // 1 b😭cd + // 2 + // 0 (zero-width space) + // + // 3 + // 0
    ...
    + //
    + // 4 + // 0 (zero-width space) + // + // 5 e + //
    + //
    + { + text: [{ + type: "string", + attributes: { + bold: true + }, + string: "a\n" + }, { + type: "string", + attributes: { + blockBreak: true + }, + string: "\n" + }], + attributes: [] + }, { + text: [{ + type: "string", + attributes: {}, + string: "b😭cd" + }, { + type: "attachment", + attributes: {}, + attachment: { + contentType: "image/png", + filename: "x.png", + filesize: 0, + height: 13, + href: TEST_IMAGE_URL, + identifier: "1", + url: TEST_IMAGE_URL, + width: 15 + } + }, { + type: "string", + attributes: {}, + string: "e" + }, { + type: "string", + attributes: { + blockBreak: true + }, + string: "\n" + }], + attributes: ["quote"] + }]); + const assertions = [{ + location: [0, 0], + container: [], + offset: 0 + }, { + location: [0, 0], + container: [0], + offset: 0 + }, { + location: [0, 0], + container: [0], + offset: 1 + }, { + location: [0, 0], + container: [0, 1], + offset: 0 + }, { + location: [0, 0], + container: [0, 1, 0], + offset: 0 + }, { + location: [0, 1], + container: [0, 1, 0], + offset: 1 + }, { + location: [0, 1], + container: [0, 1], + offset: 1 + }, { + location: [0, 2], + container: [0, 1], + offset: 2 + }, { + location: [0, 2], + container: [0], + offset: 2 + }, { + location: [0, 3], + container: [], + offset: 1 + }, { + location: [0, 3], + container: [1], + offset: 0 + }, { + location: [1, 0], + container: [1], + offset: 1 + }, { + location: [1, 0], + container: [1, 1], + offset: 0 + }, { + location: [1, 1], + container: [1, 1], + offset: 1 + }, { + location: [1, 2], + container: [1, 1], + offset: 2 + }, { + location: [1, 3], + container: [1, 1], + offset: 3 + }, { + location: [1, 4], + container: [1, 1], + offset: 4 + }, { + location: [1, 5], + container: [1, 1], + offset: 5 + }, { + location: [1, 6], + container: [1, 1], + offset: 6 + }, { + location: [1, 5], + container: [1], + offset: 2 + }, { + location: [1, 5], + container: [1, 2], + offset: 0 + }, { + location: [1, 5], + container: [1, 2], + offset: 1 + }, { + location: [1, 5], + container: [1], + offset: 3 + }, { + location: [1, 5], + container: [1, 3], + offset: 0 + }, { + location: [1, 5], + container: [1, 3], + offset: 1 + }, { + location: [1, 6], + container: [1], + offset: 4 + }, { + location: [1, 6], + container: [1, 4], + offset: 0 + }, { + location: [1, 6], + container: [1, 4], + offset: 1 + }, { + location: [1, 6], + container: [1], + offset: 5 + }, { + location: [1, 6], + container: [1, 5], + offset: 0 + }, { + location: [1, 7], + container: [1, 5], + offset: 1 + }, { + location: [1, 7], + container: [], + offset: 2 + }]; + + for (const assertion of assertions) { + const path = assertion.container; + const container = findContainer(path); + const { + offset + } = assertion; + const expectedLocation = { + index: assertion.location[0], + offset: assertion.location[1] + }; + const actualLocation = mapper.findLocationFromContainerAndOffset(container, offset); + assert.equal(format(actualLocation), format(expectedLocation), "".concat(describe(container), " at [").concat(path.join(", "), "], offset ").concat(offset, " = ").concat(format(expectedLocation))); + } + }); + test$3("findContainerAndOffsetFromLocation: (0/0)", () => { + setDocument([// + // 0
      + // 0
    • + // 0 + // 1
      + //
    • + //
    + //
    + { + text: [{ + type: "string", + attributes: { + blockBreak: true + }, + string: "\n" + }], + attributes: ["bulletList", "bullet"] + }]); + const location = { + index: 0, + offset: 0 + }; + const container = findContainer([0, 0]); + const offset = 1; + assert.deepEqual(mapper.findContainerAndOffsetFromLocation(location), [container, offset]); + }); + test$3("findContainerAndOffsetFromLocation after newline in formatted text", () => { + setDocument([// + // 0
    + // 0 + // 0 + // 0 a + // 1
    + //
    + //
    + //
    + { + text: [{ + type: "string", + attributes: { + bold: true + }, + string: "a\n" + }, { + type: "string", + attributes: { + blockBreak: true + }, + string: "\n" + }], + attributes: [] + }]); + const location = { + index: 0, + offset: 2 + }; + const container = findContainer([0]); + const offset = 2; + assert.deepEqual(mapper.findContainerAndOffsetFromLocation(location), [container, offset]); + }); + test$3("findContainerAndOffsetFromLocation after nested block", () => { + setDocument([// + //
    + //
      + //
    • + // + // a + //
    • + //
    + // + //
    + //
    + //
    + { + text: [{ + type: "string", + attributes: {}, + string: "a" + }, { + type: "string", + attributes: { + blockBreak: true + }, + string: "\n" + }], + attributes: ["quote", "bulletList", "bullet"] + }, { + text: [{ + type: "string", + attributes: { + blockBreak: true + }, + string: "\n" + }], + attributes: ["quote"] + }]); + const location = { + index: 1, + offset: 0 + }; + const container = findContainer([0]); + const offset = 2; + assert.deepEqual(mapper.findContainerAndOffsetFromLocation(location), [container, offset]); + }); +}); // --- + +let document$1 = null; +let element$1 = null; +let mapper = null; + +const setDocument = json => { + document$1 = Document.fromJSON(json); + element$1 = DocumentView.render(document$1); + return mapper = new LocationMapper(element$1); +}; + +const findContainer = path => { + let el = element$1; + + for (const index of path) { + el = el.childNodes[index]; + } + + return el; +}; + +const format = _ref => { + let { + index, + offset + } = _ref; + return "".concat(index, "/").concat(offset); +}; + +const describe = node => { + if (node.nodeType === Node.TEXT_NODE) { + return "text node ".concat(JSON.stringify(node.textContent)); + } else { + return "container <".concat(node.tagName.toLowerCase(), ">"); + } +}; + +let observer = null; +let element = null; +let summaries = []; + +const install = function (html) { + element = document.createElement("div"); + + if (html) { + element.innerHTML = html; + } + + observer = new MutationObserver(element); + observer.delegate = { + elementDidMutate(summary) { + summaries.push(summary); + } + + }; +}; + +const uninstall = () => { + var _observer; + + (_observer = observer) === null || _observer === void 0 ? void 0 : _observer.stop(); + observer = null; + element = null; + summaries = []; +}; + +const observerTest = function (name) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let callback = arguments.length > 2 ? arguments[2] : undefined; + return test$3(name, done => { + install(options.html); + callback(() => { + uninstall(); + done(); + }); + }); +}; + +testGroup("MutationObserver", () => { + observerTest("add character", { + html: "a" + }, done => { + element.firstChild.data += "b"; + defer(() => { + assert.equal(summaries.length, 1); + assert.deepEqual(summaries[0], { + textAdded: "b" + }); + done(); + }); + }); + observerTest("remove character", { + html: "ab" + }, done => { + element.firstChild.data = "a"; + defer(() => { + assert.equal(summaries.length, 1); + assert.deepEqual(summaries[0], { + textDeleted: "b" + }); + done(); + }); + }); + observerTest("replace character", { + html: "ab" + }, done => { + element.firstChild.data = "ac"; + defer(() => { + assert.equal(summaries.length, 1); + assert.deepEqual(summaries[0], { + textAdded: "c", + textDeleted: "b" + }); + done(); + }); + }); + observerTest("add
    ", { + html: "a" + }, done => { + element.appendChild(document.createElement("br")); + defer(() => { + assert.equal(summaries.length, 1); + assert.deepEqual(summaries[0], { + textAdded: "\n" + }); + done(); + }); + }); + observerTest("remove
    ", { + html: "a
    " + }, done => { + element.removeChild(element.lastChild); + defer(() => { + assert.equal(summaries.length, 1); + assert.deepEqual(summaries[0], { + textDeleted: "\n" + }); + done(); + }); + }); + observerTest("remove block comment", { + html: "
    a
    " + }, done => { + element.firstChild.removeChild(element.firstChild.firstChild); + defer(() => { + assert.equal(summaries.length, 1); + assert.deepEqual(summaries[0], { + textDeleted: "\n" + }); + done(); + }); + }); + observerTest("remove formatted element", { + html: "ab" + }, done => { + element.removeChild(element.lastChild); + defer(() => { + assert.equal(summaries.length, 1); + assert.deepEqual(summaries[0], { + textDeleted: "b" + }); + done(); + }); + }); + observerTest("remove nested formatted elements", { + html: "abc" + }, done => { + element.removeChild(element.lastChild); + defer(() => { + assert.equal(summaries.length, 1); + assert.deepEqual(summaries[0], { + textDeleted: "bc" + }); + done(); + }); + }); +}); + +testGroup("serializeToContentType", () => { + eachFixture((name, details) => { + if (details.serializedHTML) { + test$3(name, () => { + assert.equal(serializeToContentType(details.document, "text/html"), details.serializedHTML); + }); + } + }); +}); + +testGroup("summarizeStringChange", () => { + const assertions = { + "no change": { + oldString: "abc", + newString: "abc", + change: { + added: "", + removed: "" + } + }, + "adding a character": { + oldString: "", + newString: "a", + change: { + added: "a", + removed: "" + } + }, + "appending a character": { + oldString: "ab", + newString: "abc", + change: { + added: "c", + removed: "" + } + }, + "appending a multibyte character": { + oldString: "a💩", + newString: "a💩💩", + change: { + added: "💩", + removed: "" + } + }, + "prepending a character": { + oldString: "bc", + newString: "abc", + change: { + added: "a", + removed: "" + } + }, + "inserting a character": { + oldString: "ac", + newString: "abc", + change: { + added: "b", + removed: "" + } + }, + "inserting a string": { + oldString: "ac", + newString: "aZZZc", + change: { + added: "ZZZ", + removed: "" + } + }, + "replacing a character": { + oldString: "abc", + newString: "aZc", + change: { + added: "Z", + removed: "b" + } + }, + "replacing a character with a string": { + oldString: "abc", + newString: "aXYc", + change: { + added: "XY", + removed: "b" + } + }, + "replacing a string with a character": { + oldString: "abcde", + newString: "aXe", + change: { + added: "X", + removed: "bcd" + } + }, + "replacing a string with a string": { + oldString: "abcde", + newString: "aBCDe", + change: { + added: "BCD", + removed: "bcd" + } + }, + "removing a character": { + oldString: "abc", + newString: "ac", + change: { + added: "", + removed: "b" + } + } + }; + + for (const name in assertions) { + test$3(name, () => { + const details = assertions[name]; + const { + oldString, + newString, + change + } = details; + assert.deepEqual(summarizeStringChange(oldString, newString), change); + }); + } +}); + +testGroup("Text", () => testGroup("#removeTextAtRange", () => { + test$3("removes text with range in single piece", () => { + const text = new Text([new StringPiece("abc")]); + const pieces = text.removeTextAtRange([0, 1]).getPieces(); + assert.equal(pieces.length, 1); + assert.equal(pieces[0].toString(), "bc"); + assert.deepEqual(pieces[0].getAttributes(), {}); + }); + test$3("removes text with range spanning pieces", () => { + const text = new Text([new StringPiece("abc"), new StringPiece("123", { + bold: true + })]); + const pieces = text.removeTextAtRange([2, 4]).getPieces(); + assert.equal(pieces.length, 2); + assert.equal(pieces[0].toString(), "ab"); + assert.deepEqual(pieces[0].getAttributes(), {}); + assert.equal(pieces[1].toString(), "23"); + assert.deepEqual(pieces[1].getAttributes(), { + bold: true + }); + }); +})); + +testGroup("Accessibility attributes", { + template: "editor_default_aria_label" +}, () => { + test$3("sets the role to textbox", () => { + const editor = document.getElementById("editor-without-labels"); + assert.equal(editor.getAttribute("role"), "textbox"); + }); + test$3("does not set aria-label when the element has no