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/20 12:26:25 UTC
[incubator-annotator] 02/19: Make abstract TextPosition matcher
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 25d753a973aae0566c4bb6a3e47de521a379744e
Author: Gerben <ge...@treora.com>
AuthorDate: Mon Nov 16 22:55:15 2020 +0100
Make abstract TextPosition matcher
---
packages/dom/src/text-position/match.ts | 51 +++++++++++++++++++++++----------
packages/dom/src/text-quote/match.ts | 13 +++++----
2 files changed, 44 insertions(+), 20 deletions(-)
diff --git a/packages/dom/src/text-position/match.ts b/packages/dom/src/text-position/match.ts
index 7b9f1c5..985e278 100644
--- a/packages/dom/src/text-position/match.ts
+++ b/packages/dom/src/text-position/match.ts
@@ -20,32 +20,53 @@
import type { Matcher, TextPositionSelector } from '@annotator/selector';
import { ownerDocument } from '../owner-document';
-import { DomSeeker } from '../seek';
+import { TextSeeker, NonEmptyChunker } from '../seek';
import { CodePointSeeker } from '../code-point-seeker';
+import { Chunk, ChunkRange, TextNodeChunker, PartialTextNode } from '../chunker';
export function createTextPositionSelectorMatcher(
selector: TextPositionSelector,
): Matcher<Range, Range> {
+
+ const abstractMatcher: AbstractMatcher<PartialTextNode> =
+ abstractTextPositionSelectorMatcher(selector);
+
return async function* matchAll(scope) {
- const document = ownerDocument(scope);
+ const textChunks = new TextNodeChunker(scope);
- const { start, end } = selector;
+ if (textChunks.currentChunk === null)
+ throw new RangeError('Range does not contain any Text nodes.');
+ const matches = abstractMatcher(textChunks as NonEmptyChunker<PartialTextNode>);
- const codeUnitSeeker = new DomSeeker(scope);
- const codePointSeeker = new CodePointSeeker(codeUnitSeeker);
+ for await (const abstractMatch of matches) {
+ const match = ownerDocument(scope).createRange();
+ match.setStart(abstractMatch.startChunk.node, abstractMatch.startChunk.startOffset + abstractMatch.startIndex);
+ match.setEnd(abstractMatch.endChunk.node, abstractMatch.endChunk.startOffset + abstractMatch.endIndex);
+ yield match;
+ }
+ };
+}
- // Create a range to represent the described text in the dom.
- const match = document.createRange();
+type AbstractMatcher<TChunk extends Chunk<any>> =
+ Matcher<NonEmptyChunker<TChunk>, ChunkRange<TChunk>>
- // Seek to the start of the match, make the range start there.
- codePointSeeker.seekTo(start);
- match.setStart(codeUnitSeeker.referenceNode, codeUnitSeeker.offsetInReferenceNode);
+export function abstractTextPositionSelectorMatcher<TChunk extends Chunk<string>>(
+ selector: TextPositionSelector,
+): AbstractMatcher<TChunk> {
+
+ const { start, end } = selector;
+
+ return async function* matchAll<TChunk extends Chunk<string>>(textChunks: NonEmptyChunker<TChunk>) {
+ const codeUnitSeeker = new TextSeeker(textChunks);
+ const codePointSeeker = new CodePointSeeker(codeUnitSeeker);
- // Seek to the end of the match, make the range end there.
+ codePointSeeker.seekTo(start);
+ const startChunk = codeUnitSeeker.currentChunk;
+ const startIndex = codeUnitSeeker.offsetInChunk;
codePointSeeker.seekTo(end);
- match.setEnd(codeUnitSeeker.referenceNode, codeUnitSeeker.offsetInReferenceNode);
+ const endChunk = codeUnitSeeker.currentChunk;
+ const endIndex = codeUnitSeeker.offsetInChunk;
- // Yield the match.
- yield match;
- };
+ yield { startChunk, startIndex, endChunk, endIndex };
+ }
}
diff --git a/packages/dom/src/text-quote/match.ts b/packages/dom/src/text-quote/match.ts
index 5a4df52..f7c8da3 100644
--- a/packages/dom/src/text-quote/match.ts
+++ b/packages/dom/src/text-quote/match.ts
@@ -19,12 +19,15 @@
*/
import type { Matcher, TextQuoteSelector } from '@annotator/selector';
-import { TextNodeChunker, Chunk, Chunker, ChunkRange } from '../chunker';
+import { TextNodeChunker, Chunk, Chunker, ChunkRange, PartialTextNode } from '../chunker';
export function createTextQuoteSelectorMatcher(
selector: TextQuoteSelector,
): Matcher<Range, Range> {
- const abstractMatcher = abstractTextQuoteSelectorMatcher(selector);
+
+ const abstractMatcher: AbstractMatcher<PartialTextNode> =
+ abstractTextQuoteSelectorMatcher(selector);
+
return async function* matchAll(scope) {
const textChunks = new TextNodeChunker(scope);
@@ -41,12 +44,12 @@ export function createTextQuoteSelectorMatcher(
}
}
-type AbstractMatcher<TChunk extends Chunk<string>> =
+type AbstractMatcher<TChunk extends Chunk<any>> =
Matcher<Chunker<TChunk>, ChunkRange<TChunk>>
-export function abstractTextQuoteSelectorMatcher(
+export function abstractTextQuoteSelectorMatcher<TChunk extends Chunk<string>>(
selector: TextQuoteSelector,
-): AbstractMatcher<any> {
+): AbstractMatcher<TChunk> {
return async function* matchAll<TChunk extends Chunk<string>>(textChunks: Chunker<TChunk>) {
const exact = selector.exact;
const prefix = selector.prefix || '';