blob: b6f81cfb85150e63529385804d481ec0499e96f5 [file] [log] [blame]
/**
* @license
* Licensed 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 { createRangeSelector } from '@annotator/range';
import { createAnySelectorCreator } from '@annotator/selector';
import { createTextQuoteSelector } from '@annotator/text';
const allSelectorTypes = {
TextQuoteSelector: createTextQuoteSelector,
RangeSelector: createRangeSelector,
};
const selectorFunc = createAnySelectorCreator(allSelectorTypes)();
/**
* Locate a selector.
* @param {Node} root node
* @param {Selector} descriptor
* @return {Range}
*/
export async function* search(root, descriptor) {
for (const node of nodeIterator(root)) {
if (!node.nodeValue) continue;
const matches = selectorFunc({
descriptors: [descriptor],
context: node.nodeValue,
});
for await (let match of matches) {
const startIndex = match.index;
const endIndex = startIndex + match[0].length;
const range = document.createRange();
range.setStart(node, startIndex);
range.setEnd(node, endIndex);
yield range;
}
}
}
/**
* Iterate over the nodes of a sub-tree of the document.
* @param {Node} node
*/
function* nodeIterator(node) {
yield node;
for (const child of node.childNodes) {
yield* nodeIterator(child);
}
}