app-walkthrough
Version:
An intuitive guided walkthrough library with UI highlighting and voice narration for web apps.
71 lines (70 loc) • 2.83 kB
JavaScript
import { convertToCss } from "./cssUtils";
/**
* 在给定的 scope 范围内,按照 selectors 链式查找目标元素
*/
export function findElement(selectors, scope) {
let currentScope = scope;
for (const selector of selectors) {
const element = resolveElement(selector, currentScope);
console.log("scope:", scope);
console.log("element:", element);
console.log("element html:", element === null || element === void 0 ? void 0 : element.innerHTML);
if (!element) {
console.log("链式查找中未能解析选择器:", selector.selector);
return undefined;
}
currentScope = element;
}
return currentScope;
}
/**
* 根据 selector 和作用域 scope 查找元素,支持根据文本内容过滤和索引选择
*
* 逻辑说明:
* 1. 通过 convertToCss 将 TSelector 转换为 CSS 选择器字符串
* 2. 在 scope 中查找所有匹配该选择器的元素
* 3. 如果 selector 中提供了 text,则先筛选出包含该文本内容的元素(默认忽略大小写)
* 4. 使用 selector.index(默认0)选取筛选结果中的第几个元素
* 5. 返回该元素,如果找不到则返回 undefined
*/
export function resolveElement(selector, scope) {
var _a;
const selectorString = convertToCss(selector);
if (!selectorString)
return undefined;
const allElements = Array.from(scope.querySelectorAll(selectorString));
if (allElements.length === 0) {
console.warn("未找到匹配选择器的元素:", selector);
return undefined;
}
// 如果提供了 text,先按文本内容筛选元素
let filteredElements = allElements;
const targetText = selector.target;
if (targetText) {
filteredElements = allElements.filter((el) => hasTextContent(el, targetText));
if (filteredElements.length === 0) {
console.warn(`未找到包含文本 "${targetText}" 的元素,选择器为:`, selector);
return undefined;
}
}
const index = (_a = selector.index) !== null && _a !== void 0 ? _a : 0;
if (index >= filteredElements.length) {
console.warn(`索引 ${index + 1} 超出范围,筛选后仅找到 ${filteredElements.length} 个元素`, selector);
return undefined;
}
return filteredElements[index];
}
/**
* 判断元素的 textContent 是否包含指定文本,支持忽略大小写
*/
export function hasTextContent(el, text, caseSensitive = true) {
var _a;
let content = (_a = el === null || el === void 0 ? void 0 : el.textContent) !== null && _a !== void 0 ? _a : "";
if (!content)
return false;
if (!caseSensitive) {
content = content.toLowerCase();
text = text.toLowerCase();
}
return content.includes(text);
}