This is an automated email from the ASF dual-hosted git repository. gerben pushed a commit to branch allow-node-as-scope in repository https://gitbox.apache.org/repos/asf/incubator-annotator.git
commit ab0f8edc428be627d3f6ece3362cb803d4821b07 Author: Gerben <[email protected]> AuthorDate: Fri Jun 4 19:38:39 2021 +0200 Make css matcher also accept a Node as scope --- packages/dom/src/css.ts | 10 ++++---- packages/dom/src/owner-document.ts | 17 ++++++++++--- ...{owner-document.ts => range-node-conversion.ts} | 28 ++++++++++++++++++---- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/packages/dom/src/css.ts b/packages/dom/src/css.ts index 6882b1e..b2b70c6 100644 --- a/packages/dom/src/css.ts +++ b/packages/dom/src/css.ts @@ -21,6 +21,7 @@ import optimalSelect from 'optimal-select'; import type { CssSelector, Matcher } from '@apache-annotator/selector'; import { ownerDocument } from './owner-document'; +import { toRange } from './range-node-conversion'; /** * Find the elements corresponding to the given {@link @@ -45,16 +46,17 @@ import { ownerDocument } from './owner-document'; * > “If […] the user agent discovers multiple matching text sequences, then the * > selection SHOULD be treated as matching all of the matches.” * - * @param selector - The {@link CssSelector} to be anchored - * @returns A {@link Matcher} function that applies `selector` to a given {@link https://developer.mozilla.org/en-US/docs/Web/API/Range - * | Range} + * @param selector - The {@link CssSelector} to be anchored. + * @returns A {@link Matcher} function that applies `selector` to a given + * `scope`. * * @public */ export function createCssSelectorMatcher( selector: CssSelector, -): Matcher<Range, Element> { +): Matcher<Node | Range, Element> { return async function* matchAll(scope) { + scope = toRange(scope); const document = ownerDocument(scope); for (const element of document.querySelectorAll(selector.value)) { const range = document.createRange(); diff --git a/packages/dom/src/owner-document.ts b/packages/dom/src/owner-document.ts index 1c0621e..fe7818a 100644 --- a/packages/dom/src/owner-document.ts +++ b/packages/dom/src/owner-document.ts @@ -18,8 +18,19 @@ * under the License. */ -export function ownerDocument(range: Range): Document { - const { startContainer } = range; +/** + * Get the ownerDocument for either a range or a node. + * + * @param nodeOrRange the node or range for which to get the owner document. + */ +export function ownerDocument(nodeOrRange: Node | Range): Document { + const node = isRange(nodeOrRange) + ? nodeOrRange.startContainer + : nodeOrRange; // node.ownerDocument is null iff node is itself a Document. - return startContainer.ownerDocument ?? (startContainer as Document); + return node.ownerDocument ?? (node as Document); +} + +function isRange(nodeOrRange: Node | Range): nodeOrRange is Range { + return ('startContainer' in nodeOrRange); } diff --git a/packages/dom/src/owner-document.ts b/packages/dom/src/range-node-conversion.ts similarity index 53% copy from packages/dom/src/owner-document.ts copy to packages/dom/src/range-node-conversion.ts index 1c0621e..fd62543 100644 --- a/packages/dom/src/owner-document.ts +++ b/packages/dom/src/range-node-conversion.ts @@ -18,8 +18,28 @@ * under the License. */ -export function ownerDocument(range: Range): Document { - const { startContainer } = range; - // node.ownerDocument is null iff node is itself a Document. - return startContainer.ownerDocument ?? (startContainer as Document); +import { ownerDocument } from "./owner-document"; + +/** + * Returns a range that exactly selects the contents of the given node. + * + * This function is idempotent: If the given argument is already a range, it + * simply returns that range. + * + * @param nodeOrRange The node/range to convert to a range if it is not already + * a range. + */ +export function toRange(nodeOrRange: Node | Range): Range { + if (isRange(nodeOrRange)) { + return nodeOrRange; + } else { + const node = nodeOrRange; + const range = ownerDocument(node).createRange(); + range.selectNodeContents(node); + return range; + } +} + +function isRange(nodeOrRange: Node | Range): nodeOrRange is Range { + return ('startContainer' in nodeOrRange); }
