// ==UserScript==
// @name Deqi Prefech
// @namespace https://greasyfork.org/zh-CN/users/14997-lrh3321
// @version 2025-08-270
// @author LRH3321
// @description 得奇小说网, biqu33.cc, ddxiaoshuo.cc, cuoceng.com 看单个章节免翻页,把小说伪装成代码
// @license MIT
// @icon https://www.google.com/s2/favicons?sz=64&domain=deqixs.com
// @homepageURL https://greasyfork.org/zh-CN/scripts/537588-deqi-prefech
// @source https://github.com/lrh3321/deqi-prefetch
// @supportURL https://github.com/lrh3321/deqi-prefetch/issues
// @match http*://www.deqixs.com/pifu/
// @match http*://www.deqixs.com/xiaoshuo/*/*.html
// @match http*://www.deqixs.com/xiaoshuo/*/
// @match http*://www.biqu33.cc/*
// @match http*://www.ddxiaoshuo.cc/*
// @match http*://cuoceng.com/*
// @match http*://www.cuoceng.com/*
// @require https://cdn.jsdelivr.net/npm/[email protected]/prism.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/plugins/match-braces/prism-match-braces.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/plugins/line-numbers/prism-line-numbers.min.js
// @tag novels
// @connect self
// @grant GM_addElement
// @grant GM_addStyle
// @grant GM_getResourceURL
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @run-at document-end
// ==/UserScript==
(function () {
'use strict';
const d=new Set;const importCSS = async e=>{d.has(e)||(d.add(e),(t=>{typeof GM_addStyle=="function"?GM_addStyle(t):document.head.appendChild(document.createElement("style")).append(t);})(e));};
const styleCss = '[data-comment=normal] span.token.comment{font-style:normal}img[alt],.menu,.header p,h2 a,div.footer,div.container>ul.list{display:none}h2.op a{display:block}body>div.container,body>div.header,#article_main,#ss-reader-main{width:var(--container-width, "1200px")}span.token.comment{font-family:var(--novel-font-family)!important}body{-webkit-backdrop-filter:contrast(110%);backdrop-filter:contrast(110%);--primary-color: black;--secondary-color: gray}img{visibility:hidden}form{color:var(--primary-color)}form fieldset{display:block;min-inline-size:min-content;margin-inline:2px;margin-top:1rem;margin-bottom:1rem;border-width:2px;border-style:groove;border-color:gray;border-image:initial;padding-block:.35em .625em;padding-inline:.75em}fieldset label{display:flex;width:fit-content;gap:.4rem;white-space:nowrap}label input{padding-left:.5rem}editable-list li{width:fit-content;height:fit-content;display:flex;align-items:baseline}editable-list figure{margin:0}editable-list figcaption{-webkit-backdrop-filter:contrast(120%);backdrop-filter:contrast(120%);text-align:end}editable-list .icon{border:none;cursor:pointer;font-size:1.8rem}editable-list textarea{border-radius:.75rem;padding-block:.25rem;padding-inline:.75rem;width:95%}editable-list ul{display:flex;max-width:80svw;flex-wrap:wrap;justify-content:flex-start;column-gap:1rem}#header,#main .container-fluid,#article_main .row{display:none}#article_main{background:transparent}body>[style*="position:fixed"]{display:none!important}#article_main #page-links a,#article_main #page-links span{padding:1px 10px;width:28px;height:28px;display:inline-block;margin-right:10px;background:#1a73e8;color:#fff!important;line-height:25px;text-align:center;text-decoration:none!important}#article_main #page-links span{background:#ccc}#main a[role=button]{color:#555}#main a[role=button]:hover{text-decoration:none;color:#fa2080}#ss-reader-main,.info-title{border-width:0px;border-bottom-width:0px;background-color:transparent!important}#ss-reader-main .info-commend,#ss-reader-main .reader-hr,#ss-reader-main .readSet,#ss-reader-main .info-chapters-title,#ss-reader-main h1,body.read_style_1 .header,body.read_style_1 #showDetail,#readcontent .textbox.cf,body.read_style_1 .textinfo{display:none}.article-root{justify-self:center;grid-template-rows:auto 1fr auto;height:100vh;display:grid;width:var(--container-width, "1200px");color:var(--primary-color)}.article-root .breadcrumb,.article-root .breadcrumb a{display:flex;flex-wrap:wrap;gap:1rem;align-items:center;background-color:transparent;color:var(--secondary-color)}.article-root .breadcrumb li{list-style-type:none;text-wrap:nowrap}.article-root .breadcrumb li[aria-hidden]{opacity:.5}.article-root .breadcrumb a :hover{opacity:.6;text-decoration:underline}.article-root .article-title{font-size:1.5rem;display:flex;justify-content:center}.article-root .article-title code{background-color:transparent}.article-root section.img-container{display:flex;flex-direction:column}.article-root section.img-container img{visibility:initial}.article-root .article-nav{justify-self:center;background:transparent;opacity:.6}.article-root .article-nav a{padding-inline:1rem;background-color:transparent;color:var(--secondary-color)}body[hidden]{display:none!important}';
importCSS(styleCss);
var _GM_addElement = (() => typeof GM_addElement != "undefined" ? GM_addElement : void 0)();
var _GM_getValue = (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
var _GM_registerMenuCommand = (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
var _GM_setValue = (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
var _GM_xmlhttpRequest = (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
function getCodeThemeURL(theme) {
const officialThemes = new Set([
"prism",
"prism-dark",
"prism-funky",
"prism-okaidia",
"prism-twilight",
"prism-coy",
"prism-solarizedlight",
"prism-tomorrow"
]);
if (officialThemes.has(theme)) {
return `https://dev.prismjs.com/themes/${theme}.min.css`;
}
return `https://cdnjs.cloudflare.com/ajax/libs/prism-themes/1.9.0/${theme}.min.css`;
}
function releaseCopy() {
const $ = globalThis.$;
if ($) {
const doc = $(document);
doc.off("contextmenu");
doc.off("copy");
doc.off("cut");
}
document.onclick = null;
document.oncontextmenu = null;
document.oncopy = null;
document.oncut = null;
document.body.onclick = null;
document.body.oncontextmenu = null;
document.body.oncopy = null;
document.body.oncut = null;
const native_replaceState = history.replaceState;
history.replaceState = function(data, unused, url) {
if (url) {
if (url instanceof URL) {
if (url.hostname != location.hostname) {
return;
}
} else {
if (url.startsWith("http://") || url.startsWith("https://")) {
if (new URL(url).hostname != location.hostname) {
return;
}
}
}
}
native_replaceState(data, unused, url);
};
}
const isInIframe = window.self !== window.top;
function ensureDoc(doc) {
if (typeof doc === "string") {
const parser = new DOMParser();
const realDoc = parser.parseFromString(doc, "text/html");
return realDoc;
}
return doc;
}
function setAccessKeys(nav) {
const { prevAnchor, infoAnchor, nextAnchor } = nav;
if (prevAnchor) {
prevAnchor.accessKey = previousChapterAccessKey;
prevAnchor.ariaKeyShortcuts = `Alt+${previousChapterAccessKey}`;
}
if (infoAnchor) {
infoAnchor.accessKey = bookPageAccessKey;
infoAnchor.ariaKeyShortcuts = `Alt+${bookPageAccessKey}`;
}
if (nextAnchor) {
nextAnchor.accessKey = nextChapterAccessKey;
nextAnchor.ariaKeyShortcuts = `Alt+${nextChapterAccessKey}`;
}
}
function rebuildChapterBody(page) {
const newBody = document.createElement("body");
newBody.style = document.body.style.cssText;
newBody.dataset.comment = document.body.dataset.comment;
const root = document.createElement("div");
root.className = "article-root";
const header = buildNovelHeader(page);
const main = buildNovelMain(page);
const footer = buildNovelFooter(page.navigationBar);
root.append(header, main, footer);
newBody.append(root);
document.body.replaceWith(newBody);
return { root, header, main, footer };
}
function updateStyle(pre) {
const computedStyle = getComputedStyle(pre);
document.body.style.backgroundColor = getComputedStyle(pre).backgroundColor;
document.body.style.setProperty("--primary-color", computedStyle.color);
const comment = pre.querySelector("span.token.comment");
if (comment) {
const computedStyle2 = getComputedStyle(comment);
document.body.style.setProperty("--secondary-color", computedStyle2.color);
}
}
function buildNovelHeader(page) {
const { breadcrumbBar, title } = page;
const header = document.createElement("header");
if (breadcrumbBar) {
const breadcrumb = document.createElement("ol");
breadcrumb.className = "breadcrumb";
breadcrumbBar.querySelectorAll("a").forEach((a) => {
const li = document.createElement("li");
const newA = a.cloneNode(true);
li.appendChild(newA);
breadcrumb.appendChild(li);
const li2 = document.createElement("li");
li2.ariaHidden = "";
li2.innerHTML = "›";
breadcrumb.appendChild(li2);
});
breadcrumb.lastElementChild?.remove();
if (title) {
const li = document.createElement("li");
li.innerHTML = title;
breadcrumb.appendChild(li);
}
header.appendChild(breadcrumb);
}
return header;
}
function buildNovelMain(page) {
const { title, mainSection } = page;
const main = document.createElement("main");
const article = document.createElement("article");
if (title) {
const h2 = document.createElement("h2");
h2.className = "article-title";
h2.innerText = title;
h2.title = title;
article.appendChild(h2);
}
const section = document.createElement("section");
section.appendChild(mainSection);
article.appendChild(section);
main.appendChild(article);
return main;
}
function buildNovelFooter(nav) {
const footer = document.createElement("footer");
const navBar = document.createElement("nav");
navBar.className = "article-nav";
if (nav.prevAnchor) {
navBar.appendChild(nav.prevAnchor);
}
if (nav.infoAnchor) {
navBar.appendChild(nav.infoAnchor);
}
if (nav.nextAnchor) {
navBar.appendChild(nav.nextAnchor);
}
navBar.insertAdjacentHTML("beforeend", '<a href="/">小说列表</a>');
footer.appendChild(navBar);
return footer;
}
let extendLanguageElement = null;
function setupExtendLanguageSupport() {
if (!coreLanguages.has(codeLang)) {
console.log("loading language", codeLang);
const src = `https://dev.prismjs.com/components/prism-${codeLang}.js`;
if (extendLanguageElement?.src == src) {
return;
}
extendLanguageElement?.remove();
extendLanguageElement = _GM_addElement("script", { src });
}
}
function disguiseToCode(container) {
const fakeCodes = fakeCodeSnippet.split("====");
const getRandomCode = () => fakeCodes[Math.floor(Math.random() * fakeCodes.length)];
var lines = [];
const paragraphs = Array.from(container.querySelectorAll("p"));
let blockCommentStart = "/*";
let blockCommentEnd = "*/";
let shortCommnet = "";
switch (codeLang) {
case "clike":
case "javascript":
case "c":
case "csharp":
case "cpp":
case "go":
case "java":
case "kotlin":
case "rust":
case "php":
shortCommnet = "// ";
break;
case "python":
shortCommnet = "# ";
break;
case "markup":
blockCommentStart = "<!--";
blockCommentEnd = "-->";
break;
}
const codeSegments = [];
paragraphs.forEach((p) => {
const textContent = p.textContent.trim();
let line = "";
while (line.trim() == "") {
if (lines.length == 0) {
lines.push(...getRandomCode().split(/[\r]?\n/));
}
line = lines.shift();
if (line.trim().length === 1) {
codeSegments.push(line);
line = "";
}
}
const trimed = line.replace(/^[\s\t]+/, "");
if (trimed !== line) {
const prefix = line.substring(0, line.length - trimed.length);
if (textContent.length + shortCommnet.length + prefix.length < inlineLengthMax && shortCommnet != "") {
codeSegments.push(`${prefix}${shortCommnet}${textContent}`);
} else {
codeSegments.push(
`${prefix}${blockCommentStart}
${prefix} ${textContent}
${prefix}${blockCommentEnd}`
);
}
} else {
if (textContent.length + shortCommnet.length < inlineLengthMax && shortCommnet != "") {
codeSegments.push(`${shortCommnet}${textContent}`);
} else {
codeSegments.push(`${blockCommentStart}
${textContent}
${blockCommentEnd}`);
}
}
codeSegments.push(line);
p.remove();
});
codeSegments.push(...lines);
const pre = createPreformattedCode(codeSegments.join("\n"));
container.parentElement.replaceChild(pre, container);
highlightElement(pre, false, (_) => {
updateStyle(pre);
});
return pre;
}
function disguiseParagraphs(container) {
switch (disguiseMode) {
case "none":
container.style.fontSize = "var(--novel-font-size)";
container.style.fontFamily = "var(--novel-font-family)";
break;
case "code":
default:
return disguiseToCode(container);
}
return container;
}
function createPreformattedCode(snippet) {
const code = document.createElement("code");
code.className = `language-${codeLang} match-braces rainbow-braces`;
code.innerHTML = snippet;
const pre = document.createElement("pre");
pre.style.whiteSpace = "pre-wrap";
pre.style.textWrap = "pretty";
pre.style.overflowX = "auto";
pre.className = `language-${codeLang} match-braces rainbow-braces ${codeShowLineNumbers ? "line-numbers" : ""}`;
if (pre.firstChild) {
pre.replaceChild(code, pre.firstChild);
} else {
pre.appendChild(code);
}
return pre;
}
function highlightElement(el, async, callback) {
if (el instanceof HTMLElement) {
el.style.fontSize = "var(--novel-font-size)";
}
const codes = Array.from(el.querySelectorAll("code"));
const highlightAll = () => {
codes.forEach((code) => {
Prism.highlightElement(code, async, callback);
});
};
if (coreLanguages.has(codeLang)) {
highlightAll();
} else {
let count = 0;
const lazyHighlightElement = () => {
count++;
if (codeLang in Prism.languages) {
highlightAll();
return;
}
if (count > 10) {
return;
}
setTimeout(lazyHighlightElement, 200);
};
setTimeout(lazyHighlightElement, 200);
}
}
class EditableList extends HTMLElement {
itemList = null;
textInput = null;
codeSnippetsStore;
counter;
constructor() {
super();
this.addListItem = this.addListItem.bind(this);
this.handleRemoveItemListeners = this.handleRemoveItemListeners.bind(this);
this.removeListItem = this.removeListItem.bind(this);
this.counter = 0;
this.codeSnippetsStore = new Map();
}
lazyInit() {
this.innerHTML = `<h3>伪装代码段</h3>
<div>
<label>输入代码片段:</label>
<textarea rows="20" class="add-new-list-item-input"></textarea>
<button class="editable-list-add-item icon">⊕</button>
</div>
<ul class="item-list"></ul>`;
this.itemList = this.querySelector("ul.item-list");
this.textInput = this.querySelector(".add-new-list-item-input");
this.textInput.onkeydown = this.onKeydown.bind(this);
}
connectedCallback() {
this.lazyInit();
const addElementButton = this.querySelector(".editable-list-add-item");
addElementButton?.addEventListener("click", this.addListItem, false);
}
onKeydown(e) {
if (e.ctrlKey && e.key === "Enter") {
e.preventDefault();
this.addListItem();
}
}
addListItem() {
const textInput = this.textInput;
let snippet = textInput?.value.trim();
if (snippet) {
this.counter++;
const idx = this.counter.toString();
this.codeSnippetsStore.set(idx, snippet);
snippet = this.trimSnippet(snippet);
this.addCodeSnippet(idx, snippet);
textInput.value = "";
this.dispatchEvent(new CustomEvent("add-item"));
}
}
trimSnippet(s) {
const lines = s.split(/[\r\n]+/).filter((l) => l.trim());
return lines.join("\n");
}
updateCodeSnippets(snippets) {
this.codeSnippetsStore.clear();
snippets.forEach((snippet) => {
this.counter++;
snippet = this.trimSnippet(snippet);
this.codeSnippetsStore.set(this.counter.toString(), snippet);
});
this.render();
}
get codeSnippets() {
return Array.from(this.codeSnippetsStore.values());
}
render() {
if (!this.itemList) {
this.lazyInit();
}
this.itemList.innerHTML = ``;
this.codeSnippetsStore.forEach((snippet, idx) => {
this.addCodeSnippet(idx, snippet);
});
}
addCodeSnippet(idx, snippet) {
const li = document.createElement("li");
li.dataset.snippetId = idx;
const figure = document.createElement("figure");
const figcaption = document.createElement("figcaption");
const button = document.createElement("button");
const pre = createPreformattedCode(snippet);
button.classList.add("editable-list-remove-item", "icon");
button.innerHTML = "⊖";
figcaption.appendChild(button);
figure.appendChild(figcaption);
figure.appendChild(pre);
li.appendChild(figure);
this.itemList?.appendChild(li);
this.handleRemoveItemListeners([button]);
highlightElement(pre, false);
}
handleRemoveItemListeners(arrayOfElements) {
arrayOfElements.forEach((element) => {
element.addEventListener("click", this.removeListItem, false);
});
}
removeListItem(e) {
const parent = e.target?.parentNode;
if (parent) {
parent?.parentElement?.parentElement?.remove();
this.codeSnippetsStore.delete(parent?.parentElement?.parentElement?.dataset.snippetId || "");
this.dispatchEvent(new CustomEvent("remove-item"));
}
}
}
function setupEditableList() {
customElements.define("editable-list", EditableList);
}
let disguiseDebug = _GM_getValue("disguiseDebug", false);
let novelFontSize = _GM_getValue("novel-font-size", "16px");
let novelFontFamily = _GM_getValue(
"novel-font-family",
`system-ui, -apple-system, '微软雅黑', 'PingFang SC', BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif`
);
let disguiseMode = _GM_getValue("disguise-mode", "none");
let codeLang = _GM_getValue("code-lang", "javascript");
const defaultCodeSnippet = `var x = 1;
switch (x) {
case 1:
console.log('x 等于1');
case 2:
console.log('x 等于2');
default:
console.log('x 等于其他值');
}
====
switch (x) {
case 1:
console.log('x 等于1');
break;
case 2:
console.log('x 等于2');
break;
default:
console.log('x 等于其他值');
}
====
switch (1 + 3) {
case 2 + 2:
f();
break;
default:
neverHappens();
}
====
var x = 1;
switch (x) {
case true:
console.log('x 发生类型转换');
break;
default:
console.log('x 没有发生类型转换');
}
`;
let fakeCodeSnippet = _GM_getValue("fake-codes", defaultCodeSnippet);
if (fakeCodeSnippet.trim() == "") {
fakeCodeSnippet = defaultCodeSnippet;
}
let codeTheme = _GM_getValue("code-theme", "prism");
let codeParagraphItalic = _GM_getValue("code-italic", true);
let codeShowLineNumbers = _GM_getValue("line-numbers", false);
let refreshInterval = _GM_getValue("refreshInterval", 15 * 6e4);
const avalibleCodeThemes = [
{ Name: "Default", code: "prism" },
{ Name: "Dark", code: "prism-dark" },
{ Name: "Funky", code: "prism-funky" },
{ Name: "Okaidia", code: "prism-okaidia" },
{ Name: "Twilight", code: "prism-twilight" },
{ Name: "Coy", code: "prism-coy" },
{ Name: "Solarized Light", code: "prism-solarizedlight" },
{ Name: "Tomorrow Night", code: "prism-tomorrow" },
{ Name: "CB", code: "prism-cb" },
{ Name: "GHColors", code: "prism-ghcolors" },
{ Name: "Pojoaque", code: "prism-pojoaque" },
{ Name: "Xonokai", code: "prism-xonokai" },
{ Name: "Ateliersulphurpool-light", code: "prism-base16-ateliersulphurpool.light" },
{ Name: "Hopscotch", code: "prism-hopscotch" },
{ Name: "Atom Dark", code: "prism-atom-dark" },
{ Name: "Duotone Dark", code: "prism-duotone-dark" },
{ Name: "Duotone Sea", code: "prism-duotone-sea" },
{ Name: "Duotone Space", code: "prism-duotone-space" },
{ Name: "Duotone Earth", code: "prism-duotone-earth" },
{ Name: "Duotone Forest", code: "prism-duotone-forest" },
{ Name: "Duotone Light", code: "prism-duotone-light" },
{ Name: "VS", code: "prism-vs" },
{ Name: "VS Code Dark+", code: "prism-vsc-dark-plus" },
{ Name: "Darcula", code: "prism-darcula" },
{ Name: "a11y Dark", code: "prism-a11y-dark" },
{ Name: "Dracula", code: "prism-dracula" },
{ Name: "Synthwave '84", code: "prism-synthwave84" },
{ Name: "Shades of Purple", code: "prism-shades-of-purple" },
{ Name: "Material Dark", code: "prism-material-dark" },
{ Name: "Material Light", code: "prism-material-light" },
{ Name: "Material Oceanic", code: "prism-oceanic" },
{ Name: "Nord", code: "prism-nord" },
{ Name: "Coldark Cold", code: "prism-coldark-cold" },
{ Name: "Coldark Dark", code: "prism-coldark-dark" },
{ Name: "Coy without shadows", code: "prism-coy-without-shadows" },
{ Name: "Gruvbox Dark", code: "prism-gruvbox-dark" },
{ Name: "Gruvbox Light", code: "prism-gruvbox-light" },
{ Name: "Lucario", code: "prism-lucario" },
{ Name: "Night Owl", code: "prism-night-owl" },
{ Name: "Holi Theme", code: "prism-holi-theme" },
{ Name: "Z-Touch", code: "prism-z-touch" },
{ Name: "Solarized Dark Atom", code: "prism-solarized-dark-atom" },
{ Name: "One Dark", code: "prism-one-dark" },
{ Name: "One Light", code: "prism-one-light" },
{ Name: "Laserwave", code: "prism-laserwave" }
];
const avalibleCodeLanguages = [
{ Name: "Markup — markup, html, xml, svg, mathml, ssml, atom, rss", code: "markup" },
{ Name: "CSS — css", code: "css" },
{ Name: "C-like — clike", code: "clike" },
{ Name: "JavaScript — javascript, js", code: "javascript" },
{ Name: "C —c", code: "c" },
{ Name: "C# —csharp, cs, dotnet", code: "csharp" },
{ Name: "C++ —cpp", code: "cpp" },
{ Name: "Go —go", code: "go" },
{ Name: "Java —java", code: "java" },
{ Name: "Kotlin —kotlin, kt, kts", code: "kotlin" },
{ Name: "PHP —php", code: "php" },
{ Name: "Python —python, py", code: "python" },
{ Name: "Rust —rust", code: "rust" }
];
const coreLanguages = new Set(["markup", "css", "clike", "javascript"]);
function changeCodeTheme(theme) {
_GM_setValue("code-theme", theme);
codeTheme = theme;
codeThemeElement?.remove();
codeThemeElement = _GM_addElement(document.head, "link", {
href: getCodeThemeURL(theme),
rel: "stylesheet",
type: "text/css"
});
}
let codeThemeElement = null;
function setupCodeTheme() {
codeThemeElement = _GM_addElement(document.head, "link", {
href: getCodeThemeURL(codeTheme),
rel: "stylesheet",
type: "text/css"
});
if (!codeParagraphItalic) {
document.body.dataset.comment = "normal";
}
["match-braces", "line-numbers"].forEach((pluginName) => {
_GM_addElement(document.head, "link", {
href: `https://cdn.jsdelivr.net/npm/[email protected]/plugins/${pluginName}/prism-${pluginName}.min.css`,
rel: "stylesheet",
type: "text/css"
});
});
}
let bookPageAccessKey = _GM_getValue("bookPageAccessKey", "h");
let previousChapterAccessKey = _GM_getValue("previousChapterAccessKey", "b");
let nextChapterAccessKey = _GM_getValue("nextChapterAccessKey", "n");
function createAccessKeysFieldset() {
const accessKeysFieldset = document.createElement("fieldset");
accessKeysFieldset.innerHTML = `<legend>快捷键设置
<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Global_attributes/accesskey#%E5%B0%9D%E8%AF%95%E4%B8%80%E4%B8%8B" target="_blank" style="margin-left: 5rem;">快捷键使用帮助</a>
</legend>
<div style="display: flex;gap: 0.5rem;flex-wrap:wrap;">
<label>上一章:
<select id="previousChapterAccessKey"></select>
</label>
<label>目录:
<select id="bookPageAccessKey"></select>
</label>
<label>下一章:
<select id="nextChapterAccessKey"></select>
</label>
</div>`;
const previousChapterAccessKey2 = accessKeysFieldset.querySelector(
"#previousChapterAccessKey"
);
const bookPageAccessKey2 = accessKeysFieldset.querySelector("#bookPageAccessKey");
const nextChapterAccessKey2 = accessKeysFieldset.querySelector("#nextChapterAccessKey");
for (let i = 0; i < 10; i++) {
const option = document.createElement("option");
const charCode = 48 + i;
option.value = String.fromCharCode(charCode);
option.text = String.fromCharCode(charCode);
previousChapterAccessKey2.appendChild(option);
bookPageAccessKey2.appendChild(option.cloneNode(true));
nextChapterAccessKey2.appendChild(option.cloneNode(true));
}
for (let i = 0; i < 26; i++) {
const option = document.createElement("option");
const charCode = 97 + i;
option.value = String.fromCharCode(charCode);
option.text = String.fromCharCode(charCode);
previousChapterAccessKey2.appendChild(option);
bookPageAccessKey2.appendChild(option.cloneNode(true));
nextChapterAccessKey2.appendChild(option.cloneNode(true));
}
bookPageAccessKey2.value = _GM_getValue("bookPageAccessKey", "h");
previousChapterAccessKey2.value = _GM_getValue("previousChapterAccessKey", "b");
nextChapterAccessKey2.value = _GM_getValue("nextChapterAccessKey", "n");
previousChapterAccessKey2.onchange = () => {
if (previousChapterAccessKey2.selectedOptions.length > 0) {
_GM_setValue("previousChapterAccessKey", previousChapterAccessKey2.value);
}
};
bookPageAccessKey2.onchange = () => {
if (bookPageAccessKey2.selectedOptions.length > 0) {
_GM_setValue("bookPageAccessKey", bookPageAccessKey2.value);
}
};
nextChapterAccessKey2.onchange = () => {
if (nextChapterAccessKey2.selectedOptions.length > 0) {
_GM_setValue("nextChapterAccessKey", nextChapterAccessKey2.value);
}
};
return accessKeysFieldset;
}
let inlineLengthMax = _GM_getValue("inlineLengthMax", 40);
function createDisguiseCodeFieldset() {
setupExtendLanguageSupport();
const disguiseFieldset = document.createElement("fieldset");
const div = document.createElement("div");
div.style.display = "flex";
div.style.flexWrap = "wrap";
div.style.gap = "0.5rem";
disguiseFieldset.appendChild(div);
const codeThemeInput = document.createElement("select");
codeThemeInput.name = "theme";
avalibleCodeThemes.forEach((theme) => {
const option = document.createElement("option");
option.value = theme.code;
option.text = theme.Name;
codeThemeInput.appendChild(option);
});
codeThemeInput.value = codeTheme;
codeThemeInput.onchange = () => {
console.log("change");
const theme = codeThemeInput.value;
if (codeThemeInput.selectedIndex >= 0 && theme && theme != codeTheme) {
console.log(`Change code theme to ${theme}`);
changeCodeTheme(theme);
}
};
let editableList = null;
const codeThemeLabel = document.createElement("label");
codeThemeLabel.innerText = "代码主题:";
codeThemeLabel.appendChild(codeThemeInput);
div.appendChild(codeThemeLabel);
const codeDemo = `<code class="language-javascript match-braces rainbow-braces">/*
让我们说中文
*/
function foo(bar) {
// 短的注释
var a = 42,
b = 'Prism';
return a + bar(b);
}</code>`;
let preDemo = document.createElement("pre");
const renderDemo = () => {
let newPre = document.createElement("pre");
newPre.innerHTML = codeDemo;
newPre.className = `language-javascript match-braces ${codeShowLineNumbers ? "line-numbers" : ""}`;
if (codeShowLineNumbers) {
const codeDemo2 = newPre.querySelector("code");
codeDemo2.classList.add("line-numbers");
}
highlightElement(newPre);
disguiseFieldset.replaceChild(newPre, preDemo);
preDemo = newPre;
console.log("update demo");
};
const codeLangInput = document.createElement("select");
codeLangInput.name = "lang";
avalibleCodeLanguages.forEach((theme) => {
const option = document.createElement("option");
option.value = theme.code;
option.text = theme.Name;
codeLangInput.appendChild(option);
});
codeLangInput.value = codeLang;
codeLangInput.onchange = () => {
if (codeLangInput.selectedIndex >= 0) {
codeLang = codeLangInput.value;
_GM_setValue("code-lang", codeLang);
setupExtendLanguageSupport();
editableList?.render();
renderDemo();
}
};
const codeLangLabel = document.createElement("label");
codeLangLabel.innerText = "代码语言:";
codeLangLabel.appendChild(codeLangInput);
div.appendChild(codeLangLabel);
const codeShowLineNumbersInput = document.createElement("input");
codeShowLineNumbersInput.type = "checkbox";
codeShowLineNumbersInput.name = "line-numbers";
codeShowLineNumbersInput.checked = codeShowLineNumbers;
codeShowLineNumbersInput.onchange = () => {
codeShowLineNumbers = codeShowLineNumbersInput.checked;
_GM_setValue("line-numbers", codeShowLineNumbers);
console.log(`Change code show line numbers to ${codeShowLineNumbers}`, editableList);
editableList?.render();
renderDemo();
};
const codeShowLineNumbersLabel = document.createElement("label");
codeShowLineNumbersLabel.appendChild(codeShowLineNumbersInput);
codeShowLineNumbersLabel.append(" 显示行号");
div.appendChild(codeShowLineNumbersLabel);
const codeItalicInput = document.createElement("input");
codeItalicInput.type = "checkbox";
codeItalicInput.name = "font-italic";
codeItalicInput.checked = codeParagraphItalic;
codeItalicInput.onchange = () => {
const checked = codeItalicInput.checked;
_GM_setValue("code-italic", checked);
if (checked) {
document.body.dataset.comment = void 0;
} else {
document.body.dataset.comment = "normal";
}
};
const codeItalicLabel = document.createElement("label");
codeItalicLabel.appendChild(codeItalicInput);
codeItalicLabel.append(" 小说斜体");
div.appendChild(codeItalicLabel);
const codeInlineLengthInput = document.createElement("input");
codeInlineLengthInput.name = "comment-lenth-limit";
codeInlineLengthInput.type = "number";
codeInlineLengthInput.min = "15";
codeInlineLengthInput.max = "200";
codeInlineLengthInput.valueAsNumber = inlineLengthMax;
codeInlineLengthInput.onchange = () => {
_GM_setValue("inlineLengthMax", codeInlineLengthInput.value);
};
const codeInlineLengthLabel = document.createElement("label");
codeInlineLengthLabel.innerText = "单行注释长度限制:";
codeInlineLengthLabel.appendChild(codeInlineLengthInput);
div.appendChild(codeInlineLengthLabel);
const demoCodeTitle = document.createElement("h3");
demoCodeTitle.innerText = "主题效果:";
disguiseFieldset.appendChild(demoCodeTitle);
disguiseFieldset.appendChild(preDemo);
setupEditableList();
setTimeout(() => {
editableList = document.createElement("editable-list");
disguiseFieldset.appendChild(editableList);
editableList.updateCodeSnippets(fakeCodeSnippet.split("====\n"));
renderDemo();
const onItemChange = () => {
_GM_setValue("fake-codes", editableList?.codeSnippets.join("====\n"));
};
editableList.addEventListener("add-item", onItemChange);
editableList.addEventListener("remove-item", onItemChange);
}, 500);
return disguiseFieldset;
}
let containerWidth = _GM_getValue("container-width", "1200px");
function createContainerStyleFieldset() {
const containerStyleFieldset = document.createElement("fieldset");
const legend = document.createElement("legend");
legend.innerText = "正文式样";
containerStyleFieldset.appendChild(legend);
const div = document.createElement("div");
div.style = "display: flex; flex-wrap: wrap; gap: 0.5rem;";
const widthInput = document.createElement("input");
widthInput.value = containerWidth;
widthInput.size = 10;
widthInput.onchange = () => {
containerWidth = widthInput.value;
document.body.style.setProperty("--container-width", containerWidth);
_GM_setValue("container-width", widthInput.value);
};
const widthLabel = document.createElement("label");
widthLabel.innerText = "宽度:";
widthLabel.title = "单位可以是 rem, px, %, svw, vw";
widthLabel.appendChild(widthInput);
div.appendChild(widthLabel);
const fontSizeInput = document.createElement("input");
fontSizeInput.value = novelFontSize;
fontSizeInput.size = 10;
fontSizeInput.onchange = () => {
novelFontSize = fontSizeInput.value;
document.body.style.setProperty("--novel-font-size", novelFontSize);
_GM_setValue("novel-font-size", fontSizeInput.value);
};
const fontSizeLabel = document.createElement("label");
fontSizeLabel.innerText = "字体大小:";
fontSizeLabel.appendChild(fontSizeInput);
div.appendChild(fontSizeLabel);
const fontFamilyInput = document.createElement("input");
fontFamilyInput.value = novelFontFamily;
fontFamilyInput.onchange = () => {
novelFontFamily = fontFamilyInput.value;
document.body.style.setProperty("--novel-font-family", novelFontFamily);
_GM_setValue("novel-font-family", fontFamilyInput.value);
};
const fontFamilyLabel = document.createElement("label");
fontFamilyLabel.innerText = "字体:";
fontFamilyLabel.appendChild(fontFamilyInput);
div.appendChild(fontFamilyLabel);
containerStyleFieldset.appendChild(div);
return containerStyleFieldset;
}
function createSettingForm() {
const form = document.createElement("form");
form.appendChild(createContainerStyleFieldset());
const intervalInput = document.createElement("input");
intervalInput.type = "number";
intervalInput.min = "0";
intervalInput.valueAsNumber = refreshInterval / 6e4;
intervalInput.style.width = "4rem";
const intervalLabel = document.createElement("label");
intervalLabel.innerText = "刷新间隔(分钟):";
intervalLabel.appendChild(intervalInput);
form.appendChild(intervalLabel);
const button = document.createElement("button");
button.type = "submit";
button.innerText = "保存刷新设置";
button.style.marginLeft = "0.75rem";
form.appendChild(button);
form.appendChild(createAccessKeysFieldset());
const disguiseCodeFieldset = createDisguiseCodeFieldset();
const updateFieldSetsState = (label) => {
switch (label) {
case "none":
disguiseCodeFieldset.style.display = "none";
break;
case "code":
disguiseCodeFieldset.style.display = "block";
break;
}
};
updateFieldSetsState(disguiseMode);
const radioDiv = document.createElement("div");
radioDiv.style.display = "flex";
radioDiv.innerHTML = `<p>伪装模式:</p>`;
[
["none", "无"],
["code", "代码"]
].forEach(([label, placeholder]) => {
const disguiseInput = document.createElement("input");
disguiseInput.name = "disguise-radio";
disguiseInput.type = "radio";
disguiseInput.value = label;
disguiseInput.checked = disguiseMode == label;
disguiseInput.style.marginLeft = "0.5rem";
disguiseInput.style.marginRight = "0.5rem";
disguiseInput.onchange = () => {
const disguiseEnabled = disguiseInput.checked;
if (disguiseEnabled) {
_GM_setValue("disguise-mode", label);
updateFieldSetsState(label);
}
};
const disguiseLabel = document.createElement("label");
disguiseLabel.style.display = "flex";
disguiseLabel.style.alignItems = "center";
disguiseLabel.appendChild(disguiseInput);
const disguiseP = document.createElement("p");
disguiseP.innerText = placeholder;
disguiseLabel.appendChild(disguiseP);
radioDiv.appendChild(disguiseLabel);
});
form.appendChild(radioDiv);
form.appendChild(disguiseCodeFieldset);
form.onsubmit = (e) => {
e.preventDefault();
const interval = parseInt(intervalInput.value) * 6e4;
if (interval >= 0 && interval != refreshInterval) {
_GM_setValue("refreshInterval", interval);
refreshInterval = interval;
}
};
setTimeout(() => {
const pre = document.querySelector("pre");
if (pre) {
updateStyle(pre);
}
}, 1e3);
return form;
}
function setDefaultStyle() {
document.body.style.setProperty("--container-width", containerWidth);
document.body.style.setProperty("--novel-font-size", novelFontSize);
document.body.style.setProperty("--novel-font-family", novelFontFamily);
}
function handleBookPage$1() {
let finished = false;
const itemtxt = document.querySelector(".itemtxt");
const spans = Array.from(itemtxt.querySelectorAll("p > span"));
spans.forEach((span) => {
if (span.textContent?.trim() == "已完结") {
finished = true;
}
});
const settingAnchor = document.createElement("a");
settingAnchor.href = "/pifu/";
settingAnchor.style.float = "right";
settingAnchor.style.marginRight = "0.5rem";
settingAnchor.innerText = "脚本设置";
itemtxt.firstElementChild.appendChild(settingAnchor);
if (!finished) {
const title = itemtxt.querySelector("h1>a").textContent;
const latestChapter = itemtxt.querySelector("ul>li>a").textContent;
const current = document.createElement("p");
current.innerText = `当前时间:${( new Date()).toTimeString()}`;
itemtxt.appendChild(current);
document.title = `${title} - ${latestChapter}`;
if (refreshInterval > 0) {
const next = document.createElement("p");
next.innerText = `刷新时间:${new Date(Date.now() + refreshInterval).toTimeString()}`;
itemtxt.appendChild(next);
setTimeout(() => {
location.reload();
}, refreshInterval);
}
}
}
function handleSettingPage$3() {
const settingForm = createSettingForm();
const container = document.querySelector("div.container");
container.appendChild(settingForm);
}
function handleChaperPage() {
const container = document.querySelector("div.container");
if (location.pathname.includes("-") && container && isInIframe) {
const con = container.querySelector("div.con");
let nextHref = "";
let nextChapter = "";
const prenexts2 = document.querySelectorAll("div.prenext a");
for (const element of prenexts2) {
if (element instanceof HTMLAnchorElement) {
if (element.textContent == "下一页") {
nextHref = element.href;
break;
}
if (element.textContent == "下一章") {
nextChapter = element.href;
break;
}
}
}
window.parent.postMessage({
con: con.innerHTML,
next: nextHref,
nextChapter,
href: location.href
});
return;
}
if (_GM_getValue("disguiseDebug", false)) {
disguiseParagraphs(document.querySelector("div.container .con"));
return;
}
const prenexts = container.querySelectorAll("div.prenext a");
window.addEventListener("message", (e) => {
if (e.data.con) {
const next = document.createElement("div");
next.className = "con";
next.innerHTML = e.data.con;
const container2 = document.querySelector("div.container .con");
next.querySelectorAll("p").forEach((p) => container2.appendChild(p));
}
if (e.data.next) {
const iframe = document.querySelector("iframe");
if (iframe) {
iframe.contentWindow.location.replace(e.data.next);
}
} else {
console.debug("no next");
if (!isInIframe && disguiseMode != "none") {
const container2 = document.querySelector("div.container .con");
disguiseParagraphs(container2);
}
const iframe = document.querySelector("iframe");
if (iframe) {
iframe.remove();
}
const nextChapter = e.data.nextChapter;
if (nextChapter) {
for (const element of prenexts) {
if (element instanceof HTMLAnchorElement) {
if (element.textContent == "下一页") {
element.href = nextChapter;
if (nextChapter.endsWith(".html")) {
element.innerText = "下一章";
} else {
element.innerText = "返回目录";
}
break;
}
}
}
}
}
});
const nav = {};
for (const element of prenexts) {
if (element instanceof HTMLAnchorElement) {
if (element.textContent == "下一页") {
nav.nextAnchor = element;
const next = document.createElement("iframe");
next.src = element.href;
next.style.display = "none";
container && container.appendChild(next);
} else if (element.textContent == "上一章") {
nav.prevAnchor = element;
} else if (element.textContent == "目录") {
nav.infoAnchor = element;
} else if (element.textContent == "下一章") {
nav.nextAnchor = element;
if (!isInIframe && disguiseMode != "none") {
const container2 = document.querySelector("div.container .con");
disguiseParagraphs(container2);
}
}
}
}
setAccessKeys(nav);
}
function handleDeqiRoute() {
if (location.pathname === "/pifu/") {
setupCodeTheme();
setupExtendLanguageSupport();
handleSettingPage$3();
} else if (location.pathname.endsWith(".html")) {
if (!isInIframe) {
switch (disguiseMode) {
case "code":
setupCodeTheme();
setupExtendLanguageSupport();
break;
}
}
handleChaperPage();
} else if (location.pathname.startsWith("/xiaoshuo/")) {
handleBookPage$1();
}
}
let bookID = "";
const chapterLinks = new Array();
const chapterLinkSet = new Set();
function cleanupBody$1() {
const ob = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type == "childList") {
mutation.addedNodes.forEach((node) => {
if (node.nodeType == Node.ELEMENT_NODE) {
const el = node;
if (el.id == "mainboxs") {
return;
}
el.remove();
}
});
}
});
});
ob.observe(document.body, { childList: true });
const children = Array.from(document.body.children).filter(
(it) => it.id != "main" && it.id != "mainboxs"
);
children.forEach((it) => {
if (it.tagName == "STYLE" || it.className == "article-root") {
return;
}
it.remove();
});
}
function handleSettingPage$2() {
const settingForm = createSettingForm();
const articleMain = document.createElement("div");
articleMain.id = "article_main";
articleMain.classList = "container";
const container = document.getElementById("main");
articleMain.appendChild(settingForm);
container.appendChild(articleMain);
}
function handleBookPage() {
const rowDiv = document.querySelector("#main > div.nine-item > div.container > div.row");
const moreItem = createAttrOneItem();
moreItem.id = "more-item";
moreItem.appendChild(createMoreAnchor());
const resetItem = createAttrOneItem();
resetItem.id = "reset-item";
resetItem.appendChild(createResetAnchor());
rowDiv.append(moreItem, resetItem);
const links = Array.from(rowDiv.querySelectorAll("a[href][title]")).map((it) => {
return { href: it.href, title: it.title };
});
const indexStr = localStorage.getItem(`book_index_${bookID}`);
if (indexStr) {
const oldLinks = JSON.parse(indexStr);
const linkSet = new Set(links.map((it) => it.href));
oldLinks.forEach((it) => {
if (!linkSet.has(it.href)) {
links.push(it);
rowDiv.insertBefore(createChapterLink(it.href, it.title), moreItem);
}
});
links.sort((a, b) => {
return b.href.localeCompare(a.href);
});
}
chapterLinks.push(...links);
chapterLinkSet.clear();
chapterLinks.forEach((it) => {
chapterLinkSet.add(it.href);
});
localStorage.setItem(`book_index_${bookID}`, JSON.stringify(chapterLinks));
}
function fetchPreviousChapter(href, limit) {
if (limit <= 0) {
return;
}
_GM_xmlhttpRequest({
method: "GET",
url: href,
responseType: "document",
onload: (response) => {
const link = getPrevLink(response.response);
if (!chapterLinkSet.has(href)) {
chapterLinkSet.add(href);
chapterLinks.push({ title: link.title, href });
chapterLinks.sort((a, b) => {
return b.href.localeCompare(a.href);
});
localStorage.setItem(`book_index_${bookID}`, JSON.stringify(chapterLinks));
const moreItem = document.getElementById("more-item");
const element = createChapterLink(href, link.title);
moreItem.parentElement?.insertBefore(element, moreItem);
}
fetchPreviousChapter(link.href, limit - 1);
}
});
}
function createAttrOneItem() {
const div = document.createElement("div");
div.className = "col-md-4 col-sm-12 att-one-item";
return div;
}
function getLastestHref() {
const moreItem = document.getElementById("more-item");
const lastAnchor = moreItem.previousElementSibling?.querySelector("a")?.href;
return lastAnchor;
}
function createMoreAnchor() {
const a = document.createElement("a");
a.role = "button";
a.onclick = () => {
const latest = getLastestHref();
console.log("more", latest);
fetchPreviousChapter(latest, 10);
};
a.title = "更多";
a.innerHTML = "更多";
return a;
}
function createResetAnchor() {
const a = document.createElement("a");
a.role = "button";
a.onclick = () => {
console.log("reset");
localStorage.removeItem(`book_index_${bookID}`);
};
a.title = "重置";
a.innerHTML = "重置";
return a;
}
function createChapterLink(href, title) {
const div = createAttrOneItem();
const a = document.createElement("a");
a.href = new URL(href).pathname;
a.title = title;
a.innerText = title;
div.append(a);
return div;
}
function getPage() {
const mainboxs = document.getElementById("mainboxs");
const mainSection = disguiseParagraphs(mainboxs);
const prenexts = document.querySelectorAll("div.prenext a");
const navigationBar = {};
for (const element of prenexts) {
if (element instanceof HTMLAnchorElement) {
if (element.textContent == "上一章") {
navigationBar.prevAnchor = element;
} else if (element.textContent == "章节目录") {
navigationBar.infoAnchor = element;
} else if (element.textContent == "下一章") {
navigationBar.nextAnchor = element;
}
}
}
setAccessKeys(navigationBar);
const title = document.getElementById("post-h2")?.innerHTML;
const page = {
breadcrumbBar: document.querySelector("div.page-links"),
title,
mainSection,
navigationBar
};
return page;
}
function appendRemainPages(netxDivs, hasCanvas) {
const articleMain = document.getElementById("article_main");
const mainboxs = document.getElementById("mainboxs");
const scripts = [];
netxDivs.forEach((div) => {
if (typeof div === "undefined") {
return;
}
if (typeof div === "string") {
const next = document.createElement("div");
next.innerHTML = div;
mainboxs.appendChild(next);
} else {
scripts.push(div.innerHTML);
}
});
const page = getPage();
if (articleMain) {
if (hasCanvas) {
rebuildChapterBody(page);
mainboxs.id = "";
handleCanvasScript(scripts);
} else {
rebuildChapterBody(page);
}
cleanupBody$1();
}
}
function mergeCanvases(canvases) {
const result = document.createElement("canvas");
let totalWidth = 0, totalHeight = 0;
canvases.forEach((canvas) => {
totalHeight += canvas.height;
totalWidth = Math.max(totalWidth, canvas.width);
});
result.width = totalWidth;
result.height = totalHeight;
let heightOffset = 0;
canvases.forEach((canvas) => {
const ctx = result.getContext("2d");
ctx?.drawImage(canvas, 0, heightOffset);
heightOffset += canvas.height;
});
return result;
}
function handleCanvasScript(scripts) {
if (scripts.length > 0) {
console.log("handleCanvasScript", scripts);
const script = document.createElement("script");
script.textContent = scripts.shift();
forCleanCanvas(() => {
setTimeout(() => {
script.remove();
handleCanvasScript(scripts);
}, 1e3);
});
document.body.appendChild(script);
}
}
function getMainBox(doc) {
return ensureDoc(doc).getElementById("mainboxs");
}
function getCanvasScript(doc) {
const document2 = ensureDoc(doc);
let scriptCopy = void 0;
const scripts = Array.from(document2.body.querySelectorAll("script:not([src])"));
scripts.forEach((script) => {
if (typeof scriptCopy != "undefined") {
return;
}
if (script.innerHTML.includes(`if(!isMobile)`) && !script.innerHTML.includes(`qrcode`)) {
console.log("有手机浏览器限制");
scriptCopy = document2.createElement("script");
scriptCopy.innerHTML = script.innerHTML;
return;
}
});
if (typeof scriptCopy == "undefined") {
scripts.forEach((script) => {
if (typeof scriptCopy != "undefined") {
return;
}
if (script.innerHTML.includes(`display_img_line`)) {
scriptCopy = document2.createElement("script");
scriptCopy.innerHTML = script.innerHTML;
}
});
}
return scriptCopy;
}
function getPrevLink(doc) {
const rDoc = ensureDoc(doc);
return {
href: rDoc.querySelector('.prenext > a[rel="prev"]').href,
title: rDoc.getElementById("post-h2").innerText
};
}
function handleChapterPage$2() {
if (disguiseDebug) {
disguiseParagraphs(document.getElementById("mainboxs"));
return;
}
const articleMain = document.getElementById("article_main");
const nextLinks = Array.from(
document.querySelectorAll("#page-links a.post-page-numbers")
);
const netxDivs = new Array(nextLinks.length);
let remainLinks = nextLinks.length;
let hasCanvas = false;
for (let index = 0; index < nextLinks.length; index++) {
const anchor = nextLinks[index];
_GM_xmlhttpRequest({
method: "GET",
url: anchor.href,
responseType: "document",
onload: (response) => {
try {
const doc = response.response;
const div = getMainBox(doc);
if (div.getElementsByTagName("p").length == 0) {
hasCanvas = true;
netxDivs[index] = getCanvasScript(doc);
} else {
netxDivs[index] = div.innerHTML;
}
if (!hasCanvas) {
anchor.remove();
}
remainLinks--;
} catch (error) {
const div = document.createElement("div");
div.innerText = `error: ${error} with resolve ${anchor.href}`;
articleMain?.append(div);
if (error instanceof Error) {
const div2 = document.createElement("div");
div2.innerText = `name: ${error.name}, stack: ${error.stack}`;
articleMain?.append(div2);
}
}
if (remainLinks == 0) {
appendRemainPages(netxDivs, hasCanvas);
}
}
});
}
}
function canvasToImage(canvas) {
const image = new Image();
image.src = canvas.toDataURL();
return image;
}
function forCleanCanvas(callback) {
const thisWin = document.defaultView;
thisWin.cenabled = () => {
return true;
};
thisWin.isMobile = true;
const mainboxs = document.createElement("div");
mainboxs.id = "mainboxs";
document.body.appendChild(mainboxs);
console.log("forCleanCanvas");
const ob = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type == "childList") {
mutation.removedNodes.forEach((node) => {
if (node.nodeType == Node.ELEMENT_NODE) {
if (node.tagName == "DIV") {
console.log("done");
ob.disconnect();
setTimeout(() => {
const article = document.querySelector(".article-root article");
const table = mainboxs.querySelector("table");
if (article && table) {
const section = document.createElement("section");
section.className = "img-container";
mainboxs.remove();
const canvasList = Array.from(table.querySelectorAll("canvas"));
const result = mergeCanvases(canvasList);
section.appendChild(canvasToImage(result));
article.appendChild(section);
}
callback && callback();
}, 100);
}
}
});
}
});
});
ob.observe(mainboxs, { childList: true, subtree: true });
}
function handleBiqu33Route() {
if (document.documentElement.lang == "zh-TW") {
document.documentElement.lang = "zh-CN";
}
const segments = location.pathname.split("/").filter(Boolean);
const lastSegment = segments[segments.length - 1];
switch (segments.length) {
case 0:
case 1:
case 2:
cleanupBody$1();
setupCodeTheme();
setupExtendLanguageSupport();
handleSettingPage$2();
if (segments.length == 2 && segments[0] == "book") {
bookID = segments[1];
handleBookPage();
}
break;
case 3:
if (/[\d\w]+_\d+$/.test(lastSegment)) {
const rows = Array.from(document.querySelectorAll("#article_main .row"));
rows.forEach((row) => {
row.style.display = "flex";
});
const thisWin = document.defaultView;
let scriptCopy = getCanvasScript(document);
cleanupBody$1();
if (scriptCopy && !thisWin.isMobile) {
const page = getPage();
page.mainSection.innerHTML = "";
rebuildChapterBody(page);
forCleanCanvas();
thisWin.isMobile = true;
document.body.appendChild(scriptCopy);
}
return;
}
switch (disguiseMode) {
case "code":
setupCodeTheme();
setupExtendLanguageSupport();
break;
}
handleChapterPage$2();
break;
}
}
function cleanupBody() {
const children = Array.from(document.body.children).filter((it) => it.id != "ss-reader-main");
children.forEach((it) => {
it.remove();
});
}
function cleanBookPage() {
const articleMain = document.createElement("div");
articleMain.id = "ss-reader-main";
const containers = Array.from(document.body.querySelectorAll(".container"));
containers.forEach((container) => {
container.className = "";
articleMain.appendChild(container);
});
document.body.appendChild(articleMain);
cleanupBody();
}
function handleSettingPage$1() {
const articleMain = document.getElementById("ss-reader-main");
const settingForm = createSettingForm();
articleMain.appendChild(settingForm);
}
function formatArticle() {
const prevAnchor = document.getElementById("prev_url");
const infoAnchor = document.getElementById("info_url");
const nextAnchor = document.getElementById("next_url");
const navigationBar = { prevAnchor, infoAnchor, nextAnchor };
setAccessKeys(navigationBar);
const breadcrumbBar = document.querySelector(".info-title");
const title = document.title.split("-").shift();
const mainSection = disguiseParagraphs(document.getElementById("article"));
const page = { breadcrumbBar, title, mainSection, navigationBar };
rebuildChapterBody(page);
}
function continueFetchPages(curDoc) {
const nextURL = curDoc.getElementById("next_url");
if (nextURL.textContent.trim() == "下一章") {
const t = document.getElementById("next_url");
t.replaceWith(nextURL);
formatArticle();
} else {
if (nextURL.href.startsWith("javascript:")) {
console.error("Cannot fetch next page");
return;
}
_GM_xmlhttpRequest({
method: "GET",
url: nextURL.href,
responseType: "document",
onload: (response) => {
const doc = ensureDoc(response.response);
const article = document.getElementById("article");
const nextArticle = doc.getElementById("article");
const children = Array.from(nextArticle.children);
children.forEach((child) => {
article.appendChild(child);
});
continueFetchPages(doc);
}
});
}
}
function handleChapterPage$1() {
if (disguiseDebug) {
disguiseParagraphs(document.getElementById("article"));
return;
}
document.body.setAttribute("hidden", "");
continueFetchPages(document);
}
function handleDDxiaoshuoRoute() {
document.body.style.display = "flex";
document.body.style.justifyContent = "center";
const segments = location.pathname.split("/").filter(Boolean);
const lastSegment = segments[segments.length - 1];
switch (segments.length) {
case 0:
document.body.style.flexDirection = "column";
break;
case 1:
cleanBookPage();
setupCodeTheme();
setupExtendLanguageSupport();
if (location.pathname == "/history.html") {
handleSettingPage$1();
}
break;
case 2:
if (/[\d\w]+_\d+$/.test(lastSegment)) {
return;
}
switch (disguiseMode) {
case "code":
setupCodeTheme();
setupExtendLanguageSupport();
break;
}
handleChapterPage$1();
break;
}
}
function handleChapterPage() {
const showReading = document.getElementById("showReading");
const bookTitle = document.querySelector("#readcontent .book_title h1");
const nextPageBox = document.querySelector(".nextPageBox");
const prevAnchor = nextPageBox.querySelector(".prev");
const infoAnchor = nextPageBox.querySelector(".dir");
const nextAnchor = nextPageBox.querySelector(".next");
const navigationBar = { prevAnchor, infoAnchor, nextAnchor };
setAccessKeys(navigationBar);
const title = bookTitle.textContent;
const breadcrumbBar = document.querySelector(".bookNav");
const mainSection = disguiseParagraphs(showReading);
rebuildChapterBody({ breadcrumbBar, title, mainSection, navigationBar });
}
function handleSettingPage() {
const settingForm = createSettingForm();
const articleMain = document.createElement("div");
articleMain.id = "article_main";
articleMain.classList = "container";
const container = document.querySelector(".wrap_bg");
articleMain.appendChild(settingForm);
container.appendChild(articleMain);
}
function handleCuoCengRoute() {
const segments = location.pathname.split("/").filter(Boolean);
switch (segments.length) {
case 0:
document.body.style.flexDirection = "column";
break;
case 2:
setupCodeTheme();
setupExtendLanguageSupport();
handleSettingPage();
break;
case 3:
if (location.pathname.startsWith("/book/chapter/")) {
_GM_registerMenuCommand("脚本设置", function() {
open(location.pathname.replace("/book/chapter/", "/book/"));
});
return;
}
_GM_registerMenuCommand("脚本设置", function() {
open(location.pathname.replace(/\/[\d\w\-]+\.html/, ".html"));
});
switch (disguiseMode) {
case "code":
setupCodeTheme();
setupExtendLanguageSupport();
break;
}
handleChapterPage();
break;
}
}
document.defaultView.Prism = globalThis.Prism;
function handleRoute() {
if (location.host.endsWith("deqixs.com")) {
handleDeqiRoute();
_GM_registerMenuCommand("脚本设置", function() {
open("/pifu/");
});
} else if (location.hostname == "www.ddxiaoshuo.cc") {
handleDDxiaoshuoRoute();
_GM_registerMenuCommand("脚本设置", function() {
open("/history.html");
});
} else if (location.hostname == "www.cuoceng.com" || location.hostname == "cuoceng.com") {
handleCuoCengRoute();
} else if (location.hostname == "www.biqu33.cc" || location.pathname.startsWith("/book/")) {
handleBiqu33Route();
_GM_registerMenuCommand("脚本设置", function() {
open("/");
});
}
}
setDefaultStyle();
handleRoute();
releaseCopy();
})();