Commit d883b0b0 authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Migrate html module to TS

parent 5744d55a
import type {
RangeSelector,
Selector,
TextPositionSelector,
TextQuoteSelector,
} from '../../types/api';
import { RangeAnchor, TextPositionAnchor, TextQuoteAnchor } from './types'; import { RangeAnchor, TextPositionAnchor, TextQuoteAnchor } from './types';
/** type Options = {
* @typedef {import('../../types/api').RangeSelector} RangeSelector hint?: number;
* @typedef {import('../../types/api').Selector} Selector };
* @typedef {import('../../types/api').TextPositionSelector} TextPositionSelector
* @typedef {import('../../types/api').TextQuoteSelector} TextQuoteSelector
*/
/** async function querySelector(
* @param {RangeAnchor|TextPositionAnchor|TextQuoteAnchor} anchor anchor: RangeAnchor | TextPositionAnchor | TextQuoteAnchor,
* @param {object} [options] options: Options
* @param {number} [options.hint] ) {
*/
async function querySelector(anchor, options = {}) {
return anchor.toRange(options); return anchor.toRange(options);
} }
...@@ -23,18 +25,20 @@ async function querySelector(anchor, options = {}) { ...@@ -23,18 +25,20 @@ async function querySelector(anchor, options = {}) {
* It encapsulates the core anchoring algorithm, using the selectors alone or * It encapsulates the core anchoring algorithm, using the selectors alone or
* in combination to establish the best anchor within the document. * in combination to establish the best anchor within the document.
* *
* @param {Element} root - The root element of the anchoring context. * @param root - The root element of the anchoring context
* @param {Selector[]} selectors - The selectors to try. * @param selectors - The selectors to try
* @param {object} [options]
* @param {number} [options.hint]
*/ */
export function anchor(root, selectors, options = {}) { export function anchor(
let position = /** @type {TextPositionSelector|null} */ (null); root: Element,
let quote = /** @type {TextQuoteSelector|null} */ (null); selectors: Selector[],
let range = /** @type {RangeSelector|null} */ (null); options: Options = {}
) {
let position: TextPositionSelector | null = null;
let quote: TextQuoteSelector | null = null;
let range: RangeSelector | null = null;
// Collect all the selectors // Collect all the selectors
for (let selector of selectors) { for (const selector of selectors) {
switch (selector.type) { switch (selector.type) {
case 'TextPositionSelector': case 'TextPositionSelector':
position = selector; position = selector;
...@@ -51,9 +55,8 @@ export function anchor(root, selectors, options = {}) { ...@@ -51,9 +55,8 @@ export function anchor(root, selectors, options = {}) {
/** /**
* Assert the quote matches the stored quote, if applicable * Assert the quote matches the stored quote, if applicable
* @param {Range} range
*/ */
const maybeAssertQuote = range => { const maybeAssertQuote = (range: Range) => {
if (quote?.exact && range.toString() !== quote.exact) { if (quote?.exact && range.toString() !== quote.exact) {
throw new Error('quote mismatch'); throw new Error('quote mismatch');
} else { } else {
...@@ -63,14 +66,13 @@ export function anchor(root, selectors, options = {}) { ...@@ -63,14 +66,13 @@ export function anchor(root, selectors, options = {}) {
// From a default of failure, we build up catch clauses to try selectors in // From a default of failure, we build up catch clauses to try selectors in
// order, from simple to complex. // order, from simple to complex.
/** @type {Promise<Range>} */ let promise: Promise<Range> = Promise.reject('unable to anchor');
let promise = Promise.reject('unable to anchor');
if (range) { if (range) {
// Const binding assures TS that it won't be re-assigned when callback runs. // Const binding assures TS that it won't be re-assigned when callback runs.
const range_ = range; const range_ = range;
promise = promise.catch(() => { promise = promise.catch(() => {
let anchor = RangeAnchor.fromSelector(root, range_); const anchor = RangeAnchor.fromSelector(root, range_);
return querySelector(anchor, options).then(maybeAssertQuote); return querySelector(anchor, options).then(maybeAssertQuote);
}); });
} }
...@@ -78,7 +80,7 @@ export function anchor(root, selectors, options = {}) { ...@@ -78,7 +80,7 @@ export function anchor(root, selectors, options = {}) {
if (position) { if (position) {
const position_ = position; const position_ = position;
promise = promise.catch(() => { promise = promise.catch(() => {
let anchor = TextPositionAnchor.fromSelector(root, position_); const anchor = TextPositionAnchor.fromSelector(root, position_);
return querySelector(anchor, options).then(maybeAssertQuote); return querySelector(anchor, options).then(maybeAssertQuote);
}); });
} }
...@@ -86,7 +88,7 @@ export function anchor(root, selectors, options = {}) { ...@@ -86,7 +88,7 @@ export function anchor(root, selectors, options = {}) {
if (quote) { if (quote) {
const quote_ = quote; const quote_ = quote;
promise = promise.catch(() => { promise = promise.catch(() => {
let anchor = TextQuoteAnchor.fromSelector(root, quote_); const anchor = TextQuoteAnchor.fromSelector(root, quote_);
return querySelector(anchor, options); return querySelector(anchor, options);
}); });
} }
...@@ -94,19 +96,15 @@ export function anchor(root, selectors, options = {}) { ...@@ -94,19 +96,15 @@ export function anchor(root, selectors, options = {}) {
return promise; return promise;
} }
/** export function describe(root: Element, range: Range) {
* @param {Element} root
* @param {Range} range
*/
export function describe(root, range) {
const types = [RangeAnchor, TextPositionAnchor, TextQuoteAnchor]; const types = [RangeAnchor, TextPositionAnchor, TextQuoteAnchor];
const result = []; const result = [];
for (let type of types) { for (const type of types) {
try { try {
const anchor = type.fromRange(root, range); const anchor = type.fromRange(root, range);
result.push(anchor.toSelector()); result.push(anchor.toSelector());
} catch (error) { } catch (error) {
continue; // If resolving some anchor fails, we just want to skip it silently
} }
} }
return result; return result;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment