// ==UserScript==
// @name 笔趣阁优化 for iOS
// @namespace Violentmonkey Scripts
// @match https://lingjingxingzhe.com/*.html
// @match https://m.xxbiqudu.com/*.html
// @grant GM.addStyle
// @grant GM.setValue
// @grant GM.getValue
// @grant GM.deleteValue
// @version 0.0.1
// @author LinHQ
// @license GPLv3
// @description 2023/2/4 14:26:46
// ==/UserScript==
(async () => {
const version = '0.0.1'
document.head.insertAdjacentHTML('beforeend', '<meta name="theme-color" content="black">')
const typo = {
fontSize: 20,
lineHeight: 1.5
}
let sites = [
{
host: 'lingjingxingzhe.com',
title: 'h1.title',
content: '#content',
segment: 'div.read_tip', // 控制拼页的元素,不能隐藏
filters: ['.header', '.nav'],
banRegex: []
},
{
host: 'm.xxbiqudu.com',
title: '.title',
content: 'div.text',
segment: 'div.navigator-nobutton', // 控制拼页的元素,不能隐藏
filters: ['.navigator-no', '.title+script+div', '.google-auto-placed'],
banRegex: [/请记住.+网址/g]
}
]
, basicStyle = `
body {
padding-top: 0!important;
}
body * {
background: black!important;
}
img {
display: none!important;
}
`
, state = null
/**
* 注入基本样式并加载配置
*
* @return
*/
async function boot() {
const currentSite = sites.find(site => document.URL.includes(site.host))
basicStyle += `
${currentSite.filters.join(',')} {display: none!important}
${currentSite.content} {background: black; color: #d3d3d3;}
`
GM.addStyle(basicStyle)
const defaultState = {
version: version,
previous: '',
next: '',
current: document.URL
}
state = await GM.getValue(currentSite.host, defaultState)
// 上次状态还原
if (state.current !== document.URL) {
if (confirm("是否还原上次阅读状态?")) {
await GM.deleteValue(currentSite.host)
window.open(state.current, "_self")
} else {
// 重新加载状态
Object.assign(state, defaultState)
}
}
// 重新获取状态
const links = Array.from(document.querySelectorAll('a'))
for (const link of links) {
// 仅查找一次
if (state.next && state.previous) break
if (link.textContent.includes('上一')) {
state.previous = link.href
} else if (link.textContent.includes('下一')) {
state.next = link.href
}
}
GM.setValue(currentSite.host, state)
return currentSite
}
function sleep(time) {
return new Promise(res => {
setTimeout(res, time)
})
}
const site = await boot()
const txt = document.querySelector(site.content)
, segment = document.querySelector(site.segment)
if (!segment) {
return console.error('无法寻找到 segment,请重新配置脚本。')
}
const observer = new IntersectionObserver(async entries => {
if (entries[0].isIntersecting) {
observer.unobserve(segment)
// 下面开始执行无限加载
try {
const newPage = await fetch(state.next).then(resp => resp.arrayBuffer()),
decoder = new TextDecoder(document.characterSet)
const newDoc = new DOMParser().parseFromString(decoder.decode(newPage), 'text/html')
txt.insertAdjacentHTML("beforeend", "<br><hr style='border: unset;border-top: 1px solid gray; margin: ${states.lineHeight}px 0'>")
txt.insertAdjacentHTML("beforeend", `<h3 style='width: 100%; text-align: center; color: gray;'>${newDoc.querySelector(site.title).textContent}</h3>`)
let newText = newDoc.querySelector(site.content).innerHTML
site.banRegex.forEach(reg => newText = newText.replaceAll(reg, ''))
txt.insertAdjacentHTML('beforeend', newText)
// 更新状态
state.previous = state.current
state.current = state.next
state.next = Array.from(newDoc.querySelectorAll('a')).findLast(a => a.textContent.includes('下一')).href ?? ''
GM.setValue(site.host, state)
} catch (e) {
console.error(e)
} finally {
observer.observe(segment)
}
}
}, {
// 进入可见区域之前进行检测
rootMargin: window.innerHeight / 3 + 'px'
})
observer.observe(segment)
txt.style.fontSize = `${typo.fontSize}px`
txt.style.lineHeight = typo.lineHeight + ''
const viewHeight = window.innerHeight,
viewWidth = window.innerWidth
txt.addEventListener('click', event => {
/*
* 先判断上下翻页
* 再判断左右跳章
*/
if (event.clientY <= viewHeight / 3) {
window.scrollBy(0, -1 * viewHeight - typo.fontSize * 2)
} else if (event.clientY >= viewHeight * 3 / 4) {
window.scrollBy(0, viewHeight - typo.fontSize * 2)
} else {
const {previous, next, current} = state
if (event.clientX < viewWidth / 3) {
GM.deleteValue(site.host).then(() => window.open(previous, '_self'))
} else if (event.clientX > viewWidth * 3 / 4) {
GM.deleteValue(site.host).then(() => window.open(next, '_self'))
} else {
if (confirm('是否确认重载?')) {
GM.deleteValue(site.host).then(() => window.open(current, '_self'))
}
}
}
})
})()