MCPcopy
hub / github.com/Bistutu/FluentRead / grabAllNode

Function grabAllNode

entrypoints/main/dom.ts:26–102  ·  view source on GitHub ↗
(rootNode: Node)

Source from the content-addressed store, hash-verified

24
25// 传入父节点,返回所有需要翻译的 DOM 元素数组
26export function grabAllNode(rootNode: Node): Element[] {
27 if (!rootNode) return [];
28
29 const result: Element[] = [];
30
31 const walker = document.createTreeWalker(
32 rootNode,
33 NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
34 {
35 acceptNode: (node: Node): number => {
36 if (node instanceof Text) return NodeFilter.FILTER_ACCEPT;
37
38 if (!(node instanceof Element)) return NodeFilter.FILTER_SKIP;
39
40 const tag = node.tagName.toLowerCase();
41
42 // 跳过黑名单标签
43 if (skipSet.has(tag) ||
44 node.classList?.contains('sr-only') ||
45 node.classList?.contains('notranslate')) {
46 return NodeFilter.FILTER_REJECT;
47 }
48
49 // 在初始全局翻译时 跳过header与footer
50 if (tag === 'header' || tag === 'footer') {
51 return NodeFilter.FILTER_REJECT;
52 }
53
54 // 检查是否只包含有效文本内容
55 let hasText = false;
56 let hasElement = false;
57 let hasNonEmptyElement = false;
58
59 for (const child of node.childNodes) {
60 if (child.nodeType === Node.ELEMENT_NODE) {
61 hasElement = true;
62 // 检查子元素是否包含文本
63 if (child.textContent?.trim()) {
64 hasNonEmptyElement = true;
65 }
66 }
67 if (child.nodeType === Node.TEXT_NODE && child.textContent?.trim()) {
68 hasText = true;
69 }
70 }
71
72 // 如果有非空子元素,跳过当前节点
73 if (hasNonEmptyElement) {
74 return NodeFilter.FILTER_SKIP;
75 }
76
77 if (hasText && !hasElement) {
78 return NodeFilter.FILTER_ACCEPT;
79 }
80
81 // 如果有子元素,继续遍历
82 if (node.childNodes.length > 0) {
83 return NodeFilter.FILTER_SKIP;

Callers 1

autoTranslateEnglishPageFunction · 0.90

Calls 1

grabNodeFunction · 0.85

Tested by

no test coverage detected