n8n/patches/quill+2.0.0-dev.4.patch
Alex Grozav 27e2ce0470
feat: migrate editor-ui to Vite.js and various DX improvements (N8N-2277) (#4061)
* feat: Added vite.js dependencies.

* chore: Removed tests folder to follow same structure as design-system

* chore: Removed unused testing config.

* chore: Created vite.js index.html

* refactor: Updated scss structure and imports.

* refactor: Updated workflow building.

* fix: Cleared up all workflow dependency cycles. Added proper package.json imports config.

* feat: Got a working build using Vite. Need to fix issues next.

* fix: Progress! Getting process.env error.

* fix: Changed process.env to import.meta.env.

* fix: Fixed circular imports that used require(). Fixed monaco editor.

* chore: Removed commented code.

* chore: Cleaned up package.json

* feat: Made necessary changes to replace base path in css files.

* feat: Serve CSS files for `editor-ui` Vite migration (#4069)

 Serve CSS files for Vite migration

* chore: Fixed package-lock.json.

* fix: Fixed build after centralized tsconfig update.

* fix: Removed lodash-es replacement.

* fix: Commented out vitest test command.

* style: Fixed linting issues.

* fix: Added lodash-es hotfix back.

* chore: Updated package-lock.json

* refactor: Renamed all n8n scss variables to no longer be defined as private.

* feat(editor): add application-wide el-button replacement.

* fix(editor): Fix import in page alert after merge.

* chore(editor): update package-lock.json.

* fix: Case sensitive lodash-es replacement for vue-agile.

* fix: add alias for lodash-es camelcase import.

* fix: add patch-package support for fixing quill

* feat: add patch-package on postinstall

* fix: update quill patch path.

* refactor: rename quill patch

* fix: update quill version.

* fix: update quill patch

* fix: fix linting rules after installing eslint in design-system

* fix: update date picker button to have primary color

* test: update callout component snapshots

* fix(editor): fix linting issues in editor after enabling eslint

* fix(cli): add /assets/* to auth ignore endpoints in server

* chore: update package-lock.json

* chore: update package-lock.json

* fix(editor): fix linting issues

* feat: add vite-legacy support

* fix: update workflow package interface imports to type imports.

* chore: update package-lock.json

* fix(editor) fix importing translations other than english

* fix(editor): remove test command until vitest is added

* fix: increase memory allocation for vite build

* fix: add patch-package patches to n8n-custom docker build

* fix: add performance and load time improvements

* fix: add proper typing to setNodeType

* chore: update package-lock.json

* style: use generic type for reduce in setNodeType

Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
2022-09-23 17:14:28 +03:00

56 lines
59 KiB
Diff

diff --git a/node_modules/quill/core/selection.js b/node_modules/quill/core/selection.js
index 9dfc94f..7719a41 100644
--- a/node_modules/quill/core/selection.js
+++ b/node_modules/quill/core/selection.js
@@ -151,7 +151,7 @@ class Selection {
}
let side = 'left';
let rect;
- if (node instanceof Text) {
+ if (node instanceof Text || node.nodeName === '#text') {
if (offset < node.data.length) {
range.setStart(node, offset);
range.setEnd(node, offset + 1);
@@ -238,13 +238,13 @@ class Selection {
};
[range.start, range.end].forEach(position => {
let { node, offset } = position;
- while (!(node instanceof Text) && node.childNodes.length > 0) {
+ while (!(node instanceof Text || node.nodeName === '#text') && node.childNodes.length > 0) {
if (node.childNodes.length > offset) {
node = node.childNodes[offset];
offset = 0;
} else if (node.childNodes.length === offset) {
node = node.lastChild;
- if (node instanceof Text) {
+ if (node instanceof Text || node.nodeName === '#text') {
offset = node.data.length;
} else if (node.childNodes.length > 0) {
// Container case
diff --git a/node_modules/quill/dist/quill.core.js b/node_modules/quill/dist/quill.core.js
index 7c7891e..1a7fd8a 100644
--- a/node_modules/quill/dist/quill.core.js
+++ b/node_modules/quill/dist/quill.core.js
@@ -290,7 +290,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Range\", function() { return Range; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Selection; });\n/* harmony import */ var parchment__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! parchment */ \"./node_modules/parchment/src/parchment.ts\");\n/* harmony import */ var clone__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! clone */ \"./node_modules/clone/clone.js\");\n/* harmony import */ var clone__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(clone__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var deep_equal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! deep-equal */ \"./node_modules/deep-equal/index.js\");\n/* harmony import */ var deep_equal__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(deep_equal__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _emitter__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./emitter */ \"./core/emitter.js\");\n/* harmony import */ var _logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./logger */ \"./core/logger.js\");\n\n\n\n\n\nconst debug = Object(_logger__WEBPACK_IMPORTED_MODULE_4__[\"default\"])('quill:selection');\n\nclass Range {\n constructor(index, length = 0) {\n this.index = index;\n this.length = length;\n }\n\n}\n\nclass Selection {\n constructor(scroll, emitter) {\n this.emitter = emitter;\n this.scroll = scroll;\n this.composing = false;\n this.mouseDown = false;\n this.root = this.scroll.domNode;\n this.cursor = this.scroll.create('cursor', this); // savedRange is last non-null range\n\n this.savedRange = new Range(0, 0);\n this.lastRange = this.savedRange;\n this.lastNative = null;\n this.handleComposition();\n this.handleDragging();\n this.emitter.listenDOM('selectionchange', document, () => {\n if (!this.mouseDown && !this.composing) {\n setTimeout(this.update.bind(this, _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER), 1);\n }\n });\n this.emitter.on(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_BEFORE_UPDATE, () => {\n if (!this.hasFocus()) return;\n const native = this.getNativeRange();\n if (native == null) return;\n if (native.start.node === this.cursor.textNode) return; // cursor.restore() will handle\n\n this.emitter.once(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_UPDATE, () => {\n try {\n if (this.root.contains(native.start.node) && this.root.contains(native.end.node)) {\n this.setNativeRange(native.start.node, native.start.offset, native.end.node, native.end.offset);\n }\n\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n } catch (ignored) {// ignore\n }\n });\n });\n this.emitter.on(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_OPTIMIZE, (mutations, context) => {\n if (context.range) {\n const {\n startNode,\n startOffset,\n endNode,\n endOffset\n } = context.range;\n this.setNativeRange(startNode, startOffset, endNode, endOffset);\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n }\n });\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n }\n\n handleComposition() {\n this.root.addEventListener('compositionstart', () => {\n this.composing = true;\n this.scroll.batchStart();\n });\n this.root.addEventListener('compositionend', () => {\n this.scroll.batchEnd();\n this.composing = false;\n\n if (this.cursor.parent) {\n const range = this.cursor.restore();\n if (!range) return;\n setTimeout(() => {\n this.setNativeRange(range.startNode, range.startOffset, range.endNode, range.endOffset);\n }, 1);\n }\n });\n }\n\n handleDragging() {\n this.emitter.listenDOM('mousedown', document.body, () => {\n this.mouseDown = true;\n });\n this.emitter.listenDOM('mouseup', document.body, () => {\n this.mouseDown = false;\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER);\n });\n }\n\n focus() {\n if (this.hasFocus()) return;\n this.root.focus();\n this.setRange(this.savedRange);\n }\n\n format(format, value) {\n this.scroll.update();\n const nativeRange = this.getNativeRange();\n if (nativeRange == null || !nativeRange.native.collapsed || this.scroll.query(format, parchment__WEBPACK_IMPORTED_MODULE_0__[\"Scope\"].BLOCK)) return;\n\n if (nativeRange.start.node !== this.cursor.textNode) {\n const blot = this.scroll.find(nativeRange.start.node, false);\n if (blot == null) return; // TODO Give blot ability to not split\n\n if (blot instanceof parchment__WEBPACK_IMPORTED_MODULE_0__[\"LeafBlot\"]) {\n const after = blot.split(nativeRange.start.offset);\n blot.parent.insertBefore(this.cursor, after);\n } else {\n blot.insertBefore(this.cursor, nativeRange.start.node); // Should never happen\n }\n\n this.cursor.attach();\n }\n\n this.cursor.format(format, value);\n this.scroll.optimize();\n this.setNativeRange(this.cursor.textNode, this.cursor.textNode.data.length);\n this.update();\n }\n\n getBounds(index, length = 0) {\n const scrollLength = this.scroll.length();\n index = Math.min(index, scrollLength - 1);\n length = Math.min(index + length, scrollLength - 1) - index;\n let node;\n let [leaf, offset] = this.scroll.leaf(index);\n if (leaf == null) return null;\n [node, offset] = leaf.position(offset, true);\n const range = document.createRange();\n\n if (length > 0) {\n range.setStart(node, offset);\n [leaf, offset] = this.scroll.leaf(index + length);\n if (leaf == null) return null;\n [node, offset] = leaf.position(offset, true);\n range.setEnd(node, offset);\n return range.getBoundingClientRect();\n }\n\n let side = 'left';\n let rect;\n\n if (node instanceof Text) {\n if (offset < node.data.length) {\n range.setStart(node, offset);\n range.setEnd(node, offset + 1);\n } else {\n range.setStart(node, offset - 1);\n range.setEnd(node, offset);\n side = 'right';\n }\n\n rect = range.getBoundingClientRect();\n } else {\n rect = leaf.domNode.getBoundingClientRect();\n if (offset > 0) side = 'right';\n }\n\n return {\n bottom: rect.top + rect.height,\n height: rect.height,\n left: rect[side],\n right: rect[side],\n top: rect.top,\n width: 0\n };\n }\n\n getNativeRange() {\n const selection = document.getSelection();\n if (selection == null || selection.rangeCount <= 0) return null;\n const nativeRange = selection.getRangeAt(0);\n if (nativeRange == null) return null;\n const range = this.normalizeNative(nativeRange);\n debug.info('getNativeRange', range);\n return range;\n }\n\n getRange() {\n const normalized = this.getNativeRange();\n if (normalized == null) return [null, null];\n const range = this.normalizedToRange(normalized);\n return [range, normalized];\n }\n\n hasFocus() {\n return document.activeElement === this.root || contains(this.root, document.activeElement);\n }\n\n normalizedToRange(range) {\n const positions = [[range.start.node, range.start.offset]];\n\n if (!range.native.collapsed) {\n positions.push([range.end.node, range.end.offset]);\n }\n\n const indexes = positions.map(position => {\n const [node, offset] = position;\n const blot = this.scroll.find(node, true);\n const index = blot.offset(this.scroll);\n\n if (offset === 0) {\n return index;\n }\n\n if (blot instanceof parchment__WEBPACK_IMPORTED_MODULE_0__[\"LeafBlot\"]) {\n return index + blot.index(node, offset);\n }\n\n return index + blot.length();\n });\n const end = Math.min(Math.max(...indexes), this.scroll.length() - 1);\n const start = Math.min(end, ...indexes);\n return new Range(start, end - start);\n }\n\n normalizeNative(nativeRange) {\n if (!contains(this.root, nativeRange.startContainer) || !nativeRange.collapsed && !contains(this.root, nativeRange.endContainer)) {\n return null;\n }\n\n const range = {\n start: {\n node: nativeRange.startContainer,\n offset: nativeRange.startOffset\n },\n end: {\n node: nativeRange.endContainer,\n offset: nativeRange.endOffset\n },\n native: nativeRange\n };\n [range.start, range.end].forEach(position => {\n let {\n node,\n offset\n } = position;\n\n while (!(node instanceof Text) && node.childNodes.length > 0) {\n if (node.childNodes.length > offset) {\n node = node.childNodes[offset];\n offset = 0;\n } else if (node.childNodes.length === offset) {\n node = node.lastChild;\n\n if (node instanceof Text) {\n offset = node.data.length;\n } else if (node.childNodes.length > 0) {\n // Container case\n offset = node.childNodes.length;\n } else {\n // Embed case\n offset = node.childNodes.length + 1;\n }\n } else {\n break;\n }\n }\n\n position.node = node;\n position.offset = offset;\n });\n return range;\n }\n\n rangeToNative(range) {\n const indexes = range.collapsed ? [range.index] : [range.index, range.index + range.length];\n const args = [];\n const scrollLength = this.scroll.length();\n indexes.forEach((index, i) => {\n index = Math.min(scrollLength - 1, index);\n const [leaf, leafOffset] = this.scroll.leaf(index);\n const [node, offset] = leaf.position(leafOffset, i !== 0);\n args.push(node, offset);\n });\n\n if (args.length < 2) {\n return args.concat(args);\n }\n\n return args;\n }\n\n scrollIntoView(scrollingContainer) {\n const range = this.lastRange;\n if (range == null) return;\n const bounds = this.getBounds(range.index, range.length);\n if (bounds == null) return;\n const limit = this.scroll.length() - 1;\n const [first] = this.scroll.line(Math.min(range.index, limit));\n let last = first;\n\n if (range.length > 0) {\n [last] = this.scroll.line(Math.min(range.index + range.length, limit));\n }\n\n if (first == null || last == null) return;\n const scrollBounds = scrollingContainer.getBoundingClientRect();\n\n if (bounds.top < scrollBounds.top) {\n scrollingContainer.scrollTop -= scrollBounds.top - bounds.top;\n } else if (bounds.bottom > scrollBounds.bottom) {\n scrollingContainer.scrollTop += bounds.bottom - scrollBounds.bottom;\n }\n }\n\n setNativeRange(startNode, startOffset, endNode = startNode, endOffset = startOffset, force = false) {\n debug.info('setNativeRange', startNode, startOffset, endNode, endOffset);\n\n if (startNode != null && (this.root.parentNode == null || startNode.parentNode == null || endNode.parentNode == null)) {\n return;\n }\n\n const selection = document.getSelection();\n if (selection == null) return;\n\n if (startNode != null) {\n if (!this.hasFocus()) this.root.focus();\n const {\n native\n } = this.getNativeRange() || {};\n\n if (native == null || force || startNode !== native.startContainer || startOffset !== native.startOffset || endNode !== native.endContainer || endOffset !== native.endOffset) {\n if (startNode.tagName === 'BR') {\n startOffset = Array.from(startNode.parentNode.childNodes).indexOf(startNode);\n startNode = startNode.parentNode;\n }\n\n if (endNode.tagName === 'BR') {\n endOffset = Array.from(endNode.parentNode.childNodes).indexOf(endNode);\n endNode = endNode.parentNode;\n }\n\n const range = document.createRange();\n range.setStart(startNode, startOffset);\n range.setEnd(endNode, endOffset);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n } else {\n selection.removeAllRanges();\n this.root.blur();\n }\n }\n\n setRange(range, force = false, source = _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.API) {\n if (typeof force === 'string') {\n source = force;\n force = false;\n }\n\n debug.info('setRange', range);\n\n if (range != null) {\n const args = this.rangeToNative(range);\n this.setNativeRange(...args, force);\n } else {\n this.setNativeRange(null);\n }\n\n this.update(source);\n }\n\n update(source = _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER) {\n const oldRange = this.lastRange;\n const [lastRange, nativeRange] = this.getRange();\n this.lastRange = lastRange;\n this.lastNative = nativeRange;\n\n if (this.lastRange != null) {\n this.savedRange = this.lastRange;\n }\n\n if (!deep_equal__WEBPACK_IMPORTED_MODULE_2___default()(oldRange, this.lastRange)) {\n if (!this.composing && nativeRange != null && nativeRange.native.collapsed && nativeRange.start.node !== this.cursor.textNode) {\n const range = this.cursor.restore();\n\n if (range) {\n this.setNativeRange(range.startNode, range.startOffset, range.endNode, range.endOffset);\n }\n }\n\n const args = [_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SELECTION_CHANGE, clone__WEBPACK_IMPORTED_MODULE_1___default()(this.lastRange), clone__WEBPACK_IMPORTED_MODULE_1___default()(oldRange), source];\n this.emitter.emit(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.EDITOR_CHANGE, ...args);\n\n if (source !== _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT) {\n this.emitter.emit(...args);\n }\n }\n }\n\n}\n\nfunction contains(parent, descendant) {\n try {\n // Firefox inserts inaccessible nodes around video elements\n descendant.parentNode; // eslint-disable-line no-unused-expressions\n } catch (e) {\n return false;\n }\n\n return parent.contains(descendant);\n}\n\n\n\n//# sourceURL=webpack://Quill/./core/selection.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Range\", function() { return Range; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Selection; });\n/* harmony import */ var parchment__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! parchment */ \"./node_modules/parchment/src/parchment.ts\");\n/* harmony import */ var clone__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! clone */ \"./node_modules/clone/clone.js\");\n/* harmony import */ var clone__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(clone__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var deep_equal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! deep-equal */ \"./node_modules/deep-equal/index.js\");\n/* harmony import */ var deep_equal__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(deep_equal__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _emitter__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./emitter */ \"./core/emitter.js\");\n/* harmony import */ var _logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./logger */ \"./core/logger.js\");\n\n\n\n\n\nconst debug = Object(_logger__WEBPACK_IMPORTED_MODULE_4__[\"default\"])('quill:selection');\n\nclass Range {\n constructor(index, length = 0) {\n this.index = index;\n this.length = length;\n }\n\n}\n\nclass Selection {\n constructor(scroll, emitter) {\n this.emitter = emitter;\n this.scroll = scroll;\n this.composing = false;\n this.mouseDown = false;\n this.root = this.scroll.domNode;\n this.cursor = this.scroll.create('cursor', this); // savedRange is last non-null range\n\n this.savedRange = new Range(0, 0);\n this.lastRange = this.savedRange;\n this.lastNative = null;\n this.handleComposition();\n this.handleDragging();\n this.emitter.listenDOM('selectionchange', document, () => {\n if (!this.mouseDown && !this.composing) {\n setTimeout(this.update.bind(this, _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER), 1);\n }\n });\n this.emitter.on(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_BEFORE_UPDATE, () => {\n if (!this.hasFocus()) return;\n const native = this.getNativeRange();\n if (native == null) return;\n if (native.start.node === this.cursor.textNode) return; // cursor.restore() will handle\n\n this.emitter.once(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_UPDATE, () => {\n try {\n if (this.root.contains(native.start.node) && this.root.contains(native.end.node)) {\n this.setNativeRange(native.start.node, native.start.offset, native.end.node, native.end.offset);\n }\n\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n } catch (ignored) {// ignore\n }\n });\n });\n this.emitter.on(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_OPTIMIZE, (mutations, context) => {\n if (context.range) {\n const {\n startNode,\n startOffset,\n endNode,\n endOffset\n } = context.range;\n this.setNativeRange(startNode, startOffset, endNode, endOffset);\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n }\n });\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n }\n\n handleComposition() {\n this.root.addEventListener('compositionstart', () => {\n this.composing = true;\n this.scroll.batchStart();\n });\n this.root.addEventListener('compositionend', () => {\n this.scroll.batchEnd();\n this.composing = false;\n\n if (this.cursor.parent) {\n const range = this.cursor.restore();\n if (!range) return;\n setTimeout(() => {\n this.setNativeRange(range.startNode, range.startOffset, range.endNode, range.endOffset);\n }, 1);\n }\n });\n }\n\n handleDragging() {\n this.emitter.listenDOM('mousedown', document.body, () => {\n this.mouseDown = true;\n });\n this.emitter.listenDOM('mouseup', document.body, () => {\n this.mouseDown = false;\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER);\n });\n }\n\n focus() {\n if (this.hasFocus()) return;\n this.root.focus();\n this.setRange(this.savedRange);\n }\n\n format(format, value) {\n this.scroll.update();\n const nativeRange = this.getNativeRange();\n if (nativeRange == null || !nativeRange.native.collapsed || this.scroll.query(format, parchment__WEBPACK_IMPORTED_MODULE_0__[\"Scope\"].BLOCK)) return;\n\n if (nativeRange.start.node !== this.cursor.textNode) {\n const blot = this.scroll.find(nativeRange.start.node, false);\n if (blot == null) return; // TODO Give blot ability to not split\n\n if (blot instanceof parchment__WEBPACK_IMPORTED_MODULE_0__[\"LeafBlot\"]) {\n const after = blot.split(nativeRange.start.offset);\n blot.parent.insertBefore(this.cursor, after);\n } else {\n blot.insertBefore(this.cursor, nativeRange.start.node); // Should never happen\n }\n\n this.cursor.attach();\n }\n\n this.cursor.format(format, value);\n this.scroll.optimize();\n this.setNativeRange(this.cursor.textNode, this.cursor.textNode.data.length);\n this.update();\n }\n\n getBounds(index, length = 0) {\n const scrollLength = this.scroll.length();\n index = Math.min(index, scrollLength - 1);\n length = Math.min(index + length, scrollLength - 1) - index;\n let node;\n let [leaf, offset] = this.scroll.leaf(index);\n if (leaf == null) return null;\n [node, offset] = leaf.position(offset, true);\n const range = document.createRange();\n\n if (length > 0) {\n range.setStart(node, offset);\n [leaf, offset] = this.scroll.leaf(index + length);\n if (leaf == null) return null;\n [node, offset] = leaf.position(offset, true);\n range.setEnd(node, offset);\n return range.getBoundingClientRect();\n }\n\n let side = 'left';\n let rect;\n\n if (node instanceof Text || node.nodeName === '#text') {\n if (offset < node.data.length) {\n range.setStart(node, offset);\n range.setEnd(node, offset + 1);\n } else {\n range.setStart(node, offset - 1);\n range.setEnd(node, offset);\n side = 'right';\n }\n\n rect = range.getBoundingClientRect();\n } else {\n rect = leaf.domNode.getBoundingClientRect();\n if (offset > 0) side = 'right';\n }\n\n return {\n bottom: rect.top + rect.height,\n height: rect.height,\n left: rect[side],\n right: rect[side],\n top: rect.top,\n width: 0\n };\n }\n\n getNativeRange() {\n const selection = document.getSelection();\n if (selection == null || selection.rangeCount <= 0) return null;\n const nativeRange = selection.getRangeAt(0);\n if (nativeRange == null) return null;\n const range = this.normalizeNative(nativeRange);\n debug.info('getNativeRange', range);\n return range;\n }\n\n getRange() {\n const normalized = this.getNativeRange();\n if (normalized == null) return [null, null];\n const range = this.normalizedToRange(normalized);\n return [range, normalized];\n }\n\n hasFocus() {\n return document.activeElement === this.root || contains(this.root, document.activeElement);\n }\n\n normalizedToRange(range) {\n const positions = [[range.start.node, range.start.offset]];\n\n if (!range.native.collapsed) {\n positions.push([range.end.node, range.end.offset]);\n }\n\n const indexes = positions.map(position => {\n const [node, offset] = position;\n const blot = this.scroll.find(node, true);\n const index = blot.offset(this.scroll);\n\n if (offset === 0) {\n return index;\n }\n\n if (blot instanceof parchment__WEBPACK_IMPORTED_MODULE_0__[\"LeafBlot\"]) {\n return index + blot.index(node, offset);\n }\n\n return index + blot.length();\n });\n const end = Math.min(Math.max(...indexes), this.scroll.length() - 1);\n const start = Math.min(end, ...indexes);\n return new Range(start, end - start);\n }\n\n normalizeNative(nativeRange) {\n if (!contains(this.root, nativeRange.startContainer) || !nativeRange.collapsed && !contains(this.root, nativeRange.endContainer)) {\n return null;\n }\n\n const range = {\n start: {\n node: nativeRange.startContainer,\n offset: nativeRange.startOffset\n },\n end: {\n node: nativeRange.endContainer,\n offset: nativeRange.endOffset\n },\n native: nativeRange\n };\n [range.start, range.end].forEach(position => {\n let {\n node,\n offset\n } = position;\n\n while (!(node instanceof Text) && node.childNodes.length > 0) {\n if (node.childNodes.length > offset) {\n node = node.childNodes[offset];\n offset = 0;\n } else if (node.childNodes.length === offset) {\n node = node.lastChild;\n\n if (node instanceof Text) {\n offset = node.data.length;\n } else if (node.childNodes.length > 0) {\n // Container case\n offset = node.childNodes.length;\n } else {\n // Embed case\n offset = node.childNodes.length + 1;\n }\n } else {\n break;\n }\n }\n\n position.node = node;\n position.offset = offset;\n });\n return range;\n }\n\n rangeToNative(range) {\n const indexes = range.collapsed ? [range.index] : [range.index, range.index + range.length];\n const args = [];\n const scrollLength = this.scroll.length();\n indexes.forEach((index, i) => {\n index = Math.min(scrollLength - 1, index);\n const [leaf, leafOffset] = this.scroll.leaf(index);\n const [node, offset] = leaf.position(leafOffset, i !== 0);\n args.push(node, offset);\n });\n\n if (args.length < 2) {\n return args.concat(args);\n }\n\n return args;\n }\n\n scrollIntoView(scrollingContainer) {\n const range = this.lastRange;\n if (range == null) return;\n const bounds = this.getBounds(range.index, range.length);\n if (bounds == null) return;\n const limit = this.scroll.length() - 1;\n const [first] = this.scroll.line(Math.min(range.index, limit));\n let last = first;\n\n if (range.length > 0) {\n [last] = this.scroll.line(Math.min(range.index + range.length, limit));\n }\n\n if (first == null || last == null) return;\n const scrollBounds = scrollingContainer.getBoundingClientRect();\n\n if (bounds.top < scrollBounds.top) {\n scrollingContainer.scrollTop -= scrollBounds.top - bounds.top;\n } else if (bounds.bottom > scrollBounds.bottom) {\n scrollingContainer.scrollTop += bounds.bottom - scrollBounds.bottom;\n }\n }\n\n setNativeRange(startNode, startOffset, endNode = startNode, endOffset = startOffset, force = false) {\n debug.info('setNativeRange', startNode, startOffset, endNode, endOffset);\n\n if (startNode != null && (this.root.parentNode == null || startNode.parentNode == null || endNode.parentNode == null)) {\n return;\n }\n\n const selection = document.getSelection();\n if (selection == null) return;\n\n if (startNode != null) {\n if (!this.hasFocus()) this.root.focus();\n const {\n native\n } = this.getNativeRange() || {};\n\n if (native == null || force || startNode !== native.startContainer || startOffset !== native.startOffset || endNode !== native.endContainer || endOffset !== native.endOffset) {\n if (startNode.tagName === 'BR') {\n startOffset = Array.from(startNode.parentNode.childNodes).indexOf(startNode);\n startNode = startNode.parentNode;\n }\n\n if (endNode.tagName === 'BR') {\n endOffset = Array.from(endNode.parentNode.childNodes).indexOf(endNode);\n endNode = endNode.parentNode;\n }\n\n const range = document.createRange();\n range.setStart(startNode, startOffset);\n range.setEnd(endNode, endOffset);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n } else {\n selection.removeAllRanges();\n this.root.blur();\n }\n }\n\n setRange(range, force = false, source = _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.API) {\n if (typeof force === 'string') {\n source = force;\n force = false;\n }\n\n debug.info('setRange', range);\n\n if (range != null) {\n const args = this.rangeToNative(range);\n this.setNativeRange(...args, force);\n } else {\n this.setNativeRange(null);\n }\n\n this.update(source);\n }\n\n update(source = _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER) {\n const oldRange = this.lastRange;\n const [lastRange, nativeRange] = this.getRange();\n this.lastRange = lastRange;\n this.lastNative = nativeRange;\n\n if (this.lastRange != null) {\n this.savedRange = this.lastRange;\n }\n\n if (!deep_equal__WEBPACK_IMPORTED_MODULE_2___default()(oldRange, this.lastRange)) {\n if (!this.composing && nativeRange != null && nativeRange.native.collapsed && nativeRange.start.node !== this.cursor.textNode) {\n const range = this.cursor.restore();\n\n if (range) {\n this.setNativeRange(range.startNode, range.startOffset, range.endNode, range.endOffset);\n }\n }\n\n const args = [_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SELECTION_CHANGE, clone__WEBPACK_IMPORTED_MODULE_1___default()(this.lastRange), clone__WEBPACK_IMPORTED_MODULE_1___default()(oldRange), source];\n this.emitter.emit(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.EDITOR_CHANGE, ...args);\n\n if (source !== _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT) {\n this.emitter.emit(...args);\n }\n }\n }\n\n}\n\nfunction contains(parent, descendant) {\n try {\n // Firefox inserts inaccessible nodes around video elements\n descendant.parentNode; // eslint-disable-line no-unused-expressions\n } catch (e) {\n return false;\n }\n\n return parent.contains(descendant);\n}\n\n\n\n//# sourceURL=webpack://Quill/./core/selection.js?");
/***/ }),
diff --git a/node_modules/quill/dist/quill.js b/node_modules/quill/dist/quill.js
index 2d45561..52e4303 100644
--- a/node_modules/quill/dist/quill.js
+++ b/node_modules/quill/dist/quill.js
@@ -620,7 +620,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Range\", function() { return Range; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Selection; });\n/* harmony import */ var parchment__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! parchment */ \"./node_modules/parchment/src/parchment.ts\");\n/* harmony import */ var clone__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! clone */ \"./node_modules/clone/clone.js\");\n/* harmony import */ var clone__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(clone__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var deep_equal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! deep-equal */ \"./node_modules/deep-equal/index.js\");\n/* harmony import */ var deep_equal__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(deep_equal__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _emitter__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./emitter */ \"./core/emitter.js\");\n/* harmony import */ var _logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./logger */ \"./core/logger.js\");\n\n\n\n\n\nconst debug = Object(_logger__WEBPACK_IMPORTED_MODULE_4__[\"default\"])('quill:selection');\n\nclass Range {\n constructor(index, length = 0) {\n this.index = index;\n this.length = length;\n }\n\n}\n\nclass Selection {\n constructor(scroll, emitter) {\n this.emitter = emitter;\n this.scroll = scroll;\n this.composing = false;\n this.mouseDown = false;\n this.root = this.scroll.domNode;\n this.cursor = this.scroll.create('cursor', this); // savedRange is last non-null range\n\n this.savedRange = new Range(0, 0);\n this.lastRange = this.savedRange;\n this.lastNative = null;\n this.handleComposition();\n this.handleDragging();\n this.emitter.listenDOM('selectionchange', document, () => {\n if (!this.mouseDown && !this.composing) {\n setTimeout(this.update.bind(this, _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER), 1);\n }\n });\n this.emitter.on(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_BEFORE_UPDATE, () => {\n if (!this.hasFocus()) return;\n const native = this.getNativeRange();\n if (native == null) return;\n if (native.start.node === this.cursor.textNode) return; // cursor.restore() will handle\n\n this.emitter.once(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_UPDATE, () => {\n try {\n if (this.root.contains(native.start.node) && this.root.contains(native.end.node)) {\n this.setNativeRange(native.start.node, native.start.offset, native.end.node, native.end.offset);\n }\n\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n } catch (ignored) {// ignore\n }\n });\n });\n this.emitter.on(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_OPTIMIZE, (mutations, context) => {\n if (context.range) {\n const {\n startNode,\n startOffset,\n endNode,\n endOffset\n } = context.range;\n this.setNativeRange(startNode, startOffset, endNode, endOffset);\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n }\n });\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n }\n\n handleComposition() {\n this.root.addEventListener('compositionstart', () => {\n this.composing = true;\n this.scroll.batchStart();\n });\n this.root.addEventListener('compositionend', () => {\n this.scroll.batchEnd();\n this.composing = false;\n\n if (this.cursor.parent) {\n const range = this.cursor.restore();\n if (!range) return;\n setTimeout(() => {\n this.setNativeRange(range.startNode, range.startOffset, range.endNode, range.endOffset);\n }, 1);\n }\n });\n }\n\n handleDragging() {\n this.emitter.listenDOM('mousedown', document.body, () => {\n this.mouseDown = true;\n });\n this.emitter.listenDOM('mouseup', document.body, () => {\n this.mouseDown = false;\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER);\n });\n }\n\n focus() {\n if (this.hasFocus()) return;\n this.root.focus();\n this.setRange(this.savedRange);\n }\n\n format(format, value) {\n this.scroll.update();\n const nativeRange = this.getNativeRange();\n if (nativeRange == null || !nativeRange.native.collapsed || this.scroll.query(format, parchment__WEBPACK_IMPORTED_MODULE_0__[\"Scope\"].BLOCK)) return;\n\n if (nativeRange.start.node !== this.cursor.textNode) {\n const blot = this.scroll.find(nativeRange.start.node, false);\n if (blot == null) return; // TODO Give blot ability to not split\n\n if (blot instanceof parchment__WEBPACK_IMPORTED_MODULE_0__[\"LeafBlot\"]) {\n const after = blot.split(nativeRange.start.offset);\n blot.parent.insertBefore(this.cursor, after);\n } else {\n blot.insertBefore(this.cursor, nativeRange.start.node); // Should never happen\n }\n\n this.cursor.attach();\n }\n\n this.cursor.format(format, value);\n this.scroll.optimize();\n this.setNativeRange(this.cursor.textNode, this.cursor.textNode.data.length);\n this.update();\n }\n\n getBounds(index, length = 0) {\n const scrollLength = this.scroll.length();\n index = Math.min(index, scrollLength - 1);\n length = Math.min(index + length, scrollLength - 1) - index;\n let node;\n let [leaf, offset] = this.scroll.leaf(index);\n if (leaf == null) return null;\n [node, offset] = leaf.position(offset, true);\n const range = document.createRange();\n\n if (length > 0) {\n range.setStart(node, offset);\n [leaf, offset] = this.scroll.leaf(index + length);\n if (leaf == null) return null;\n [node, offset] = leaf.position(offset, true);\n range.setEnd(node, offset);\n return range.getBoundingClientRect();\n }\n\n let side = 'left';\n let rect;\n\n if (node instanceof Text) {\n if (offset < node.data.length) {\n range.setStart(node, offset);\n range.setEnd(node, offset + 1);\n } else {\n range.setStart(node, offset - 1);\n range.setEnd(node, offset);\n side = 'right';\n }\n\n rect = range.getBoundingClientRect();\n } else {\n rect = leaf.domNode.getBoundingClientRect();\n if (offset > 0) side = 'right';\n }\n\n return {\n bottom: rect.top + rect.height,\n height: rect.height,\n left: rect[side],\n right: rect[side],\n top: rect.top,\n width: 0\n };\n }\n\n getNativeRange() {\n const selection = document.getSelection();\n if (selection == null || selection.rangeCount <= 0) return null;\n const nativeRange = selection.getRangeAt(0);\n if (nativeRange == null) return null;\n const range = this.normalizeNative(nativeRange);\n debug.info('getNativeRange', range);\n return range;\n }\n\n getRange() {\n const normalized = this.getNativeRange();\n if (normalized == null) return [null, null];\n const range = this.normalizedToRange(normalized);\n return [range, normalized];\n }\n\n hasFocus() {\n return document.activeElement === this.root || contains(this.root, document.activeElement);\n }\n\n normalizedToRange(range) {\n const positions = [[range.start.node, range.start.offset]];\n\n if (!range.native.collapsed) {\n positions.push([range.end.node, range.end.offset]);\n }\n\n const indexes = positions.map(position => {\n const [node, offset] = position;\n const blot = this.scroll.find(node, true);\n const index = blot.offset(this.scroll);\n\n if (offset === 0) {\n return index;\n }\n\n if (blot instanceof parchment__WEBPACK_IMPORTED_MODULE_0__[\"LeafBlot\"]) {\n return index + blot.index(node, offset);\n }\n\n return index + blot.length();\n });\n const end = Math.min(Math.max(...indexes), this.scroll.length() - 1);\n const start = Math.min(end, ...indexes);\n return new Range(start, end - start);\n }\n\n normalizeNative(nativeRange) {\n if (!contains(this.root, nativeRange.startContainer) || !nativeRange.collapsed && !contains(this.root, nativeRange.endContainer)) {\n return null;\n }\n\n const range = {\n start: {\n node: nativeRange.startContainer,\n offset: nativeRange.startOffset\n },\n end: {\n node: nativeRange.endContainer,\n offset: nativeRange.endOffset\n },\n native: nativeRange\n };\n [range.start, range.end].forEach(position => {\n let {\n node,\n offset\n } = position;\n\n while (!(node instanceof Text) && node.childNodes.length > 0) {\n if (node.childNodes.length > offset) {\n node = node.childNodes[offset];\n offset = 0;\n } else if (node.childNodes.length === offset) {\n node = node.lastChild;\n\n if (node instanceof Text) {\n offset = node.data.length;\n } else if (node.childNodes.length > 0) {\n // Container case\n offset = node.childNodes.length;\n } else {\n // Embed case\n offset = node.childNodes.length + 1;\n }\n } else {\n break;\n }\n }\n\n position.node = node;\n position.offset = offset;\n });\n return range;\n }\n\n rangeToNative(range) {\n const indexes = range.collapsed ? [range.index] : [range.index, range.index + range.length];\n const args = [];\n const scrollLength = this.scroll.length();\n indexes.forEach((index, i) => {\n index = Math.min(scrollLength - 1, index);\n const [leaf, leafOffset] = this.scroll.leaf(index);\n const [node, offset] = leaf.position(leafOffset, i !== 0);\n args.push(node, offset);\n });\n\n if (args.length < 2) {\n return args.concat(args);\n }\n\n return args;\n }\n\n scrollIntoView(scrollingContainer) {\n const range = this.lastRange;\n if (range == null) return;\n const bounds = this.getBounds(range.index, range.length);\n if (bounds == null) return;\n const limit = this.scroll.length() - 1;\n const [first] = this.scroll.line(Math.min(range.index, limit));\n let last = first;\n\n if (range.length > 0) {\n [last] = this.scroll.line(Math.min(range.index + range.length, limit));\n }\n\n if (first == null || last == null) return;\n const scrollBounds = scrollingContainer.getBoundingClientRect();\n\n if (bounds.top < scrollBounds.top) {\n scrollingContainer.scrollTop -= scrollBounds.top - bounds.top;\n } else if (bounds.bottom > scrollBounds.bottom) {\n scrollingContainer.scrollTop += bounds.bottom - scrollBounds.bottom;\n }\n }\n\n setNativeRange(startNode, startOffset, endNode = startNode, endOffset = startOffset, force = false) {\n debug.info('setNativeRange', startNode, startOffset, endNode, endOffset);\n\n if (startNode != null && (this.root.parentNode == null || startNode.parentNode == null || endNode.parentNode == null)) {\n return;\n }\n\n const selection = document.getSelection();\n if (selection == null) return;\n\n if (startNode != null) {\n if (!this.hasFocus()) this.root.focus();\n const {\n native\n } = this.getNativeRange() || {};\n\n if (native == null || force || startNode !== native.startContainer || startOffset !== native.startOffset || endNode !== native.endContainer || endOffset !== native.endOffset) {\n if (startNode.tagName === 'BR') {\n startOffset = Array.from(startNode.parentNode.childNodes).indexOf(startNode);\n startNode = startNode.parentNode;\n }\n\n if (endNode.tagName === 'BR') {\n endOffset = Array.from(endNode.parentNode.childNodes).indexOf(endNode);\n endNode = endNode.parentNode;\n }\n\n const range = document.createRange();\n range.setStart(startNode, startOffset);\n range.setEnd(endNode, endOffset);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n } else {\n selection.removeAllRanges();\n this.root.blur();\n }\n }\n\n setRange(range, force = false, source = _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.API) {\n if (typeof force === 'string') {\n source = force;\n force = false;\n }\n\n debug.info('setRange', range);\n\n if (range != null) {\n const args = this.rangeToNative(range);\n this.setNativeRange(...args, force);\n } else {\n this.setNativeRange(null);\n }\n\n this.update(source);\n }\n\n update(source = _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER) {\n const oldRange = this.lastRange;\n const [lastRange, nativeRange] = this.getRange();\n this.lastRange = lastRange;\n this.lastNative = nativeRange;\n\n if (this.lastRange != null) {\n this.savedRange = this.lastRange;\n }\n\n if (!deep_equal__WEBPACK_IMPORTED_MODULE_2___default()(oldRange, this.lastRange)) {\n if (!this.composing && nativeRange != null && nativeRange.native.collapsed && nativeRange.start.node !== this.cursor.textNode) {\n const range = this.cursor.restore();\n\n if (range) {\n this.setNativeRange(range.startNode, range.startOffset, range.endNode, range.endOffset);\n }\n }\n\n const args = [_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SELECTION_CHANGE, clone__WEBPACK_IMPORTED_MODULE_1___default()(this.lastRange), clone__WEBPACK_IMPORTED_MODULE_1___default()(oldRange), source];\n this.emitter.emit(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.EDITOR_CHANGE, ...args);\n\n if (source !== _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT) {\n this.emitter.emit(...args);\n }\n }\n }\n\n}\n\nfunction contains(parent, descendant) {\n try {\n // Firefox inserts inaccessible nodes around video elements\n descendant.parentNode; // eslint-disable-line no-unused-expressions\n } catch (e) {\n return false;\n }\n\n return parent.contains(descendant);\n}\n\n\n\n//# sourceURL=webpack://Quill/./core/selection.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Range\", function() { return Range; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Selection; });\n/* harmony import */ var parchment__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! parchment */ \"./node_modules/parchment/src/parchment.ts\");\n/* harmony import */ var clone__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! clone */ \"./node_modules/clone/clone.js\");\n/* harmony import */ var clone__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(clone__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var deep_equal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! deep-equal */ \"./node_modules/deep-equal/index.js\");\n/* harmony import */ var deep_equal__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(deep_equal__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _emitter__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./emitter */ \"./core/emitter.js\");\n/* harmony import */ var _logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./logger */ \"./core/logger.js\");\n\n\n\n\n\nconst debug = Object(_logger__WEBPACK_IMPORTED_MODULE_4__[\"default\"])('quill:selection');\n\nclass Range {\n constructor(index, length = 0) {\n this.index = index;\n this.length = length;\n }\n\n}\n\nclass Selection {\n constructor(scroll, emitter) {\n this.emitter = emitter;\n this.scroll = scroll;\n this.composing = false;\n this.mouseDown = false;\n this.root = this.scroll.domNode;\n this.cursor = this.scroll.create('cursor', this); // savedRange is last non-null range\n\n this.savedRange = new Range(0, 0);\n this.lastRange = this.savedRange;\n this.lastNative = null;\n this.handleComposition();\n this.handleDragging();\n this.emitter.listenDOM('selectionchange', document, () => {\n if (!this.mouseDown && !this.composing) {\n setTimeout(this.update.bind(this, _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER), 1);\n }\n });\n this.emitter.on(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_BEFORE_UPDATE, () => {\n if (!this.hasFocus()) return;\n const native = this.getNativeRange();\n if (native == null) return;\n if (native.start.node === this.cursor.textNode) return; // cursor.restore() will handle\n\n this.emitter.once(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_UPDATE, () => {\n try {\n if (this.root.contains(native.start.node) && this.root.contains(native.end.node)) {\n this.setNativeRange(native.start.node, native.start.offset, native.end.node, native.end.offset);\n }\n\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n } catch (ignored) {// ignore\n }\n });\n });\n this.emitter.on(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SCROLL_OPTIMIZE, (mutations, context) => {\n if (context.range) {\n const {\n startNode,\n startOffset,\n endNode,\n endOffset\n } = context.range;\n this.setNativeRange(startNode, startOffset, endNode, endOffset);\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n }\n });\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT);\n }\n\n handleComposition() {\n this.root.addEventListener('compositionstart', () => {\n this.composing = true;\n this.scroll.batchStart();\n });\n this.root.addEventListener('compositionend', () => {\n this.scroll.batchEnd();\n this.composing = false;\n\n if (this.cursor.parent) {\n const range = this.cursor.restore();\n if (!range) return;\n setTimeout(() => {\n this.setNativeRange(range.startNode, range.startOffset, range.endNode, range.endOffset);\n }, 1);\n }\n });\n }\n\n handleDragging() {\n this.emitter.listenDOM('mousedown', document.body, () => {\n this.mouseDown = true;\n });\n this.emitter.listenDOM('mouseup', document.body, () => {\n this.mouseDown = false;\n this.update(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER);\n });\n }\n\n focus() {\n if (this.hasFocus()) return;\n this.root.focus();\n this.setRange(this.savedRange);\n }\n\n format(format, value) {\n this.scroll.update();\n const nativeRange = this.getNativeRange();\n if (nativeRange == null || !nativeRange.native.collapsed || this.scroll.query(format, parchment__WEBPACK_IMPORTED_MODULE_0__[\"Scope\"].BLOCK)) return;\n\n if (nativeRange.start.node !== this.cursor.textNode) {\n const blot = this.scroll.find(nativeRange.start.node, false);\n if (blot == null) return; // TODO Give blot ability to not split\n\n if (blot instanceof parchment__WEBPACK_IMPORTED_MODULE_0__[\"LeafBlot\"]) {\n const after = blot.split(nativeRange.start.offset);\n blot.parent.insertBefore(this.cursor, after);\n } else {\n blot.insertBefore(this.cursor, nativeRange.start.node); // Should never happen\n }\n\n this.cursor.attach();\n }\n\n this.cursor.format(format, value);\n this.scroll.optimize();\n this.setNativeRange(this.cursor.textNode, this.cursor.textNode.data.length);\n this.update();\n }\n\n getBounds(index, length = 0) {\n const scrollLength = this.scroll.length();\n index = Math.min(index, scrollLength - 1);\n length = Math.min(index + length, scrollLength - 1) - index;\n let node;\n let [leaf, offset] = this.scroll.leaf(index);\n if (leaf == null) return null;\n [node, offset] = leaf.position(offset, true);\n const range = document.createRange();\n\n if (length > 0) {\n range.setStart(node, offset);\n [leaf, offset] = this.scroll.leaf(index + length);\n if (leaf == null) return null;\n [node, offset] = leaf.position(offset, true);\n range.setEnd(node, offset);\n return range.getBoundingClientRect();\n }\n\n let side = 'left';\n let rect;\n\n if (node instanceof Text || node.nodeName === '#text') {\n if (offset < node.data.length) {\n range.setStart(node, offset);\n range.setEnd(node, offset + 1);\n } else {\n range.setStart(node, offset - 1);\n range.setEnd(node, offset);\n side = 'right';\n }\n\n rect = range.getBoundingClientRect();\n } else {\n rect = leaf.domNode.getBoundingClientRect();\n if (offset > 0) side = 'right';\n }\n\n return {\n bottom: rect.top + rect.height,\n height: rect.height,\n left: rect[side],\n right: rect[side],\n top: rect.top,\n width: 0\n };\n }\n\n getNativeRange() {\n const selection = document.getSelection();\n if (selection == null || selection.rangeCount <= 0) return null;\n const nativeRange = selection.getRangeAt(0);\n if (nativeRange == null) return null;\n const range = this.normalizeNative(nativeRange);\n debug.info('getNativeRange', range);\n return range;\n }\n\n getRange() {\n const normalized = this.getNativeRange();\n if (normalized == null) return [null, null];\n const range = this.normalizedToRange(normalized);\n return [range, normalized];\n }\n\n hasFocus() {\n return document.activeElement === this.root || contains(this.root, document.activeElement);\n }\n\n normalizedToRange(range) {\n const positions = [[range.start.node, range.start.offset]];\n\n if (!range.native.collapsed) {\n positions.push([range.end.node, range.end.offset]);\n }\n\n const indexes = positions.map(position => {\n const [node, offset] = position;\n const blot = this.scroll.find(node, true);\n const index = blot.offset(this.scroll);\n\n if (offset === 0) {\n return index;\n }\n\n if (blot instanceof parchment__WEBPACK_IMPORTED_MODULE_0__[\"LeafBlot\"]) {\n return index + blot.index(node, offset);\n }\n\n return index + blot.length();\n });\n const end = Math.min(Math.max(...indexes), this.scroll.length() - 1);\n const start = Math.min(end, ...indexes);\n return new Range(start, end - start);\n }\n\n normalizeNative(nativeRange) {\n if (!contains(this.root, nativeRange.startContainer) || !nativeRange.collapsed && !contains(this.root, nativeRange.endContainer)) {\n return null;\n }\n\n const range = {\n start: {\n node: nativeRange.startContainer,\n offset: nativeRange.startOffset\n },\n end: {\n node: nativeRange.endContainer,\n offset: nativeRange.endOffset\n },\n native: nativeRange\n };\n [range.start, range.end].forEach(position => {\n let {\n node,\n offset\n } = position;\n\n while (!(node instanceof Text) && node.childNodes.length > 0) {\n if (node.childNodes.length > offset) {\n node = node.childNodes[offset];\n offset = 0;\n } else if (node.childNodes.length === offset) {\n node = node.lastChild;\n\n if (node instanceof Text) {\n offset = node.data.length;\n } else if (node.childNodes.length > 0) {\n // Container case\n offset = node.childNodes.length;\n } else {\n // Embed case\n offset = node.childNodes.length + 1;\n }\n } else {\n break;\n }\n }\n\n position.node = node;\n position.offset = offset;\n });\n return range;\n }\n\n rangeToNative(range) {\n const indexes = range.collapsed ? [range.index] : [range.index, range.index + range.length];\n const args = [];\n const scrollLength = this.scroll.length();\n indexes.forEach((index, i) => {\n index = Math.min(scrollLength - 1, index);\n const [leaf, leafOffset] = this.scroll.leaf(index);\n const [node, offset] = leaf.position(leafOffset, i !== 0);\n args.push(node, offset);\n });\n\n if (args.length < 2) {\n return args.concat(args);\n }\n\n return args;\n }\n\n scrollIntoView(scrollingContainer) {\n const range = this.lastRange;\n if (range == null) return;\n const bounds = this.getBounds(range.index, range.length);\n if (bounds == null) return;\n const limit = this.scroll.length() - 1;\n const [first] = this.scroll.line(Math.min(range.index, limit));\n let last = first;\n\n if (range.length > 0) {\n [last] = this.scroll.line(Math.min(range.index + range.length, limit));\n }\n\n if (first == null || last == null) return;\n const scrollBounds = scrollingContainer.getBoundingClientRect();\n\n if (bounds.top < scrollBounds.top) {\n scrollingContainer.scrollTop -= scrollBounds.top - bounds.top;\n } else if (bounds.bottom > scrollBounds.bottom) {\n scrollingContainer.scrollTop += bounds.bottom - scrollBounds.bottom;\n }\n }\n\n setNativeRange(startNode, startOffset, endNode = startNode, endOffset = startOffset, force = false) {\n debug.info('setNativeRange', startNode, startOffset, endNode, endOffset);\n\n if (startNode != null && (this.root.parentNode == null || startNode.parentNode == null || endNode.parentNode == null)) {\n return;\n }\n\n const selection = document.getSelection();\n if (selection == null) return;\n\n if (startNode != null) {\n if (!this.hasFocus()) this.root.focus();\n const {\n native\n } = this.getNativeRange() || {};\n\n if (native == null || force || startNode !== native.startContainer || startOffset !== native.startOffset || endNode !== native.endContainer || endOffset !== native.endOffset) {\n if (startNode.tagName === 'BR') {\n startOffset = Array.from(startNode.parentNode.childNodes).indexOf(startNode);\n startNode = startNode.parentNode;\n }\n\n if (endNode.tagName === 'BR') {\n endOffset = Array.from(endNode.parentNode.childNodes).indexOf(endNode);\n endNode = endNode.parentNode;\n }\n\n const range = document.createRange();\n range.setStart(startNode, startOffset);\n range.setEnd(endNode, endOffset);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n } else {\n selection.removeAllRanges();\n this.root.blur();\n }\n }\n\n setRange(range, force = false, source = _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.API) {\n if (typeof force === 'string') {\n source = force;\n force = false;\n }\n\n debug.info('setRange', range);\n\n if (range != null) {\n const args = this.rangeToNative(range);\n this.setNativeRange(...args, force);\n } else {\n this.setNativeRange(null);\n }\n\n this.update(source);\n }\n\n update(source = _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.USER) {\n const oldRange = this.lastRange;\n const [lastRange, nativeRange] = this.getRange();\n this.lastRange = lastRange;\n this.lastNative = nativeRange;\n\n if (this.lastRange != null) {\n this.savedRange = this.lastRange;\n }\n\n if (!deep_equal__WEBPACK_IMPORTED_MODULE_2___default()(oldRange, this.lastRange)) {\n if (!this.composing && nativeRange != null && nativeRange.native.collapsed && nativeRange.start.node !== this.cursor.textNode) {\n const range = this.cursor.restore();\n\n if (range) {\n this.setNativeRange(range.startNode, range.startOffset, range.endNode, range.endOffset);\n }\n }\n\n const args = [_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.SELECTION_CHANGE, clone__WEBPACK_IMPORTED_MODULE_1___default()(this.lastRange), clone__WEBPACK_IMPORTED_MODULE_1___default()(oldRange), source];\n this.emitter.emit(_emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].events.EDITOR_CHANGE, ...args);\n\n if (source !== _emitter__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sources.SILENT) {\n this.emitter.emit(...args);\n }\n }\n }\n\n}\n\nfunction contains(parent, descendant) {\n try {\n // Firefox inserts inaccessible nodes around video elements\n descendant.parentNode; // eslint-disable-line no-unused-expressions\n } catch (e) {\n return false;\n }\n\n return parent.contains(descendant);\n}\n\n\n\n//# sourceURL=webpack://Quill/./core/selection.js?");
/***/ }),