// ==UserScript==
// @name Deqi Prefech
// @namespace https://greasyfork.org/zh-CN/users/14997-lrh3321
// @version 2025-08-080
// @author LRH3321
// @description 得奇小说网, biqu33.cc,看单个章节免翻页,把小说伪装成代码
// @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 *://www.deqixs.com/pifu/
// @match *://www.deqixs.com/xiaoshuo/*/*.html
// @match *://www.deqixs.com/xiaoshuo/*/
// @match *://www.biqu33.cc/*
// @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
// @grant unsafeWindow
// @run-at document-end
// ==/UserScript==
(e=>{if(typeof GM_addStyle=="function"){GM_addStyle(e);return}const t=document.createElement("style");t.textContent=e,document.head.append(t)})(' [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{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%)}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;--list-display: none}editable-list li:hover{--list-display: block}editable-list li:hover .icon{top:0rem;right:3rem}editable-list .icon{border:none;cursor:pointer;position:relative;font-size:1.8rem;display:var(--list-display)}editable-list textarea{padding:.5rem;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} ');
(function () {
'use strict';
var _GM_addElement = /* @__PURE__ */ (() => typeof GM_addElement != "undefined" ? GM_addElement : void 0)();
var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
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, (_) => {
document.body.style.backgroundColor = getComputedStyle(pre).backgroundColor;
});
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:
disguiseToCode(container);
break;
}
}
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 = /* @__PURE__ */ 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");
}
// fires after the element has been attached to the DOM
connectedCallback() {
this.lazyInit();
const addElementButton = this.querySelector(".editable-list-add-item");
addElementButton?.addEventListener("click", this.addListItem, false);
}
// add items to the list
addListItem() {
const textInput = this.textInput;
let snippet = textInput?.value;
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 button = document.createElement("button");
const pre = createPreformattedCode(snippet);
button.classList.add("editable-list-remove-item", "icon");
button.innerHTML = "⊖";
li.appendChild(pre);
li.appendChild(button);
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.remove();
this.codeSnippetsStore.delete(parent.dataset.snippetId || "");
this.dispatchEvent(new CustomEvent("remove-item"));
}
}
}
function setupEditableList() {
customElements.define("editable-list", EditableList);
}
function getCodeThemeURL(theme) {
const officialThemes = /* @__PURE__ */ 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 $ = _unsafeWindow.$ || window.$;
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;
}
const isInIframe = window.self !== window.top;
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" },
// A wider selection of Prism themes
{ 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 = /* @__PURE__ */ 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) {
const computedStyle = getComputedStyle(pre);
document.body.style.backgroundColor = computedStyle.backgroundColor;
form.style.color = computedStyle.color;
}
}, 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() {
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 = `当前时间:${(/* @__PURE__ */ 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$1() {
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 = "下一章";
element.accessKey = nextChapterAccessKey;
element.ariaKeyShortcuts = `Alt+${nextChapterAccessKey}`;
} else {
element.innerText = "返回目录";
}
break;
}
}
}
}
}
});
for (const element of prenexts) {
if (element instanceof HTMLAnchorElement) {
if (element.textContent == "下一页") {
const next = document.createElement("iframe");
next.src = element.href;
next.style.display = "none";
container && container.appendChild(next);
} else if (element.textContent == "上一章") {
element.accessKey = previousChapterAccessKey;
element.ariaKeyShortcuts = `Alt+${previousChapterAccessKey}`;
} else if (element.textContent == "目录") {
element.accessKey = bookPageAccessKey;
element.ariaKeyShortcuts = `Alt+${bookPageAccessKey}`;
} else if (element.textContent == "下一章") {
element.accessKey = nextChapterAccessKey;
element.ariaKeyShortcuts = `Alt+${nextChapterAccessKey}`;
if (!isInIframe && disguiseMode != "none") {
const container2 = document.querySelector("div.container .con");
disguiseParagraphs(container2);
}
}
}
}
}
function handleDeqiRoute() {
if (location.pathname === "/pifu/") {
setupCodeTheme();
setupExtendLanguageSupport();
handleSettingPage$1();
} else if (location.pathname.endsWith(".html")) {
if (!isInIframe) {
switch (disguiseMode) {
case "code":
setupCodeTheme();
setupExtendLanguageSupport();
break;
}
}
handleChaperPage();
} else if (location.pathname.startsWith("/xiaoshuo/")) {
handleBookPage();
}
}
function handleSettingPage() {
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 handleChapterPage() {
if (disguiseDebug) {
disguiseParagraphs(document.getElementById("mainboxs"));
return;
}
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 element = nextLinks[index];
_GM_xmlhttpRequest({
method: "GET",
url: element.href,
responseType: "document",
onload: (response) => {
const doc = response.response;
const div = doc.getElementById("mainboxs");
if (div.getElementsByTagName("p").length == 0) {
hasCanvas = true;
}
netxDivs[index] = div.innerHTML;
element.remove();
remainLinks--;
if (remainLinks == 0) {
const mainboxs = document.getElementById("mainboxs");
netxDivs.forEach((div2) => {
const next = document.createElement("div");
next.innerHTML = div2;
mainboxs.appendChild(next);
});
const main = document.getElementById("article_main");
if (main) {
main.appendChild(document.querySelector("div.page-links"));
main.appendChild(mainboxs);
main.appendChild(document.querySelector("div.prenext"));
main.appendChild(document.querySelector("div.post-content"));
main.querySelectorAll(".page-links, .post-content");
}
if (hasCanvas) {
document.body.append("章节不完整");
}
disguiseParagraphs(mainboxs);
}
}
});
}
const prenexts = document.querySelectorAll("div.prenext a");
for (const element of prenexts) {
if (element instanceof HTMLAnchorElement) {
if (element.textContent == "上一章") {
element.accessKey = previousChapterAccessKey;
element.ariaKeyShortcuts = `Alt+${previousChapterAccessKey}`;
} else if (element.textContent == "章节目录") {
element.accessKey = bookPageAccessKey;
element.ariaKeyShortcuts = `Alt+${bookPageAccessKey}`;
} else if (element.textContent == "下一章") {
element.accessKey = nextChapterAccessKey;
element.ariaKeyShortcuts = `Alt+${nextChapterAccessKey}`;
}
}
}
}
function handleBiqu33Route() {
const segments = location.pathname.split("/").filter(Boolean);
const lastSegment = segments[segments.length - 1];
switch (segments.length) {
case 0:
case 1:
case 2:
setupCodeTheme();
setupExtendLanguageSupport();
handleSettingPage();
break;
case 3:
if (/[\d\w]+_\d+$/.test(lastSegment)) {
return;
}
switch (disguiseMode) {
case "code":
setupCodeTheme();
setupExtendLanguageSupport();
break;
}
handleChapterPage();
break;
}
}
window.Prism = _unsafeWindow.Prism = _unsafeWindow.Prism || window.Prism;
function handleRoute() {
if (location.host.endsWith("deqixs.com")) {
handleDeqiRoute();
_GM_registerMenuCommand("脚本设置", function() {
open("/pifu/");
});
} else if (location.hostname == "www.biqu33.cc" || location.pathname.startsWith("/book/")) {
handleBiqu33Route();
_GM_registerMenuCommand("脚本设置", function() {
open("/");
});
}
}
setDefaultStyle();
handleRoute();
releaseCopy();
})();