This is an automated email from the ASF dual-hosted git repository.

gerben pushed a commit to branch improve-range-stuff
in repository https://gitbox.apache.org/repos/asf/incubator-annotator.git

commit 2be85b60f215851808a92ebabbbeaf3424b32cff
Author: Gerben <[email protected]>
AuthorDate: Thu Jun 25 23:40:54 2020 +0200

    WIP reimplement range iteration
---
 packages/dom/src/text-iterator.ts       | 64 +++++++++++++++++++++++++++++++++
 packages/dom/src/text-quote/describe.ts | 25 ++-----------
 2 files changed, 66 insertions(+), 23 deletions(-)

diff --git a/packages/dom/src/text-iterator.ts 
b/packages/dom/src/text-iterator.ts
new file mode 100644
index 0000000..53e8732
--- /dev/null
+++ b/packages/dom/src/text-iterator.ts
@@ -0,0 +1,64 @@
+/**
+ * @license
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+interface TextRange extends Range {
+  // We guarantee that to always have Text nodes as start and end containers.
+  readonly startContainer: Text;
+  readonly endContainer: Text;
+  cloneRange(): TextRange;
+
+  // Allow only Text nodes to be passed to these methods.
+  insertNode(node: Text): void;
+  selectNodeContents(node: Text): void;
+  setEnd(node: Text, offset: number): void;
+  setStart(node: Text, offset: number): void;
+
+  // Do not allow these methods to be used at all.
+  selectNode(node: never): void;
+  setEndAfter(node: never): void;
+  setEndBefore(node: never): void;
+  setStartAfter(node: never): void;
+  setStartBefore(node: never): void;
+  surroundContents(newParent: never): void;
+}
+
+function shrinkRangeToTextNodes(range: Range): TextRange {
+  // TODO walk to first & last text nodes inside the range.
+  return range as TextRange;
+}
+
+class TextIterator {
+  constructor(range: Range) {
+    const iter = document.createNodeIterator(
+      range.commonAncestorContainer,
+      NodeFilter.SHOW_TEXT,
+      {
+        acceptNode: node =>
+          range.intersectsNode(node)
+            ? NodeFilter.FILTER_ACCEPT
+            : NodeFilter.FILTER_REJECT
+      },
+    );
+
+    // Move to the start of the first text node (if any).
+    if (iter.nextNode())
+      iter.previousNode();
+  }
+}
diff --git a/packages/dom/src/text-quote/describe.ts 
b/packages/dom/src/text-quote/describe.ts
index 15749c9..0cc1760 100644
--- a/packages/dom/src/text-quote/describe.ts
+++ b/packages/dom/src/text-quote/describe.ts
@@ -148,29 +148,8 @@ function getRangeTextPosition(range: Range, scope: 
DomScope): number {
     },
   );
   const scopeOffset = isTextNode(scopeAsRange.startContainer) ? 
scopeAsRange.startOffset : 0;
-  if (isTextNode(range.startContainer))
-    return seek(iter, range.startContainer) + range.startOffset - scopeOffset;
-  else
-    return seek(iter, firstTextNodeInRange(range)) - scopeOffset;
-}
-
-function firstTextNodeInRange(range: Range): Text {
-  // Find the first text node inside the range.
-  const iter = document.createNodeIterator(
-    range.commonAncestorContainer,
-    NodeFilter.SHOW_TEXT,
-    {
-      acceptNode(node: Text) {
-        // Only reveal nodes within the range; and skip any empty text nodes.
-        return range.intersectsNode(node) && node.length > 0
-          ? NodeFilter.FILTER_ACCEPT
-          : NodeFilter.FILTER_REJECT
-      },
-    },
-  );
-  const node = iter.nextNode() as Text | null;
-  if (node === null) throw new Error('Range contains no text nodes');
-  return node;
+  const rangeOffset = isTextNode(range.startContainer) ? range.startOffset : 0;
+  return seek(iter, range.startContainer) + rangeOffset - scopeOffset;
 }
 
 function isTextNode(node: Node): node is Text {

Reply via email to