// ==UserScript==
// @name Auto Read bee
// @namespace http://tampermonkey.net/
// @version 1.0.5
// @description Linuxdo auto read
// @author bee
// @match https://meta.discourse.org/*
// @match https://linux.do/*
// @match https://meta.appinn.net/*
// @match https://community.openai.com/
// @grant none
// @license MIT
// @icon https://www.google.com/s2/favicons?domain=linux.do
// ==/UserScript==
//set stop limit
const stopLimit = 350;
const readSuggestPost = false;
const defaultPost = "https://linux.do/t/topic/53589/1501";
const readDelay = 2000; // 滚动检查的间隔(毫秒)
const postCommentsCount = 200;// filter post under this comments, over this will PASS
const BASE_URL = `https://${window.location.hostname}`;
const refreshRate = 400;
const failRetry = 10;
const autoSelectFloor = true;
/**
* This function set Floor infos value, return how much post been read.
* @param {boolean} refresh - if true, reset all values
* @returns {Object} - Returns an object with the result of the operation and the number of posts read.
*/
let lastFloor = null;
let startFloor = null;
let endFloor = null;
let readCounter = 0;
let failCounter = 0;
let directWaitCounter = 0
let readInterval;
let waitNextRefresh = 0;
function setFloor(refresh = false) {
if (refresh) {
lastFloor = null;
startFloor = null;
endFloor = null;
failCounter = 0;
return {result: "refreshed"};
}
try {
let element_floor = document.querySelector('.timeline-replies');
let floor_numbers = element_floor.textContent.trim().split(' / ');
let readCountTemp = startFloor - lastFloor;
if (readCountTemp > 0) {
failCounter = 0;
}
if (lastFloor) {
readCounter = parseInt(localStorage.getItem("readCounter") || "0", 10);
readCounter += (readCountTemp < 20 && readCountTemp > 0)? readCountTemp : 0;
localStorage.setItem("readCounter", readCounter.toString());
//console.log("add read",startFloor - lastFloor," ==> ", readCounter);
}
lastFloor = startFloor;
startFloor = parseInt(floor_numbers[0].replace(" ", ""));
endFloor = parseInt(floor_numbers[1].replace(" ", ""));
return {result: "success", readFloor: readCountTemp};
} catch (error) {
return {result: "fail"};
}
}
// back to last read if exist
/**
* This function checks if there is a 'last read' button on the page and clicks it if it exists.
* The 'last read' button is typically used in forums to navigate to the last read post in a thread.
*
* @returns {boolean} - Returns true if the 'last read' button was found and clicked, false otherwise.
*/
function checkLastRead() {
let buttonLastRead = document.querySelector('.timeline-last-read .btn');
if (buttonLastRead) {
buttonLastRead.click();
return true;
}
return false;
}
function setBtnText_readToday() {
let btnAutoRead = document.getElementById("btnAutoRead");
btnAutoRead.textContent = localStorage.getItem("read") === "true" ? `◼ ( ${readCounter} )` : `▶ ( ${readCounter} )`;
}
function check_read_limit() {
if (readCounter > stopLimit) {
document.getElementById('btnAutoRead').click();
return true;
}
return false;
}
// read post
function readPost(postFloor = 1, autoSelect = false) {
let element = document.querySelectorAll('.boxed.onscreen-post');
try {
//find which element.id === post_${postFloor}
let targetElement = null;
if (autoSelect) {
let switchTemp = false;
let targetFound = false;
for (let counterTemp = 0; element.length > counterTemp; counterTemp++) {
if (isInViewport(element[counterTemp]) === false && switchTemp === true) {
if (targetFound === false) {
targetElement = element[counterTemp];
targetFound = true;
break;
}
}
if (isInViewport(element[counterTemp]) === true) {
switchTemp = true;
}
}
if (targetElement) {
scrollIntoBee(targetElement);
return {result: "success"};
} else {
console.log("[WARN] Can't find floor ");
scrollIntoBee(element[element.length - 1]);
return {result: "moveBack"};
}
}
element.forEach((e) => {
if (e.id === `post_${postFloor}`) {
targetElement = e;
}
});
if (targetElement) {
scrollIntoBee(targetElement);
return {result: "success"};
}
scrollIntoBee(element[(element.length - 3) > 1 ? (element.length - 3) : element.length]);
return {result: "success"};
} catch (e) {
scrollIntoBee(element[(element.length - 3) > 1 ? (element.length - 3) : 1]);
console.log("[WARN] Can't find floor ");
return {result: "fail"};
}
}
function isInViewport(element) {
const rect = element.getBoundingClientRect();
return (rect.top >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight)
//rect.left >= 0 &&
//rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
//rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
async function directNextPost() {
if (waitNextRefresh === 0) {
waitNextRefresh++;
return;
}
waitNextRefresh = 0;
if (window.location.href.includes('/t/topic/') && readSuggestPost) {
let suggestPost;
suggestPost = document.querySelector('a[href="/unread"]');
if (suggestPost) {
suggestPost.click();
console.log("[INFO] found unread ==> ○");
return;
}
console.log("[WARN] unread post ==> X");
/*suggestPost = document.querySelector('a.badge');//document.querySelector('a.raw-topic-link');
if (suggestPost) {
suggestPost.click();
console.log("[INFO] found suggested post ==> ○");
return;
}
console.log("[WARN] suggest post ==> X");
suggestPost = document.querySelector('a[href="/new"]');
if (suggestPost) {
suggestPost.click();
console.log("[INFO] found new ==> ○");
return;
}
console.log("[WARN] new post ==> X , back to home.");
suggestPost = document.querySelector('a[href="/"]');
if (suggestPost) {
suggestPost.click();
console.log("[INFO] found index ==> ○");
return;
}*/
}
if (window.location.href.includes('/search') && directWaitCounter < 5) {
let links = document.querySelectorAll('a[href^="/t/topic"]');
let hrefs;
if (links && 0 < links.length) {
directWaitCounter = 0;
hrefs = Array.from(links, link => link.getAttribute('href'));
const tempUrl = hrefs.shift();
localStorage.setItem("unreadList", JSON.stringify(hrefs));
console.log("[INFO] Got ", hrefs.length, " unread posts");
gotoUrl(tempUrl);
return;
}
directWaitCounter++;
console.log("[WARN] Got 0 unread posts");
}
if (window.location.href.includes('/search')) {
directWaitCounter = 0;
gotoUrl("/ubm");//useBackupMethod
}
if (window.location.href === `${BASE_URL}/unread` /*||
window.location.href === `${BASE_URL}/`*/) {
let suggestPost = document.querySelector('a[class*="badge badge-notification"]');
if (suggestPost) {
console.log("[INFO] found post ==> ○");
suggestPost.click();
}
return;
}
/*if (window.location.href === `${BASE_URL}/new`) {
let suggestPost = document.querySelector('a[href*="/t/topic/"]');
if (suggestPost) {
console.log("[INFO] found post ==> ○");
suggestPost.click();
}
return;
}*/
let unreadList = JSON.parse(localStorage.getItem("unreadList"));
if (!unreadList || unreadList.length <= 0) {
gotoUrl("/search?expanded=true&q=in%3Aunseen%20min_posts%3A20");
return;
}
if (0 < unreadList.length) {
let tempUrl = unreadList.shift();
let userUrl = window.location.href.match(/\/t\/topic\/(\d+)?/);
if (userUrl !== null && userUrl[1] === tempUrl.match(/\/t\/topic\/(\d+)?/)[1]) {
localStorage.setItem("unreadList", JSON.stringify(unreadList));
tempUrl = unreadList.shift();
console.log("[INFO] Delete done post");
}
console.log("[INFO] Least ", unreadList.length, " unread posts in storage");
if (tempUrl) {
gotoUrl(tempUrl);
}
return;
}
// backup method
console.log("[WARN] Use api to get unread posts");
const topicListStr = localStorage.getItem("topicList");
if (!topicListStr) {
await getLatestTopic();
}
const topicList = JSON.parse(topicListStr);
if (topicList && 0 < topicList.length) {
// 从未读列表中取出第一个
let topic = topicList.shift();
if (window.location.href.includes(`/t/topic/${topic.id}`)) {
localStorage.setItem("topicList", JSON.stringify(topicList));
topic = topicList.shift();
}
//window.location.href = `${BASE_URL}/t/topic/${topic.id}`;
gotoUrl(`/t/topic/${topic.id}`);
}
}
function gotoUrl(url) {
let directPost = document.querySelector('a[href="/"]');
directPost.href = `${url}`;
directPost.click();
directPost.href = "/";
}
function scrollIntoBee(element, marginOffset = 4) {
const temp_marginTop = (element.style.marginTop === undefined || '') ? '0px' : element.style.marginTop;
//decrease 130px from temp_marginTop
element.style.marginTop = `-${marginOffset}rem`;
element.scrollIntoView({behavior: "smooth"});
element.style.marginTop = temp_marginTop;
}
// 获取最新文章列表
async function getLatestTopic() {
let latestPage = 0;
const latestPageStr = localStorage.getItem("latestPage");
if (latestPageStr) {
latestPage = Number(latestPageStr);
}
latestPage++;
const url = `${BASE_URL}/latest.json?no_definitions=true&page=${latestPage}`;
try {
const response = await fetch(url);
const result = await response.json();
if (result) {
const topicList = [];
result.topic_list.topics.forEach((topic) => {
// 未读以及评论数小于50
if (!topic.unseen && postCommentsCount > topic.posts_count) {
topicList.push(topic);
}
});
localStorage.setItem("latestPage", latestPage.toString());
localStorage.setItem("topicList", JSON.stringify(topicList));
console.log(`[INFO] Got ${topicList.length} topics`);
}
} catch (error) {
console.log(`[FAIL] Fail to get topics : `);
console.error(error);
}
}
function waitReady() {
let element = document.querySelector('.loading-indicator-container');
return element && element.classList.contains('ready');
}
// 打开新的文章
function openNewTopic() {
const topicListStr = localStorage.getItem("topicList");
let suggestPost = document.querySelector('a.raw-topic-link');//document.querySelector('.badge.badge-notification.unread-posts');
if (suggestPost && readSuggestPost) {
//suggestPost.click();
window.location.href = suggestPost.getAttribute('href');
} else if (topicListStr) {
const topicList = JSON.parse(topicListStr);
if (topicList && 0 < topicList.length) {
// 从未读列表中取出第一个
const topic = topicList.shift();
localStorage.setItem("topicList", JSON.stringify(topicList));
window.location.href = `${BASE_URL}/t/topic/${topic.id}`;
} else {
// 获取最新文章列表
getLatestTopic();
// 打开新的文章
openNewTopic();
}
} else {
// 获取最新文章列表
getLatestTopic();
// 打开新的文章
openNewTopic();
}
}
function addStartBtn() {
//let ul = document.querySelector('.icons.d-header-icons');btn btn-icon-text btn-default sidebar__panel-switch-button
let ul = document.querySelector('.sidebar-footer-wrapper');
let li = document.createElement('li');
li.className = "sidebar-section-link-wrapper";
let a = document.createElement('a');
a.id = "startA";
a.className = "ember-view sidebar-section-link sidebar-row";
//let a2 = document.createElement('a');
//a2.id = "directUrl";
//a2.className = "ember-view sidebar-section-link sidebar-row";
//a2.href = "";
let span1 = document.createElement('span');
span1.className = "sidebar-section-link-prefix icon";
let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.classList.add("fa", "d-icon", "d-icon-angle-double-right", "svg-icon", "prefix-icon", "svg-string");
let use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#angle-double-right');
let span2 = document.createElement('span');
span2.className = "sidebar-section-link-content-text";
span2.id = "btnAutoRead";
span2.textContent = '▶ ( - )';
svg.appendChild(use);
span1.appendChild(svg);
a.appendChild(span1);
a.appendChild(span2);
//li.appendChild(a2);
li.appendChild(a);
ul.prepend(li);
a.onclick = function () {
const currentlyReading = localStorage.getItem("read") === "true";
const newReadState = !currentlyReading;
localStorage.setItem("read", newReadState.toString());
span2.textContent = newReadState ? `◼ ( ${readCounter} )` : `▶ ( ${readCounter} )`;
if (newReadState) {
autoRunStart();
} else {
clearInterval(readInterval);
}
};
}
function addAutoBtn() {
//let ul = document.querySelector('.icons.d-header-icons');btn btn-icon-text btn-default sidebar__panel-switch-button
let ul = document.querySelector('.sidebar-footer-wrapper');
let li = document.createElement('li');
li.className = "sidebar-section-link-wrapper";
let a = document.createElement('a');
a.id = "startA2";
a.className = "ember-view sidebar-section-link sidebar-row";
//let a2 = document.createElement('a');
//a2.id = "directUrl";
//a2.className = "ember-view sidebar-section-link sidebar-row";
//a2.href = "";
let span1 = document.createElement('span');
span1.className = "sidebar-section-link-prefix icon";
let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.classList.add("fa", "d-icon", "d-icon-angle-down", "svg-icon", "prefix-icon", "svg-string");
let use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#angle-down');
let span2 = document.createElement('span');
span2.className = "sidebar-section-link-content-text";
span2.id = "btnAutoRead2";
span2.textContent = '▼';
svg.appendChild(use);
span1.appendChild(svg);
a.appendChild(span1);
a.appendChild(span2);
//li.appendChild(a2);
li.appendChild(a);
ul.prepend(li);
a.onclick = function () {
const currentlyReading = localStorage.getItem("read") === "true";
const newReadState = !currentlyReading;
localStorage.setItem("read", newReadState.toString());
document.getElementById("btnAutoRead").textContent = newReadState ? `◼ ( ${readCounter} )` : `▶ ( ${readCounter} )`;
if (newReadState) {
autoRunStart(true);
} else {
clearInterval(readInterval);
}
};
}
function addCleanBtn() {
//let ul = document.querySelector('.icons.d-header-icons');
let ul = document.querySelector('.sidebar-footer-wrapper');
let li = document.createElement('li');
li.className = "sidebar-section-link-wrapper";
let a = document.createElement('a');
a.id = "cleanA";
a.className = "ember-view sidebar-section-link sidebar-row";
let span1 = document.createElement('span');
span1.className = "sidebar-section-link-prefix icon";
let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.classList.add("fa", "d-icon", "d-icon-discourse-sparkles", "svg-icon", "prefix-icon", "svg-string");
let use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#discourse-sparkles');
let span2 = document.createElement('span');
span2.className = "sidebar-section-link-content-text";
span2.id = "btnAutoReadReset";
span2.textContent = '✨';
svg.appendChild(use);
span1.appendChild(svg);
a.appendChild(span1);
a.appendChild(span2);
li.appendChild(a);
ul.prepend(li);
li.onclick = function () {
readCounter = 0;
localStorage.setItem("readCounter", readCounter.toString());
document.getElementById('btnAutoRead').textContent = localStorage.getItem("read") === "true" ? `◼ ( ${readCounter} )` : `▶ ( ${readCounter} )`;
};
}
function isNewPost() {
if (localStorage.getItem("readUrl").split("/").slice(0, 6).join("/") !== window.location.href.split("/").slice(0, 6).join("/")) {
localStorage.setItem("readUrl", window.location.href.split("/").slice(0, 6).join("/"));
return true;
}
return false;
}
function autoRunStart(singleTopic = false) {
readInterval = setInterval(async () => {
if (check_read_limit() || !waitReady) {
return;
}
let errorElement = document.querySelector('.page-not-found');
if (errorElement) {
console.log("[WARN] Page not found");
await directNextPost();
return;
}
let retryElement = document.querySelector('.btn.btn-icon-text.btn-primary.topic-retry');
let retryElement2 = document.querySelector('.error-page');
if (retryElement) {
retryElement.click();
return;
}
if (retryElement2) {
document.querySelector('.btn.btn-icon-text.btn-primary').click();
}
if (window.location.href.includes('/t/topic/')) {
const isNew = isNewPost();
if (isNew) {
failCounter = 0;
console.log("[INFO] New post")
setFloor(true);
}
checkLastRead();
const existFloor = setFloor();
if (existFloor.result !== "success") {
let element = document.querySelectorAll('.boxed.onscreen-post');
if (element) {
if (singleTopic) {
document.getElementById('btnAutoRead').click();
return;
}
await directNextPost();
console.log("[INFO] Direct post...")
}
return;
}
setBtnText_readToday();
if (startFloor === endFloor) {
if (singleTopic) {
document.getElementById('btnAutoRead').click();
return;
}
await directNextPost();
console.log("[INFO] Direct post...")
return;
}
if (failCounter < failRetry) {
if (existFloor.readFloor === 0) {
if (endFloor - startFloor < 3) {
if (singleTopic) {
document.getElementById('btnAutoRead').click();
return;
}
await directNextPost();
console.log("[INFO] Direct post...")
return;
}
failCounter++;
if (failCounter > failRetry / 2) {
console.log("[INFO] +800...");
window.scrollBy(0, 800);
}
} else {
failCounter = 0;
//return;
}
//console.log("[INFO] Reading...", existFloor.readFloor === 0 ? startFloor + 3 : startFloor, " ==> ", endFloor);
let readResult;
if (failCounter === failRetry - 1) {
readResult = readPost((startFloor - 5) > 1 ? (startFloor - 5) : 1);
} else {
readResult = readPost((startFloor + 1) < endFloor ? (startFloor + 1) : endFloor, autoSelectFloor);
//console.log("[INFO] try...", (startFloor + 1), " ==> ", failCounter);
}
if (readResult.result === "fail") {
//failCounter++;
console.log("[WARN] Retry read floor : ", startFloor + 1, " ==> ", failCounter);
return;
}
if (readResult.result === "moveBack" || endFloor - startFloor < 5) {
if (singleTopic) {
document.getElementById('btnAutoRead').click();
return;
}
await directNextPost();
console.log("[INFO] Direct post...")
return;
}
return;
}
window.scrollBy(0, 200);
return;
}
if (singleTopic) {
document.getElementById('btnAutoRead').click();
return;
}
await directNextPost();
/*if (window.location.href.includes('/t/topic/')) {
checkLastRead();
setFloor(true);
readPost(1);
}*/
}, (refreshRate < 2000 && autoSelectFloor) ? (refreshRate + 2000) : (refreshRate));
}
// 检查是否是第一次运行脚本
function checkFirstRun() {
if (localStorage.getItem("isFirstRun") === null || localStorage.getItem("readUrl") === null) {
//init
console.log("[INFO] Init data");
localStorage.setItem("isFirstRun", "false");
localStorage.setItem("read", "false"); // 开始时自动滚动关闭
localStorage.setItem("autoLikeEnabled", "false"); //默认关闭自动点赞
localStorage.setItem("unreadList", "[]");
localStorage.setItem("readUrl", "https://linux.do/t/topic/1");
}
addCleanBtn();
addAutoBtn();
addStartBtn();
}
// 1. 创建一个函数来处理 article 元素
function handleArticle(articleElement) {
// 2. 提取 article 的 id 數字
const postId = parseInt(articleElement.id.replace('post_', ''));
// 3. 生成文字
const text = postId + ' F';
// 4. 在 [[代碼插入處]] 插入文字 (修改部分)
const avatarDiv = articleElement.querySelector('.topic-avatar');
if (avatarDiv === null) return;
const existingText = avatarDiv.querySelector(`div[id='post-${postId}-f']`); // 檢查是否存在新添加的文字
if (!existingText) { // 如果不存在,才插入
const newText = document.createElement('div');
newText.textContent = text;
newText.id = `post-${postId}-f`; // 添加 ID
newText.style.textAlign = 'center'; // 設置文字居中
newText.style.cursor = 'pointer'; // 設置鼠標指針為鏈接樣式
// 添加鼠標懸停事件
newText.addEventListener('mouseover', () => {
newText.style.cursor = 'pointer'; // 設置鼠標指針為鏈接樣式
});
// 添加點擊事件
newText.addEventListener('click', async () => {
// 檢查按鈕是否已存在
if (newText.querySelector(`#copyPostIdButton-${postId}`)) return;
// 創建按鈕
const copyPostIdButton = document.createElement('button');
copyPostIdButton.id = `copyPostIdButton-${postId}`;
copyPostIdButton.className = 'btn btn-icon-text btn-default';
copyPostIdButton.textContent = 'id';
copyPostIdButton.addEventListener('click', () => {
navigator.clipboard.writeText(articleElement.dataset.postId)
.then(() => {
//console.log('Data-post-id copied to clipboard!');
alert('copied !');
})
.catch(err => {
//console.error('Failed to copy: ', err);
alert('Failed to copy: ', err);
});
});
const copyRequestUrlButton = document.createElement('button');
copyRequestUrlButton.id = `copyRequestUrlButton-${postId}`;
copyRequestUrlButton.className = 'btn btn-icon-text btn-default';
copyRequestUrlButton.textContent = 'URL';
copyRequestUrlButton.addEventListener('click', () => {
//const requestUrl = `https://linux.do/discourse-reactions/posts/${articleElement.dataset.postId}/reactions-users.json`;
const requestUrl = `https://linux.do/user_actions.json?limit=2000&username=${articleElement.innerHTML.match(/data-user-card="([^"]+)"/)[1]}&filter=2`;
navigator.clipboard.writeText(requestUrl)
.then(() => {
//console.log('Request URL copied to clipboard!');
alert('copied !');
})
.catch(err => {
//console.error('Failed to copy: ', err);
alert('Failed to copy: ', err);
});
});
const copyUserListButton = document.createElement('button');
copyUserListButton.id = `copyUserListButton-${postId}`;
copyUserListButton.className = 'btn btn-icon-text btn-default';
copyUserListButton.textContent = 'List';
copyUserListButton.addEventListener('click', async () => {
const postId = parseInt(articleElement.dataset.postId);
const requestUrl1 = `https://linux.do/user_actions.json?limit=2000&username=${articleElement.innerHTML.match(/data-user-card="([^"]+)"/)[1]}&filter=2`;
const requestUrl2 = `https://linux.do/discourse-reactions/posts/reactions-received.json?username=${articleElement.innerHTML.match(/data-user-card="([^"]+)"/)[1]}`;
try {
const [response1, response2] = await Promise.all([fetch(requestUrl1), fetch(requestUrl2)]);
const data1 = await response1.json();
const data2 = await response2.json();
const userList1 = data1.user_actions
.filter(action => action.post_id === postId)
.map((action, index) => `${index + 1}. ${action.acting_username}`);
const userList2 = data2
.filter(item => item.post_id === postId)
.map((item, index) => `${userList1.length + index + 1}. ${item.user.username}`);
const userList = [...userList1, ...userList2];
await navigator.clipboard.writeText(userList.join('\n'));
//console.log('User list copied to clipboard!');
alert('copied !');
} catch (err) {
//console.error('Failed to copy: ', err);
alert('Failed !');
}
});
/*copyUserListButton.addEventListener('click', async () => {
const requestUrl = `https://linux.do/discourse-reactions/posts/${articleElement.dataset.postId}/reactions-users.json`;
const response = await fetch(requestUrl);
const data = await response.json();
const userList = data.reaction_users
.flatMap(reaction => reaction.users)
.map((user, index) => `${index + 1}. ${user.username}`);
navigator.clipboard.writeText(userList.join('\n'))
.then(() => {
console.log('User list copied to clipboard!');
})
.catch(err => {
console.error('Failed to copy: ', err);
});
});*/
// 將按鈕添加到 newText 元素
newText.appendChild(copyPostIdButton);
newText.appendChild(copyRequestUrlButton);
newText.appendChild(copyUserListButton);
});
avatarDiv.appendChild(newText);
}
}
function addFloorListener() {
// 6. 处理现有的 article 元素
const articleElements = Array.from(document.querySelectorAll('article'))
.filter(articleElement => articleElement.id !== undefined);
articleElements.forEach(articleElement => {
handleArticle(articleElement);
});
// 7. 监听新的 article 元素的添加
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
//console.log(mutation);
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach(node => {
/*if (node.tagName === 'ARTICLE') {
handleArticle(node);
console.log("run F");
}*/
// 6. 处理现有的 article 元素
const articleElements = Array.from(document.querySelectorAll('article'))
.filter(articleElement => articleElement.id !== undefined);
articleElements.forEach(articleElement => {
handleArticle(articleElement);
});
});
}
});
});
observer.observe(document.body, {childList: true, subtree: true});
}
(function () {
("use strict");
checkFirstRun();
addFloorListener();
})();