This is an automated email from the ASF dual-hosted git repository. randall pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-annotator.git
commit 35cc009c32e6b06bd700cf764802b37374b6e002 Author: Randall Leeds <[email protected]> AuthorDate: Wed Jul 22 23:46:45 2020 -0700 Apply automatic lint fixes --- @types/cartesian/index.d.ts | 4 +- @types/dom-seek/index.d.ts | 5 +- babel.config.js | 5 +- packages/dom/src/css.ts | 4 +- packages/dom/src/highlight-range.ts | 25 ++++----- packages/dom/src/range/cartesian.ts | 21 ++++---- packages/dom/src/range/match.ts | 7 +-- packages/dom/src/scope.ts | 6 +-- packages/dom/src/text-quote/describe.ts | 65 +++++++++++++++-------- packages/dom/src/text-quote/match.ts | 6 ++- packages/dom/src/types.ts | 4 +- packages/dom/test/range/cartesian.test.ts | 3 +- packages/dom/test/text-quote/describe-cases.ts | 10 ++-- packages/dom/test/text-quote/describe.test.ts | 30 ++++++++--- packages/dom/test/text-quote/match-cases.ts | 71 +++++++++++++++----------- packages/dom/test/text-quote/match.test.ts | 33 ++++++++---- packages/dom/test/text-quote/utils.ts | 37 ++++++++++---- packages/selector/src/index.ts | 10 ++-- packages/selector/src/types.ts | 22 ++++---- 19 files changed, 227 insertions(+), 141 deletions(-) diff --git a/@types/cartesian/index.d.ts b/@types/cartesian/index.d.ts index 9fc47e3..e7ad466 100644 --- a/@types/cartesian/index.d.ts +++ b/@types/cartesian/index.d.ts @@ -1,3 +1,5 @@ declare module 'cartesian' { - export default function cartesian<T>(list: Array<Array<T>> | { [k: string]: Array<T> }): Array<Array<T>>; + export default function cartesian<T>( + list: Array<Array<T>> | { [k: string]: Array<T> }, + ): Array<Array<T>>; } diff --git a/@types/dom-seek/index.d.ts b/@types/dom-seek/index.d.ts index 5bc1bc2..a8d9cd7 100644 --- a/@types/dom-seek/index.d.ts +++ b/@types/dom-seek/index.d.ts @@ -1,3 +1,6 @@ declare module 'dom-seek' { - export default function seek(iter: NodeIterator, where: number | Text): number; + export default function seek( + iter: NodeIterator, + where: number | Text, + ): number; } diff --git a/babel.config.js b/babel.config.js index 0c052cc..e020409 100644 --- a/babel.config.js +++ b/babel.config.js @@ -55,9 +55,6 @@ module.exports = api => { ...(DEV ? [['module-resolver', resolverOptions]] : []), ...(TEST ? ['istanbul'] : []), ], - presets: [ - ['@babel/env', envOptions], - '@babel/preset-typescript', - ], + presets: [['@babel/env', envOptions], '@babel/preset-typescript'], }; }; diff --git a/packages/dom/src/css.ts b/packages/dom/src/css.ts index 124dd01..b6b212d 100644 --- a/packages/dom/src/css.ts +++ b/packages/dom/src/css.ts @@ -20,7 +20,9 @@ import { CssSelector, Matcher } from '@annotator/selector'; -export function createCssSelectorMatcher(selector: CssSelector): Matcher<Document, Element> { +export function createCssSelectorMatcher( + selector: CssSelector, +): Matcher<Document, Element> { return async function* matchAll(scope: Document) { yield* scope.querySelectorAll(selector.value); }; diff --git a/packages/dom/src/highlight-range.ts b/packages/dom/src/highlight-range.ts index e18a6a4..922da67 100644 --- a/packages/dom/src/highlight-range.ts +++ b/packages/dom/src/highlight-range.ts @@ -30,8 +30,8 @@ // - attributes: an Object defining any attributes to be set on the wrapper elements. export function highlightRange( range: Range, - tagName: string = 'mark', - attributes: Record<string, string> = {} + tagName = 'mark', + attributes: Record<string, string> = {}, ): () => void { // First put all nodes in an array (splits start and end nodes if needed) const nodes = textNodesInRange(range); @@ -59,10 +59,7 @@ function textNodesInRange(range: Range): Text[] { if (range.collapsed) return []; // If the start or end node is a text node and only partly in the range, split it. - if ( - isTextNode(range.startContainer) && - range.startOffset > 0 - ) { + if (isTextNode(range.startContainer) && range.startOffset > 0) { const endOffset = range.endOffset; // (this may get lost when the splitting the node) const createdNode = range.startContainer.splitText(range.startOffset); if (range.endContainer === range.startContainer) { @@ -79,7 +76,8 @@ function textNodesInRange(range: Range): Text[] { } // Collect the text nodes. - const document = range.startContainer.ownerDocument || range.startContainer as Document; + const document = + range.startContainer.ownerDocument || (range.startContainer as Document); const walker = document.createTreeWalker( range.commonAncestorContainer, NodeFilter.SHOW_TEXT, @@ -87,7 +85,7 @@ function textNodesInRange(range: Range): Text[] { acceptNode: node => range.intersectsNode(node) ? NodeFilter.FILTER_ACCEPT - : NodeFilter.FILTER_REJECT + : NodeFilter.FILTER_REJECT, }, ); walker.currentNode = range.startContainer; @@ -107,15 +105,18 @@ function textNodesInRange(range: Range): Text[] { // } const nodes: Text[] = []; - if (isTextNode(walker.currentNode)) - nodes.push(walker.currentNode); + if (isTextNode(walker.currentNode)) nodes.push(walker.currentNode); while (walker.nextNode() && range.comparePoint(walker.currentNode, 0) !== 1) nodes.push(walker.currentNode as Text); return nodes; } // Replace [node] with <tagName ...attributes>[node]</tagName> -function wrapNodeInHighlight(node: ChildNode, tagName: string, attributes: Record<string, string>): HTMLElement { +function wrapNodeInHighlight( + node: ChildNode, + tagName: string, + attributes: Record<string, string>, +): HTMLElement { const document = node.ownerDocument as Document; const highlightElement = document.createElement(tagName); Object.keys(attributes).forEach(key => { @@ -149,5 +150,5 @@ function removeHighlight(highlightElement: HTMLElement) { } function isTextNode(node: Node): node is Text { - return node.nodeType === Node.TEXT_NODE + return node.nodeType === Node.TEXT_NODE; } diff --git a/packages/dom/src/range/cartesian.ts b/packages/dom/src/range/cartesian.ts index 256e313..439cd8b 100644 --- a/packages/dom/src/range/cartesian.ts +++ b/packages/dom/src/range/cartesian.ts @@ -20,7 +20,9 @@ import cartesianArrays from 'cartesian'; -export async function* product<T>(...iterables: AsyncIterable<T>[]): AsyncGenerator<Array<T>, void, undefined> { +export async function* product<T>( + ...iterables: AsyncIterable<T>[] +): AsyncGenerator<Array<T>, void, undefined> { // We listen to all iterators in parallel, while logging all the values they // produce. Whenever an iterator produces a value, we produce and yield all // combinations of that value with the logged values from other iterators. @@ -31,18 +33,19 @@ export async function* product<T>(...iterables: AsyncIterable<T>[]): AsyncGenera const logs: T[][] = iterables.map(() => []); type NumberedResultPromise = Promise<{ - nextResult: IteratorResult<T>, - iterableNr: number + nextResult: IteratorResult<T>; + iterableNr: number; }>; - function notNull(p: NumberedResultPromise | null): p is NumberedResultPromise { - return p !== null + function notNull( + p: NumberedResultPromise | null, + ): p is NumberedResultPromise { + return p !== null; } - const nextValuePromises: Array<NumberedResultPromise | null> = iterators.map((iterator, iterableNr) => - iterator - .next() - .then( + const nextValuePromises: Array<NumberedResultPromise | null> = iterators.map( + (iterator, iterableNr) => + iterator.next().then( // Label the result with iterableNr, to know which iterable produced // this value after Promise.race below. nextResult => ({ nextResult, iterableNr }), diff --git a/packages/dom/src/range/match.ts b/packages/dom/src/range/match.ts index 2e30af9..9cfe529 100644 --- a/packages/dom/src/range/match.ts +++ b/packages/dom/src/range/match.ts @@ -21,11 +21,12 @@ import { RangeSelector, Selector } from '@annotator/selector'; import { ownerDocument } from '../scope'; -import { product } from './cartesian'; import { DomMatcher, DomScope } from '../types'; +import { product } from './cartesian'; + export function makeCreateRangeSelectorMatcher( - createMatcher: <T extends Selector>(selector: T) => DomMatcher + createMatcher: <T extends Selector>(selector: T) => DomMatcher, ): (selector: RangeSelector) => DomMatcher { return function createRangeSelectorMatcher(selector: RangeSelector) { const startMatcher = createMatcher(selector.startSelector); @@ -39,7 +40,7 @@ export function makeCreateRangeSelectorMatcher( const pairs = product(startMatches, endMatches); - for await (let [start, end] of pairs) { + for await (const [start, end] of pairs) { const result = document.createRange(); result.setStart(start.endContainer, start.endOffset); diff --git a/packages/dom/src/scope.ts b/packages/dom/src/scope.ts index e7aec59..816bb03 100644 --- a/packages/dom/src/scope.ts +++ b/packages/dom/src/scope.ts @@ -21,10 +21,8 @@ import { DomScope } from './types'; export function ownerDocument(scope: DomScope): Document { - const node = isRange(scope) - ? scope.commonAncestorContainer - : scope; - return node.ownerDocument || node as Document; + const node = isRange(scope) ? scope.commonAncestorContainer : scope; + return node.ownerDocument || (node as Document); } export function rangeFromScope(scope: DomScope): Range { diff --git a/packages/dom/src/text-quote/describe.ts b/packages/dom/src/text-quote/describe.ts index eebd86d..d690013 100644 --- a/packages/dom/src/text-quote/describe.ts +++ b/packages/dom/src/text-quote/describe.ts @@ -41,18 +41,22 @@ export async function describeTextQuote( const result: TextQuoteSelector = { type: 'TextQuoteSelector', exact }; - const { prefix, suffix } = calculateContextForDisambiguation(range, result, scope); + const { prefix, suffix } = calculateContextForDisambiguation( + range, + result, + scope, + ); result.prefix = prefix; result.suffix = suffix; - return result + return result; } function calculateContextForDisambiguation( range: Range, selector: TextQuoteSelector, scope: DomScope, -): { prefix?: string, suffix?: string } { +): { prefix?: string; suffix?: string } { const exactText = selector.exact; const scopeText = rangeFromScope(scope).toString(); const targetStartIndex = getRangeTextPosition(range, scope); @@ -72,11 +76,10 @@ function calculateContextForDisambiguation( // would have invalidated the match. const affixLengthPairs: Array<[number, number]> = []; for (const matchStartIndex of stringMatches) { - const matchEndIndex = matchStartIndex + exactText.length + const matchEndIndex = matchStartIndex + exactText.length; // Skip the found match if it is the actual target. - if (matchStartIndex === targetStartIndex) - continue; + if (matchStartIndex === targetStartIndex) continue; // Count how many characters before & after them the false match and target have in common. const sufficientPrefixLength = charactersNeededToBeUnique( @@ -95,29 +98,46 @@ function calculateContextForDisambiguation( // Find the prefix and suffix that would invalidate all mismatches, using the minimal characters // for prefix and suffix combined. const [prefixLength, suffixLength] = minimalSolution(affixLengthPairs); - const prefix = scopeText.substring(targetStartIndex - prefixLength, targetStartIndex); - const suffix = scopeText.substring(targetEndIndex, targetEndIndex + suffixLength); + const prefix = scopeText.substring( + targetStartIndex - prefixLength, + targetStartIndex, + ); + const suffix = scopeText.substring( + targetEndIndex, + targetEndIndex + suffixLength, + ); return { prefix, suffix }; } -function charactersNeededToBeUnique(target: string, impostor: string, reverse: boolean = false) { +function charactersNeededToBeUnique( + target: string, + impostor: string, + reverse = false, +) { // Count how many characters the two strings have in common. let overlap = 0; - const charAt = (s: string, i: number) => reverse ? s[s.length - 1 - i] : s[overlap]; - while (overlap < target.length && charAt(target, overlap) === charAt(impostor, overlap)) + const charAt = (s: string, i: number) => + reverse ? s[s.length - 1 - i] : s[overlap]; + while ( + overlap < target.length && + charAt(target, overlap) === charAt(impostor, overlap) + ) overlap++; - if (overlap === target.length) - return Infinity; // (no substring of target can make it distinguishable from its impostor) - else - return overlap + 1; + if (overlap === target.length) return Infinity; + // (no substring of target can make it distinguishable from its impostor) + else return overlap + 1; } -function minimalSolution(requirements: Array<[number, number]>): [number, number] { +function minimalSolution( + requirements: Array<[number, number]>, +): [number, number] { // Ensure we try solutions with an empty prefix or suffix. requirements.push([0, 0]); // Build all the pairs and order them by their sums. - const pairs = requirements.flatMap(l => requirements.map<[number, number]>(r => [l[0], r[1]])); + const pairs = requirements.flatMap(l => + requirements.map<[number, number]>(r => [l[0], r[1]]), + ); pairs.sort((a, b) => a[0] + a[1] - (b[0] + b[1])); // Find the first pair that satisfies every requirement. @@ -143,15 +163,16 @@ function getRangeTextPosition(range: Range, scope: DomScope): number { // Only reveal nodes within the range return scopeAsRange.intersectsNode(node) ? NodeFilter.FILTER_ACCEPT - : NodeFilter.FILTER_REJECT + : NodeFilter.FILTER_REJECT; }, }, ); - const scopeOffset = isTextNode(scopeAsRange.startContainer) ? scopeAsRange.startOffset : 0; + 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; + else return seek(iter, firstTextNodeInRange(range)) - scopeOffset; } function firstTextNodeInRange(range: Range): Text { @@ -164,7 +185,7 @@ function firstTextNodeInRange(range: Range): 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 + : NodeFilter.FILTER_REJECT; }, }, ); diff --git a/packages/dom/src/text-quote/match.ts b/packages/dom/src/text-quote/match.ts index 04bb8a6..ed4d46d 100644 --- a/packages/dom/src/text-quote/match.ts +++ b/packages/dom/src/text-quote/match.ts @@ -24,7 +24,9 @@ import seek from 'dom-seek'; import { DomScope, DomMatcher } from '../types'; import { ownerDocument, rangeFromScope } from '../scope'; -export function createTextQuoteSelectorMatcher(selector: TextQuoteSelector): DomMatcher { +export function createTextQuoteSelectorMatcher( + selector: TextQuoteSelector, +): DomMatcher { return async function* matchAll(scope: DomScope) { const document = ownerDocument(scope); const scopeAsRange = rangeFromScope(scope); @@ -43,7 +45,7 @@ export function createTextQuoteSelectorMatcher(selector: TextQuoteSelector): Dom // Only reveal nodes within the range; and skip any empty text nodes. return scopeAsRange.intersectsNode(node) && node.length > 0 ? NodeFilter.FILTER_ACCEPT - : NodeFilter.FILTER_REJECT + : NodeFilter.FILTER_REJECT; }, }, ); diff --git a/packages/dom/src/types.ts b/packages/dom/src/types.ts index bc9636e..ae16c07 100644 --- a/packages/dom/src/types.ts +++ b/packages/dom/src/types.ts @@ -20,6 +20,6 @@ import { Matcher } from '@annotator/selector'; -export type DomScope = Node | Range +export type DomScope = Node | Range; -export type DomMatcher = Matcher<DomScope, Range> +export type DomMatcher = Matcher<DomScope, Range>; diff --git a/packages/dom/test/range/cartesian.test.ts b/packages/dom/test/range/cartesian.test.ts index 5fd854b..937b402 100644 --- a/packages/dom/test/range/cartesian.test.ts +++ b/packages/dom/test/range/cartesian.test.ts @@ -19,6 +19,7 @@ */ import { assert } from 'chai'; + import { product } from '../../src/range/cartesian'; async function* gen1() { @@ -51,7 +52,7 @@ describe('cartesian', () => { ]; const result: number[][] = []; - for await (let value of cart) { + for await (const value of cart) { result.push(value); } diff --git a/packages/dom/test/text-quote/describe-cases.ts b/packages/dom/test/text-quote/describe-cases.ts index 8010b46..6e38aad 100644 --- a/packages/dom/test/text-quote/describe-cases.ts +++ b/packages/dom/test/text-quote/describe-cases.ts @@ -24,12 +24,12 @@ import { RangeInfo } from './utils'; const testCases: { [name: string]: { - html: string, - range: RangeInfo, - expected: TextQuoteSelector, - } + html: string; + range: RangeInfo; + expected: TextQuoteSelector; + }; } = { - 'simple': { + simple: { html: '<b>lorem ipsum dolor amet yada yada</b>', range: { startContainerXPath: '//b/text()', diff --git a/packages/dom/test/text-quote/describe.test.ts b/packages/dom/test/text-quote/describe.test.ts index f962157..47e9d68 100644 --- a/packages/dom/test/text-quote/describe.test.ts +++ b/packages/dom/test/text-quote/describe.test.ts @@ -19,7 +19,9 @@ */ import { assert } from 'chai'; + import { describeTextQuote } from '../../src/text-quote/describe'; + import testCases from './describe-cases'; import testMatchCases from './match-cases'; import { hydrateRange, evaluateXPath } from './utils'; @@ -32,7 +34,7 @@ describe('describeTextQuote', () => { const doc = domParser.parseFromString(html, 'text/html'); const result = await describeTextQuote(hydrateRange(range, doc), doc); assert.deepEqual(result, expected); - }) + }); } it('works with custom scope', async () => { @@ -68,13 +70,17 @@ describe('describeTextQuote', () => { it('works if the range equals the scope', async () => { const { html, range, expected } = testCases['simple']; const doc = domParser.parseFromString(html, 'text/html'); - const result = await describeTextQuote(hydrateRange(range, doc), hydrateRange(range, doc)); + const result = await describeTextQuote( + hydrateRange(range, doc), + hydrateRange(range, doc), + ); assert.deepEqual(result, expected); }); describe('inverts test cases of text quote matcher', () => { - const applicableTestCases = Object.entries(testMatchCases) - .filter(([_, { expected }]) => expected.length > 0); + const applicableTestCases = Object.entries(testMatchCases).filter( + ([_, { expected }]) => expected.length > 0, + ); for (const [name, { html, selector, expected }] of applicableTestCases) { it(`case: '${name}'`, async () => { @@ -85,9 +91,21 @@ describe('describeTextQuote', () => { assert.equal(result.exact, selector.exact); // Our result may have a different combination of prefix/suffix; only check for obvious inconsistency. if (selector.prefix && result.prefix) - assert(selector.prefix.endsWith(result.prefix.substring(result.prefix.length - selector.prefix.length)), 'Inconsistent prefixes'); + assert( + selector.prefix.endsWith( + result.prefix.substring( + result.prefix.length - selector.prefix.length, + ), + ), + 'Inconsistent prefixes', + ); if (selector.suffix && result.suffix) - assert(selector.suffix.startsWith(result.suffix.substring(0, selector.suffix.length)), 'Inconsistent suffixes'); + assert( + selector.suffix.startsWith( + result.suffix.substring(0, selector.suffix.length), + ), + 'Inconsistent suffixes', + ); } }); } diff --git a/packages/dom/test/text-quote/match-cases.ts b/packages/dom/test/text-quote/match-cases.ts index 9ea434b..4f23c82 100644 --- a/packages/dom/test/text-quote/match-cases.ts +++ b/packages/dom/test/text-quote/match-cases.ts @@ -24,12 +24,12 @@ import { RangeInfo } from './utils'; const testCases: { [name: string]: { - html: string, - selector: TextQuoteSelector, - expected: RangeInfo[], - } + html: string; + selector: TextQuoteSelector; + expected: RangeInfo[]; + }; } = { - 'simple': { + simple: { html: '<b>lorem ipsum dolor amet yada yada</b>', selector: { type: 'TextQuoteSelector', @@ -105,7 +105,8 @@ const testCases: { ], }, 'text inside <head>': { - html: '<head><title>The title</title></head><b>lorem ipsum dolor amet yada yada</b>', + html: + '<head><title>The title</title></head><b>lorem ipsum dolor amet yada yada</b>', selector: { type: 'TextQuoteSelector', exact: 'title', @@ -292,12 +293,14 @@ const testCases: { exact: '', }, // A five character string contains six spots to find an empty string - expected: Array(6).fill(null).map((_, i) => ({ - startContainerXPath: '//b/text()', - startOffset: i, - endContainerXPath: '//b/text()', - endOffset: i, - })) + expected: Array(6) + .fill(null) + .map((_, i) => ({ + startContainerXPath: '//b/text()', + startOffset: i, + endContainerXPath: '//b/text()', + endOffset: i, + })), }, 'empty quote, with prefix': { html: '<b>lorem ipsum dolor amet yada yada</b>', @@ -306,12 +309,14 @@ const testCases: { exact: '', prefix: 'dolor', }, - expected: [{ - startContainerXPath: '//b/text()', - startOffset: 17, - endContainerXPath: '//b/text()', - endOffset: 17, - }] + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 17, + endContainerXPath: '//b/text()', + endOffset: 17, + }, + ], }, 'empty quote, with suffix': { html: '<b>lorem ipsum dolor amet yada yada</b>', @@ -320,12 +325,14 @@ const testCases: { exact: '', suffix: 'i', }, - expected: [{ - startContainerXPath: '//b/text()', - startOffset: 6, - endContainerXPath: '//b/text()', - endOffset: 6, - }] + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 6, + endContainerXPath: '//b/text()', + endOffset: 6, + }, + ], }, 'empty quote, with prefix and suffix': { html: '<b>lorem ipsum dolor amet yada yada</b>', @@ -335,12 +342,14 @@ const testCases: { prefix: 'lorem ', suffix: 'ipsum', }, - expected: [{ - startContainerXPath: '//b/text()', - startOffset: 6, - endContainerXPath: '//b/text()', - endOffset: 6, - }] + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 6, + endContainerXPath: '//b/text()', + endOffset: 6, + }, + ], }, 'empty quote, no matches': { html: '<b>lorem ipsum dolor amet yada yada</b>', @@ -350,7 +359,7 @@ const testCases: { prefix: 'X', }, expected: [], - } + }, }; export default testCases; diff --git a/packages/dom/test/text-quote/match.test.ts b/packages/dom/test/text-quote/match.test.ts index 6ea5563..5fea7a3 100644 --- a/packages/dom/test/text-quote/match.test.ts +++ b/packages/dom/test/text-quote/match.test.ts @@ -23,13 +23,16 @@ import { TextQuoteSelector } from '@annotator/selector'; import { createTextQuoteSelectorMatcher } from '../../src/text-quote/match'; import { DomScope } from '../../src/types'; + import testCases from './match-cases'; import { evaluateXPath, RangeInfo } from './utils'; const domParser = new window.DOMParser(); describe('createTextQuoteSelectorMatcher', () => { - for (const [name, { html, selector, expected }] of Object.entries(testCases)) { + for (const [name, { html, selector, expected }] of Object.entries( + testCases, + )) { it(`works for case: '${name}'`, async () => { const doc = domParser.parseFromString(html, 'text/html'); await testMatcher(doc, doc, selector, expected); @@ -182,21 +185,29 @@ async function testMatcher( ) { const matcher = createTextQuoteSelectorMatcher(selector); const matches = []; - for await (const value of matcher(scope)) - matches.push(value); + for await (const value of matcher(scope)) matches.push(value); assert.equal(matches.length, expected.length); matches.forEach((match, i) => { const expectedRange = expected[i]; - const expectedStartContainer = evaluateXPath(doc, expectedRange.startContainerXPath); - const expectedEndContainer = evaluateXPath(doc, expectedRange.endContainerXPath); - assert(match.startContainer === expectedStartContainer, - `unexpected start container: ${prettyNodeName(match.startContainer)}; ` - + `expected ${prettyNodeName(expectedStartContainer)}` + const expectedStartContainer = evaluateXPath( + doc, + expectedRange.startContainerXPath, + ); + const expectedEndContainer = evaluateXPath( + doc, + expectedRange.endContainerXPath, + ); + assert( + match.startContainer === expectedStartContainer, + `unexpected start container: ${prettyNodeName(match.startContainer)}; ` + + `expected ${prettyNodeName(expectedStartContainer)}`, ); assert.equal(match.startOffset, expectedRange.startOffset); - assert(match.endContainer === evaluateXPath(doc, expectedRange.endContainerXPath), - `unexpected end container: ${prettyNodeName(match.endContainer)}; ` - + `expected ${prettyNodeName(expectedEndContainer)}` + assert( + match.endContainer === + evaluateXPath(doc, expectedRange.endContainerXPath), + `unexpected end container: ${prettyNodeName(match.endContainer)}; ` + + `expected ${prettyNodeName(expectedEndContainer)}`, ); assert.equal(match.endOffset, expectedRange.endOffset); }); diff --git a/packages/dom/test/text-quote/utils.ts b/packages/dom/test/text-quote/utils.ts index 511a89c..9a484a9 100644 --- a/packages/dom/test/text-quote/utils.ts +++ b/packages/dom/test/text-quote/utils.ts @@ -18,28 +18,43 @@ * under the License. */ -import { assert } from "chai"; +import { assert } from 'chai'; // RangeInfo serialises a Range’s start and end containers as XPaths. export type RangeInfo = { - startContainerXPath: string, - startOffset: number, - endContainerXPath: string, - endOffset: number, + startContainerXPath: string; + startOffset: number; + endContainerXPath: string; + endOffset: number; }; export function evaluateXPath(doc: Document, xpath: string): Node { - const result = doc.evaluate(xpath, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - const nodes = new Array(result.snapshotLength).fill(undefined).map((_, i) => result.snapshotItem(i)); - assert.equal(nodes.length, 1, - `Test suite contains XPath with ${nodes.length} results instead of 1: '${xpath}'` + const result = doc.evaluate( + xpath, + doc, + null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, + ); + const nodes = new Array(result.snapshotLength) + .fill(undefined) + .map((_, i) => result.snapshotItem(i)); + assert.equal( + nodes.length, + 1, + `Test suite contains XPath with ${nodes.length} results instead of 1: '${xpath}'`, ); return nodes[0] as Node; } export function hydrateRange(rangeInfo: RangeInfo, doc: Document): Range { const range = doc.createRange(); - range.setStart(evaluateXPath(doc, rangeInfo.startContainerXPath), rangeInfo.startOffset); - range.setEnd(evaluateXPath(doc, rangeInfo.endContainerXPath), rangeInfo.endOffset); + range.setStart( + evaluateXPath(doc, rangeInfo.startContainerXPath), + rangeInfo.startOffset, + ); + range.setEnd( + evaluateXPath(doc, rangeInfo.endContainerXPath), + rangeInfo.endOffset, + ); return range; } diff --git a/packages/selector/src/index.ts b/packages/selector/src/index.ts index 8135f6e..b0bf9af 100644 --- a/packages/selector/src/index.ts +++ b/packages/selector/src/index.ts @@ -25,21 +25,23 @@ export * from './types'; export function makeRefinable< // Any subtype of Selector can be made refinable; but note we limit the value // of refinedBy because it must also be accepted by matcherCreator. - TSelector extends (Selector & { refinedBy: TSelector }), + TSelector extends Selector & { refinedBy: TSelector }, TScope, // To enable refinement, the implementation’s Match object must be usable as a // Scope object itself. - TMatch extends TScope, + TMatch extends TScope >( matcherCreator: (selector: TSelector) => Matcher<TScope, TMatch>, ): (selector: TSelector) => Matcher<TScope, TMatch> { return function createMatcherWithRefinement( - sourceSelector: TSelector + sourceSelector: TSelector, ): Matcher<TScope, TMatch> { const matcher = matcherCreator(sourceSelector); if (sourceSelector.refinedBy) { - const refiningSelector = createMatcherWithRefinement(sourceSelector.refinedBy); + const refiningSelector = createMatcherWithRefinement( + sourceSelector.refinedBy, + ); return async function* matchAll(scope) { for await (const match of matcher(scope)) { diff --git a/packages/selector/src/types.ts b/packages/selector/src/types.ts index bf7c9d0..fc4f64b 100644 --- a/packages/selector/src/types.ts +++ b/packages/selector/src/types.ts @@ -19,27 +19,27 @@ */ export interface Selector { - refinedBy?: Selector, + refinedBy?: Selector; } export interface CssSelector extends Selector { - type: 'CssSelector', - value: string, + type: 'CssSelector'; + value: string; } export interface TextQuoteSelector extends Selector { - type: 'TextQuoteSelector', - exact: string, - prefix?: string, - suffix?: string, + type: 'TextQuoteSelector'; + exact: string; + prefix?: string; + suffix?: string; } export interface RangeSelector extends Selector { - type: 'RangeSelector', - startSelector: Selector, - endSelector: Selector, + type: 'RangeSelector'; + startSelector: Selector; + endSelector: Selector; } export interface Matcher<TScope, TMatch> { - (scope: TScope): AsyncGenerator<TMatch, void, void>, + (scope: TScope): AsyncGenerator<TMatch, void, void>; }
