You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@annotator.apache.org by ge...@apache.org on 2020/10/13 20:59:39 UTC
[incubator-annotator] 04/05: Turn seek into Seeker class
This is an automated email from the ASF dual-hosted git repository.
gerben pushed a commit to branch import-dom-seek
in repository https://gitbox.apache.org/repos/asf/incubator-annotator.git
commit c442273f6eb527ae8fcd84ac8b9eaccabfcbff7a
Author: Gerben <ge...@treora.com>
AuthorDate: Fri Oct 9 22:07:56 2020 +0200
Turn seek into Seeker class
So it can just contain its NodeIterator.
---
packages/dom/src/seek.ts | 124 +++++++++++++++++---------------
packages/dom/src/text-position/match.ts | 23 ++----
packages/dom/src/text-quote/describe.ts | 19 ++---
packages/dom/src/text-quote/match.ts | 23 ++----
4 files changed, 81 insertions(+), 108 deletions(-)
diff --git a/packages/dom/src/seek.ts b/packages/dom/src/seek.ts
index 3a707ed..c8f77ad 100644
--- a/packages/dom/src/seek.ts
+++ b/packages/dom/src/seek.ts
@@ -1,75 +1,81 @@
-const E_END = 'Iterator exhausted before seek ended.';
-const E_SHOW = 'Argument 1 of seek must use filter NodeFilter.SHOW_TEXT.';
-const E_WHERE = 'Argument 2 of seek must be an integer or a Text Node.';
-
-const DOCUMENT_POSITION_PRECEDING = 2;
-const SHOW_TEXT = 4;
-const TEXT_NODE = 3;
-
-export default function seek(iter: NodeIterator, where: number | Text): number {
- if (iter.whatToShow !== SHOW_TEXT) {
- let error: Error & { code?: number };
-
- // istanbul ignore next
- try {
- error = new DOMException(E_SHOW, 'InvalidStateError');
- } catch {
- error = new Error(E_SHOW);
- error.code = 11;
- error.name = 'InvalidStateError';
- error.toString = () => `InvalidStateError: ${E_SHOW}`;
- }
+import { ownerDocument } from "./owner-document";
- throw error;
+const E_END = 'Iterator exhausted before seek ended.';
+const E_WHERE = 'Argument of seek must be an integer or a Text Node.';
+
+export class Seeker {
+ iter: NodeIterator;
+
+ constructor(scope: Range) {
+ const document = ownerDocument(scope);
+ this.iter = document.createNodeIterator(
+ scope.commonAncestorContainer,
+ NodeFilter.SHOW_TEXT,
+ {
+ acceptNode(node: Text) {
+ return scope.intersectsNode(node)
+ ? NodeFilter.FILTER_ACCEPT
+ : NodeFilter.FILTER_REJECT;
+ },
+ },
+ );
}
- let count = 0;
- let node: Node | null = iter.referenceNode;
- let predicates = null;
-
- if (isInteger(where)) {
- predicates = {
- forward: () => count < where,
- backward: () => count > where || !iter.pointerBeforeReferenceNode,
- };
- } else if (isText(where)) {
- predicates = {
- forward: before(node, where) ? () => false : () => node !== where,
- backward: () => node !== where || !iter.pointerBeforeReferenceNode,
- };
- } else {
- throw new TypeError(E_WHERE);
+ getCurrentNode() {
+ return this.iter.referenceNode;
}
- while (predicates.forward()) {
- node = iter.nextNode();
+ seek(where: number | Text): number {
+ const iter = this.iter;
+
+ let count = 0;
+ let node: Node | null = iter.referenceNode;
+ let predicates = null;
+
+ if (isInteger(where)) {
+ predicates = {
+ forward: () => count < where,
+ backward: () => count > where || !iter.pointerBeforeReferenceNode,
+ };
+ } else if (isText(where)) {
+ predicates = {
+ forward: before(node, where) ? () => false : () => node !== where,
+ backward: () => node !== where || !iter.pointerBeforeReferenceNode,
+ };
+ } else {
+ throw new TypeError(E_WHERE);
+ }
+
+ while (predicates.forward()) {
+ node = iter.nextNode();
- if (node === null) {
- throw new RangeError(E_END);
+ if (node === null) {
+ throw new RangeError(E_END);
+ }
+
+ count += (node as Text).data.length;
}
- count += (node as Text).data.length;
- }
+ if (iter.nextNode()) {
+ node = iter.previousNode();
+ }
- if (iter.nextNode()) {
- node = iter.previousNode();
- }
+ while (predicates.backward()) {
+ node = iter.previousNode();
- while (predicates.backward()) {
- node = iter.previousNode();
+ if (node === null) {
+ throw new RangeError(E_END);
+ }
- if (node === null) {
- throw new RangeError(E_END);
+ count -= (node as Text).data.length;
}
- count -= (node as Text).data.length;
- }
+ if (!isText(iter.referenceNode)) {
+ throw new RangeError(E_END);
+ }
- if (!isText(iter.referenceNode)) {
- throw new RangeError(E_END);
+ return count;
}
-
- return count;
}
function isInteger(n: any): n is number {
@@ -78,9 +84,9 @@ function isInteger(n: any): n is number {
}
function isText(node: Node): node is Text {
- return node.nodeType === TEXT_NODE;
+ return node.nodeType === Node.TEXT_NODE;
}
function before(ref: Node, node: Node): boolean {
- return !!(ref.compareDocumentPosition(node) & DOCUMENT_POSITION_PRECEDING);
+ return !!(ref.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_PRECEDING);
}
diff --git a/packages/dom/src/text-position/match.ts b/packages/dom/src/text-position/match.ts
index 00acd4c..7a57226 100644
--- a/packages/dom/src/text-position/match.ts
+++ b/packages/dom/src/text-position/match.ts
@@ -20,7 +20,7 @@
import type { Matcher, TextPositionSelector } from '@annotator/selector';
import { ownerDocument } from '../owner-document';
-import seek from '../seek';
+import { Seeker } from '../seek';
export function createTextPositionSelectorMatcher(
selector: TextPositionSelector,
@@ -31,18 +31,7 @@ export function createTextPositionSelectorMatcher(
const { start, end } = selector;
- const iter = document.createNodeIterator(
- scope.commonAncestorContainer,
- NodeFilter.SHOW_TEXT,
- {
- acceptNode(node: Text) {
- // Only reveal nodes within the range; and skip any empty text nodes.
- return scope.intersectsNode(node) && node.length > 0
- ? NodeFilter.FILTER_ACCEPT
- : NodeFilter.FILTER_REJECT;
- },
- },
- );
+ const seeker = new Seeker(scope);
// The index of the first character of iter.referenceNode inside the text.
let referenceNodeIndex = isTextNode(scope.startContainer)
@@ -57,12 +46,12 @@ export function createTextPositionSelectorMatcher(
const match = document.createRange();
// Seek to the start of the match, make the range start there.
- referenceNodeIndex += seek(iter, matchStartIndex - referenceNodeIndex);
- match.setStart(iter.referenceNode, matchStartIndex - referenceNodeIndex);
+ referenceNodeIndex += seeker.seek(matchStartIndex - referenceNodeIndex);
+ match.setStart(seeker.getCurrentNode(), matchStartIndex - referenceNodeIndex);
// Seek to the end of the match, make the range end there.
- referenceNodeIndex += seek(iter, matchEndIndex - referenceNodeIndex);
- match.setEnd(iter.referenceNode, matchEndIndex - referenceNodeIndex);
+ referenceNodeIndex += seeker.seek(matchEndIndex - referenceNodeIndex);
+ match.setEnd(seeker.getCurrentNode(), matchEndIndex - referenceNodeIndex);
// Yield the match.
yield match;
diff --git a/packages/dom/src/text-quote/describe.ts b/packages/dom/src/text-quote/describe.ts
index 514208b..e5846bc 100644
--- a/packages/dom/src/text-quote/describe.ts
+++ b/packages/dom/src/text-quote/describe.ts
@@ -20,7 +20,7 @@
import type { TextQuoteSelector } from '@annotator/selector';
import { ownerDocument } from '../owner-document';
-import seek from '../seek';
+import { Seeker } from '../seek';
export async function describeTextQuote(
range: Range,
@@ -120,22 +120,11 @@ function calculateContextForDisambiguation(
// Get the index of the first character of range within the text of scope.
function getRangeTextPosition(range: Range, scope: Range): number {
- const iter = ownerDocument(scope).createNodeIterator(
- scope.commonAncestorContainer,
- NodeFilter.SHOW_TEXT,
- {
- acceptNode(node: Text) {
- // Only reveal nodes within the range
- return scope.intersectsNode(node)
- ? NodeFilter.FILTER_ACCEPT
- : NodeFilter.FILTER_REJECT;
- },
- },
- );
+ const seeker = new Seeker(scope);
const scopeOffset = isTextNode(scope.startContainer) ? scope.startOffset : 0;
if (isTextNode(range.startContainer))
- return seek(iter, range.startContainer) + range.startOffset - scopeOffset;
- else return seek(iter, firstTextNodeInRange(range)) - scopeOffset;
+ return seeker.seek(range.startContainer) + range.startOffset - scopeOffset;
+ else return seeker.seek(firstTextNodeInRange(range)) - scopeOffset;
}
function firstTextNodeInRange(range: Range): Text {
diff --git a/packages/dom/src/text-quote/match.ts b/packages/dom/src/text-quote/match.ts
index c6b769b..6282769 100644
--- a/packages/dom/src/text-quote/match.ts
+++ b/packages/dom/src/text-quote/match.ts
@@ -20,7 +20,7 @@
import type { Matcher, TextQuoteSelector } from '@annotator/selector';
import { ownerDocument } from '../owner-document';
-import seek from '../seek';
+import { Seeker } from '../seek';
export function createTextQuoteSelectorMatcher(
selector: TextQuoteSelector,
@@ -34,18 +34,7 @@ export function createTextQuoteSelectorMatcher(
const suffix = selector.suffix || '';
const searchPattern = prefix + exact + suffix;
- const iter = document.createNodeIterator(
- scope.commonAncestorContainer,
- NodeFilter.SHOW_TEXT,
- {
- acceptNode(node: Text) {
- // Only reveal nodes within the range; and skip any empty text nodes.
- return scope.intersectsNode(node) && node.length > 0
- ? NodeFilter.FILTER_ACCEPT
- : NodeFilter.FILTER_REJECT;
- },
- },
- );
+ const seeker = new Seeker(scope);
// The index of the first character of iter.referenceNode inside the text.
let referenceNodeIndex = isTextNode(scope.startContainer)
@@ -66,12 +55,12 @@ export function createTextQuoteSelectorMatcher(
const match = document.createRange();
// Seek to the start of the match, make the range start there.
- referenceNodeIndex += seek(iter, matchStartIndex - referenceNodeIndex);
- match.setStart(iter.referenceNode, matchStartIndex - referenceNodeIndex);
+ referenceNodeIndex += seeker.seek(matchStartIndex - referenceNodeIndex);
+ match.setStart(seeker.getCurrentNode(), matchStartIndex - referenceNodeIndex);
// Seek to the end of the match, make the range end there.
- referenceNodeIndex += seek(iter, matchEndIndex - referenceNodeIndex);
- match.setEnd(iter.referenceNode, matchEndIndex - referenceNodeIndex);
+ referenceNodeIndex += seeker.seek(matchEndIndex - referenceNodeIndex);
+ match.setEnd(seeker.getCurrentNode(), matchEndIndex - referenceNodeIndex);
// Yield the match.
yield match;