* 判断是否应该跳过Medium网站上的特定元素
(node: any)
| 1172 | * 判断是否应该跳过Medium网站上的特定元素 |
| 1173 | */ |
| 1174 | function shouldSkipMediumElement(node: any): boolean { |
| 1175 | // 如果当前节点或其祖先节点匹配这些选择器,则跳过 |
| 1176 | const skipSelectors = [ |
| 1177 | // 导航栏和工具栏 |
| 1178 | 'nav', |
| 1179 | 'div.metabar', |
| 1180 | 'div.js-metabar', |
| 1181 | // 侧边栏 |
| 1182 | 'div.js-sidebarContainer', |
| 1183 | 'div.js-sidebar', |
| 1184 | // UI元素 |
| 1185 | 'button', |
| 1186 | 'input', |
| 1187 | 'textarea', |
| 1188 | // 代码块 |
| 1189 | 'pre', |
| 1190 | 'code', |
| 1191 | // 底部元素 |
| 1192 | 'footer', |
| 1193 | // 作者资料卡 |
| 1194 | 'div.pw-multi-author-card', |
| 1195 | // 推荐文章卡片上的标题/描述以外的内容 |
| 1196 | 'div.pw-card-body div.pw-card-description ~ *', |
| 1197 | // 分享按钮和响应按钮 |
| 1198 | 'div.pw-post-actions', |
| 1199 | 'div.pw-responses-header', |
| 1200 | ]; |
| 1201 | |
| 1202 | // 检查当前节点是否匹配跳过选择器 |
| 1203 | for (const selector of skipSelectors) { |
| 1204 | if (node.matches?.(selector)) return true; |
| 1205 | |
| 1206 | // 检查祖先节点 |
| 1207 | let parent = node.parentElement; |
| 1208 | while (parent) { |
| 1209 | if (parent.matches?.(selector)) return true; |
| 1210 | parent = parent.parentElement; |
| 1211 | } |
| 1212 | } |
| 1213 | |
| 1214 | // 检查节点的类名是否包含特定关键字 |
| 1215 | const skipClassKeywords = ['js-', 'btn', 'button', 'u-', 'overlay', 'postActionsBar']; |
| 1216 | |
| 1217 | if (node.className && typeof node.className === 'string') { |
| 1218 | for (const keyword of skipClassKeywords) { |
| 1219 | if (node.className.includes(keyword)) return true; |
| 1220 | } |
| 1221 | } |
| 1222 | |
| 1223 | // 忽略代码片段 |
| 1224 | if (node.tagName?.toLowerCase() === 'pre' || node.tagName?.toLowerCase() === 'code') return true; |
| 1225 | |
| 1226 | // 忽略图片图标 |
| 1227 | if (node.tagName?.toLowerCase() === 'svg' || node.tagName?.toLowerCase() === 'img') return true; |
| 1228 | |
| 1229 | return false; |
| 1230 | } |
| 1231 |