0&&void 0!==arguments[0]?arguments[0]:k;if(!(this instanceof t))return new t(n);this.options={},x(this.options,k,n),this.options.cancelLegacy&&!R()||_(this)};return q.init=function(t){return console.warn(\"Depreciated: Macy.init will be removed in v3.0.0 opt to use Macy directly like so Macy({ /*options here*/ }) \"),new q(t)},q.prototype.recalculateOnImageLoad=function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return e(this,h(\"img\",this.container),!t)},q.prototype.runOnImageLoad=function(t){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=h(\"img\",this.container);return this.on(this.constants.EVENT_IMAGE_COMPLETE,t),n&&this.on(this.constants.EVENT_IMAGE_LOAD,t),e(this,r,n)},q.prototype.recalculate=function(){var t=this,n=arguments.length>0&&void 0!==arguments[0]&&arguments[0],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return e&&this.queue.clear(),this.queue.add(function(){return V(t,n,e)})},q.prototype.remove=function(){window.removeEventListener(\"resize\",this.resizer),v(this.container.children,function(t){t.removeAttribute(\"data-macy-complete\"),t.removeAttribute(\"style\")}),this.container.removeAttribute(\"style\")},q.prototype.reInit=function(){this.recalculate(!0,!0),this.emit(this.constants.EVENT_INITIALIZED),window.addEventListener(\"resize\",this.resizer),this.container.style.position=\"relative\"},q.prototype.on=function(t,n){this.events.on(t,n)},q.prototype.emit=function(t,n){this.events.emit(t,n)},q.constants={EVENT_INITIALIZED:\"macy.initialized\",EVENT_RECALCULATED:\"macy.recalculated\",EVENT_IMAGE_LOAD:\"macy.image.load\",EVENT_IMAGE_ERROR:\"macy.image.error\",EVENT_IMAGE_COMPLETE:\"macy.images.complete\",EVENT_RESIZE:\"macy.resize\"},q.prototype.constants=q.constants,q});\n", "/* eslint-disable */\n/*\nTrix 2.1.10\nCopyright \u00A9 2024 37signals, LLC\n */\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Trix = factory());\n})(this, (function () { 'use strict';\n\n var name = \"trix\";\n var version = \"2.1.10\";\n var description = \"A rich text editor for everyday writing\";\n var main = \"dist/trix.umd.min.js\";\n var module = \"dist/trix.esm.min.js\";\n var style = \"dist/trix.css\";\n var files = [\n \t\"dist/*.css\",\n \t\"dist/*.js\",\n \t\"dist/*.map\",\n \t\"src/{inspector,trix}/*.js\"\n ];\n var repository = {\n \ttype: \"git\",\n \turl: \"git+https://github.com/basecamp/trix.git\"\n };\n var keywords = [\n \t\"rich text\",\n \t\"wysiwyg\",\n \t\"editor\"\n ];\n var author = \"37signals, LLC\";\n var license = \"MIT\";\n var bugs = {\n \turl: \"https://github.com/basecamp/trix/issues\"\n };\n var homepage = \"https://trix-editor.org/\";\n var devDependencies = {\n \t\"@babel/core\": \"^7.16.0\",\n \t\"@babel/preset-env\": \"^7.16.4\",\n \t\"@rollup/plugin-babel\": \"^5.3.0\",\n \t\"@rollup/plugin-commonjs\": \"^22.0.2\",\n \t\"@rollup/plugin-json\": \"^4.1.0\",\n \t\"@rollup/plugin-node-resolve\": \"^13.3.0\",\n \t\"@web/dev-server\": \"^0.1.34\",\n \t\"babel-eslint\": \"^10.1.0\",\n \tconcurrently: \"^7.4.0\",\n \teslint: \"^7.32.0\",\n \tesm: \"^3.2.25\",\n \tkarma: \"6.4.1\",\n \t\"karma-chrome-launcher\": \"3.2.0\",\n \t\"karma-qunit\": \"^4.1.2\",\n \t\"karma-sauce-launcher\": \"^4.3.6\",\n \t\"node-sass\": \"^7.0.1\",\n \tqunit: \"2.19.1\",\n \trangy: \"^1.3.0\",\n \trollup: \"^2.56.3\",\n \t\"rollup-plugin-includepaths\": \"^0.2.4\",\n \t\"rollup-plugin-terser\": \"^7.0.2\",\n \tsvgo: \"^2.8.0\",\n \twebdriverio: \"^7.19.5\"\n };\n var resolutions = {\n \twebdriverio: \"^7.19.5\"\n };\n var scripts = {\n \t\"build-css\": \"node-sass --functions=./assets/trix/stylesheets/functions assets/trix.scss dist/trix.css\",\n \t\"build-js\": \"rollup -c\",\n \t\"build-assets\": \"cp -f assets/*.html dist/\",\n \tbuild: \"yarn run build-js && yarn run build-css && yarn run build-assets\",\n \twatch: \"rollup -c -w\",\n \tlint: \"eslint .\",\n \tpretest: \"yarn run lint && yarn run build\",\n \ttest: \"karma start\",\n \tprerelease: \"yarn version && yarn test\",\n \trelease: \"npm adduser && npm publish\",\n \tpostrelease: \"git push && git push --tags\",\n \tdev: \"web-dev-server --app-index index.html --root-dir dist --node-resolve --open\",\n \tstart: \"yarn build-assets && concurrently --kill-others --names js,css,dev-server 'yarn watch' 'yarn build-css --watch' 'yarn dev'\"\n };\n var dependencies = {\n \tdompurify: \"^3.2.3\"\n };\n var _package = {\n \tname: name,\n \tversion: version,\n \tdescription: description,\n \tmain: main,\n \tmodule: module,\n \tstyle: style,\n \tfiles: files,\n \trepository: repository,\n \tkeywords: keywords,\n \tauthor: author,\n \tlicense: license,\n \tbugs: bugs,\n \thomepage: homepage,\n \tdevDependencies: devDependencies,\n \tresolutions: resolutions,\n \tscripts: scripts,\n \tdependencies: dependencies\n };\n\n const attachmentSelector = \"[data-trix-attachment]\";\n const 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 };\n\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 htmlAttributes: [\"language\"],\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$1(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$1(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 const tagName$1 = element => {\n var _element$tagName;\n return element === null || element === void 0 || (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase();\n };\n\n const androidVersionMatch = navigator.userAgent.match(/android\\s([0-9]+.*Chrome)/i);\n const androidVersion = androidVersionMatch && parseInt(androidVersionMatch[1]);\n var browser$1 = {\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 // Android 13, especially on Samsung keyboards, emits extra compositionend and beforeinput events\n // that can make the input handler lose the current selection or enter an infinite input -> render -> input\n // loop.\n recentAndroid: androidVersion && androidVersion > 12,\n samsungAndroid: androidVersion && navigator.userAgent.match(/Android.*SM-/),\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: typeof InputEvent !== \"undefined\" && [\"data\", \"getTargetRanges\", \"inputType\"].every(prop => prop in InputEvent.prototype)\n };\n\n var css$3 = {\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\n var lang$1 = {\n attachFiles: \"Attach Files\",\n bold: \"Bold\",\n bullets: \"Bullets\",\n byte: \"Byte\",\n bytes: \"Bytes\",\n captionPlaceholder: \"Add a caption\u2026\",\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\u2026\",\n GB: \"GB\",\n KB: \"KB\",\n MB: \"MB\",\n PB: \"PB\",\n TB: \"TB\"\n };\n\n /* eslint-disable\n no-case-declarations,\n */\n const sizes = [lang$1.bytes, lang$1.KB, lang$1.MB, lang$1.GB, lang$1.TB, lang$1.PB];\n var file_size_formatting = {\n prefix: \"IEC\",\n precision: 2,\n formatter(number) {\n switch (number) {\n case 0:\n return \"0 \".concat(lang$1.bytes);\n case 1:\n return \"1 \".concat(lang$1.byte);\n default:\n let base;\n if (this.prefix === \"SI\") {\n base = 1000;\n } else if (this.prefix === \"IEC\") {\n base = 1024;\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 \"\".concat(withoutInsignificantZeros, \" \").concat(sizes[exp]);\n }\n }\n };\n\n const ZERO_WIDTH_SPACE = \"\\uFEFF\";\n const NON_BREAKING_SPACE = \"\\u00A0\";\n const OBJECT_REPLACEMENT_CHARACTER = \"\\uFFFC\";\n\n 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\n const html$2 = document.documentElement;\n const match = html$2.matches;\n const handleEvent = function (eventName) {\n let {\n onElement,\n matchingSelector,\n withCallback,\n inPhase,\n preventDefault,\n times\n } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n const element = onElement ? onElement : html$2;\n const selector = matchingSelector;\n const useCapture = inPhase === \"capturing\";\n const handler = function (event) {\n if (times != null && --times === 0) {\n handler.destroy();\n }\n const target = findClosestElementFromNode(event.target, {\n matchingSelector: selector\n });\n if (target != null) {\n withCallback === null || withCallback === void 0 || withCallback.call(target, event, target);\n if (preventDefault) {\n event.preventDefault();\n }\n }\n };\n handler.destroy = () => element.removeEventListener(eventName, handler, useCapture);\n element.addEventListener(eventName, handler, useCapture);\n return handler;\n };\n const handleEventOnce = function (eventName) {\n let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n options.times = 1;\n return handleEvent(eventName, options);\n };\n const triggerEvent = function (eventName) {\n let {\n onElement,\n bubbles,\n cancelable,\n attributes\n } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n const element = onElement != null ? onElement : html$2;\n bubbles = bubbles !== false;\n cancelable = cancelable !== false;\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 const elementMatchesSelector = function (element, selector) {\n if ((element === null || element === void 0 ? void 0 : element.nodeType) === 1) {\n return match.call(element, selector);\n }\n };\n const findClosestElementFromNode = function (node) {\n let {\n matchingSelector,\n untilNode\n } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n while (node && node.nodeType !== Node.ELEMENT_NODE) {\n node = node.parentNode;\n }\n if (node == null) {\n return;\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 const findInnerElement = function (element) {\n while ((_element = element) !== null && _element !== void 0 && _element.firstElementChild) {\n var _element;\n element = element.firstElementChild;\n }\n return element;\n };\n const innerElementIsActive = element => document.activeElement !== element && elementContainsNode(element, document.activeElement);\n 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 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 const findElementFromContainerAndOffset = function (container, offset) {\n const node = findNodeFromContainerAndOffset(container, offset);\n return findClosestElementFromNode(node);\n };\n const findChildIndexOfNode = function (node) {\n var _node;\n if (!((_node = node) !== null && _node !== void 0 && _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 const removeNode = node => {\n var _node$parentNode;\n return node === null || node === void 0 || (_node$parentNode = node.parentNode) === null || _node$parentNode === void 0 ? void 0 : _node$parentNode.removeChild(node);\n };\n const walkTree = function (tree) {\n let {\n onlyNodesOfType,\n usingFilter,\n expandEntityReferences\n } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\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 return document.createTreeWalker(tree, whatToShow, usingFilter != null ? usingFilter : null, expandEntityReferences === true);\n };\n const tagName = element => {\n var _element$tagName;\n return element === null || element === void 0 || (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase();\n };\n const makeElement = function (tag) {\n let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let key, value;\n if (typeof tag === \"object\") {\n options = tag;\n tag = options.tagName;\n } else {\n options = {\n attributes: options\n };\n }\n const element = document.createElement(tag);\n if (options.editable != null) {\n if (options.attributes == null) {\n options.attributes = {};\n }\n options.attributes.contenteditable = options.editable;\n }\n if (options.attributes) {\n for (key in options.attributes) {\n value = options.attributes[key];\n element.setAttribute(key, value);\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 if (options.data) {\n for (key in options.data) {\n value = options.data[key];\n element.dataset[key] = value;\n }\n }\n if (options.className) {\n options.className.split(\" \").forEach(className => {\n element.classList.add(className);\n });\n }\n if (options.textContent) {\n element.textContent = options.textContent;\n }\n if (options.childNodes) {\n [].concat(options.childNodes).forEach(childNode => {\n element.appendChild(childNode);\n });\n }\n return element;\n };\n let blockTagNames = undefined;\n const getBlockTagNames = function () {\n if (blockTagNames != null) {\n return blockTagNames;\n }\n blockTagNames = [];\n for (const key in attributes) {\n const attributes$1 = attributes[key];\n if (attributes$1.tagName) {\n blockTagNames.push(attributes$1.tagName);\n }\n }\n return blockTagNames;\n };\n const nodeIsBlockContainer = node => nodeIsBlockStartComment(node === null || node === void 0 ? void 0 : node.firstChild);\n const nodeProbablyIsBlockContainer = function (node) {\n return getBlockTagNames().includes(tagName(node)) && !getBlockTagNames().includes(tagName(node.firstChild));\n };\n const nodeIsBlockStart = function (node) {\n let {\n strict\n } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n strict: true\n };\n if (strict) {\n return nodeIsBlockStartComment(node);\n } else {\n return nodeIsBlockStartComment(node) || !nodeIsBlockStartComment(node.firstChild) && nodeProbablyIsBlockContainer(node);\n }\n };\n const nodeIsBlockStartComment = node => nodeIsCommentNode(node) && (node === null || node === void 0 ? void 0 : node.data) === \"block\";\n const nodeIsCommentNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.COMMENT_NODE;\n const nodeIsCursorTarget = function (node) {\n let {\n name\n } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\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 const nodeIsAttachmentElement = node => elementMatchesSelector(node, attachmentSelector);\n const nodeIsEmptyTextNode = node => nodeIsTextNode(node) && (node === null || node === void 0 ? void 0 : node.data) === \"\";\n const nodeIsTextNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.TEXT_NODE;\n\n const input = {\n level2Enabled: true,\n getLevel() {\n if (this.level2Enabled && browser$1.supportsInputEvents) {\n return 2;\n } else {\n return 0;\n }\n },\n pickFiles(callback) {\n const input = makeElement(\"input\", {\n type: \"file\",\n multiple: true,\n hidden: true,\n id: this.fileInputId\n });\n input.addEventListener(\"change\", () => {\n callback(input.files);\n removeNode(input);\n });\n removeNode(document.getElementById(this.fileInputId));\n document.body.appendChild(input);\n input.click();\n }\n };\n\n var key_names = {\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\n var parser = {\n removeBlankTableCells: false,\n tableCellSeparator: \" | \",\n tableRowSeparator: \"\\n\"\n };\n\n var text_attributes = {\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(\".concat(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: {\n backgroundColor: \"highlight\"\n }\n }\n };\n\n var toolbar = {\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 const undo = {\n interval: 5000\n };\n\n var config = /*#__PURE__*/Object.freeze({\n __proto__: null,\n attachments: attachments,\n blockAttributes: attributes,\n browser: browser$1,\n css: css$3,\n fileSize: file_size_formatting,\n input: input,\n keyNames: key_names,\n lang: lang$1,\n parser: parser,\n textAttributes: text_attributes,\n toolbar: toolbar,\n undo: undo\n });\n\n class BasicObject {\n static proxyMethod(expression) {\n const {\n name,\n toMethod,\n toProperty,\n optional\n } = parseProxyMethodExpression(expression);\n this.prototype[name] = function () {\n let subject;\n let object;\n if (toMethod) {\n if (optional) {\n var _this$toMethod;\n object = (_this$toMethod = this[toMethod]) === null || _this$toMethod === void 0 ? void 0 : _this$toMethod.call(this);\n } else {\n object = this[toMethod]();\n }\n } else if (toProperty) {\n object = this[toProperty];\n }\n if (optional) {\n var _object;\n subject = (_object = object) === null || _object === void 0 ? void 0 : _object[name];\n if (subject) {\n return apply$1.call(subject, object, arguments);\n }\n } else {\n subject = object[name];\n return apply$1.call(subject, object, arguments);\n }\n };\n }\n }\n const parseProxyMethodExpression = function (expression) {\n const match = expression.match(proxyMethodExpressionPattern);\n if (!match) {\n throw new Error(\"can't parse @proxyMethod expression: \".concat(expression));\n }\n const args = {\n name: match[4]\n };\n if (match[2] != null) {\n args.toMethod = match[1];\n } else {\n args.toProperty = match[1];\n }\n if (match[3] != null) {\n args.optional = true;\n }\n return args;\n };\n const {\n apply: apply$1\n } = Function.prototype;\n const proxyMethodExpressionPattern = new RegExp(\"\\\n^\\\n(.+?)\\\n(\\\\(\\\\))?\\\n(\\\\?)?\\\n\\\\.\\\n(.+?)\\\n$\\\n\");\n\n var _Array$from, _$codePointAt$1, _$1, _String$fromCodePoint;\n class UTF16String extends BasicObject {\n static box() {\n let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n if (value instanceof this) {\n return value;\n } else {\n return this.fromUCS2String(value === null || value === void 0 ? void 0 : value.toString());\n }\n }\n static fromUCS2String(ucs2String) {\n return new this(ucs2String, ucs2decode(ucs2String));\n }\n static fromCodepoints(codepoints) {\n return new this(ucs2encode(codepoints), codepoints);\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 offsetToUCS2Offset(offset) {\n return ucs2encode(this.codepoints.slice(0, Math.max(0, offset))).length;\n }\n offsetFromUCS2Offset(ucs2Offset) {\n return ucs2decode(this.ucs2String.slice(0, Math.max(0, ucs2Offset))).length;\n }\n slice() {\n return this.constructor.fromCodepoints(this.codepoints.slice(...arguments));\n }\n charAt(offset) {\n return this.slice(offset, offset + 1);\n }\n isEqualTo(value) {\n return this.constructor.box(value).ucs2String === this.ucs2String;\n }\n toJSON() {\n return this.ucs2String;\n }\n getCacheKey() {\n return this.ucs2String;\n }\n toString() {\n return this.ucs2String;\n }\n }\n const hasArrayFrom = ((_Array$from = Array.from) === null || _Array$from === void 0 ? void 0 : _Array$from.call(Array, \"\\ud83d\\udc7c\").length) === 1;\n const hasStringCodePointAt$1 = ((_$codePointAt$1 = (_$1 = \" \").codePointAt) === null || _$codePointAt$1 === void 0 ? void 0 : _$codePointAt$1.call(_$1, 0)) != null;\n const hasStringFromCodePoint = ((_String$fromCodePoint = String.fromCodePoint) === null || _String$fromCodePoint === void 0 ? void 0 : _String$fromCodePoint.call(String, 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\n let 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.\n if (hasArrayFrom && hasStringCodePointAt$1) {\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 {\n length\n } = string;\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 return output;\n };\n }\n\n // Creates a string based on an array of numeric code points.\n if (hasStringFromCodePoint) {\n ucs2encode = array => String.fromCodePoint(...Array.from(array || []));\n } else {\n ucs2encode = function (array) {\n const characters = (() => {\n const result = [];\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 return result;\n })();\n return characters.join(\"\");\n };\n }\n\n let id$2 = 0;\n class TrixObject extends BasicObject {\n static fromJSONString(jsonString) {\n return this.fromJSON(JSON.parse(jsonString));\n }\n constructor() {\n super(...arguments);\n this.id = ++id$2;\n }\n hasSameConstructorAs(object) {\n return this.constructor === (object === null || object === void 0 ? void 0 : object.constructor);\n }\n isEqualTo(object) {\n return this === object;\n }\n inspect() {\n const parts = [];\n const contents = this.contentsForInspection() || {};\n for (const key in contents) {\n const value = contents[key];\n parts.push(\"\".concat(key, \"=\").concat(value));\n }\n return \"#<\".concat(this.constructor.name, \":\").concat(this.id).concat(parts.length ? \" \".concat(parts.join(\", \")) : \"\", \">\");\n }\n contentsForInspection() {}\n toJSONString() {\n return JSON.stringify(this);\n }\n toUTF16String() {\n return UTF16String.box(this);\n }\n getCacheKey() {\n return this.id.toString();\n }\n }\n\n /* eslint-disable\n id-length,\n */\n const arraysAreEqual = function () {\n let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];\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 const arrayStartsWith = function () {\n let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];\n return arraysAreEqual(a.slice(0, b.length), b);\n };\n const spliceArray = function (array) {\n const result = array.slice(0);\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n result.splice(...args);\n return result;\n };\n const summarizeArrayChange = function () {\n let oldArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n let newArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];\n const added = [];\n const removed = [];\n const existingValues = new Set();\n oldArray.forEach(value => {\n existingValues.add(value);\n });\n const currentValues = new Set();\n newArray.forEach(value => {\n currentValues.add(value);\n if (!existingValues.has(value)) {\n added.push(value);\n }\n });\n oldArray.forEach(value => {\n if (!currentValues.has(value)) {\n removed.push(value);\n }\n });\n return {\n added,\n removed\n };\n };\n\n // https://github.com/mathiasbynens/unicode-2.1.8/blob/master/Bidi_Class/Right_To_Left/regex.js\n 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]/;\n const getDirection = function () {\n const input = makeElement(\"input\", {\n dir: \"auto\",\n name: \"x\",\n dirName: \"x.dir\"\n });\n const textArea = makeElement(\"textarea\", {\n dir: \"auto\",\n name: \"y\",\n dirName: \"y.dir\"\n });\n const form = makeElement(\"form\");\n form.appendChild(input);\n form.appendChild(textArea);\n const supportsDirName = function () {\n try {\n return new FormData(form).has(textArea.dirName);\n } catch (error) {\n return false;\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 if (supportsDirName) {\n return function (string) {\n textArea.value = string;\n return new FormData(form).get(textArea.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\n let allAttributeNames = null;\n let blockAttributeNames = null;\n let textAttributeNames = null;\n let listAttributeNames = null;\n const getAllAttributeNames = () => {\n if (!allAttributeNames) {\n allAttributeNames = getTextAttributeNames().concat(getBlockAttributeNames());\n }\n return allAttributeNames;\n };\n const getBlockConfig = attributeName => attributes[attributeName];\n const getBlockAttributeNames = () => {\n if (!blockAttributeNames) {\n blockAttributeNames = Object.keys(attributes);\n }\n return blockAttributeNames;\n };\n const getTextConfig = attributeName => text_attributes[attributeName];\n const getTextAttributeNames = () => {\n if (!textAttributeNames) {\n textAttributeNames = Object.keys(text_attributes);\n }\n return textAttributeNames;\n };\n const getListAttributeNames = () => {\n if (!listAttributeNames) {\n listAttributeNames = [];\n for (const key in attributes) {\n const {\n listAttribute\n } = attributes[key];\n if (listAttribute != null) {\n listAttributeNames.push(listAttribute);\n }\n }\n }\n return listAttributeNames;\n };\n\n /* eslint-disable\n */\n const installDefaultCSSForTagName = function (tagName, defaultCSS) {\n const styleElement = insertStyleElementForTagName(tagName);\n styleElement.textContent = defaultCSS.replace(/%t/g, tagName);\n };\n const 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 const getCSPNonce = function () {\n const element = getMetaElement(\"trix-csp-nonce\") || getMetaElement(\"csp-nonce\");\n if (element) {\n const {\n nonce,\n content\n } = element;\n return nonce == \"\" ? content : nonce;\n }\n };\n const getMetaElement = name => document.head.querySelector(\"meta[name=\".concat(name, \"]\"));\n\n const testTransferData = {\n \"application/x-trix-feature-detection\": \"test\"\n };\n const dataTransferIsPlainText = function (dataTransfer) {\n const text = dataTransfer.getData(\"text/plain\");\n const html = dataTransfer.getData(\"text/html\");\n if (text && html) {\n const {\n body\n } = new DOMParser().parseFromString(html, \"text/html\");\n if (body.textContent === text) {\n return !body.querySelector(\"*\");\n }\n } else {\n return text === null || text === void 0 ? void 0 : text.length;\n }\n };\n const dataTransferIsMsOfficePaste = _ref => {\n let {\n dataTransfer\n } = _ref;\n return dataTransfer.types.includes(\"Files\") && dataTransfer.types.includes(\"text/html\") && dataTransfer.getData(\"text/html\").includes(\"urn:schemas-microsoft-com:office:office\");\n };\n const dataTransferIsWritable = function (dataTransfer) {\n if (!(dataTransfer !== null && dataTransfer !== void 0 && dataTransfer.setData)) return false;\n for (const key in testTransferData) {\n const value = testTransferData[key];\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 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 function shouldRenderInmmediatelyToDealWithIOSDictation(inputEvent) {\n if (/iPhone|iPad/.test(navigator.userAgent)) {\n // Handle garbled content and duplicated newlines when using dictation on iOS 18+. Upon dictation completion, iOS sends\n // the list of insertText / insertParagraph events in a quick sequence. If we don't render\n // the editor synchronously, the internal range fails to update and results in garbled content or duplicated newlines.\n //\n // This workaround is necessary because iOS doesn't send composing events as expected while dictating:\n // https://bugs.webkit.org/show_bug.cgi?id=261764\n return !inputEvent.inputType || inputEvent.inputType === \"insertParagraph\";\n } else {\n return false;\n }\n }\n\n const defer = fn => setTimeout(fn, 1);\n\n /* eslint-disable\n id-length,\n */\n const copyObject = function () {\n let object = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n const result = {};\n for (const key in object) {\n const value = object[key];\n result[key] = value;\n }\n return result;\n };\n const objectsAreEqual = function () {\n let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\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\n const normalizeRange = function (range) {\n if (range == null) return;\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 const rangeIsCollapsed = function (range) {\n if (range == null) return;\n const [start, end] = normalizeRange(range);\n return rangeValuesAreEqual(start, end);\n };\n const rangesAreEqual = function (leftRange, rightRange) {\n if (leftRange == null || rightRange == null) return;\n const [leftStart, leftEnd] = normalizeRange(leftRange);\n const [rightStart, rightEnd] = normalizeRange(rightRange);\n return rangeValuesAreEqual(leftStart, rightStart) && rangeValuesAreEqual(leftEnd, rightEnd);\n };\n const copyValue = function (value) {\n if (typeof value === \"number\") {\n return value;\n } else {\n return copyObject(value);\n }\n };\n const rangeValuesAreEqual = function (left, right) {\n if (typeof left === \"number\") {\n return left === right;\n } else {\n return objectsAreEqual(left, right);\n }\n };\n\n class SelectionChangeObserver extends BasicObject {\n constructor() {\n super(...arguments);\n this.update = this.update.bind(this);\n this.selectionManagers = [];\n }\n start() {\n if (!this.started) {\n this.started = true;\n document.addEventListener(\"selectionchange\", this.update, true);\n }\n }\n stop() {\n if (this.started) {\n this.started = false;\n return document.removeEventListener(\"selectionchange\", this.update, true);\n }\n }\n registerSelectionManager(selectionManager) {\n if (!this.selectionManagers.includes(selectionManager)) {\n this.selectionManagers.push(selectionManager);\n return this.start();\n }\n }\n unregisterSelectionManager(selectionManager) {\n this.selectionManagers = this.selectionManagers.filter(sm => sm !== selectionManager);\n if (this.selectionManagers.length === 0) {\n return this.stop();\n }\n }\n notifySelectionManagersOfSelectionChange() {\n return this.selectionManagers.map(selectionManager => selectionManager.selectionDidChange());\n }\n update() {\n this.notifySelectionManagersOfSelectionChange();\n }\n reset() {\n this.update();\n }\n }\n const selectionChangeObserver = new SelectionChangeObserver();\n const getDOMSelection = function () {\n const selection = window.getSelection();\n if (selection.rangeCount > 0) {\n return selection;\n }\n };\n const getDOMRange = function () {\n var _getDOMSelection;\n const domRange = (_getDOMSelection = getDOMSelection()) === null || _getDOMSelection === void 0 ? void 0 : _getDOMSelection.getRangeAt(0);\n if (domRange) {\n if (!domRangeIsPrivate(domRange)) {\n return domRange;\n }\n }\n };\n 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\n const domRangeIsPrivate = domRange => nodeIsPrivate(domRange.startContainer) || nodeIsPrivate(domRange.endContainer);\n const nodeIsPrivate = node => !Object.getPrototypeOf(node);\n\n /* eslint-disable\n id-length,\n no-useless-escape,\n */\n const normalizeSpaces = string => string.replace(new RegExp(\"\".concat(ZERO_WIDTH_SPACE), \"g\"), \"\").replace(new RegExp(\"\".concat(NON_BREAKING_SPACE), \"g\"), \" \");\n const normalizeNewlines = string => string.replace(/\\r\\n?/g, \"\\n\");\n const breakableWhitespacePattern = new RegExp(\"[^\\\\S\".concat(NON_BREAKING_SPACE, \"]\"));\n const squishBreakableWhitespace = string => string\n // Replace all breakable whitespace characters with a space\n .replace(new RegExp(\"\".concat(breakableWhitespacePattern.source), \"g\"), \" \")\n // Replace two or more spaces with a single space\n .replace(/\\ {2,}/g, \" \");\n const summarizeStringChange = function (oldString, newString) {\n let added, removed;\n oldString = UTF16String.box(oldString);\n newString = UTF16String.box(newString);\n if (newString.length < oldString.length) {\n [removed, added] = utf16StringDifferences(oldString, newString);\n } else {\n [added, removed] = utf16StringDifferences(newString, oldString);\n }\n return {\n added,\n removed\n };\n };\n const utf16StringDifferences = function (a, b) {\n if (a.isEqualTo(b)) {\n return [\"\", \"\"];\n }\n const diffA = utf16StringDifference(a, b);\n const {\n length\n } = diffA.utf16String;\n let diffB;\n if (length) {\n const {\n offset\n } = 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 return [diffA.utf16String.toString(), diffB.utf16String.toString()];\n };\n const utf16StringDifference = function (a, b) {\n let leftIndex = 0;\n let rightIndexA = a.length;\n let rightIndexB = b.length;\n while (leftIndex < rightIndexA && a.charAt(leftIndex).isEqualTo(b.charAt(leftIndex))) {\n leftIndex++;\n }\n while (rightIndexA > leftIndex + 1 && a.charAt(rightIndexA - 1).isEqualTo(b.charAt(rightIndexB - 1))) {\n rightIndexA--;\n rightIndexB--;\n }\n return {\n utf16String: a.slice(leftIndex, rightIndexA),\n offset: leftIndex\n };\n };\n\n class Hash extends TrixObject {\n static fromCommonAttributesOfObjects() {\n let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n if (!objects.length) {\n return new this();\n }\n let hash = box(objects[0]);\n let keys = hash.getKeys();\n objects.slice(1).forEach(object => {\n keys = hash.getKeysCommonToHash(box(object));\n hash = hash.slice(keys);\n });\n return hash;\n }\n static box(values) {\n return box(values);\n }\n constructor() {\n let values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n super(...arguments);\n this.values = copy(values);\n }\n add(key, value) {\n return this.merge(object(key, value));\n }\n remove(key) {\n return new Hash(copy(this.values, key));\n }\n get(key) {\n return this.values[key];\n }\n has(key) {\n return key in this.values;\n }\n merge(values) {\n return new Hash(merge(this.values, unbox(values)));\n }\n slice(keys) {\n const values = {};\n Array.from(keys).forEach(key => {\n if (this.has(key)) {\n values[key] = this.values[key];\n }\n });\n return new Hash(values);\n }\n getKeys() {\n return Object.keys(this.values);\n }\n getKeysCommonToHash(hash) {\n hash = box(hash);\n return this.getKeys().filter(key => this.values[key] === hash.values[key]);\n }\n isEqualTo(values) {\n return arraysAreEqual(this.toArray(), box(values).toArray());\n }\n isEmpty() {\n return this.getKeys().length === 0;\n }\n toArray() {\n if (!this.array) {\n const result = [];\n for (const key in this.values) {\n const value = this.values[key];\n result.push(result.push(key, value));\n }\n this.array = result.slice(0);\n }\n return this.array;\n }\n toObject() {\n return copy(this.values);\n }\n toJSON() {\n return this.toObject();\n }\n contentsForInspection() {\n return {\n values: JSON.stringify(this.values)\n };\n }\n }\n const object = function (key, value) {\n const result = {};\n result[key] = value;\n return result;\n };\n const merge = function (object, values) {\n const result = copy(object);\n for (const key in values) {\n const value = values[key];\n result[key] = value;\n }\n return result;\n };\n const copy = function (object, keyToRemove) {\n const result = {};\n const sortedKeys = Object.keys(object).sort();\n sortedKeys.forEach(key => {\n if (key !== keyToRemove) {\n result[key] = object[key];\n }\n });\n return result;\n };\n const box = function (object) {\n if (object instanceof Hash) {\n return object;\n } else {\n return new Hash(object);\n }\n };\n const unbox = function (object) {\n if (object instanceof Hash) {\n return object.values;\n } else {\n return object;\n }\n };\n\n class ObjectGroup {\n static groupObjects() {\n let ungroupedObjects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n let {\n depth,\n asTree\n } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let group;\n if (asTree) {\n if (depth == null) {\n depth = 0;\n }\n }\n const objects = [];\n Array.from(ungroupedObjects).forEach(object => {\n var _object$canBeGrouped2;\n if (group) {\n var _object$canBeGrouped, _group$canBeGroupedWi, _group;\n 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)) {\n group.push(object);\n return;\n } else {\n objects.push(new this(group, {\n depth,\n asTree\n }));\n group = null;\n }\n }\n if ((_object$canBeGrouped2 = object.canBeGrouped) !== null && _object$canBeGrouped2 !== void 0 && _object$canBeGrouped2.call(object, depth)) {\n group = [object];\n } else {\n objects.push(object);\n }\n });\n if (group) {\n objects.push(new this(group, {\n depth,\n asTree\n }));\n }\n return objects;\n }\n constructor() {\n let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n let {\n depth,\n asTree\n } = arguments.length > 1 ? arguments[1] : undefined;\n this.objects = objects;\n if (asTree) {\n this.depth = depth;\n this.objects = this.constructor.groupObjects(this.objects, {\n asTree,\n depth: this.depth + 1\n });\n }\n }\n getObjects() {\n return this.objects;\n }\n getDepth() {\n return this.depth;\n }\n getCacheKey() {\n const keys = [\"objectGroup\"];\n Array.from(this.getObjects()).forEach(object => {\n keys.push(object.getCacheKey());\n });\n return keys.join(\"/\");\n }\n }\n\n class ObjectMap extends BasicObject {\n constructor() {\n let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n super(...arguments);\n this.objects = {};\n Array.from(objects).forEach(object => {\n const hash = JSON.stringify(object);\n if (this.objects[hash] == null) {\n this.objects[hash] = object;\n }\n });\n }\n find(object) {\n const hash = JSON.stringify(object);\n return this.objects[hash];\n }\n }\n\n class ElementStore {\n constructor(elements) {\n this.reset(elements);\n }\n add(element) {\n const key = getKey(element);\n this.elements[key] = element;\n }\n remove(element) {\n const key = getKey(element);\n const value = this.elements[key];\n if (value) {\n delete this.elements[key];\n return value;\n }\n }\n reset() {\n let elements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n this.elements = {};\n Array.from(elements).forEach(element => {\n this.add(element);\n });\n return elements;\n }\n }\n const getKey = element => element.dataset.trixStoreKey;\n\n class Operation extends BasicObject {\n isPerforming() {\n return this.performing === true;\n }\n hasPerformed() {\n return this.performed === true;\n }\n hasSucceeded() {\n return this.performed && this.succeeded;\n }\n hasFailed() {\n return this.performed && !this.succeeded;\n }\n getPromise() {\n if (!this.promise) {\n this.promise = new Promise((resolve, reject) => {\n this.performing = true;\n return this.perform((succeeded, result) => {\n this.succeeded = succeeded;\n this.performing = false;\n this.performed = true;\n if (this.succeeded) {\n resolve(result);\n } else {\n reject(result);\n }\n });\n });\n }\n return this.promise;\n }\n perform(callback) {\n return callback(false);\n }\n release() {\n var _this$promise, _this$promise$cancel;\n (_this$promise = this.promise) === null || _this$promise === void 0 || (_this$promise$cancel = _this$promise.cancel) === null || _this$promise$cancel === void 0 || _this$promise$cancel.call(_this$promise);\n this.promise = null;\n this.performing = null;\n this.performed = null;\n this.succeeded = null;\n }\n }\n Operation.proxyMethod(\"getPromise().then\");\n Operation.proxyMethod(\"getPromise().catch\");\n\n class ObjectView extends BasicObject {\n constructor(object) {\n let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n super(...arguments);\n this.object = object;\n this.options = options;\n this.childViews = [];\n this.rootView = this;\n }\n getNodes() {\n if (!this.nodes) {\n this.nodes = this.createNodes();\n }\n return this.nodes.map(node => node.cloneNode(true));\n }\n invalidate() {\n var _this$parentView;\n this.nodes = null;\n this.childViews = [];\n return (_this$parentView = this.parentView) === null || _this$parentView === void 0 ? void 0 : _this$parentView.invalidate();\n }\n invalidateViewForObject(object) {\n var _this$findViewForObje;\n return (_this$findViewForObje = this.findViewForObject(object)) === null || _this$findViewForObje === void 0 ? void 0 : _this$findViewForObje.invalidate();\n }\n findOrCreateCachedChildView(viewClass, object, options) {\n let view = this.getCachedViewForObject(object);\n if (view) {\n this.recordChildView(view);\n } else {\n view = this.createChildView(...arguments);\n this.cacheViewForObject(view, object);\n }\n return view;\n }\n createChildView(viewClass, object) {\n let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n if (object instanceof ObjectGroup) {\n options.viewClass = viewClass;\n viewClass = ObjectGroupView;\n }\n const view = new viewClass(object, options);\n return this.recordChildView(view);\n }\n recordChildView(view) {\n view.parentView = this;\n view.rootView = this.rootView;\n this.childViews.push(view);\n return view;\n }\n getAllChildViews() {\n let views = [];\n this.childViews.forEach(childView => {\n views.push(childView);\n views = views.concat(childView.getAllChildViews());\n });\n return views;\n }\n findElement() {\n return this.findElementForObject(this.object);\n }\n findElementForObject(object) {\n const id = object === null || object === void 0 ? void 0 : object.id;\n if (id) {\n return this.rootView.element.querySelector(\"[data-trix-id='\".concat(id, \"']\"));\n }\n }\n findViewForObject(object) {\n for (const view of this.getAllChildViews()) {\n if (view.object === object) {\n return view;\n }\n }\n }\n getViewCache() {\n if (this.rootView === this) {\n if (this.isViewCachingEnabled()) {\n if (!this.viewCache) {\n this.viewCache = {};\n }\n return this.viewCache;\n }\n } else {\n return this.rootView.getViewCache();\n }\n }\n isViewCachingEnabled() {\n return this.shouldCacheViews !== false;\n }\n enableViewCaching() {\n this.shouldCacheViews = true;\n }\n disableViewCaching() {\n this.shouldCacheViews = false;\n }\n getCachedViewForObject(object) {\n var _this$getViewCache;\n return (_this$getViewCache = this.getViewCache()) === null || _this$getViewCache === void 0 ? void 0 : _this$getViewCache[object.getCacheKey()];\n }\n cacheViewForObject(view, object) {\n const cache = this.getViewCache();\n if (cache) {\n cache[object.getCacheKey()] = view;\n }\n }\n garbageCollectCachedViews() {\n const cache = this.getViewCache();\n if (cache) {\n const views = this.getAllChildViews().concat(this);\n const objectKeys = views.map(view => view.object.getCacheKey());\n for (const key in cache) {\n if (!objectKeys.includes(key)) {\n delete cache[key];\n }\n }\n }\n }\n }\n class ObjectGroupView extends ObjectView {\n constructor() {\n super(...arguments);\n this.objectGroup = this.object;\n this.viewClass = this.options.viewClass;\n delete this.options.viewClass;\n }\n getChildViews() {\n if (!this.childViews.length) {\n Array.from(this.objectGroup.getObjects()).forEach(object => {\n this.findOrCreateCachedChildView(this.viewClass, object, this.options);\n });\n }\n return this.childViews;\n }\n createNodes() {\n const element = this.createContainerElement();\n this.getChildViews().forEach(view => {\n Array.from(view.getNodes()).forEach(node => {\n element.appendChild(node);\n });\n });\n return [element];\n }\n createContainerElement() {\n let depth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.objectGroup.getDepth();\n return this.getChildViews()[0].createContainerElement(depth);\n }\n }\n\n /*! @license DOMPurify 3.2.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.3/LICENSE */\n\n const {\n entries,\n setPrototypeOf,\n isFrozen,\n getPrototypeOf,\n getOwnPropertyDescriptor\n } = Object;\n let {\n freeze,\n seal,\n create\n } = Object; // eslint-disable-line import/no-mutable-exports\n let {\n apply,\n construct\n } = typeof Reflect !== 'undefined' && Reflect;\n if (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n }\n if (!seal) {\n seal = function seal(x) {\n return x;\n };\n }\n if (!apply) {\n apply = function apply(fun, thisValue, args) {\n return fun.apply(thisValue, args);\n };\n }\n if (!construct) {\n construct = function construct(Func, args) {\n return new Func(...args);\n };\n }\n const arrayForEach = unapply(Array.prototype.forEach);\n const arrayPop = unapply(Array.prototype.pop);\n const arrayPush = unapply(Array.prototype.push);\n const stringToLowerCase = unapply(String.prototype.toLowerCase);\n const stringToString = unapply(String.prototype.toString);\n const stringMatch = unapply(String.prototype.match);\n const stringReplace = unapply(String.prototype.replace);\n const stringIndexOf = unapply(String.prototype.indexOf);\n const stringTrim = unapply(String.prototype.trim);\n const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\n const regExpTest = unapply(RegExp.prototype.test);\n const typeErrorCreate = unconstruct(TypeError);\n /**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param func - The function to be wrapped and called.\n * @returns A new function that calls the given function with a specified thisArg and arguments.\n */\n function unapply(func) {\n return function (thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n return apply(func, thisArg, args);\n };\n }\n /**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param func - The constructor function to be wrapped and called.\n * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n */\n function unconstruct(func) {\n return function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n return construct(func, args);\n };\n }\n /**\n * Add properties to a lookup table\n *\n * @param set - The set to which elements will be added.\n * @param array - The array containing elements to be added to the set.\n * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns The modified set with added elements.\n */\n function addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n }\n /**\n * Clean up an array to harden against CSPP\n *\n * @param array - The array to be cleaned.\n * @returns The cleaned version of the array\n */\n function cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n }\n /**\n * Shallow clone an object\n *\n * @param object - The object to be cloned.\n * @returns A new object that copies the original.\n */\n function clone(object) {\n const newObject = create(null);\n for (const [property, value] of entries(object)) {\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (Array.isArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n }\n /**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param object - The object to look up the getter function in its prototype chain.\n * @param prop - The property name for which to find the getter function.\n * @returns The getter function found in the prototype chain or a fallback function.\n */\n function lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n }\n const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\n const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\n const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n // List of SVG elements that are disallowed by default.\n // We still need to know them so that we can do namespace\n // checks properly in case one wants to add them to\n // allow-list.\n const svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\n const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n // Similarly to SVG, we want to know all MathML elements,\n // even those that we disallow by default.\n const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\n const text = freeze(['#text']);\n const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);\n const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\n const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\n const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n // eslint-disable-next-line unicorn/better-regex\n const MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\n const ERB_EXPR = seal(/<%[\\w\\W]*|[\\w\\W]*%>/gm);\n const TMPLIT_EXPR = seal(/\\$\\{[\\w\\W]*}/gm); // eslint-disable-line unicorn/better-regex\n const DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]+$/); // eslint-disable-line no-useless-escape\n const ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\n const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n );\n\n const IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\n const ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n );\n\n const DOCTYPE_NAME = seal(/^html$/i);\n const CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n var EXPRESSIONS = /*#__PURE__*/Object.freeze({\n __proto__: null,\n ARIA_ATTR: ARIA_ATTR,\n ATTR_WHITESPACE: ATTR_WHITESPACE,\n CUSTOM_ELEMENT: CUSTOM_ELEMENT,\n DATA_ATTR: DATA_ATTR,\n DOCTYPE_NAME: DOCTYPE_NAME,\n ERB_EXPR: ERB_EXPR,\n IS_ALLOWED_URI: IS_ALLOWED_URI,\n IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n MUSTACHE_EXPR: MUSTACHE_EXPR,\n TMPLIT_EXPR: TMPLIT_EXPR\n });\n\n /* eslint-disable @typescript-eslint/indent */\n // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\n const NODE_TYPE = {\n element: 1,\n attribute: 2,\n text: 3,\n cdataSection: 4,\n entityReference: 5,\n // Deprecated\n entityNode: 6,\n // Deprecated\n progressingInstruction: 7,\n comment: 8,\n document: 9,\n documentType: 10,\n documentFragment: 11,\n notation: 12 // Deprecated\n };\n\n const getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n };\n /**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param trustedTypes The policy factory.\n * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\n const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n };\n const _createHooksMap = function _createHooksMap() {\n return {\n afterSanitizeAttributes: [],\n afterSanitizeElements: [],\n afterSanitizeShadowDOM: [],\n beforeSanitizeAttributes: [],\n beforeSanitizeElements: [],\n beforeSanitizeShadowDOM: [],\n uponSanitizeAttribute: [],\n uponSanitizeElement: [],\n uponSanitizeShadowNode: []\n };\n };\n function createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n DOMPurify.version = '3.2.3';\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let {\n document\n } = window;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n const {\n DocumentFragment,\n HTMLTemplateElement,\n Node,\n Element,\n NodeFilter,\n NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,\n HTMLFormElement,\n DOMParser,\n trustedTypes\n } = window;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const remove = lookupGetter(ElementPrototype, 'remove');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n const {\n implementation,\n createNodeIterator,\n createDocumentFragment,\n getElementsByTagName\n } = document;\n const {\n importNode\n } = originalDocument;\n let hooks = _createHooksMap();\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const {\n MUSTACHE_EXPR,\n ERB_EXPR,\n TMPLIT_EXPR,\n DATA_ATTR,\n ARIA_ATTR,\n IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE,\n CUSTOM_ELEMENT\n } = EXPRESSIONS;\n let {\n IS_ALLOWED_URI: IS_ALLOWED_URI$1\n } = EXPRESSIONS;\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n /*\n * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n /* Decide if document with ... should be returned */\n let WHOLE_DOCUMENT = false;\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (\u00A77.3.3)\n * - DOM Tree Accessors (\u00A73.1.5)\n * - Form Element Parent-Child Relations (\u00A74.10.3)\n * - Iframe srcdoc / Nested WindowProxies (\u00A74.8.5)\n * - HTMLCollection (\u00A74.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES = {};\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n /* Tags that are safe for data: URIs */\n let DATA_URI_TAGS = null;\n const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n /* Attributes safe for values like \"javascript:\" */\n let URI_SAFE_ATTRIBUTES = null;\n const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n let NAMESPACE = HTML_NAMESPACE;\n let IS_EMPTY_INPUT = false;\n /* Allowed XHTML+XML namespaces */\n let ALLOWED_NAMESPACES = null;\n const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erroneously deleted from\n // HTML namespace.\n const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n /* Parsing of strict XHTML documents */\n let PARSER_MEDIA_TYPE = null;\n const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n let transformCaseFunc = null;\n /* Keep a reference to config to pass to hooks */\n let CONFIG = null;\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n const formElement = document.createElement('form');\n const isRegexOrFunction = function isRegexOrFunction(testValue) {\n return testValue instanceof RegExp || testValue instanceof Function;\n };\n /**\n * _parseConfig\n *\n * @param cfg optional config literal\n */\n // eslint-disable-next-line complexity\n const _parseConfig = function _parseConfig() {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n /* Shield configuration object from tampering */\n if (!cfg || typeof cfg !== 'object') {\n cfg = {};\n }\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n PARSER_MEDIA_TYPE =\n // eslint-disable-next-line unicorn/prefer-includes\n SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n /* Set configuration parameters */\n ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;\n ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;\n URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;\n DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;\n FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;\n FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};\n FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};\n USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;\n NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;\n MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;\n HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;\n CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {\n CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;\n }\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, text);\n ALLOWED_ATTR = [];\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html$1);\n addToSet(ALLOWED_ATTR, html);\n }\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg$1);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl$1);\n addToSet(ALLOWED_ATTR, mathMl);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n }\n if (cfg.ADD_ATTR) {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n }\n if (cfg.ADD_URI_SAFE_ATTR) {\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);\n }\n if (cfg.FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);\n }\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n if (cfg.TRUSTED_TYPES_POLICY) {\n if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n }\n if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n }\n // Overwrite existing TrustedTypes policy.\n trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n // Sign local variables required by `sanitize`.\n emptyHTML = trustedTypesPolicy.createHTML('');\n } else {\n // Uninitialized policy, attempt to initialize the internal dompurify policy.\n if (trustedTypesPolicy === undefined) {\n trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n }\n // If creating the internal policy succeeded sign internal variables.\n if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {\n emptyHTML = trustedTypesPolicy.createHTML('');\n }\n }\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n CONFIG = cfg;\n };\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n /**\n * @param element a DOM element whose namespace is being checked\n * @returns Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n const _checkValidNamespace = function _checkValidNamespace(element) {\n let parent = getParentNode(element);\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: NAMESPACE,\n tagName: 'template'\n };\n }\n const tagName = stringToLowerCase(element.tagName);\n const parentTagName = stringToLowerCase(parent.tagName);\n if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n return false;\n }\n if (element.namespaceURI === SVG_NAMESPACE) {\n // The only way to switch from HTML namespace to SVG\n // is via