Text source range refactor (#949)

* Rename functions for better clarity

* Remove unused properties

* Add getNodesInRange function

* Improve ignore nodes check

* Use private fields
This commit is contained in:
toasted-nutbread 2020-10-20 20:54:26 -04:00 committed by GitHub
parent 9bda0a9eb4
commit 6f980d8f2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 38 deletions

View File

@ -89,7 +89,7 @@ class TextSourceElement {
// NOP // NOP
} }
equals(other) { hasSameStart(other) {
return ( return (
typeof other === 'object' && typeof other === 'object' &&
other !== null && other !== null &&
@ -100,6 +100,10 @@ class TextSourceElement {
); );
} }
getNodesInRange() {
return [];
}
static getElementContent(element) { static getElementContent(element) {
let content; let content;
switch (element.nodeName.toUpperCase()) { switch (element.nodeName.toUpperCase()) {

View File

@ -17,70 +17,75 @@
/* global /* global
* DOMTextScanner * DOMTextScanner
* DocumentUtil
*/ */
class TextSourceRange { class TextSourceRange {
constructor(range, content, imposterContainer, imposterSourceElement) { constructor(range, content, imposterContainer, imposterSourceElement) {
this.range = range; this._range = range;
this.rangeStartOffset = range.startOffset; this._rangeStartOffset = range.startOffset;
this.content = content; this._content = content;
this.imposterContainer = imposterContainer; this._imposterContainer = imposterContainer;
this.imposterSourceElement = imposterSourceElement; this._imposterSourceElement = imposterSourceElement;
} }
get startOffset() { get range() {
return this.range.startOffset; return this._range;
} }
get endOffset() { get rangeStartOffset() {
return this.range.endOffset; return this._rangeStartOffset;
}
get imposterSourceElement() {
return this._imposterSourceElement;
} }
clone() { clone() {
return new TextSourceRange(this.range.cloneRange(), this.content, this.imposterContainer, this.imposterSourceElement); return new TextSourceRange(this._range.cloneRange(), this._content, this._imposterContainer, this._imposterSourceElement);
} }
cleanup() { cleanup() {
if (this.imposterContainer !== null && this.imposterContainer.parentNode !== null) { if (this._imposterContainer !== null && this._imposterContainer.parentNode !== null) {
this.imposterContainer.parentNode.removeChild(this.imposterContainer); this._imposterContainer.parentNode.removeChild(this._imposterContainer);
} }
} }
text() { text() {
return this.content; return this._content;
} }
setEndOffset(length, layoutAwareScan, fromEnd=false) { setEndOffset(length, layoutAwareScan, fromEnd=false) {
const state = ( const state = (
fromEnd ? fromEnd ?
new DOMTextScanner(this.range.endContainer, this.range.endOffset, !layoutAwareScan, layoutAwareScan).seek(length) : new DOMTextScanner(this._range.endContainer, this._range.endOffset, !layoutAwareScan, layoutAwareScan).seek(length) :
new DOMTextScanner(this.range.startContainer, this.range.startOffset, !layoutAwareScan, layoutAwareScan).seek(length) new DOMTextScanner(this._range.startContainer, this._range.startOffset, !layoutAwareScan, layoutAwareScan).seek(length)
); );
this.range.setEnd(state.node, state.offset); this._range.setEnd(state.node, state.offset);
this.content = (fromEnd ? this.content + state.content : state.content); this._content = (fromEnd ? this._content + state.content : state.content);
return length - state.remainder; return length - state.remainder;
} }
setStartOffset(length, layoutAwareScan) { setStartOffset(length, layoutAwareScan) {
const state = new DOMTextScanner(this.range.startContainer, this.range.startOffset, !layoutAwareScan, layoutAwareScan).seek(-length); const state = new DOMTextScanner(this._range.startContainer, this._range.startOffset, !layoutAwareScan, layoutAwareScan).seek(-length);
this.range.setStart(state.node, state.offset); this._range.setStart(state.node, state.offset);
this.rangeStartOffset = this.range.startOffset; this._rangeStartOffset = this._range.startOffset;
this.content = state.content + this.content; this._content = state.content + this._content;
return length - state.remainder; return length - state.remainder;
} }
getRect() { getRect() {
return this.range.getBoundingClientRect(); return this._range.getBoundingClientRect();
} }
getWritingMode() { getWritingMode() {
return TextSourceRange.getElementWritingMode(TextSourceRange.getParentElement(this.range.startContainer)); return TextSourceRange.getElementWritingMode(TextSourceRange.getParentElement(this._range.startContainer));
} }
select() { select() {
const selection = window.getSelection(); const selection = window.getSelection();
selection.removeAllRanges(); selection.removeAllRanges();
selection.addRange(this.range); selection.addRange(this._range);
} }
deselect() { deselect() {
@ -88,7 +93,7 @@ class TextSourceRange {
selection.removeAllRanges(); selection.removeAllRanges();
} }
equals(other) { hasSameStart(other) {
if (!( if (!(
typeof other === 'object' && typeof other === 'object' &&
other !== null && other !== null &&
@ -96,14 +101,14 @@ class TextSourceRange {
)) { )) {
return false; return false;
} }
if (this.imposterSourceElement !== null) { if (this._imposterSourceElement !== null) {
return ( return (
this.imposterSourceElement === other.imposterSourceElement && this._imposterSourceElement === other.imposterSourceElement &&
this.rangeStartOffset === other.rangeStartOffset this._rangeStartOffset === other.rangeStartOffset
); );
} else { } else {
try { try {
return this.range.compareBoundaryPoints(Range.START_TO_START, other.range) === 0; return this._range.compareBoundaryPoints(Range.START_TO_START, other.range) === 0;
} catch (e) { } catch (e) {
if (e.name === 'WrongDocumentError') { if (e.name === 'WrongDocumentError') {
// This can happen with shadow DOMs if the ranges are in different documents. // This can happen with shadow DOMs if the ranges are in different documents.
@ -114,6 +119,10 @@ class TextSourceRange {
} }
} }
getNodesInRange() {
return DocumentUtil.getNodesInRange(this._range);
}
static getParentElement(node) { static getParentElement(node) {
while (node !== null && node.nodeType !== Node.ELEMENT_NODE) { while (node !== null && node.nodeType !== Node.ELEMENT_NODE) {
node = node.parentNode; node = node.parentNode;

View File

@ -178,13 +178,12 @@ class TextScanner extends EventDispatcher {
clonedTextSource.setEndOffset(length, layoutAwareScan); clonedTextSource.setEndOffset(length, layoutAwareScan);
if (this._ignoreNodes !== null && clonedTextSource.range) { if (this._ignoreNodes !== null) {
length = clonedTextSource.text().length; length = clonedTextSource.text().length;
while (clonedTextSource.range && length > 0) { while (
const nodes = DocumentUtil.getNodesInRange(clonedTextSource.range); length > 0 &&
if (!DocumentUtil.anyNodeMatchesSelector(nodes, this._ignoreNodes)) { DocumentUtil.anyNodeMatchesSelector(clonedTextSource.getNodesInRange(), this._ignoreNodes)
break; ) {
}
--length; --length;
clonedTextSource.setEndOffset(length, layoutAwareScan); clonedTextSource.setEndOffset(length, layoutAwareScan);
} }
@ -247,7 +246,7 @@ class TextScanner extends EventDispatcher {
let optionsContext = null; let optionsContext = null;
try { try {
if (this._textSourceCurrent !== null && this._textSourceCurrent.equals(textSource)) { if (this._textSourceCurrent !== null && this._textSourceCurrent.hasSameStart(textSource)) {
return; return;
} }
@ -772,7 +771,7 @@ class TextScanner extends EventDispatcher {
if ( if (
this._textSourceCurrent !== null && this._textSourceCurrent !== null &&
!this._textSourceCurrent.equals(textSourceCurrentPrevious) !this._textSourceCurrent.hasSameStart(textSourceCurrentPrevious)
) { ) {
this._preventScroll = preventScroll; this._preventScroll = preventScroll;
this._preventNextContextMenu = true; this._preventNextContextMenu = true;