Make css matcher also accept a Node as scope
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 @@
* > “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/range-node-conversion.ts b/packages/dom/src/range-node-conversion.ts
new file mode 100644
index 0000000..fd62543
--- /dev/null
+++ b/packages/dom/src/range-node-conversion.ts
@@ -0,0 +1,45 @@
+/**
+ * @license
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+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);
+}