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 <[email protected]> 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 || '';
