From 06b6e500addd3de02ebac6d2ce3b1f3aa5a6a295 Mon Sep 17 00:00:00 2001 From: khanghy1000 <46063255+khanghy1000@users.noreply.github.com> Date: Fri, 9 Jan 2026 18:54:46 +0700 Subject: [PATCH 01/10] fix: update element selectors - Use more stable selectors instead of generated class names. - Fix removeTagButton/clearTagsButton visibility in edit mode. - Tested: labeling, remove all tags from selected works, delete a bookmark tag. --- index.js | 248 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 158 insertions(+), 90 deletions(-) diff --git a/index.js b/index.js index 8cbd0eb..7e9be6d 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,7 @@ // @name Pixiv收藏夹自动标签 // @name:en Label Pixiv Bookmarks // @namespace http://tampermonkey.net/ -// @version 5.18 +// @version 5.19 // @description 自动为Pixiv收藏夹内图片打上已有的标签,并可以搜索收藏夹 // @description:en Automatically add existing labels for images in the bookmarks, and users are able to search the bookmarks // @author philimao @@ -20,7 +20,7 @@ // ==/UserScript== -const version = "5.18"; +const version = "5.19"; const latest = `♢ 处理Pixiv组件类名更新 ♢ Update constants due to change of element class names ♢ 并非所有功能都已恢复,仅验证了设置标签功能 @@ -50,19 +50,20 @@ let unsafeWindow_ = unsafeWindow, GM_registerMenuCommand_ = GM_registerMenuCommand; // selectors -const BANNER = ".sc-8bf48ebe-0"; +const BANNER = ".bg-surface1 > div:first-child"; const THEME_CONTAINER = "html"; -const WORK_SECTION = "section.sc-3d8ed48f-0"; // 作品section,从works->pagination -const WORK_CONTAINER = "ul.sc-7d21cb21-1.jELUak"; // 仅包含作品 -const PAGE_BODY = ".sc-2b45994f-0.cUskQy"; // 自主页、收藏起下方 -const EDIT_BUTTON_CONTAINER = ".sc-9d335d39-6.cfUrtF"; // 管理收藏按钮父容器,包含左侧作品文字 -const REMOVE_BOOKMARK_CONTAINER = ".sc-231887f1-4.kvBpUA"; -const WORK_NUM = ".sc-b5e6ab10-0.hfQbJx"; -const ADD_TAGS_MODAL_ENTRY = ".bbTNLI"; // 原生添加标签窗口中标签按钮 -const ALL_TAGS_BUTTON = ".jkGZFM"; // 标签切换窗口触发按钮 -const ALL_TAGS_CONTAINER = ".hpRxDJ"; // 标签按钮容器 -const ALL_TAGS_MODAL = ".ggMyQW"; // 原生标签切换窗口 -const ALL_TAGS_MODAL_CONTAINER = ".gOPhqx"; // 原生标签切换窗口中标签按钮容器 +const WORK_SECTION = "section:has(h2)"; // 作品section,从works->pagination +const WORK_CONTAINER = "section ul"; // 仅包含作品 +const PAGE_BODY = '#__next [data-overlay-container="true"] > div:first-child'; // 自主页、收藏起下方 +const EDIT_BUTTON_CONTAINER = "section > div:first-child"; // 管理收藏按钮父容器,包含左侧作品文字 +const REMOVE_BOOKMARK_CONTAINER = + "section > div:nth-child(3) > div > div:first-child"; +const WORK_NUM = "section h2 + div"; +const ADD_TAGS_MODAL_ENTRY = 'ul[role="listbox"] button, ul li button'; // 原生添加标签窗口中标签按钮 +const ALL_TAGS_BUTTON = + "section > div:nth-child(2) > div:first-child > div:last-child"; // 标签切换窗口触发按钮 +const ALL_TAGS_CONTAINER = "section > div:nth-child(2) > div:first-child"; // 标签按钮容器 +const ALL_TAGS_MODAL_CONTAINER = '[role="dialog"] > div'; // 原生标签切换窗口中标签按钮容器 function getCharacterName(tag) { return tag.split("(")[0]; @@ -127,6 +128,7 @@ function getValue(name, defaultValue) { function setValue(name, value) { if (name === "synonymDict" && (!value || !Object.keys(value).length)) return; GM_setValue_(name, value); + // backup let valueArray = JSON.parse(window.localStorage.getItem(name)); if (!valueArray) valueArray = []; @@ -1082,7 +1084,7 @@ async function handleSearch(evt) { document.querySelector("#search_prompt").innerText = "无结果 / No Result"; else document.querySelector("#search_prompt").innerText = ` - 当前搜索进度 / Searched:${searchOffset} / ${totalBookmarks} + 当前搜索进度 / Searched: ${searchOffset} / ${totalBookmarks} `; if (searchOffset < totalBookmarks) document.querySelector("#search_more").style.display = "block"; @@ -1116,8 +1118,8 @@ function displayWork(work, resultsDiv, textColor) {
R-18
- - + + @@ -2818,7 +2820,6 @@ Tag ${tag} will be renamed to ${newName}.\n All related works (both public and p }); // all tags selection modal - const c_ = ALL_TAGS_CONTAINER.slice(1); const allTagsModal = document.createElement("div"); allTagsModal.className = "modal fade"; allTagsModal.id = "all_tags_modal"; @@ -2829,21 +2830,21 @@ Tag ${tag} will be renamed to ${newName}.\n All related works (both public and p
- +
`; - const parodyContainer = allTagsModal.querySelector(ALL_TAGS_CONTAINER); - const characterContainer = [ - ...allTagsModal.querySelectorAll(ALL_TAGS_CONTAINER), - ][1]; + const parodyContainer = allTagsModal.querySelector( + ".all-tags-parody-container", + ); + const characterContainer = allTagsModal.querySelector( + ".all-tags-character-container", + ); userTags.forEach((tag) => { const d = document.createElement("div"); - d.className = "sc-1jxp5wn-2 cdeTmC"; + d.style.cssText = "display: inline-flex; margin: 4px;"; d.innerHTML = ` -
-
-
-
#${tag}
-
+
+
+
#${tag}
`; d.addEventListener("click", async () => { @@ -3058,8 +3059,18 @@ async function initializeVariables() { const prevClearTag = theme ? "dydUg" : "jbzOgz"; const clearTag = theme ? "jbzOgz" : "dydUg"; const clearTagsButton = document.querySelector("#clear_tags_button"); - if (clearTagsButton) - clearTagsButton.children[0].classList.replace(prevClearTag, clearTag); + if (clearTagsButton) { + const clearButtonBgColor = theme + ? "rgba(255, 255, 255, 0.08)" + : "rgba(0, 0, 0, 0.04)"; + const clearButtonTextColor = theme + ? "rgba(255, 255, 255, 0.88)" + : "rgba(0, 0, 0, 0.88)"; + clearTagsButton.querySelector("div").style.backgroundColor = + clearButtonBgColor; + clearTagsButton.querySelector("div > div").style.color = + clearButtonTextColor; + } }).observe(themeDiv, { attributes: true }); synonymDict = getValue("synonymDict", {}); @@ -3105,37 +3116,60 @@ async function injectElements() {