您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
(我已经安装了用户样式管理器,让我安装!)
// ==UserScript==
// @name Novel Ranking Filter [No GM_API Version]
// @name:ja 小説ランキングフィルター [GM_APIなし]
// @namespace https://gf.qytechs.cn/en/users/1264733
// @version 2024-06-19
// @description Novel Ranking Filtering Bookmarklet for Mobile Browser
// @description:ja モバイルブラウザ用小説ランキングフィルタリングブックマークレット
// @author LE37
// @license MIT
// @include https://www.alphapolis.co.jp/novel/index*
// @include https://www.alphapolis.co.jp/novel/ranking/*
// @include https://kakuyomu.jp/genr*
// @include https://kakuyomu.jp/pick*
// @include https://kakuyomu.jp/rank*
// @include https://kakuyomu.jp/sear*
// @include https://kakuyomu.jp/rece*
// @include https://syosetu.org/?mode=rank*
// @include https://yomou.syosetu.com/rank/*
// @include https://yomou.syosetu.com/search*
// @exclude https://www.alphapolis.co.jp/novel/ranking/annual
// @exclude https://yomou.syosetu.com/rank/top/
// @grant none
// ==/UserScript==
(()=>{
/*LS20240619*/
'use strict';
// GM key, Nodelist, userLink, userid, tag, alt;
let gMk, eNo, eUl, sId, sTg, eAt;
// View mode
let cSv = false;
// Show/hide Blocklist
let sFb = false;
// Client type
const rMb = navigator.userAgent.includes("Mobile");
const path = location.pathname;
switch (location.host) {
case "www.alphapolis.co.jp":
gMk = "A";
eNo = "div.section";
eUl = "div.author>a";
sId = /detail\/(\d+)$/;
sTg = "li.tag a";
break;
case "syosetu.org":
gMk = "H";
eNo = rMb ? "div.search_box" : "div.section3";
eUl = null;
sId = /:(.*)/;
sTg = rMb ? 'span[id^="tag_"]' : 'div.all_keyword:nth-child(9) a';
eAt = rMb ? "p:nth-child(2)" : "div.blo_title_sak";
break;
case "kakuyomu.jp":
gMk = "K";
sId = /users\/(.*)$/;
if (path.startsWith("/search")) {
eNo = rMb ? 'div[class*="Spacer_margin-ml-m__"]' : 'div[class*="NewBox_borderSize-bb"]';
eUl = rMb ? 'span[class*="workLabelAuthor__"] a' : "div.partialGiftWidgetActivityName>a";
sTg = 'a[href^="/tags/"]';
} else if (path.startsWith("/recent_r")) {
eNo = "div.recentReviews-item";
eUl = "a.widget-workCard-authorLabel";
sTg = 'a[href^="/tags/"]';
} else {
eNo = "div.widget-work";
eUl = "a.widget-workCard-authorLabel";
sTg = "a[itemprop='keywords']";
}
break;
case "yomou.syosetu.com":
gMk = "N";
if (path.startsWith("/search")) {
eNo = rMb ? "div.smpnovel_list" : "div.searchkekka_box";
eUl = rMb ? null : "a:nth-child(2)";
sId = rMb ? /:(.*)/ : /\/(\d+)/;
sTg = 'a[href*="?word"]';
eAt = "p.author";
} else {
eNo = "div.p-ranklist-item";
eUl = "div.p-ranklist-item__author a";
sId = /\/(\d+)/;
sTg = "div.p-ranklist-item__keyword a";
}
break;
}
//console.log( {gMk, eNo, eUl, sId, sTg, eAt} );
// Read list
const G = JSON.parse(localStorage.getItem(gMk));
let O = G ? G : { AL:[], TL:[] };
let tal = O.AL;
let ttl = O.TL;
// Save list
function USV() {
O = { AL:tal, TL:ttl };
localStorage.setItem(gMk, JSON.stringify(O));
}
// Sort list
function UST() {
tal.sort();
ttl.sort();
USV();
}
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// Script fire time
if (gMk === "K" && path.startsWith("/search")) {
sleep(1500).then(() => FMD());
} else {
FMD();
}
CFB();
// Filtering multiple targets
function FMD() {
const no = document.querySelectorAll(eNo);
for (let i = 0; i < no.length; i++) {
let rBk = false;
let uId;
// Filtering content contain single id(link) or text
let eLk = eUl ? no[i].querySelector(eUl) : no[i].querySelector(eAt);
if ( eLk !== null
|| (gMk === "N" && rMb) ) {
if (!eLk) {
// Narou search mobile no author link
if (gMk === "N") {
const tca = document.createElement("p");
tca.classList.add("author");
tca.style.color = "#fe7643";
const head = no[i].querySelector("div.accordion_head");
// AD
if (!head) {
//console.log("===A D===");
//rBk = true;
continue;
}
tca.textContent = head.textContent.split("\n")[3];
no[i].querySelector("a.read_button").after(tca);
eLk = tca;
uId = eLk.textContent.match(sId)[1];
}
} else {
uId = eUl ? eLk.href.match(sId)[1] : eLk.textContent.match(sId)[1];
}
//console.log(uId);
rBk = CHK(eLk, "a", tal, uId);
}
if (sTg && !rBk) {
// Filtering content contain multiple tags(text)
// Tag node
let tno;
// Hameln mobile origin tag, custom tag
let tot, tct;
if (gMk === "H" && rMb) {
tot = no[i].querySelector(".trigger p:nth-child(4)");
tct = no[i].querySelector(sTg);
if (!tct) {
tno = tot.textContent.slice(3).match(/[^\s]+/g);
tot.innerHTML = "";
} else {
tno = no[i].querySelectorAll(sTg);
}
} else {
tno = no[i].querySelectorAll(sTg);
}
for (let j = 0; j < tno.length; j++) {
let tag;
if (tot && !tct) {
tag = tno[j];
tot.innerHTML += '<span id="tag_' + j + '">' + tag + '</span>';
} else {
tag = tno[j].textContent;
}
//console.log(tag);
rBk = tot && !tct ? CHK(no[i].querySelector("span#tag_"+j), "t", ttl, tag) : CHK(tno[j], "t", ttl, tag);
if (rBk) break;
}
}
// Blocked show type
no[i].style.display = !cSv && rBk ? "none" : "";
no[i].style.opacity = cSv && rBk ? "0.5" : "1";
}
}
// Check keyword
function CHK(ele, n, l, s) {
const r = l.some((v) => s === v);
if (!ele.classList.contains("c_h_k")) {
ele.classList.add("c_h_k");
ele.setAttribute("data-lkw", n + s);
}
if (cSv) {
ele.style.border = r ? "thin solid fuchsia" : "thin solid dodgerblue";
} else {
ele.style.border = "none";
}
return r;
}
// Select mode
function SVM() {
const btn = document.getElementById("nrf_fcb");
if (!cSv) {
cSv = true;
btn.textContent = "📙";
document.addEventListener("click", ECH);
} else {
cSv = false;
btn.textContent = "📘";
document.removeEventListener("click", ECH);
// Auto save list
USV();
}
FMD();
}
// Handler
function ECH(e) {
e.preventDefault();
const tEle = e.target.classList.contains("c_h_k") ? e.target
: e.target.parentElement.classList.contains("c_h_k") ? e.target.parentElement
: null;
//console.log(tEle);
if (tEle) {
const tda = tEle.getAttribute("data-lkw");
const tlst = tda.slice(0, 1) === "a" ? tal : ttl;
const tid = tda.slice(1);
const li = tlst.findIndex((v) => v === tid);
if (li !== -1) {
tlst.splice(li,1);
} else {
tlst.push(tid);
}
FMD();
}
}
// Create Blocklists Menu
function CBM() {
if (!document.getElementById("nrf_blm")) {
const cbl = document.body.appendChild(document.createElement("div"));
const pos = !rMb ? " width: 50%; left: 25%;" : " width: 98%; left: 1%;";
cbl.id = "nrf_blm";
cbl.style = "position: fixed;" + pos + " overflow-y: scroll; height: 52%; top:10%; z-index: 9999; background-color: #f1f3f5; display: none;";
}
const blm = document.getElementById("nrf_blm");
if (!sFb) {
sFb = true;
UBM();
blm.style.display = "";
blm.addEventListener("click", DBL);
} else {
sFb = false;
blm.style.display = "none";
blm.removeEventListener("click", DBL);
blm.innerHTML = "";
}
}
// Delete Block List
function DBL(e) {
if (e.target.classList.contains("nrf_dbl")) {
const key = e.target.textContent;
localStorage.removeItem(key);
UBM();
// Delete current
if (key === gMk) {
// Delete cache
tal = [];
ttl = [];
USV();
FMD();
}
}
}
// Update Blocklists Menu
function UBM() {
const blm = document.getElementById("nrf_blm");
blm.innerHTML = "";
Object.keys(localStorage).forEach(k => {
blm.innerHTML += '<p style="margin-left: 1em; font-size: 1em; line-height: 2em;">' +
'<span class="nrf_dbl" type="button" style="color: red; cursor: pointer;">' + k + '</span>' +
'<span>: ' + localStorage.getItem(k) + '</span>' +
'</p>';
});
}
// Create Float Button
function CFB() {
const btn = document.body.appendChild(document.createElement("button"));
// Button Style
btn.id = "nrf_fcb";
btn.textContent = "📘";
btn.style = "position: fixed; bottom: 2em; right: 2em; width: 44px; height: 44px; z-index: 9999; font-size: 200%; opacity: 50%; cursor:pointer; border: none; padding: unset;";
btn.type = "button";
btn.addEventListener("click", (e) => { SVM(); });
btn.addEventListener("dblclick", (e) => { CBM(); });
}
})();