From 67101824338e46899f9146e84e159ba4a895e115 Mon Sep 17 00:00:00 2001 From: Kyle Keating Date: Wed, 7 Oct 2020 10:40:18 -0700 Subject: [PATCH] Covert html.coffee to js --- src/annotator/anchoring/html.coffee | 89 ----------------------- src/annotator/anchoring/html.js | 107 ++++++++++++++++++++++++++++ src/annotator/anchoring/types.js | 2 +- src/annotator/guest.js | 2 - 4 files changed, 108 insertions(+), 92 deletions(-) delete mode 100644 src/annotator/anchoring/html.coffee create mode 100644 src/annotator/anchoring/html.js diff --git a/src/annotator/anchoring/html.coffee b/src/annotator/anchoring/html.coffee deleted file mode 100644 index 532b166a2ab..00000000000 --- a/src/annotator/anchoring/html.coffee +++ /dev/null @@ -1,89 +0,0 @@ -{ - RangeAnchor - TextPositionAnchor - TextQuoteAnchor -} = require('./types') - - -querySelector = (type, root, selector, options) -> - doQuery = (resolve, reject) -> - try - anchor = type.fromSelector(root, selector, options) - range = anchor.toRange(options) - resolve(range) - catch error - reject(error) - return new Promise(doQuery) - - -###* -# Anchor a set of selectors. -# -# This function converts a set of selectors into a document range. -# It encapsulates the core anchoring algorithm, using the selectors alone or -# in combination to establish the best anchor within the document. -# -# :param Element root: The root element of the anchoring context. -# :param Array selectors: The selectors to try. -# :param Object options: Options to pass to the anchor implementations. -# :return: A Promise that resolves to a Range on success. -# :rtype: Promise -#### -exports.anchor = (root, selectors, options = {}) -> - # Selectors - fragment = null - position = null - quote = null - range = null - - # Collect all the selectors - for selector in selectors ? [] - switch selector.type - when 'TextPositionSelector' - position = selector - options.hint = position.start # TextQuoteAnchor hint - when 'TextQuoteSelector' - quote = selector - when 'RangeSelector' - range = selector - - # Assert the quote matches the stored quote, if applicable - maybeAssertQuote = (range) -> - if quote?.exact? and range.toString() != quote.exact - throw new Error('quote mismatch') - else - return range - - # From a default of failure, we build up catch clauses to try selectors in - # order, from simple to complex. - promise = Promise.reject('unable to anchor') - - if range? - promise = promise.catch -> - return querySelector(RangeAnchor, root, range, options) - .then(maybeAssertQuote) - - if position? - promise = promise.catch -> - return querySelector(TextPositionAnchor, root, position, options) - .then(maybeAssertQuote) - - if quote? - promise = promise.catch -> - # Note: similarity of the quote is implied. - return querySelector(TextQuoteAnchor, root, quote, options) - - return promise - - -exports.describe = (root, range, options = {}) -> - types = [RangeAnchor, TextPositionAnchor, TextQuoteAnchor] - - selectors = for type in types - try - anchor = type.fromRange(root, range, options) - selector = anchor.toSelector(options) - catch - continue - - return selectors diff --git a/src/annotator/anchoring/html.js b/src/annotator/anchoring/html.js new file mode 100644 index 00000000000..b33f6e57dbf --- /dev/null +++ b/src/annotator/anchoring/html.js @@ -0,0 +1,107 @@ +import { RangeAnchor, TextPositionAnchor, TextQuoteAnchor } from './types'; + +/** + * @typedef {import("./types").AnyRangeType} AnyRangeType + * @typedef {import('../../types/api').Selector} Selector + */ + +/** + * @param {RangeAnchor|TextPositionAnchor|TextQuoteAnchor} anchor + * @param {Object} [options] + * @param {number} [options.hint] + */ +async function querySelector(anchor, options = {}) { + return anchor.toRange(options); +} + +/** + * Anchor a set of selectors. + * + * This function converts a set of selectors into a document range. + * It encapsulates the core anchoring algorithm, using the selectors alone or + * in combination to establish the best anchor within the document. + * + * @param {Node} root - The root element of the anchoring context. + * @param {Selector[]} selectors - The selectors to try. + * @param {Object} [options] + * @param {number} [options.hint] + */ +export function anchor(root, selectors, options = {}) { + let position = null; + let quote = null; + let range = null; + + // Collect all the selectors + for (let selector of selectors) { + switch (selector.type) { + case 'TextPositionSelector': + position = selector; + options.hint = position.start; // TextQuoteAnchor hint + break; + case 'TextQuoteSelector': + quote = selector; + break; + case 'RangeSelector': + range = selector; + break; + } + } + + /** + * Assert the quote matches the stored quote, if applicable + * @param {Range} range + */ + const maybeAssertQuote = range => { + if (quote?.exact && range.toString() !== quote.exact) { + throw new Error('quote mismatch'); + } else { + return range; + } + }; + + // From a default of failure, we build up catch clauses to try selectors in + // order, from simple to complex. + /** @type {Promise} */ + let promise = Promise.reject('unable to anchor'); + + if (range) { + promise = promise.catch(() => { + let anchor = RangeAnchor.fromSelector(root, range); + return querySelector(anchor, options).then(maybeAssertQuote); + }); + } + + if (position) { + promise = promise.catch(() => { + let anchor = TextPositionAnchor.fromSelector(root, position); + return querySelector(anchor, options).then(maybeAssertQuote); + }); + } + + if (quote) { + promise = promise.catch(() => { + let anchor = TextQuoteAnchor.fromSelector(root, quote); + return querySelector(anchor, options); + }); + } + + return promise; +} + +/** + * @param {Node} root + * @param {Range} range + */ +export function describe(root, range) { + const types = [RangeAnchor, TextPositionAnchor, TextQuoteAnchor]; + const result = []; + for (let type of types) { + try { + const anchor = type.fromRange(root, range); + result.push(anchor.toSelector()); + } catch (error) { + continue; + } + } + return result; +} diff --git a/src/annotator/anchoring/types.js b/src/annotator/anchoring/types.js index b7f97e2c002..ad5aa80ea48 100644 --- a/src/annotator/anchoring/types.js +++ b/src/annotator/anchoring/types.js @@ -137,7 +137,7 @@ export class TextPositionAnchor { } /** - * Converts between TextQuoteSelector selectors and Range objects. + * Converts between `TextQuoteSelector` selectors and `Range` objects. */ export class TextQuoteAnchor { /** diff --git a/src/annotator/guest.js b/src/annotator/guest.js index 443df565094..e461f97813c 100644 --- a/src/annotator/guest.js +++ b/src/annotator/guest.js @@ -4,9 +4,7 @@ import scrollIntoView from 'scroll-into-view'; import Delegator from './delegator'; import { Adder } from './adder'; -// @ts-expect-error - Module is CoffeeScript import * as htmlAnchoring from './anchoring/html'; - import { sniff } from './anchoring/range'; import { getHighlightsContainingNode,