editable.ts 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editable.umd.cjs +1 -1
- package/dist/editable.umd.cjs.map +1 -1
- package/lib/core.d.ts +11 -0
- package/lib/core.d.ts.map +1 -1
- package/lib/core.js +5 -0
- package/lib/core.js.map +1 -1
- package/lib/plugins/text-diff/diff-algorithm.d.ts +14 -0
- package/lib/plugins/text-diff/diff-algorithm.d.ts.map +1 -0
- package/lib/plugins/text-diff/diff-algorithm.js +148 -0
- package/lib/plugins/text-diff/diff-algorithm.js.map +1 -0
- package/lib/plugins/text-diff/text-diff.d.ts +36 -0
- package/lib/plugins/text-diff/text-diff.d.ts.map +1 -0
- package/lib/plugins/text-diff/text-diff.js +206 -0
- package/lib/plugins/text-diff/text-diff.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editable.umd.cjs","sources":["../lib/config.js","../lib/util/error.js","../lib/util/string.js","../lib/node-iterator.js","../lib/node-type.js","../lib/util/dom.js","../lib/parser.js","../lib/range-save-restore.js","../lib/content.js","../lib/block.js","../lib/quotes.js","../lib/clipboard.js","../lib/feature-detection.js","../lib/eventable.js","../lib/util/viewport.js","../lib/cursor.js","../lib/highlight-text.js","../lib/plugins/highlighting/text-search.js","../lib/highlight-support.js","../lib/selection.js","../lib/range-container.js","../lib/selection-watcher.js","../lib/keyboard.js","../lib/smartQuotes.js","../lib/dispatcher.js","../lib/util/merge.js","../lib/plugins/highlighting/spellcheck-service.js","../lib/plugins/highlighting/whitespace-highlighting.js","../lib/plugins/highlighting/match-collection.js","../lib/monitored-highlighting.js","../lib/util/log.js","../lib/create-default-events.js","../lib/create-default-behavior.js","../lib/util/element.js","../lib/util/binary_search.js","../lib/core.js"],"sourcesContent":["const config = {\n log: false,\n logErrors: true,\n editableClass: 'js-editable',\n editableDisabledClass: 'js-editable-disabled',\n pastingAttribute: 'data-editable-is-pasting',\n trimLeadingAndTrailingWhitespaces: true,\n boldMarkup: {\n type: 'tag',\n name: 'strong',\n attribs: {},\n trim: true\n },\n italicMarkup: {\n type: 'tag',\n name: 'em',\n attribs: {},\n trim: true\n },\n underlineMarkup: {\n type: 'tag',\n name: 'u',\n attribs: {},\n trim: false\n },\n linkMarkup: {\n type: 'tag',\n name: 'a',\n attribs: {},\n trim: true\n },\n pastedHtmlRules: {\n allowedElements: {\n 'a': {\n 'href': true,\n 'rel': true,\n 'target': true\n },\n 'strong': {},\n 'em': {},\n 'br': {}\n },\n allowedPlainTextElements: {\n 'br': {}\n },\n requiredAttributes: {\n 'a': ['href']\n },\n transformElements: {\n 'b': 'strong',\n 'i': 'em'\n },\n splitIntoBlocks: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'blockquote'],\n blockLevelElements: [\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'p', 'pre', 'hr', 'blockquote',\n 'article', 'figure', 'header', 'footer', 'ul', 'ol', 'li', 'section', 'table', 'video'\n ],\n blacklistedElements: ['style', 'script'],\n keepInternalRelativeLinks: false,\n replaceQuotes: {}\n }\n};\nexport default config;\n//# sourceMappingURL=config.js.map","import config from '../config.js';\n// Allows for safe error logging\n// Falls back to console.log if console.error is not available\nexport default function error(...args) {\n if (config.logErrors === false)\n return;\n const errorArgs = args.length === 1 ? args[0] : args;\n if (!global.console)\n return;\n if (typeof console.error === 'function') {\n console.error(errorArgs);\n return;\n }\n console.log(errorArgs);\n}\n//# sourceMappingURL=error.js.map","const toString = Object.prototype.toString;\nconst htmlCharacters = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n};\n// TODO: replace with lodash methods\nexport function trimRight(text) {\n return text.replace(/\\s+$/, '');\n}\nexport function trimLeft(text) {\n return text.replace(/^\\s+/, '');\n}\nexport function trim(text) {\n return text.replace(/^\\s+|\\s+$/g, '');\n}\nexport function isString(obj) {\n return toString.call(obj) === '[object String]';\n}\n/**\n * Turn any string into a regular expression.\n * This can be used to search or replace a string conveniently.\n */\nexport function regexp(str, flags) {\n if (!flags)\n flags = 'g';\n const escapedStr = str.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n return new RegExp(escapedStr, flags);\n}\n/**\n * Escape HTML characters <, > and &\n * Usage: escapeHtml('<div>')\n *\n * @param { String }\n * @param { Boolean } Optional. If true \" and ' will also be escaped.\n * @return { String } Escaped Html you can assign to innerHTML of an element.\n */\n// TODO: replace with npm.im/he\nexport function escapeHtml(s, forAttribute) {\n return s.replace(forAttribute ? /[&<>'\"]/g : /[&<>]/g, function (c) {\n return htmlCharacters[c] || c;\n });\n}\n/**\n * Escape a string the browser way.\n */\nexport function browserEscapeHtml(str) {\n const div = document.createElement('div');\n div.appendChild(document.createTextNode(str));\n return div.innerHTML;\n}\nexport function replaceLast(text, searchValue, replaceValue) {\n if (!text)\n return '';\n text = `${text}`;\n if (!searchValue || replaceValue == null)\n return text;\n const lastOccurrenceIndex = text.lastIndexOf(searchValue);\n if (lastOccurrenceIndex === -1)\n return text;\n return `${text.slice(0, lastOccurrenceIndex)}${replaceValue}${text.slice(lastOccurrenceIndex + searchValue.length)}`;\n}\nexport function endsWithSingleSpace(text) {\n return /\\S+\\s{1}$/.test(text);\n}\n//# sourceMappingURL=string.js.map","import { textNode } from './node-type.js';\n// A DOM node iterator.\n//\n// Has the ability to replace nodes on the fly and continue\n// the iteration.\nexport default class NodeIterator {\n constructor(root, method) {\n this.current = this.previous = this.nextNode = this.root = root;\n this.iteratorFunc = this[method || 'getNext'];\n }\n [Symbol.iterator]() {\n return this;\n }\n getNextTextNode() {\n let next;\n while ((next = this.getNext())) {\n if (next.nodeType === textNode && next.data !== '')\n return next;\n }\n return undefined;\n }\n getPreviousTextNode() {\n let prev;\n while ((prev = this.getPrevious())) {\n if (prev.nodeType === textNode && prev.data !== '')\n return prev;\n }\n return undefined;\n }\n next() {\n const value = this.iteratorFunc();\n return value ? { value } : { done: true, value: undefined };\n }\n getNext() {\n let n = this.current = this.nextNode;\n let child;\n this.nextNode = undefined;\n if (this.current) {\n child = n.firstChild;\n // Skip the children of elements with the attribute data-editable=\"remove\"\n // This prevents text nodes that are not part of the content to be included.\n if (child && n.getAttribute?.('data-editable') !== 'remove') {\n this.nextNode = child;\n }\n else {\n while ((n !== this.root) && n) {\n const nextSibling = n.nextSibling;\n if (nextSibling) {\n this.nextNode = nextSibling;\n break;\n }\n n = n.parentNode;\n }\n }\n }\n return this.current;\n }\n getPrevious() {\n let n = this.current = this.previous;\n let child;\n this.previous = undefined;\n if (this.current) {\n child = n.lastChild;\n // Skip the children of elements with the attribute data-editable=\"remove\"\n // This prevents text nodes that are not part of the content to be included.\n if (child && n.getAttribute?.('data-editable') !== 'remove') {\n this.previous = child;\n }\n else {\n while ((n !== this.root) && n) {\n const prevSibling = n.previousSibling;\n if (prevSibling) {\n this.previous = prevSibling;\n break;\n }\n n = n.parentNode;\n }\n }\n }\n return this.current;\n }\n replaceCurrent(replacement) {\n this.current = replacement;\n this.nextNode = undefined;\n this.previous = undefined;\n let n = this.current;\n while ((n !== this.root) && n) {\n const nextSibling = n.nextSibling;\n if (nextSibling) {\n this.nextNode = nextSibling;\n break;\n }\n n = n.parentNode;\n }\n }\n}\n//# sourceMappingURL=node-iterator.js.map","// DOM node types\n// https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeType\nexport const elementNode = 1;\nexport const attributeNode = 2;\nexport const textNode = 3;\nexport const cdataSectionNode = 4;\nexport const entityReferenceNode = 5;\nexport const entityNode = 6;\nexport const processingInstructionNode = 7;\nexport const commentNode = 8;\nexport const documentNode = 9;\nexport const documentTypeNode = 10;\nexport const documentFragmentNode = 11;\nexport const notationNode = 12;\n//# sourceMappingURL=node-type.js.map","import NodeIterator from '../node-iterator.js';\nimport { textNode } from '../node-type.js';\nexport const domArray = (target, documentOrHost, host) => {\n if (typeof target === 'string') {\n const doc = documentOrHost.querySelectorAll ? documentOrHost : documentOrHost.ownerDocument;\n const container = host || documentOrHost;\n return Array.from(container.querySelectorAll ? container.querySelectorAll(target) : doc.querySelectorAll(target));\n }\n if (target.tagName)\n return [target];\n if (Array.isArray(target))\n return target;\n // Support NodeList and jQuery arrays\n return Array.from(target);\n};\nexport const domSelector = (target, document) => {\n if (typeof target === 'string')\n return document.querySelector(target);\n if (target.tagName)\n return target;\n // Support NodeList and jQuery arrays\n if (target[0])\n return target[0];\n return target;\n};\nexport const createElement = (html, win = window) => {\n const el = win.document.createElement('div');\n el.innerHTML = html;\n return el.firstElementChild;\n};\nexport const closest = (elem, selector) => {\n if (!elem)\n return undefined;\n // For text nodes or other nodes without closest, traverse to parent element\n let currentNode = elem;\n while (currentNode && !currentNode.closest) {\n currentNode = currentNode.parentNode;\n }\n if (currentNode && currentNode.closest) {\n return currentNode.closest(selector);\n }\n return undefined;\n};\nexport const createRange = (win = window) => {\n return win.document.createRange();\n};\nexport const getSelection = (win = window) => {\n const docSelection = win.document.getSelection ? win.document.getSelection() : null;\n if (docSelection)\n return docSelection;\n return win.getSelection ? win.getSelection() : null;\n};\nexport const getNodes = (range, nodeTypes, filterFunc, win = window) => {\n const nodes = [];\n const nodeIterator = win.document.createNodeIterator(range.commonAncestorContainer, NodeFilter.SHOW_ALL, {\n acceptNode(node) {\n if (range.intersectsNode(node) &&\n nodeTypes.includes(node.nodeType) &&\n node !== range.commonAncestorContainer // Exclude the common ancestor container\n ) {\n if (typeof filterFunc === 'function') {\n return filterFunc(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n }\n return NodeFilter.FILTER_ACCEPT;\n }\n return NodeFilter.FILTER_SKIP;\n }\n });\n let currentNode;\n while ((currentNode = nodeIterator.nextNode())) {\n nodes.push(currentNode);\n }\n return nodes;\n};\nexport const normalizeBoundaries = (range) => {\n if (range.startContainer.compareDocumentPosition(range.endContainer) === Node.DOCUMENT_POSITION_FOLLOWING) {\n range.setStartBefore(range.endContainer);\n }\n if (range.endContainer.compareDocumentPosition(range.startContainer) === Node.DOCUMENT_POSITION_PRECEDING) {\n range.setEndAfter(range.startContainer);\n }\n};\nexport const containsRange = (containerRange, testRange) => {\n return (containerRange.compareBoundaryPoints(Range.START_TO_START, testRange) <= 0 &&\n containerRange.compareBoundaryPoints(Range.END_TO_END, testRange) >= 0);\n};\nexport const containsNodeText = (range, node) => {\n const nodeRange = document.createRange();\n nodeRange.selectNodeContents(node);\n const comparisonStart = range.compareBoundaryPoints(Range.START_TO_START, nodeRange);\n const comparisonEnd = range.compareBoundaryPoints(Range.END_TO_END, nodeRange);\n return comparisonStart <= 0 && comparisonEnd >= 0;\n};\nexport const nodeContainsRange = (node, range) => {\n const nodeRange = document.createRange();\n nodeRange.selectNodeContents(node);\n const comparisonStart = range.compareBoundaryPoints(Range.START_TO_START, nodeRange);\n const comparisonEnd = range.compareBoundaryPoints(Range.END_TO_END, nodeRange);\n return comparisonStart >= 0 && comparisonEnd <= 0;\n};\nconst isCharacterDataNode = (node) => {\n return node && (node.nodeType === Node.TEXT_NODE || node.nodeType === Node.COMMENT_NODE);\n};\nconst splitDataNode = (node, offset) => {\n return node.splitText(offset);\n};\nexport const splitBoundaries = (range) => {\n const startContainer = range.startContainer;\n const startOffset = range.startOffset;\n const endContainer = range.endContainer;\n const endOffset = range.endOffset;\n if (isCharacterDataNode(endContainer) && endOffset > 0 && endOffset < endContainer.length) {\n splitDataNode(endContainer, endOffset);\n }\n if (isCharacterDataNode(startContainer) && startOffset > 0 && startOffset < startContainer.length) {\n const newStartContainer = splitDataNode(startContainer, startOffset);\n range.setStart(newStartContainer, 0);\n }\n};\nexport const toCharacterRange = (range, container) => {\n const startRange = range.cloneRange();\n startRange.setStart(container, 0);\n startRange.setEnd(range.startContainer, range.startOffset);\n const rangeText = range.toString();\n const start = startRange.toString().length;\n const end = start + rangeText.length;\n return { start, end, text: rangeText };\n};\nexport const rangesAreEqual = (range1, range2) => {\n return (range1.startContainer === range2.startContainer &&\n range1.startOffset === range2.startOffset &&\n range1.endContainer === range2.endContainer &&\n range1.endOffset === range2.endOffset);\n};\nexport const rangeToHtml = (range, win = window) => {\n const div = win.document.createElement('div');\n div.appendChild(range.cloneContents());\n return div.innerHTML;\n};\nexport const getSelectionCoordinates = (selection) => {\n const range = selection.getRangeAt(0); // Assuming you want coordinates of the first range\n const rects = range.getClientRects();\n const coordinates = [];\n for (let i = 0; i < rects.length; i++) {\n const rect = rects[i];\n coordinates.push({\n top: rect.top,\n left: rect.left,\n bottom: rect.bottom,\n right: rect.right,\n width: rect.width,\n height: rect.height\n });\n }\n return coordinates;\n};\nexport const createRangeFromCharacterRange = (element, actualStartIndex, actualEndIndex) => {\n const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null);\n let currentIndex = 0;\n let startNode = null;\n let endNode = null;\n let startOffset = 0;\n let endOffset = 0;\n while (walker.nextNode()) {\n const node = walker.currentNode;\n const nodeLength = node.nodeValue?.length || 0;\n if (currentIndex + nodeLength <= actualStartIndex) {\n currentIndex += nodeLength;\n continue;\n }\n if (!startNode) {\n startNode = node;\n startOffset = actualStartIndex - currentIndex;\n }\n if (currentIndex + nodeLength >= actualEndIndex) {\n endNode = node;\n endOffset = actualEndIndex - currentIndex;\n break;\n }\n currentIndex += nodeLength;\n }\n if (startNode && endNode) {\n const range = createRange();\n range.setStart(startNode, startOffset);\n range.setEnd(endNode, endOffset);\n return range;\n }\n else {\n throw new Error('Invalid character offsets.');\n }\n};\nexport function findStartExcludingWhitespace({ root, startContainer, startOffset, whitespacesOnTheLeft }) {\n const isTextNode = startContainer.nodeType === textNode;\n if (!isTextNode) {\n return findStartExcludingWhitespace({\n root,\n startContainer: startContainer.childNodes[startOffset],\n startOffset: 0,\n whitespacesOnTheLeft\n });\n }\n const offsetAfterWhitespace = startOffset + whitespacesOnTheLeft;\n if (startContainer.length > offsetAfterWhitespace) {\n return [startContainer, offsetAfterWhitespace];\n }\n // Pass the root so that the iterator can traverse to siblings\n const iterator = new NodeIterator(root);\n // Set the position to the node which is selected\n iterator.nextNode = startContainer;\n // Iterate once to avoid returning self\n iterator.getNextTextNode();\n const container = iterator.getNextTextNode();\n if (!container) {\n // No more text nodes - use the end of the last text node\n const previousTextNode = iterator.getPreviousTextNode();\n if (!previousTextNode)\n throw new Error('No previous text node found');\n return [previousTextNode, previousTextNode.length];\n }\n return findStartExcludingWhitespace({\n root,\n startContainer: container,\n startOffset: 0,\n whitespacesOnTheLeft: offsetAfterWhitespace - startContainer.length\n });\n}\nexport function findEndExcludingWhitespace({ root, endContainer, endOffset, whitespacesOnTheRight }) {\n const isTextNode = endContainer.nodeType === textNode;\n if (!isTextNode) {\n const isFirstNode = !endContainer.childNodes[endOffset - 1];\n const container = isFirstNode\n ? endContainer.childNodes[endOffset]\n : endContainer.childNodes[endOffset - 1];\n let offset = 0;\n if (!isFirstNode) {\n offset = container.nodeType === textNode\n ? container.length\n : container.childNodes.length;\n }\n return findEndExcludingWhitespace({\n root,\n endContainer: container,\n endOffset: offset,\n whitespacesOnTheRight\n });\n }\n const offsetBeforeWhitespace = endOffset - whitespacesOnTheRight;\n if (offsetBeforeWhitespace > 0) {\n return [endContainer, offsetBeforeWhitespace];\n }\n // Pass the root so that the iterator can traverse to siblings\n const iterator = new NodeIterator(root);\n // Set the position to the node which is selected\n iterator.previous = endContainer;\n // Iterate once to avoid returning self\n iterator.getPreviousTextNode();\n const container = iterator.getPreviousTextNode();\n if (!container) {\n // No more text nodes - use the start of the first text node\n const nextNode = iterator.getNextTextNode();\n if (!nextNode)\n throw new Error('No next text node found');\n return [nextNode, 0];\n }\n return findEndExcludingWhitespace({\n root,\n endContainer: container,\n endOffset: container.length,\n whitespacesOnTheRight: whitespacesOnTheRight - endOffset\n });\n}\n//# sourceMappingURL=dom.js.map","import * as string from './util/string.js';\nimport * as nodeType from './node-type.js';\nimport config from './config.js';\nimport { closest } from './util/dom.js';\n/**\n * The parser module provides helper methods to parse html-chunks\n * manipulations and helpers for common tasks.\n * Provides DOM lookup helpers\n *\n * @module core\n * @submodule parser\n */\n/**\n * Get the editableJS host block of a node.\n *\n * @method getHost\n * @param {DOM Node}\n * @return {DOM Node}\n */\nexport function getHost(node) {\n node = (node.jquery ? node[0] : node);\n // Check if the node itself is an editable element\n if (node && node.classList && node.classList.contains(config.editableClass)) {\n return node;\n }\n const result = closest(node, `.${config.editableClass}`);\n if (result)\n return result;\n const contentEditableHost = closest(node, '[contenteditable=\"true\"]');\n return contentEditableHost || null;\n}\n/**\n * Get the index of a node so that\n * parent.childNodes[ getNodeIndex(node) ] would return the node again.\n *\n * @method getNodeIndex\n * @param {HTMLElement}\n */\nexport function getNodeIndex(node) {\n let index = 0;\n let currentNode = node.previousSibling;\n while (currentNode !== null) {\n index++;\n currentNode = currentNode.previousSibling;\n }\n return index;\n}\n/**\n * Check if node contains text or element nodes\n * whitespace counts too!\n *\n * @method isVoid\n * @param {HTMLElement}\n */\nexport function isVoid(node) {\n const childNodes = Array.from(node.childNodes);\n for (const child of childNodes) {\n if (child.nodeType === nodeType.textNode && !isVoidTextNode(child)) {\n return false;\n }\n if (child.nodeType === nodeType.elementNode) {\n return false;\n }\n }\n return true;\n}\n/**\n * Check if node is a text node and completely empty without any whitespace\n *\n * @method isVoidTextNode\n * @param {HTMLElement}\n */\nexport function isVoidTextNode(node) {\n return node.nodeType === nodeType.textNode && !node.nodeValue;\n}\n/**\n * Check if node is a text node and contains nothing but whitespace\n *\n * @method isWhitespaceOnly\n * @param {HTMLElement}\n */\nexport function isWhitespaceOnly(node) {\n return node.nodeType === nodeType.textNode && lastOffsetWithContent(node) === 0;\n}\nexport function isLinebreak(node) {\n return node.nodeType === nodeType.elementNode && node.tagName === 'BR';\n}\n/**\n * Returns the last offset where the cursor can be positioned to\n * be at the visible end of its container.\n * Currently works only for empty text nodes (not empty tags)\n *\n * @method isWhitespaceOnly\n * @param {HTMLElement}\n */\nexport function lastOffsetWithContent(elem) {\n if (elem.nodeType === nodeType.textNode) {\n const nodeValue = elem.nodeValue;\n if (!nodeValue)\n return 0;\n return string.trimRight(nodeValue).length;\n }\n let lastOffset = 0;\n Array.from(elem.childNodes).reverse().every((node, index, nodes) => {\n if (isWhitespaceOnly(node) || isLinebreak(node))\n return true;\n lastOffset = nodes.length - index;\n return false;\n });\n return lastOffset;\n}\nexport function isBeginningOfHost(host, container, offset) {\n if (container === host)\n return isStartOffset(container, offset);\n if (isStartOffset(container, offset)) {\n // The index of the element simulates a range offset\n // right before the element.\n const offsetInParent = getNodeIndex(container);\n const parentNode = container.parentNode;\n if (!parentNode)\n return false;\n return isBeginningOfHost(host, parentNode, offsetInParent);\n }\n return false;\n}\nexport function isEndOfHost(host, container, offset) {\n if (container === host)\n return isEndOffset(container, offset);\n if (isEndOffset(container, offset)) {\n // The index of the element plus one simulates a range offset\n // right after the element.\n const offsetInParent = getNodeIndex(container) + 1;\n const parentNode = container.parentNode;\n if (!parentNode)\n return false;\n return isEndOfHost(host, parentNode, offsetInParent);\n }\n return false;\n}\nexport function isStartOffset(container, offset) {\n if (container.nodeType === nodeType.textNode)\n return offset === 0;\n if (container.childNodes.length === 0)\n return true;\n const firstChild = container.firstChild;\n if (container.childNodes.length === 1 &&\n firstChild &&\n firstChild.nodeType === nodeType.elementNode &&\n firstChild.getAttribute('data-editable') === 'remove')\n return true;\n return container.childNodes[offset] === container.firstChild;\n}\nexport function isEndOffset(container, offset) {\n if (container.nodeType === nodeType.textNode)\n return offset === container.length;\n if (container.childNodes.length === 0)\n return true;\n if (offset > 0)\n return container.childNodes[offset - 1] === container.lastChild;\n return false;\n}\nexport function isTextEndOfHost(host, container, offset) {\n if (container === host)\n return isTextEndOffset(container, offset);\n if (isTextEndOffset(container, offset)) {\n // The index of the element plus one simulates a range offset\n // right after the element.\n const offsetInParent = getNodeIndex(container) + 1;\n const parentNode = container.parentNode;\n if (!parentNode)\n return false;\n return isTextEndOfHost(host, parentNode, offsetInParent);\n }\n return false;\n}\nexport function isTextEndOffset(container, offset) {\n if (container.nodeType === nodeType.textNode) {\n const nodeValue = container.nodeValue;\n if (!nodeValue)\n return offset === 0;\n const text = string.trimRight(nodeValue);\n return offset >= text.length;\n }\n if (container.childNodes.length === 0)\n return true;\n return offset >= lastOffsetWithContent(container);\n}\nexport function isSameNode(target, source) {\n let i, len, attr;\n if (target.nodeType !== source.nodeType)\n return false;\n if (target.nodeName !== source.nodeName)\n return false;\n if (target.nodeType !== 1 || source.nodeType !== 1)\n return true;\n const targetElem = target;\n const sourceElem = source;\n for (i = 0, len = targetElem.attributes.length; i < len; i++) {\n attr = targetElem.attributes[i];\n if (sourceElem.getAttribute(attr.name) !== attr.value)\n return false;\n }\n return true;\n}\n/**\n * Return the deepest last child of a node.\n *\n * @method lastChild\n * @param {HTMLElement} container The container to iterate on.\n * @return {HTMLElement} The deepest last child in the container.\n */\nexport function lastChild(container) {\n return container.lastChild\n ? lastChild(container.lastChild)\n : container;\n}\n/**\n * Obsolete version of {{#crossLink \"lastChild\"}}{{/crossLink}}.\n */\nexport function latestChild(container) {\n console.warn('Editable.js: Using obsolete function parser.latestCild(), use lastChild() instead');\n return lastChild(container);\n}\n/**\n * Checks if a documentFragment has no children.\n * Fragments without children can cause errors if inserted into ranges.\n *\n * @method isDocumentFragmentWithoutChildren\n * @param {HTMLElement} DOM node.\n * @return {Boolean}\n */\nexport function isDocumentFragmentWithoutChildren(fragment) {\n return !!(fragment &&\n fragment.nodeType === nodeType.documentFragmentNode &&\n fragment.childNodes.length === 0);\n}\n/**\n * Determine if an element behaves like an inline element.\n */\nexport function isInlineElement(window, element) {\n const styles = element.currentStyle || window.getComputedStyle(element, '');\n const display = styles.display;\n switch (display) {\n case 'inline':\n case 'inline-block':\n return true;\n default:\n return false;\n }\n}\n//# sourceMappingURL=parser.js.map","import error from './util/error.js';\nimport * as nodeType from './node-type.js';\nimport { createRange, normalizeBoundaries } from './util/dom.js';\n/**\n * Inspired by the Selection save and restore module for Rangy by Tim Down\n * Saves and restores ranges using invisible marker elements in the DOM.\n */\nlet boundaryMarkerId = 0;\n// (U+FEFF) zero width no-break space\nconst markerTextChar = '\\ufeff';\nfunction isSecondChildOfCommonAncestor(range, rangeContainer) {\n const parent = range.commonAncestorContainer;\n if (parent.nodeType === 3)\n return false; // if we are on the text node it can't be a parent\n const possibleChild = rangeContainer.parentElement;\n return possibleChild?.parentElement === parent;\n}\nexport function insertRangeBoundaryMarker(range, atStart) {\n const container = range.commonAncestorContainer;\n // If ownerDocument is null the commonAncestorContainer is window.document\n if (!container.ownerDocument) {\n error('Cannot save range: range is empty');\n throw new Error('Cannot save range: range is empty');\n }\n const ownerDoc = container.ownerDocument;\n if (!ownerDoc.defaultView) {\n error('Cannot save range: document has no defaultView');\n throw new Error('Cannot save range: document has no defaultView');\n }\n // Create the marker element containing a single\n // invisible character using DOM methods and insert it\n const doc = ownerDoc.defaultView.document;\n const markerEl = doc.createElement('span');\n markerEl.id = `editable-range-boundary-${++boundaryMarkerId}`;\n markerEl.setAttribute('data-editable', 'remove');\n markerEl.style.lineHeight = '0';\n markerEl.style.display = 'none';\n markerEl.appendChild(doc.createTextNode(markerTextChar));\n // This logic can expand the selection by inserting the marker before the element\n // of the start or end container. In some cases this prevents breaking up existing tags.\n // The solution is not perfect, but has been here a while.\n // And it is somewhat inconsistent as it check if the container is a second grade child\n // of the common ancestor.\n // It can help to prevent the nuking of e.g. comments when formatting like bold\n // is applied.\n const directlyBeforeFormatTag = atStart && isSecondChildOfCommonAncestor(range, range.startContainer);\n const directlyAfterFormatTag = !atStart && isSecondChildOfCommonAncestor(range, range.endContainer);\n if (directlyBeforeFormatTag) {\n const startParentElem = range.startContainer.parentElement;\n if (startParentElem && startParentElem.parentElement) {\n startParentElem.parentElement.insertBefore(markerEl, startParentElem);\n }\n }\n else if (directlyAfterFormatTag) {\n const endParentElem = range.endContainer.parentElement;\n if (endParentElem && endParentElem.parentElement) {\n endParentElem.parentElement.insertBefore(markerEl, endParentElem.nextSibling);\n }\n }\n else {\n // Clone the Range and collapse to the appropriate boundary point\n const boundaryRange = range.cloneRange();\n boundaryRange.collapse(atStart);\n boundaryRange.insertNode(markerEl);\n }\n return markerEl;\n}\nexport function setRangeBoundary(host, range, markerId, atStart) {\n const markerEl = getMarker(host, markerId);\n if (!markerEl)\n return console.log('Marker element has been removed. Cannot restore selection.');\n range[atStart ? 'setStartBefore' : 'setEndBefore'](markerEl);\n markerEl.remove();\n}\nexport function save(range) {\n let rangeInfo;\n let startEl;\n let endEl;\n // insert markers\n if (range.collapsed) {\n endEl = insertRangeBoundaryMarker(range, false);\n rangeInfo = {\n markerId: endEl.id,\n collapsed: true\n };\n }\n else {\n endEl = insertRangeBoundaryMarker(range, false);\n startEl = insertRangeBoundaryMarker(range, true);\n rangeInfo = {\n startMarkerId: startEl.id,\n endMarkerId: endEl.id,\n collapsed: false\n };\n }\n // Adjust each range's boundaries to lie between its markers\n if (range.collapsed) {\n range.setStartBefore(endEl);\n range.collapse(true);\n }\n else {\n range.setEndBefore(endEl);\n if (startEl) {\n range.setStartAfter(startEl);\n }\n }\n return rangeInfo;\n}\nexport function restore(host, rangeInfo) {\n if (rangeInfo.restored)\n return;\n const range = createRange();\n if (rangeInfo.collapsed) {\n if (!rangeInfo.markerId) {\n console.log('Marker ID is missing. Cannot restore selection.');\n return undefined;\n }\n const markerEl = getMarker(host, rangeInfo.markerId);\n if (markerEl) {\n markerEl.style.display = 'inline';\n const previousNode = markerEl.previousSibling;\n // Workaround for rangy issue 17\n if (previousNode && previousNode.nodeType === nodeType.textNode) {\n markerEl.remove();\n range.setStart(previousNode, previousNode.length);\n }\n else {\n range.setStartBefore(markerEl);\n range.collapse(true);\n markerEl.remove();\n }\n }\n else {\n console.log('Marker element has been removed. Cannot restore selection.');\n }\n }\n else {\n if (rangeInfo.startMarkerId && rangeInfo.endMarkerId) {\n setRangeBoundary(host, range, rangeInfo.startMarkerId, true);\n setRangeBoundary(host, range, rangeInfo.endMarkerId, false);\n }\n else {\n console.log('Marker IDs are missing. Cannot restore selection.');\n return undefined;\n }\n }\n normalizeBoundaries(range);\n return range;\n}\nfunction getMarker(host, id) {\n return host.querySelector(`#${id}`);\n}\n//# sourceMappingURL=range-save-restore.js.map","import * as nodeType from './node-type.js';\nimport * as rangeSaveRestore from './range-save-restore.js';\nimport * as parser from './parser.js';\nimport * as string from './util/string.js';\nimport { createElement, createRange, getNodes, normalizeBoundaries, splitBoundaries, containsNodeText } from './util/dom.js';\nimport config from './config.js';\nfunction restoreRange(host, range, func) {\n const savedRange = rangeSaveRestore.save(range);\n func();\n return rangeSaveRestore.restore(host, savedRange);\n}\nconst zeroWidthSpace = /\\u200B/g;\nconst zeroWidthNonBreakingSpace = /\\uFEFF/g;\nconst whitespaceExceptSpace = /[^\\S ]/g;\nconst everythingWhitespace = /^\\s+$/;\nconst leadingWhitespace = /^\\s+/;\nconst trailingWhitespace = /\\s+$/;\n// Clean up the Html.\nexport function tidyHtml(element) {\n // if (element.normalize) element.normalize()\n normalizeTags(element);\n}\n// Remove empty tags and merge consecutive tags (they must have the same\n// attributes).\n//\n// @method normalizeTags\n// @param {HTMLElement} element The element to process.\nexport function normalizeTags(element) {\n const fragment = document.createDocumentFragment();\n // Remove line breaks at the beginning of a content block\n removeWhitespaces(element, 'firstChild');\n // Remove line breaks at the end of a content block\n removeWhitespaces(element, 'lastChild');\n const nodesToProcess = Array.from(element.childNodes);\n const processedIndices = new Set();\n for (let i = 0; i < nodesToProcess.length; i++) {\n if (processedIndices.has(i))\n continue;\n const node = nodesToProcess[i];\n // skip empty tags, so they'll get removed\n if (node.nodeName !== 'BR' && !node.textContent)\n continue;\n if (node.nodeType === nodeType.elementNode && node.nodeName !== 'BR') {\n // Create a merged node starting with this node\n const mergedNode = node.cloneNode(false);\n // Copy children from the first node\n for (const child of Array.from(node.childNodes)) {\n mergedNode.appendChild(child.cloneNode(true));\n }\n // Merge consecutive same tags\n let j = i + 1;\n while (j < nodesToProcess.length) {\n const sibling = nodesToProcess[j];\n if (!parser.isSameNode(sibling, node))\n break;\n // Copy children from the consecutive sibling\n for (const siblingChild of Array.from(sibling.childNodes)) {\n mergedNode.appendChild(siblingChild.cloneNode(true));\n }\n processedIndices.add(j);\n sibling.remove();\n j++;\n }\n // Recursively normalize the merged node\n normalizeTags(mergedNode);\n fragment.appendChild(mergedNode);\n }\n else {\n fragment.appendChild(node.cloneNode(true));\n }\n }\n while (element.firstChild)\n element.removeChild(element.firstChild);\n element.appendChild(fragment);\n}\nexport function normalizeWhitespace(text) {\n return text.replace(whitespaceExceptSpace, ' ');\n}\n// Clean the element from character, tags, etc... added by the plugin logic.\n//\n// @method cleanInternals\n// @param {HTMLElement} element The element to process.\nexport function cleanInternals(element) {\n // Uses extract content for simplicity. A custom method\n // that does not clone the element could be faster if needed.\n element.innerHTML = extractContent(element, true);\n}\n// Extracts the content from a host element.\n// Does not touch or change the host. Just returns\n// the content and removes elements marked for removal by editable.\n//\n// @param {DOM node or document fragment} Element where to clean out the innerHTML.\n// If you pass a document fragment it will be empty after this call.\n// @param {Boolean} Flag whether to keep ui elements like spellchecking highlights.\n// @returns {String} The cleaned innerHTML of the passed element or document fragment.\nexport function extractContent(element, keepUiElements) {\n if (!element)\n return '';\n const innerHtml = (element.nodeType === nodeType.documentFragmentNode\n ? getInnerHtmlOfFragment(element)\n : element.innerHTML)\n .replace(zeroWidthNonBreakingSpace, '') // Used for forcing inline elements to have a height\n .replace(zeroWidthSpace, '<br>'); // Used for cross-browser newlines\n const clone = document.createElement('div');\n clone.innerHTML = innerHtml;\n unwrapInternalNodes(clone, keepUiElements);\n // Remove line breaks at the beginning of a content block\n removeWhitespaces(clone, 'firstChild');\n // Remove line breaks at the end of a content block\n removeWhitespaces(clone, 'lastChild');\n return clone.innerHTML;\n}\nexport function getInnerHtmlOfFragment(documentFragment) {\n if (!documentFragment || !documentFragment.childNodes) {\n return '';\n }\n const div = document.createElement('div');\n // JSDOM doesn't support appendChild with DocumentFragment directly\n // Clone and append each child instead\n const children = Array.from(documentFragment.childNodes);\n for (const child of children) {\n div.appendChild(child.cloneNode(true));\n }\n return div.innerHTML;\n}\n// Create a document fragment from an html string\n// @param {String} e.g. 'some html <span>text</span>.'\nexport function createFragmentFromString(htmlString) {\n const wrapper = document.createElement('div');\n wrapper.innerHTML = htmlString;\n const fragment = document.createDocumentFragment();\n while (wrapper.firstChild)\n fragment.appendChild(wrapper.firstChild);\n return fragment;\n}\nexport function adoptElement(node, doc) {\n if (typeof node === 'string') {\n // If node is a string (selector), query for it\n const element = doc.querySelector(node);\n if (!element)\n throw new Error(`Element not found: ${node}`);\n return element;\n }\n if (node.ownerDocument !== doc) {\n return doc.adoptNode(node);\n }\n return node;\n}\n// It will return a fragment with the cloned contents of the range\n// without the commonAncestorElement.\n//\n// @param {Range}\n// @return {DocumentFragment}\nexport function cloneRangeContents(range) {\n const rangeFragment = range.cloneContents();\n const parent = rangeFragment.childNodes[0];\n const fragment = document.createDocumentFragment();\n while (parent.childNodes.length)\n fragment.appendChild(parent.childNodes[0]);\n return fragment;\n}\nfunction removeWhitespaces(node, type, firstCall = true) {\n let elem;\n // loop through all children:\n // from left to right if type = 'firstChild',\n // from right to left if type = 'lastChild'\n while ((elem = node[type])) {\n if (elem.nodeType === nodeType.textNode) {\n // Just remove text nodes if they consist only of whitespace\n if (elem.textContent && everythingWhitespace.test(elem.textContent))\n node.removeChild(elem);\n else\n break;\n }\n else if (elem.nodeName === 'BR') {\n elem.remove();\n }\n else {\n // For element nodes (e.g. <strong> tags), we repeat the logic recursively\n // to remove empty text nodes or <br> tags.\n if (elem[type])\n removeWhitespaces(elem, type, false);\n break;\n }\n }\n // Text nodes with leading/trailing whitespace can be trimmed if config allows.\n // We only do it to the outermost text node. Once a text was wrapped in\n // another element, we preserve the whitespace.\n if (!firstCall)\n return;\n elem = node[type];\n if (elem?.nodeType !== nodeType.textNode)\n return;\n // Remove whitespaces at the end or start of a block with content\n // e.g. ' Hello world' > 'Hello World'\n if (config.trimLeadingAndTrailingWhitespaces && elem.textContent) {\n elem.textContent = elem.textContent.replace(type.startsWith('last') ? trailingWhitespace : leadingWhitespace, '');\n }\n}\n// Remove elements that were inserted for internal or user interface purposes\n//\n// @param {DOM node}\n// @param {Boolean} whether to keep ui elements like spellchecking highlights\n// Currently:\n// - Saved ranges\nexport function unwrapInternalNodes(sibling, keepUiElements) {\n while (sibling) {\n const nextSibling = sibling.nextSibling;\n if (sibling.nodeType !== nodeType.elementNode) {\n sibling = nextSibling;\n continue;\n }\n const elem = sibling;\n const attr = elem.getAttribute('data-editable');\n if (elem.firstChild)\n unwrapInternalNodes(elem.firstChild, keepUiElements);\n if (attr === 'remove' || (attr === 'ui-remove' && !keepUiElements)) {\n elem.remove();\n }\n else if (attr === 'unwrap' || (attr === 'ui-unwrap' && !keepUiElements)) {\n unwrap(elem);\n }\n sibling = nextSibling;\n }\n}\n// Get all tags that start or end inside the range\nexport function getTags(host, range, filterFunc) {\n const innerTags = getInnerTags(range, filterFunc);\n const ancestorTags = getAncestorTags(host, range, filterFunc);\n return innerTags.concat(ancestorTags);\n}\n// Get all ancestor tags that start or end inside the range\nexport function getAncestorTags(host, range, filterFunc) {\n const tags = [];\n let node = range.commonAncestorContainer;\n while (node && node !== host) {\n if (!filterFunc || filterFunc(node))\n tags.push(node);\n node = node.parentNode;\n }\n return tags;\n}\nexport function getTagsByName(host, range, tagName) {\n return getTags(host, range, (node) => {\n return node.nodeName.toUpperCase() === tagName.toUpperCase();\n });\n}\nexport function getTagsByNameAndAttributes(host, range, elem) {\n return getTags(host, range, (node) => {\n return node.nodeName.toUpperCase() === elem.nodeName.toUpperCase() &&\n node.nodeType === nodeType.elementNode &&\n areSameAttributes(node.attributes, elem.attributes);\n });\n}\nexport function areSameAttributes(attrs1, attrs2) {\n if (attrs1.length !== attrs2.length)\n return false;\n for (let i = 0; i < attrs1.length; i++) {\n const attr1 = attrs1[i];\n const attr2 = attrs2.getNamedItem(attr1.name);\n if (!attr2 || attr2.value !== attr1.value)\n return false;\n }\n return true;\n}\n// Get all tags that start or end inside the range\nexport function getInnerTags(range, filterFunc) {\n return getNodes(range, [nodeType.elementNode], filterFunc);\n}\n// Get all tags whose text is completely within the current selection.\nexport function getContainedTags(range, filterFunc) {\n return getNodes(range, [nodeType.elementNode], filterFunc)\n .filter(elem => containsNodeText(range, elem));\n}\n// Transform an array of elements into an array\n// of tagnames in uppercase\n//\n// @return example: ['STRONG', 'B']\nexport function getTagNames(elements = []) {\n return elements.map((element) => element.nodeName);\n}\nexport function isAffectedBy(host, range, tagName) {\n return getTags(host, range, null)\n .some((elem) => elem.nodeName === tagName.toUpperCase());\n}\n// select a whole element\nexport function selectNodeContents(element) {\n const range = createRange();\n range.selectNodeContents(element);\n return range;\n}\nfunction intersectsRange(range1, range2) {\n return range1.compareBoundaryPoints(Range.END_TO_START, range2) === -1 &&\n range2.compareBoundaryPoints(Range.END_TO_START, range1) === -1;\n}\n// Check if the range selects all of the elements contents,\n// not less or more.\n//\n// @param visible: Only compare visible text. That way it does not\n// matter if the user selects an additional whitespace or not.\nexport function isExactSelection(range, elem, visible) {\n const elemRange = createRange();\n elemRange.selectNodeContents(elem);\n if (!intersectsRange(range, elemRange))\n return false;\n let rangeText = range.toString();\n let elemText = (elem.jquery ? elem[0] : elem).textContent;\n if (visible) {\n rangeText = string.trim(rangeText);\n elemText = string.trim(elemText);\n }\n return rangeText !== '' && rangeText === elemText;\n}\nexport function expandTo(host, range, elem) {\n range.selectNodeContents(elem);\n return range;\n}\nexport function toggleTag(host, range, elem) {\n const elems = getTagsByNameAndAttributes(host, range, elem);\n if (elems.length === 1 &&\n elems[0].nodeType === nodeType.elementNode &&\n isExactSelection(range, elems[0], true)) {\n const result = removeFormattingElem(host, range, elem);\n if (!result)\n return range;\n return result;\n }\n return forceWrap(host, range, elem);\n}\nexport function isWrappable(range) {\n return canSurroundContents(range);\n}\nexport function forceWrap(host, range, elem) {\n let restoredRange = restoreRange(host, range, () => {\n nukeElem(host, range, elem);\n });\n // remove all tags if the range is not wrappable\n if (!restoredRange || !isWrappable(restoredRange)) {\n if (!restoredRange)\n return range;\n restoredRange = restoreRange(host, restoredRange, () => {\n nuke(host, restoredRange, null);\n });\n if (!restoredRange)\n return range;\n }\n wrap(restoredRange, elem);\n return restoredRange;\n}\nexport function wrap(range, elem) {\n if (!isWrappable(range)) {\n console.log('content.wrap(): can not surround range');\n return;\n }\n let element;\n if (typeof elem === 'string') {\n element = createElement(elem);\n if (!element) {\n console.log('content.wrap(): could not create element');\n return;\n }\n }\n else {\n element = elem;\n }\n range.surroundContents(element);\n}\nexport function unwrap(elem) {\n elem = elem.jquery ? elem[0] : elem;\n const parent = elem.parentNode;\n if (!parent)\n return;\n while (elem.firstChild)\n parent.insertBefore(elem.firstChild, elem);\n parent.removeChild(elem);\n}\nexport function removeFormattingElem(host, range, elem) {\n return restoreRange(host, range, () => {\n nukeElem(host, range, elem);\n });\n}\nexport function removeFormatting(host, range, selector) {\n return restoreRange(host, range, () => {\n nuke(host, range, selector);\n });\n}\n// Unwrap all tags this range is affected by.\n// Can also affect content outside of the range.\nexport function nuke(host, range, selector) {\n getTags(host, range, null).forEach((elem) => {\n if (elem.nodeName.toUpperCase() !== 'BR' && (!selector || elem.matches(selector))) {\n unwrap(elem);\n }\n });\n}\n// Unwrap all tags this range is affected by.\n// Can also affect content outside of the range.\nexport function nukeElem(host, range, node) {\n getTags(host, range, null).forEach((elem) => {\n if (elem.nodeName.toUpperCase() !== 'BR' && (!node ||\n (elem.nodeName.toUpperCase() === node.nodeName.toUpperCase() &&\n areSameAttributes(elem.attributes, node.attributes)))) {\n unwrap(elem);\n }\n });\n}\n// Insert a single character (or string) before or after\n// the range.\nexport function insertCharacter(range, character, atStart) {\n const insertEl = document.createTextNode(character);\n const boundaryRange = range.cloneRange();\n boundaryRange.collapse(atStart);\n boundaryRange.insertNode(insertEl);\n range[atStart ? 'setStartBefore' : 'setEndAfter'](insertEl);\n normalizeBoundaries(range);\n}\n// Surround the range with characters like start and end quotes.\n//\n// @method surround\nexport function surround(host, range, startCharacter, endCharacter) {\n insertCharacter(range, endCharacter || startCharacter, false);\n insertCharacter(range, startCharacter, true);\n return range;\n}\n// Removes a character from the text within a range.\n//\n// @method deleteCharacter\nexport function deleteCharacter(host, range, character) {\n if (!containsString(range, character))\n return range;\n // check for selection.rangeCount > 0 ?\n const selection = window.getSelection();\n if (selection && selection.rangeCount > 0)\n splitBoundaries(range);\n const restoredRange = restoreRange(host, range, () => {\n getNodes(range, [nodeType.textNode], (node) => {\n return node.nodeValue !== null && node.nodeValue.indexOf(character) >= 0;\n })\n .forEach((node) => {\n const textNode = node;\n if (textNode.nodeValue) {\n // Use replace with global regex instead of replaceAll for better compatibility\n textNode.nodeValue = textNode.nodeValue.replace(new RegExp(character.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'), '');\n }\n });\n });\n if (restoredRange) {\n normalizeBoundaries(restoredRange);\n return restoredRange;\n }\n return range;\n}\nexport function containsString(range, str) {\n return range.toString().indexOf(str) >= 0;\n}\n// Unwrap all tags this range is affected by.\n// Can also affect content outside of the range.\nexport function nukeTag(host, range, tagName) {\n getTags(host, range, null).forEach((elem) => {\n if (elem.nodeName.toUpperCase() === tagName.toUpperCase())\n unwrap(elem);\n });\n}\nfunction createNodeIterator(root, filter) {\n let currentNode = root;\n let previousNode = null;\n function nextNode() {\n if (!currentNode) {\n return null;\n }\n if (currentNode.firstChild && previousNode !== currentNode.firstChild) {\n previousNode = currentNode;\n currentNode = currentNode.firstChild;\n }\n else if (currentNode.nextSibling) {\n previousNode = currentNode;\n currentNode = currentNode.nextSibling;\n }\n else {\n let parent = currentNode.parentNode;\n while (parent && parent !== root) {\n if (parent.nextSibling) {\n previousNode = currentNode = parent.nextSibling;\n break;\n }\n parent = parent.parentNode;\n }\n if (!parent || parent === root) {\n previousNode = currentNode = null;\n }\n }\n return currentNode;\n }\n return {\n next: nextNode\n };\n}\nfunction isNodeFullyContained(node, range) {\n const nodeRange = document.createRange();\n nodeRange.selectNodeContents(node);\n return range.compareBoundaryPoints(Range.START_TO_START, nodeRange) <= 0 &&\n range.compareBoundaryPoints(Range.END_TO_END, nodeRange) >= 0;\n}\nfunction canSurroundContents(range) {\n if (!range || !range.startContainer || !range.endContainer) {\n return false;\n }\n if (range.startContainer === range.endContainer)\n return true;\n // Create a custom node iterator for the common ancestor container\n const iterator = createNodeIterator(range.commonAncestorContainer, function (node) {\n return range.isPointInRange(node, 0);\n });\n let currentNode;\n let boundariesInvalid = false;\n while ((currentNode = iterator.next())) {\n if (currentNode.nodeType === Node.ELEMENT_NODE) {\n if (!isNodeFullyContained(currentNode, range)) {\n boundariesInvalid = true;\n break;\n }\n }\n }\n return !boundariesInvalid;\n}\n//# sourceMappingURL=content.js.map","import config from './config.js';\nimport * as content from './content.js';\nlet nextBlockId = 1;\nconst state = {};\nexport const next = getSibling('nextElementSibling');\nexport const previous = getSibling('previousElementSibling');\nexport function init(elem, { normalize, plainText, shouldSpellcheck } = {}) {\n setBlockId(elem);\n elem.setAttribute('contenteditable', 'true');\n elem.setAttribute('spellcheck', String(Boolean(shouldSpellcheck)));\n elem.setAttribute('data-plaintext', String(Boolean(plainText)));\n elem.classList.remove(config.editableDisabledClass);\n elem.classList.add(config.editableClass);\n if (normalize)\n content.tidyHtml(elem);\n}\nexport function disable(elem) {\n elem.removeAttribute('contenteditable');\n elem.removeAttribute('spellcheck');\n elem.removeAttribute('data-plaintext');\n setState(elem, undefined);\n elem.classList.remove(config.editableClass);\n elem.classList.add(config.editableDisabledClass);\n}\nexport function isPlainTextBlock(elem) {\n return elem.getAttribute('data-plaintext') === 'true';\n}\nexport function setBlockId(elem) {\n if (!elem.hasAttribute('data-editable')) {\n elem.setAttribute('data-editable', `id-${nextBlockId}`);\n nextBlockId += 1;\n }\n}\nexport function getState(elem) {\n if (elem.hasAttribute('data-editable')) {\n const id = elem.getAttribute('data-editable');\n if (id)\n return state[id];\n }\n}\nexport function setState(elem, data) {\n if (elem.hasAttribute('data-editable')) {\n const id = elem.getAttribute('data-editable');\n if (id)\n state[id] = data;\n }\n}\n// Helpers\n// -------\nfunction getSibling(type) {\n return function (element) {\n const sibling = element[type];\n return sibling && sibling.getAttribute('contenteditable')\n ? sibling\n : null;\n };\n}\n//# sourceMappingURL=block.js.map","const doubleQuotePairs = [\n ['«', '»'], // ch german, french\n ['»', '«'], // danish\n ['\"', '\"'], // danish, not specified\n ['“', '”'], // english US\n ['”', '”'], // swedish\n ['“', '“'], // chinese simplified\n ['„', '“'] // german\n];\nconst singleQuotePairs = [\n ['‘', '’'], // english UK\n ['‹', '›'], // ch german, french\n ['‚', '‘'], // german\n ['’', '’'], // swedish\n ['›', '‹'], // danish\n [`'`, `'`], // danish, not specified\n [`‘`, `’`] // chinese simplified\n];\nconst apostrophe = [\n '’', // german\n `'` // default\n];\nconst quotesRegex = /([‘’‹›‚'«»\"“”„])(?![^<]*?>)/g;\n// whitespace end of tag, or any dash (normal, en or em-dash)\n// or any opening double quote\nconst beforeOpeningQuote = /\\s|[>\\-–—«»”\"“„]/;\n// whitespace begin of tag, or any dash (normal, en or em-dash)\n// or any closing quote, or any punctuation\nconst afterClosingQuote = /\\s|[<\\-–—«»”\"“‘’‹›'.;?:,]/;\nlet replacements;\nexport function replaceAllQuotes(str, replaceQuotesRules) {\n replacements = replaceQuotesRules || {};\n replacements.quotes = replacements.quotes || [undefined, undefined];\n replacements.singleQuotes = replacements.singleQuotes || [undefined, undefined];\n const matches = getAllQuotes(str);\n if (matches.length > 0) {\n replaceMatchedQuotes(matches, 0);\n return replaceExistingQuotes(str, matches);\n }\n return str;\n}\nfunction replaceMatchedQuotes(matches, position) {\n while (position < matches.length) {\n const closingTag = findClosingQuote(matches, position);\n if (closingTag) {\n matches[position].replace = closingTag.type === 'double'\n ? replacements.quotes?.[0]\n : replacements.singleQuotes?.[0];\n matches[closingTag.position].replace = closingTag.type === 'double'\n ? replacements.quotes?.[1]\n : replacements.singleQuotes?.[1];\n if (closingTag.position !== position + 1) {\n const nestedMatches = matches.slice(position + 1, closingTag.position);\n if (nestedMatches && nestedMatches.length > 0) {\n replaceMatchedQuotes(nestedMatches, 0);\n }\n }\n position = closingTag.position + 1;\n }\n else {\n matches[position].replace = replaceApostrophe(matches[position].char);\n position += 1;\n }\n }\n}\nfunction findClosingQuote(matches, position) {\n if (position === matches.length - 1)\n return undefined;\n const current = matches[position];\n const openingQuote = current.char;\n if (current.before && !beforeOpeningQuote.test(current.before))\n return undefined;\n const possibleClosingSingleQuotes = getPossibleClosingQuotes(openingQuote, singleQuotePairs);\n const possibleClosingDoubleQuotes = getPossibleClosingQuotes(openingQuote, doubleQuotePairs);\n // Also allow straight quotes as potential closers when we have quote pairs (they can be converted)\n // But only for the same quote type (straight double quote for double quotes, straight single quote for single quotes)\n let allPossibleDoubleClosers = possibleClosingDoubleQuotes;\n let allPossibleSingleClosers = possibleClosingSingleQuotes;\n const hasStraightQuoteFallback = (possibleClosingDoubleQuotes.length > 0 && !possibleClosingDoubleQuotes.includes('\"')) ||\n (possibleClosingSingleQuotes.length > 0 && !possibleClosingSingleQuotes.includes(\"'\"));\n // Only add straight double quote if this is a double quote type (has double quote pairs defined)\n if (possibleClosingDoubleQuotes.length > 0 && !possibleClosingDoubleQuotes.includes('\"')) {\n allPossibleDoubleClosers = [...possibleClosingDoubleQuotes, '\"'];\n }\n // Only add straight single quote if this is a single quote type (has single quote pairs defined)\n if (possibleClosingSingleQuotes.length > 0 && !possibleClosingSingleQuotes.includes(\"'\")) {\n allPossibleSingleClosers = [...possibleClosingSingleQuotes, \"'\"];\n }\n // Check if opening quote is itself a straight quote - if so, prefer outermost match\n const isStraightQuote = openingQuote === '\"' || openingQuote === \"'\";\n // Prefer exact pair matches over straight quote fallbacks\n // For straight quote fallbacks or straight quotes themselves, prefer outermost match to avoid incorrect nested matching\n let bestStraightQuoteMatch;\n for (let i = position + 1; i < matches.length; i++) {\n const candidateChar = matches[i].char;\n const candidateAfter = matches[i].after;\n const passesAfterCheck = (candidateAfter && afterClosingQuote.test(candidateAfter)) || !candidateAfter;\n if (passesAfterCheck) {\n if (allPossibleSingleClosers.includes(candidateChar)) {\n // Check if this is an exact pair match (not a straight quote fallback)\n const isExactMatch = possibleClosingSingleQuotes.includes(candidateChar);\n // For straight quotes themselves, always prefer outermost match\n if (isExactMatch && !isStraightQuote) {\n // Return immediately for exact pair matches (except for straight quotes)\n return { position: i, type: 'single' };\n }\n // For straight quote fallbacks or straight quotes themselves, continue searching for the outermost match\n if (hasStraightQuoteFallback || isStraightQuote) {\n if (!bestStraightQuoteMatch || (bestStraightQuoteMatch.type === 'single' && i > bestStraightQuoteMatch.position)) {\n bestStraightQuoteMatch = { position: i, type: 'single' };\n }\n }\n else {\n return { position: i, type: 'single' };\n }\n }\n if (allPossibleDoubleClosers.includes(candidateChar)) {\n // Check if this is an exact pair match (not a straight quote fallback)\n const isExactMatch = possibleClosingDoubleQuotes.includes(candidateChar);\n // For straight quotes themselves, always prefer outermost match\n if (isExactMatch && !isStraightQuote) {\n // Return immediately for exact pair matches (except for straight quotes)\n return { position: i, type: 'double' };\n }\n // For straight quote fallbacks or straight quotes themselves, continue searching for the outermost match\n if (hasStraightQuoteFallback || isStraightQuote) {\n if (!bestStraightQuoteMatch || (bestStraightQuoteMatch.type === 'double' && i > bestStraightQuoteMatch.position)) {\n bestStraightQuoteMatch = { position: i, type: 'double' };\n }\n }\n else {\n return { position: i, type: 'double' };\n }\n }\n }\n }\n // Return the outermost straight quote match if we found one\n if (bestStraightQuoteMatch) {\n return bestStraightQuoteMatch;\n }\n return undefined;\n}\nfunction getPossibleClosingQuotes(openingQuote, pairs) {\n return pairs.filter((quotePair) => quotePair[0] === openingQuote).map((quotePair) => quotePair[1]);\n}\nfunction replaceApostrophe(quote) {\n if (apostrophe.includes(quote)) {\n return replacements.apostrophe;\n }\n return undefined;\n}\nfunction getAllQuotes(str) {\n return [...str.matchAll(quotesRegex)].map((match) => {\n const index = match.index;\n return {\n char: match[1],\n before: index > 0 ? str[index - 1] : '',\n after: (index + 1) < str.length ? str[index + 1] : ''\n };\n });\n}\nfunction replaceExistingQuotes(str, matches) {\n let index = 0;\n return str.replace(quotesRegex, (match) => {\n const replacement = matches[index].replace || matches[index].char;\n index += 1;\n return replacement;\n });\n}\n//# sourceMappingURL=quotes.js.map","import config from './config.js';\nimport * as string from './util/string.js';\nimport * as nodeType from './node-type.js';\nimport * as quotes from './quotes.js';\nimport { isPlainTextBlock } from './block.js';\nlet allowedElements;\nlet allowedPlainTextElements;\nlet requiredAttributes;\nlet transformElements;\nlet blockLevelElements;\nlet replaceQuotes;\nlet splitIntoBlocks;\nlet blacklistedElements;\nconst whitespaceOnly = /^\\s*$/;\nconst blockPlaceholder = '<!-- BLOCK -->';\nlet keepInternalRelativeLinks;\nupdateConfig(config);\nexport function updateConfig(conf) {\n const rules = conf.pastedHtmlRules;\n allowedElements = rules.allowedElements || {};\n allowedPlainTextElements = rules.allowedPlainTextElements || {};\n requiredAttributes = rules.requiredAttributes || {};\n transformElements = rules.transformElements || {};\n blacklistedElements = rules.blacklistedElements || [];\n keepInternalRelativeLinks = rules.keepInternalRelativeLinks || false;\n replaceQuotes = rules.replaceQuotes || {};\n blockLevelElements = {};\n rules.blockLevelElements.forEach((name) => { blockLevelElements[name] = true; });\n splitIntoBlocks = {};\n rules.splitIntoBlocks.forEach((name) => { splitIntoBlocks[name] = true; });\n}\nexport function paste(block, cursor, clipboardContent) {\n const document = block.ownerDocument;\n block.setAttribute(config.pastingAttribute, 'true');\n if (cursor.isSelection) {\n const selection = cursor;\n cursor = selection.deleteExactSurroundingTags()\n .deleteContainedTags()\n .deleteContent();\n }\n // Create a placeholder to help parse HTML\n const pasteHolder = document.createElement('div');\n pasteHolder.innerHTML = clipboardContent;\n const isPlainText = isPlainTextBlock(block);\n const blocks = parseContent(pasteHolder, { plainText: isPlainText });\n block.removeAttribute(config.pastingAttribute);\n return { blocks, cursor };\n}\n/**\n * - Parse pasted content\n * - Split it up into blocks\n * - clean and normalize every block\n * - optionally strip the host location an anchorTag-href\n * www.livindocs.io/internalLink -> /internalLink\n *\n * @param {DOM node} A container where the pasted content is located.\n * @returns {Array of Strings} An array of cleaned innerHTML like strings.\n */\nexport function parseContent(element, { plainText = false } = {}) {\n const options = {\n allowedElements: plainText ? allowedPlainTextElements : allowedElements,\n keepInternalRelativeLinks: plainText ? false : keepInternalRelativeLinks\n };\n // Filter pasted content\n return filterHtmlElements(element, options)\n // Handle Blocks\n .split(blockPlaceholder)\n .map((entry) => string.trim(cleanWhitespace(replaceAllQuotes(entry))))\n .filter((entry) => !whitespaceOnly.test(entry));\n}\nfunction filterHtmlElements(elem, options) {\n return Array.from(elem.childNodes).reduce((content, child) => {\n if (blacklistedElements.indexOf(child.nodeName.toLowerCase()) !== -1) {\n return '';\n }\n const childElement = child;\n // Keep internal relative links relative (on paste).\n if (options.keepInternalRelativeLinks && childElement.nodeName === 'A' && childElement.href) {\n const hrefAttr = childElement.getAttribute('href');\n if (hrefAttr) {\n const stripInternalHost = hrefAttr.replace(window.location.origin, '');\n childElement.setAttribute('href', stripInternalHost);\n }\n }\n if (child.nodeType === nodeType.elementNode) {\n const childContent = filterHtmlElements(childElement, options);\n return content + conditionalNodeWrap(childElement, childContent, options);\n }\n // Escape HTML characters <, > and &\n if (child.nodeType === nodeType.textNode) {\n return content + string.escapeHtml(child.nodeValue || '');\n }\n return content;\n }, '');\n}\nfunction conditionalNodeWrap(child, content, options) {\n let nodeName = child.nodeName.toLowerCase();\n nodeName = transformNodeName(nodeName);\n if (shouldKeepNode(nodeName, child, options)) {\n const attributes = filterAttributes(nodeName, child);\n if (nodeName === 'br')\n return `<${nodeName + attributes}>`;\n if (!whitespaceOnly.test(content)) {\n return `<${nodeName + attributes}>${content}</${nodeName}>`;\n }\n return content;\n }\n if (splitIntoBlocks[nodeName]) {\n return blockPlaceholder + content + blockPlaceholder;\n }\n // prevent missing whitespace between text when block-level\n // elements are removed.\n if (blockLevelElements[nodeName])\n return `${content} `;\n return content;\n}\n// returns string of concatenated attributes e.g. 'target=\"_blank\" rel=\"nofollow\" href=\"/test.com\"'\nfunction filterAttributes(nodeName, node) {\n return Array.from(node.attributes).reduce((attributes, attr) => {\n const name = attr.name;\n const value = attr.value;\n if (allowedElements[nodeName]?.[name] && value) {\n return `${attributes} ${name}=\"${value}\"`;\n }\n return attributes;\n }, '');\n}\nfunction transformNodeName(nodeName) {\n return transformElements[nodeName] || nodeName;\n}\nfunction hasRequiredAttributes(nodeName, node) {\n const requiredAttrs = requiredAttributes[nodeName];\n if (!requiredAttrs)\n return true;\n return !requiredAttrs.some((name) => !node.getAttribute(name));\n}\nfunction shouldKeepNode(nodeName, node, options) {\n return !!options.allowedElements[nodeName] && hasRequiredAttributes(nodeName, node);\n}\nfunction cleanWhitespace(str) {\n return str\n .replace(/\\n/g, ' ')\n .replace(/ {2,}/g, ' ')\n .replace(/(.)\\u00A0/g, (match, group) => group + (/[\\u0020]/.test(group)\n ? '\\u00A0'\n : ' '));\n}\nfunction replaceAllQuotes(str) {\n if (replaceQuotes.quotes || replaceQuotes.singleQuotes || replaceQuotes.apostrophe) {\n return quotes.replaceAllQuotes(str, replaceQuotes);\n }\n return str;\n}\n//# sourceMappingURL=clipboard.js.map","/**\n* Check for contenteditable support\n*\n* (from Modernizr)\n* this is known to false positive in some mobile browsers\n* here is a whitelist of verified working browsers:\n* https://github.com/NielsLeenheer/html5test/blob/549f6eac866aa861d9649a0707ff2c0157895706/scripts/engine.js#L2083\n*/\nexport const contenteditable = typeof document.documentElement.contentEditable !== 'undefined';\n// Detect webkit browser engine\n// That way we can detect the contenteditable span bug on safari, but exclude chrome\n// Regex taken from: https://github.com/lancedikson/bowser/blob/f09411489ced05811c91cc6670a8e4ca9cbe39a7/src/parser-engines.js#L93-L106\n// Attention, this might be error prone as any engine version change breaks this.\nconst isBlink = /(apple)?webkit\\/537\\.36/i.test(window.navigator.userAgent);\nconst isWebkit = /(apple)?webkit/i.test(window.navigator.userAgent);\nconst webKit = !isBlink && isWebkit;\n/**\n * Check selectionchange event (supported in IE, Chrome, Firefox and Safari)\n * Firefox supports it since version 52 (2017).\n * Opera has no support as of 2021.\n */\nconst hasNativeSelectionchangeSupport = (document) => {\n const doc = document;\n const osc = doc.onselectionchange;\n if (osc !== undefined) {\n try {\n doc.onselectionchange = 0;\n return doc.onselectionchange === null;\n }\n catch (e) {\n // ignore\n }\n finally {\n doc.onselectionchange = osc;\n }\n }\n return false;\n};\nexport const selectionchange = hasNativeSelectionchangeSupport(document);\n// See Keyboard.prototype.preventContenteditableBug for more information.\nexport const contenteditableSpanBug = !!webKit;\n//# sourceMappingURL=feature-detection.js.map","// Eventable Mixin.\n//\n// Simple mixin to add event emitter methods to an object (Publish/Subscribe).\n//\n// Add on, off and notify methods to an object:\n// eventable(obj)\n//\n// publish an event:\n// obj.notify(context, 'action', param1, param2)\n//\n// Optionally pass a context that will be applied to every event:\n// eventable(obj, context)\n//\n// With this publishing can omit the context argument:\n// obj.notify('action', param1, param2)\n//\n// Subscribe to a 'channel'\n// obj.on('action', funtion(param1, param2){ ... })\n//\n// Unsubscribe an individual listener:\n// obj.off('action', method)\n//\n// Unsubscribe all listeners of a channel:\n// obj.off('action')\n//\n// Unsubscribe all listeners of all channels:\n// obj.off()\nexport default function eventable(obj, notifyContext) {\n const events = getEventableModule(notifyContext);\n obj.on = events.on;\n obj.off = events.off;\n obj.notify = events.notify;\n}\nfunction getEventableModule(notifyContext) {\n const listeners = {};\n function addListener(events, listener) {\n events.split(' ').forEach(event => {\n listeners[event] = listeners[event] || [];\n listeners[event].unshift(listener);\n });\n }\n function removeListener(event, listener) {\n const eventListeners = listeners[event];\n if (!eventListeners)\n return;\n const index = eventListeners.indexOf(listener);\n if (index < 0)\n return;\n eventListeners.splice(index, 1);\n }\n // Public Methods\n const result = {\n on(eventOrEvents, listener) {\n if (arguments.length === 2 && typeof eventOrEvents === 'string') {\n addListener(eventOrEvents, listener);\n }\n else if (arguments.length === 1 && typeof eventOrEvents === 'object') {\n for (const eventType in eventOrEvents)\n addListener(eventType, eventOrEvents[eventType]);\n }\n return result;\n },\n off(event, listener) {\n if (arguments.length === 2) {\n removeListener(event, listener);\n }\n else if (arguments.length === 1) {\n listeners[event] = [];\n }\n else {\n Object.keys(listeners).forEach(key => delete listeners[key]);\n }\n },\n notify(context, event, ...args) {\n const allArgs = Array.from(arguments);\n let actualContext;\n let actualEvent;\n let actualArgs;\n if (notifyContext) {\n actualEvent = context;\n actualContext = notifyContext;\n actualArgs = allArgs.slice(1);\n }\n else {\n actualContext = context;\n actualEvent = event;\n actualArgs = allArgs.slice(2);\n }\n if (result.switchContext) {\n const nextEvent = result.switchContext.events.shift();\n if (actualEvent !== nextEvent)\n result.switchContext = undefined;\n }\n const eventListeners = listeners[actualEvent];\n if (!eventListeners)\n return;\n // Execute the newest listeners first.\n // Stop if a listener returns false.\n eventListeners.every((listener) => listener.apply(actualContext, actualArgs) !== false);\n }\n };\n return result;\n}\n//# sourceMappingURL=eventable.js.map","// code from mdn: https://developer.mozilla.org/en-US/docs/Web/API/window.scrollX\nfunction getScrollPosition(win) {\n const x = (win.pageXOffset !== undefined) ? win.pageXOffset : (win.document.documentElement || win.document.body.parentNode || win.document.body).scrollLeft;\n const y = (win.pageYOffset !== undefined) ? win.pageYOffset : (win.document.documentElement || win.document.body.parentNode || win.document.body).scrollTop;\n return { x, y };\n}\nexport { getScrollPosition };\n//# sourceMappingURL=viewport.js.map","import * as viewport from './util/viewport.js';\nimport * as content from './content.js';\nimport * as parser from './parser.js';\nimport * as string from './util/string.js';\nimport { elementNode, documentFragmentNode } from './node-type.js';\nimport error from './util/error.js';\nimport * as rangeSaveRestore from './range-save-restore.js';\nimport { closest, getSelection, rangesAreEqual } from './util/dom.js';\n/**\n * The Cursor module provides a cross-browser abstraction layer for cursor.\n *\n * @module core\n * @submodule cursor\n */\nexport default class Cursor {\n static findHost(elem, selector) {\n return closest(elem, selector);\n }\n /**\n * Class for the Cursor module.\n *\n * @class Cursor\n * @constructor\n */\n constructor(editableHost, range) {\n this.setHost(editableHost);\n this.range = range;\n this.isCursor = true;\n }\n // Get all tags that affect the current selection. Optionally pass a\n // method to filter the returned elements.\n //\n // @param {Function filter(node)} [Optional] Method to filter the returned\n // DOM Nodes.\n // @return {Array of DOM Nodes}\n getTags(filterFunc) {\n return content.getTags(this.host, this.range, filterFunc);\n }\n // Get the names of all tags that affect the current selection. Optionally\n // pass a method to filter the returned elements.\n //\n // @param {Function filter(node)} [Optional] Method to filter the DOM\n // Nodes whose names are returned.\n // @return {Array<String> of tag names}\n getTagNames(filterFunc) {\n const tags = this.getTags(filterFunc);\n return content.getTagNames(tags);\n }\n // Get all tags of the specified type that affect the current selection.\n //\n // @method getTagsByName\n // @param {String} tagName. E.g. 'a' to get all links.\n // @return {Array of DOM Nodes}\n getTagsByName(tagName) {\n return content.getTagsByName(this.host, this.range, tagName);\n }\n // Get all tags that are completely within the current selection.\n getInnerTags(filterFunc) {\n return content.getInnerTags(this.range, filterFunc);\n }\n // Get all tags whose text is completely within the current selection.\n getContainedTags(filterFunc) {\n return content.getContainedTags(this.range, filterFunc);\n }\n // Get all tags that surround the current selection.\n getAncestorTags(filterFunc) {\n return content.getAncestorTags(this.host, this.range, filterFunc);\n }\n isAtEnd() {\n return parser.isEndOfHost(this.host, this.range.endContainer, this.range.endOffset);\n }\n isAtTextEnd() {\n return parser.isTextEndOfHost(this.host, this.range.endContainer, this.range.endOffset);\n }\n isAtLastLine() {\n const hostRange = this.win.document.createRange();\n hostRange.selectNodeContents(this.host);\n hostRange.collapse(false);\n const hostCoords = getRangeBoundingClientRect(hostRange, this.win);\n const cursorCoords = getRangeBoundingClientRect(this.range, this.win);\n return isCloseTo(hostCoords.bottom, cursorCoords.bottom);\n }\n isAtFirstLine() {\n const hostRange = this.win.document.createRange();\n hostRange.selectNodeContents(this.host);\n hostRange.collapse(true);\n const hostCoords = getRangeBoundingClientRect(hostRange, this.win);\n const cursorCoords = getRangeBoundingClientRect(this.range, this.win);\n return isCloseTo(hostCoords.top, cursorCoords.top);\n }\n isAtBeginning() {\n return parser.isBeginningOfHost(this.host, this.range.startContainer, this.range.startOffset);\n }\n // Insert content before the cursor\n //\n // @param {String, DOM node or document fragment}\n insertBefore(element) {\n if (string.isString(element))\n element = content.createFragmentFromString(element);\n if (parser.isDocumentFragmentWithoutChildren(element))\n return;\n element = this.adoptElement(element);\n let preceedingElement = element;\n if (element.nodeType === documentFragmentNode) {\n const lastIndex = element.childNodes.length - 1;\n preceedingElement = element.childNodes[lastIndex];\n }\n this.range.insertNode(element);\n this.range.setStartAfter(preceedingElement);\n this.range.setEndAfter(preceedingElement);\n this.host.normalize(); // mend text nodes\n }\n // Insert content after the cursor\n //\n // @param {String, DOM node or document fragment}\n insertAfter(element) {\n if (string.isString(element))\n element = content.createFragmentFromString(element);\n if (parser.isDocumentFragmentWithoutChildren(element))\n return;\n element = this.adoptElement(element);\n const after = this.range.cloneRange();\n after.setStart(after.endContainer, after.endOffset);\n after.collapse(true);\n after.insertNode(element);\n this.host.normalize(); // mend text nodes\n }\n // Alias for #setVisibleSelection()\n setSelection() {\n this.setVisibleSelection();\n }\n setVisibleSelection() {\n if (this.win.document.activeElement !== this.host) {\n const { x, y } = viewport.getScrollPosition(this.win);\n this.win.scrollTo(x, y);\n }\n const selection = getSelection(this.win);\n if (!selection)\n return;\n selection.removeAllRanges();\n selection.addRange(this.range);\n }\n // Take the following example:\n // (The character '|' represents the cursor position)\n //\n // <div contenteditable=\"true\">fo|o</div>\n // before() will return a document fragment containing a text node 'fo'.\n //\n // @returns {Document Fragment} content before the cursor or selection.\n before() {\n const range = this.range.cloneRange();\n range.collapse(true);\n range.setStartBefore(this.host);\n return content.cloneRangeContents(range);\n }\n textBefore() {\n const range = this.range.cloneRange();\n range.collapse(true);\n range.setStartBefore(this.host);\n return range.toString();\n }\n // Same as before() but returns a string.\n beforeHtml() {\n return content.getInnerHtmlOfFragment(this.before());\n }\n // Take the following example:\n // (The character '|' represents the cursor position)\n //\n // <div contenteditable=\"true\">fo|o</div>\n // after() will return a document fragment containing a text node 'o'.\n //\n // @returns {Document Fragment} content after the cursor or selection.\n after() {\n const range = this.range.cloneRange();\n range.collapse(false);\n range.setEndAfter(this.host);\n return content.cloneRangeContents(range);\n }\n textAfter() {\n const range = this.range.cloneRange();\n range.collapse(false);\n range.setEndAfter(this.host);\n return range.toString();\n }\n // Same as after() but returns a string.\n afterHtml() {\n return content.getInnerHtmlOfFragment(this.after());\n }\n getBoundingClientRect() {\n return this.range.getBoundingClientRect();\n }\n // Get the BoundingClientRect of the cursor.\n // The returned values are transformed to be absolute\n // (relative to the document).\n getCoordinates(positioning = 'absolute') {\n const coords = this.range.getBoundingClientRect();\n if (positioning === 'fixed')\n return coords;\n // translate into absolute positions\n const { x, y } = viewport.getScrollPosition(this.win);\n return {\n top: coords.top + y,\n bottom: coords.bottom + y,\n left: coords.left + x,\n right: coords.right + x,\n height: coords.height,\n width: coords.width\n };\n }\n moveBefore(element) {\n this.updateHost(element);\n this.range.setStartBefore(element);\n this.range.setEndBefore(element);\n if (this.isSelection)\n return new Cursor(this.host, this.range);\n }\n moveAfter(element) {\n this.updateHost(element);\n this.range.setEndAfter(element);\n this.range.setStartAfter(element);\n if (this.isSelection)\n return new Cursor(this.host, this.range);\n }\n // Move the cursor to the beginning of the host.\n moveAtBeginning(element = this.host) {\n this.updateHost(element);\n this.range.selectNodeContents(element);\n this.range.collapse(true);\n if (this.isSelection)\n return new Cursor(this.host, this.range);\n }\n // Move the cursor to the end of the host.\n moveAtEnd(element = this.host) {\n this.updateHost(element);\n this.range.selectNodeContents(element);\n this.range.collapse(false);\n if (this.isSelection)\n return new Cursor(this.host, this.range);\n }\n // Move the cursor after the last visible character of the host.\n moveAtTextEnd(element) {\n const lastChild = parser.lastChild(element);\n if (lastChild && lastChild.nodeType === elementNode) {\n return this.moveAtEnd(lastChild);\n }\n }\n setHost(element) {\n if (element.jquery)\n element = element[0];\n this.host = element;\n const doc = element.ownerDocument;\n this.win = (element === undefined || element === null || !doc) ? window : (doc.defaultView || window);\n }\n updateHost(element) {\n const host = parser.getHost(element);\n if (!host)\n error('Can not set cursor outside of an editable block');\n this.setHost(host);\n }\n retainVisibleSelection(callback) {\n this.save();\n callback(); // eslint-disable-line callback-return\n this.restore();\n this.setVisibleSelection();\n }\n save() {\n this.savedRangeInfo = rangeSaveRestore.save(this.range);\n this.savedRangeInfo.host = this.host;\n }\n restore() {\n if (!this.savedRangeInfo) {\n error('Could not restore selection');\n return;\n }\n if (this.savedRangeInfo.host) {\n this.host = this.savedRangeInfo.host;\n }\n const restoredRange = rangeSaveRestore.restore(this.host, this.savedRangeInfo);\n if (!restoredRange) {\n error('Could not restore selection range');\n return;\n }\n this.range = restoredRange;\n this.savedRangeInfo = undefined;\n }\n equals(cursor) {\n if (!cursor)\n return false;\n if (!cursor.host)\n return false;\n if (!cursor.host.isEqualNode(this.host))\n return false;\n if (!cursor.range)\n return false;\n if (!rangesAreEqual(cursor.range, this.range))\n return false;\n return true;\n }\n // Create an element with the correct ownerWindow\n // (see: http://www.w3.org/DOM/faq.html#ownerdoc)\n createElement(tagName, attributes = {}) {\n const element = this.win.document.createElement(tagName);\n for (const attributeName in attributes) {\n const attributeValue = attributes[attributeName];\n element.setAttribute(attributeName, attributeValue);\n }\n return element;\n }\n createTextNode(text) {\n return this.win.document.createTextNode(text);\n }\n // Make sure a node has the correct ownerWindow\n // (see: https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode)\n adoptElement(node) {\n return content.adoptElement(node, this.win.document);\n }\n // Currently we call triggerChange manually after format changes.\n // This is to prevent excessive triggering of the change event during\n // merge or split operations or other manipulations by scripts.\n triggerChange() {\n const event = new Event('formatEditable', { bubbles: true, cancelable: false });\n this.host.dispatchEvent(event);\n }\n}\n/**\n* Get position of the range or cursor\n*\n* Can be used to reliably get the boundingClientRect without\n* some any of the drawbacks that the native range has.\n*\n* With the native range.getClientBoundingRect(), newlines are\n* not considered when calculating the position\n*\n* @param {Range} range\n* @param {Window} win\n*/\nfunction getRangeBoundingClientRect(range, win) {\n if (range.startContainer.nodeType !== elementNode)\n return range.getBoundingClientRect();\n const el = win.document.createElement('span');\n el.setAttribute('doc-editable', 'unwrap');\n range.insertNode(el);\n const coords = el.getBoundingClientRect();\n el.remove();\n return coords;\n}\nfunction isCloseTo(a, b) {\n if (a === b)\n return true;\n if (Math.abs(a - b) <= 2)\n return true;\n return false;\n}\n//# sourceMappingURL=cursor.js.map","import NodeIterator from './node-iterator.js';\nimport * as nodeType from './node-type.js';\nimport { createRange } from './util/dom.js';\nexport default {\n // Get the text from an editable block with a NodeIterator.\n // This must work the same as when later iterating over the text\n // in highlightMatches().\n extractText(element, convertBRs = true) {\n let text = '';\n getText(element, convertBRs, (part) => { text += part; });\n return text;\n },\n // Go through the element to highlight the matches while keeping the\n // existing html valid (highlighting a match may require inserting multiple\n // elements).\n //\n // @params\n // - matches\n // Array of positions in the string to highlight:\n // e.g [{\n // startIndex: 0,\n // endIndex: 1,\n // match: 'The', // not used, only the indexes are used for highlighting)\n // marker: DOMNode, // A clone of this element will be inserted\n // id: 'a7382', // used in word-id attribute\n // title: 'The World' // used in title attribute (optional)\n // }]\n highlightMatches(element, matches, countBRs = true) {\n if (!matches || matches.length === 0) {\n return;\n }\n element.normalize(); // mend text nodes\n const iterator = new NodeIterator(element);\n let currentMatchIndex = 0;\n let totalOffset = 0;\n let currentMatch = matches[currentMatchIndex];\n let portions = [];\n let next;\n let wordId = currentMatch.id || currentMatch.startIndex;\n let textNode;\n while ((next = iterator.getNext())) {\n // Account for <br> elements\n if (next.nodeType === nodeType.textNode && next.data !== '') {\n textNode = next;\n }\n else if (countBRs && next.nodeType === nodeType.elementNode && next.nodeName === 'BR') {\n totalOffset += 1;\n continue;\n }\n else {\n continue;\n }\n if (!textNode)\n continue;\n const nodeText = textNode.data;\n let nodeEndOffset = totalOffset + nodeText.length;\n if (currentMatch.startIndex < nodeEndOffset && totalOffset < currentMatch.endIndex) {\n // get portion position (fist, last or in the middle)\n const isFirstPortion = totalOffset <= currentMatch.startIndex;\n const isLastPortion = nodeEndOffset >= currentMatch.endIndex;\n if (isFirstPortion) {\n wordId = currentMatch.id || currentMatch.startIndex;\n }\n // calculate offset and length\n let offset;\n if (isFirstPortion) {\n offset = currentMatch.startIndex - totalOffset;\n }\n else {\n offset = 0;\n }\n let length;\n if (isLastPortion) {\n length = (currentMatch.endIndex - totalOffset) - offset;\n }\n else {\n length = nodeText.length - offset;\n }\n // create portion object\n const portion = {\n element: textNode,\n text: nodeText.substring(offset, offset + length),\n offset,\n length,\n isLastPortion,\n wordId\n };\n portions.push(portion);\n if (isLastPortion) {\n const lastNode = this.wrapMatch(portions, currentMatch.marker, currentMatch.title);\n if (lastNode) {\n iterator.replaceCurrent(lastNode);\n // recalculate nodeEndOffset if we have to replace the current node.\n nodeEndOffset = totalOffset + portion.length + portion.offset;\n portions = [];\n currentMatchIndex += 1;\n if (currentMatchIndex < matches.length) {\n currentMatch = matches[currentMatchIndex];\n }\n }\n }\n }\n totalOffset = nodeEndOffset;\n }\n },\n // @return the last wrapped element\n wrapMatch(portions, stencilElement, title) {\n return portions.map((portion) => this.wrapPortion(portion, stencilElement, title)).pop();\n },\n wrapPortion(portion, stencilElement, title) {\n const range = createRange();\n range.setStart(portion.element, portion.offset);\n range.setEnd(portion.element, portion.offset + portion.length);\n const node = stencilElement.cloneNode(true);\n node.setAttribute('data-word-id', String(portion.wordId));\n if (title)\n node.setAttribute('title', title);\n range.surroundContents(node);\n // Fix a weird behaviour where an empty text node is inserted after the range\n if (node.nextSibling) {\n const next = node.nextSibling;\n if (next.nodeType === nodeType.textNode && next.data === '') {\n next.remove();\n }\n }\n return node;\n }\n};\n// Extract the text of an element.\n// This has two notable behaviours:\n// - It uses a NodeIterator which will skip elements\n// with data-editable=\"remove\"\n// - It returns a \\n for <br> elements\n// (The only block level element allowed inside of editables)\nfunction getText(element, convertBRs, func) {\n const iterator = new NodeIterator(element);\n let next;\n while ((next = iterator.getNext())) {\n if (next.nodeType === nodeType.textNode && next.data !== '') {\n func(next.data);\n }\n else if (convertBRs && next.nodeType === nodeType.elementNode && next.nodeName === 'BR') {\n func('\\n');\n }\n }\n}\n//# sourceMappingURL=highlight-text.js.map","export function searchText(text, searchTerm, marker) {\n const matchMode = 'text';\n return findMatches(text, [searchTerm], matchMode, marker);\n}\nexport function searchWord(text, word, marker) {\n const matchMode = 'word';\n return findMatches(text, [word], matchMode, marker);\n}\nexport function searchAllWords(text, words, marker) {\n const matchMode = 'word';\n return findMatches(text, words, matchMode, marker);\n}\nfunction findMatches(text, searchTexts, matchMode, marker) {\n if (!text || text === '')\n return [];\n if (marker && !isElement(marker))\n return [];\n if (!searchTexts?.length)\n return [];\n const createRegex = matchMode === 'word'\n ? createWordRegex\n : createHighlightRegex;\n const regex = createRegex(searchTexts);\n const matches = [...text.matchAll(regex)];\n return matches.map((match) => {\n let startIndex;\n let matchedText;\n if (matchMode === 'word') {\n startIndex = match.index + match[1].length;\n matchedText = match[2];\n }\n else {\n startIndex = match.index;\n matchedText = match[0];\n }\n return {\n startIndex,\n endIndex: startIndex + matchedText.length,\n match: matchedText,\n marker\n };\n });\n}\nfunction isElement(obj) {\n try {\n if (!obj)\n return false;\n return obj instanceof obj.ownerDocument?.defaultView.HTMLElement;\n }\n catch (e) {\n // Browsers not supporting W3 DOM2 don't have HTMLElement and\n // an exception is thrown and we end up here. Testing some\n // properties that all elements have (works on IE7)\n return (typeof obj === 'object') &&\n (obj.nodeType === 1) && (typeof obj.style === 'object') &&\n (typeof obj.ownerDocument === 'object');\n }\n}\nfunction createHighlightRegex(words = []) {\n const escapedWords = words.map((word) => escapeRegEx(word));\n const regex = `(${escapedWords.join('|')})`;\n return new RegExp(regex, 'g');\n}\n// Regex to find whole words within a string\n//\n// Unicode character blocks for letters.\n// See: http://jrgraphix.net/research/unicode_blocks.php\n//\n// \\\\u0041-\\\\u005A A-Z (Basic Latin)\n// \\\\u0061-\\\\u007A a-z (Basic Latin)\n// \\\\u0030-\\\\u0039 0-9 (Basic Latin)\n// \\\\u00AA ª (Latin-1 Supplement)\n// \\\\u00B5 µ (Latin-1 Supplement)\n// \\\\u00BA º (Latin-1 Supplement)\n// \\\\u00C0-\\\\u00D6 À-Ö (Latin-1 Supplement)\n// \\\\u00D8-\\\\u00F6 Ø-ö (Latin-1 Supplement)\n// \\\\u00F8-\\\\u00FF ø-ÿ (Latin-1 Supplement)\n// \\\\u0100-\\\\u017F Ā-ſ (Latin Extended-A)\n// \\\\u0180-\\\\u024F ƀ-ɏ (Latin Extended-B)\nconst letterChars = '\\\\u0041-\\\\u005A\\\\u0061-\\\\u007A\\\\u0030-\\\\u0039\\\\u00AA\\\\u00B5\\\\u00BA\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u00FF\\\\u0100-\\\\u017F\\\\u0180-\\\\u024F';\nfunction createWordRegex(words = []) {\n const escapedWords = words.map((word) => escapeRegEx(word));\n // (notLetter|^)(words)(?=notLetter|$)\n const regex = `([^${letterChars}]|^)` +\n `(${escapedWords.join('|')})` +\n `(?=[^${letterChars}]|$)`;\n return new RegExp(regex, 'g');\n}\nfunction escapeRegEx(s) {\n return String(s).replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1');\n}\n//# sourceMappingURL=text-search.js.map","import * as content from './content.js';\nimport highlightText from './highlight-text.js';\nimport { searchText } from './plugins/highlighting/text-search.js';\nimport { createElement, createRange, toCharacterRange } from './util/dom.js';\nconst highlightSupport = {\n // Used to highlight arbitrary text in an editable. All occurrences\n // will be highlighted.\n highlightText(editableHost, text, highlightId, type, dispatcher, win) {\n if (this.hasHighlight(editableHost, highlightId))\n return;\n const blockText = highlightText.extractText(editableHost);\n const marker = `<span class=\"highlight-${type}\"></span>`;\n let winWindow = win;\n if (!winWindow) {\n const doc = editableHost.ownerDocument || (typeof document !== 'undefined' ? document : null);\n winWindow = doc?.defaultView || undefined;\n }\n if (!winWindow) {\n winWindow = (typeof window !== 'undefined' && window.document ? window : undefined);\n }\n if (!winWindow) {\n throw new Error('Could not determine window object for highlightText');\n }\n const markerNode = highlightSupport.createMarkerNode(marker, type, winWindow);\n if (!markerNode)\n return undefined;\n const matches = searchText(blockText, text, markerNode);\n if (matches && matches.length) {\n const match = matches[0];\n if (highlightId)\n match.id = highlightId;\n highlightText.highlightMatches(editableHost, matches);\n if (dispatcher)\n dispatcher.notify('change', editableHost);\n return match.startIndex;\n }\n return undefined;\n },\n // Used to highlight comments.\n // This function was changed to track matches when text is added to the start\n // of a component, but multiple white spaces break it in a strict sense\n // The function works in the editor and in browsers, but tests with\n // multiple white spaces will fail.\n // Browsers change the white spaces to   and the function works,\n // and the tests in highlight.spec.js have been updated to represent this.\n highlightRange(editableHost, text, highlightId, startIndex, endIndex, dispatcher, win, type = 'comment') {\n if (this.hasHighlight(editableHost, highlightId)) {\n this.removeHighlight(editableHost, highlightId, dispatcher);\n }\n const blockText = highlightText.extractText(editableHost, false);\n if (blockText === '')\n return -1; // the text was deleted so we can't highlight anything\n let winWindow = win;\n if (!winWindow) {\n const doc = editableHost.ownerDocument || (typeof document !== 'undefined' ? document : null);\n winWindow = doc?.defaultView || undefined;\n }\n if (!winWindow) {\n winWindow = (typeof window !== 'undefined' && window.document ? window : undefined);\n }\n if (!winWindow) {\n throw new Error('Could not determine window object for highlightRange');\n }\n const marker = this.createMarkerNode(`<span class=\"highlight-${type}\"></span>`, type, winWindow);\n if (!marker)\n return -1;\n const actualStartIndex = startIndex;\n const actualEndIndex = endIndex;\n highlightText.highlightMatches(editableHost, [{\n startIndex: actualStartIndex,\n endIndex: actualEndIndex,\n match: text.substring(actualStartIndex, actualEndIndex),\n id: highlightId,\n marker\n }], false);\n if (dispatcher)\n dispatcher.notify('change', editableHost);\n return actualStartIndex;\n },\n updateHighlight(editableHost, highlightId, addCssClass, removeCssClass) {\n if (!document.documentElement.classList)\n return;\n const elems = editableHost.querySelectorAll(`[data-word-id=\"${highlightId}\"]`);\n for (const elem of Array.from(elems)) {\n if (removeCssClass)\n elem.classList.remove(removeCssClass);\n if (addCssClass)\n elem.classList.add(addCssClass);\n }\n },\n removeHighlight(editableHost, highlightId, dispatcher) {\n const elems = editableHost.querySelectorAll(`[data-word-id=\"${highlightId}\"]`);\n for (const elem of Array.from(elems)) {\n content.unwrap(elem);\n }\n // remove empty text nodes, combine adjacent text nodes\n editableHost.normalize();\n if (dispatcher)\n dispatcher.notify('change', editableHost);\n },\n hasHighlight(editableHost, highlightId) {\n const matches = editableHost.querySelectorAll(`[data-word-id=\"${highlightId}\"]`);\n return !!matches.length;\n },\n extractHighlightedRanges(editableHost, type) {\n let findMarkersQuery = '[data-word-id]';\n if (type)\n findMarkersQuery += `[data-highlight=\"${type}\"]`;\n const markers = editableHost.querySelectorAll(findMarkersQuery);\n if (!markers.length)\n return undefined;\n const groups = {};\n for (const marker of Array.from(markers)) {\n const highlightId = marker.getAttribute('data-word-id');\n if (highlightId && !groups[highlightId]) {\n groups[highlightId] = editableHost.querySelectorAll(`[data-word-id=\"${highlightId}\"]`);\n }\n }\n const res = {};\n for (const highlightId in groups) {\n const position = this.extractMarkerNodePosition(editableHost, groups[highlightId]);\n if (position)\n res[highlightId] = position;\n }\n return res;\n },\n extractMarkerNodePosition(editableHost, markers) {\n if (markers.length === 0)\n return undefined;\n const range = createRange();\n if (markers.length > 1) {\n range.setStartBefore(markers[0]);\n range.setEndAfter(markers[markers.length - 1]);\n }\n else {\n range.selectNode(markers[0]);\n }\n const textRange = toCharacterRange(range, editableHost);\n return {\n start: textRange.start,\n end: textRange.end,\n text: textRange.text, // browser range result (does whitespace normalization)\n nativeRange: range\n };\n },\n cleanupStaleMarkerNodes(editableHost, highlightType) {\n const nodes = editableHost.querySelectorAll(`span[data-highlight=\"${highlightType}\"]`);\n for (const node of Array.from(nodes)) {\n if (!node.textContent || !node.textContent.length) {\n node.remove();\n }\n }\n },\n createMarkerNode(markerMarkup, highlightType, win) {\n let winWindow = win || null;\n if (!winWindow) {\n // Try to get window from global scope\n winWindow = (typeof window !== 'undefined' && window.document ? window : null);\n }\n if (!winWindow || !winWindow.document) {\n throw new Error(`Window object with document is required. win: ${typeof win}, window: ${typeof window}`);\n }\n const marker = createElement(markerMarkup, winWindow);\n if (!marker)\n return null;\n marker.setAttribute('data-editable', 'ui-unwrap');\n marker.setAttribute('data-highlight', highlightType);\n return marker;\n }\n};\nexport default highlightSupport;\n//# sourceMappingURL=highlight-support.js.map","import Cursor from './cursor.js';\nimport * as content from './content.js';\nimport * as parser from './parser.js';\nimport * as block from './block.js';\nimport config from './config.js';\nimport highlightSupport from './highlight-support.js';\nimport highlightText from './highlight-text.js';\nimport { toCharacterRange, rangeToHtml, findStartExcludingWhitespace, findEndExcludingWhitespace } from './util/dom.js';\n/**\n * The Selection module provides a cross-browser abstraction layer for range\n * and selection.\n *\n * @module core\n * @submodule selection\n */\n/**\n * Class that represents a selection and provides functionality to access or\n * modify the selection.\n *\n * @class Selection\n * @constructor\n */\nexport default class Selection extends Cursor {\n constructor(editableHost, range) {\n super(editableHost, range);\n delete this.isCursor;\n this.isSelection = true;\n }\n // Get the text inside the selection.\n text() {\n return this.range.toString();\n }\n // Get the html inside the selection.\n html() {\n return rangeToHtml(this.range);\n }\n isAllSelected() {\n return parser.isBeginningOfHost(this.host, this.range.startContainer, this.range.startOffset) && parser.isTextEndOfHost(this.host, this.range.endContainer, this.range.endOffset);\n }\n getTextRange() {\n return toCharacterRange(this.range, this.host);\n }\n // Return a plain string of the current selection content.\n toString() {\n return this.range.toString();\n }\n // Return true if the selection can be wrapped, i.e. all open nodes\n // are closed within this selection.\n isWrappable() {\n return content.isWrappable(this.range);\n }\n // Get the ClientRects of this selection.\n // Use this if you want more precision than getBoundingClientRect can give.\n getRects() {\n // consider: translate into absolute positions\n // just like Cursor#getCoordinates()\n return this.range.getClientRects();\n }\n link(href, attrs = {}) {\n if (href)\n attrs.href = href;\n const link = this.createElement(config.linkMarkup.name, config.linkMarkup.attribs);\n for (const key in attrs) {\n const value = attrs[key];\n if (value === undefined)\n continue;\n if (value === null) {\n link.removeAttribute(key);\n }\n else {\n link.setAttribute(key, value);\n }\n }\n if (config.linkMarkup.trim)\n this.trimRange();\n this.forceWrap(link);\n }\n // trims whitespaces on the left and right of a selection, i.e. what you want in case of links\n trimRange() {\n const textToTrim = this.range.toString();\n const whitespacesOnTheLeft = textToTrim.search(/\\S|$/);\n const lastNonWhitespace = textToTrim.search(/\\S[\\s]+$/);\n const whitespacesOnTheRight = lastNonWhitespace === -1\n ? 0\n : textToTrim.length - (lastNonWhitespace + 1);\n const [startContainer, startOffset] = findStartExcludingWhitespace({\n root: this.range.commonAncestorContainer,\n startContainer: this.range.startContainer,\n startOffset: this.range.startOffset,\n whitespacesOnTheLeft\n });\n this.range.setStart(startContainer, startOffset);\n const [endContainer, endOffset] = findEndExcludingWhitespace({\n root: this.range.commonAncestorContainer,\n endContainer: this.range.endContainer,\n endOffset: this.range.endOffset,\n whitespacesOnTheRight\n });\n this.range.setEnd(endContainer, endOffset);\n }\n unlink() {\n this.removeFormatting(config.linkMarkup.name);\n }\n toggleLink(href, attrs = {}) {\n const links = this.getTagsByName(config.linkMarkup.name);\n if (links.length >= 1) {\n const firstLink = links[0];\n if (this.isExactSelection(firstLink, 'visible')) {\n this.unlink();\n }\n else {\n this.expandTo(firstLink);\n }\n }\n else {\n this.link(href, attrs);\n }\n }\n highlightComment({ highlightId, textRange }) {\n highlightSupport.highlightRange(this.host, textRange.text, highlightId, textRange.start, textRange.end, undefined, // dispatcher\n this.win, 'comment');\n }\n // Manually add a highlight\n // Note: the current code does not work with newlines (LP)\n highlight({ highlightId }) {\n const textBefore = this.textBefore();\n const currentTextContent = this.text();\n const marker = '<span class=\"highlight-comment\"></span>';\n const markerNode = highlightSupport.createMarkerNode(marker, 'comment', this.win);\n if (!markerNode)\n return;\n markerNode.setAttribute('data-match', currentTextContent);\n const match = {\n startIndex: textBefore.length,\n endIndex: textBefore.length + currentTextContent.length,\n match: currentTextContent,\n marker: markerNode\n };\n // Note: highlighting won't retain the selection\n highlightText.highlightMatches(this.host, [match]);\n }\n // e.g. toggle('<em>')\n toggle(elem) {\n if (block.isPlainTextBlock(this.host))\n return;\n if (this.range.collapsed)\n return;\n elem = this.adoptElement(elem);\n const newRange = content.toggleTag(this.host, this.range, elem);\n if (newRange) {\n this.range = newRange;\n this.setVisibleSelection();\n }\n }\n toggleCustom({ tagName, attributes, trim = false }) {\n const customElem = this.createElement(tagName, attributes);\n if (trim)\n this.trimRange();\n this.toggle(customElem);\n }\n makeCustom({ tagName, attributes, trim = false }) {\n const customElem = this.createElement(tagName, attributes);\n if (trim)\n this.trimRange();\n this.forceWrap(customElem);\n }\n makeBold() {\n const bold = this.createElement(config.boldMarkup.name, config.boldMarkup.attribs);\n if (config.boldMarkup.trim)\n this.trimRange();\n this.forceWrap(bold);\n }\n toggleBold() {\n const bold = this.createElement(config.boldMarkup.name, config.boldMarkup.attribs);\n if (config.boldMarkup.trim)\n this.trimRange();\n this.toggle(bold);\n }\n giveEmphasis() {\n const em = this.createElement(config.italicMarkup.name, config.italicMarkup.attribs);\n if (config.italicMarkup.trim)\n this.trimRange();\n this.forceWrap(em);\n }\n toggleEmphasis() {\n const em = this.createElement(config.italicMarkup.name, config.italicMarkup.attribs);\n if (config.italicMarkup.trim)\n this.trimRange();\n this.toggle(em);\n }\n makeUnderline() {\n const u = this.createElement(config.underlineMarkup.name, config.underlineMarkup.attribs);\n if (config.underlineMarkup.trim)\n this.trimRange();\n this.forceWrap(u);\n }\n toggleUnderline() {\n const u = this.createElement(config.underlineMarkup.name, config.underlineMarkup.attribs);\n if (config.underlineMarkup.trim)\n this.trimRange();\n this.toggle(u);\n }\n insertCharacter(character) {\n const cursor = this.deleteContent();\n const textNode = cursor.createTextNode(character);\n cursor.insertBefore(textNode);\n cursor.setVisibleSelection();\n return cursor;\n }\n // Surround the selection with characters like quotes.\n //\n // @param {String} E.g. '«'\n // @param {String} E.g. '»'\n surround(startCharacter, endCharacter) {\n this.range = content.surround(this.host, this.range, startCharacter, endCharacter);\n this.setVisibleSelection();\n }\n removeSurround(startCharacter, endCharacter) {\n this.range = content.deleteCharacter(this.host, this.range, startCharacter);\n this.range = content.deleteCharacter(this.host, this.range, endCharacter);\n this.setVisibleSelection();\n }\n removeChars(chars = []) {\n for (let i = 0; i < chars.length; i++) {\n const char = chars[i];\n this.range = content.deleteCharacter(this.host, this.range, char);\n }\n this.setVisibleSelection();\n }\n toggleSurround(startCharacter, endCharacter) {\n if (this.containsString(startCharacter) &&\n this.containsString(endCharacter)) {\n this.removeSurround(startCharacter, endCharacter);\n }\n else {\n this.surround(startCharacter, endCharacter);\n }\n }\n // @param {String} selector. An element selector, e.g. 'a' or 'span.some-class'\n // that represents elements to be removed; if undefined,\n // remove all.\n removeFormatting(selector) {\n const newRange = content.removeFormatting(this.host, this.range, selector || null);\n if (newRange) {\n this.range = newRange;\n this.setVisibleSelection();\n }\n }\n // Delete the farest ancestor that is an exact selection\n //\n // @return Selection instance\n deleteExactSurroundingTags() {\n const ancestorTags = this.getAncestorTags().reverse();\n for (const ancestorTag of ancestorTags) {\n if (this.isExactSelection(ancestorTag, undefined)) {\n ancestorTag.remove();\n break;\n }\n }\n return new Selection(this.host, this.range);\n }\n // Delete all the tags whose text is completely within the current selection.\n //\n // @return Selection instance\n deleteContainedTags() {\n const containedTags = this.getContainedTags();\n containedTags.forEach(containedTag => containedTag.remove());\n return new Selection(this.host, this.range);\n }\n // Delete the contents inside the range and exact surrounding markups.\n // After that the selection will be a cursor.\n //\n // @return Cursor instance\n deleteContent() {\n this.range.deleteContents();\n return new Cursor(this.host, this.range);\n }\n // Expand the current selection.\n //\n // @param {DOM Node}\n expandTo(elem) {\n this.range = content.expandTo(this.host, this.range, elem);\n this.setVisibleSelection();\n }\n // Collapse the selection at the beginning of the selection\n //\n // @return Cursor instance\n collapseAtBeginning(elem) {\n this.range.collapse(true);\n this.setVisibleSelection();\n return new Cursor(this.host, this.range);\n }\n // Collapse the selection at the end of the selection\n //\n // @return Cursor instance\n collapseAtEnd(elem) {\n this.range.collapse(false);\n this.setVisibleSelection();\n return new Cursor(this.host, this.range);\n }\n // Wrap the selection with the specified tag. If any other tag with\n // the same tagName is affecting the selection this tag will be\n // remove first.\n forceWrap(elem) {\n if (block.isPlainTextBlock(this.host))\n return;\n if (this.range.collapsed)\n return;\n elem = this.adoptElement(elem);\n const newRange = content.forceWrap(this.host, this.range, elem);\n if (newRange) {\n this.range = newRange;\n this.setVisibleSelection();\n }\n }\n // Check if the selection is the same as the elements contents.\n //\n // @method isExactSelection\n // @param {DOM Node}\n // @param {flag: undefined or 'visible'} if 'visible' is passed\n // whitespaces at the beginning or end of the selection will\n // be ignored.\n // @return {Boolean}\n isExactSelection(elem, onlyVisible) {\n return content.isExactSelection(this.range, elem, onlyVisible === 'visible');\n }\n // Check if the selection contains the passed string.\n //\n // @method containsString\n // @return {Boolean}\n containsString(str) {\n return content.containsString(this.range, str);\n }\n // Delete all occurrences of the specified character from the\n // selection.\n deleteCharacter(character) {\n this.range = content.deleteCharacter(this.host, this.range, character);\n this.setVisibleSelection();\n }\n}\n//# sourceMappingURL=selection.js.map","import Cursor from './cursor.js';\nimport Selection from './selection.js';\nimport { rangesAreEqual } from './util/dom.js';\n/** RangeContainer\n *\n * primarily used to compare ranges\n * its designed to work with undefined ranges as well\n * so we can easily compare them without checking for undefined\n * all the time\n */\nexport default class RangeContainer {\n constructor(editableHost, range) {\n this.host = editableHost && editableHost.jquery\n ? editableHost[0]\n : editableHost;\n // Safari 17 seems to modify the range instance on the fly which breaks later comparisons.\n // We clone the range at the time of the RangeContainer creation.\n // https://developer.apple.com/documentation/safari-release-notes/safari-17-release-notes#New-Features\n this.range = range?.cloneRange();\n this.isAnythingSelected = (range !== undefined);\n this.isCursor = (this.isAnythingSelected && range.collapsed);\n this.isSelection = (this.isAnythingSelected && !this.isCursor);\n }\n getCursor() {\n if (this.isCursor && this.host && this.range)\n return new Cursor(this.host, this.range);\n return undefined;\n }\n getSelection() {\n if (this.isSelection && this.host && this.range)\n return new Selection(this.host, this.range);\n return undefined;\n }\n forceCursor() {\n if (!this.isSelection)\n return this.getCursor();\n const selection = this.getSelection();\n if (selection)\n return selection.deleteContent();\n return undefined;\n }\n isDifferentFrom(otherRangeContainer = new RangeContainer()) {\n const self = this.range;\n const other = otherRangeContainer.range;\n if (self && other)\n return !rangesAreEqual(self, other);\n if (!self && other)\n return false;\n return true;\n }\n}\n//# sourceMappingURL=range-container.js.map","import * as parser from './parser.js';\nimport RangeContainer from './range-container.js';\nimport Cursor from './cursor.js';\nimport Selection from './selection.js';\nimport { getSelection } from './util/dom.js';\n/**\n * The SelectionWatcher module watches for selection changes inside\n * of editable blocks.\n *\n * @module core\n * @submodule selectionWatcher\n */\nexport default class SelectionWatcher {\n constructor(dispatcher, win) {\n this.dispatcher = dispatcher;\n this.win = win || window;\n this.selection = undefined;\n this.currentSelection = undefined;\n this.currentRange = undefined;\n }\n /**\n * Updates the internal selection pointer to the current selection.\n * Returns true if no exception occurred.\n */\n syncSelection() {\n // Note: the try catch was introduced because of rangy exceptions with nativeSelections\n try {\n this.selection = getSelection(this.win);\n }\n catch (err) {\n return false;\n }\n return true;\n }\n /**\n * Return a RangeContainer if the current selection is within an editable\n * otherwise return an empty RangeContainer\n */\n getRangeContainer() {\n const successfulSync = this.syncSelection();\n // rangeCount is 0 or 1 in all browsers except firefox\n // firefox can work with multiple ranges\n // (on a mac hold down the command key to select multiple ranges)\n if (this.selection?.rangeCount && successfulSync) {\n try {\n const range = this.selection.getRangeAt(0);\n // Check if range is still valid (not detached)\n if (range && range.commonAncestorContainer) {\n const hostNode = parser.getHost(range.commonAncestorContainer);\n if (hostNode)\n return new RangeContainer(hostNode, range);\n }\n }\n catch (err) {\n // Range might be detached, return empty container\n }\n }\n // return an empty range container\n return new RangeContainer();\n }\n /**\n * Gets a fresh RangeContainer with the current selection or cursor.\n *\n * @return RangeContainer instance\n */\n getFreshRange() {\n return this.getRangeContainer();\n }\n /**\n * Gets a fresh RangeContainer with the current selection or cursor.\n *\n * @return Either a Cursor or Selection instance or undefined if\n * there is neither a selection or cursor.\n */\n getFreshSelection() {\n const rangeContainer = this.getRangeContainer();\n return rangeContainer.isCursor\n ? rangeContainer.getCursor()\n : rangeContainer.getSelection();\n }\n /**\n * Get the selection set by the last selectionChanged event.\n * Sometimes the event does not fire fast enough and the selection\n * you get is not the one the user sees.\n * In those cases use #getFreshSelection()\n *\n * @return Either a Cursor or Selection instance or undefined if\n * there is neither a selection or cursor.\n */\n getSelection() {\n return this.currentSelection;\n }\n forceCursor() {\n const rangeContainer = this.getRangeContainer();\n return rangeContainer.forceCursor();\n }\n selectionChanged() {\n const newRangeContainer = this.getRangeContainer();\n if (newRangeContainer.isDifferentFrom(this.currentRange)) {\n const lastSelection = this.currentSelection;\n this.currentRange = newRangeContainer;\n // empty selection or cursor\n if (lastSelection) {\n if (lastSelection.isCursor && !this.currentRange.isCursor) {\n this.dispatcher.notify('cursor', lastSelection.host);\n }\n else if (lastSelection.isSelection && !this.currentRange.isSelection) {\n this.dispatcher.notify('selection', lastSelection.host);\n }\n }\n // set new selection or cursor and fire event\n if (this.currentRange.isCursor && this.currentRange.host && this.currentRange.range) {\n this.currentSelection = new Cursor(this.currentRange.host, this.currentRange.range);\n this.dispatcher.notify('cursor', this.currentSelection.host, this.currentSelection);\n }\n else if (this.currentRange.isSelection && this.currentRange.host && this.currentRange.range) {\n this.currentSelection = new Selection(this.currentRange.host, this.currentRange.range);\n this.dispatcher.notify('selection', this.currentSelection.host, this.currentSelection);\n }\n else {\n this.currentSelection = undefined;\n }\n }\n }\n}\n//# sourceMappingURL=selection-watcher.js.map","import { createRange, containsRange } from './util/dom.js';\nimport { contenteditableSpanBug } from './feature-detection.js';\nimport * as nodeType from './node-type.js';\nimport eventable from './eventable.js';\n/**\n * The Keyboard module defines an event API for key events.\n */\nexport default class Keyboard {\n constructor(selectionWatcher) {\n eventable(this);\n this.selectionWatcher = selectionWatcher;\n this.key = Keyboard.key;\n }\n dispatchKeyEvent(event, target, notifyCharacterEvent) {\n switch (event.keyCode) {\n case this.key.left:\n return this.notify(target, 'left', event);\n case this.key.right:\n return this.notify(target, 'right', event);\n case this.key.up:\n return this.notify(target, 'up', event);\n case this.key.down:\n return this.notify(target, 'down', event);\n case this.key.tab:\n if (event.shiftKey)\n return this.notify(target, 'shiftTab', event);\n return this.notify(target, 'tab', event);\n case this.key.esc:\n return this.notify(target, 'esc', event);\n case this.key.backspace:\n this.preventContenteditableBug(target, event);\n return this.notify(target, 'backspace', event);\n case this.key.delete:\n this.preventContenteditableBug(target, event);\n return this.notify(target, 'delete', event);\n case this.key.enter:\n if (event.shiftKey)\n return this.notify(target, 'shiftEnter', event);\n return this.notify(target, 'enter', event);\n case this.key.ctrl:\n case this.key.shift:\n case this.key.alt:\n return;\n // Metakey\n case 224: // Firefox: 224\n case 17: // Opera: 17\n case 91: // Chrome/Safari: 91 (Left)\n case 93: // Chrome/Safari: 93 (Right)\n return;\n default:\n // Added here to avoid using fall-through in the switch\n // when b or i are pressed without ctrlKey or metaKey\n if (event.keyCode === this.key.b && (event.ctrlKey || event.metaKey)) {\n return this.notify(target, 'bold', event);\n }\n if (event.keyCode === this.key.i && (event.ctrlKey || event.metaKey)) {\n return this.notify(target, 'italic', event);\n }\n this.preventContenteditableBug(target, event);\n if (!notifyCharacterEvent)\n return;\n // Don't notify character events as long as either the ctrl or\n // meta key are pressed.\n // see: https://github.com/livingdocsIO/editable.js/pull/125\n if (!event.ctrlKey && !event.metaKey)\n return this.notify(target, 'character', event);\n }\n }\n preventContenteditableBug(target, event) {\n if (!contenteditableSpanBug)\n return;\n if (event.ctrlKey || event.metaKey)\n return;\n // This fixes a strange webkit bug that can be reproduced as follows:\n //\n // 1. A node used within a contenteditable has some style, e.g through the\n // following CSS:\n //\n // strong {\n // color: red\n // }\n //\n // 2. A selection starts with the first character of a styled node and ends\n // outside of that node, e.g: \"big beautiful\" is selected in the following\n // html:\n //\n // <p contenteditable=\"true\">\n // Hello <strong>big</strong> beautiful world\n // </p>\n //\n // 3. The user types a letter character to replace \"big beautiful\", e.g. \"x\"\n //\n // Result: Webkits adds <font> and <b> tags:\n //\n // <p contenteditable=\"true\">\n // Hello\n // <font color=\"#ff0000\">\n // <b>f</b>\n // </font>\n // world\n // </p>\n //\n // This bug ONLY happens, if the first character of the node is selected and\n // the selection goes further than the node.\n //\n // Solution:\n //\n // Manually remove the element that would be removed anyway before inserting\n // the new letter.\n const rangeContainer = this.selectionWatcher.getFreshRange();\n if (!rangeContainer.isSelection || !rangeContainer.range)\n return;\n const nodeToRemove = Keyboard.getNodeToRemove(rangeContainer.range, target);\n if (nodeToRemove)\n nodeToRemove.remove();\n }\n static getNodeToRemove(selectionRange, target) {\n // This function is only used by preventContenteditableBug. It is exposed on\n // the Keyboard constructor for testing purpose only.\n // Let's make sure we are in the edge-case, in which the bug happens.\n // The selection does not start at the beginning of a node. We have\n // nothing to do.\n if (selectionRange.startOffset !== 0)\n return undefined;\n let startNodeElement = selectionRange.startContainer;\n // If the node is a textNode, we select its parent.\n if (startNodeElement.nodeType === nodeType.textNode) {\n const parent = startNodeElement.parentNode;\n if (!parent || parent.nodeType !== nodeType.elementNode)\n return undefined;\n startNodeElement = parent;\n }\n // The target is the contenteditable element, which we do not want to replace\n if (startNodeElement === target)\n return undefined;\n // We get a range that contains everything within the sartNodeElement to test\n // if the selectionRange is within the startNode, we have nothing to do.\n const firstChild = startNodeElement.firstChild;\n const lastChild = startNodeElement.lastChild;\n if (!firstChild || !lastChild)\n return undefined;\n const startNodeRange = createRange();\n startNodeRange.setStartBefore(firstChild);\n startNodeRange.setEndAfter(lastChild);\n if (containsRange(startNodeRange, selectionRange))\n return undefined;\n // If the selectionRange.startContainer was a textNode, we have to make sure\n // that its parent's content starts with this node. Content is either a\n // text node or an element. This is done to avoid false positives like the\n // following one:\n // <strong>foo<em>bar</em>|baz</strong>quux|\n if (selectionRange.startContainer.nodeType === nodeType.textNode) {\n const contentNodeTypes = [nodeType.textNode, nodeType.elementNode];\n let firstContentNode = startNodeElement.firstChild;\n do {\n if (firstContentNode && contentNodeTypes.indexOf(firstContentNode.nodeType) !== -1)\n break;\n firstContentNode = firstContentNode ? firstContentNode.nextSibling : null;\n } while (firstContentNode);\n if (firstContentNode !== selectionRange.startContainer)\n return undefined;\n }\n // Now we know, that we have to return at least the startNodeElement for\n // removal. But it could be, that we also need to remove its parent, e.g.\n // we need to remove <strong> in the following example:\n // <strong><em>|foo</em>bar</strong>baz|\n const rangeStartingBeforeCurrentElement = selectionRange.cloneRange();\n rangeStartingBeforeCurrentElement.setStartBefore(startNodeElement);\n const parentResult = Keyboard.getNodeToRemove(rangeStartingBeforeCurrentElement, target);\n return parentResult || startNodeElement;\n }\n}\nKeyboard.key = Keyboard.prototype.key = {\n left: 37,\n up: 38,\n right: 39,\n down: 40,\n tab: 9,\n esc: 27,\n backspace: 8,\n delete: 46,\n enter: 13,\n shift: 16,\n ctrl: 17,\n alt: 18,\n b: 66,\n i: 73\n};\n//# sourceMappingURL=keyboard.js.map","const isValidQuotePairConfig = (quotePair) => Array.isArray(quotePair) && quotePair.length === 2;\nexport const shouldApplySmartQuotes = (config, target) => {\n const { smartQuotes, quotes, singleQuotes } = config;\n return !!smartQuotes && isValidQuotePairConfig(quotes) && isValidQuotePairConfig(singleQuotes) && target.isContentEditable;\n};\nexport const isDoubleQuote = (char) => /^[\\u00AB\\u00BB\\u201C\\u201D\\u201E\\u0022]$/.test(char);\nexport const isSingleQuote = (char) => /^[\\u2018\\u2019\\u2039\\u203A\\u201A\\u0027]$/.test(char);\nexport const isApostrophe = (char) => /^[\\u2019\\u0027]$/.test(char);\nexport const isWhitespace = (char) => /^\\s$/.test(char);\nexport const isSeparatorOrWhitespace = (char) => /\\s|[>\\-–—]/.test(char);\nconst shouldBeOpeningQuote = (text, indexCharBefore) => indexCharBefore < 0 || isSeparatorOrWhitespace(text[indexCharBefore]);\nconst shouldBeClosingQuote = (text, indexCharBefore) => !!text[indexCharBefore] && !isSeparatorOrWhitespace(text[indexCharBefore]);\nconst hasCharAfter = (textArr, indexCharAfter) => !!textArr[indexCharAfter] && !isWhitespace(textArr[indexCharAfter]);\nconst shouldBeSingleOpeningQuote = (text, indexCharBefore) => !!text[indexCharBefore] && isDoubleQuote(text[indexCharBefore]);\nexport const replaceQuote = (range, index, quoteType) => {\n const startContainer = range?.startContainer;\n if (!startContainer || startContainer.nodeType !== 3) { // Node.TEXT_NODE\n return null;\n }\n const textNode = startContainer;\n const nodeValue = textNode.nodeValue;\n if (!nodeValue) {\n return null;\n }\n const newText = `${nodeValue.substring(0, index)}${quoteType}${nodeValue.substring(index + 1)}`;\n const newTextNode = document.createTextNode(newText);\n textNode.replaceWith(newTextNode);\n return newTextNode;\n};\nconst hasSingleOpeningQuote = (textArr, offset, singleOpeningQuote) => {\n if (offset <= 0) {\n return false;\n }\n for (let i = offset - 1; i >= 0; i--) {\n if (isSingleQuote(textArr[i]) && (!isApostrophe(singleOpeningQuote) && !isApostrophe(textArr[i]))) {\n return textArr[i] === singleOpeningQuote;\n }\n }\n return false;\n};\nexport const applySmartQuotes = (range, config, char, target, cursorOffset) => {\n const isCharSingleQuote = isSingleQuote(char);\n const isCharDoubleQuote = isDoubleQuote(char);\n if (!isCharDoubleQuote && !isCharSingleQuote) {\n return;\n }\n const { quotes, singleQuotes } = config;\n if (char === quotes[0] || char === quotes[1] || char === singleQuotes[0] || char === singleQuotes[1]) {\n return;\n }\n const offset = range.startOffset;\n const textContent = range.startContainer.textContent;\n if (!textContent)\n return;\n const textArr = [...textContent];\n let newTextNode = null;\n // Special case for a single quote following a double quote,\n // which should be transformed into a single opening quote\n if (isCharSingleQuote && shouldBeSingleOpeningQuote(textArr, offset - 2)) {\n newTextNode = replaceQuote(range, offset - 1, singleQuotes[0]);\n }\n else if (shouldBeClosingQuote(textArr, offset - 2)) {\n if (isCharSingleQuote) {\n // Don't transform apostrophes\n if (hasCharAfter(textArr, offset)) {\n return;\n }\n // Don't transform single-quote if there is no respective single-opening-quote\n if (!hasSingleOpeningQuote(textArr, offset, singleQuotes[0])) {\n return;\n }\n }\n const closingQuote = isCharSingleQuote ? singleQuotes[1] : quotes[1];\n newTextNode = replaceQuote(range, offset - 1, closingQuote);\n }\n else if (shouldBeOpeningQuote(textArr, offset - 2)) {\n const openingQuote = isCharSingleQuote ? singleQuotes[0] : quotes[0];\n newTextNode = replaceQuote(range, offset - 1, openingQuote);\n }\n if (!newTextNode) {\n return;\n }\n // Resets the cursor to the currentPosition after applying the smart-quote\n const window = target.ownerDocument.defaultView;\n if (!window)\n return;\n const selection = window.getSelection();\n if (!selection)\n return;\n selection.collapse(newTextNode, cursorOffset ?? offset);\n};\n//# sourceMappingURL=smartQuotes.js.map","import { selectionchange } from './feature-detection.js';\nimport * as clipboard from './clipboard.js';\nimport * as content from './content.js';\nimport eventable from './eventable.js';\nimport SelectionWatcher from './selection-watcher.js';\nimport config from './config.js';\nimport Keyboard from './keyboard.js';\nimport { closest } from './util/dom.js';\nimport { replaceLast, endsWithSingleSpace } from './util/string.js';\nimport { applySmartQuotes, shouldApplySmartQuotes } from './smartQuotes.js';\n/**\n * The Dispatcher module is responsible for dealing with events and their handlers.\n *\n * @module core\n * @submodule dispatcher\n */\nexport default class Dispatcher {\n constructor(editable) {\n const win = editable.win;\n eventable(this, editable);\n this.document = win.document;\n this.config = editable.config;\n this.editable = editable;\n this.editableSelector = editable.editableSelector;\n this.selectionWatcher = new SelectionWatcher(this, win);\n this.keyboard = new Keyboard(this.selectionWatcher);\n this.activeListeners = [];\n this.setup();\n this.getEditableBlockByEvent = (evt) => {\n const target = evt.target;\n return target ? closest(target, editable.editableSelector) : undefined;\n };\n }\n setupDocumentListener(event, func, capture = false) {\n const listener = { event, listener: func.bind(this), capture };\n this.activeListeners.push(listener);\n this.document.addEventListener(event, listener.listener, capture);\n return this;\n }\n /**\n * Sets up all events that Editable.JS is catching.\n *\n * @method setup\n */\n setup() {\n // setup all events listeners and keyboard handlers\n this.setupKeyboardEvents();\n this.setupEventListeners();\n }\n unload() {\n this.off();\n for (const l of this.activeListeners) {\n this.document.removeEventListener(l.event, l.listener, l.capture);\n }\n this.activeListeners.length = 0;\n }\n suspend() {\n if (this.suspended)\n return;\n this.suspended = true;\n for (const l of this.activeListeners) {\n this.document.removeEventListener(l.event, l.listener, l.capture);\n }\n this.activeListeners.length = 0;\n }\n continue() {\n if (!this.suspended)\n return;\n this.suspended = false;\n this.setupEventListeners();\n }\n setupEventListeners() {\n this.setupElementListeners();\n this.setupKeydownListener();\n if (selectionchange) {\n this.setupSelectionChangeListeners();\n }\n else {\n this.setupSelectionChangeFallbackListeners();\n }\n }\n /**\n * Sets up events that are triggered on modifying an element.\n *\n * @method setupElementListeners\n */\n setupElementListeners() {\n const currentInput = { offset: undefined };\n this\n .setupDocumentListener('focus', function focusListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const target = evt.target;\n if (target && target.getAttribute(config.pastingAttribute))\n return;\n this.selectionWatcher.syncSelection();\n this.notify('focus', block);\n }, true)\n .setupDocumentListener('blur', function blurListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n if (block.getAttribute(config.pastingAttribute))\n return;\n this.notify('blur', block);\n }, true)\n .setupDocumentListener('copy', function copyListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const selection = this.selectionWatcher.getFreshSelection();\n if (selection && selection.isSelection) {\n this.notify('clipboard', block, 'copy', selection);\n }\n })\n .setupDocumentListener('cut', function cutListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const selection = this.selectionWatcher.getFreshSelection();\n if (selection && selection.isSelection) {\n this.notify('clipboard', block, 'cut', selection);\n }\n })\n .setupDocumentListener('paste', function pasteListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const clipEvent = evt;\n clipEvent.preventDefault();\n const selection = this.selectionWatcher.getFreshSelection();\n if (!selection || !clipEvent.clipboardData)\n return;\n const clipboardContent = clipEvent.clipboardData.getData('text/html') || clipEvent.clipboardData.getData('text/plain');\n const { blocks, cursor } = clipboard.paste(block, selection, clipboardContent);\n if (blocks.length) {\n const target = clipEvent.target;\n if (target && endsWithSingleSpace(target.innerText)) {\n cursor.retainVisibleSelection(() => {\n block.innerHTML = replaceLast(block.innerHTML, ' ', ' ');\n });\n }\n this.notify('paste', block, blocks, cursor);\n // The input event does not fire when we process the content manually\n // and insert it via script\n this.notify('change', block);\n }\n else {\n cursor.setVisibleSelection();\n }\n })\n .setupDocumentListener('input', function inputListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const target = evt.target;\n if (target && shouldApplySmartQuotes(this.config, target)) {\n const selection = this.selectionWatcher.getFreshSelection();\n if (!selection || !selection.range)\n return;\n // Save offset of new input, to reset cursor correctly after timeout delay\n currentInput.offset = selection.range.startOffset;\n const inputEvent = evt;\n const quotesConfig = this.config.quotes || { quotes: [], singleQuotes: [] };\n setTimeout(() => {\n if (inputEvent.data) {\n applySmartQuotes(selection.range, quotesConfig, inputEvent.data, target, currentInput.offset);\n }\n }, 300);\n }\n this.notify('change', block);\n })\n .setupDocumentListener('formatEditable', function formatEditableListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n this.notify('change', block);\n });\n }\n dispatchSwitchEvent(event, element, direction) {\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)\n return;\n const cursor = this.selectionWatcher.getFreshSelection();\n if (!cursor || cursor.isSelection)\n return;\n // store position\n if (!this.switchContext) {\n this.switchContext = {\n positionX: cursor.getBoundingClientRect().left,\n events: ['cursor']\n };\n }\n else {\n this.switchContext.events = ['cursor'];\n }\n if (direction === 'up' && cursor.isAtFirstLine()) {\n event.preventDefault();\n event.stopPropagation();\n this.switchContext.events = ['switch', 'blur', 'focus', 'cursor'];\n this.notify('switch', element, direction, cursor);\n }\n if (direction === 'down' && cursor.isAtLastLine()) {\n event.preventDefault();\n event.stopPropagation();\n this.switchContext.events = ['switch', 'blur', 'focus', 'cursor'];\n this.notify('switch', element, direction, cursor);\n }\n }\n /**\n * Sets up listener for keydown event which forwards events to\n * the Keyboard instance.\n *\n * @method setupKeydownListener\n */\n setupKeydownListener() {\n this.setupDocumentListener('keydown', function (evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const keyEvent = evt;\n this.keyboard.dispatchKeyEvent(keyEvent, block, false);\n }, true);\n }\n /**\n * Sets up handlers for the keyboard events.\n * Keyboard definitions are in {{#crossLink \"Keyboard\"}}{{/crossLink}}.\n *\n * @method setupKeyboardEvents\n */\n setupKeyboardEvents() {\n const self = this;\n this.keyboard\n .on('up', function (event) {\n self.dispatchSwitchEvent(event, this, 'up');\n })\n .on('down', function (event) {\n self.dispatchSwitchEvent(event, this, 'down');\n })\n .on('backspace', function (event) {\n const editableBlock = this;\n const rangeContainer = self.selectionWatcher.getFreshRange();\n if (!rangeContainer.isCursor)\n return;\n const cursor = rangeContainer.getCursor();\n if (!cursor || !cursor.isAtBeginning())\n return;\n event.preventDefault();\n event.stopPropagation();\n self.notify('merge', editableBlock, 'before', cursor);\n })\n .on('delete', function (event) {\n const editableBlock = this;\n const rangeContainer = self.selectionWatcher.getFreshRange();\n if (!rangeContainer.isCursor)\n return;\n const cursor = rangeContainer.getCursor();\n if (!cursor || !cursor.isAtTextEnd())\n return;\n event.preventDefault();\n event.stopPropagation();\n self.notify('merge', editableBlock, 'after', cursor);\n })\n .on('enter', function (event) {\n const editableBlock = this;\n event.preventDefault();\n event.stopPropagation();\n const rangeContainer = self.selectionWatcher.getFreshRange();\n const cursor = rangeContainer.forceCursor();\n if (!cursor)\n return;\n if (cursor.isAtTextEnd()) {\n self.notify('insert', editableBlock, 'after', cursor);\n }\n else if (cursor.isAtBeginning()) {\n self.notify('insert', editableBlock, 'before', cursor);\n }\n else {\n const beforeFragment = cursor.before();\n const afterFragment = cursor.after();\n self.notify('split', editableBlock, content.getInnerHtmlOfFragment(beforeFragment), content.getInnerHtmlOfFragment(afterFragment), cursor);\n }\n })\n .on('shiftEnter', function (event) {\n const editableBlock = this;\n event.preventDefault();\n event.stopPropagation();\n const cursor = self.selectionWatcher.forceCursor();\n if (cursor) {\n self.notify('newline', editableBlock, cursor);\n }\n })\n .on('bold', function (event) {\n event.preventDefault();\n event.stopPropagation();\n const selection = self.selectionWatcher.getFreshSelection();\n if (selection && selection.isSelection) {\n self.notify('toggleBold', selection);\n }\n })\n .on('italic', function (event) {\n event.preventDefault();\n event.stopPropagation();\n const selection = self.selectionWatcher.getFreshSelection();\n if (selection && selection.isSelection) {\n self.notify('toggleEmphasis', selection);\n }\n })\n .on('character', function (event) {\n const editableBlock = this;\n self.notify('change', editableBlock);\n });\n }\n /**\n * Sets up events that are triggered on a selection change.\n *\n * @method setupSelectionChangeListeners\n */\n setupSelectionChangeListeners() {\n let selectionDirty = false;\n let suppressSelectionChanges = false;\n const selectionWatcher = this.selectionWatcher;\n // fires on mousemove (thats probably a bit too much)\n // catches changes like 'select all' from context menu\n this.setupDocumentListener('selectionchange', (evt) => {\n let didSyncSelection = false;\n let cursor = this.selectionWatcher.getFreshSelection();\n if (!cursor) {\n selectionWatcher.selectionChanged();\n didSyncSelection = true;\n cursor = this.selectionWatcher.getSelection();\n }\n if (cursor && cursor.isSelection && cursor.isAtBeginning() && cursor.isAtEnd()) {\n this.notify('selectToBoundary', cursor.host, evt, 'both');\n }\n else if (cursor && cursor.isSelection && cursor.isAtBeginning()) {\n this.notify('selectToBoundary', cursor.host, evt, 'start');\n }\n else if (cursor && cursor.isSelection && cursor.isAtEnd()) {\n this.notify('selectToBoundary', cursor.host, evt, 'end');\n }\n if (suppressSelectionChanges) {\n selectionDirty = true;\n }\n else if (!didSyncSelection) {\n selectionWatcher.selectionChanged();\n }\n });\n // listen for selection changes by mouse so we can\n // suppress the selectionchange event and only fire the\n // change event on mouseup\n this.setupDocumentListener('mousedown', function (evt) {\n const mouseEvent = evt;\n if (!this.getEditableBlockByEvent(evt))\n return;\n if (this.config.mouseMoveSelectionChanges === false) {\n suppressSelectionChanges = true;\n // Without this timeout the previous selection is active\n // until the mouseup event (no. not good).\n setTimeout(() => selectionWatcher.selectionChanged(), 0);\n }\n const self = this;\n this.document.addEventListener('mouseup', () => {\n suppressSelectionChanges = false;\n if (selectionDirty) {\n selectionDirty = false;\n selectionWatcher.selectionChanged();\n }\n }, {\n capture: true,\n once: true\n });\n });\n }\n /**\n * Fallback solution to support selection change events on browsers that don't\n * support selectionChange.\n *\n * @method setupSelectionChangeFallbackListeners\n */\n setupSelectionChangeFallbackListeners() {\n const notifySelectionBoundary = (evt) => {\n const cursor = this.selectionWatcher.getFreshSelection();\n if (cursor && cursor.isSelection && cursor.isAtBeginning() && cursor.isAtEnd()) {\n this.notify('selectToBoundary', cursor.host, evt, 'both');\n }\n else if (cursor && cursor.isSelection && cursor.isAtBeginning()) {\n this.notify('selectToBoundary', cursor.host, evt, 'start');\n }\n else if (cursor && cursor.isSelection && cursor.isAtEnd()) {\n this.notify('selectToBoundary', cursor.host, evt, 'end');\n }\n };\n // listen for selection changes by mouse\n this.setupDocumentListener('mouseup', (evt) => {\n // In Opera when clicking outside of a block\n // it does not update the selection as it should\n // without the timeout\n setTimeout(() => {\n this.selectionWatcher.selectionChanged();\n notifySelectionBoundary(evt);\n }, 0);\n });\n // listen for selection changes by keys\n this.setupDocumentListener('keyup', (evt) => {\n if (!this.getEditableBlockByEvent(evt))\n return;\n // when pressing Command + Shift + Left for example the keyup is only triggered\n // after at least two keys are released. Strange. The culprit seems to be the\n // Command key. Do we need a workaround?\n this.selectionWatcher.selectionChanged();\n notifySelectionBoundary(evt);\n });\n }\n}\n//# sourceMappingURL=dispatcher.js.map","/**\n * Deep merge objects, creating a new object with merged properties.\n * Arrays are replaced (not merged).\n */\nexport function deepMerge(target, ...sources) {\n const result = { ...target };\n for (const source of sources) {\n if (!source || typeof source !== 'object')\n continue;\n for (const key in source) {\n if (!Object.prototype.hasOwnProperty.call(source, key))\n continue;\n const sourceValue = source[key];\n const targetValue = result[key];\n // Deep merge if both are plain objects\n if (sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)) {\n result[key] = deepMerge({}, targetValue, sourceValue);\n }\n else {\n result[key] = sourceValue;\n }\n }\n }\n return result;\n}\n//# sourceMappingURL=merge.js.map","import * as content from '../../content.js';\n/**\n* Spellcheck class.\n*\n* @class Spellcheck\n* @constructor\n*/\nexport default class SpellcheckService {\n constructor(spellcheckService) {\n this.spellcheckService = spellcheckService;\n }\n check(text, callback) {\n if (!text)\n return callback(null);\n const condensedText = content.normalizeWhitespace(text);\n this.spellcheckService(condensedText, (misspelledWords) => {\n if (misspelledWords && misspelledWords.length > 0) {\n return callback(null, misspelledWords);\n }\n return callback(null);\n });\n }\n}\n//# sourceMappingURL=spellcheck-service.js.map","// See: https://en.wikipedia.org/wiki/Whitespace_character\nconst characters = {\n 'A0': 'no-break space', // \\\\u00A0\n '2000': 'en quad', // \\\\u2000\n '2001': 'em quad', // \\\\u2001\n '2002': 'en space', // \\\\u2002\n '2003': 'em space', // \\\\u2003\n '2004': 'three-per-em space', // \\\\u2004\n '2005': 'four-per-em space', // \\\\u2005\n '2006': 'six-per-em space', // \\\\u2006\n '2007': 'figure space', // \\\\u2007\n '2008': 'punctuation space', // \\\\u2008\n '2009': 'thin space', // \\\\u2009\n '200A': 'hair space', // \\\\u200A\n '202F': 'narrow no-break space', // \\\\u202F\n '205F': 'medium mathematical space', // \\\\u205F\n '3000': 'ideographic space' // \\\\u3000\n};\n// The no-break space is not highlighted as this can cause problems.\n// Browser can insert no-break spaces when typing at the end of\n// a paragraph and the highlighting prevents browsers from converting\n// the no-break space back to a normal space when the user keeps typing.\nconst specialWhitespaceChars = '\\\\u2000-\\\\u200A\\\\u202F\\\\u205F\\\\u3000';\nconst specialWhitespaceCharsRegex = new RegExp(`[${specialWhitespaceChars}]`, 'g');\nexport default class WhitespaceHighlighting {\n constructor(markerNode) {\n this.marker = markerNode;\n }\n findMatches(text) {\n if (!text)\n return;\n const matches = [...text.matchAll(specialWhitespaceCharsRegex)];\n return matches.map((entry) => this.prepareMatch(entry));\n }\n prepareMatch(match) {\n const startIndex = match.index;\n const unicode = getUnicode(match[0]);\n const description = characters[unicode] || 'unknown whitespace';\n return {\n startIndex,\n endIndex: startIndex + match.length,\n match: match[0],\n title: `${description} (\\\\u${unicode})`,\n marker: this.marker\n };\n }\n}\nfunction getUnicode(character) {\n const code = character.charCodeAt(0);\n return `${code.toString(16).toUpperCase()}`;\n}\n//# sourceMappingURL=whitespace-highlighting.js.map","export default class MatchCollection {\n constructor() {\n this.matches = [];\n }\n addMatches(matches) {\n if (!matches?.length)\n return;\n this.matches = mergeMatches(this.matches, matches);\n }\n}\n// Private Helpers\n// ---------------\nfunction mergeMatches(matches1, matches2) {\n let next;\n const length1 = matches1.length;\n const length2 = matches2.length;\n let lastEndIndex = -1;\n const output = [];\n const state = {\n a1: matches1,\n i1: 0,\n a2: matches2,\n i2: 0\n };\n while (state.i1 < length1 || state.i2 < length2) {\n next = pickNext(state);\n if (next && next.startIndex >= lastEndIndex) {\n output.push(next);\n lastEndIndex = next.endIndex;\n }\n else if (next) {\n lastEndIndex = next.endIndex;\n }\n }\n return output;\n}\nfunction pickNext(state) {\n const i1 = state.i1;\n const i2 = state.i2;\n const item1 = state.a1[i1];\n const item2 = state.a2[i2];\n if (item1 && item2 && item1.startIndex < item2.startIndex) {\n state.i1 = i1 + 1;\n return item1;\n }\n else if (item1 && item2) {\n state.i2 = i2 + 1;\n return item2;\n }\n else if (item1) {\n state.i1 = i1 + 1;\n return item1;\n }\n else if (item2) {\n state.i2 = i2 + 1;\n return item2;\n }\n else {\n return undefined;\n }\n}\n//# sourceMappingURL=match-collection.js.map","import * as nodeType from './node-type.js';\nimport { deepMerge } from './util/merge.js';\nimport * as content from './content.js';\nimport highlightText from './highlight-text.js';\nimport SpellcheckService from './plugins/highlighting/spellcheck-service.js';\nimport WhitespaceHighlighting from './plugins/highlighting/whitespace-highlighting.js';\nimport { searchAllWords } from './plugins/highlighting/text-search.js';\nimport MatchCollection from './plugins/highlighting/match-collection.js';\nimport highlightSupport from './highlight-support.js';\nimport { domArray, domSelector } from './util/dom.js';\nexport default class MonitoredHighlighting {\n constructor(editable, configuration, spellcheckConfig) {\n this.editable = editable;\n this.win = editable.win;\n this.focusedEditableHost = undefined;\n this.currentlyCheckedEditableHost = undefined;\n this.timeout = {};\n const defaultConfig = {\n checkOnInit: false,\n checkOnFocus: false,\n checkOnChange: true,\n // unbounce rate in ms before calling the spellcheck service after changes\n throttle: 1000,\n // remove highlights after a change if the cursor is inside a highlight\n removeOnCorrection: true,\n spellcheck: {\n marker: '<span class=\"highlight-spellcheck\"></span>',\n throttle: 1000,\n spellcheckService: function () { }\n },\n whitespace: {\n marker: '<span class=\"highlight-whitespace\"></span>'\n }\n };\n this.config = deepMerge({}, defaultConfig, configuration);\n const spellcheckService = this.config.spellcheck.spellcheckService;\n const spellcheckMarker = this.config.spellcheck.marker;\n const whitespaceMarker = this.config.whitespace.marker;\n const whitespaceMarkerNode = highlightSupport\n .createMarkerNode(whitespaceMarker, 'whitespace', this.win);\n const spellcheckMarkerNode = highlightSupport\n .createMarkerNode(spellcheckMarker, 'spellcheck', this.win);\n if (!whitespaceMarkerNode || !spellcheckMarkerNode) {\n throw new Error('Failed to create marker nodes');\n }\n this.spellcheckMarkerNode = spellcheckMarkerNode;\n this.spellcheckService = new SpellcheckService(spellcheckService);\n this.whitespace = new WhitespaceHighlighting(whitespaceMarkerNode);\n this.setupListeners();\n }\n // Events\n // ------\n setupListeners() {\n if (this.config.checkOnFocus) {\n this.editable.on('focus', (editableHost) => this.onFocus(editableHost));\n this.editable.on('blur', (editableHost) => this.onBlur(editableHost));\n }\n if (this.config.checkOnChange || this.config.removeOnCorrection) {\n this.editable.on('change', (editableHost) => this.onChange(editableHost));\n }\n if (this.config.checkOnInit) {\n this.editable.on('init', (editableHost) => this.onInit(editableHost));\n }\n }\n onInit(editableHost) {\n this.highlight(editableHost);\n }\n onFocus(editableHost) {\n if (this.focusedEditableHost !== editableHost) {\n this.focusedEditableHost = editableHost;\n this.editableHasChanged(editableHost, undefined);\n }\n }\n onBlur(editableHost) {\n if (this.focusedEditableHost === editableHost) {\n this.focusedEditableHost = undefined;\n }\n }\n onChange(editableHost) {\n if (this.config.checkOnChange) {\n this.editableHasChanged(editableHost, this.config.throttle);\n }\n if (this.config.removeOnCorrection) {\n this.removeHighlightsAtCursor(editableHost);\n }\n }\n // Manage Highlights\n // -----------------\n editableHasChanged(editableHost, throttle) {\n if (this.timeout.id && this.timeout.editableHost === editableHost) {\n clearTimeout(this.timeout.id);\n }\n const timeoutId = setTimeout(() => {\n this.highlight(editableHost);\n this.timeout = {};\n }, throttle || 0);\n this.timeout = {\n id: timeoutId,\n editableHost: editableHost\n };\n }\n highlight(editableHost) {\n const textBefore = highlightText.extractText(editableHost);\n // getSpellcheck\n this.spellcheckService.check(textBefore, (err, misspelledWords) => {\n if (err || !editableHost.isConnected) {\n return;\n } // return in case the host was removed from the dom\n // refresh the text\n const text = highlightText.extractText(editableHost);\n const matchCollection = new MatchCollection();\n if (misspelledWords && misspelledWords.length > 0) {\n const matches = searchAllWords(text, misspelledWords, this.spellcheckMarkerNode);\n matchCollection.addMatches(matches);\n }\n const whitespaceMatches = this.whitespace.findMatches(text);\n if (whitespaceMatches) {\n // Convert WhitespaceMatch[] to Match[]\n const matches = whitespaceMatches.map(m => ({\n startIndex: m.startIndex || 0,\n endIndex: m.endIndex,\n match: m.match,\n marker: m.marker\n }));\n matchCollection.addMatches(matches);\n }\n this.safeHighlightMatches(editableHost, matchCollection.matches);\n });\n }\n // Calls highlightMatches internally but ensures\n // that the selection stays the same\n safeHighlightMatches(editableHost, matches) {\n const selection = this.editable.getSelection(editableHost);\n if (selection) {\n selection.retainVisibleSelection(() => {\n this.highlightMatches(editableHost, matches);\n });\n }\n else {\n this.highlightMatches(editableHost, matches);\n }\n if (this.editable.dispatcher) {\n this.editable.dispatcher.notify('spellcheckUpdated', editableHost);\n }\n }\n highlightMatches(editableHost, matches) {\n // Remove old highlights\n this.removeHighlights(editableHost);\n // Create new highlights\n if (matches && matches.length > 0) {\n // const span = this.createMarkerNode()\n highlightText.highlightMatches(editableHost, matches);\n }\n }\n removeHighlights(editableHost) {\n const host = domSelector(editableHost, this.win.document);\n if (!host)\n return;\n for (const elem of domArray('[data-highlight=\"spellcheck\"], [data-highlight=\"whitespace\"]', this.win.document, host)) {\n content.unwrap(elem);\n }\n }\n removeHighlightsAtCursor(editableHost) {\n const host = domSelector(editableHost, this.win.document);\n if (!host)\n return;\n editableHost = host;\n const selection = this.editable.getSelection(editableHost);\n if (selection && selection.isCursor) {\n let elementAtCursor = selection.range.startContainer;\n if (elementAtCursor.nodeType === nodeType.textNode) {\n elementAtCursor = elementAtCursor.parentNode;\n }\n let wordId;\n do {\n if (elementAtCursor === editableHost)\n return;\n const highlightType = elementAtCursor.getAttribute('data-highlight');\n if (highlightType === 'spellcheck' || highlightType === 'whitespace') {\n wordId = elementAtCursor.getAttribute('data-word-id');\n break;\n }\n } while ((elementAtCursor = elementAtCursor.parentNode));\n if (wordId) {\n selection.retainVisibleSelection(() => {\n for (const elem of domArray(`[data-word-id=\"${wordId}\"]`, this.win.document, host)) {\n content.unwrap(elem);\n }\n });\n }\n }\n }\n}\n//# sourceMappingURL=monitored-highlighting.js.map","import config from '../config.js';\n// Allows for safe console logging\n// If the last param is the string \"trace\" console.trace will be called\n// configuration: disable with config.log = false\nexport default function log(...args) {\n if (config.log === false)\n return;\n if (!global.console)\n return;\n const logArgs = args.length === 1 ? args[0] : args;\n if (args.length !== 1 && logArgs[logArgs.length - 1] === 'trace') {\n logArgs.pop();\n if (console.trace)\n console.trace();\n }\n console.log(logArgs);\n}\n//# sourceMappingURL=log.js.map","import createDefaultBehavior from './create-default-behavior.js';\nexport default function createDefaultEvents(editable) {\n const behavior = createDefaultBehavior(editable);\n return {\n /**\n * The focus event is triggered when an element gains focus.\n * The default behavior is to... TODO\n *\n * @event focus\n * @param {HTMLElement} element The element triggering the event.\n */\n focus(element) {\n behavior.focus(element);\n },\n /**\n * The blur event is triggered when an element looses focus.\n * The default behavior is to... TODO\n *\n * @event blur\n * @param {HTMLElement} element The element triggering the event.\n */\n blur(element) {\n behavior.blur(element);\n },\n /**\n * The selection event is triggered after the user has selected some\n * content.\n * The default behavior is to... TODO\n *\n * @event selection\n * @param {HTMLElement} element The element triggering the event.\n * @param {Selection} selection The actual Selection object.\n */\n selection(element, selection) {\n behavior.selection(element, selection);\n },\n /**\n * The cursor event is triggered after cursor position has changed.\n * The default behavior is to... TODO\n *\n * @event cursor\n * @param {HTMLElement} element The element triggering the event.\n * @param {Cursor} cursor The actual Cursor object.\n */\n cursor(element, cursor) {\n behavior.cursor(element, cursor);\n },\n /**\n * The newline event is triggered when a newline should be inserted. This\n * happens when SHIFT+ENTER key is pressed.\n * The default behavior is to add a <br />\n *\n * @event newline\n * @param {HTMLElement} element The element triggering the event.\n * @param {Cursor} cursor The actual cursor object.\n */\n newline(element, cursor) {\n behavior.newline(element, cursor);\n },\n /**\n * The split event is triggered when a block should be split into two\n * blocks. This happens when ENTER is pressed within a non-empty block.\n * The default behavior is to... TODO\n *\n * @event split\n * @param {HTMLElement} element The element triggering the event.\n * @param {String} before The HTML string before the split.\n * @param {String} after The HTML string after the split.\n * @param {Cursor} cursor The actual cursor object.\n */\n split(element, before, after, cursor) {\n behavior.split(element, before, after, cursor);\n },\n /**\n * The insert event is triggered when a new block should be inserted. This\n * happens when ENTER key is pressed at the beginning of a block (should\n * insert before) or at the end of a block (should insert after).\n * The default behavior is to... TODO\n *\n * @event insert\n * @param {HTMLElement} element The element triggering the event.\n * @param {String} direction The insert direction: \"before\" or \"after\".\n * @param {Cursor} cursor The actual cursor object.\n */\n insert(element, direction, cursor) {\n behavior.insert(element, direction, cursor);\n },\n /**\n * The merge event is triggered when two needs to be merged. This happens\n * when BACKSPACE is pressed at the beginning of a block (should merge with\n * the preceding block) or DEL is pressed at the end of a block (should\n * merge with the following block).\n * The default behavior is to... TODO\n *\n * @event merge\n * @param {HTMLElement} element The element triggering the event.\n * @param {String} direction The merge direction: \"before\" or \"after\".\n * @param {Cursor} cursor The actual cursor object.\n */\n merge(element, direction, cursor) {\n behavior.merge(element, direction, cursor);\n },\n /**\n * The empty event is triggered when a block is emptied.\n * The default behavior is to... TODO\n *\n * @event empty\n * @param {HTMLElement} element The element triggering the event.\n */\n empty(element) {\n behavior.empty(element);\n },\n /**\n * The switch event is triggered when the user switches to another block.\n * This happens when an ARROW key is pressed near the boundaries of a block.\n * The default behavior is to... TODO\n *\n * @event switch\n * @param {HTMLElement} element The element triggering the event.\n * @param {String} direction The switch direction: \"before\" or \"after\".\n * @param {Cursor} cursor The actual cursor object.*\n */\n switch(element, direction, cursor) {\n behavior.switch(element, direction, cursor);\n },\n /**\n * The move event is triggered when the user moves a selection in a block.\n * This happens when the user selects some (or all) content in a block and\n * an ARROW key is pressed (up: drag before, down: drag after).\n * The default behavior is to... TODO\n *\n * @event move\n * @param {HTMLElement} element The element triggering the event.\n * @param {Selection} selection The actual Selection object.\n * @param {String} direction The move direction: \"before\" or \"after\".\n */\n move(element, selection, direction) {\n behavior.move(element, selection, direction);\n },\n /**\n * The clipboard event is triggered when the user copies or cuts\n * a selection within a block.\n *\n * @event clipboard\n * @param {HTMLElement} element The element triggering the event.\n * @param {String} action The clipboard action: \"copy\" or \"cut\".\n * @param {Selection} selection A selection object around the copied content.\n */\n clipboard(element, action, selection) {\n behavior.clipboard(element, action, selection);\n },\n /**\n * The paste event is triggered when the user pastes text\n *\n * @event paste\n * @param {HTMLElement} The element triggering the event.\n * @param {Array of String} The pasted blocks\n * @param {Cursor} The cursor object.\n */\n paste(element, blocks, cursor) {\n behavior.paste(element, blocks, cursor);\n },\n /**\n * The toggleBold event is triggered when the bold keyboard shortcut is used\n *\n * @event toggleBold\n * @param {Selection} The selection object.\n */\n toggleBold(selection) {\n behavior.toggleBold(selection);\n },\n /**\n * The toggleEmphasis event is triggered when the italic keyboard shortcut is used\n *\n * @event toggleEmphasis\n * @param {Selection} The selection object.\n */\n toggleEmphasis(selection) {\n behavior.toggleEmphasis(selection);\n }\n };\n}\n//# sourceMappingURL=create-default-events.js.map","import * as parser from './parser.js';\nimport * as content from './content.js';\nimport log from './util/log.js';\nimport * as nodeType from './node-type.js';\n/**\n * The Behavior module defines the behavior triggered in response to the Editable.JS\n * events (see {{#crossLink \"Editable\"}}{{/crossLink}}).\n * The behavior can be overwritten by a user with Editable.init() or on\n * Editable.add() per element.\n *\n * @module core\n * @submodule behavior\n */\nexport default function createDefaultBehavior(editable) {\n const document = editable.win.document;\n /**\n * Factory for the default behavior.\n * Provides default behavior of the Editable.JS API.\n *\n * @static\n */\n return {\n /** @param {HTMLElement} element */\n focus(element) {\n if (!parser.isVoid(element))\n return;\n // Add an zero width space if the editable is empty to force it to have a height\n // E.g. Firefox does not render empty block elements\n // and most browsers do not render empty inline elements.\n element.appendChild(document.createTextNode('\\uFEFF'));\n },\n blur(element) {\n // Note: there is a special case when the tab is changed where\n // we can get a blur event even if the cursor is still in the editable.\n // This blur would cause us to loose the cursor position (cause of cleanInternals()).\n // To prevent this we check if the activeElement is still the editable.\n // (Note: document.getSelection() did not work reliably in this case.)\n if (document.activeElement === element)\n return;\n content.cleanInternals(element);\n },\n selection(element, selection) {\n log(selection ? 'Default selection behavior' : 'Default selection empty behavior');\n },\n cursor(element, cursor) {\n log('Default cursor behavior');\n },\n newline(element, cursor) {\n // When the cursor is at the text end, we'll need to add an empty text node\n // after the br tag to ensure that the cursor shows up on the next line\n if (cursor.isAtTextEnd()) {\n const br = document.createElement('br');\n cursor.insertBefore(br);\n // Only append a zero width space if there's none after the br tag\n // We don't need to remove them as they get cleaned up on blur\n const nextSibling = br.nextSibling;\n if (nextSibling?.nodeType !== nodeType.textNode ||\n nextSibling.textContent?.[0] !== '\\uFEFF') {\n cursor.insertAfter(document.createTextNode('\\uFEFF'));\n }\n }\n else {\n cursor.insertBefore(document.createElement('br'));\n }\n cursor.setVisibleSelection();\n },\n insert(element, direction, cursor) {\n const newElement = element.cloneNode(false);\n if (newElement.id)\n newElement.removeAttribute('id');\n if (direction === 'before') {\n element.parentNode?.insertBefore(newElement, element);\n }\n else {\n element.parentNode?.insertBefore(newElement, element.nextSibling);\n }\n editable.createCursorAtEnd(newElement)?.setVisibleSelection();\n },\n split(element, before, after, cursor) {\n const fragment = content.createFragmentFromString(before);\n const newNode = element.cloneNode(false);\n newNode.appendChild(fragment);\n const parent = element.parentNode;\n if (parent) {\n parent.insertBefore(newNode, element);\n }\n element.innerHTML = after;\n content.tidyHtml(newNode);\n content.tidyHtml(element);\n cursor.setVisibleSelection();\n },\n merge(element, direction, cursor) {\n const target = direction === 'before'\n ? element.previousElementSibling\n : element.nextElementSibling;\n if (!target)\n return;\n const targetContent = content.extractContent(target, false);\n const elementContent = content.extractContent(element, false);\n // Calculate text lengths before merging to position cursor correctly\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = targetContent;\n const targetTextLength = tempDiv.textContent?.length || 0;\n tempDiv.innerHTML = elementContent;\n const elementTextLength = tempDiv.textContent?.length || 0;\n const mergedContent = direction === 'before'\n ? targetContent + elementContent\n : elementContent + targetContent;\n element.innerHTML = mergedContent;\n target.remove();\n // Position cursor at the merge boundary\n const cursorOffset = direction === 'before'\n ? targetTextLength\n : elementTextLength;\n editable.createCursorAtCharacterOffset({ element, offset: cursorOffset });\n },\n empty(element) {\n log('Default empty behavior');\n },\n switch(element, direction, cursor) {\n switch (direction) {\n case 'before':\n const prevSibling = element.previousElementSibling;\n if (prevSibling) {\n const prevCursor = editable.createCursorAtEnd(prevSibling);\n if (prevCursor)\n prevCursor.setVisibleSelection();\n }\n break;\n case 'after':\n const nextSibling = element.nextElementSibling;\n if (nextSibling) {\n const nextCursor = editable.createCursorAtBeginning(nextSibling);\n if (nextCursor)\n nextCursor.setVisibleSelection();\n }\n break;\n }\n },\n move(element, selection, direction) {\n log('Default move behavior');\n },\n paste(element, blocks, cursor) {\n cursor.insertBefore(blocks[0]);\n if (blocks.length <= 1) {\n cursor.setVisibleSelection();\n return;\n }\n const parent = element.parentNode;\n if (!parent)\n return;\n let currentElement = element;\n blocks.slice(1).forEach((str) => {\n const newElement = element.cloneNode(false);\n if (newElement.id)\n newElement.removeAttribute('id');\n const fragment = content.createFragmentFromString(str);\n newElement.appendChild(fragment);\n parent.insertBefore(newElement, currentElement.nextSibling);\n currentElement = newElement;\n });\n // focus last element\n const lastCursor = editable.createCursorAtEnd(currentElement);\n if (lastCursor)\n lastCursor.setVisibleSelection();\n },\n clipboard(element, action, cursor) {\n log('Default clipboard behavior');\n },\n toggleBold(selection) {\n selection.toggleBold();\n },\n toggleEmphasis(selection) {\n selection.toggleEmphasis();\n }\n };\n}\n//# sourceMappingURL=create-default-behavior.js.map","import NodeIterator from '../node-iterator.js';\nexport function textNodesUnder(node) {\n const iterator = new NodeIterator(node, 'getNextTextNode');\n return [...iterator];\n}\n// NOTE: if there is only one text node, then just that node and\n// the abs offset are returned\nexport function getTextNodeAndRelativeOffset({ textNodes, absOffset }) {\n let cumulativeOffset = 0;\n let relativeOffset = 0;\n let targetNode;\n for (let i = 0; i < textNodes.length; i++) {\n const node = textNodes[i];\n const nodeLength = node.textContent?.length || 0;\n if (absOffset <= cumulativeOffset + nodeLength) {\n targetNode = node;\n relativeOffset = absOffset - cumulativeOffset;\n break;\n }\n cumulativeOffset += nodeLength;\n }\n return { node: targetNode, relativeOffset };\n}\nexport function getTotalCharCount(element) {\n const textNodes = textNodesUnder(element);\n const reducer = (acc, node) => acc + (node.textContent?.length || 0);\n return textNodes.reduce(reducer, 0);\n}\n//# sourceMappingURL=element.js.map","import { getTotalCharCount, textNodesUnder, getTextNodeAndRelativeOffset } from './element.js';\n/**\n * This is a binary search algorithm implementation aimed at finding\n * a character offset position in a consecutive strings of characters\n * over several lines.\n *\n * Refer to this page in order to learn more about binary search:\n * https://en.wikipedia.org/wiki/Binary_search_algorithm\n *\n * @returns {object}\n * - object with boolean `wasFound` indicating if the binary search found an offset and `offset` to indicate the actual character offset\n */\nexport function binaryCursorSearch({ host, requiredOnFirstLine, requiredOnLastLine, positionX // coordinates relative to viewport (e.g. from getBoundingClientRect())\n }) {\n const hostRange = host.ownerDocument.createRange();\n hostRange.selectNodeContents(host);\n // JSDOM doesn't support getBoundingClientRect on Range, use element instead\n let hostCoords;\n try {\n hostCoords = hostRange.getBoundingClientRect();\n }\n catch (e) {\n // Fallback for JSDOM\n hostCoords = host.getBoundingClientRect() || {\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n width: 0,\n height: 0,\n x: 0,\n y: 0,\n toJSON: () => ({})\n };\n }\n const totalCharCount = getTotalCharCount(host);\n const textNodes = textNodesUnder(host);\n // early terminate on empty editables\n if (totalCharCount === 0)\n return { wasFound: false };\n const data = {\n currentOffset: Math.floor(totalCharCount / 2),\n leftLimit: 0,\n rightLimit: totalCharCount\n };\n let offset = data.currentOffset;\n let distance = 0;\n let safety = 20;\n while (data.leftLimit < data.rightLimit && safety > 0) {\n safety = safety - 1;\n offset = data.currentOffset;\n const range = createRangeAtCharacterOffset({ textNodes, offset: data.currentOffset });\n // JSDOM doesn't support getBoundingClientRect on Range\n let coords;\n try {\n coords = range.getBoundingClientRect();\n }\n catch (e) {\n // Fallback for JSDOM - use a mock DOMRect\n coords = {\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n width: 0,\n height: 0,\n x: 0,\n y: 0,\n toJSON: () => ({})\n };\n }\n distance = Math.abs(coords.left - positionX);\n // up / down axis\n if (requiredOnFirstLine && hostCoords.top !== coords.top) {\n moveLeft(data);\n continue;\n }\n else if (requiredOnLastLine && hostCoords.bottom !== coords.bottom) {\n moveRight(data);\n continue;\n }\n // left / right axis\n if (positionX < coords.left) {\n moveLeft(data);\n }\n else {\n moveRight(data);\n }\n }\n const range = createRangeAtCharacterOffset({ textNodes, offset: data.currentOffset });\n // JSDOM doesn't support getBoundingClientRect on Range\n let coords;\n try {\n coords = range.getBoundingClientRect();\n }\n catch (e) {\n // Fallback for JSDOM\n coords = {\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n width: 0,\n height: 0,\n x: 0,\n y: 0,\n toJSON: () => ({})\n };\n }\n const finalDistance = Math.abs(coords.left - positionX);\n // Decide if last or second last offset is closest\n if (finalDistance < distance) {\n distance = finalDistance;\n offset = data.currentOffset;\n }\n return { distance, offset, wasFound: true };\n}\n// move the binary search index in between the current position and the left limit\nfunction moveLeft(data) {\n data.rightLimit = data.currentOffset;\n data.currentOffset = Math.floor((data.currentOffset + data.leftLimit) / 2);\n}\n// move the binary search index in between the current position and the right limit\nfunction moveRight(data) {\n data.leftLimit = data.currentOffset;\n data.currentOffset = Math.ceil((data.currentOffset + data.rightLimit) / 2);\n}\nfunction createRangeAtCharacterOffset({ textNodes, offset }) {\n const { node, relativeOffset } = getTextNodeAndRelativeOffset({ textNodes, absOffset: offset });\n if (!node)\n throw new Error('Could not find text node for offset');\n const newRange = node.ownerDocument.createRange();\n newRange.setStart(node, relativeOffset);\n newRange.collapse(true);\n return newRange;\n}\n//# sourceMappingURL=binary_search.js.map","import config from './config.js';\nimport error from './util/error.js';\nimport * as parser from './parser.js';\nimport * as block from './block.js';\nimport * as content from './content.js';\nimport * as clipboard from './clipboard.js';\nimport Dispatcher from './dispatcher.js';\nimport Cursor from './cursor.js';\nimport highlightSupport from './highlight-support.js';\nimport MonitoredHighlighting from './monitored-highlighting.js';\nimport createDefaultEvents from './create-default-events.js';\nimport { textNodesUnder, getTextNodeAndRelativeOffset } from './util/element.js';\nimport { binaryCursorSearch } from './util/binary_search.js';\nimport { domArray, createRange, nodeContainsRange } from './util/dom.js';\nexport class Editable {\n constructor(instanceConfig) {\n const defaultInstanceConfig = {\n window: window,\n defaultBehavior: true,\n mouseMoveSelectionChanges: false,\n browserSpellcheck: true\n };\n this.config = Object.assign(defaultInstanceConfig, instanceConfig);\n this.win = this.config.window;\n this.editableSelector = `.${config.editableClass}`;\n this.dispatcher = new Dispatcher(this);\n if (this.config.defaultBehavior === true) {\n this.dispatcher.on(createDefaultEvents(this));\n }\n }\n static getGlobalConfig() {\n return config;\n }\n static globalConfig(globalConfig) {\n Object.assign(config, globalConfig);\n clipboard.updateConfig(config);\n }\n add(target, options) {\n this.enable(target, options);\n return this;\n }\n remove(target) {\n const targets = domArray(target, this.win.document);\n this.disable(targets);\n for (const element of targets) {\n element.classList.remove(config.editableDisabledClass);\n }\n return this;\n }\n disable(target) {\n const targets = domArray(target || `.${config.editableClass}`, this.win.document);\n for (const element of targets) {\n block.disable(element);\n }\n return this;\n }\n enable(target, options) {\n const opts = typeof options === 'boolean' ? { normalize: options } : (options ?? {});\n const { normalize = false, plainText = false } = opts;\n const shouldSpellcheck = this.config.browserSpellcheck;\n const targets = domArray(target || `.${config.editableDisabledClass}`, this.win.document);\n for (const element of targets) {\n block.init(element, { normalize, plainText, shouldSpellcheck });\n this.dispatcher.notify('init', element);\n }\n return this;\n }\n suspend(target) {\n const targets = domArray(target || `.${config.editableClass}`, this.win.document);\n for (const element of targets) {\n element.removeAttribute('contenteditable');\n }\n this.dispatcher.suspend();\n return this;\n }\n continue(target) {\n const targets = domArray(target || `.${config.editableClass}`, this.win.document);\n for (const element of targets) {\n element.setAttribute('contenteditable', 'true');\n }\n this.dispatcher.continue();\n return this;\n }\n createCursor(element, position = 'beginning') {\n const host = Cursor.findHost(element, this.editableSelector);\n if (!host)\n return undefined;\n const range = createRange(this.win);\n if (position === 'beginning' || position === 'end') {\n range.selectNodeContents(element);\n range.collapse(position === 'beginning');\n }\n else if (element !== host) {\n if (position === 'before') {\n range.setStartBefore(element);\n range.setEndBefore(element);\n }\n else if (position === 'after') {\n range.setStartAfter(element);\n range.setEndAfter(element);\n }\n }\n else {\n error('EditableJS: cannot create cursor outside of an editable block.');\n }\n return new Cursor(host, range);\n }\n createCursorAtCharacterOffset({ element, offset }) {\n const textNodes = textNodesUnder(element);\n const { node, relativeOffset } = getTextNodeAndRelativeOffset({ textNodes, absOffset: offset });\n if (!node)\n throw new Error('Could not find text node for offset');\n const newRange = createRange(this.win);\n newRange.setStart(node, relativeOffset);\n newRange.collapse(true);\n const host = Cursor.findHost(element, this.editableSelector);\n if (!host)\n throw new Error('No editable host found');\n const nextCursor = new Cursor(host, newRange);\n nextCursor.setVisibleSelection();\n return nextCursor;\n }\n createCursorAtBeginning(element) {\n return this.createCursor(element, 'beginning');\n }\n createCursorAtEnd(element) {\n return this.createCursor(element, 'end');\n }\n createCursorBefore(element) {\n return this.createCursor(element, 'before');\n }\n createCursorAfter(element) {\n return this.createCursor(element, 'after');\n }\n getContent(element) {\n return content.extractContent(element);\n }\n appendTo(inputElement, contentToAppend) {\n const element = content.adoptElement(inputElement, this.win.document);\n const cursor = this.createCursor(element, 'end');\n if (!cursor)\n throw new Error('Could not create cursor');\n cursor.insertAfter(typeof contentToAppend === 'string'\n ? content.createFragmentFromString(contentToAppend)\n : contentToAppend);\n return cursor;\n }\n prependTo(inputElement, contentToPrepend) {\n const element = content.adoptElement(inputElement, this.win.document);\n const cursor = this.createCursor(element, 'beginning');\n if (!cursor)\n throw new Error('Could not create cursor');\n cursor.insertBefore(typeof contentToPrepend === 'string'\n ? content.createFragmentFromString(contentToPrepend)\n : contentToPrepend);\n return cursor;\n }\n getSelection(editableHost) {\n const selection = this.dispatcher.selectionWatcher.getFreshSelection();\n if (!editableHost || !selection)\n return selection;\n const range = selection.range;\n if (editableHost?.isConnected && nodeContainsRange(editableHost, range)) {\n return selection;\n }\n return undefined;\n }\n setupHighlighting(hightlightingConfig) {\n this.highlighting = new MonitoredHighlighting(this, hightlightingConfig, undefined);\n return this;\n }\n setupSpellcheck(conf) {\n let marker;\n if (conf.markerNode) {\n marker = conf.markerNode.outerHTML;\n }\n this.setupHighlighting({\n throttle: conf.throttle,\n spellcheck: {\n marker: marker,\n spellcheckService: conf.spellcheckService\n }\n });\n this.spellcheck = {\n checkSpelling: (elem) => {\n this.highlighting?.highlight(elem);\n }\n };\n return this;\n }\n highlight({ editableHost, text, highlightId, textRange, raiseEvents, type = 'comment' }) {\n if (!textRange) {\n const result = highlightSupport.highlightText(editableHost, text, highlightId, type, raiseEvents ? this.dispatcher : undefined, this.win);\n return result || -1;\n }\n if (typeof textRange.start !== 'number' || typeof textRange.end !== 'number') {\n error('Error in Editable.highlight: You passed a textRange object with invalid keys. Expected shape: { start: Number, end: Number }');\n return -1;\n }\n if (textRange.start === textRange.end) {\n error('Error in Editable.highlight: You passed a textRange object with equal start and end offsets, which is considered a cursor and therefore unfit to create a highlight.');\n return -1;\n }\n return highlightSupport.highlightRange(editableHost, text, highlightId, textRange.start, textRange.end, raiseEvents ? this.dispatcher : undefined, this.win, type);\n }\n getHighlightPositions({ editableHost, type }) {\n const result = highlightSupport.extractHighlightedRanges(editableHost, type);\n if (!result)\n return {};\n // Convert the result to TextRange format (without nativeRange)\n const textRanges = {};\n for (const highlightId in result) {\n const { start, end, text } = result[highlightId];\n textRanges[highlightId] = { start, end, text };\n }\n return textRanges;\n }\n removeHighlight({ editableHost, highlightId, raiseEvents }) {\n highlightSupport.removeHighlight(editableHost, highlightId, raiseEvents ? this.dispatcher : undefined);\n }\n decorateHighlight({ editableHost, highlightId, addCssClass, removeCssClass }) {\n highlightSupport.updateHighlight(editableHost, highlightId, addCssClass, removeCssClass);\n }\n on(event, handler) {\n this.dispatcher.on(event, handler);\n return this;\n }\n off(...args) {\n this.dispatcher.off.apply(this.dispatcher, args);\n return this;\n }\n unload() {\n this.dispatcher.unload();\n return this;\n }\n findClosestCursorOffset({ element, origCoordinates, requiredOnFirstLine = false, requiredOnLastLine = false }) {\n const positionX = this.dispatcher.switchContext && this.dispatcher.switchContext.positionX !== undefined\n ? this.dispatcher.switchContext.positionX\n : origCoordinates.left;\n return binaryCursorSearch({\n host: element,\n requiredOnFirstLine,\n requiredOnLastLine,\n positionX\n });\n }\n}\n// Expose modules and editable\nEditable.parser = parser;\nEditable.content = content;\n// Set up callback functions for several events.\nconst eventNames = ['focus', 'blur', 'flow', 'selection', 'cursor', 'newline',\n 'insert', 'split', 'merge', 'empty', 'change', 'switch',\n 'move', 'clipboard', 'paste', 'spellcheckUpdated', 'selectToBoundary'];\neventNames.forEach((name) => {\n // Generate a callback function to subscribe to an event.\n Editable.prototype[name] = function (handler) {\n return this.on(name, handler);\n };\n});\n//# sourceMappingURL=core.js.map"],"names":["config","log","logErrors","editableClass","editableDisabledClass","pastingAttribute","trimLeadingAndTrailingWhitespaces","boldMarkup","type","name","attribs","trim","italicMarkup","underlineMarkup","linkMarkup","pastedHtmlRules","allowedElements","a","href","rel","target","strong","em","br","allowedPlainTextElements","requiredAttributes","transformElements","b","i","splitIntoBlocks","blockLevelElements","blacklistedElements","keepInternalRelativeLinks","replaceQuotes","error","args","errorArgs","length","global","console","toString","Object","prototype","htmlCharacters","trimRight","text","replace","isString","obj","call","NodeIterator","constructor","root","method","this","current","previous","nextNode","iteratorFunc","Symbol","iterator","getNextTextNode","next","getNext","nodeType","data","getPreviousTextNode","prev","getPrevious","value","done","child","n","firstChild","getAttribute","nextSibling","parentNode","lastChild","prevSibling","previousSibling","replaceCurrent","replacement","domArray","documentOrHost","host","doc","querySelectorAll","ownerDocument","container","Array","from","tagName","isArray","domSelector","document","querySelector","createElement","html","win","window","el","innerHTML","firstElementChild","closest","elem","selector","currentNode","createRange","getSelection","docSelection","getNodes","range","nodeTypes","filterFunc","nodes","nodeIterator","createNodeIterator","commonAncestorContainer","NodeFilter","SHOW_ALL","acceptNode","node","intersectsNode","includes","FILTER_ACCEPT","FILTER_SKIP","push","normalizeBoundaries","startContainer","compareDocumentPosition","endContainer","Node","DOCUMENT_POSITION_FOLLOWING","setStartBefore","DOCUMENT_POSITION_PRECEDING","setEndAfter","isCharacterDataNode","TEXT_NODE","COMMENT_NODE","splitDataNode","offset","splitText","toCharacterRange","startRange","cloneRange","setStart","setEnd","startOffset","rangeText","start","end","rangesAreEqual","range1","range2","endOffset","findStartExcludingWhitespace","whitespacesOnTheLeft","childNodes","offsetAfterWhitespace","previousTextNode","Error","findEndExcludingWhitespace","whitespacesOnTheRight","isFirstNode","offsetBeforeWhitespace","getHost","jquery","classList","contains","result","getNodeIndex","index","isVoid","isVoidTextNode","nodeValue","isWhitespaceOnly","lastOffsetWithContent","isLinebreak","string.trimRight","lastOffset","reverse","every","isBeginningOfHost","isStartOffset","offsetInParent","isEndOfHost","isEndOffset","isTextEndOfHost","isTextEndOffset","isSameNode","source","len","attr","nodeName","targetElem","sourceElem","attributes","isDocumentFragmentWithoutChildren","fragment","element","currentStyle","getComputedStyle","display","warn","boundaryMarkerId","isSecondChildOfCommonAncestor","rangeContainer","parent","possibleChild","parentElement","insertRangeBoundaryMarker","atStart","ownerDoc","defaultView","markerEl","id","setAttribute","style","lineHeight","appendChild","createTextNode","directlyBeforeFormatTag","directlyAfterFormatTag","startParentElem","insertBefore","endParentElem","boundaryRange","collapse","insertNode","setRangeBoundary","markerId","getMarker","remove","save","rangeInfo","startEl","endEl","collapsed","startMarkerId","endMarkerId","setEndBefore","setStartAfter","restore","restored","previousNode","restoreRange","func","savedRange","rangeSaveRestore.save","rangeSaveRestore.restore","zeroWidthSpace","zeroWidthNonBreakingSpace","whitespaceExceptSpace","everythingWhitespace","leadingWhitespace","trailingWhitespace","tidyHtml","normalizeTags","createDocumentFragment","removeWhitespaces","nodesToProcess","processedIndices","Set","has","textContent","mergedNode","cloneNode","j","sibling","parser.isSameNode","siblingChild","add","removeChild","normalizeWhitespace","cleanInternals","extractContent","keepUiElements","innerHtml","getInnerHtmlOfFragment","clone","unwrapInternalNodes","documentFragment","div","children","createFragmentFromString","htmlString","wrapper","adoptElement","adoptNode","cloneRangeContents","cloneContents","firstCall","test","startsWith","unwrap","getTags","innerTags","getInnerTags","ancestorTags","getAncestorTags","concat","tags","getTagsByName","toUpperCase","getTagsByNameAndAttributes","areSameAttributes","attrs1","attrs2","attr1","attr2","getNamedItem","getContainedTags","filter","nodeRange","selectNodeContents","comparisonStart","compareBoundaryPoints","Range","START_TO_START","comparisonEnd","END_TO_END","containsNodeText","getTagNames","elements","map","isExactSelection","visible","elemRange","END_TO_START","elemText","string.trim","expandTo","toggleTag","elems","removeFormattingElem","forceWrap","isWrappable","boundariesInvalid","ELEMENT_NODE","isNodeFullyContained","canSurroundContents","restoredRange","nukeElem","nuke","wrap","surroundContents","removeFormatting","forEach","matches","insertCharacter","character","insertEl","surround","startCharacter","endCharacter","deleteCharacter","containsString","selection","rangeCount","newStartContainer","splitBoundaries","indexOf","textNode","RegExp","str","some","nextBlockId","init","normalize","plainText","shouldSpellcheck","hasAttribute","setBlockId","String","Boolean","content.tidyHtml","disable","removeAttribute","setState","isPlainTextBlock","doubleQuotePairs","singleQuotePairs","apostrophe","quotesRegex","beforeOpeningQuote","afterClosingQuote","replacements","replaceAllQuotes","replaceQuotesRules","quotes","singleQuotes","matchAll","match","char","before","after","getAllQuotes","replaceMatchedQuotes","replaceExistingQuotes","position","closingTag","findClosingQuote","nestedMatches","slice","replaceApostrophe","openingQuote","possibleClosingSingleQuotes","getPossibleClosingQuotes","possibleClosingDoubleQuotes","allPossibleDoubleClosers","allPossibleSingleClosers","hasStraightQuoteFallback","isStraightQuote","bestStraightQuoteMatch","candidateChar","candidateAfter","pairs","quotePair","quote","whitespaceOnly","blockPlaceholder","updateConfig","conf","rules","paste","block","cursor","clipboardContent","isSelection","deleteExactSurroundingTags","deleteContainedTags","deleteContent","pasteHolder","blocks","filterHtmlElements","split","entry","quotes.replaceAllQuotes","group","parseContent","options","reduce","content","toLowerCase","childElement","hrefAttr","stripInternalHost","location","origin","transformNodeName","requiredAttrs","hasRequiredAttributes","shouldKeepNode","filterAttributes","conditionalNodeWrap","c","documentElement","contentEditable","isBlink","navigator","userAgent","isWebkit","webKit","selectionchange","osc","onselectionchange","e","hasNativeSelectionchangeSupport","contenteditableSpanBug","eventable","notifyContext","events","listeners","addListener","listener","event","unshift","removeListener","eventListeners","splice","on","eventOrEvents","arguments","eventType","off","keys","key","notify","context","allArgs","actualContext","actualEvent","actualArgs","switchContext","shift","apply","getEventableModule","getScrollPosition","x","pageXOffset","body","scrollLeft","y","pageYOffset","scrollTop","Cursor","findHost","editableHost","setHost","isCursor","content.getTags","content.getTagNames","content.getTagsByName","content.getInnerTags","content.getContainedTags","content.getAncestorTags","isAtEnd","parser.isEndOfHost","isAtTextEnd","parser.isTextEndOfHost","isAtLastLine","hostRange","hostCoords","getRangeBoundingClientRect","cursorCoords","isCloseTo","bottom","isAtFirstLine","top","isAtBeginning","parser.isBeginningOfHost","string.isString","content.createFragmentFromString","parser.isDocumentFragmentWithoutChildren","preceedingElement","lastIndex","insertAfter","setSelection","setVisibleSelection","activeElement","viewport.getScrollPosition","scrollTo","removeAllRanges","addRange","content.cloneRangeContents","textBefore","beforeHtml","content.getInnerHtmlOfFragment","textAfter","afterHtml","getBoundingClientRect","getCoordinates","positioning","coords","left","right","height","width","moveBefore","updateHost","moveAfter","moveAtBeginning","moveAtEnd","moveAtTextEnd","parser.lastChild","parser.getHost","retainVisibleSelection","callback","savedRangeInfo","equals","isEqualNode","attributeName","attributeValue","content.adoptElement","triggerChange","Event","bubbles","cancelable","dispatchEvent","Math","abs","highlightText","extractText","convertBRs","getText","part","highlightMatches","countBRs","currentMatchIndex","totalOffset","currentMatch","portions","wordId","startIndex","nodeText","nodeEndOffset","endIndex","isFirstPortion","isLastPortion","portion","substring","lastNode","wrapMatch","marker","title","stencilElement","wrapPortion","pop","findMatches","searchTexts","matchMode","HTMLElement","isElement","regex","createWordRegex","createHighlightRegex","matchedText","words","word","escapeRegEx","join","letterChars","escapedWords","s","highlightSupport","highlightId","dispatcher","hasHighlight","blockText","winWindow","markerNode","createMarkerNode","searchTerm","searchText","highlightRange","removeHighlight","actualStartIndex","actualEndIndex","updateHighlight","addCssClass","removeCssClass","content.unwrap","extractHighlightedRanges","findMarkersQuery","markers","groups","res","extractMarkerNodePosition","selectNode","textRange","nativeRange","cleanupStaleMarkerNodes","highlightType","markerMarkup","Selection","super","rangeToHtml","isAllSelected","getTextRange","content.isWrappable","getRects","getClientRects","link","attrs","trimRange","textToTrim","search","lastNonWhitespace","unlink","toggleLink","links","firstLink","highlightComment","highlight","currentTextContent","toggle","block.isPlainTextBlock","newRange","content.toggleTag","toggleCustom","customElem","makeCustom","makeBold","bold","toggleBold","giveEmphasis","toggleEmphasis","makeUnderline","u","toggleUnderline","content.surround","removeSurround","content.deleteCharacter","removeChars","chars","toggleSurround","content.removeFormatting","ancestorTag","containedTag","deleteContents","content.expandTo","collapseAtBeginning","collapseAtEnd","content.forceWrap","onlyVisible","content.isExactSelection","content.containsString","RangeContainer","isAnythingSelected","getCursor","forceCursor","isDifferentFrom","otherRangeContainer","self","other","SelectionWatcher","currentSelection","currentRange","syncSelection","err","getRangeContainer","successfulSync","getRangeAt","hostNode","getFreshRange","getFreshSelection","selectionChanged","newRangeContainer","lastSelection","Keyboard","selectionWatcher","dispatchKeyEvent","notifyCharacterEvent","keyCode","up","down","tab","shiftKey","esc","backspace","preventContenteditableBug","delete","enter","ctrl","alt","ctrlKey","metaKey","nodeToRemove","getNodeToRemove","selectionRange","startNodeElement","startNodeRange","testRange","containerRange","contentNodeTypes","firstContentNode","rangeStartingBeforeCurrentElement","isValidQuotePairConfig","isDoubleQuote","isSingleQuote","isApostrophe","isSeparatorOrWhitespace","replaceQuote","quoteType","newText","newTextNode","replaceWith","applySmartQuotes","cursorOffset","isCharSingleQuote","textArr","indexCharBefore","shouldBeClosingQuote","indexCharAfter","hasCharAfter","singleOpeningQuote","hasSingleOpeningQuote","closingQuote","shouldBeOpeningQuote","Dispatcher","editable","editableSelector","keyboard","activeListeners","setup","getEditableBlockByEvent","evt","setupDocumentListener","capture","bind","addEventListener","setupKeyboardEvents","setupEventListeners","unload","l","removeEventListener","suspend","suspended","setupElementListeners","setupKeydownListener","setupSelectionChangeListeners","setupSelectionChangeFallbackListeners","currentInput","clipEvent","preventDefault","clipboardData","getData","clipboard.paste","innerText","searchValue","replaceValue","lastOccurrenceIndex","lastIndexOf","replaceLast","smartQuotes","isContentEditable","shouldApplySmartQuotes","inputEvent","quotesConfig","setTimeout","dispatchSwitchEvent","direction","altKey","positionX","stopPropagation","keyEvent","editableBlock","beforeFragment","afterFragment","selectionDirty","suppressSelectionChanges","didSyncSelection","mouseMoveSelectionChanges","once","notifySelectionBoundary","deepMerge","sources","hasOwnProperty","sourceValue","targetValue","SpellcheckService","spellcheckService","check","condensedText","content.normalizeWhitespace","misspelledWords","characters","A0","specialWhitespaceCharsRegex","WhitespaceHighlighting","prepareMatch","unicode","charCodeAt","description","MatchCollection","addMatches","matches1","matches2","length1","length2","lastEndIndex","output","state","a1","i1","a2","i2","pickNext","mergeMatches","item1","item2","MonitoredHighlighting","configuration","spellcheckConfig","focusedEditableHost","currentlyCheckedEditableHost","timeout","checkOnInit","checkOnFocus","checkOnChange","throttle","removeOnCorrection","spellcheck","whitespace","spellcheckMarker","whitespaceMarker","whitespaceMarkerNode","spellcheckMarkerNode","setupListeners","onFocus","onBlur","onChange","onInit","editableHasChanged","removeHighlightsAtCursor","clearTimeout","timeoutId","isConnected","matchCollection","searchAllWords","whitespaceMatches","m","safeHighlightMatches","removeHighlights","elementAtCursor","logArgs","trace","createDefaultEvents","behavior","focus","parser.isVoid","blur","content.cleanInternals","newline","insert","newElement","createCursorAtEnd","newNode","merge","previousElementSibling","nextElementSibling","targetContent","content.extractContent","elementContent","tempDiv","targetTextLength","elementTextLength","mergedContent","createCursorAtCharacterOffset","empty","prevCursor","nextCursor","createCursorAtBeginning","move","currentElement","lastCursor","clipboard","action","createDefaultBehavior","switch","textNodesUnder","getTextNodeAndRelativeOffset","textNodes","absOffset","targetNode","cumulativeOffset","relativeOffset","nodeLength","binaryCursorSearch","requiredOnFirstLine","requiredOnLastLine","toJSON","totalCharCount","acc","wasFound","currentOffset","floor","leftLimit","rightLimit","distance","safety","createRangeAtCharacterOffset","moveLeft","moveRight","finalDistance","ceil","Editable","instanceConfig","defaultInstanceConfig","defaultBehavior","browserSpellcheck","assign","getGlobalConfig","globalConfig","clipboard.updateConfig","enable","targets","block.disable","opts","block.init","continue","createCursor","createCursorBefore","createCursorAfter","getContent","appendTo","inputElement","contentToAppend","prependTo","contentToPrepend","nodeContainsRange","setupHighlighting","hightlightingConfig","highlighting","setupSpellcheck","outerHTML","checkSpelling","raiseEvents","getHighlightPositions","textRanges","decorateHighlight","handler","findClosestCursorOffset","origCoordinates","parser"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"editable.umd.cjs","sources":["../lib/config.js","../lib/util/error.js","../lib/util/string.js","../lib/node-iterator.js","../lib/node-type.js","../lib/util/dom.js","../lib/parser.js","../lib/range-save-restore.js","../lib/content.js","../lib/block.js","../lib/quotes.js","../lib/clipboard.js","../lib/feature-detection.js","../lib/eventable.js","../lib/util/viewport.js","../lib/cursor.js","../lib/highlight-text.js","../lib/plugins/highlighting/text-search.js","../lib/highlight-support.js","../lib/selection.js","../lib/range-container.js","../lib/selection-watcher.js","../lib/keyboard.js","../lib/smartQuotes.js","../lib/dispatcher.js","../lib/util/merge.js","../lib/plugins/highlighting/spellcheck-service.js","../lib/plugins/highlighting/whitespace-highlighting.js","../lib/plugins/highlighting/match-collection.js","../lib/monitored-highlighting.js","../lib/plugins/text-diff/diff-algorithm.js","../lib/plugins/text-diff/text-diff.js","../lib/util/log.js","../lib/create-default-events.js","../lib/create-default-behavior.js","../lib/util/element.js","../lib/util/binary_search.js","../lib/core.js"],"sourcesContent":["const config = {\n log: false,\n logErrors: true,\n editableClass: 'js-editable',\n editableDisabledClass: 'js-editable-disabled',\n pastingAttribute: 'data-editable-is-pasting',\n trimLeadingAndTrailingWhitespaces: true,\n boldMarkup: {\n type: 'tag',\n name: 'strong',\n attribs: {},\n trim: true\n },\n italicMarkup: {\n type: 'tag',\n name: 'em',\n attribs: {},\n trim: true\n },\n underlineMarkup: {\n type: 'tag',\n name: 'u',\n attribs: {},\n trim: false\n },\n linkMarkup: {\n type: 'tag',\n name: 'a',\n attribs: {},\n trim: true\n },\n pastedHtmlRules: {\n allowedElements: {\n 'a': {\n 'href': true,\n 'rel': true,\n 'target': true\n },\n 'strong': {},\n 'em': {},\n 'br': {}\n },\n allowedPlainTextElements: {\n 'br': {}\n },\n requiredAttributes: {\n 'a': ['href']\n },\n transformElements: {\n 'b': 'strong',\n 'i': 'em'\n },\n splitIntoBlocks: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'blockquote'],\n blockLevelElements: [\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'p', 'pre', 'hr', 'blockquote',\n 'article', 'figure', 'header', 'footer', 'ul', 'ol', 'li', 'section', 'table', 'video'\n ],\n blacklistedElements: ['style', 'script'],\n keepInternalRelativeLinks: false,\n replaceQuotes: {}\n }\n};\nexport default config;\n//# sourceMappingURL=config.js.map","import config from '../config.js';\n// Allows for safe error logging\n// Falls back to console.log if console.error is not available\nexport default function error(...args) {\n if (config.logErrors === false)\n return;\n const errorArgs = args.length === 1 ? args[0] : args;\n if (!global.console)\n return;\n if (typeof console.error === 'function') {\n console.error(errorArgs);\n return;\n }\n console.log(errorArgs);\n}\n//# sourceMappingURL=error.js.map","const toString = Object.prototype.toString;\nconst htmlCharacters = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n};\n// TODO: replace with lodash methods\nexport function trimRight(text) {\n return text.replace(/\\s+$/, '');\n}\nexport function trimLeft(text) {\n return text.replace(/^\\s+/, '');\n}\nexport function trim(text) {\n return text.replace(/^\\s+|\\s+$/g, '');\n}\nexport function isString(obj) {\n return toString.call(obj) === '[object String]';\n}\n/**\n * Turn any string into a regular expression.\n * This can be used to search or replace a string conveniently.\n */\nexport function regexp(str, flags) {\n if (!flags)\n flags = 'g';\n const escapedStr = str.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n return new RegExp(escapedStr, flags);\n}\n/**\n * Escape HTML characters <, > and &\n * Usage: escapeHtml('<div>')\n *\n * @param { String }\n * @param { Boolean } Optional. If true \" and ' will also be escaped.\n * @return { String } Escaped Html you can assign to innerHTML of an element.\n */\n// TODO: replace with npm.im/he\nexport function escapeHtml(s, forAttribute) {\n return s.replace(forAttribute ? /[&<>'\"]/g : /[&<>]/g, function (c) {\n return htmlCharacters[c] || c;\n });\n}\n/**\n * Escape a string the browser way.\n */\nexport function browserEscapeHtml(str) {\n const div = document.createElement('div');\n div.appendChild(document.createTextNode(str));\n return div.innerHTML;\n}\nexport function replaceLast(text, searchValue, replaceValue) {\n if (!text)\n return '';\n text = `${text}`;\n if (!searchValue || replaceValue == null)\n return text;\n const lastOccurrenceIndex = text.lastIndexOf(searchValue);\n if (lastOccurrenceIndex === -1)\n return text;\n return `${text.slice(0, lastOccurrenceIndex)}${replaceValue}${text.slice(lastOccurrenceIndex + searchValue.length)}`;\n}\nexport function endsWithSingleSpace(text) {\n return /\\S+\\s{1}$/.test(text);\n}\n//# sourceMappingURL=string.js.map","import { textNode } from './node-type.js';\n// A DOM node iterator.\n//\n// Has the ability to replace nodes on the fly and continue\n// the iteration.\nexport default class NodeIterator {\n constructor(root, method) {\n this.current = this.previous = this.nextNode = this.root = root;\n this.iteratorFunc = this[method || 'getNext'];\n }\n [Symbol.iterator]() {\n return this;\n }\n getNextTextNode() {\n let next;\n while ((next = this.getNext())) {\n if (next.nodeType === textNode && next.data !== '')\n return next;\n }\n return undefined;\n }\n getPreviousTextNode() {\n let prev;\n while ((prev = this.getPrevious())) {\n if (prev.nodeType === textNode && prev.data !== '')\n return prev;\n }\n return undefined;\n }\n next() {\n const value = this.iteratorFunc();\n return value ? { value } : { done: true, value: undefined };\n }\n getNext() {\n let n = this.current = this.nextNode;\n let child;\n this.nextNode = undefined;\n if (this.current) {\n child = n.firstChild;\n // Skip the children of elements with the attribute data-editable=\"remove\"\n // This prevents text nodes that are not part of the content to be included.\n if (child && n.getAttribute?.('data-editable') !== 'remove') {\n this.nextNode = child;\n }\n else {\n while ((n !== this.root) && n) {\n const nextSibling = n.nextSibling;\n if (nextSibling) {\n this.nextNode = nextSibling;\n break;\n }\n n = n.parentNode;\n }\n }\n }\n return this.current;\n }\n getPrevious() {\n let n = this.current = this.previous;\n let child;\n this.previous = undefined;\n if (this.current) {\n child = n.lastChild;\n // Skip the children of elements with the attribute data-editable=\"remove\"\n // This prevents text nodes that are not part of the content to be included.\n if (child && n.getAttribute?.('data-editable') !== 'remove') {\n this.previous = child;\n }\n else {\n while ((n !== this.root) && n) {\n const prevSibling = n.previousSibling;\n if (prevSibling) {\n this.previous = prevSibling;\n break;\n }\n n = n.parentNode;\n }\n }\n }\n return this.current;\n }\n replaceCurrent(replacement) {\n this.current = replacement;\n this.nextNode = undefined;\n this.previous = undefined;\n let n = this.current;\n while ((n !== this.root) && n) {\n const nextSibling = n.nextSibling;\n if (nextSibling) {\n this.nextNode = nextSibling;\n break;\n }\n n = n.parentNode;\n }\n }\n}\n//# sourceMappingURL=node-iterator.js.map","// DOM node types\n// https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeType\nexport const elementNode = 1;\nexport const attributeNode = 2;\nexport const textNode = 3;\nexport const cdataSectionNode = 4;\nexport const entityReferenceNode = 5;\nexport const entityNode = 6;\nexport const processingInstructionNode = 7;\nexport const commentNode = 8;\nexport const documentNode = 9;\nexport const documentTypeNode = 10;\nexport const documentFragmentNode = 11;\nexport const notationNode = 12;\n//# sourceMappingURL=node-type.js.map","import NodeIterator from '../node-iterator.js';\nimport { textNode } from '../node-type.js';\nexport const domArray = (target, documentOrHost, host) => {\n if (typeof target === 'string') {\n const doc = documentOrHost.querySelectorAll ? documentOrHost : documentOrHost.ownerDocument;\n const container = host || documentOrHost;\n return Array.from(container.querySelectorAll ? container.querySelectorAll(target) : doc.querySelectorAll(target));\n }\n if (target.tagName)\n return [target];\n if (Array.isArray(target))\n return target;\n // Support NodeList and jQuery arrays\n return Array.from(target);\n};\nexport const domSelector = (target, document) => {\n if (typeof target === 'string')\n return document.querySelector(target);\n if (target.tagName)\n return target;\n // Support NodeList and jQuery arrays\n if (target[0])\n return target[0];\n return target;\n};\nexport const createElement = (html, win = window) => {\n const el = win.document.createElement('div');\n el.innerHTML = html;\n return el.firstElementChild;\n};\nexport const closest = (elem, selector) => {\n if (!elem)\n return undefined;\n // For text nodes or other nodes without closest, traverse to parent element\n let currentNode = elem;\n while (currentNode && !currentNode.closest) {\n currentNode = currentNode.parentNode;\n }\n if (currentNode && currentNode.closest) {\n return currentNode.closest(selector);\n }\n return undefined;\n};\nexport const createRange = (win = window) => {\n return win.document.createRange();\n};\nexport const getSelection = (win = window) => {\n const docSelection = win.document.getSelection ? win.document.getSelection() : null;\n if (docSelection)\n return docSelection;\n return win.getSelection ? win.getSelection() : null;\n};\nexport const getNodes = (range, nodeTypes, filterFunc, win = window) => {\n const nodes = [];\n const nodeIterator = win.document.createNodeIterator(range.commonAncestorContainer, NodeFilter.SHOW_ALL, {\n acceptNode(node) {\n if (range.intersectsNode(node) &&\n nodeTypes.includes(node.nodeType) &&\n node !== range.commonAncestorContainer // Exclude the common ancestor container\n ) {\n if (typeof filterFunc === 'function') {\n return filterFunc(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n }\n return NodeFilter.FILTER_ACCEPT;\n }\n return NodeFilter.FILTER_SKIP;\n }\n });\n let currentNode;\n while ((currentNode = nodeIterator.nextNode())) {\n nodes.push(currentNode);\n }\n return nodes;\n};\nexport const normalizeBoundaries = (range) => {\n if (range.startContainer.compareDocumentPosition(range.endContainer) === Node.DOCUMENT_POSITION_FOLLOWING) {\n range.setStartBefore(range.endContainer);\n }\n if (range.endContainer.compareDocumentPosition(range.startContainer) === Node.DOCUMENT_POSITION_PRECEDING) {\n range.setEndAfter(range.startContainer);\n }\n};\nexport const containsRange = (containerRange, testRange) => {\n return (containerRange.compareBoundaryPoints(Range.START_TO_START, testRange) <= 0 &&\n containerRange.compareBoundaryPoints(Range.END_TO_END, testRange) >= 0);\n};\nexport const containsNodeText = (range, node) => {\n const nodeRange = document.createRange();\n nodeRange.selectNodeContents(node);\n const comparisonStart = range.compareBoundaryPoints(Range.START_TO_START, nodeRange);\n const comparisonEnd = range.compareBoundaryPoints(Range.END_TO_END, nodeRange);\n return comparisonStart <= 0 && comparisonEnd >= 0;\n};\nexport const nodeContainsRange = (node, range) => {\n const nodeRange = document.createRange();\n nodeRange.selectNodeContents(node);\n const comparisonStart = range.compareBoundaryPoints(Range.START_TO_START, nodeRange);\n const comparisonEnd = range.compareBoundaryPoints(Range.END_TO_END, nodeRange);\n return comparisonStart >= 0 && comparisonEnd <= 0;\n};\nconst isCharacterDataNode = (node) => {\n return node && (node.nodeType === Node.TEXT_NODE || node.nodeType === Node.COMMENT_NODE);\n};\nconst splitDataNode = (node, offset) => {\n return node.splitText(offset);\n};\nexport const splitBoundaries = (range) => {\n const startContainer = range.startContainer;\n const startOffset = range.startOffset;\n const endContainer = range.endContainer;\n const endOffset = range.endOffset;\n if (isCharacterDataNode(endContainer) && endOffset > 0 && endOffset < endContainer.length) {\n splitDataNode(endContainer, endOffset);\n }\n if (isCharacterDataNode(startContainer) && startOffset > 0 && startOffset < startContainer.length) {\n const newStartContainer = splitDataNode(startContainer, startOffset);\n range.setStart(newStartContainer, 0);\n }\n};\nexport const toCharacterRange = (range, container) => {\n const startRange = range.cloneRange();\n startRange.setStart(container, 0);\n startRange.setEnd(range.startContainer, range.startOffset);\n const rangeText = range.toString();\n const start = startRange.toString().length;\n const end = start + rangeText.length;\n return { start, end, text: rangeText };\n};\nexport const rangesAreEqual = (range1, range2) => {\n return (range1.startContainer === range2.startContainer &&\n range1.startOffset === range2.startOffset &&\n range1.endContainer === range2.endContainer &&\n range1.endOffset === range2.endOffset);\n};\nexport const rangeToHtml = (range, win = window) => {\n const div = win.document.createElement('div');\n div.appendChild(range.cloneContents());\n return div.innerHTML;\n};\nexport const getSelectionCoordinates = (selection) => {\n const range = selection.getRangeAt(0); // Assuming you want coordinates of the first range\n const rects = range.getClientRects();\n const coordinates = [];\n for (let i = 0; i < rects.length; i++) {\n const rect = rects[i];\n coordinates.push({\n top: rect.top,\n left: rect.left,\n bottom: rect.bottom,\n right: rect.right,\n width: rect.width,\n height: rect.height\n });\n }\n return coordinates;\n};\nexport const createRangeFromCharacterRange = (element, actualStartIndex, actualEndIndex) => {\n const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null);\n let currentIndex = 0;\n let startNode = null;\n let endNode = null;\n let startOffset = 0;\n let endOffset = 0;\n while (walker.nextNode()) {\n const node = walker.currentNode;\n const nodeLength = node.nodeValue?.length || 0;\n if (currentIndex + nodeLength <= actualStartIndex) {\n currentIndex += nodeLength;\n continue;\n }\n if (!startNode) {\n startNode = node;\n startOffset = actualStartIndex - currentIndex;\n }\n if (currentIndex + nodeLength >= actualEndIndex) {\n endNode = node;\n endOffset = actualEndIndex - currentIndex;\n break;\n }\n currentIndex += nodeLength;\n }\n if (startNode && endNode) {\n const range = createRange();\n range.setStart(startNode, startOffset);\n range.setEnd(endNode, endOffset);\n return range;\n }\n else {\n throw new Error('Invalid character offsets.');\n }\n};\nexport function findStartExcludingWhitespace({ root, startContainer, startOffset, whitespacesOnTheLeft }) {\n const isTextNode = startContainer.nodeType === textNode;\n if (!isTextNode) {\n return findStartExcludingWhitespace({\n root,\n startContainer: startContainer.childNodes[startOffset],\n startOffset: 0,\n whitespacesOnTheLeft\n });\n }\n const offsetAfterWhitespace = startOffset + whitespacesOnTheLeft;\n if (startContainer.length > offsetAfterWhitespace) {\n return [startContainer, offsetAfterWhitespace];\n }\n // Pass the root so that the iterator can traverse to siblings\n const iterator = new NodeIterator(root);\n // Set the position to the node which is selected\n iterator.nextNode = startContainer;\n // Iterate once to avoid returning self\n iterator.getNextTextNode();\n const container = iterator.getNextTextNode();\n if (!container) {\n // No more text nodes - use the end of the last text node\n const previousTextNode = iterator.getPreviousTextNode();\n if (!previousTextNode)\n throw new Error('No previous text node found');\n return [previousTextNode, previousTextNode.length];\n }\n return findStartExcludingWhitespace({\n root,\n startContainer: container,\n startOffset: 0,\n whitespacesOnTheLeft: offsetAfterWhitespace - startContainer.length\n });\n}\nexport function findEndExcludingWhitespace({ root, endContainer, endOffset, whitespacesOnTheRight }) {\n const isTextNode = endContainer.nodeType === textNode;\n if (!isTextNode) {\n const isFirstNode = !endContainer.childNodes[endOffset - 1];\n const container = isFirstNode\n ? endContainer.childNodes[endOffset]\n : endContainer.childNodes[endOffset - 1];\n let offset = 0;\n if (!isFirstNode) {\n offset = container.nodeType === textNode\n ? container.length\n : container.childNodes.length;\n }\n return findEndExcludingWhitespace({\n root,\n endContainer: container,\n endOffset: offset,\n whitespacesOnTheRight\n });\n }\n const offsetBeforeWhitespace = endOffset - whitespacesOnTheRight;\n if (offsetBeforeWhitespace > 0) {\n return [endContainer, offsetBeforeWhitespace];\n }\n // Pass the root so that the iterator can traverse to siblings\n const iterator = new NodeIterator(root);\n // Set the position to the node which is selected\n iterator.previous = endContainer;\n // Iterate once to avoid returning self\n iterator.getPreviousTextNode();\n const container = iterator.getPreviousTextNode();\n if (!container) {\n // No more text nodes - use the start of the first text node\n const nextNode = iterator.getNextTextNode();\n if (!nextNode)\n throw new Error('No next text node found');\n return [nextNode, 0];\n }\n return findEndExcludingWhitespace({\n root,\n endContainer: container,\n endOffset: container.length,\n whitespacesOnTheRight: whitespacesOnTheRight - endOffset\n });\n}\n//# sourceMappingURL=dom.js.map","import * as string from './util/string.js';\nimport * as nodeType from './node-type.js';\nimport config from './config.js';\nimport { closest } from './util/dom.js';\n/**\n * The parser module provides helper methods to parse html-chunks\n * manipulations and helpers for common tasks.\n * Provides DOM lookup helpers\n *\n * @module core\n * @submodule parser\n */\n/**\n * Get the editableJS host block of a node.\n *\n * @method getHost\n * @param {DOM Node}\n * @return {DOM Node}\n */\nexport function getHost(node) {\n node = (node.jquery ? node[0] : node);\n // Check if the node itself is an editable element\n if (node && node.classList && node.classList.contains(config.editableClass)) {\n return node;\n }\n const result = closest(node, `.${config.editableClass}`);\n if (result)\n return result;\n const contentEditableHost = closest(node, '[contenteditable=\"true\"]');\n return contentEditableHost || null;\n}\n/**\n * Get the index of a node so that\n * parent.childNodes[ getNodeIndex(node) ] would return the node again.\n *\n * @method getNodeIndex\n * @param {HTMLElement}\n */\nexport function getNodeIndex(node) {\n let index = 0;\n let currentNode = node.previousSibling;\n while (currentNode !== null) {\n index++;\n currentNode = currentNode.previousSibling;\n }\n return index;\n}\n/**\n * Check if node contains text or element nodes\n * whitespace counts too!\n *\n * @method isVoid\n * @param {HTMLElement}\n */\nexport function isVoid(node) {\n const childNodes = Array.from(node.childNodes);\n for (const child of childNodes) {\n if (child.nodeType === nodeType.textNode && !isVoidTextNode(child)) {\n return false;\n }\n if (child.nodeType === nodeType.elementNode) {\n return false;\n }\n }\n return true;\n}\n/**\n * Check if node is a text node and completely empty without any whitespace\n *\n * @method isVoidTextNode\n * @param {HTMLElement}\n */\nexport function isVoidTextNode(node) {\n return node.nodeType === nodeType.textNode && !node.nodeValue;\n}\n/**\n * Check if node is a text node and contains nothing but whitespace\n *\n * @method isWhitespaceOnly\n * @param {HTMLElement}\n */\nexport function isWhitespaceOnly(node) {\n return node.nodeType === nodeType.textNode && lastOffsetWithContent(node) === 0;\n}\nexport function isLinebreak(node) {\n return node.nodeType === nodeType.elementNode && node.tagName === 'BR';\n}\n/**\n * Returns the last offset where the cursor can be positioned to\n * be at the visible end of its container.\n * Currently works only for empty text nodes (not empty tags)\n *\n * @method isWhitespaceOnly\n * @param {HTMLElement}\n */\nexport function lastOffsetWithContent(elem) {\n if (elem.nodeType === nodeType.textNode) {\n const nodeValue = elem.nodeValue;\n if (!nodeValue)\n return 0;\n return string.trimRight(nodeValue).length;\n }\n let lastOffset = 0;\n Array.from(elem.childNodes).reverse().every((node, index, nodes) => {\n if (isWhitespaceOnly(node) || isLinebreak(node))\n return true;\n lastOffset = nodes.length - index;\n return false;\n });\n return lastOffset;\n}\nexport function isBeginningOfHost(host, container, offset) {\n if (container === host)\n return isStartOffset(container, offset);\n if (isStartOffset(container, offset)) {\n // The index of the element simulates a range offset\n // right before the element.\n const offsetInParent = getNodeIndex(container);\n const parentNode = container.parentNode;\n if (!parentNode)\n return false;\n return isBeginningOfHost(host, parentNode, offsetInParent);\n }\n return false;\n}\nexport function isEndOfHost(host, container, offset) {\n if (container === host)\n return isEndOffset(container, offset);\n if (isEndOffset(container, offset)) {\n // The index of the element plus one simulates a range offset\n // right after the element.\n const offsetInParent = getNodeIndex(container) + 1;\n const parentNode = container.parentNode;\n if (!parentNode)\n return false;\n return isEndOfHost(host, parentNode, offsetInParent);\n }\n return false;\n}\nexport function isStartOffset(container, offset) {\n if (container.nodeType === nodeType.textNode)\n return offset === 0;\n if (container.childNodes.length === 0)\n return true;\n const firstChild = container.firstChild;\n if (container.childNodes.length === 1 &&\n firstChild &&\n firstChild.nodeType === nodeType.elementNode &&\n firstChild.getAttribute('data-editable') === 'remove')\n return true;\n return container.childNodes[offset] === container.firstChild;\n}\nexport function isEndOffset(container, offset) {\n if (container.nodeType === nodeType.textNode)\n return offset === container.length;\n if (container.childNodes.length === 0)\n return true;\n if (offset > 0)\n return container.childNodes[offset - 1] === container.lastChild;\n return false;\n}\nexport function isTextEndOfHost(host, container, offset) {\n if (container === host)\n return isTextEndOffset(container, offset);\n if (isTextEndOffset(container, offset)) {\n // The index of the element plus one simulates a range offset\n // right after the element.\n const offsetInParent = getNodeIndex(container) + 1;\n const parentNode = container.parentNode;\n if (!parentNode)\n return false;\n return isTextEndOfHost(host, parentNode, offsetInParent);\n }\n return false;\n}\nexport function isTextEndOffset(container, offset) {\n if (container.nodeType === nodeType.textNode) {\n const nodeValue = container.nodeValue;\n if (!nodeValue)\n return offset === 0;\n const text = string.trimRight(nodeValue);\n return offset >= text.length;\n }\n if (container.childNodes.length === 0)\n return true;\n return offset >= lastOffsetWithContent(container);\n}\nexport function isSameNode(target, source) {\n let i, len, attr;\n if (target.nodeType !== source.nodeType)\n return false;\n if (target.nodeName !== source.nodeName)\n return false;\n if (target.nodeType !== 1 || source.nodeType !== 1)\n return true;\n const targetElem = target;\n const sourceElem = source;\n for (i = 0, len = targetElem.attributes.length; i < len; i++) {\n attr = targetElem.attributes[i];\n if (sourceElem.getAttribute(attr.name) !== attr.value)\n return false;\n }\n return true;\n}\n/**\n * Return the deepest last child of a node.\n *\n * @method lastChild\n * @param {HTMLElement} container The container to iterate on.\n * @return {HTMLElement} The deepest last child in the container.\n */\nexport function lastChild(container) {\n return container.lastChild\n ? lastChild(container.lastChild)\n : container;\n}\n/**\n * Obsolete version of {{#crossLink \"lastChild\"}}{{/crossLink}}.\n */\nexport function latestChild(container) {\n console.warn('Editable.js: Using obsolete function parser.latestCild(), use lastChild() instead');\n return lastChild(container);\n}\n/**\n * Checks if a documentFragment has no children.\n * Fragments without children can cause errors if inserted into ranges.\n *\n * @method isDocumentFragmentWithoutChildren\n * @param {HTMLElement} DOM node.\n * @return {Boolean}\n */\nexport function isDocumentFragmentWithoutChildren(fragment) {\n return !!(fragment &&\n fragment.nodeType === nodeType.documentFragmentNode &&\n fragment.childNodes.length === 0);\n}\n/**\n * Determine if an element behaves like an inline element.\n */\nexport function isInlineElement(window, element) {\n const styles = element.currentStyle || window.getComputedStyle(element, '');\n const display = styles.display;\n switch (display) {\n case 'inline':\n case 'inline-block':\n return true;\n default:\n return false;\n }\n}\n//# sourceMappingURL=parser.js.map","import error from './util/error.js';\nimport * as nodeType from './node-type.js';\nimport { createRange, normalizeBoundaries } from './util/dom.js';\n/**\n * Inspired by the Selection save and restore module for Rangy by Tim Down\n * Saves and restores ranges using invisible marker elements in the DOM.\n */\nlet boundaryMarkerId = 0;\n// (U+FEFF) zero width no-break space\nconst markerTextChar = '\\ufeff';\nfunction isSecondChildOfCommonAncestor(range, rangeContainer) {\n const parent = range.commonAncestorContainer;\n if (parent.nodeType === 3)\n return false; // if we are on the text node it can't be a parent\n const possibleChild = rangeContainer.parentElement;\n return possibleChild?.parentElement === parent;\n}\nexport function insertRangeBoundaryMarker(range, atStart) {\n const container = range.commonAncestorContainer;\n // If ownerDocument is null the commonAncestorContainer is window.document\n if (!container.ownerDocument) {\n error('Cannot save range: range is empty');\n throw new Error('Cannot save range: range is empty');\n }\n const ownerDoc = container.ownerDocument;\n if (!ownerDoc.defaultView) {\n error('Cannot save range: document has no defaultView');\n throw new Error('Cannot save range: document has no defaultView');\n }\n // Create the marker element containing a single\n // invisible character using DOM methods and insert it\n const doc = ownerDoc.defaultView.document;\n const markerEl = doc.createElement('span');\n markerEl.id = `editable-range-boundary-${++boundaryMarkerId}`;\n markerEl.setAttribute('data-editable', 'remove');\n markerEl.style.lineHeight = '0';\n markerEl.style.display = 'none';\n markerEl.appendChild(doc.createTextNode(markerTextChar));\n // This logic can expand the selection by inserting the marker before the element\n // of the start or end container. In some cases this prevents breaking up existing tags.\n // The solution is not perfect, but has been here a while.\n // And it is somewhat inconsistent as it check if the container is a second grade child\n // of the common ancestor.\n // It can help to prevent the nuking of e.g. comments when formatting like bold\n // is applied.\n const directlyBeforeFormatTag = atStart && isSecondChildOfCommonAncestor(range, range.startContainer);\n const directlyAfterFormatTag = !atStart && isSecondChildOfCommonAncestor(range, range.endContainer);\n if (directlyBeforeFormatTag) {\n const startParentElem = range.startContainer.parentElement;\n if (startParentElem && startParentElem.parentElement) {\n startParentElem.parentElement.insertBefore(markerEl, startParentElem);\n }\n }\n else if (directlyAfterFormatTag) {\n const endParentElem = range.endContainer.parentElement;\n if (endParentElem && endParentElem.parentElement) {\n endParentElem.parentElement.insertBefore(markerEl, endParentElem.nextSibling);\n }\n }\n else {\n // Clone the Range and collapse to the appropriate boundary point\n const boundaryRange = range.cloneRange();\n boundaryRange.collapse(atStart);\n boundaryRange.insertNode(markerEl);\n }\n return markerEl;\n}\nexport function setRangeBoundary(host, range, markerId, atStart) {\n const markerEl = getMarker(host, markerId);\n if (!markerEl)\n return console.log('Marker element has been removed. Cannot restore selection.');\n range[atStart ? 'setStartBefore' : 'setEndBefore'](markerEl);\n markerEl.remove();\n}\nexport function save(range) {\n let rangeInfo;\n let startEl;\n let endEl;\n // insert markers\n if (range.collapsed) {\n endEl = insertRangeBoundaryMarker(range, false);\n rangeInfo = {\n markerId: endEl.id,\n collapsed: true\n };\n }\n else {\n endEl = insertRangeBoundaryMarker(range, false);\n startEl = insertRangeBoundaryMarker(range, true);\n rangeInfo = {\n startMarkerId: startEl.id,\n endMarkerId: endEl.id,\n collapsed: false\n };\n }\n // Adjust each range's boundaries to lie between its markers\n if (range.collapsed) {\n range.setStartBefore(endEl);\n range.collapse(true);\n }\n else {\n range.setEndBefore(endEl);\n if (startEl) {\n range.setStartAfter(startEl);\n }\n }\n return rangeInfo;\n}\nexport function restore(host, rangeInfo) {\n if (rangeInfo.restored)\n return;\n const range = createRange();\n if (rangeInfo.collapsed) {\n if (!rangeInfo.markerId) {\n console.log('Marker ID is missing. Cannot restore selection.');\n return undefined;\n }\n const markerEl = getMarker(host, rangeInfo.markerId);\n if (markerEl) {\n markerEl.style.display = 'inline';\n const previousNode = markerEl.previousSibling;\n // Workaround for rangy issue 17\n if (previousNode && previousNode.nodeType === nodeType.textNode) {\n markerEl.remove();\n range.setStart(previousNode, previousNode.length);\n }\n else {\n range.setStartBefore(markerEl);\n range.collapse(true);\n markerEl.remove();\n }\n }\n else {\n console.log('Marker element has been removed. Cannot restore selection.');\n }\n }\n else {\n if (rangeInfo.startMarkerId && rangeInfo.endMarkerId) {\n setRangeBoundary(host, range, rangeInfo.startMarkerId, true);\n setRangeBoundary(host, range, rangeInfo.endMarkerId, false);\n }\n else {\n console.log('Marker IDs are missing. Cannot restore selection.');\n return undefined;\n }\n }\n normalizeBoundaries(range);\n return range;\n}\nfunction getMarker(host, id) {\n return host.querySelector(`#${id}`);\n}\n//# sourceMappingURL=range-save-restore.js.map","import * as nodeType from './node-type.js';\nimport * as rangeSaveRestore from './range-save-restore.js';\nimport * as parser from './parser.js';\nimport * as string from './util/string.js';\nimport { createElement, createRange, getNodes, normalizeBoundaries, splitBoundaries, containsNodeText } from './util/dom.js';\nimport config from './config.js';\nfunction restoreRange(host, range, func) {\n const savedRange = rangeSaveRestore.save(range);\n func();\n return rangeSaveRestore.restore(host, savedRange);\n}\nconst zeroWidthSpace = /\\u200B/g;\nconst zeroWidthNonBreakingSpace = /\\uFEFF/g;\nconst whitespaceExceptSpace = /[^\\S ]/g;\nconst everythingWhitespace = /^\\s+$/;\nconst leadingWhitespace = /^\\s+/;\nconst trailingWhitespace = /\\s+$/;\n// Clean up the Html.\nexport function tidyHtml(element) {\n // if (element.normalize) element.normalize()\n normalizeTags(element);\n}\n// Remove empty tags and merge consecutive tags (they must have the same\n// attributes).\n//\n// @method normalizeTags\n// @param {HTMLElement} element The element to process.\nexport function normalizeTags(element) {\n const fragment = document.createDocumentFragment();\n // Remove line breaks at the beginning of a content block\n removeWhitespaces(element, 'firstChild');\n // Remove line breaks at the end of a content block\n removeWhitespaces(element, 'lastChild');\n const nodesToProcess = Array.from(element.childNodes);\n const processedIndices = new Set();\n for (let i = 0; i < nodesToProcess.length; i++) {\n if (processedIndices.has(i))\n continue;\n const node = nodesToProcess[i];\n // skip empty tags, so they'll get removed\n if (node.nodeName !== 'BR' && !node.textContent)\n continue;\n if (node.nodeType === nodeType.elementNode && node.nodeName !== 'BR') {\n // Create a merged node starting with this node\n const mergedNode = node.cloneNode(false);\n // Copy children from the first node\n for (const child of Array.from(node.childNodes)) {\n mergedNode.appendChild(child.cloneNode(true));\n }\n // Merge consecutive same tags\n let j = i + 1;\n while (j < nodesToProcess.length) {\n const sibling = nodesToProcess[j];\n if (!parser.isSameNode(sibling, node))\n break;\n // Copy children from the consecutive sibling\n for (const siblingChild of Array.from(sibling.childNodes)) {\n mergedNode.appendChild(siblingChild.cloneNode(true));\n }\n processedIndices.add(j);\n sibling.remove();\n j++;\n }\n // Recursively normalize the merged node\n normalizeTags(mergedNode);\n fragment.appendChild(mergedNode);\n }\n else {\n fragment.appendChild(node.cloneNode(true));\n }\n }\n while (element.firstChild)\n element.removeChild(element.firstChild);\n element.appendChild(fragment);\n}\nexport function normalizeWhitespace(text) {\n return text.replace(whitespaceExceptSpace, ' ');\n}\n// Clean the element from character, tags, etc... added by the plugin logic.\n//\n// @method cleanInternals\n// @param {HTMLElement} element The element to process.\nexport function cleanInternals(element) {\n // Uses extract content for simplicity. A custom method\n // that does not clone the element could be faster if needed.\n element.innerHTML = extractContent(element, true);\n}\n// Extracts the content from a host element.\n// Does not touch or change the host. Just returns\n// the content and removes elements marked for removal by editable.\n//\n// @param {DOM node or document fragment} Element where to clean out the innerHTML.\n// If you pass a document fragment it will be empty after this call.\n// @param {Boolean} Flag whether to keep ui elements like spellchecking highlights.\n// @returns {String} The cleaned innerHTML of the passed element or document fragment.\nexport function extractContent(element, keepUiElements) {\n if (!element)\n return '';\n const innerHtml = (element.nodeType === nodeType.documentFragmentNode\n ? getInnerHtmlOfFragment(element)\n : element.innerHTML)\n .replace(zeroWidthNonBreakingSpace, '') // Used for forcing inline elements to have a height\n .replace(zeroWidthSpace, '<br>'); // Used for cross-browser newlines\n const clone = document.createElement('div');\n clone.innerHTML = innerHtml;\n unwrapInternalNodes(clone, keepUiElements);\n // Remove line breaks at the beginning of a content block\n removeWhitespaces(clone, 'firstChild');\n // Remove line breaks at the end of a content block\n removeWhitespaces(clone, 'lastChild');\n return clone.innerHTML;\n}\nexport function getInnerHtmlOfFragment(documentFragment) {\n if (!documentFragment || !documentFragment.childNodes) {\n return '';\n }\n const div = document.createElement('div');\n // JSDOM doesn't support appendChild with DocumentFragment directly\n // Clone and append each child instead\n const children = Array.from(documentFragment.childNodes);\n for (const child of children) {\n div.appendChild(child.cloneNode(true));\n }\n return div.innerHTML;\n}\n// Create a document fragment from an html string\n// @param {String} e.g. 'some html <span>text</span>.'\nexport function createFragmentFromString(htmlString) {\n const wrapper = document.createElement('div');\n wrapper.innerHTML = htmlString;\n const fragment = document.createDocumentFragment();\n while (wrapper.firstChild)\n fragment.appendChild(wrapper.firstChild);\n return fragment;\n}\nexport function adoptElement(node, doc) {\n if (typeof node === 'string') {\n // If node is a string (selector), query for it\n const element = doc.querySelector(node);\n if (!element)\n throw new Error(`Element not found: ${node}`);\n return element;\n }\n if (node.ownerDocument !== doc) {\n return doc.adoptNode(node);\n }\n return node;\n}\n// It will return a fragment with the cloned contents of the range\n// without the commonAncestorElement.\n//\n// @param {Range}\n// @return {DocumentFragment}\nexport function cloneRangeContents(range) {\n const rangeFragment = range.cloneContents();\n const parent = rangeFragment.childNodes[0];\n const fragment = document.createDocumentFragment();\n while (parent.childNodes.length)\n fragment.appendChild(parent.childNodes[0]);\n return fragment;\n}\nfunction removeWhitespaces(node, type, firstCall = true) {\n let elem;\n // loop through all children:\n // from left to right if type = 'firstChild',\n // from right to left if type = 'lastChild'\n while ((elem = node[type])) {\n if (elem.nodeType === nodeType.textNode) {\n // Just remove text nodes if they consist only of whitespace\n if (elem.textContent && everythingWhitespace.test(elem.textContent))\n node.removeChild(elem);\n else\n break;\n }\n else if (elem.nodeName === 'BR') {\n elem.remove();\n }\n else {\n // For element nodes (e.g. <strong> tags), we repeat the logic recursively\n // to remove empty text nodes or <br> tags.\n if (elem[type])\n removeWhitespaces(elem, type, false);\n break;\n }\n }\n // Text nodes with leading/trailing whitespace can be trimmed if config allows.\n // We only do it to the outermost text node. Once a text was wrapped in\n // another element, we preserve the whitespace.\n if (!firstCall)\n return;\n elem = node[type];\n if (elem?.nodeType !== nodeType.textNode)\n return;\n // Remove whitespaces at the end or start of a block with content\n // e.g. ' Hello world' > 'Hello World'\n if (config.trimLeadingAndTrailingWhitespaces && elem.textContent) {\n elem.textContent = elem.textContent.replace(type.startsWith('last') ? trailingWhitespace : leadingWhitespace, '');\n }\n}\n// Remove elements that were inserted for internal or user interface purposes\n//\n// @param {DOM node}\n// @param {Boolean} whether to keep ui elements like spellchecking highlights\n// Currently:\n// - Saved ranges\nexport function unwrapInternalNodes(sibling, keepUiElements) {\n while (sibling) {\n const nextSibling = sibling.nextSibling;\n if (sibling.nodeType !== nodeType.elementNode) {\n sibling = nextSibling;\n continue;\n }\n const elem = sibling;\n const attr = elem.getAttribute('data-editable');\n if (elem.firstChild)\n unwrapInternalNodes(elem.firstChild, keepUiElements);\n if (attr === 'remove' || (attr === 'ui-remove' && !keepUiElements)) {\n elem.remove();\n }\n else if (attr === 'unwrap' || (attr === 'ui-unwrap' && !keepUiElements)) {\n unwrap(elem);\n }\n sibling = nextSibling;\n }\n}\n// Get all tags that start or end inside the range\nexport function getTags(host, range, filterFunc) {\n const innerTags = getInnerTags(range, filterFunc);\n const ancestorTags = getAncestorTags(host, range, filterFunc);\n return innerTags.concat(ancestorTags);\n}\n// Get all ancestor tags that start or end inside the range\nexport function getAncestorTags(host, range, filterFunc) {\n const tags = [];\n let node = range.commonAncestorContainer;\n while (node && node !== host) {\n if (!filterFunc || filterFunc(node))\n tags.push(node);\n node = node.parentNode;\n }\n return tags;\n}\nexport function getTagsByName(host, range, tagName) {\n return getTags(host, range, (node) => {\n return node.nodeName.toUpperCase() === tagName.toUpperCase();\n });\n}\nexport function getTagsByNameAndAttributes(host, range, elem) {\n return getTags(host, range, (node) => {\n return node.nodeName.toUpperCase() === elem.nodeName.toUpperCase() &&\n node.nodeType === nodeType.elementNode &&\n areSameAttributes(node.attributes, elem.attributes);\n });\n}\nexport function areSameAttributes(attrs1, attrs2) {\n if (attrs1.length !== attrs2.length)\n return false;\n for (let i = 0; i < attrs1.length; i++) {\n const attr1 = attrs1[i];\n const attr2 = attrs2.getNamedItem(attr1.name);\n if (!attr2 || attr2.value !== attr1.value)\n return false;\n }\n return true;\n}\n// Get all tags that start or end inside the range\nexport function getInnerTags(range, filterFunc) {\n return getNodes(range, [nodeType.elementNode], filterFunc);\n}\n// Get all tags whose text is completely within the current selection.\nexport function getContainedTags(range, filterFunc) {\n return getNodes(range, [nodeType.elementNode], filterFunc)\n .filter(elem => containsNodeText(range, elem));\n}\n// Transform an array of elements into an array\n// of tagnames in uppercase\n//\n// @return example: ['STRONG', 'B']\nexport function getTagNames(elements = []) {\n return elements.map((element) => element.nodeName);\n}\nexport function isAffectedBy(host, range, tagName) {\n return getTags(host, range, null)\n .some((elem) => elem.nodeName === tagName.toUpperCase());\n}\n// select a whole element\nexport function selectNodeContents(element) {\n const range = createRange();\n range.selectNodeContents(element);\n return range;\n}\nfunction intersectsRange(range1, range2) {\n return range1.compareBoundaryPoints(Range.END_TO_START, range2) === -1 &&\n range2.compareBoundaryPoints(Range.END_TO_START, range1) === -1;\n}\n// Check if the range selects all of the elements contents,\n// not less or more.\n//\n// @param visible: Only compare visible text. That way it does not\n// matter if the user selects an additional whitespace or not.\nexport function isExactSelection(range, elem, visible) {\n const elemRange = createRange();\n elemRange.selectNodeContents(elem);\n if (!intersectsRange(range, elemRange))\n return false;\n let rangeText = range.toString();\n let elemText = (elem.jquery ? elem[0] : elem).textContent;\n if (visible) {\n rangeText = string.trim(rangeText);\n elemText = string.trim(elemText);\n }\n return rangeText !== '' && rangeText === elemText;\n}\nexport function expandTo(host, range, elem) {\n range.selectNodeContents(elem);\n return range;\n}\nexport function toggleTag(host, range, elem) {\n const elems = getTagsByNameAndAttributes(host, range, elem);\n if (elems.length === 1 &&\n elems[0].nodeType === nodeType.elementNode &&\n isExactSelection(range, elems[0], true)) {\n const result = removeFormattingElem(host, range, elem);\n if (!result)\n return range;\n return result;\n }\n return forceWrap(host, range, elem);\n}\nexport function isWrappable(range) {\n return canSurroundContents(range);\n}\nexport function forceWrap(host, range, elem) {\n let restoredRange = restoreRange(host, range, () => {\n nukeElem(host, range, elem);\n });\n // remove all tags if the range is not wrappable\n if (!restoredRange || !isWrappable(restoredRange)) {\n if (!restoredRange)\n return range;\n restoredRange = restoreRange(host, restoredRange, () => {\n nuke(host, restoredRange, null);\n });\n if (!restoredRange)\n return range;\n }\n wrap(restoredRange, elem);\n return restoredRange;\n}\nexport function wrap(range, elem) {\n if (!isWrappable(range)) {\n console.log('content.wrap(): can not surround range');\n return;\n }\n let element;\n if (typeof elem === 'string') {\n element = createElement(elem);\n if (!element) {\n console.log('content.wrap(): could not create element');\n return;\n }\n }\n else {\n element = elem;\n }\n range.surroundContents(element);\n}\nexport function unwrap(elem) {\n elem = elem.jquery ? elem[0] : elem;\n const parent = elem.parentNode;\n if (!parent)\n return;\n while (elem.firstChild)\n parent.insertBefore(elem.firstChild, elem);\n parent.removeChild(elem);\n}\nexport function removeFormattingElem(host, range, elem) {\n return restoreRange(host, range, () => {\n nukeElem(host, range, elem);\n });\n}\nexport function removeFormatting(host, range, selector) {\n return restoreRange(host, range, () => {\n nuke(host, range, selector);\n });\n}\n// Unwrap all tags this range is affected by.\n// Can also affect content outside of the range.\nexport function nuke(host, range, selector) {\n getTags(host, range, null).forEach((elem) => {\n if (elem.nodeName.toUpperCase() !== 'BR' && (!selector || elem.matches(selector))) {\n unwrap(elem);\n }\n });\n}\n// Unwrap all tags this range is affected by.\n// Can also affect content outside of the range.\nexport function nukeElem(host, range, node) {\n getTags(host, range, null).forEach((elem) => {\n if (elem.nodeName.toUpperCase() !== 'BR' && (!node ||\n (elem.nodeName.toUpperCase() === node.nodeName.toUpperCase() &&\n areSameAttributes(elem.attributes, node.attributes)))) {\n unwrap(elem);\n }\n });\n}\n// Insert a single character (or string) before or after\n// the range.\nexport function insertCharacter(range, character, atStart) {\n const insertEl = document.createTextNode(character);\n const boundaryRange = range.cloneRange();\n boundaryRange.collapse(atStart);\n boundaryRange.insertNode(insertEl);\n range[atStart ? 'setStartBefore' : 'setEndAfter'](insertEl);\n normalizeBoundaries(range);\n}\n// Surround the range with characters like start and end quotes.\n//\n// @method surround\nexport function surround(host, range, startCharacter, endCharacter) {\n insertCharacter(range, endCharacter || startCharacter, false);\n insertCharacter(range, startCharacter, true);\n return range;\n}\n// Removes a character from the text within a range.\n//\n// @method deleteCharacter\nexport function deleteCharacter(host, range, character) {\n if (!containsString(range, character))\n return range;\n // check for selection.rangeCount > 0 ?\n const selection = window.getSelection();\n if (selection && selection.rangeCount > 0)\n splitBoundaries(range);\n const restoredRange = restoreRange(host, range, () => {\n getNodes(range, [nodeType.textNode], (node) => {\n return node.nodeValue !== null && node.nodeValue.indexOf(character) >= 0;\n })\n .forEach((node) => {\n const textNode = node;\n if (textNode.nodeValue) {\n // Use replace with global regex instead of replaceAll for better compatibility\n textNode.nodeValue = textNode.nodeValue.replace(new RegExp(character.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'), '');\n }\n });\n });\n if (restoredRange) {\n normalizeBoundaries(restoredRange);\n return restoredRange;\n }\n return range;\n}\nexport function containsString(range, str) {\n return range.toString().indexOf(str) >= 0;\n}\n// Unwrap all tags this range is affected by.\n// Can also affect content outside of the range.\nexport function nukeTag(host, range, tagName) {\n getTags(host, range, null).forEach((elem) => {\n if (elem.nodeName.toUpperCase() === tagName.toUpperCase())\n unwrap(elem);\n });\n}\nfunction createNodeIterator(root, filter) {\n let currentNode = root;\n let previousNode = null;\n function nextNode() {\n if (!currentNode) {\n return null;\n }\n if (currentNode.firstChild && previousNode !== currentNode.firstChild) {\n previousNode = currentNode;\n currentNode = currentNode.firstChild;\n }\n else if (currentNode.nextSibling) {\n previousNode = currentNode;\n currentNode = currentNode.nextSibling;\n }\n else {\n let parent = currentNode.parentNode;\n while (parent && parent !== root) {\n if (parent.nextSibling) {\n previousNode = currentNode = parent.nextSibling;\n break;\n }\n parent = parent.parentNode;\n }\n if (!parent || parent === root) {\n previousNode = currentNode = null;\n }\n }\n return currentNode;\n }\n return {\n next: nextNode\n };\n}\nfunction isNodeFullyContained(node, range) {\n const nodeRange = document.createRange();\n nodeRange.selectNodeContents(node);\n return range.compareBoundaryPoints(Range.START_TO_START, nodeRange) <= 0 &&\n range.compareBoundaryPoints(Range.END_TO_END, nodeRange) >= 0;\n}\nfunction canSurroundContents(range) {\n if (!range || !range.startContainer || !range.endContainer) {\n return false;\n }\n if (range.startContainer === range.endContainer)\n return true;\n // Create a custom node iterator for the common ancestor container\n const iterator = createNodeIterator(range.commonAncestorContainer, function (node) {\n return range.isPointInRange(node, 0);\n });\n let currentNode;\n let boundariesInvalid = false;\n while ((currentNode = iterator.next())) {\n if (currentNode.nodeType === Node.ELEMENT_NODE) {\n if (!isNodeFullyContained(currentNode, range)) {\n boundariesInvalid = true;\n break;\n }\n }\n }\n return !boundariesInvalid;\n}\n//# sourceMappingURL=content.js.map","import config from './config.js';\nimport * as content from './content.js';\nlet nextBlockId = 1;\nconst state = {};\nexport const next = getSibling('nextElementSibling');\nexport const previous = getSibling('previousElementSibling');\nexport function init(elem, { normalize, plainText, shouldSpellcheck } = {}) {\n setBlockId(elem);\n elem.setAttribute('contenteditable', 'true');\n elem.setAttribute('spellcheck', String(Boolean(shouldSpellcheck)));\n elem.setAttribute('data-plaintext', String(Boolean(plainText)));\n elem.classList.remove(config.editableDisabledClass);\n elem.classList.add(config.editableClass);\n if (normalize)\n content.tidyHtml(elem);\n}\nexport function disable(elem) {\n elem.removeAttribute('contenteditable');\n elem.removeAttribute('spellcheck');\n elem.removeAttribute('data-plaintext');\n setState(elem, undefined);\n elem.classList.remove(config.editableClass);\n elem.classList.add(config.editableDisabledClass);\n}\nexport function isPlainTextBlock(elem) {\n return elem.getAttribute('data-plaintext') === 'true';\n}\nexport function setBlockId(elem) {\n if (!elem.hasAttribute('data-editable')) {\n elem.setAttribute('data-editable', `id-${nextBlockId}`);\n nextBlockId += 1;\n }\n}\nexport function getState(elem) {\n if (elem.hasAttribute('data-editable')) {\n const id = elem.getAttribute('data-editable');\n if (id)\n return state[id];\n }\n}\nexport function setState(elem, data) {\n if (elem.hasAttribute('data-editable')) {\n const id = elem.getAttribute('data-editable');\n if (id)\n state[id] = data;\n }\n}\n// Helpers\n// -------\nfunction getSibling(type) {\n return function (element) {\n const sibling = element[type];\n return sibling && sibling.getAttribute('contenteditable')\n ? sibling\n : null;\n };\n}\n//# sourceMappingURL=block.js.map","const doubleQuotePairs = [\n ['«', '»'], // ch german, french\n ['»', '«'], // danish\n ['\"', '\"'], // danish, not specified\n ['“', '”'], // english US\n ['”', '”'], // swedish\n ['“', '“'], // chinese simplified\n ['„', '“'] // german\n];\nconst singleQuotePairs = [\n ['‘', '’'], // english UK\n ['‹', '›'], // ch german, french\n ['‚', '‘'], // german\n ['’', '’'], // swedish\n ['›', '‹'], // danish\n [`'`, `'`], // danish, not specified\n [`‘`, `’`] // chinese simplified\n];\nconst apostrophe = [\n '’', // german\n `'` // default\n];\nconst quotesRegex = /([‘’‹›‚'«»\"“”„])(?![^<]*?>)/g;\n// whitespace end of tag, or any dash (normal, en or em-dash)\n// or any opening double quote\nconst beforeOpeningQuote = /\\s|[>\\-–—«»”\"“„]/;\n// whitespace begin of tag, or any dash (normal, en or em-dash)\n// or any closing quote, or any punctuation\nconst afterClosingQuote = /\\s|[<\\-–—«»”\"“‘’‹›'.;?:,]/;\nlet replacements;\nexport function replaceAllQuotes(str, replaceQuotesRules) {\n replacements = replaceQuotesRules || {};\n replacements.quotes = replacements.quotes || [undefined, undefined];\n replacements.singleQuotes = replacements.singleQuotes || [undefined, undefined];\n const matches = getAllQuotes(str);\n if (matches.length > 0) {\n replaceMatchedQuotes(matches, 0);\n return replaceExistingQuotes(str, matches);\n }\n return str;\n}\nfunction replaceMatchedQuotes(matches, position) {\n while (position < matches.length) {\n const closingTag = findClosingQuote(matches, position);\n if (closingTag) {\n matches[position].replace = closingTag.type === 'double'\n ? replacements.quotes?.[0]\n : replacements.singleQuotes?.[0];\n matches[closingTag.position].replace = closingTag.type === 'double'\n ? replacements.quotes?.[1]\n : replacements.singleQuotes?.[1];\n if (closingTag.position !== position + 1) {\n const nestedMatches = matches.slice(position + 1, closingTag.position);\n if (nestedMatches && nestedMatches.length > 0) {\n replaceMatchedQuotes(nestedMatches, 0);\n }\n }\n position = closingTag.position + 1;\n }\n else {\n matches[position].replace = replaceApostrophe(matches[position].char);\n position += 1;\n }\n }\n}\nfunction findClosingQuote(matches, position) {\n if (position === matches.length - 1)\n return undefined;\n const current = matches[position];\n const openingQuote = current.char;\n if (current.before && !beforeOpeningQuote.test(current.before))\n return undefined;\n const possibleClosingSingleQuotes = getPossibleClosingQuotes(openingQuote, singleQuotePairs);\n const possibleClosingDoubleQuotes = getPossibleClosingQuotes(openingQuote, doubleQuotePairs);\n // Also allow straight quotes as potential closers when we have quote pairs (they can be converted)\n // But only for the same quote type (straight double quote for double quotes, straight single quote for single quotes)\n let allPossibleDoubleClosers = possibleClosingDoubleQuotes;\n let allPossibleSingleClosers = possibleClosingSingleQuotes;\n const hasStraightQuoteFallback = (possibleClosingDoubleQuotes.length > 0 && !possibleClosingDoubleQuotes.includes('\"')) ||\n (possibleClosingSingleQuotes.length > 0 && !possibleClosingSingleQuotes.includes(\"'\"));\n // Only add straight double quote if this is a double quote type (has double quote pairs defined)\n if (possibleClosingDoubleQuotes.length > 0 && !possibleClosingDoubleQuotes.includes('\"')) {\n allPossibleDoubleClosers = [...possibleClosingDoubleQuotes, '\"'];\n }\n // Only add straight single quote if this is a single quote type (has single quote pairs defined)\n if (possibleClosingSingleQuotes.length > 0 && !possibleClosingSingleQuotes.includes(\"'\")) {\n allPossibleSingleClosers = [...possibleClosingSingleQuotes, \"'\"];\n }\n // Check if opening quote is itself a straight quote - if so, prefer outermost match\n const isStraightQuote = openingQuote === '\"' || openingQuote === \"'\";\n // Prefer exact pair matches over straight quote fallbacks\n // For straight quote fallbacks or straight quotes themselves, prefer outermost match to avoid incorrect nested matching\n let bestStraightQuoteMatch;\n for (let i = position + 1; i < matches.length; i++) {\n const candidateChar = matches[i].char;\n const candidateAfter = matches[i].after;\n const passesAfterCheck = (candidateAfter && afterClosingQuote.test(candidateAfter)) || !candidateAfter;\n if (passesAfterCheck) {\n if (allPossibleSingleClosers.includes(candidateChar)) {\n // Check if this is an exact pair match (not a straight quote fallback)\n const isExactMatch = possibleClosingSingleQuotes.includes(candidateChar);\n // For straight quotes themselves, always prefer outermost match\n if (isExactMatch && !isStraightQuote) {\n // Return immediately for exact pair matches (except for straight quotes)\n return { position: i, type: 'single' };\n }\n // For straight quote fallbacks or straight quotes themselves, continue searching for the outermost match\n if (hasStraightQuoteFallback || isStraightQuote) {\n if (!bestStraightQuoteMatch || (bestStraightQuoteMatch.type === 'single' && i > bestStraightQuoteMatch.position)) {\n bestStraightQuoteMatch = { position: i, type: 'single' };\n }\n }\n else {\n return { position: i, type: 'single' };\n }\n }\n if (allPossibleDoubleClosers.includes(candidateChar)) {\n // Check if this is an exact pair match (not a straight quote fallback)\n const isExactMatch = possibleClosingDoubleQuotes.includes(candidateChar);\n // For straight quotes themselves, always prefer outermost match\n if (isExactMatch && !isStraightQuote) {\n // Return immediately for exact pair matches (except for straight quotes)\n return { position: i, type: 'double' };\n }\n // For straight quote fallbacks or straight quotes themselves, continue searching for the outermost match\n if (hasStraightQuoteFallback || isStraightQuote) {\n if (!bestStraightQuoteMatch || (bestStraightQuoteMatch.type === 'double' && i > bestStraightQuoteMatch.position)) {\n bestStraightQuoteMatch = { position: i, type: 'double' };\n }\n }\n else {\n return { position: i, type: 'double' };\n }\n }\n }\n }\n // Return the outermost straight quote match if we found one\n if (bestStraightQuoteMatch) {\n return bestStraightQuoteMatch;\n }\n return undefined;\n}\nfunction getPossibleClosingQuotes(openingQuote, pairs) {\n return pairs.filter((quotePair) => quotePair[0] === openingQuote).map((quotePair) => quotePair[1]);\n}\nfunction replaceApostrophe(quote) {\n if (apostrophe.includes(quote)) {\n return replacements.apostrophe;\n }\n return undefined;\n}\nfunction getAllQuotes(str) {\n return [...str.matchAll(quotesRegex)].map((match) => {\n const index = match.index;\n return {\n char: match[1],\n before: index > 0 ? str[index - 1] : '',\n after: (index + 1) < str.length ? str[index + 1] : ''\n };\n });\n}\nfunction replaceExistingQuotes(str, matches) {\n let index = 0;\n return str.replace(quotesRegex, (match) => {\n const replacement = matches[index].replace || matches[index].char;\n index += 1;\n return replacement;\n });\n}\n//# sourceMappingURL=quotes.js.map","import config from './config.js';\nimport * as string from './util/string.js';\nimport * as nodeType from './node-type.js';\nimport * as quotes from './quotes.js';\nimport { isPlainTextBlock } from './block.js';\nlet allowedElements;\nlet allowedPlainTextElements;\nlet requiredAttributes;\nlet transformElements;\nlet blockLevelElements;\nlet replaceQuotes;\nlet splitIntoBlocks;\nlet blacklistedElements;\nconst whitespaceOnly = /^\\s*$/;\nconst blockPlaceholder = '<!-- BLOCK -->';\nlet keepInternalRelativeLinks;\nupdateConfig(config);\nexport function updateConfig(conf) {\n const rules = conf.pastedHtmlRules;\n allowedElements = rules.allowedElements || {};\n allowedPlainTextElements = rules.allowedPlainTextElements || {};\n requiredAttributes = rules.requiredAttributes || {};\n transformElements = rules.transformElements || {};\n blacklistedElements = rules.blacklistedElements || [];\n keepInternalRelativeLinks = rules.keepInternalRelativeLinks || false;\n replaceQuotes = rules.replaceQuotes || {};\n blockLevelElements = {};\n rules.blockLevelElements.forEach((name) => { blockLevelElements[name] = true; });\n splitIntoBlocks = {};\n rules.splitIntoBlocks.forEach((name) => { splitIntoBlocks[name] = true; });\n}\nexport function paste(block, cursor, clipboardContent) {\n const document = block.ownerDocument;\n block.setAttribute(config.pastingAttribute, 'true');\n if (cursor.isSelection) {\n const selection = cursor;\n cursor = selection.deleteExactSurroundingTags()\n .deleteContainedTags()\n .deleteContent();\n }\n // Create a placeholder to help parse HTML\n const pasteHolder = document.createElement('div');\n pasteHolder.innerHTML = clipboardContent;\n const isPlainText = isPlainTextBlock(block);\n const blocks = parseContent(pasteHolder, { plainText: isPlainText });\n block.removeAttribute(config.pastingAttribute);\n return { blocks, cursor };\n}\n/**\n * - Parse pasted content\n * - Split it up into blocks\n * - clean and normalize every block\n * - optionally strip the host location an anchorTag-href\n * www.livindocs.io/internalLink -> /internalLink\n *\n * @param {DOM node} A container where the pasted content is located.\n * @returns {Array of Strings} An array of cleaned innerHTML like strings.\n */\nexport function parseContent(element, { plainText = false } = {}) {\n const options = {\n allowedElements: plainText ? allowedPlainTextElements : allowedElements,\n keepInternalRelativeLinks: plainText ? false : keepInternalRelativeLinks\n };\n // Filter pasted content\n return filterHtmlElements(element, options)\n // Handle Blocks\n .split(blockPlaceholder)\n .map((entry) => string.trim(cleanWhitespace(replaceAllQuotes(entry))))\n .filter((entry) => !whitespaceOnly.test(entry));\n}\nfunction filterHtmlElements(elem, options) {\n return Array.from(elem.childNodes).reduce((content, child) => {\n if (blacklistedElements.indexOf(child.nodeName.toLowerCase()) !== -1) {\n return '';\n }\n const childElement = child;\n // Keep internal relative links relative (on paste).\n if (options.keepInternalRelativeLinks && childElement.nodeName === 'A' && childElement.href) {\n const hrefAttr = childElement.getAttribute('href');\n if (hrefAttr) {\n const stripInternalHost = hrefAttr.replace(window.location.origin, '');\n childElement.setAttribute('href', stripInternalHost);\n }\n }\n if (child.nodeType === nodeType.elementNode) {\n const childContent = filterHtmlElements(childElement, options);\n return content + conditionalNodeWrap(childElement, childContent, options);\n }\n // Escape HTML characters <, > and &\n if (child.nodeType === nodeType.textNode) {\n return content + string.escapeHtml(child.nodeValue || '');\n }\n return content;\n }, '');\n}\nfunction conditionalNodeWrap(child, content, options) {\n let nodeName = child.nodeName.toLowerCase();\n nodeName = transformNodeName(nodeName);\n if (shouldKeepNode(nodeName, child, options)) {\n const attributes = filterAttributes(nodeName, child);\n if (nodeName === 'br')\n return `<${nodeName + attributes}>`;\n if (!whitespaceOnly.test(content)) {\n return `<${nodeName + attributes}>${content}</${nodeName}>`;\n }\n return content;\n }\n if (splitIntoBlocks[nodeName]) {\n return blockPlaceholder + content + blockPlaceholder;\n }\n // prevent missing whitespace between text when block-level\n // elements are removed.\n if (blockLevelElements[nodeName])\n return `${content} `;\n return content;\n}\n// returns string of concatenated attributes e.g. 'target=\"_blank\" rel=\"nofollow\" href=\"/test.com\"'\nfunction filterAttributes(nodeName, node) {\n return Array.from(node.attributes).reduce((attributes, attr) => {\n const name = attr.name;\n const value = attr.value;\n if (allowedElements[nodeName]?.[name] && value) {\n return `${attributes} ${name}=\"${value}\"`;\n }\n return attributes;\n }, '');\n}\nfunction transformNodeName(nodeName) {\n return transformElements[nodeName] || nodeName;\n}\nfunction hasRequiredAttributes(nodeName, node) {\n const requiredAttrs = requiredAttributes[nodeName];\n if (!requiredAttrs)\n return true;\n return !requiredAttrs.some((name) => !node.getAttribute(name));\n}\nfunction shouldKeepNode(nodeName, node, options) {\n return !!options.allowedElements[nodeName] && hasRequiredAttributes(nodeName, node);\n}\nfunction cleanWhitespace(str) {\n return str\n .replace(/\\n/g, ' ')\n .replace(/ {2,}/g, ' ')\n .replace(/(.)\\u00A0/g, (match, group) => group + (/[\\u0020]/.test(group)\n ? '\\u00A0'\n : ' '));\n}\nfunction replaceAllQuotes(str) {\n if (replaceQuotes.quotes || replaceQuotes.singleQuotes || replaceQuotes.apostrophe) {\n return quotes.replaceAllQuotes(str, replaceQuotes);\n }\n return str;\n}\n//# sourceMappingURL=clipboard.js.map","/**\n* Check for contenteditable support\n*\n* (from Modernizr)\n* this is known to false positive in some mobile browsers\n* here is a whitelist of verified working browsers:\n* https://github.com/NielsLeenheer/html5test/blob/549f6eac866aa861d9649a0707ff2c0157895706/scripts/engine.js#L2083\n*/\nexport const contenteditable = typeof document.documentElement.contentEditable !== 'undefined';\n// Detect webkit browser engine\n// That way we can detect the contenteditable span bug on safari, but exclude chrome\n// Regex taken from: https://github.com/lancedikson/bowser/blob/f09411489ced05811c91cc6670a8e4ca9cbe39a7/src/parser-engines.js#L93-L106\n// Attention, this might be error prone as any engine version change breaks this.\nconst isBlink = /(apple)?webkit\\/537\\.36/i.test(window.navigator.userAgent);\nconst isWebkit = /(apple)?webkit/i.test(window.navigator.userAgent);\nconst webKit = !isBlink && isWebkit;\n/**\n * Check selectionchange event (supported in IE, Chrome, Firefox and Safari)\n * Firefox supports it since version 52 (2017).\n * Opera has no support as of 2021.\n */\nconst hasNativeSelectionchangeSupport = (document) => {\n const doc = document;\n const osc = doc.onselectionchange;\n if (osc !== undefined) {\n try {\n doc.onselectionchange = 0;\n return doc.onselectionchange === null;\n }\n catch (e) {\n // ignore\n }\n finally {\n doc.onselectionchange = osc;\n }\n }\n return false;\n};\nexport const selectionchange = hasNativeSelectionchangeSupport(document);\n// See Keyboard.prototype.preventContenteditableBug for more information.\nexport const contenteditableSpanBug = !!webKit;\n//# sourceMappingURL=feature-detection.js.map","// Eventable Mixin.\n//\n// Simple mixin to add event emitter methods to an object (Publish/Subscribe).\n//\n// Add on, off and notify methods to an object:\n// eventable(obj)\n//\n// publish an event:\n// obj.notify(context, 'action', param1, param2)\n//\n// Optionally pass a context that will be applied to every event:\n// eventable(obj, context)\n//\n// With this publishing can omit the context argument:\n// obj.notify('action', param1, param2)\n//\n// Subscribe to a 'channel'\n// obj.on('action', funtion(param1, param2){ ... })\n//\n// Unsubscribe an individual listener:\n// obj.off('action', method)\n//\n// Unsubscribe all listeners of a channel:\n// obj.off('action')\n//\n// Unsubscribe all listeners of all channels:\n// obj.off()\nexport default function eventable(obj, notifyContext) {\n const events = getEventableModule(notifyContext);\n obj.on = events.on;\n obj.off = events.off;\n obj.notify = events.notify;\n}\nfunction getEventableModule(notifyContext) {\n const listeners = {};\n function addListener(events, listener) {\n events.split(' ').forEach(event => {\n listeners[event] = listeners[event] || [];\n listeners[event].unshift(listener);\n });\n }\n function removeListener(event, listener) {\n const eventListeners = listeners[event];\n if (!eventListeners)\n return;\n const index = eventListeners.indexOf(listener);\n if (index < 0)\n return;\n eventListeners.splice(index, 1);\n }\n // Public Methods\n const result = {\n on(eventOrEvents, listener) {\n if (arguments.length === 2 && typeof eventOrEvents === 'string') {\n addListener(eventOrEvents, listener);\n }\n else if (arguments.length === 1 && typeof eventOrEvents === 'object') {\n for (const eventType in eventOrEvents)\n addListener(eventType, eventOrEvents[eventType]);\n }\n return result;\n },\n off(event, listener) {\n if (arguments.length === 2) {\n removeListener(event, listener);\n }\n else if (arguments.length === 1) {\n listeners[event] = [];\n }\n else {\n Object.keys(listeners).forEach(key => delete listeners[key]);\n }\n },\n notify(context, event, ...args) {\n const allArgs = Array.from(arguments);\n let actualContext;\n let actualEvent;\n let actualArgs;\n if (notifyContext) {\n actualEvent = context;\n actualContext = notifyContext;\n actualArgs = allArgs.slice(1);\n }\n else {\n actualContext = context;\n actualEvent = event;\n actualArgs = allArgs.slice(2);\n }\n if (result.switchContext) {\n const nextEvent = result.switchContext.events.shift();\n if (actualEvent !== nextEvent)\n result.switchContext = undefined;\n }\n const eventListeners = listeners[actualEvent];\n if (!eventListeners)\n return;\n // Execute the newest listeners first.\n // Stop if a listener returns false.\n eventListeners.every((listener) => listener.apply(actualContext, actualArgs) !== false);\n }\n };\n return result;\n}\n//# sourceMappingURL=eventable.js.map","// code from mdn: https://developer.mozilla.org/en-US/docs/Web/API/window.scrollX\nfunction getScrollPosition(win) {\n const x = (win.pageXOffset !== undefined) ? win.pageXOffset : (win.document.documentElement || win.document.body.parentNode || win.document.body).scrollLeft;\n const y = (win.pageYOffset !== undefined) ? win.pageYOffset : (win.document.documentElement || win.document.body.parentNode || win.document.body).scrollTop;\n return { x, y };\n}\nexport { getScrollPosition };\n//# sourceMappingURL=viewport.js.map","import * as viewport from './util/viewport.js';\nimport * as content from './content.js';\nimport * as parser from './parser.js';\nimport * as string from './util/string.js';\nimport { elementNode, documentFragmentNode } from './node-type.js';\nimport error from './util/error.js';\nimport * as rangeSaveRestore from './range-save-restore.js';\nimport { closest, getSelection, rangesAreEqual } from './util/dom.js';\n/**\n * The Cursor module provides a cross-browser abstraction layer for cursor.\n *\n * @module core\n * @submodule cursor\n */\nexport default class Cursor {\n static findHost(elem, selector) {\n return closest(elem, selector);\n }\n /**\n * Class for the Cursor module.\n *\n * @class Cursor\n * @constructor\n */\n constructor(editableHost, range) {\n this.setHost(editableHost);\n this.range = range;\n this.isCursor = true;\n }\n // Get all tags that affect the current selection. Optionally pass a\n // method to filter the returned elements.\n //\n // @param {Function filter(node)} [Optional] Method to filter the returned\n // DOM Nodes.\n // @return {Array of DOM Nodes}\n getTags(filterFunc) {\n return content.getTags(this.host, this.range, filterFunc);\n }\n // Get the names of all tags that affect the current selection. Optionally\n // pass a method to filter the returned elements.\n //\n // @param {Function filter(node)} [Optional] Method to filter the DOM\n // Nodes whose names are returned.\n // @return {Array<String> of tag names}\n getTagNames(filterFunc) {\n const tags = this.getTags(filterFunc);\n return content.getTagNames(tags);\n }\n // Get all tags of the specified type that affect the current selection.\n //\n // @method getTagsByName\n // @param {String} tagName. E.g. 'a' to get all links.\n // @return {Array of DOM Nodes}\n getTagsByName(tagName) {\n return content.getTagsByName(this.host, this.range, tagName);\n }\n // Get all tags that are completely within the current selection.\n getInnerTags(filterFunc) {\n return content.getInnerTags(this.range, filterFunc);\n }\n // Get all tags whose text is completely within the current selection.\n getContainedTags(filterFunc) {\n return content.getContainedTags(this.range, filterFunc);\n }\n // Get all tags that surround the current selection.\n getAncestorTags(filterFunc) {\n return content.getAncestorTags(this.host, this.range, filterFunc);\n }\n isAtEnd() {\n return parser.isEndOfHost(this.host, this.range.endContainer, this.range.endOffset);\n }\n isAtTextEnd() {\n return parser.isTextEndOfHost(this.host, this.range.endContainer, this.range.endOffset);\n }\n isAtLastLine() {\n const hostRange = this.win.document.createRange();\n hostRange.selectNodeContents(this.host);\n hostRange.collapse(false);\n const hostCoords = getRangeBoundingClientRect(hostRange, this.win);\n const cursorCoords = getRangeBoundingClientRect(this.range, this.win);\n return isCloseTo(hostCoords.bottom, cursorCoords.bottom);\n }\n isAtFirstLine() {\n const hostRange = this.win.document.createRange();\n hostRange.selectNodeContents(this.host);\n hostRange.collapse(true);\n const hostCoords = getRangeBoundingClientRect(hostRange, this.win);\n const cursorCoords = getRangeBoundingClientRect(this.range, this.win);\n return isCloseTo(hostCoords.top, cursorCoords.top);\n }\n isAtBeginning() {\n return parser.isBeginningOfHost(this.host, this.range.startContainer, this.range.startOffset);\n }\n // Insert content before the cursor\n //\n // @param {String, DOM node or document fragment}\n insertBefore(element) {\n if (string.isString(element))\n element = content.createFragmentFromString(element);\n if (parser.isDocumentFragmentWithoutChildren(element))\n return;\n element = this.adoptElement(element);\n let preceedingElement = element;\n if (element.nodeType === documentFragmentNode) {\n const lastIndex = element.childNodes.length - 1;\n preceedingElement = element.childNodes[lastIndex];\n }\n this.range.insertNode(element);\n this.range.setStartAfter(preceedingElement);\n this.range.setEndAfter(preceedingElement);\n this.host.normalize(); // mend text nodes\n }\n // Insert content after the cursor\n //\n // @param {String, DOM node or document fragment}\n insertAfter(element) {\n if (string.isString(element))\n element = content.createFragmentFromString(element);\n if (parser.isDocumentFragmentWithoutChildren(element))\n return;\n element = this.adoptElement(element);\n const after = this.range.cloneRange();\n after.setStart(after.endContainer, after.endOffset);\n after.collapse(true);\n after.insertNode(element);\n this.host.normalize(); // mend text nodes\n }\n // Alias for #setVisibleSelection()\n setSelection() {\n this.setVisibleSelection();\n }\n setVisibleSelection() {\n if (this.win.document.activeElement !== this.host) {\n const { x, y } = viewport.getScrollPosition(this.win);\n this.win.scrollTo(x, y);\n }\n const selection = getSelection(this.win);\n if (!selection)\n return;\n selection.removeAllRanges();\n selection.addRange(this.range);\n }\n // Take the following example:\n // (The character '|' represents the cursor position)\n //\n // <div contenteditable=\"true\">fo|o</div>\n // before() will return a document fragment containing a text node 'fo'.\n //\n // @returns {Document Fragment} content before the cursor or selection.\n before() {\n const range = this.range.cloneRange();\n range.collapse(true);\n range.setStartBefore(this.host);\n return content.cloneRangeContents(range);\n }\n textBefore() {\n const range = this.range.cloneRange();\n range.collapse(true);\n range.setStartBefore(this.host);\n return range.toString();\n }\n // Same as before() but returns a string.\n beforeHtml() {\n return content.getInnerHtmlOfFragment(this.before());\n }\n // Take the following example:\n // (The character '|' represents the cursor position)\n //\n // <div contenteditable=\"true\">fo|o</div>\n // after() will return a document fragment containing a text node 'o'.\n //\n // @returns {Document Fragment} content after the cursor or selection.\n after() {\n const range = this.range.cloneRange();\n range.collapse(false);\n range.setEndAfter(this.host);\n return content.cloneRangeContents(range);\n }\n textAfter() {\n const range = this.range.cloneRange();\n range.collapse(false);\n range.setEndAfter(this.host);\n return range.toString();\n }\n // Same as after() but returns a string.\n afterHtml() {\n return content.getInnerHtmlOfFragment(this.after());\n }\n getBoundingClientRect() {\n return this.range.getBoundingClientRect();\n }\n // Get the BoundingClientRect of the cursor.\n // The returned values are transformed to be absolute\n // (relative to the document).\n getCoordinates(positioning = 'absolute') {\n const coords = this.range.getBoundingClientRect();\n if (positioning === 'fixed')\n return coords;\n // translate into absolute positions\n const { x, y } = viewport.getScrollPosition(this.win);\n return {\n top: coords.top + y,\n bottom: coords.bottom + y,\n left: coords.left + x,\n right: coords.right + x,\n height: coords.height,\n width: coords.width\n };\n }\n moveBefore(element) {\n this.updateHost(element);\n this.range.setStartBefore(element);\n this.range.setEndBefore(element);\n if (this.isSelection)\n return new Cursor(this.host, this.range);\n }\n moveAfter(element) {\n this.updateHost(element);\n this.range.setEndAfter(element);\n this.range.setStartAfter(element);\n if (this.isSelection)\n return new Cursor(this.host, this.range);\n }\n // Move the cursor to the beginning of the host.\n moveAtBeginning(element = this.host) {\n this.updateHost(element);\n this.range.selectNodeContents(element);\n this.range.collapse(true);\n if (this.isSelection)\n return new Cursor(this.host, this.range);\n }\n // Move the cursor to the end of the host.\n moveAtEnd(element = this.host) {\n this.updateHost(element);\n this.range.selectNodeContents(element);\n this.range.collapse(false);\n if (this.isSelection)\n return new Cursor(this.host, this.range);\n }\n // Move the cursor after the last visible character of the host.\n moveAtTextEnd(element) {\n const lastChild = parser.lastChild(element);\n if (lastChild && lastChild.nodeType === elementNode) {\n return this.moveAtEnd(lastChild);\n }\n }\n setHost(element) {\n if (element.jquery)\n element = element[0];\n this.host = element;\n const doc = element.ownerDocument;\n this.win = (element === undefined || element === null || !doc) ? window : (doc.defaultView || window);\n }\n updateHost(element) {\n const host = parser.getHost(element);\n if (!host)\n error('Can not set cursor outside of an editable block');\n this.setHost(host);\n }\n retainVisibleSelection(callback) {\n this.save();\n callback(); // eslint-disable-line callback-return\n this.restore();\n this.setVisibleSelection();\n }\n save() {\n this.savedRangeInfo = rangeSaveRestore.save(this.range);\n this.savedRangeInfo.host = this.host;\n }\n restore() {\n if (!this.savedRangeInfo) {\n error('Could not restore selection');\n return;\n }\n if (this.savedRangeInfo.host) {\n this.host = this.savedRangeInfo.host;\n }\n const restoredRange = rangeSaveRestore.restore(this.host, this.savedRangeInfo);\n if (!restoredRange) {\n error('Could not restore selection range');\n return;\n }\n this.range = restoredRange;\n this.savedRangeInfo = undefined;\n }\n equals(cursor) {\n if (!cursor)\n return false;\n if (!cursor.host)\n return false;\n if (!cursor.host.isEqualNode(this.host))\n return false;\n if (!cursor.range)\n return false;\n if (!rangesAreEqual(cursor.range, this.range))\n return false;\n return true;\n }\n // Create an element with the correct ownerWindow\n // (see: http://www.w3.org/DOM/faq.html#ownerdoc)\n createElement(tagName, attributes = {}) {\n const element = this.win.document.createElement(tagName);\n for (const attributeName in attributes) {\n const attributeValue = attributes[attributeName];\n element.setAttribute(attributeName, attributeValue);\n }\n return element;\n }\n createTextNode(text) {\n return this.win.document.createTextNode(text);\n }\n // Make sure a node has the correct ownerWindow\n // (see: https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode)\n adoptElement(node) {\n return content.adoptElement(node, this.win.document);\n }\n // Currently we call triggerChange manually after format changes.\n // This is to prevent excessive triggering of the change event during\n // merge or split operations or other manipulations by scripts.\n triggerChange() {\n const event = new Event('formatEditable', { bubbles: true, cancelable: false });\n this.host.dispatchEvent(event);\n }\n}\n/**\n* Get position of the range or cursor\n*\n* Can be used to reliably get the boundingClientRect without\n* some any of the drawbacks that the native range has.\n*\n* With the native range.getClientBoundingRect(), newlines are\n* not considered when calculating the position\n*\n* @param {Range} range\n* @param {Window} win\n*/\nfunction getRangeBoundingClientRect(range, win) {\n if (range.startContainer.nodeType !== elementNode)\n return range.getBoundingClientRect();\n const el = win.document.createElement('span');\n el.setAttribute('doc-editable', 'unwrap');\n range.insertNode(el);\n const coords = el.getBoundingClientRect();\n el.remove();\n return coords;\n}\nfunction isCloseTo(a, b) {\n if (a === b)\n return true;\n if (Math.abs(a - b) <= 2)\n return true;\n return false;\n}\n//# sourceMappingURL=cursor.js.map","import NodeIterator from './node-iterator.js';\nimport * as nodeType from './node-type.js';\nimport { createRange } from './util/dom.js';\nexport default {\n // Get the text from an editable block with a NodeIterator.\n // This must work the same as when later iterating over the text\n // in highlightMatches().\n extractText(element, convertBRs = true) {\n let text = '';\n getText(element, convertBRs, (part) => { text += part; });\n return text;\n },\n // Go through the element to highlight the matches while keeping the\n // existing html valid (highlighting a match may require inserting multiple\n // elements).\n //\n // @params\n // - matches\n // Array of positions in the string to highlight:\n // e.g [{\n // startIndex: 0,\n // endIndex: 1,\n // match: 'The', // not used, only the indexes are used for highlighting)\n // marker: DOMNode, // A clone of this element will be inserted\n // id: 'a7382', // used in word-id attribute\n // title: 'The World' // used in title attribute (optional)\n // }]\n highlightMatches(element, matches, countBRs = true) {\n if (!matches || matches.length === 0) {\n return;\n }\n element.normalize(); // mend text nodes\n const iterator = new NodeIterator(element);\n let currentMatchIndex = 0;\n let totalOffset = 0;\n let currentMatch = matches[currentMatchIndex];\n let portions = [];\n let next;\n let wordId = currentMatch.id || currentMatch.startIndex;\n let textNode;\n while ((next = iterator.getNext())) {\n // Account for <br> elements\n if (next.nodeType === nodeType.textNode && next.data !== '') {\n textNode = next;\n }\n else if (countBRs && next.nodeType === nodeType.elementNode && next.nodeName === 'BR') {\n totalOffset += 1;\n continue;\n }\n else {\n continue;\n }\n if (!textNode)\n continue;\n const nodeText = textNode.data;\n let nodeEndOffset = totalOffset + nodeText.length;\n if (currentMatch.startIndex < nodeEndOffset && totalOffset < currentMatch.endIndex) {\n // get portion position (fist, last or in the middle)\n const isFirstPortion = totalOffset <= currentMatch.startIndex;\n const isLastPortion = nodeEndOffset >= currentMatch.endIndex;\n if (isFirstPortion) {\n wordId = currentMatch.id || currentMatch.startIndex;\n }\n // calculate offset and length\n let offset;\n if (isFirstPortion) {\n offset = currentMatch.startIndex - totalOffset;\n }\n else {\n offset = 0;\n }\n let length;\n if (isLastPortion) {\n length = (currentMatch.endIndex - totalOffset) - offset;\n }\n else {\n length = nodeText.length - offset;\n }\n // create portion object\n const portion = {\n element: textNode,\n text: nodeText.substring(offset, offset + length),\n offset,\n length,\n isLastPortion,\n wordId\n };\n portions.push(portion);\n if (isLastPortion) {\n const lastNode = this.wrapMatch(portions, currentMatch.marker, currentMatch.title);\n if (lastNode) {\n iterator.replaceCurrent(lastNode);\n // recalculate nodeEndOffset if we have to replace the current node.\n nodeEndOffset = totalOffset + portion.length + portion.offset;\n portions = [];\n currentMatchIndex += 1;\n if (currentMatchIndex < matches.length) {\n currentMatch = matches[currentMatchIndex];\n }\n }\n }\n }\n totalOffset = nodeEndOffset;\n }\n },\n // @return the last wrapped element\n wrapMatch(portions, stencilElement, title) {\n return portions.map((portion) => this.wrapPortion(portion, stencilElement, title)).pop();\n },\n wrapPortion(portion, stencilElement, title) {\n const range = createRange();\n range.setStart(portion.element, portion.offset);\n range.setEnd(portion.element, portion.offset + portion.length);\n const node = stencilElement.cloneNode(true);\n node.setAttribute('data-word-id', String(portion.wordId));\n if (title)\n node.setAttribute('title', title);\n range.surroundContents(node);\n // Fix a weird behaviour where an empty text node is inserted after the range\n if (node.nextSibling) {\n const next = node.nextSibling;\n if (next.nodeType === nodeType.textNode && next.data === '') {\n next.remove();\n }\n }\n return node;\n }\n};\n// Extract the text of an element.\n// This has two notable behaviours:\n// - It uses a NodeIterator which will skip elements\n// with data-editable=\"remove\"\n// - It returns a \\n for <br> elements\n// (The only block level element allowed inside of editables)\nfunction getText(element, convertBRs, func) {\n const iterator = new NodeIterator(element);\n let next;\n while ((next = iterator.getNext())) {\n if (next.nodeType === nodeType.textNode && next.data !== '') {\n func(next.data);\n }\n else if (convertBRs && next.nodeType === nodeType.elementNode && next.nodeName === 'BR') {\n func('\\n');\n }\n }\n}\n//# sourceMappingURL=highlight-text.js.map","export function searchText(text, searchTerm, marker) {\n const matchMode = 'text';\n return findMatches(text, [searchTerm], matchMode, marker);\n}\nexport function searchWord(text, word, marker) {\n const matchMode = 'word';\n return findMatches(text, [word], matchMode, marker);\n}\nexport function searchAllWords(text, words, marker) {\n const matchMode = 'word';\n return findMatches(text, words, matchMode, marker);\n}\nfunction findMatches(text, searchTexts, matchMode, marker) {\n if (!text || text === '')\n return [];\n if (marker && !isElement(marker))\n return [];\n if (!searchTexts?.length)\n return [];\n const createRegex = matchMode === 'word'\n ? createWordRegex\n : createHighlightRegex;\n const regex = createRegex(searchTexts);\n const matches = [...text.matchAll(regex)];\n return matches.map((match) => {\n let startIndex;\n let matchedText;\n if (matchMode === 'word') {\n startIndex = match.index + match[1].length;\n matchedText = match[2];\n }\n else {\n startIndex = match.index;\n matchedText = match[0];\n }\n return {\n startIndex,\n endIndex: startIndex + matchedText.length,\n match: matchedText,\n marker\n };\n });\n}\nfunction isElement(obj) {\n try {\n if (!obj)\n return false;\n return obj instanceof obj.ownerDocument?.defaultView.HTMLElement;\n }\n catch (e) {\n // Browsers not supporting W3 DOM2 don't have HTMLElement and\n // an exception is thrown and we end up here. Testing some\n // properties that all elements have (works on IE7)\n return (typeof obj === 'object') &&\n (obj.nodeType === 1) && (typeof obj.style === 'object') &&\n (typeof obj.ownerDocument === 'object');\n }\n}\nfunction createHighlightRegex(words = []) {\n const escapedWords = words.map((word) => escapeRegEx(word));\n const regex = `(${escapedWords.join('|')})`;\n return new RegExp(regex, 'g');\n}\n// Regex to find whole words within a string\n//\n// Unicode character blocks for letters.\n// See: http://jrgraphix.net/research/unicode_blocks.php\n//\n// \\\\u0041-\\\\u005A A-Z (Basic Latin)\n// \\\\u0061-\\\\u007A a-z (Basic Latin)\n// \\\\u0030-\\\\u0039 0-9 (Basic Latin)\n// \\\\u00AA ª (Latin-1 Supplement)\n// \\\\u00B5 µ (Latin-1 Supplement)\n// \\\\u00BA º (Latin-1 Supplement)\n// \\\\u00C0-\\\\u00D6 À-Ö (Latin-1 Supplement)\n// \\\\u00D8-\\\\u00F6 Ø-ö (Latin-1 Supplement)\n// \\\\u00F8-\\\\u00FF ø-ÿ (Latin-1 Supplement)\n// \\\\u0100-\\\\u017F Ā-ſ (Latin Extended-A)\n// \\\\u0180-\\\\u024F ƀ-ɏ (Latin Extended-B)\nconst letterChars = '\\\\u0041-\\\\u005A\\\\u0061-\\\\u007A\\\\u0030-\\\\u0039\\\\u00AA\\\\u00B5\\\\u00BA\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u00FF\\\\u0100-\\\\u017F\\\\u0180-\\\\u024F';\nfunction createWordRegex(words = []) {\n const escapedWords = words.map((word) => escapeRegEx(word));\n // (notLetter|^)(words)(?=notLetter|$)\n const regex = `([^${letterChars}]|^)` +\n `(${escapedWords.join('|')})` +\n `(?=[^${letterChars}]|$)`;\n return new RegExp(regex, 'g');\n}\nfunction escapeRegEx(s) {\n return String(s).replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1');\n}\n//# sourceMappingURL=text-search.js.map","import * as content from './content.js';\nimport highlightText from './highlight-text.js';\nimport { searchText } from './plugins/highlighting/text-search.js';\nimport { createElement, createRange, toCharacterRange } from './util/dom.js';\nconst highlightSupport = {\n // Used to highlight arbitrary text in an editable. All occurrences\n // will be highlighted.\n highlightText(editableHost, text, highlightId, type, dispatcher, win) {\n if (this.hasHighlight(editableHost, highlightId))\n return;\n const blockText = highlightText.extractText(editableHost);\n const marker = `<span class=\"highlight-${type}\"></span>`;\n let winWindow = win;\n if (!winWindow) {\n const doc = editableHost.ownerDocument || (typeof document !== 'undefined' ? document : null);\n winWindow = doc?.defaultView || undefined;\n }\n if (!winWindow) {\n winWindow = (typeof window !== 'undefined' && window.document ? window : undefined);\n }\n if (!winWindow) {\n throw new Error('Could not determine window object for highlightText');\n }\n const markerNode = highlightSupport.createMarkerNode(marker, type, winWindow);\n if (!markerNode)\n return undefined;\n const matches = searchText(blockText, text, markerNode);\n if (matches && matches.length) {\n const match = matches[0];\n if (highlightId)\n match.id = highlightId;\n highlightText.highlightMatches(editableHost, matches);\n if (dispatcher)\n dispatcher.notify('change', editableHost);\n return match.startIndex;\n }\n return undefined;\n },\n // Used to highlight comments.\n // This function was changed to track matches when text is added to the start\n // of a component, but multiple white spaces break it in a strict sense\n // The function works in the editor and in browsers, but tests with\n // multiple white spaces will fail.\n // Browsers change the white spaces to   and the function works,\n // and the tests in highlight.spec.js have been updated to represent this.\n highlightRange(editableHost, text, highlightId, startIndex, endIndex, dispatcher, win, type = 'comment') {\n if (this.hasHighlight(editableHost, highlightId)) {\n this.removeHighlight(editableHost, highlightId, dispatcher);\n }\n const blockText = highlightText.extractText(editableHost, false);\n if (blockText === '')\n return -1; // the text was deleted so we can't highlight anything\n let winWindow = win;\n if (!winWindow) {\n const doc = editableHost.ownerDocument || (typeof document !== 'undefined' ? document : null);\n winWindow = doc?.defaultView || undefined;\n }\n if (!winWindow) {\n winWindow = (typeof window !== 'undefined' && window.document ? window : undefined);\n }\n if (!winWindow) {\n throw new Error('Could not determine window object for highlightRange');\n }\n const marker = this.createMarkerNode(`<span class=\"highlight-${type}\"></span>`, type, winWindow);\n if (!marker)\n return -1;\n const actualStartIndex = startIndex;\n const actualEndIndex = endIndex;\n highlightText.highlightMatches(editableHost, [{\n startIndex: actualStartIndex,\n endIndex: actualEndIndex,\n match: text.substring(actualStartIndex, actualEndIndex),\n id: highlightId,\n marker\n }], false);\n if (dispatcher)\n dispatcher.notify('change', editableHost);\n return actualStartIndex;\n },\n updateHighlight(editableHost, highlightId, addCssClass, removeCssClass) {\n if (!document.documentElement.classList)\n return;\n const elems = editableHost.querySelectorAll(`[data-word-id=\"${highlightId}\"]`);\n for (const elem of Array.from(elems)) {\n if (removeCssClass)\n elem.classList.remove(removeCssClass);\n if (addCssClass)\n elem.classList.add(addCssClass);\n }\n },\n removeHighlight(editableHost, highlightId, dispatcher) {\n const elems = editableHost.querySelectorAll(`[data-word-id=\"${highlightId}\"]`);\n for (const elem of Array.from(elems)) {\n content.unwrap(elem);\n }\n // remove empty text nodes, combine adjacent text nodes\n editableHost.normalize();\n if (dispatcher)\n dispatcher.notify('change', editableHost);\n },\n hasHighlight(editableHost, highlightId) {\n const matches = editableHost.querySelectorAll(`[data-word-id=\"${highlightId}\"]`);\n return !!matches.length;\n },\n extractHighlightedRanges(editableHost, type) {\n let findMarkersQuery = '[data-word-id]';\n if (type)\n findMarkersQuery += `[data-highlight=\"${type}\"]`;\n const markers = editableHost.querySelectorAll(findMarkersQuery);\n if (!markers.length)\n return undefined;\n const groups = {};\n for (const marker of Array.from(markers)) {\n const highlightId = marker.getAttribute('data-word-id');\n if (highlightId && !groups[highlightId]) {\n groups[highlightId] = editableHost.querySelectorAll(`[data-word-id=\"${highlightId}\"]`);\n }\n }\n const res = {};\n for (const highlightId in groups) {\n const position = this.extractMarkerNodePosition(editableHost, groups[highlightId]);\n if (position)\n res[highlightId] = position;\n }\n return res;\n },\n extractMarkerNodePosition(editableHost, markers) {\n if (markers.length === 0)\n return undefined;\n const range = createRange();\n if (markers.length > 1) {\n range.setStartBefore(markers[0]);\n range.setEndAfter(markers[markers.length - 1]);\n }\n else {\n range.selectNode(markers[0]);\n }\n const textRange = toCharacterRange(range, editableHost);\n return {\n start: textRange.start,\n end: textRange.end,\n text: textRange.text, // browser range result (does whitespace normalization)\n nativeRange: range\n };\n },\n cleanupStaleMarkerNodes(editableHost, highlightType) {\n const nodes = editableHost.querySelectorAll(`span[data-highlight=\"${highlightType}\"]`);\n for (const node of Array.from(nodes)) {\n if (!node.textContent || !node.textContent.length) {\n node.remove();\n }\n }\n },\n createMarkerNode(markerMarkup, highlightType, win) {\n let winWindow = win || null;\n if (!winWindow) {\n // Try to get window from global scope\n winWindow = (typeof window !== 'undefined' && window.document ? window : null);\n }\n if (!winWindow || !winWindow.document) {\n throw new Error(`Window object with document is required. win: ${typeof win}, window: ${typeof window}`);\n }\n const marker = createElement(markerMarkup, winWindow);\n if (!marker)\n return null;\n marker.setAttribute('data-editable', 'ui-unwrap');\n marker.setAttribute('data-highlight', highlightType);\n return marker;\n }\n};\nexport default highlightSupport;\n//# sourceMappingURL=highlight-support.js.map","import Cursor from './cursor.js';\nimport * as content from './content.js';\nimport * as parser from './parser.js';\nimport * as block from './block.js';\nimport config from './config.js';\nimport highlightSupport from './highlight-support.js';\nimport highlightText from './highlight-text.js';\nimport { toCharacterRange, rangeToHtml, findStartExcludingWhitespace, findEndExcludingWhitespace } from './util/dom.js';\n/**\n * The Selection module provides a cross-browser abstraction layer for range\n * and selection.\n *\n * @module core\n * @submodule selection\n */\n/**\n * Class that represents a selection and provides functionality to access or\n * modify the selection.\n *\n * @class Selection\n * @constructor\n */\nexport default class Selection extends Cursor {\n constructor(editableHost, range) {\n super(editableHost, range);\n delete this.isCursor;\n this.isSelection = true;\n }\n // Get the text inside the selection.\n text() {\n return this.range.toString();\n }\n // Get the html inside the selection.\n html() {\n return rangeToHtml(this.range);\n }\n isAllSelected() {\n return parser.isBeginningOfHost(this.host, this.range.startContainer, this.range.startOffset) && parser.isTextEndOfHost(this.host, this.range.endContainer, this.range.endOffset);\n }\n getTextRange() {\n return toCharacterRange(this.range, this.host);\n }\n // Return a plain string of the current selection content.\n toString() {\n return this.range.toString();\n }\n // Return true if the selection can be wrapped, i.e. all open nodes\n // are closed within this selection.\n isWrappable() {\n return content.isWrappable(this.range);\n }\n // Get the ClientRects of this selection.\n // Use this if you want more precision than getBoundingClientRect can give.\n getRects() {\n // consider: translate into absolute positions\n // just like Cursor#getCoordinates()\n return this.range.getClientRects();\n }\n link(href, attrs = {}) {\n if (href)\n attrs.href = href;\n const link = this.createElement(config.linkMarkup.name, config.linkMarkup.attribs);\n for (const key in attrs) {\n const value = attrs[key];\n if (value === undefined)\n continue;\n if (value === null) {\n link.removeAttribute(key);\n }\n else {\n link.setAttribute(key, value);\n }\n }\n if (config.linkMarkup.trim)\n this.trimRange();\n this.forceWrap(link);\n }\n // trims whitespaces on the left and right of a selection, i.e. what you want in case of links\n trimRange() {\n const textToTrim = this.range.toString();\n const whitespacesOnTheLeft = textToTrim.search(/\\S|$/);\n const lastNonWhitespace = textToTrim.search(/\\S[\\s]+$/);\n const whitespacesOnTheRight = lastNonWhitespace === -1\n ? 0\n : textToTrim.length - (lastNonWhitespace + 1);\n const [startContainer, startOffset] = findStartExcludingWhitespace({\n root: this.range.commonAncestorContainer,\n startContainer: this.range.startContainer,\n startOffset: this.range.startOffset,\n whitespacesOnTheLeft\n });\n this.range.setStart(startContainer, startOffset);\n const [endContainer, endOffset] = findEndExcludingWhitespace({\n root: this.range.commonAncestorContainer,\n endContainer: this.range.endContainer,\n endOffset: this.range.endOffset,\n whitespacesOnTheRight\n });\n this.range.setEnd(endContainer, endOffset);\n }\n unlink() {\n this.removeFormatting(config.linkMarkup.name);\n }\n toggleLink(href, attrs = {}) {\n const links = this.getTagsByName(config.linkMarkup.name);\n if (links.length >= 1) {\n const firstLink = links[0];\n if (this.isExactSelection(firstLink, 'visible')) {\n this.unlink();\n }\n else {\n this.expandTo(firstLink);\n }\n }\n else {\n this.link(href, attrs);\n }\n }\n highlightComment({ highlightId, textRange }) {\n highlightSupport.highlightRange(this.host, textRange.text, highlightId, textRange.start, textRange.end, undefined, // dispatcher\n this.win, 'comment');\n }\n // Manually add a highlight\n // Note: the current code does not work with newlines (LP)\n highlight({ highlightId }) {\n const textBefore = this.textBefore();\n const currentTextContent = this.text();\n const marker = '<span class=\"highlight-comment\"></span>';\n const markerNode = highlightSupport.createMarkerNode(marker, 'comment', this.win);\n if (!markerNode)\n return;\n markerNode.setAttribute('data-match', currentTextContent);\n const match = {\n startIndex: textBefore.length,\n endIndex: textBefore.length + currentTextContent.length,\n match: currentTextContent,\n marker: markerNode\n };\n // Note: highlighting won't retain the selection\n highlightText.highlightMatches(this.host, [match]);\n }\n // e.g. toggle('<em>')\n toggle(elem) {\n if (block.isPlainTextBlock(this.host))\n return;\n if (this.range.collapsed)\n return;\n elem = this.adoptElement(elem);\n const newRange = content.toggleTag(this.host, this.range, elem);\n if (newRange) {\n this.range = newRange;\n this.setVisibleSelection();\n }\n }\n toggleCustom({ tagName, attributes, trim = false }) {\n const customElem = this.createElement(tagName, attributes);\n if (trim)\n this.trimRange();\n this.toggle(customElem);\n }\n makeCustom({ tagName, attributes, trim = false }) {\n const customElem = this.createElement(tagName, attributes);\n if (trim)\n this.trimRange();\n this.forceWrap(customElem);\n }\n makeBold() {\n const bold = this.createElement(config.boldMarkup.name, config.boldMarkup.attribs);\n if (config.boldMarkup.trim)\n this.trimRange();\n this.forceWrap(bold);\n }\n toggleBold() {\n const bold = this.createElement(config.boldMarkup.name, config.boldMarkup.attribs);\n if (config.boldMarkup.trim)\n this.trimRange();\n this.toggle(bold);\n }\n giveEmphasis() {\n const em = this.createElement(config.italicMarkup.name, config.italicMarkup.attribs);\n if (config.italicMarkup.trim)\n this.trimRange();\n this.forceWrap(em);\n }\n toggleEmphasis() {\n const em = this.createElement(config.italicMarkup.name, config.italicMarkup.attribs);\n if (config.italicMarkup.trim)\n this.trimRange();\n this.toggle(em);\n }\n makeUnderline() {\n const u = this.createElement(config.underlineMarkup.name, config.underlineMarkup.attribs);\n if (config.underlineMarkup.trim)\n this.trimRange();\n this.forceWrap(u);\n }\n toggleUnderline() {\n const u = this.createElement(config.underlineMarkup.name, config.underlineMarkup.attribs);\n if (config.underlineMarkup.trim)\n this.trimRange();\n this.toggle(u);\n }\n insertCharacter(character) {\n const cursor = this.deleteContent();\n const textNode = cursor.createTextNode(character);\n cursor.insertBefore(textNode);\n cursor.setVisibleSelection();\n return cursor;\n }\n // Surround the selection with characters like quotes.\n //\n // @param {String} E.g. '«'\n // @param {String} E.g. '»'\n surround(startCharacter, endCharacter) {\n this.range = content.surround(this.host, this.range, startCharacter, endCharacter);\n this.setVisibleSelection();\n }\n removeSurround(startCharacter, endCharacter) {\n this.range = content.deleteCharacter(this.host, this.range, startCharacter);\n this.range = content.deleteCharacter(this.host, this.range, endCharacter);\n this.setVisibleSelection();\n }\n removeChars(chars = []) {\n for (let i = 0; i < chars.length; i++) {\n const char = chars[i];\n this.range = content.deleteCharacter(this.host, this.range, char);\n }\n this.setVisibleSelection();\n }\n toggleSurround(startCharacter, endCharacter) {\n if (this.containsString(startCharacter) &&\n this.containsString(endCharacter)) {\n this.removeSurround(startCharacter, endCharacter);\n }\n else {\n this.surround(startCharacter, endCharacter);\n }\n }\n // @param {String} selector. An element selector, e.g. 'a' or 'span.some-class'\n // that represents elements to be removed; if undefined,\n // remove all.\n removeFormatting(selector) {\n const newRange = content.removeFormatting(this.host, this.range, selector || null);\n if (newRange) {\n this.range = newRange;\n this.setVisibleSelection();\n }\n }\n // Delete the farest ancestor that is an exact selection\n //\n // @return Selection instance\n deleteExactSurroundingTags() {\n const ancestorTags = this.getAncestorTags().reverse();\n for (const ancestorTag of ancestorTags) {\n if (this.isExactSelection(ancestorTag, undefined)) {\n ancestorTag.remove();\n break;\n }\n }\n return new Selection(this.host, this.range);\n }\n // Delete all the tags whose text is completely within the current selection.\n //\n // @return Selection instance\n deleteContainedTags() {\n const containedTags = this.getContainedTags();\n containedTags.forEach(containedTag => containedTag.remove());\n return new Selection(this.host, this.range);\n }\n // Delete the contents inside the range and exact surrounding markups.\n // After that the selection will be a cursor.\n //\n // @return Cursor instance\n deleteContent() {\n this.range.deleteContents();\n return new Cursor(this.host, this.range);\n }\n // Expand the current selection.\n //\n // @param {DOM Node}\n expandTo(elem) {\n this.range = content.expandTo(this.host, this.range, elem);\n this.setVisibleSelection();\n }\n // Collapse the selection at the beginning of the selection\n //\n // @return Cursor instance\n collapseAtBeginning(elem) {\n this.range.collapse(true);\n this.setVisibleSelection();\n return new Cursor(this.host, this.range);\n }\n // Collapse the selection at the end of the selection\n //\n // @return Cursor instance\n collapseAtEnd(elem) {\n this.range.collapse(false);\n this.setVisibleSelection();\n return new Cursor(this.host, this.range);\n }\n // Wrap the selection with the specified tag. If any other tag with\n // the same tagName is affecting the selection this tag will be\n // remove first.\n forceWrap(elem) {\n if (block.isPlainTextBlock(this.host))\n return;\n if (this.range.collapsed)\n return;\n elem = this.adoptElement(elem);\n const newRange = content.forceWrap(this.host, this.range, elem);\n if (newRange) {\n this.range = newRange;\n this.setVisibleSelection();\n }\n }\n // Check if the selection is the same as the elements contents.\n //\n // @method isExactSelection\n // @param {DOM Node}\n // @param {flag: undefined or 'visible'} if 'visible' is passed\n // whitespaces at the beginning or end of the selection will\n // be ignored.\n // @return {Boolean}\n isExactSelection(elem, onlyVisible) {\n return content.isExactSelection(this.range, elem, onlyVisible === 'visible');\n }\n // Check if the selection contains the passed string.\n //\n // @method containsString\n // @return {Boolean}\n containsString(str) {\n return content.containsString(this.range, str);\n }\n // Delete all occurrences of the specified character from the\n // selection.\n deleteCharacter(character) {\n this.range = content.deleteCharacter(this.host, this.range, character);\n this.setVisibleSelection();\n }\n}\n//# sourceMappingURL=selection.js.map","import Cursor from './cursor.js';\nimport Selection from './selection.js';\nimport { rangesAreEqual } from './util/dom.js';\n/** RangeContainer\n *\n * primarily used to compare ranges\n * its designed to work with undefined ranges as well\n * so we can easily compare them without checking for undefined\n * all the time\n */\nexport default class RangeContainer {\n constructor(editableHost, range) {\n this.host = editableHost && editableHost.jquery\n ? editableHost[0]\n : editableHost;\n // Safari 17 seems to modify the range instance on the fly which breaks later comparisons.\n // We clone the range at the time of the RangeContainer creation.\n // https://developer.apple.com/documentation/safari-release-notes/safari-17-release-notes#New-Features\n this.range = range?.cloneRange();\n this.isAnythingSelected = (range !== undefined);\n this.isCursor = (this.isAnythingSelected && range.collapsed);\n this.isSelection = (this.isAnythingSelected && !this.isCursor);\n }\n getCursor() {\n if (this.isCursor && this.host && this.range)\n return new Cursor(this.host, this.range);\n return undefined;\n }\n getSelection() {\n if (this.isSelection && this.host && this.range)\n return new Selection(this.host, this.range);\n return undefined;\n }\n forceCursor() {\n if (!this.isSelection)\n return this.getCursor();\n const selection = this.getSelection();\n if (selection)\n return selection.deleteContent();\n return undefined;\n }\n isDifferentFrom(otherRangeContainer = new RangeContainer()) {\n const self = this.range;\n const other = otherRangeContainer.range;\n if (self && other)\n return !rangesAreEqual(self, other);\n if (!self && other)\n return false;\n return true;\n }\n}\n//# sourceMappingURL=range-container.js.map","import * as parser from './parser.js';\nimport RangeContainer from './range-container.js';\nimport Cursor from './cursor.js';\nimport Selection from './selection.js';\nimport { getSelection } from './util/dom.js';\n/**\n * The SelectionWatcher module watches for selection changes inside\n * of editable blocks.\n *\n * @module core\n * @submodule selectionWatcher\n */\nexport default class SelectionWatcher {\n constructor(dispatcher, win) {\n this.dispatcher = dispatcher;\n this.win = win || window;\n this.selection = undefined;\n this.currentSelection = undefined;\n this.currentRange = undefined;\n }\n /**\n * Updates the internal selection pointer to the current selection.\n * Returns true if no exception occurred.\n */\n syncSelection() {\n // Note: the try catch was introduced because of rangy exceptions with nativeSelections\n try {\n this.selection = getSelection(this.win);\n }\n catch (err) {\n return false;\n }\n return true;\n }\n /**\n * Return a RangeContainer if the current selection is within an editable\n * otherwise return an empty RangeContainer\n */\n getRangeContainer() {\n const successfulSync = this.syncSelection();\n // rangeCount is 0 or 1 in all browsers except firefox\n // firefox can work with multiple ranges\n // (on a mac hold down the command key to select multiple ranges)\n if (this.selection?.rangeCount && successfulSync) {\n try {\n const range = this.selection.getRangeAt(0);\n // Check if range is still valid (not detached)\n if (range && range.commonAncestorContainer) {\n const hostNode = parser.getHost(range.commonAncestorContainer);\n if (hostNode)\n return new RangeContainer(hostNode, range);\n }\n }\n catch (err) {\n // Range might be detached, return empty container\n }\n }\n // return an empty range container\n return new RangeContainer();\n }\n /**\n * Gets a fresh RangeContainer with the current selection or cursor.\n *\n * @return RangeContainer instance\n */\n getFreshRange() {\n return this.getRangeContainer();\n }\n /**\n * Gets a fresh RangeContainer with the current selection or cursor.\n *\n * @return Either a Cursor or Selection instance or undefined if\n * there is neither a selection or cursor.\n */\n getFreshSelection() {\n const rangeContainer = this.getRangeContainer();\n return rangeContainer.isCursor\n ? rangeContainer.getCursor()\n : rangeContainer.getSelection();\n }\n /**\n * Get the selection set by the last selectionChanged event.\n * Sometimes the event does not fire fast enough and the selection\n * you get is not the one the user sees.\n * In those cases use #getFreshSelection()\n *\n * @return Either a Cursor or Selection instance or undefined if\n * there is neither a selection or cursor.\n */\n getSelection() {\n return this.currentSelection;\n }\n forceCursor() {\n const rangeContainer = this.getRangeContainer();\n return rangeContainer.forceCursor();\n }\n selectionChanged() {\n const newRangeContainer = this.getRangeContainer();\n if (newRangeContainer.isDifferentFrom(this.currentRange)) {\n const lastSelection = this.currentSelection;\n this.currentRange = newRangeContainer;\n // empty selection or cursor\n if (lastSelection) {\n if (lastSelection.isCursor && !this.currentRange.isCursor) {\n this.dispatcher.notify('cursor', lastSelection.host);\n }\n else if (lastSelection.isSelection && !this.currentRange.isSelection) {\n this.dispatcher.notify('selection', lastSelection.host);\n }\n }\n // set new selection or cursor and fire event\n if (this.currentRange.isCursor && this.currentRange.host && this.currentRange.range) {\n this.currentSelection = new Cursor(this.currentRange.host, this.currentRange.range);\n this.dispatcher.notify('cursor', this.currentSelection.host, this.currentSelection);\n }\n else if (this.currentRange.isSelection && this.currentRange.host && this.currentRange.range) {\n this.currentSelection = new Selection(this.currentRange.host, this.currentRange.range);\n this.dispatcher.notify('selection', this.currentSelection.host, this.currentSelection);\n }\n else {\n this.currentSelection = undefined;\n }\n }\n }\n}\n//# sourceMappingURL=selection-watcher.js.map","import { createRange, containsRange } from './util/dom.js';\nimport { contenteditableSpanBug } from './feature-detection.js';\nimport * as nodeType from './node-type.js';\nimport eventable from './eventable.js';\n/**\n * The Keyboard module defines an event API for key events.\n */\nexport default class Keyboard {\n constructor(selectionWatcher) {\n eventable(this);\n this.selectionWatcher = selectionWatcher;\n this.key = Keyboard.key;\n }\n dispatchKeyEvent(event, target, notifyCharacterEvent) {\n switch (event.keyCode) {\n case this.key.left:\n return this.notify(target, 'left', event);\n case this.key.right:\n return this.notify(target, 'right', event);\n case this.key.up:\n return this.notify(target, 'up', event);\n case this.key.down:\n return this.notify(target, 'down', event);\n case this.key.tab:\n if (event.shiftKey)\n return this.notify(target, 'shiftTab', event);\n return this.notify(target, 'tab', event);\n case this.key.esc:\n return this.notify(target, 'esc', event);\n case this.key.backspace:\n this.preventContenteditableBug(target, event);\n return this.notify(target, 'backspace', event);\n case this.key.delete:\n this.preventContenteditableBug(target, event);\n return this.notify(target, 'delete', event);\n case this.key.enter:\n if (event.shiftKey)\n return this.notify(target, 'shiftEnter', event);\n return this.notify(target, 'enter', event);\n case this.key.ctrl:\n case this.key.shift:\n case this.key.alt:\n return;\n // Metakey\n case 224: // Firefox: 224\n case 17: // Opera: 17\n case 91: // Chrome/Safari: 91 (Left)\n case 93: // Chrome/Safari: 93 (Right)\n return;\n default:\n // Added here to avoid using fall-through in the switch\n // when b or i are pressed without ctrlKey or metaKey\n if (event.keyCode === this.key.b && (event.ctrlKey || event.metaKey)) {\n return this.notify(target, 'bold', event);\n }\n if (event.keyCode === this.key.i && (event.ctrlKey || event.metaKey)) {\n return this.notify(target, 'italic', event);\n }\n this.preventContenteditableBug(target, event);\n if (!notifyCharacterEvent)\n return;\n // Don't notify character events as long as either the ctrl or\n // meta key are pressed.\n // see: https://github.com/livingdocsIO/editable.js/pull/125\n if (!event.ctrlKey && !event.metaKey)\n return this.notify(target, 'character', event);\n }\n }\n preventContenteditableBug(target, event) {\n if (!contenteditableSpanBug)\n return;\n if (event.ctrlKey || event.metaKey)\n return;\n // This fixes a strange webkit bug that can be reproduced as follows:\n //\n // 1. A node used within a contenteditable has some style, e.g through the\n // following CSS:\n //\n // strong {\n // color: red\n // }\n //\n // 2. A selection starts with the first character of a styled node and ends\n // outside of that node, e.g: \"big beautiful\" is selected in the following\n // html:\n //\n // <p contenteditable=\"true\">\n // Hello <strong>big</strong> beautiful world\n // </p>\n //\n // 3. The user types a letter character to replace \"big beautiful\", e.g. \"x\"\n //\n // Result: Webkits adds <font> and <b> tags:\n //\n // <p contenteditable=\"true\">\n // Hello\n // <font color=\"#ff0000\">\n // <b>f</b>\n // </font>\n // world\n // </p>\n //\n // This bug ONLY happens, if the first character of the node is selected and\n // the selection goes further than the node.\n //\n // Solution:\n //\n // Manually remove the element that would be removed anyway before inserting\n // the new letter.\n const rangeContainer = this.selectionWatcher.getFreshRange();\n if (!rangeContainer.isSelection || !rangeContainer.range)\n return;\n const nodeToRemove = Keyboard.getNodeToRemove(rangeContainer.range, target);\n if (nodeToRemove)\n nodeToRemove.remove();\n }\n static getNodeToRemove(selectionRange, target) {\n // This function is only used by preventContenteditableBug. It is exposed on\n // the Keyboard constructor for testing purpose only.\n // Let's make sure we are in the edge-case, in which the bug happens.\n // The selection does not start at the beginning of a node. We have\n // nothing to do.\n if (selectionRange.startOffset !== 0)\n return undefined;\n let startNodeElement = selectionRange.startContainer;\n // If the node is a textNode, we select its parent.\n if (startNodeElement.nodeType === nodeType.textNode) {\n const parent = startNodeElement.parentNode;\n if (!parent || parent.nodeType !== nodeType.elementNode)\n return undefined;\n startNodeElement = parent;\n }\n // The target is the contenteditable element, which we do not want to replace\n if (startNodeElement === target)\n return undefined;\n // We get a range that contains everything within the sartNodeElement to test\n // if the selectionRange is within the startNode, we have nothing to do.\n const firstChild = startNodeElement.firstChild;\n const lastChild = startNodeElement.lastChild;\n if (!firstChild || !lastChild)\n return undefined;\n const startNodeRange = createRange();\n startNodeRange.setStartBefore(firstChild);\n startNodeRange.setEndAfter(lastChild);\n if (containsRange(startNodeRange, selectionRange))\n return undefined;\n // If the selectionRange.startContainer was a textNode, we have to make sure\n // that its parent's content starts with this node. Content is either a\n // text node or an element. This is done to avoid false positives like the\n // following one:\n // <strong>foo<em>bar</em>|baz</strong>quux|\n if (selectionRange.startContainer.nodeType === nodeType.textNode) {\n const contentNodeTypes = [nodeType.textNode, nodeType.elementNode];\n let firstContentNode = startNodeElement.firstChild;\n do {\n if (firstContentNode && contentNodeTypes.indexOf(firstContentNode.nodeType) !== -1)\n break;\n firstContentNode = firstContentNode ? firstContentNode.nextSibling : null;\n } while (firstContentNode);\n if (firstContentNode !== selectionRange.startContainer)\n return undefined;\n }\n // Now we know, that we have to return at least the startNodeElement for\n // removal. But it could be, that we also need to remove its parent, e.g.\n // we need to remove <strong> in the following example:\n // <strong><em>|foo</em>bar</strong>baz|\n const rangeStartingBeforeCurrentElement = selectionRange.cloneRange();\n rangeStartingBeforeCurrentElement.setStartBefore(startNodeElement);\n const parentResult = Keyboard.getNodeToRemove(rangeStartingBeforeCurrentElement, target);\n return parentResult || startNodeElement;\n }\n}\nKeyboard.key = Keyboard.prototype.key = {\n left: 37,\n up: 38,\n right: 39,\n down: 40,\n tab: 9,\n esc: 27,\n backspace: 8,\n delete: 46,\n enter: 13,\n shift: 16,\n ctrl: 17,\n alt: 18,\n b: 66,\n i: 73\n};\n//# sourceMappingURL=keyboard.js.map","const isValidQuotePairConfig = (quotePair) => Array.isArray(quotePair) && quotePair.length === 2;\nexport const shouldApplySmartQuotes = (config, target) => {\n const { smartQuotes, quotes, singleQuotes } = config;\n return !!smartQuotes && isValidQuotePairConfig(quotes) && isValidQuotePairConfig(singleQuotes) && target.isContentEditable;\n};\nexport const isDoubleQuote = (char) => /^[\\u00AB\\u00BB\\u201C\\u201D\\u201E\\u0022]$/.test(char);\nexport const isSingleQuote = (char) => /^[\\u2018\\u2019\\u2039\\u203A\\u201A\\u0027]$/.test(char);\nexport const isApostrophe = (char) => /^[\\u2019\\u0027]$/.test(char);\nexport const isWhitespace = (char) => /^\\s$/.test(char);\nexport const isSeparatorOrWhitespace = (char) => /\\s|[>\\-–—]/.test(char);\nconst shouldBeOpeningQuote = (text, indexCharBefore) => indexCharBefore < 0 || isSeparatorOrWhitespace(text[indexCharBefore]);\nconst shouldBeClosingQuote = (text, indexCharBefore) => !!text[indexCharBefore] && !isSeparatorOrWhitespace(text[indexCharBefore]);\nconst hasCharAfter = (textArr, indexCharAfter) => !!textArr[indexCharAfter] && !isWhitespace(textArr[indexCharAfter]);\nconst shouldBeSingleOpeningQuote = (text, indexCharBefore) => !!text[indexCharBefore] && isDoubleQuote(text[indexCharBefore]);\nexport const replaceQuote = (range, index, quoteType) => {\n const startContainer = range?.startContainer;\n if (!startContainer || startContainer.nodeType !== 3) { // Node.TEXT_NODE\n return null;\n }\n const textNode = startContainer;\n const nodeValue = textNode.nodeValue;\n if (!nodeValue) {\n return null;\n }\n const newText = `${nodeValue.substring(0, index)}${quoteType}${nodeValue.substring(index + 1)}`;\n const newTextNode = document.createTextNode(newText);\n textNode.replaceWith(newTextNode);\n return newTextNode;\n};\nconst hasSingleOpeningQuote = (textArr, offset, singleOpeningQuote) => {\n if (offset <= 0) {\n return false;\n }\n for (let i = offset - 1; i >= 0; i--) {\n if (isSingleQuote(textArr[i]) && (!isApostrophe(singleOpeningQuote) && !isApostrophe(textArr[i]))) {\n return textArr[i] === singleOpeningQuote;\n }\n }\n return false;\n};\nexport const applySmartQuotes = (range, config, char, target, cursorOffset) => {\n const isCharSingleQuote = isSingleQuote(char);\n const isCharDoubleQuote = isDoubleQuote(char);\n if (!isCharDoubleQuote && !isCharSingleQuote) {\n return;\n }\n const { quotes, singleQuotes } = config;\n if (char === quotes[0] || char === quotes[1] || char === singleQuotes[0] || char === singleQuotes[1]) {\n return;\n }\n const offset = range.startOffset;\n const textContent = range.startContainer.textContent;\n if (!textContent)\n return;\n const textArr = [...textContent];\n let newTextNode = null;\n // Special case for a single quote following a double quote,\n // which should be transformed into a single opening quote\n if (isCharSingleQuote && shouldBeSingleOpeningQuote(textArr, offset - 2)) {\n newTextNode = replaceQuote(range, offset - 1, singleQuotes[0]);\n }\n else if (shouldBeClosingQuote(textArr, offset - 2)) {\n if (isCharSingleQuote) {\n // Don't transform apostrophes\n if (hasCharAfter(textArr, offset)) {\n return;\n }\n // Don't transform single-quote if there is no respective single-opening-quote\n if (!hasSingleOpeningQuote(textArr, offset, singleQuotes[0])) {\n return;\n }\n }\n const closingQuote = isCharSingleQuote ? singleQuotes[1] : quotes[1];\n newTextNode = replaceQuote(range, offset - 1, closingQuote);\n }\n else if (shouldBeOpeningQuote(textArr, offset - 2)) {\n const openingQuote = isCharSingleQuote ? singleQuotes[0] : quotes[0];\n newTextNode = replaceQuote(range, offset - 1, openingQuote);\n }\n if (!newTextNode) {\n return;\n }\n // Resets the cursor to the currentPosition after applying the smart-quote\n const window = target.ownerDocument.defaultView;\n if (!window)\n return;\n const selection = window.getSelection();\n if (!selection)\n return;\n selection.collapse(newTextNode, cursorOffset ?? offset);\n};\n//# sourceMappingURL=smartQuotes.js.map","import { selectionchange } from './feature-detection.js';\nimport * as clipboard from './clipboard.js';\nimport * as content from './content.js';\nimport eventable from './eventable.js';\nimport SelectionWatcher from './selection-watcher.js';\nimport config from './config.js';\nimport Keyboard from './keyboard.js';\nimport { closest } from './util/dom.js';\nimport { replaceLast, endsWithSingleSpace } from './util/string.js';\nimport { applySmartQuotes, shouldApplySmartQuotes } from './smartQuotes.js';\n/**\n * The Dispatcher module is responsible for dealing with events and their handlers.\n *\n * @module core\n * @submodule dispatcher\n */\nexport default class Dispatcher {\n constructor(editable) {\n const win = editable.win;\n eventable(this, editable);\n this.document = win.document;\n this.config = editable.config;\n this.editable = editable;\n this.editableSelector = editable.editableSelector;\n this.selectionWatcher = new SelectionWatcher(this, win);\n this.keyboard = new Keyboard(this.selectionWatcher);\n this.activeListeners = [];\n this.setup();\n this.getEditableBlockByEvent = (evt) => {\n const target = evt.target;\n return target ? closest(target, editable.editableSelector) : undefined;\n };\n }\n setupDocumentListener(event, func, capture = false) {\n const listener = { event, listener: func.bind(this), capture };\n this.activeListeners.push(listener);\n this.document.addEventListener(event, listener.listener, capture);\n return this;\n }\n /**\n * Sets up all events that Editable.JS is catching.\n *\n * @method setup\n */\n setup() {\n // setup all events listeners and keyboard handlers\n this.setupKeyboardEvents();\n this.setupEventListeners();\n }\n unload() {\n this.off();\n for (const l of this.activeListeners) {\n this.document.removeEventListener(l.event, l.listener, l.capture);\n }\n this.activeListeners.length = 0;\n }\n suspend() {\n if (this.suspended)\n return;\n this.suspended = true;\n for (const l of this.activeListeners) {\n this.document.removeEventListener(l.event, l.listener, l.capture);\n }\n this.activeListeners.length = 0;\n }\n continue() {\n if (!this.suspended)\n return;\n this.suspended = false;\n this.setupEventListeners();\n }\n setupEventListeners() {\n this.setupElementListeners();\n this.setupKeydownListener();\n if (selectionchange) {\n this.setupSelectionChangeListeners();\n }\n else {\n this.setupSelectionChangeFallbackListeners();\n }\n }\n /**\n * Sets up events that are triggered on modifying an element.\n *\n * @method setupElementListeners\n */\n setupElementListeners() {\n const currentInput = { offset: undefined };\n this\n .setupDocumentListener('focus', function focusListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const target = evt.target;\n if (target && target.getAttribute(config.pastingAttribute))\n return;\n this.selectionWatcher.syncSelection();\n this.notify('focus', block);\n }, true)\n .setupDocumentListener('blur', function blurListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n if (block.getAttribute(config.pastingAttribute))\n return;\n this.notify('blur', block);\n }, true)\n .setupDocumentListener('copy', function copyListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const selection = this.selectionWatcher.getFreshSelection();\n if (selection && selection.isSelection) {\n this.notify('clipboard', block, 'copy', selection);\n }\n })\n .setupDocumentListener('cut', function cutListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const selection = this.selectionWatcher.getFreshSelection();\n if (selection && selection.isSelection) {\n this.notify('clipboard', block, 'cut', selection);\n }\n })\n .setupDocumentListener('paste', function pasteListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const clipEvent = evt;\n clipEvent.preventDefault();\n const selection = this.selectionWatcher.getFreshSelection();\n if (!selection || !clipEvent.clipboardData)\n return;\n const clipboardContent = clipEvent.clipboardData.getData('text/html') || clipEvent.clipboardData.getData('text/plain');\n const { blocks, cursor } = clipboard.paste(block, selection, clipboardContent);\n if (blocks.length) {\n const target = clipEvent.target;\n if (target && endsWithSingleSpace(target.innerText)) {\n cursor.retainVisibleSelection(() => {\n block.innerHTML = replaceLast(block.innerHTML, ' ', ' ');\n });\n }\n this.notify('paste', block, blocks, cursor);\n // The input event does not fire when we process the content manually\n // and insert it via script\n this.notify('change', block);\n }\n else {\n cursor.setVisibleSelection();\n }\n })\n .setupDocumentListener('input', function inputListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const target = evt.target;\n if (target && shouldApplySmartQuotes(this.config, target)) {\n const selection = this.selectionWatcher.getFreshSelection();\n if (!selection || !selection.range)\n return;\n // Save offset of new input, to reset cursor correctly after timeout delay\n currentInput.offset = selection.range.startOffset;\n const inputEvent = evt;\n const quotesConfig = this.config.quotes || { quotes: [], singleQuotes: [] };\n setTimeout(() => {\n if (inputEvent.data) {\n applySmartQuotes(selection.range, quotesConfig, inputEvent.data, target, currentInput.offset);\n }\n }, 300);\n }\n this.notify('change', block);\n })\n .setupDocumentListener('formatEditable', function formatEditableListener(evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n this.notify('change', block);\n });\n }\n dispatchSwitchEvent(event, element, direction) {\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)\n return;\n const cursor = this.selectionWatcher.getFreshSelection();\n if (!cursor || cursor.isSelection)\n return;\n // store position\n if (!this.switchContext) {\n this.switchContext = {\n positionX: cursor.getBoundingClientRect().left,\n events: ['cursor']\n };\n }\n else {\n this.switchContext.events = ['cursor'];\n }\n if (direction === 'up' && cursor.isAtFirstLine()) {\n event.preventDefault();\n event.stopPropagation();\n this.switchContext.events = ['switch', 'blur', 'focus', 'cursor'];\n this.notify('switch', element, direction, cursor);\n }\n if (direction === 'down' && cursor.isAtLastLine()) {\n event.preventDefault();\n event.stopPropagation();\n this.switchContext.events = ['switch', 'blur', 'focus', 'cursor'];\n this.notify('switch', element, direction, cursor);\n }\n }\n /**\n * Sets up listener for keydown event which forwards events to\n * the Keyboard instance.\n *\n * @method setupKeydownListener\n */\n setupKeydownListener() {\n this.setupDocumentListener('keydown', function (evt) {\n const block = this.getEditableBlockByEvent(evt);\n if (!block)\n return;\n const keyEvent = evt;\n this.keyboard.dispatchKeyEvent(keyEvent, block, false);\n }, true);\n }\n /**\n * Sets up handlers for the keyboard events.\n * Keyboard definitions are in {{#crossLink \"Keyboard\"}}{{/crossLink}}.\n *\n * @method setupKeyboardEvents\n */\n setupKeyboardEvents() {\n const self = this;\n this.keyboard\n .on('up', function (event) {\n self.dispatchSwitchEvent(event, this, 'up');\n })\n .on('down', function (event) {\n self.dispatchSwitchEvent(event, this, 'down');\n })\n .on('backspace', function (event) {\n const editableBlock = this;\n const rangeContainer = self.selectionWatcher.getFreshRange();\n if (!rangeContainer.isCursor)\n return;\n const cursor = rangeContainer.getCursor();\n if (!cursor || !cursor.isAtBeginning())\n return;\n event.preventDefault();\n event.stopPropagation();\n self.notify('merge', editableBlock, 'before', cursor);\n })\n .on('delete', function (event) {\n const editableBlock = this;\n const rangeContainer = self.selectionWatcher.getFreshRange();\n if (!rangeContainer.isCursor)\n return;\n const cursor = rangeContainer.getCursor();\n if (!cursor || !cursor.isAtTextEnd())\n return;\n event.preventDefault();\n event.stopPropagation();\n self.notify('merge', editableBlock, 'after', cursor);\n })\n .on('enter', function (event) {\n const editableBlock = this;\n event.preventDefault();\n event.stopPropagation();\n const rangeContainer = self.selectionWatcher.getFreshRange();\n const cursor = rangeContainer.forceCursor();\n if (!cursor)\n return;\n if (cursor.isAtTextEnd()) {\n self.notify('insert', editableBlock, 'after', cursor);\n }\n else if (cursor.isAtBeginning()) {\n self.notify('insert', editableBlock, 'before', cursor);\n }\n else {\n const beforeFragment = cursor.before();\n const afterFragment = cursor.after();\n self.notify('split', editableBlock, content.getInnerHtmlOfFragment(beforeFragment), content.getInnerHtmlOfFragment(afterFragment), cursor);\n }\n })\n .on('shiftEnter', function (event) {\n const editableBlock = this;\n event.preventDefault();\n event.stopPropagation();\n const cursor = self.selectionWatcher.forceCursor();\n if (cursor) {\n self.notify('newline', editableBlock, cursor);\n }\n })\n .on('bold', function (event) {\n event.preventDefault();\n event.stopPropagation();\n const selection = self.selectionWatcher.getFreshSelection();\n if (selection && selection.isSelection) {\n self.notify('toggleBold', selection);\n }\n })\n .on('italic', function (event) {\n event.preventDefault();\n event.stopPropagation();\n const selection = self.selectionWatcher.getFreshSelection();\n if (selection && selection.isSelection) {\n self.notify('toggleEmphasis', selection);\n }\n })\n .on('character', function (event) {\n const editableBlock = this;\n self.notify('change', editableBlock);\n });\n }\n /**\n * Sets up events that are triggered on a selection change.\n *\n * @method setupSelectionChangeListeners\n */\n setupSelectionChangeListeners() {\n let selectionDirty = false;\n let suppressSelectionChanges = false;\n const selectionWatcher = this.selectionWatcher;\n // fires on mousemove (thats probably a bit too much)\n // catches changes like 'select all' from context menu\n this.setupDocumentListener('selectionchange', (evt) => {\n let didSyncSelection = false;\n let cursor = this.selectionWatcher.getFreshSelection();\n if (!cursor) {\n selectionWatcher.selectionChanged();\n didSyncSelection = true;\n cursor = this.selectionWatcher.getSelection();\n }\n if (cursor && cursor.isSelection && cursor.isAtBeginning() && cursor.isAtEnd()) {\n this.notify('selectToBoundary', cursor.host, evt, 'both');\n }\n else if (cursor && cursor.isSelection && cursor.isAtBeginning()) {\n this.notify('selectToBoundary', cursor.host, evt, 'start');\n }\n else if (cursor && cursor.isSelection && cursor.isAtEnd()) {\n this.notify('selectToBoundary', cursor.host, evt, 'end');\n }\n if (suppressSelectionChanges) {\n selectionDirty = true;\n }\n else if (!didSyncSelection) {\n selectionWatcher.selectionChanged();\n }\n });\n // listen for selection changes by mouse so we can\n // suppress the selectionchange event and only fire the\n // change event on mouseup\n this.setupDocumentListener('mousedown', function (evt) {\n const mouseEvent = evt;\n if (!this.getEditableBlockByEvent(evt))\n return;\n if (this.config.mouseMoveSelectionChanges === false) {\n suppressSelectionChanges = true;\n // Without this timeout the previous selection is active\n // until the mouseup event (no. not good).\n setTimeout(() => selectionWatcher.selectionChanged(), 0);\n }\n const self = this;\n this.document.addEventListener('mouseup', () => {\n suppressSelectionChanges = false;\n if (selectionDirty) {\n selectionDirty = false;\n selectionWatcher.selectionChanged();\n }\n }, {\n capture: true,\n once: true\n });\n });\n }\n /**\n * Fallback solution to support selection change events on browsers that don't\n * support selectionChange.\n *\n * @method setupSelectionChangeFallbackListeners\n */\n setupSelectionChangeFallbackListeners() {\n const notifySelectionBoundary = (evt) => {\n const cursor = this.selectionWatcher.getFreshSelection();\n if (cursor && cursor.isSelection && cursor.isAtBeginning() && cursor.isAtEnd()) {\n this.notify('selectToBoundary', cursor.host, evt, 'both');\n }\n else if (cursor && cursor.isSelection && cursor.isAtBeginning()) {\n this.notify('selectToBoundary', cursor.host, evt, 'start');\n }\n else if (cursor && cursor.isSelection && cursor.isAtEnd()) {\n this.notify('selectToBoundary', cursor.host, evt, 'end');\n }\n };\n // listen for selection changes by mouse\n this.setupDocumentListener('mouseup', (evt) => {\n // In Opera when clicking outside of a block\n // it does not update the selection as it should\n // without the timeout\n setTimeout(() => {\n this.selectionWatcher.selectionChanged();\n notifySelectionBoundary(evt);\n }, 0);\n });\n // listen for selection changes by keys\n this.setupDocumentListener('keyup', (evt) => {\n if (!this.getEditableBlockByEvent(evt))\n return;\n // when pressing Command + Shift + Left for example the keyup is only triggered\n // after at least two keys are released. Strange. The culprit seems to be the\n // Command key. Do we need a workaround?\n this.selectionWatcher.selectionChanged();\n notifySelectionBoundary(evt);\n });\n }\n}\n//# sourceMappingURL=dispatcher.js.map","/**\n * Deep merge objects, creating a new object with merged properties.\n * Arrays are replaced (not merged).\n */\nexport function deepMerge(target, ...sources) {\n const result = { ...target };\n for (const source of sources) {\n if (!source || typeof source !== 'object')\n continue;\n for (const key in source) {\n if (!Object.prototype.hasOwnProperty.call(source, key))\n continue;\n const sourceValue = source[key];\n const targetValue = result[key];\n // Deep merge if both are plain objects\n if (sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)) {\n result[key] = deepMerge({}, targetValue, sourceValue);\n }\n else {\n result[key] = sourceValue;\n }\n }\n }\n return result;\n}\n//# sourceMappingURL=merge.js.map","import * as content from '../../content.js';\n/**\n* Spellcheck class.\n*\n* @class Spellcheck\n* @constructor\n*/\nexport default class SpellcheckService {\n constructor(spellcheckService) {\n this.spellcheckService = spellcheckService;\n }\n check(text, callback) {\n if (!text)\n return callback(null);\n const condensedText = content.normalizeWhitespace(text);\n this.spellcheckService(condensedText, (misspelledWords) => {\n if (misspelledWords && misspelledWords.length > 0) {\n return callback(null, misspelledWords);\n }\n return callback(null);\n });\n }\n}\n//# sourceMappingURL=spellcheck-service.js.map","// See: https://en.wikipedia.org/wiki/Whitespace_character\nconst characters = {\n 'A0': 'no-break space', // \\\\u00A0\n '2000': 'en quad', // \\\\u2000\n '2001': 'em quad', // \\\\u2001\n '2002': 'en space', // \\\\u2002\n '2003': 'em space', // \\\\u2003\n '2004': 'three-per-em space', // \\\\u2004\n '2005': 'four-per-em space', // \\\\u2005\n '2006': 'six-per-em space', // \\\\u2006\n '2007': 'figure space', // \\\\u2007\n '2008': 'punctuation space', // \\\\u2008\n '2009': 'thin space', // \\\\u2009\n '200A': 'hair space', // \\\\u200A\n '202F': 'narrow no-break space', // \\\\u202F\n '205F': 'medium mathematical space', // \\\\u205F\n '3000': 'ideographic space' // \\\\u3000\n};\n// The no-break space is not highlighted as this can cause problems.\n// Browser can insert no-break spaces when typing at the end of\n// a paragraph and the highlighting prevents browsers from converting\n// the no-break space back to a normal space when the user keeps typing.\nconst specialWhitespaceChars = '\\\\u2000-\\\\u200A\\\\u202F\\\\u205F\\\\u3000';\nconst specialWhitespaceCharsRegex = new RegExp(`[${specialWhitespaceChars}]`, 'g');\nexport default class WhitespaceHighlighting {\n constructor(markerNode) {\n this.marker = markerNode;\n }\n findMatches(text) {\n if (!text)\n return;\n const matches = [...text.matchAll(specialWhitespaceCharsRegex)];\n return matches.map((entry) => this.prepareMatch(entry));\n }\n prepareMatch(match) {\n const startIndex = match.index;\n const unicode = getUnicode(match[0]);\n const description = characters[unicode] || 'unknown whitespace';\n return {\n startIndex,\n endIndex: startIndex + match.length,\n match: match[0],\n title: `${description} (\\\\u${unicode})`,\n marker: this.marker\n };\n }\n}\nfunction getUnicode(character) {\n const code = character.charCodeAt(0);\n return `${code.toString(16).toUpperCase()}`;\n}\n//# sourceMappingURL=whitespace-highlighting.js.map","export default class MatchCollection {\n constructor() {\n this.matches = [];\n }\n addMatches(matches) {\n if (!matches?.length)\n return;\n this.matches = mergeMatches(this.matches, matches);\n }\n}\n// Private Helpers\n// ---------------\nfunction mergeMatches(matches1, matches2) {\n let next;\n const length1 = matches1.length;\n const length2 = matches2.length;\n let lastEndIndex = -1;\n const output = [];\n const state = {\n a1: matches1,\n i1: 0,\n a2: matches2,\n i2: 0\n };\n while (state.i1 < length1 || state.i2 < length2) {\n next = pickNext(state);\n if (next && next.startIndex >= lastEndIndex) {\n output.push(next);\n lastEndIndex = next.endIndex;\n }\n else if (next) {\n lastEndIndex = next.endIndex;\n }\n }\n return output;\n}\nfunction pickNext(state) {\n const i1 = state.i1;\n const i2 = state.i2;\n const item1 = state.a1[i1];\n const item2 = state.a2[i2];\n if (item1 && item2 && item1.startIndex < item2.startIndex) {\n state.i1 = i1 + 1;\n return item1;\n }\n else if (item1 && item2) {\n state.i2 = i2 + 1;\n return item2;\n }\n else if (item1) {\n state.i1 = i1 + 1;\n return item1;\n }\n else if (item2) {\n state.i2 = i2 + 1;\n return item2;\n }\n else {\n return undefined;\n }\n}\n//# sourceMappingURL=match-collection.js.map","import * as nodeType from './node-type.js';\nimport { deepMerge } from './util/merge.js';\nimport * as content from './content.js';\nimport highlightText from './highlight-text.js';\nimport SpellcheckService from './plugins/highlighting/spellcheck-service.js';\nimport WhitespaceHighlighting from './plugins/highlighting/whitespace-highlighting.js';\nimport { searchAllWords } from './plugins/highlighting/text-search.js';\nimport MatchCollection from './plugins/highlighting/match-collection.js';\nimport highlightSupport from './highlight-support.js';\nimport { domArray, domSelector } from './util/dom.js';\nexport default class MonitoredHighlighting {\n constructor(editable, configuration, spellcheckConfig) {\n this.editable = editable;\n this.win = editable.win;\n this.focusedEditableHost = undefined;\n this.currentlyCheckedEditableHost = undefined;\n this.timeout = {};\n const defaultConfig = {\n checkOnInit: false,\n checkOnFocus: false,\n checkOnChange: true,\n // unbounce rate in ms before calling the spellcheck service after changes\n throttle: 1000,\n // remove highlights after a change if the cursor is inside a highlight\n removeOnCorrection: true,\n spellcheck: {\n marker: '<span class=\"highlight-spellcheck\"></span>',\n throttle: 1000,\n spellcheckService: function () { }\n },\n whitespace: {\n marker: '<span class=\"highlight-whitespace\"></span>'\n }\n };\n this.config = deepMerge({}, defaultConfig, configuration);\n const spellcheckService = this.config.spellcheck.spellcheckService;\n const spellcheckMarker = this.config.spellcheck.marker;\n const whitespaceMarker = this.config.whitespace.marker;\n const whitespaceMarkerNode = highlightSupport\n .createMarkerNode(whitespaceMarker, 'whitespace', this.win);\n const spellcheckMarkerNode = highlightSupport\n .createMarkerNode(spellcheckMarker, 'spellcheck', this.win);\n if (!whitespaceMarkerNode || !spellcheckMarkerNode) {\n throw new Error('Failed to create marker nodes');\n }\n this.spellcheckMarkerNode = spellcheckMarkerNode;\n this.spellcheckService = new SpellcheckService(spellcheckService);\n this.whitespace = new WhitespaceHighlighting(whitespaceMarkerNode);\n this.setupListeners();\n }\n // Events\n // ------\n setupListeners() {\n if (this.config.checkOnFocus) {\n this.editable.on('focus', (editableHost) => this.onFocus(editableHost));\n this.editable.on('blur', (editableHost) => this.onBlur(editableHost));\n }\n if (this.config.checkOnChange || this.config.removeOnCorrection) {\n this.editable.on('change', (editableHost) => this.onChange(editableHost));\n }\n if (this.config.checkOnInit) {\n this.editable.on('init', (editableHost) => this.onInit(editableHost));\n }\n }\n onInit(editableHost) {\n this.highlight(editableHost);\n }\n onFocus(editableHost) {\n if (this.focusedEditableHost !== editableHost) {\n this.focusedEditableHost = editableHost;\n this.editableHasChanged(editableHost, undefined);\n }\n }\n onBlur(editableHost) {\n if (this.focusedEditableHost === editableHost) {\n this.focusedEditableHost = undefined;\n }\n }\n onChange(editableHost) {\n if (this.config.checkOnChange) {\n this.editableHasChanged(editableHost, this.config.throttle);\n }\n if (this.config.removeOnCorrection) {\n this.removeHighlightsAtCursor(editableHost);\n }\n }\n // Manage Highlights\n // -----------------\n editableHasChanged(editableHost, throttle) {\n if (this.timeout.id && this.timeout.editableHost === editableHost) {\n clearTimeout(this.timeout.id);\n }\n const timeoutId = setTimeout(() => {\n this.highlight(editableHost);\n this.timeout = {};\n }, throttle || 0);\n this.timeout = {\n id: timeoutId,\n editableHost: editableHost\n };\n }\n highlight(editableHost) {\n const textBefore = highlightText.extractText(editableHost);\n // getSpellcheck\n this.spellcheckService.check(textBefore, (err, misspelledWords) => {\n if (err || !editableHost.isConnected) {\n return;\n } // return in case the host was removed from the dom\n // refresh the text\n const text = highlightText.extractText(editableHost);\n const matchCollection = new MatchCollection();\n if (misspelledWords && misspelledWords.length > 0) {\n const matches = searchAllWords(text, misspelledWords, this.spellcheckMarkerNode);\n matchCollection.addMatches(matches);\n }\n const whitespaceMatches = this.whitespace.findMatches(text);\n if (whitespaceMatches) {\n // Convert WhitespaceMatch[] to Match[]\n const matches = whitespaceMatches.map(m => ({\n startIndex: m.startIndex || 0,\n endIndex: m.endIndex,\n match: m.match,\n marker: m.marker\n }));\n matchCollection.addMatches(matches);\n }\n this.safeHighlightMatches(editableHost, matchCollection.matches);\n });\n }\n // Calls highlightMatches internally but ensures\n // that the selection stays the same\n safeHighlightMatches(editableHost, matches) {\n const selection = this.editable.getSelection(editableHost);\n if (selection) {\n selection.retainVisibleSelection(() => {\n this.highlightMatches(editableHost, matches);\n });\n }\n else {\n this.highlightMatches(editableHost, matches);\n }\n if (this.editable.dispatcher) {\n this.editable.dispatcher.notify('spellcheckUpdated', editableHost);\n }\n }\n highlightMatches(editableHost, matches) {\n // Remove old highlights\n this.removeHighlights(editableHost);\n // Create new highlights\n if (matches && matches.length > 0) {\n // const span = this.createMarkerNode()\n highlightText.highlightMatches(editableHost, matches);\n }\n }\n removeHighlights(editableHost) {\n const host = domSelector(editableHost, this.win.document);\n if (!host)\n return;\n for (const elem of domArray('[data-highlight=\"spellcheck\"], [data-highlight=\"whitespace\"]', this.win.document, host)) {\n content.unwrap(elem);\n }\n }\n removeHighlightsAtCursor(editableHost) {\n const host = domSelector(editableHost, this.win.document);\n if (!host)\n return;\n editableHost = host;\n const selection = this.editable.getSelection(editableHost);\n if (selection && selection.isCursor) {\n let elementAtCursor = selection.range.startContainer;\n if (elementAtCursor.nodeType === nodeType.textNode) {\n elementAtCursor = elementAtCursor.parentNode;\n }\n let wordId;\n do {\n if (elementAtCursor === editableHost)\n return;\n const highlightType = elementAtCursor.getAttribute('data-highlight');\n if (highlightType === 'spellcheck' || highlightType === 'whitespace') {\n wordId = elementAtCursor.getAttribute('data-word-id');\n break;\n }\n } while ((elementAtCursor = elementAtCursor.parentNode));\n if (wordId) {\n selection.retainVisibleSelection(() => {\n for (const elem of domArray(`[data-word-id=\"${wordId}\"]`, this.win.document, host)) {\n content.unwrap(elem);\n }\n });\n }\n }\n }\n}\n//# sourceMappingURL=monitored-highlighting.js.map","/**\n * Compute character-level diff between two strings\n * Returns an array of operations (equal, delete, insert)\n */\nexport function computeDiff(oldText, newText) {\n if (oldText === newText) {\n return [{\n type: 'equal',\n value: oldText,\n oldStart: 0,\n oldEnd: oldText.length,\n newStart: 0,\n newEnd: newText.length\n }];\n }\n if (oldText === '') {\n return [{\n type: 'insert',\n value: newText,\n oldStart: 0,\n oldEnd: 0,\n newStart: 0,\n newEnd: newText.length\n }];\n }\n if (newText === '') {\n return [{\n type: 'delete',\n value: oldText,\n oldStart: 0,\n oldEnd: oldText.length,\n newStart: 0,\n newEnd: 0\n }];\n }\n // Use longest common subsequence (LCS) approach\n const operations = [];\n const lcs = computeLCS(oldText, newText);\n let oldIndex = 0;\n let newIndex = 0;\n let lcsIndex = 0;\n while (oldIndex < oldText.length || newIndex < newText.length) {\n // Find the next common character\n if (lcsIndex < lcs.length &&\n oldIndex < oldText.length &&\n newIndex < newText.length &&\n oldText[oldIndex] === lcs[lcsIndex] &&\n newText[newIndex] === lcs[lcsIndex]) {\n // Common character found\n const startOld = oldIndex;\n const startNew = newIndex;\n let commonLength = 0;\n while (lcsIndex < lcs.length &&\n oldIndex < oldText.length &&\n newIndex < newText.length &&\n oldText[oldIndex] === lcs[lcsIndex] &&\n newText[newIndex] === lcs[lcsIndex]) {\n commonLength++;\n oldIndex++;\n newIndex++;\n lcsIndex++;\n }\n operations.push({\n type: 'equal',\n value: oldText.substring(startOld, (startOld + commonLength)),\n oldStart: startOld,\n oldEnd: (startOld + commonLength),\n newStart: startNew,\n newEnd: (startNew + commonLength)\n });\n }\n else {\n // Handle deletions and insertions\n const deleteStart = oldIndex;\n const insertStart = newIndex;\n // Collect deletions (characters in oldText not in LCS)\n while (oldIndex < oldText.length &&\n ((lcsIndex >= lcs.length) || (oldText[oldIndex] !== lcs[lcsIndex]))) {\n oldIndex++;\n }\n // Collect insertions (characters in newText not in LCS)\n while (newIndex < newText.length &&\n ((lcsIndex >= lcs.length) || (newText[newIndex] !== lcs[lcsIndex]))) {\n newIndex++;\n }\n if (oldIndex > deleteStart) {\n operations.push({\n type: 'delete',\n value: oldText.substring(deleteStart, oldIndex),\n oldStart: deleteStart,\n oldEnd: oldIndex,\n newStart: insertStart,\n newEnd: insertStart\n });\n }\n if (newIndex > insertStart) {\n operations.push({\n type: 'insert',\n value: newText.substring(insertStart, newIndex),\n oldStart: deleteStart,\n oldEnd: deleteStart,\n newStart: insertStart,\n newEnd: newIndex\n });\n }\n }\n }\n return operations;\n}\n/**\n * Compute Longest Common Subsequence (LCS) between two strings\n * Returns the LCS as a string\n */\nfunction computeLCS(str1, str2) {\n const m = str1.length;\n const n = str2.length;\n const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));\n // Build DP table\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (str1[i - 1] === str2[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1] + 1;\n }\n else {\n dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);\n }\n }\n }\n // Reconstruct LCS\n let lcs = '';\n let i = m;\n let j = n;\n while (i > 0 && j > 0) {\n if (str1[i - 1] === str2[j - 1]) {\n lcs = str1[i - 1] + lcs;\n i--;\n j--;\n }\n else if (dp[i - 1][j] > dp[i][j - 1]) {\n i--;\n }\n else {\n j--;\n }\n }\n return lcs;\n}\n//# sourceMappingURL=diff-algorithm.js.map","import highlightText from '../../highlight-text.js';\nimport highlightSupport from '../../highlight-support.js';\nimport { computeDiff } from './diff-algorithm.js';\nimport { domArray, domSelector } from '../../util/dom.js';\nimport * as content from '../../content.js';\nexport default class TextDiff {\n constructor(editable, configuration) {\n this.isApplyingDiff = false;\n this.editable = editable;\n this.win = editable.win;\n this.originalTexts = new Map();\n const defaultConfig = {\n enabled: true,\n checkOnInit: true,\n checkOnFocus: false,\n markerDeleted: '<span class=\"highlight-diff-deleted\"></span>',\n markerInserted: '<span class=\"highlight-diff-inserted\"></span>',\n throttle: 300\n };\n this.config = Object.assign({}, defaultConfig, configuration);\n this.timeout = {};\n // Create marker nodes\n const deletedMarkerNode = highlightSupport.createMarkerNode(this.config.markerDeleted, 'diff-deleted', this.win);\n const insertedMarkerNode = highlightSupport.createMarkerNode(this.config.markerInserted, 'diff-inserted', this.win);\n if (!deletedMarkerNode || !insertedMarkerNode) {\n throw new Error('Failed to create diff marker nodes');\n }\n this.deletedMarkerNode = deletedMarkerNode;\n this.insertedMarkerNode = insertedMarkerNode;\n this.setupListeners();\n }\n setupListeners() {\n if (this.config.checkOnInit) {\n this.editable.on('init', (editableHost) => this.onInit(editableHost));\n }\n if (this.config.checkOnFocus) {\n this.editable.on('focus', (editableHost) => this.onFocus(editableHost));\n }\n if (this.config.enabled) {\n this.editable.on('change', (editableHost) => this.onChange(editableHost));\n }\n }\n onInit(editableHost) {\n this.captureOriginalText(editableHost);\n }\n onFocus(editableHost) {\n if (this.config.checkOnFocus) {\n this.captureOriginalText(editableHost);\n }\n }\n onChange(editableHost) {\n if (!this.config.enabled || this.isApplyingDiff)\n return;\n if (this.timeout.id && this.timeout.editableHost === editableHost) {\n clearTimeout(this.timeout.id);\n }\n const timeoutId = setTimeout(() => {\n this.computeAndApplyDiff(editableHost);\n this.timeout = {};\n }, this.config.throttle);\n this.timeout = {\n id: timeoutId,\n editableHost\n };\n }\n captureOriginalText(editableHost) {\n const text = highlightText.extractText(editableHost);\n this.originalTexts.set(editableHost, text);\n // Clear existing diff highlights when capturing new original\n this.clearDiffHighlights(editableHost);\n }\n setOriginalText(editableHost, text) {\n this.originalTexts.set(editableHost, text);\n this.computeAndApplyDiff(editableHost);\n }\n getOriginalText(editableHost) {\n return this.originalTexts.get(editableHost);\n }\n clearOriginalText(editableHost) {\n this.originalTexts.delete(editableHost);\n this.clearDiffHighlights(editableHost);\n }\n computeAndApplyDiff(editableHost) {\n const originalText = this.originalTexts.get(editableHost);\n if (!originalText)\n return;\n const currentText = highlightText.extractText(editableHost);\n if (originalText === currentText) {\n this.clearDiffHighlights(editableHost);\n return;\n }\n const operations = computeDiff(originalText, currentText);\n this.applyDiff(editableHost, operations);\n }\n applyDiff(editableHost, operations) {\n // Prevent recursive calls\n if (this.isApplyingDiff)\n return;\n this.isApplyingDiff = true;\n try {\n // Clear existing diff highlights\n this.clearDiffHighlights(editableHost);\n const selection = this.editable.getSelection(editableHost);\n const retainSelection = selection && selection.retainVisibleSelection;\n if (retainSelection) {\n selection.retainVisibleSelection(() => {\n this.highlightDiffOperations(editableHost, operations);\n });\n }\n else {\n this.highlightDiffOperations(editableHost, operations);\n }\n }\n finally {\n this.isApplyingDiff = false;\n }\n }\n highlightDiffOperations(editableHost, operations) {\n const currentText = highlightText.extractText(editableHost, false);\n let highlightIdCounter = 0;\n // First, handle insertions (they exist in current text)\n for (const op of operations) {\n if (op.type === 'insert') {\n const highlightId = `diff-inserted-${highlightIdCounter++}`;\n const startIndex = op.newStart;\n const endIndex = Math.min(op.newEnd, currentText.length);\n if (startIndex < currentText.length && endIndex > startIndex) {\n try {\n highlightSupport.highlightRange(editableHost, op.value, highlightId, startIndex, endIndex, undefined, this.win, 'diff-inserted');\n }\n catch (e) {\n console.warn('Failed to highlight insertion:', e);\n }\n }\n }\n }\n // Then handle deletions by inserting them as non-editable markers\n // We need to process deletions in reverse order to maintain correct positions\n const deletions = operations.filter(op => op.type === 'delete').reverse();\n for (const op of deletions) {\n const highlightId = `diff-deleted-${highlightIdCounter++}`;\n const insertPosition = this.mapOriginalToCurrentPosition(operations, op.oldStart);\n if (insertPosition !== null) {\n try {\n const cursor = this.editable.createCursorAtCharacterOffset({\n element: editableHost,\n offset: insertPosition\n });\n if (cursor) {\n cursor.retainVisibleSelection(() => {\n // Create a span with the deleted text, marked as non-editable\n const deletedSpan = this.deletedMarkerNode.cloneNode(true);\n deletedSpan.setAttribute('data-word-id', highlightId);\n deletedSpan.setAttribute('contenteditable', 'false');\n deletedSpan.setAttribute('data-editable', 'remove'); // Mark for removal when extracting content\n deletedSpan.textContent = op.value;\n // Insert the span before the cursor position\n cursor.insertBefore(deletedSpan);\n });\n }\n }\n catch (e) {\n console.warn('Failed to insert deletion marker:', e);\n }\n }\n }\n }\n mapOriginalToCurrentPosition(operations, originalPosition) {\n let currentPosition = 0;\n for (const op of operations) {\n if (originalPosition < op.oldStart) {\n break;\n }\n if (op.type === 'equal') {\n if (originalPosition < op.oldEnd) {\n const offsetInOp = originalPosition - op.oldStart;\n return currentPosition + offsetInOp;\n }\n currentPosition += op.newEnd - op.newStart;\n }\n else if (op.type === 'delete') {\n if (originalPosition < op.oldEnd) {\n // Position is within deletion, return the position where it was deleted\n return currentPosition;\n }\n // Don't advance currentPosition for deletions\n }\n else if (op.type === 'insert') {\n currentPosition += op.newEnd - op.newStart;\n }\n }\n return currentPosition;\n }\n clearDiffHighlights(editableHost) {\n const host = domSelector(editableHost, this.win.document);\n if (!host)\n return;\n for (const elem of domArray('[data-highlight=\"diff-deleted\"], [data-highlight=\"diff-inserted\"]', this.win.document, host)) {\n content.unwrap(elem);\n }\n }\n removeDiffHighlights(editableHost) {\n this.clearDiffHighlights(editableHost);\n }\n}\n//# sourceMappingURL=text-diff.js.map","import config from '../config.js';\n// Allows for safe console logging\n// If the last param is the string \"trace\" console.trace will be called\n// configuration: disable with config.log = false\nexport default function log(...args) {\n if (config.log === false)\n return;\n if (!global.console)\n return;\n const logArgs = args.length === 1 ? args[0] : args;\n if (args.length !== 1 && logArgs[logArgs.length - 1] === 'trace') {\n logArgs.pop();\n if (console.trace)\n console.trace();\n }\n console.log(logArgs);\n}\n//# sourceMappingURL=log.js.map","import createDefaultBehavior from './create-default-behavior.js';\nexport default function createDefaultEvents(editable) {\n const behavior = createDefaultBehavior(editable);\n return {\n /**\n * The focus event is triggered when an element gains focus.\n * The default behavior is to... TODO\n *\n * @event focus\n * @param {HTMLElement} element The element triggering the event.\n */\n focus(element) {\n behavior.focus(element);\n },\n /**\n * The blur event is triggered when an element looses focus.\n * The default behavior is to... TODO\n *\n * @event blur\n * @param {HTMLElement} element The element triggering the event.\n */\n blur(element) {\n behavior.blur(element);\n },\n /**\n * The selection event is triggered after the user has selected some\n * content.\n * The default behavior is to... TODO\n *\n * @event selection\n * @param {HTMLElement} element The element triggering the event.\n * @param {Selection} selection The actual Selection object.\n */\n selection(element, selection) {\n behavior.selection(element, selection);\n },\n /**\n * The cursor event is triggered after cursor position has changed.\n * The default behavior is to... TODO\n *\n * @event cursor\n * @param {HTMLElement} element The element triggering the event.\n * @param {Cursor} cursor The actual Cursor object.\n */\n cursor(element, cursor) {\n behavior.cursor(element, cursor);\n },\n /**\n * The newline event is triggered when a newline should be inserted. This\n * happens when SHIFT+ENTER key is pressed.\n * The default behavior is to add a <br />\n *\n * @event newline\n * @param {HTMLElement} element The element triggering the event.\n * @param {Cursor} cursor The actual cursor object.\n */\n newline(element, cursor) {\n behavior.newline(element, cursor);\n },\n /**\n * The split event is triggered when a block should be split into two\n * blocks. This happens when ENTER is pressed within a non-empty block.\n * The default behavior is to... TODO\n *\n * @event split\n * @param {HTMLElement} element The element triggering the event.\n * @param {String} before The HTML string before the split.\n * @param {String} after The HTML string after the split.\n * @param {Cursor} cursor The actual cursor object.\n */\n split(element, before, after, cursor) {\n behavior.split(element, before, after, cursor);\n },\n /**\n * The insert event is triggered when a new block should be inserted. This\n * happens when ENTER key is pressed at the beginning of a block (should\n * insert before) or at the end of a block (should insert after).\n * The default behavior is to... TODO\n *\n * @event insert\n * @param {HTMLElement} element The element triggering the event.\n * @param {String} direction The insert direction: \"before\" or \"after\".\n * @param {Cursor} cursor The actual cursor object.\n */\n insert(element, direction, cursor) {\n behavior.insert(element, direction, cursor);\n },\n /**\n * The merge event is triggered when two needs to be merged. This happens\n * when BACKSPACE is pressed at the beginning of a block (should merge with\n * the preceding block) or DEL is pressed at the end of a block (should\n * merge with the following block).\n * The default behavior is to... TODO\n *\n * @event merge\n * @param {HTMLElement} element The element triggering the event.\n * @param {String} direction The merge direction: \"before\" or \"after\".\n * @param {Cursor} cursor The actual cursor object.\n */\n merge(element, direction, cursor) {\n behavior.merge(element, direction, cursor);\n },\n /**\n * The empty event is triggered when a block is emptied.\n * The default behavior is to... TODO\n *\n * @event empty\n * @param {HTMLElement} element The element triggering the event.\n */\n empty(element) {\n behavior.empty(element);\n },\n /**\n * The switch event is triggered when the user switches to another block.\n * This happens when an ARROW key is pressed near the boundaries of a block.\n * The default behavior is to... TODO\n *\n * @event switch\n * @param {HTMLElement} element The element triggering the event.\n * @param {String} direction The switch direction: \"before\" or \"after\".\n * @param {Cursor} cursor The actual cursor object.*\n */\n switch(element, direction, cursor) {\n behavior.switch(element, direction, cursor);\n },\n /**\n * The move event is triggered when the user moves a selection in a block.\n * This happens when the user selects some (or all) content in a block and\n * an ARROW key is pressed (up: drag before, down: drag after).\n * The default behavior is to... TODO\n *\n * @event move\n * @param {HTMLElement} element The element triggering the event.\n * @param {Selection} selection The actual Selection object.\n * @param {String} direction The move direction: \"before\" or \"after\".\n */\n move(element, selection, direction) {\n behavior.move(element, selection, direction);\n },\n /**\n * The clipboard event is triggered when the user copies or cuts\n * a selection within a block.\n *\n * @event clipboard\n * @param {HTMLElement} element The element triggering the event.\n * @param {String} action The clipboard action: \"copy\" or \"cut\".\n * @param {Selection} selection A selection object around the copied content.\n */\n clipboard(element, action, selection) {\n behavior.clipboard(element, action, selection);\n },\n /**\n * The paste event is triggered when the user pastes text\n *\n * @event paste\n * @param {HTMLElement} The element triggering the event.\n * @param {Array of String} The pasted blocks\n * @param {Cursor} The cursor object.\n */\n paste(element, blocks, cursor) {\n behavior.paste(element, blocks, cursor);\n },\n /**\n * The toggleBold event is triggered when the bold keyboard shortcut is used\n *\n * @event toggleBold\n * @param {Selection} The selection object.\n */\n toggleBold(selection) {\n behavior.toggleBold(selection);\n },\n /**\n * The toggleEmphasis event is triggered when the italic keyboard shortcut is used\n *\n * @event toggleEmphasis\n * @param {Selection} The selection object.\n */\n toggleEmphasis(selection) {\n behavior.toggleEmphasis(selection);\n }\n };\n}\n//# sourceMappingURL=create-default-events.js.map","import * as parser from './parser.js';\nimport * as content from './content.js';\nimport log from './util/log.js';\nimport * as nodeType from './node-type.js';\n/**\n * The Behavior module defines the behavior triggered in response to the Editable.JS\n * events (see {{#crossLink \"Editable\"}}{{/crossLink}}).\n * The behavior can be overwritten by a user with Editable.init() or on\n * Editable.add() per element.\n *\n * @module core\n * @submodule behavior\n */\nexport default function createDefaultBehavior(editable) {\n const document = editable.win.document;\n /**\n * Factory for the default behavior.\n * Provides default behavior of the Editable.JS API.\n *\n * @static\n */\n return {\n /** @param {HTMLElement} element */\n focus(element) {\n if (!parser.isVoid(element))\n return;\n // Add an zero width space if the editable is empty to force it to have a height\n // E.g. Firefox does not render empty block elements\n // and most browsers do not render empty inline elements.\n element.appendChild(document.createTextNode('\\uFEFF'));\n },\n blur(element) {\n // Note: there is a special case when the tab is changed where\n // we can get a blur event even if the cursor is still in the editable.\n // This blur would cause us to loose the cursor position (cause of cleanInternals()).\n // To prevent this we check if the activeElement is still the editable.\n // (Note: document.getSelection() did not work reliably in this case.)\n if (document.activeElement === element)\n return;\n content.cleanInternals(element);\n },\n selection(element, selection) {\n log(selection ? 'Default selection behavior' : 'Default selection empty behavior');\n },\n cursor(element, cursor) {\n log('Default cursor behavior');\n },\n newline(element, cursor) {\n // When the cursor is at the text end, we'll need to add an empty text node\n // after the br tag to ensure that the cursor shows up on the next line\n if (cursor.isAtTextEnd()) {\n const br = document.createElement('br');\n cursor.insertBefore(br);\n // Only append a zero width space if there's none after the br tag\n // We don't need to remove them as they get cleaned up on blur\n const nextSibling = br.nextSibling;\n if (nextSibling?.nodeType !== nodeType.textNode ||\n nextSibling.textContent?.[0] !== '\\uFEFF') {\n cursor.insertAfter(document.createTextNode('\\uFEFF'));\n }\n }\n else {\n cursor.insertBefore(document.createElement('br'));\n }\n cursor.setVisibleSelection();\n },\n insert(element, direction, cursor) {\n const newElement = element.cloneNode(false);\n if (newElement.id)\n newElement.removeAttribute('id');\n if (direction === 'before') {\n element.parentNode?.insertBefore(newElement, element);\n }\n else {\n element.parentNode?.insertBefore(newElement, element.nextSibling);\n }\n editable.createCursorAtEnd(newElement)?.setVisibleSelection();\n },\n split(element, before, after, cursor) {\n const fragment = content.createFragmentFromString(before);\n const newNode = element.cloneNode(false);\n newNode.appendChild(fragment);\n const parent = element.parentNode;\n if (parent) {\n parent.insertBefore(newNode, element);\n }\n element.innerHTML = after;\n content.tidyHtml(newNode);\n content.tidyHtml(element);\n cursor.setVisibleSelection();\n },\n merge(element, direction, cursor) {\n const target = direction === 'before'\n ? element.previousElementSibling\n : element.nextElementSibling;\n if (!target)\n return;\n const targetContent = content.extractContent(target, false);\n const elementContent = content.extractContent(element, false);\n // Calculate text lengths before merging to position cursor correctly\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = targetContent;\n const targetTextLength = tempDiv.textContent?.length || 0;\n tempDiv.innerHTML = elementContent;\n const elementTextLength = tempDiv.textContent?.length || 0;\n const mergedContent = direction === 'before'\n ? targetContent + elementContent\n : elementContent + targetContent;\n element.innerHTML = mergedContent;\n target.remove();\n // Position cursor at the merge boundary\n const cursorOffset = direction === 'before'\n ? targetTextLength\n : elementTextLength;\n editable.createCursorAtCharacterOffset({ element, offset: cursorOffset });\n },\n empty(element) {\n log('Default empty behavior');\n },\n switch(element, direction, cursor) {\n switch (direction) {\n case 'before':\n const prevSibling = element.previousElementSibling;\n if (prevSibling) {\n const prevCursor = editable.createCursorAtEnd(prevSibling);\n if (prevCursor)\n prevCursor.setVisibleSelection();\n }\n break;\n case 'after':\n const nextSibling = element.nextElementSibling;\n if (nextSibling) {\n const nextCursor = editable.createCursorAtBeginning(nextSibling);\n if (nextCursor)\n nextCursor.setVisibleSelection();\n }\n break;\n }\n },\n move(element, selection, direction) {\n log('Default move behavior');\n },\n paste(element, blocks, cursor) {\n cursor.insertBefore(blocks[0]);\n if (blocks.length <= 1) {\n cursor.setVisibleSelection();\n return;\n }\n const parent = element.parentNode;\n if (!parent)\n return;\n let currentElement = element;\n blocks.slice(1).forEach((str) => {\n const newElement = element.cloneNode(false);\n if (newElement.id)\n newElement.removeAttribute('id');\n const fragment = content.createFragmentFromString(str);\n newElement.appendChild(fragment);\n parent.insertBefore(newElement, currentElement.nextSibling);\n currentElement = newElement;\n });\n // focus last element\n const lastCursor = editable.createCursorAtEnd(currentElement);\n if (lastCursor)\n lastCursor.setVisibleSelection();\n },\n clipboard(element, action, cursor) {\n log('Default clipboard behavior');\n },\n toggleBold(selection) {\n selection.toggleBold();\n },\n toggleEmphasis(selection) {\n selection.toggleEmphasis();\n }\n };\n}\n//# sourceMappingURL=create-default-behavior.js.map","import NodeIterator from '../node-iterator.js';\nexport function textNodesUnder(node) {\n const iterator = new NodeIterator(node, 'getNextTextNode');\n return [...iterator];\n}\n// NOTE: if there is only one text node, then just that node and\n// the abs offset are returned\nexport function getTextNodeAndRelativeOffset({ textNodes, absOffset }) {\n let cumulativeOffset = 0;\n let relativeOffset = 0;\n let targetNode;\n for (let i = 0; i < textNodes.length; i++) {\n const node = textNodes[i];\n const nodeLength = node.textContent?.length || 0;\n if (absOffset <= cumulativeOffset + nodeLength) {\n targetNode = node;\n relativeOffset = absOffset - cumulativeOffset;\n break;\n }\n cumulativeOffset += nodeLength;\n }\n return { node: targetNode, relativeOffset };\n}\nexport function getTotalCharCount(element) {\n const textNodes = textNodesUnder(element);\n const reducer = (acc, node) => acc + (node.textContent?.length || 0);\n return textNodes.reduce(reducer, 0);\n}\n//# sourceMappingURL=element.js.map","import { getTotalCharCount, textNodesUnder, getTextNodeAndRelativeOffset } from './element.js';\n/**\n * This is a binary search algorithm implementation aimed at finding\n * a character offset position in a consecutive strings of characters\n * over several lines.\n *\n * Refer to this page in order to learn more about binary search:\n * https://en.wikipedia.org/wiki/Binary_search_algorithm\n *\n * @returns {object}\n * - object with boolean `wasFound` indicating if the binary search found an offset and `offset` to indicate the actual character offset\n */\nexport function binaryCursorSearch({ host, requiredOnFirstLine, requiredOnLastLine, positionX // coordinates relative to viewport (e.g. from getBoundingClientRect())\n }) {\n const hostRange = host.ownerDocument.createRange();\n hostRange.selectNodeContents(host);\n // JSDOM doesn't support getBoundingClientRect on Range, use element instead\n let hostCoords;\n try {\n hostCoords = hostRange.getBoundingClientRect();\n }\n catch (e) {\n // Fallback for JSDOM\n hostCoords = host.getBoundingClientRect() || {\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n width: 0,\n height: 0,\n x: 0,\n y: 0,\n toJSON: () => ({})\n };\n }\n const totalCharCount = getTotalCharCount(host);\n const textNodes = textNodesUnder(host);\n // early terminate on empty editables\n if (totalCharCount === 0)\n return { wasFound: false };\n const data = {\n currentOffset: Math.floor(totalCharCount / 2),\n leftLimit: 0,\n rightLimit: totalCharCount\n };\n let offset = data.currentOffset;\n let distance = 0;\n let safety = 20;\n while (data.leftLimit < data.rightLimit && safety > 0) {\n safety = safety - 1;\n offset = data.currentOffset;\n const range = createRangeAtCharacterOffset({ textNodes, offset: data.currentOffset });\n // JSDOM doesn't support getBoundingClientRect on Range\n let coords;\n try {\n coords = range.getBoundingClientRect();\n }\n catch (e) {\n // Fallback for JSDOM - use a mock DOMRect\n coords = {\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n width: 0,\n height: 0,\n x: 0,\n y: 0,\n toJSON: () => ({})\n };\n }\n distance = Math.abs(coords.left - positionX);\n // up / down axis\n if (requiredOnFirstLine && hostCoords.top !== coords.top) {\n moveLeft(data);\n continue;\n }\n else if (requiredOnLastLine && hostCoords.bottom !== coords.bottom) {\n moveRight(data);\n continue;\n }\n // left / right axis\n if (positionX < coords.left) {\n moveLeft(data);\n }\n else {\n moveRight(data);\n }\n }\n const range = createRangeAtCharacterOffset({ textNodes, offset: data.currentOffset });\n // JSDOM doesn't support getBoundingClientRect on Range\n let coords;\n try {\n coords = range.getBoundingClientRect();\n }\n catch (e) {\n // Fallback for JSDOM\n coords = {\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n width: 0,\n height: 0,\n x: 0,\n y: 0,\n toJSON: () => ({})\n };\n }\n const finalDistance = Math.abs(coords.left - positionX);\n // Decide if last or second last offset is closest\n if (finalDistance < distance) {\n distance = finalDistance;\n offset = data.currentOffset;\n }\n return { distance, offset, wasFound: true };\n}\n// move the binary search index in between the current position and the left limit\nfunction moveLeft(data) {\n data.rightLimit = data.currentOffset;\n data.currentOffset = Math.floor((data.currentOffset + data.leftLimit) / 2);\n}\n// move the binary search index in between the current position and the right limit\nfunction moveRight(data) {\n data.leftLimit = data.currentOffset;\n data.currentOffset = Math.ceil((data.currentOffset + data.rightLimit) / 2);\n}\nfunction createRangeAtCharacterOffset({ textNodes, offset }) {\n const { node, relativeOffset } = getTextNodeAndRelativeOffset({ textNodes, absOffset: offset });\n if (!node)\n throw new Error('Could not find text node for offset');\n const newRange = node.ownerDocument.createRange();\n newRange.setStart(node, relativeOffset);\n newRange.collapse(true);\n return newRange;\n}\n//# sourceMappingURL=binary_search.js.map","import config from './config.js';\nimport error from './util/error.js';\nimport * as parser from './parser.js';\nimport * as block from './block.js';\nimport * as content from './content.js';\nimport * as clipboard from './clipboard.js';\nimport Dispatcher from './dispatcher.js';\nimport Cursor from './cursor.js';\nimport highlightSupport from './highlight-support.js';\nimport MonitoredHighlighting from './monitored-highlighting.js';\nimport TextDiff from './plugins/text-diff/text-diff.js';\nimport createDefaultEvents from './create-default-events.js';\nimport { textNodesUnder, getTextNodeAndRelativeOffset } from './util/element.js';\nimport { binaryCursorSearch } from './util/binary_search.js';\nimport { domArray, createRange, nodeContainsRange } from './util/dom.js';\nexport class Editable {\n constructor(instanceConfig) {\n const defaultInstanceConfig = {\n window: window,\n defaultBehavior: true,\n mouseMoveSelectionChanges: false,\n browserSpellcheck: true\n };\n this.config = Object.assign(defaultInstanceConfig, instanceConfig);\n this.win = this.config.window;\n this.editableSelector = `.${config.editableClass}`;\n this.dispatcher = new Dispatcher(this);\n if (this.config.defaultBehavior === true) {\n this.dispatcher.on(createDefaultEvents(this));\n }\n }\n static getGlobalConfig() {\n return config;\n }\n static globalConfig(globalConfig) {\n Object.assign(config, globalConfig);\n clipboard.updateConfig(config);\n }\n add(target, options) {\n this.enable(target, options);\n return this;\n }\n remove(target) {\n const targets = domArray(target, this.win.document);\n this.disable(targets);\n for (const element of targets) {\n element.classList.remove(config.editableDisabledClass);\n }\n return this;\n }\n disable(target) {\n const targets = domArray(target || `.${config.editableClass}`, this.win.document);\n for (const element of targets) {\n block.disable(element);\n }\n return this;\n }\n enable(target, options) {\n const opts = typeof options === 'boolean' ? { normalize: options } : (options ?? {});\n const { normalize = false, plainText = false } = opts;\n const shouldSpellcheck = this.config.browserSpellcheck;\n const targets = domArray(target || `.${config.editableDisabledClass}`, this.win.document);\n for (const element of targets) {\n block.init(element, { normalize, plainText, shouldSpellcheck });\n this.dispatcher.notify('init', element);\n }\n return this;\n }\n suspend(target) {\n const targets = domArray(target || `.${config.editableClass}`, this.win.document);\n for (const element of targets) {\n element.removeAttribute('contenteditable');\n }\n this.dispatcher.suspend();\n return this;\n }\n continue(target) {\n const targets = domArray(target || `.${config.editableClass}`, this.win.document);\n for (const element of targets) {\n element.setAttribute('contenteditable', 'true');\n }\n this.dispatcher.continue();\n return this;\n }\n createCursor(element, position = 'beginning') {\n const host = Cursor.findHost(element, this.editableSelector);\n if (!host)\n return undefined;\n const range = createRange(this.win);\n if (position === 'beginning' || position === 'end') {\n range.selectNodeContents(element);\n range.collapse(position === 'beginning');\n }\n else if (element !== host) {\n if (position === 'before') {\n range.setStartBefore(element);\n range.setEndBefore(element);\n }\n else if (position === 'after') {\n range.setStartAfter(element);\n range.setEndAfter(element);\n }\n }\n else {\n error('EditableJS: cannot create cursor outside of an editable block.');\n }\n return new Cursor(host, range);\n }\n createCursorAtCharacterOffset({ element, offset }) {\n const textNodes = textNodesUnder(element);\n const { node, relativeOffset } = getTextNodeAndRelativeOffset({ textNodes, absOffset: offset });\n if (!node)\n throw new Error('Could not find text node for offset');\n const newRange = createRange(this.win);\n newRange.setStart(node, relativeOffset);\n newRange.collapse(true);\n const host = Cursor.findHost(element, this.editableSelector);\n if (!host)\n throw new Error('No editable host found');\n const nextCursor = new Cursor(host, newRange);\n nextCursor.setVisibleSelection();\n return nextCursor;\n }\n createCursorAtBeginning(element) {\n return this.createCursor(element, 'beginning');\n }\n createCursorAtEnd(element) {\n return this.createCursor(element, 'end');\n }\n createCursorBefore(element) {\n return this.createCursor(element, 'before');\n }\n createCursorAfter(element) {\n return this.createCursor(element, 'after');\n }\n getContent(element) {\n return content.extractContent(element);\n }\n appendTo(inputElement, contentToAppend) {\n const element = content.adoptElement(inputElement, this.win.document);\n const cursor = this.createCursor(element, 'end');\n if (!cursor)\n throw new Error('Could not create cursor');\n cursor.insertAfter(typeof contentToAppend === 'string'\n ? content.createFragmentFromString(contentToAppend)\n : contentToAppend);\n return cursor;\n }\n prependTo(inputElement, contentToPrepend) {\n const element = content.adoptElement(inputElement, this.win.document);\n const cursor = this.createCursor(element, 'beginning');\n if (!cursor)\n throw new Error('Could not create cursor');\n cursor.insertBefore(typeof contentToPrepend === 'string'\n ? content.createFragmentFromString(contentToPrepend)\n : contentToPrepend);\n return cursor;\n }\n getSelection(editableHost) {\n const selection = this.dispatcher.selectionWatcher.getFreshSelection();\n if (!editableHost || !selection)\n return selection;\n const range = selection.range;\n if (editableHost?.isConnected && nodeContainsRange(editableHost, range)) {\n return selection;\n }\n return undefined;\n }\n setupHighlighting(hightlightingConfig) {\n this.highlighting = new MonitoredHighlighting(this, hightlightingConfig, undefined);\n return this;\n }\n setupSpellcheck(conf) {\n let marker;\n if (conf.markerNode) {\n marker = conf.markerNode.outerHTML;\n }\n this.setupHighlighting({\n throttle: conf.throttle,\n spellcheck: {\n marker: marker,\n spellcheckService: conf.spellcheckService\n }\n });\n this.spellcheck = {\n checkSpelling: (elem) => {\n this.highlighting?.highlight(elem);\n }\n };\n return this;\n }\n setupTextDiff(config) {\n this.textDiff = new TextDiff(this, config || {});\n return this;\n }\n highlight({ editableHost, text, highlightId, textRange, raiseEvents, type = 'comment' }) {\n if (!textRange) {\n const result = highlightSupport.highlightText(editableHost, text, highlightId, type, raiseEvents ? this.dispatcher : undefined, this.win);\n return result || -1;\n }\n if (typeof textRange.start !== 'number' || typeof textRange.end !== 'number') {\n error('Error in Editable.highlight: You passed a textRange object with invalid keys. Expected shape: { start: Number, end: Number }');\n return -1;\n }\n if (textRange.start === textRange.end) {\n error('Error in Editable.highlight: You passed a textRange object with equal start and end offsets, which is considered a cursor and therefore unfit to create a highlight.');\n return -1;\n }\n return highlightSupport.highlightRange(editableHost, text, highlightId, textRange.start, textRange.end, raiseEvents ? this.dispatcher : undefined, this.win, type);\n }\n getHighlightPositions({ editableHost, type }) {\n const result = highlightSupport.extractHighlightedRanges(editableHost, type);\n if (!result)\n return {};\n // Convert the result to TextRange format (without nativeRange)\n const textRanges = {};\n for (const highlightId in result) {\n const { start, end, text } = result[highlightId];\n textRanges[highlightId] = { start, end, text };\n }\n return textRanges;\n }\n removeHighlight({ editableHost, highlightId, raiseEvents }) {\n highlightSupport.removeHighlight(editableHost, highlightId, raiseEvents ? this.dispatcher : undefined);\n }\n decorateHighlight({ editableHost, highlightId, addCssClass, removeCssClass }) {\n highlightSupport.updateHighlight(editableHost, highlightId, addCssClass, removeCssClass);\n }\n on(event, handler) {\n this.dispatcher.on(event, handler);\n return this;\n }\n off(...args) {\n this.dispatcher.off.apply(this.dispatcher, args);\n return this;\n }\n unload() {\n this.dispatcher.unload();\n return this;\n }\n findClosestCursorOffset({ element, origCoordinates, requiredOnFirstLine = false, requiredOnLastLine = false }) {\n const positionX = this.dispatcher.switchContext && this.dispatcher.switchContext.positionX !== undefined\n ? this.dispatcher.switchContext.positionX\n : origCoordinates.left;\n return binaryCursorSearch({\n host: element,\n requiredOnFirstLine,\n requiredOnLastLine,\n positionX\n });\n }\n}\n// Expose modules and editable\nEditable.parser = parser;\nEditable.content = content;\n// Set up callback functions for several events.\nconst eventNames = ['focus', 'blur', 'flow', 'selection', 'cursor', 'newline',\n 'insert', 'split', 'merge', 'empty', 'change', 'switch',\n 'move', 'clipboard', 'paste', 'spellcheckUpdated', 'selectToBoundary'];\neventNames.forEach((name) => {\n // Generate a callback function to subscribe to an event.\n Editable.prototype[name] = function (handler) {\n return this.on(name, handler);\n };\n});\n//# sourceMappingURL=core.js.map"],"names":["config","log","logErrors","editableClass","editableDisabledClass","pastingAttribute","trimLeadingAndTrailingWhitespaces","boldMarkup","type","name","attribs","trim","italicMarkup","underlineMarkup","linkMarkup","pastedHtmlRules","allowedElements","a","href","rel","target","strong","em","br","allowedPlainTextElements","requiredAttributes","transformElements","b","i","splitIntoBlocks","blockLevelElements","blacklistedElements","keepInternalRelativeLinks","replaceQuotes","error","args","errorArgs","length","global","console","toString","Object","prototype","htmlCharacters","trimRight","text","replace","isString","obj","call","NodeIterator","constructor","root","method","this","current","previous","nextNode","iteratorFunc","Symbol","iterator","getNextTextNode","next","getNext","nodeType","data","getPreviousTextNode","prev","getPrevious","value","done","child","n","firstChild","getAttribute","nextSibling","parentNode","lastChild","prevSibling","previousSibling","replaceCurrent","replacement","domArray","documentOrHost","host","doc","querySelectorAll","ownerDocument","container","Array","from","tagName","isArray","domSelector","document","querySelector","createElement","html","win","window","el","innerHTML","firstElementChild","closest","elem","selector","currentNode","createRange","getSelection","docSelection","getNodes","range","nodeTypes","filterFunc","nodes","nodeIterator","createNodeIterator","commonAncestorContainer","NodeFilter","SHOW_ALL","acceptNode","node","intersectsNode","includes","FILTER_ACCEPT","FILTER_SKIP","push","normalizeBoundaries","startContainer","compareDocumentPosition","endContainer","Node","DOCUMENT_POSITION_FOLLOWING","setStartBefore","DOCUMENT_POSITION_PRECEDING","setEndAfter","isCharacterDataNode","TEXT_NODE","COMMENT_NODE","splitDataNode","offset","splitText","toCharacterRange","startRange","cloneRange","setStart","setEnd","startOffset","rangeText","start","end","rangesAreEqual","range1","range2","endOffset","findStartExcludingWhitespace","whitespacesOnTheLeft","childNodes","offsetAfterWhitespace","previousTextNode","Error","findEndExcludingWhitespace","whitespacesOnTheRight","isFirstNode","offsetBeforeWhitespace","getHost","jquery","classList","contains","result","getNodeIndex","index","isVoid","isVoidTextNode","nodeValue","isWhitespaceOnly","lastOffsetWithContent","isLinebreak","string.trimRight","lastOffset","reverse","every","isBeginningOfHost","isStartOffset","offsetInParent","isEndOfHost","isEndOffset","isTextEndOfHost","isTextEndOffset","isSameNode","source","len","attr","nodeName","targetElem","sourceElem","attributes","isDocumentFragmentWithoutChildren","fragment","element","currentStyle","getComputedStyle","display","warn","boundaryMarkerId","isSecondChildOfCommonAncestor","rangeContainer","parent","possibleChild","parentElement","insertRangeBoundaryMarker","atStart","ownerDoc","defaultView","markerEl","id","setAttribute","style","lineHeight","appendChild","createTextNode","directlyBeforeFormatTag","directlyAfterFormatTag","startParentElem","insertBefore","endParentElem","boundaryRange","collapse","insertNode","setRangeBoundary","markerId","getMarker","remove","save","rangeInfo","startEl","endEl","collapsed","startMarkerId","endMarkerId","setEndBefore","setStartAfter","restore","restored","previousNode","restoreRange","func","savedRange","rangeSaveRestore.save","rangeSaveRestore.restore","zeroWidthSpace","zeroWidthNonBreakingSpace","whitespaceExceptSpace","everythingWhitespace","leadingWhitespace","trailingWhitespace","tidyHtml","normalizeTags","createDocumentFragment","removeWhitespaces","nodesToProcess","processedIndices","Set","has","textContent","mergedNode","cloneNode","j","sibling","parser.isSameNode","siblingChild","add","removeChild","normalizeWhitespace","cleanInternals","extractContent","keepUiElements","innerHtml","getInnerHtmlOfFragment","clone","unwrapInternalNodes","documentFragment","div","children","createFragmentFromString","htmlString","wrapper","adoptElement","adoptNode","cloneRangeContents","cloneContents","firstCall","test","startsWith","unwrap","getTags","innerTags","getInnerTags","ancestorTags","getAncestorTags","concat","tags","getTagsByName","toUpperCase","getTagsByNameAndAttributes","areSameAttributes","attrs1","attrs2","attr1","attr2","getNamedItem","getContainedTags","filter","nodeRange","selectNodeContents","comparisonStart","compareBoundaryPoints","Range","START_TO_START","comparisonEnd","END_TO_END","containsNodeText","getTagNames","elements","map","isExactSelection","visible","elemRange","END_TO_START","elemText","string.trim","expandTo","toggleTag","elems","removeFormattingElem","forceWrap","isWrappable","boundariesInvalid","ELEMENT_NODE","isNodeFullyContained","canSurroundContents","restoredRange","nukeElem","nuke","wrap","surroundContents","removeFormatting","forEach","matches","insertCharacter","character","insertEl","surround","startCharacter","endCharacter","deleteCharacter","containsString","selection","rangeCount","newStartContainer","splitBoundaries","indexOf","textNode","RegExp","str","some","nextBlockId","init","normalize","plainText","shouldSpellcheck","hasAttribute","setBlockId","String","Boolean","content.tidyHtml","disable","removeAttribute","setState","isPlainTextBlock","doubleQuotePairs","singleQuotePairs","apostrophe","quotesRegex","beforeOpeningQuote","afterClosingQuote","replacements","replaceAllQuotes","replaceQuotesRules","quotes","singleQuotes","matchAll","match","char","before","after","getAllQuotes","replaceMatchedQuotes","replaceExistingQuotes","position","closingTag","findClosingQuote","nestedMatches","slice","replaceApostrophe","openingQuote","possibleClosingSingleQuotes","getPossibleClosingQuotes","possibleClosingDoubleQuotes","allPossibleDoubleClosers","allPossibleSingleClosers","hasStraightQuoteFallback","isStraightQuote","bestStraightQuoteMatch","candidateChar","candidateAfter","pairs","quotePair","quote","whitespaceOnly","blockPlaceholder","updateConfig","conf","rules","paste","block","cursor","clipboardContent","isSelection","deleteExactSurroundingTags","deleteContainedTags","deleteContent","pasteHolder","blocks","filterHtmlElements","split","entry","quotes.replaceAllQuotes","group","parseContent","options","reduce","content","toLowerCase","childElement","hrefAttr","stripInternalHost","location","origin","transformNodeName","requiredAttrs","hasRequiredAttributes","shouldKeepNode","filterAttributes","conditionalNodeWrap","c","documentElement","contentEditable","isBlink","navigator","userAgent","isWebkit","webKit","selectionchange","osc","onselectionchange","e","hasNativeSelectionchangeSupport","contenteditableSpanBug","eventable","notifyContext","events","listeners","addListener","listener","event","unshift","removeListener","eventListeners","splice","on","eventOrEvents","arguments","eventType","off","keys","key","notify","context","allArgs","actualContext","actualEvent","actualArgs","switchContext","shift","apply","getEventableModule","getScrollPosition","x","pageXOffset","body","scrollLeft","y","pageYOffset","scrollTop","Cursor","findHost","editableHost","setHost","isCursor","content.getTags","content.getTagNames","content.getTagsByName","content.getInnerTags","content.getContainedTags","content.getAncestorTags","isAtEnd","parser.isEndOfHost","isAtTextEnd","parser.isTextEndOfHost","isAtLastLine","hostRange","hostCoords","getRangeBoundingClientRect","cursorCoords","isCloseTo","bottom","isAtFirstLine","top","isAtBeginning","parser.isBeginningOfHost","string.isString","content.createFragmentFromString","parser.isDocumentFragmentWithoutChildren","preceedingElement","lastIndex","insertAfter","setSelection","setVisibleSelection","activeElement","viewport.getScrollPosition","scrollTo","removeAllRanges","addRange","content.cloneRangeContents","textBefore","beforeHtml","content.getInnerHtmlOfFragment","textAfter","afterHtml","getBoundingClientRect","getCoordinates","positioning","coords","left","right","height","width","moveBefore","updateHost","moveAfter","moveAtBeginning","moveAtEnd","moveAtTextEnd","parser.lastChild","parser.getHost","retainVisibleSelection","callback","savedRangeInfo","equals","isEqualNode","attributeName","attributeValue","content.adoptElement","triggerChange","Event","bubbles","cancelable","dispatchEvent","Math","abs","highlightText","extractText","convertBRs","getText","part","highlightMatches","countBRs","currentMatchIndex","totalOffset","currentMatch","portions","wordId","startIndex","nodeText","nodeEndOffset","endIndex","isFirstPortion","isLastPortion","portion","substring","lastNode","wrapMatch","marker","title","stencilElement","wrapPortion","pop","findMatches","searchTexts","matchMode","HTMLElement","isElement","regex","createWordRegex","createHighlightRegex","matchedText","words","word","escapeRegEx","join","letterChars","escapedWords","s","highlightSupport","highlightId","dispatcher","hasHighlight","blockText","winWindow","markerNode","createMarkerNode","searchTerm","searchText","highlightRange","removeHighlight","actualStartIndex","actualEndIndex","updateHighlight","addCssClass","removeCssClass","content.unwrap","extractHighlightedRanges","findMarkersQuery","markers","groups","res","extractMarkerNodePosition","selectNode","textRange","nativeRange","cleanupStaleMarkerNodes","highlightType","markerMarkup","Selection","super","rangeToHtml","isAllSelected","getTextRange","content.isWrappable","getRects","getClientRects","link","attrs","trimRange","textToTrim","search","lastNonWhitespace","unlink","toggleLink","links","firstLink","highlightComment","highlight","currentTextContent","toggle","block.isPlainTextBlock","newRange","content.toggleTag","toggleCustom","customElem","makeCustom","makeBold","bold","toggleBold","giveEmphasis","toggleEmphasis","makeUnderline","u","toggleUnderline","content.surround","removeSurround","content.deleteCharacter","removeChars","chars","toggleSurround","content.removeFormatting","ancestorTag","containedTag","deleteContents","content.expandTo","collapseAtBeginning","collapseAtEnd","content.forceWrap","onlyVisible","content.isExactSelection","content.containsString","RangeContainer","isAnythingSelected","getCursor","forceCursor","isDifferentFrom","otherRangeContainer","self","other","SelectionWatcher","currentSelection","currentRange","syncSelection","err","getRangeContainer","successfulSync","getRangeAt","hostNode","getFreshRange","getFreshSelection","selectionChanged","newRangeContainer","lastSelection","Keyboard","selectionWatcher","dispatchKeyEvent","notifyCharacterEvent","keyCode","up","down","tab","shiftKey","esc","backspace","preventContenteditableBug","delete","enter","ctrl","alt","ctrlKey","metaKey","nodeToRemove","getNodeToRemove","selectionRange","startNodeElement","startNodeRange","testRange","containerRange","contentNodeTypes","firstContentNode","rangeStartingBeforeCurrentElement","isValidQuotePairConfig","isDoubleQuote","isSingleQuote","isApostrophe","isSeparatorOrWhitespace","replaceQuote","quoteType","newText","newTextNode","replaceWith","applySmartQuotes","cursorOffset","isCharSingleQuote","textArr","indexCharBefore","shouldBeClosingQuote","indexCharAfter","hasCharAfter","singleOpeningQuote","hasSingleOpeningQuote","closingQuote","shouldBeOpeningQuote","Dispatcher","editable","editableSelector","keyboard","activeListeners","setup","getEditableBlockByEvent","evt","setupDocumentListener","capture","bind","addEventListener","setupKeyboardEvents","setupEventListeners","unload","l","removeEventListener","suspend","suspended","setupElementListeners","setupKeydownListener","setupSelectionChangeListeners","setupSelectionChangeFallbackListeners","currentInput","clipEvent","preventDefault","clipboardData","getData","clipboard.paste","innerText","searchValue","replaceValue","lastOccurrenceIndex","lastIndexOf","replaceLast","smartQuotes","isContentEditable","shouldApplySmartQuotes","inputEvent","quotesConfig","setTimeout","dispatchSwitchEvent","direction","altKey","positionX","stopPropagation","keyEvent","editableBlock","beforeFragment","afterFragment","selectionDirty","suppressSelectionChanges","didSyncSelection","mouseMoveSelectionChanges","once","notifySelectionBoundary","deepMerge","sources","hasOwnProperty","sourceValue","targetValue","SpellcheckService","spellcheckService","check","condensedText","content.normalizeWhitespace","misspelledWords","characters","A0","specialWhitespaceCharsRegex","WhitespaceHighlighting","prepareMatch","unicode","charCodeAt","description","MatchCollection","addMatches","matches1","matches2","length1","length2","lastEndIndex","output","state","a1","i1","a2","i2","pickNext","mergeMatches","item1","item2","MonitoredHighlighting","configuration","spellcheckConfig","focusedEditableHost","currentlyCheckedEditableHost","timeout","checkOnInit","checkOnFocus","checkOnChange","throttle","removeOnCorrection","spellcheck","whitespace","spellcheckMarker","whitespaceMarker","whitespaceMarkerNode","spellcheckMarkerNode","setupListeners","onFocus","onBlur","onChange","onInit","editableHasChanged","removeHighlightsAtCursor","clearTimeout","timeoutId","isConnected","matchCollection","searchAllWords","whitespaceMatches","m","safeHighlightMatches","removeHighlights","elementAtCursor","computeDiff","oldText","oldStart","oldEnd","newStart","newEnd","operations","lcs","str1","str2","dp","fill","max","computeLCS","oldIndex","newIndex","lcsIndex","startOld","startNew","commonLength","deleteStart","insertStart","TextDiff","isApplyingDiff","originalTexts","Map","assign","enabled","markerDeleted","markerInserted","deletedMarkerNode","insertedMarkerNode","captureOriginalText","computeAndApplyDiff","set","clearDiffHighlights","setOriginalText","getOriginalText","get","clearOriginalText","originalText","currentText","applyDiff","highlightDiffOperations","highlightIdCounter","op","min","deletions","insertPosition","mapOriginalToCurrentPosition","createCursorAtCharacterOffset","deletedSpan","originalPosition","currentPosition","removeDiffHighlights","logArgs","trace","createDefaultEvents","behavior","focus","parser.isVoid","blur","content.cleanInternals","newline","insert","newElement","createCursorAtEnd","newNode","merge","previousElementSibling","nextElementSibling","targetContent","content.extractContent","elementContent","tempDiv","targetTextLength","elementTextLength","mergedContent","empty","prevCursor","nextCursor","createCursorAtBeginning","move","currentElement","lastCursor","clipboard","action","createDefaultBehavior","switch","textNodesUnder","getTextNodeAndRelativeOffset","textNodes","absOffset","targetNode","cumulativeOffset","relativeOffset","nodeLength","binaryCursorSearch","requiredOnFirstLine","requiredOnLastLine","toJSON","totalCharCount","acc","wasFound","currentOffset","floor","leftLimit","rightLimit","distance","safety","createRangeAtCharacterOffset","moveLeft","moveRight","finalDistance","ceil","Editable","instanceConfig","defaultInstanceConfig","defaultBehavior","browserSpellcheck","getGlobalConfig","globalConfig","clipboard.updateConfig","enable","targets","block.disable","opts","block.init","continue","createCursor","createCursorBefore","createCursorAfter","getContent","appendTo","inputElement","contentToAppend","prependTo","contentToPrepend","nodeContainsRange","setupHighlighting","hightlightingConfig","highlighting","setupSpellcheck","outerHTML","checkSpelling","setupTextDiff","textDiff","raiseEvents","getHighlightPositions","textRanges","decorateHighlight","handler","findClosestCursorOffset","origCoordinates","parser"],"mappings":"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"}
|