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/11/18 18:58:59 UTC

[incubator-annotator] branch import-dom-seek updated (645eb77 -> 2ec7100)

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

gerben pushed a change to branch import-dom-seek
in repository https://gitbox.apache.org/repos/asf/incubator-annotator.git.


    from 645eb77  Factor out chunkRangeToRange
     new 84ae601  Handle half-characters in CodePointSeeker.seekToChunk
     new d6a0be0  Make CodePointSeeker.seekToChunk count units, not points
     new ec53350  Create basic tests for describe text position
     new 2ec7100  Export describeTextPosition & use it in demo

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 packages/dom/src/code-point-seeker.ts            | 38 +++++++---------
 packages/dom/src/index.ts                        |  1 +
 packages/dom/test/text-position/describe.test.ts | 55 ++++++++++++++++++++++++
 web/demo/index.html                              |  9 ++++
 web/demo/index.js                                | 14 ++++--
 5 files changed, 92 insertions(+), 25 deletions(-)
 create mode 100644 packages/dom/test/text-position/describe.test.ts


[incubator-annotator] 02/04: Make CodePointSeeker.seekToChunk count units, not points

Posted by ge...@apache.org.
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 d6a0be00eee0901b9e423dace49341a94afd7098
Author: Gerben <ge...@treora.com>
AuthorDate: Wed Nov 18 18:57:38 2020 +0100

    Make CodePointSeeker.seekToChunk count units, not points
    
    We don’t actually ever want to count chunk offsets as code points. Note
    its (unused) offsetInChunk method also returns the number in code units.
    
    Ideally the caller would invoke the TextSeeker’s (= codeUnitSeeker’s)
    seekToChunk method. But, currently, doing so would not update the
    codePointSeeker’s position.
---
 packages/dom/src/code-point-seeker.ts | 23 ++---------------------
 1 file changed, 2 insertions(+), 21 deletions(-)

diff --git a/packages/dom/src/code-point-seeker.ts b/packages/dom/src/code-point-seeker.ts
index 10cb1b1..b97089e 100644
--- a/packages/dom/src/code-point-seeker.ts
+++ b/packages/dom/src/code-point-seeker.ts
@@ -61,10 +61,9 @@ export class CodePointSeeker<TChunk extends Chunk<string>> implements ChunkSeeke
   private _readOrSeekToChunk(read: true, target: TChunk, offset?: number): string[]
   private _readOrSeekToChunk(read: false, target: TChunk, offset?: number): void
   private _readOrSeekToChunk(read: boolean, target: TChunk, offset: number = 0) {
-    const oldPosition = this.position;
     const oldRawPosition = this.raw.position;
 
-    let s = this.raw.readToChunk(target, 0);
+    let s = this.raw.readToChunk(target, offset);
 
     const movedForward = this.raw.position >= oldRawPosition;
 
@@ -82,25 +81,7 @@ export class CodePointSeeker<TChunk extends Chunk<string>> implements ChunkSeeke
       ? this.position + result.length
       : this.position - result.length;
 
-    const targetPosition = this.position + offset;
-    if (!read) {
-      this.seekTo(targetPosition);
-    } else {
-      if (targetPosition >= this.position) {
-        // Read further until the target.
-        result = result.concat(this.readTo(targetPosition));
-      }
-      else if (targetPosition >= oldPosition) {
-        // We passed by our target position: step back.
-        this.seekTo(targetPosition);
-        result = result.slice(0, targetPosition - oldPosition);
-      } else {
-        // The target precedes our starting position: read backwards from there.
-        this.seekTo(oldPosition);
-        result = this.readTo(targetPosition);
-      }
-      return result;
-    }
+    if (read) return result;
   }
 
   private _readOrSeekTo(read: true, target: number, roundUp?: boolean): string[];


[incubator-annotator] 03/04: Create basic tests for describe text position

Posted by ge...@apache.org.
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 ec53350d56e55dbd67981d43ed2204d90080d40c
Author: Gerben <ge...@treora.com>
AuthorDate: Wed Nov 18 19:40:18 2020 +0100

    Create basic tests for describe text position
---
 packages/dom/test/text-position/describe.test.ts | 55 ++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/packages/dom/test/text-position/describe.test.ts b/packages/dom/test/text-position/describe.test.ts
new file mode 100644
index 0000000..2eefd38
--- /dev/null
+++ b/packages/dom/test/text-position/describe.test.ts
@@ -0,0 +1,55 @@
+/**
+ * @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.
+ */
+
+import { assert } from 'chai';
+import { describeTextPosition } from '../../src/text-position/describe';
+import { hydrateRange } from '../utils';
+import { testCases } from './match-cases';
+
+const domParser = new window.DOMParser();
+
+describe('createTextPositionSelectorMatcher', () => {
+  describe('inverts test cases of text position matcher', () => {
+    for (const [name, { html, selector, expected }] of Object.entries(
+      testCases,
+    )) {
+      const range = expected[0];
+      it(`case: '${name}'`, async () => {
+        const doc = domParser.parseFromString(html, 'text/html');
+        const scope = doc.createRange();
+        scope.selectNodeContents(doc);
+        const result = await describeTextPosition(hydrateRange(range, doc), scope);
+        assert.deepEqual(result, selector);
+      });
+    }
+  });
+
+  it('works with a scope', () => {
+    // TODO
+  });
+
+  it('works with split text nodes', () => {
+    // TODO
+  });
+
+  it('works with code points split across text nodes', () => {
+    // TODO
+  });
+});


[incubator-annotator] 01/04: Handle half-characters in CodePointSeeker.seekToChunk

Posted by ge...@apache.org.
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 84ae601a32ef278dc4660da6be5a91586950389b
Author: Gerben <ge...@treora.com>
AuthorDate: Wed Nov 18 18:55:18 2020 +0100

    Handle half-characters in CodePointSeeker.seekToChunk
---
 packages/dom/src/code-point-seeker.ts | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/packages/dom/src/code-point-seeker.ts b/packages/dom/src/code-point-seeker.ts
index b0a95cd..10cb1b1 100644
--- a/packages/dom/src/code-point-seeker.ts
+++ b/packages/dom/src/code-point-seeker.ts
@@ -64,8 +64,21 @@ export class CodePointSeeker<TChunk extends Chunk<string>> implements ChunkSeeke
     const oldPosition = this.position;
     const oldRawPosition = this.raw.position;
 
-    let result = [...this.raw.readToChunk(target, 0)];
-    this.position = this.raw.position >= oldRawPosition
+    let s = this.raw.readToChunk(target, 0);
+
+    const movedForward = this.raw.position >= oldRawPosition;
+
+    if (movedForward && endsWithinCharacter(s)) {
+      this.raw.seekBy(-1);
+      s = s.slice(0, -1);
+    } else if (!movedForward && startsWithinCharacter(s)) {
+      this.raw.seekBy(1);
+      s = s.slice(1);
+    }
+
+    let result = [...s];
+
+    this.position = movedForward
       ? this.position + result.length
       : this.position - result.length;
 
@@ -86,8 +99,8 @@ export class CodePointSeeker<TChunk extends Chunk<string>> implements ChunkSeeke
         this.seekTo(oldPosition);
         result = this.readTo(targetPosition);
       }
+      return result;
     }
-    return result;
   }
 
   private _readOrSeekTo(read: true, target: number, roundUp?: boolean): string[];


[incubator-annotator] 04/04: Export describeTextPosition & use it in demo

Posted by ge...@apache.org.
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 2ec7100003fdef3fbfb18ed25852535f8959f3d6
Author: Gerben <ge...@treora.com>
AuthorDate: Wed Nov 18 19:46:19 2020 +0100

    Export describeTextPosition & use it in demo
---
 packages/dom/src/index.ts |  1 +
 web/demo/index.html       |  9 +++++++++
 web/demo/index.js         | 14 +++++++++++---
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/packages/dom/src/index.ts b/packages/dom/src/index.ts
index 3d7ca58..cd7d2ea 100644
--- a/packages/dom/src/index.ts
+++ b/packages/dom/src/index.ts
@@ -21,4 +21,5 @@
 export * from './css';
 export * from './range';
 export * from './text-quote';
+export * from './text-position';
 export * from './highlight-range';
diff --git a/web/demo/index.html b/web/demo/index.html
index ad2d0a2..3ed0961 100644
--- a/web/demo/index.html
+++ b/web/demo/index.html
@@ -72,6 +72,15 @@ under the License.
           Upon a change of selection, a
           <a rel="external" href="https://www.w3.org/TR/2017/REC-annotation-model-20170223/#text-quote-selector" target="_blank">TextQuoteSelector</a>
           will be created, that describes what was selected.</p>
+          <form id="form">
+            The selector can work either
+            <br/>
+            <input type="radio" name="describeMode" value="TextQuote" id="describeModeTextQuote" checked>
+            <label for="describeModeTextQuote">by quoting the selected text</label>; or
+            </br>
+            <input type="radio" name="describeMode" value="TextPosition" id="describeModeTextPosition">
+            <label for="describeModeTextPosition">by counting the selected characters’ position in the text</label>.
+          </form>
       </div>
       <div class="column">
         <h2>Text is found here</h2>
diff --git a/web/demo/index.js b/web/demo/index.js
index cb96a40..842e074 100644
--- a/web/demo/index.js
+++ b/web/demo/index.js
@@ -18,12 +18,14 @@
  * under the License.
  */
 
-/* global info, module, source, target */
+/* global info, module, source, target, form */
 
 import {
   makeCreateRangeSelectorMatcher,
   createTextQuoteSelectorMatcher,
   describeTextQuote,
+  createTextPositionSelectorMatcher,
+  describeTextPosition,
   highlightRange,
 } from '@annotator/dom';
 import { makeRefinable } from '@annotator/selector';
@@ -88,13 +90,14 @@ function cleanup() {
   while ((removeHighlight = cleanupFunctions.shift())) {
     removeHighlight();
   }
-  target.normalize();
+  // target.normalize();
   info.innerText = '';
 }
 
 const createMatcher = makeRefinable((selector) => {
   const innerCreateMatcher = {
     TextQuoteSelector: createTextQuoteSelectorMatcher,
+    TextPositionSelector: createTextPositionSelectorMatcher,
     RangeSelector: makeCreateRangeSelectorMatcher(createMatcher),
   }[selector.type];
 
@@ -126,12 +129,16 @@ async function anchor(selector) {
 
 async function onSelectionChange() {
   cleanup();
+  const describeMode = form.describeMode.value;
   const scope = document.createRange();
   scope.selectNodeContents(source);
   const selection = document.getSelection();
   for (let i = 0; i < selection.rangeCount; i++) {
     const range = selection.getRangeAt(i);
-    const selector = await describeTextQuote(range, scope);
+    const selector =
+      describeMode === 'TextPosition'
+        ? await describeTextPosition(range, scope)
+        : await describeTextQuote(range, scope);
     await anchor(selector);
   }
 }
@@ -146,6 +153,7 @@ function onSelectorExampleClick(event) {
 }
 
 document.addEventListener('selectionchange', onSelectionChange);
+form.addEventListener('change', onSelectionChange);
 document.addEventListener('click', onSelectorExampleClick);
 
 if (module.hot) {