// ==UserScript==
// @name 小报童目录
// @namespace http://tampermonkey.net/
// @version 1.0
// @description 在文章页中添加小册目录,需要先访问一次小册的目录表做缓存
// @author ibucoin
// @match https://xiaobot.net/*
// @grant unsafeWindow
// @run-at document-start
// @grant GM_addStyle
// @license MIT
// @downloadURL https://update.greasyfork.icu/scripts/498214/%E5%B0%8F%E6%8A%A5%E7%AB%A5%E7%9B%AE%E5%BD%95.user.js
// @updateURL https://update.greasyfork.icu/scripts/498214/%E5%B0%8F%E6%8A%A5%E7%AB%A5%E7%9B%AE%E5%BD%95.meta.js
// ==/UserScript==
(function () {
'use strict';
// 添加 CSS 样式
GM_addStyle(
`
.list-info {
background: #fffdfc;
mix-blend-mode: normal;
-webkit-backdrop-filter: blur(40px);
backdrop-filter: blur(40px);
border-radius: 6px;
margin-bottom: 20px;
padding: 18px 19px;
width: 262px;
margin-top: 30px;
margin-left: 15px;
height:400px;
}
.fiexed {
overflow-y: auto;
position: sticky;
top: 80px;
border-top-left-radius: 0.5rem;
border-bottom-left-radius: 0.5rem;
background-color: #ffffff;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.list-info a {
color:#1f2937;
}
.list-info li {
list-style:none;
}
.item {
font-size: 14px;
display: block;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
color: #1F2937;
}
.item.active {
color:red;
}
.item:hover {
background-color: #F3F4F6;
}
.reset-btn {
color: #fff;
background: #b14b43;
font-size: 12px;
width:100px;
text-align:center;
padding:10px 0;
margin-top:10px;
line-height: 17px;
border-radius: 2px;
cursor:pointer;
}
`
);
// 设置缓存数据
function setCache(key, value) {
localStorage.setItem(key, value)
}
// 获取缓存数据
function getCache(key) {
return localStorage.getItem(key)
}
let slug = ''
setTimeout(() => {
const searchBox = document.querySelector('.searchBox');
console.log('searchBox',searchBox)
let button = `
重置列表缓存
`
searchBox.insertAdjacentHTML('afterend', button);
document.getElementById('reset-btn').addEventListener('click', clearCache);
function clearCache() {
//获取当前的key
let currentUrl = window.location.href;
const regex = /\/p\/([^\/]+)/;
const match = currentUrl.match(regex);
if (match && match[1]) {
const key = match[1];
localStorage.removeItem(`${key}_data`)
location.reload()
}
}
}, 1500)
console.log(window.location.href)
// 创建一个函数来处理 XHR 请求
function handleXHRRequest(xhr) {
// 监听 XHR 的 load 事件
xhr.addEventListener('load', function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let url = xhr.responseURL
var pattern = /^https:\/\/api\.xiaobot\.net\/paper\/(.*?)\/post\?/;
const sidebars = document.querySelectorAll('.list-info');
sidebars.forEach(element => {
element.remove();
});
var match = url.match(pattern);
if (match && match[1]) {
let bookSlug = match[1]
let {
data
} = JSON.parse(xhr.response)
const newData = data.map(({
title,
uuid
}) => ({
title,
uuid
}));
let key = `${bookSlug}_data`
//先获取缓存中的数据
let cachedData = JSON.parse(localStorage.getItem(key)) || [];
let insertData = newData.filter(item => !cachedData.some(cachedItem => cachedItem.uuid ===
item.uuid) && (item.title != null));
if (insertData.length > 0) {
cachedData = cachedData.concat(insertData);
setCache(key, JSON.stringify(cachedData))
}
}
function isMatchingPostURL(url) {
var pattern = /^https:\/\/api\.xiaobot\.net\/post\/[^/]+$/;
return pattern.test(url);
}
if (isMatchingPostURL(url)) {
//进入详细页获取缓存数据
const {
data
} = JSON.parse(xhr.response)
let bookSlug = data.paper.slug
slug = bookSlug
window.setTimeout(() => {
//判断当前是否在post页
const sharePaper = document.querySelector('.share-paper');
const sidebars = document.querySelectorAll('.list-info');
sidebars.forEach(element => {
element.remove();
});
let key = `${slug}_data`
let cacheData = JSON.parse(getCache(key))
let html = ""
let content = ""
function getLastString(url) {
const regex = /\/([^/]+)$/;
const match = url.match(regex);
return match ? match[1] : null;
}
let pathname = window.location.url
let keyUuid = getLastString(url)
let total = cacheData.length
let prePage = ''
let nextPage = ''
cacheData.forEach((item, index) => {
let link = `https://xiaobot.net/post/${item.uuid}`
if (item.title) {
let active = '';
if (keyUuid && keyUuid == item.uuid) {
active = 'active'
prePage = cacheData[index - 1] ?? ''
nextPage = cacheData[index + 1] ?? ''
}
let no = total - index
let li =
`${no} ${item.title}`
content += li
}
})
html =
``
function getPageLink(item) {
let link = `https://xiaobot.net/post/${item.uuid}`
let title = item.title
if (title) {
return `${title}`
} else {
return '无'
}
}
let prePageLink = getPageLink(prePage)
let nextPageLink = getPageLink(nextPage)
const pageHtml =
`
下一篇:${prePageLink}
上一篇:${nextPageLink}
`
const pagePosition = document.querySelector('.light_feedback');
let webUrl = window.location.href
if (!isMatchingPostURL(url)) {
return
}
sharePaper.insertAdjacentHTML('afterend', html);
pagePosition.insertAdjacentHTML('beforebegin', pageHtml);
//scroll to this
let contentElement = document.getElementById('sidelist')
let targetElement = document.querySelector('.item.active')
const targetPosition = targetElement.offsetTop;
const containerHeight = contentElement.clientHeight;
const targetHeight = targetElement.offsetHeight;
const scrollPosition = targetPosition - (containerHeight / 2) + (
targetHeight / 2);
contentElement.scrollTo({
top: scrollPosition,
behavior: 'smooth'
});
//添加上一篇和下一篇
}, 1000);
}
} else {
console.log('请求失败,状态码:', xhr.status);
}
}
});
// 监听 XHR 的 error 事件
xhr.addEventListener('error', function () {
console.log('请求出错');
});
}
// 保存原始的 XHR open 和 send 方法
var originalOpen = XMLHttpRequest.prototype.open;
var originalSend = XMLHttpRequest.prototype.send;
function updateLimitParameter(url, newLimit) {
return url.replace(/limit=\d+/, `limit=${newLimit}`);
}
// 重写 XHR 的 open 方法
XMLHttpRequest.prototype.open = function () {
handleXHRRequest(this);
originalOpen.apply(this, arguments);
};
// 重写 XHR 的 send 方法
XMLHttpRequest.prototype.send = function () {
originalSend.apply(this, arguments);
};
})();