// ==UserScript== // @name SimpleNovelReader // @namespace net.myitian.js.SimpleNovelReader // @version 0.7.3 // @description 简单的笔趣阁类网站小说阅读器 // @source https://github.com/Myitian/SimpleNovelReader // @author Myitian // @license MIT // @match *://*.xiaoshuohu.com/*/*/*.html* // @match *://*.ibiquge.cc/*/*.html* // @match *://*.beqege.com/*/*.html* // @match *://*.beqege.cc/*/*.html* // @match *://*.biqiuge.net/*_*/*.html* // @match *://*.biquge11.cc/read/*/*.html* // @match *://*.bqgpp.com/read/*/*.html* // @match *://*.qe19.cc/read/*/*.html // @match *://*.biquge66.net/book/*/*.html* // @match *://*.52bqg.org/book_*/*.html* // @match *://*.bqg78.cc/book/*/*.html* // @match *://*.bige3.cc/book/*/*.html* // @match *://*.biqg.cc/book/*/*.html* // @match *://*.wxsc8.com/book/*/*.html* // @match *://*.5scw.com/book_*/*.html* // @match *://*.zhenhunxiaoshuo.com/*.html* // @match *://*.xyyuedu.com/writer/*/*/*.html* // @match *://*.wxzpyd.com/novel/chapter/*.html* // @match *://*.e365xs.com/*/read_*.html* // @match *://*.xbanxia.com/books/*/*.html // @match *://*.faloo.com/*.html // @match *://funs.me/text/*/*.html // @match *://*.trxs.cc/tongren/*/*.html // @match *://trxs.cc/tongren/*/*.html // @match *://*.hjwzw.com/Book/Read/*,* // @match *://www.69shuba.pro/txt/*/* // @match *://bh3.mihoyo.com/news/* // @match *://ys.mihoyo.com/main/news/detail/* // @match *://sr.mihoyo.com/news/* // @match *://zzz.mihoyo.com/news/* // @match file:///*.txt // @match file:///*.htm // @match file:///*.html // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM_registerMenuCommand // @downloadURL https://update.greasyfork.icu/scripts/479004/SimpleNovelReader.user.js // @updateURL https://update.greasyfork.icu/scripts/479004/SimpleNovelReader.meta.js // ==/UserScript== const PageRegex = [ /.*:\/\/.*\.xiaoshuohu\.com\/.*\/.*\/.*\.html.*/, /.*:\/\/.*\.ibiquge\.cc\/.*\/.*\.html.*/, /.*:\/\/.*\.beqege\.com\/.*\/.*\.html.*/, /.*:\/\/.*\.beqege\.cc\/.*\/.*\.html.*/, /.*:\/\/.*\.biqiuge\.net\/.*_.*\/.*\.html.*/, /.*:\/\/.*\.biquge11\.cc\/read\/.*\/.*\.html.*/, /.*:\/\/.*\.bqgpp\.com\/read\/.*\/.*\.html.*/, /.*:\/\/.*\.qe19\.cc\/read\/.*\/.*\.html/, /.*:\/\/.*\.biquge66\.net\/book\/.*\/.*\.html.*/, /.*:\/\/.*\.52bqg\.org\/book_.*\/.*\.html.*/, /.*:\/\/.*\.bqg78\.cc\/book\/.*\/.*\.html.*/, /.*:\/\/.*\.bige3\.cc\/book\/.*\/.*\.html.*/, /.*:\/\/.*\.biqg\.cc\/book\/.*\/.*\.html.*/, /.*:\/\/.*\.wxsc8\.com\/book\/.*\/.*\.html.*/, /.*:\/\/.*\.5scw\.com\/book_.*\/.*\.html.*/, /.*:\/\/.*\.zhenhunxiaoshuo\.com\/.*\.html.*/, /.*:\/\/.*\.xyyuedu\.com\/writer\/.*\/.*\/.*\.html.*/, /.*:\/\/.*\.wxzpyd\.com\/novel\/chapter\/.*\.html.*/, /.*:\/\/.*\.e365xs\.com\/.*\/read_.*\.html.*/, /.*:\/\/.*\.xbanxia\.com\/books\/.*\/.*\.html/, /.*:\/\/.*\.faloo\.com\/.*\.html/, /.*:\/\/funs\.me\/text\/.*\/.*\.html/, /.*:\/\/.*\.trxs\.cc\/tongren\/.*\/.*\.html/, /.*:\/\/trxs\.cc\/tongren\/.*\/.*\.html/, /.*:\/\/.*\.hjwzw\.com\/Book\/Read\/.*,.*/, /.*:\/\/www\.69shuba\.pro\/txt\/.*\/.*/, /.*:\/\/bh3\.mihoyo\.com\/news\/.*/, /.*:\/\/ys\.mihoyo\.com\/main\/news\/detail\/.*/, /.*:\/\/sr\.mihoyo\.com\/news\/.*/, /.*:\/\/zzz\.mihoyo\.com\/news\/.*/, /file:\/\/\/.*\.txt/, /file:\/\/\/.*\.htm/, /file:\/\/\/.*\.html/ ]; const StandalonePageRegex = [ /.*:\/\/(?:sr|zzz)\.mihoyo\.com\/.*/, /file:\/\/\/.*\.txt/, /file:\/\/\/.*\.htm/, /file:\/\/\/.*\.html/ ]; const DynamicPageRegex = [ /.*:\/\/.*\.mihoyo\.com\/.*/, /file:\/\/\/.*\.txt/, /file:\/\/\/.*\.htm/, /file:\/\/\/.*\.html/ ]; const ProcessLFRegex = [ /file:\/\/\/.*\.txt/ ]; const FontSizes = [ ["xx-small", "极小"], ["x-small", "小"], ["small", "较小"], ["medium", "中"], ["large", "较大"], ["x-large", "大"], ["xx-large", "极大"] ]; const SimpleNovelReader = document.createElement("div"); const OriginalUrl = window.location.origin + window.location.pathname + window.location.search; const ActivePageRegex = PageRegex.find(x => x.test(window.location.href)); const IsDynamicPage = DynamicPageRegex.findIndex(x => x.test(window.location.href)) != -1; const IsStandalonePage = StandalonePageRegex.findIndex(x => x.test(window.location.href)) != -1; const IsProcessingLF = ProcessLFRegex.findIndex(x => x.test(window.location.href)) != -1; /** * @param {Document} doc */ function extractPageData(doc) { const pageTitle = doc.title.trim(); /** @type {?HTMLElement} */ const title = ( doc.querySelector("#arcxs_title>h1,.bookname>h1,.pt-read-cont>.pt-read-title>h1,.pt-read>div") ?? doc.querySelector(".article-title,.bookname,#nr_title,.title,.zhong,.cont-title,.article__title,.news-detail__title,tr>td[background='/image/bgheader.gif']") ?? doc.querySelector("h1") ); /** @type {string} */ const content = ( doc.querySelector("#onearcxsbd,#cont-body,.pt-read-text,.article__bd,#nr1") ?? doc.querySelector(".article-content,#content,#chaptercontent,#nr,.article,.pt-read-cont,.main-wrap,.article__content,.news-detail__content,.read_chapterDetail,.txtnav,.nodeContent,#AllySite+div,#ChSize") ?? doc.querySelector("article:not(#myt-snr-content)") ?? doc.querySelector("html>body>pre") // for txt in Firefox )?.innerHTML.replaceAll(" ", ""); /** @type {?HTMLAnchorElement} */ const prev = ( doc.querySelector("[rel=prev],#prev_url,#pb_prev,#link-preview,.pt-prechapter>a") ?? doc.querySelector(".bottem1>a:nth-child(1),.col-md-6.text-center>a[href]:nth-child(1),b>a.prevPage:nth-child(1),td.prev>a,article>ul.pages>li:nth-child(2)>a,.page_chapter>ul>li:nth-child(1)>a,.pt-prechapter,.buttombar__prev:not(.buttombar__prev--disabled),.article__ft>a[href]:nth-child(1),.pageNav>a:nth-child(2),.page1>a:nth-child(1),.bl_pre,center>a.pages:nth-of-type(1)") ?? doc.querySelector("body>table:has(#AllySite)+div>a:nth-child(1)") ); /** @type {?HTMLAnchorElement} */ const info = ( doc.querySelector("[rel='category tag'],#info_url,#pb_mulu,#link-indexz,.pt-catalogue>a") ?? doc.querySelector(".bottem1>a:nth-child(2),.col-md-6.text-center>a[href]:nth-child(2),a.returnIndex,td.mulu>a,article>ul.pages>li:nth-child(4)>a,.page_chapter>ul>li:nth-child(2)>a,.pt-prechapter+a,.news-detail .btn-back,.topbar__back,.nuxt-link-active,.pageNav>a:nth-child(5),.page1>a:nth-child(3),#page_muLu,tr>td>li>a:nth-of-type(3)") ?? doc.querySelector("body>table:has(#AllySite)+div>a:nth-child(2)") ); /** @type {?HTMLAnchorElement} */ const next = ( doc.querySelector("[rel=next],#next_url,#pb_next,#link-next,.pt-nextchapter>a") ?? doc.querySelector(".bottem1>a:nth-child(3),.col-md-6.text-center>a[href]:nth-child(3),b>a.prevPage:nth-child(2),td.next>a,article>ul.pages>li:nth-child(3)>a,.page_chapter>ul>li:nth-child(3)>a,.pt-nextchapter,.buttombar__next:not(.buttombar__next--disabled),.article__ft>a[href]:nth-child(2),.pageNav>a:nth-child(3),.page1>a:nth-child(4),.bl_next,center>a.pages:nth-of-type(2)") ?? doc.querySelector("body>table:has(#AllySite)+div>a:nth-child(3)") ); const prevText = prev?.href ?? ""; const nextText = next?.href ?? ""; return { pageTitle: pageTitle, title: title?.innerText?.trim() ?? pageTitle, content: content?.trim() ?? "", prev: ActivePageRegex.test(prevText) ? prevText?.trim() : "", info: info?.href.trim() ?? "", next: ActivePageRegex.test(nextText) ? nextText?.trim() : "" }; } /** * @param {?{pageTitle:string,title:string,content:string,prev:string,info:string,next:string}} data */ function loadPageData(data) { if (data) { document.title = data.pageTitle; /** @type {HTMLHeadingElement} */ const title = SimpleNovelReader.querySelector("#myt-snr-title"); title.innerText = data.title; if (IsProcessingLF) { const lines = data.content.split("\n"); SimpleNovelReader.querySelector("#myt-snr-content").innerHTML = "

" + lines.join("

") + "

"; } else { SimpleNovelReader.querySelector("#myt-snr-content").innerHTML = data.content; } /** @type {HTMLButtonElement} */ const prev = SimpleNovelReader.querySelector("#myt-snr-prev"); prev.dataset.href = data.prev; prev.disabled = !data.prev; /** @type {HTMLButtonElement} */ const info = SimpleNovelReader.querySelector("#myt-snr-info"); info.dataset.href = data.info; /** @type {HTMLButtonElement} */ const next = SimpleNovelReader.querySelector("#myt-snr-next"); next.dataset.href = data.next; next.disabled = !data.next; } else { SimpleNovelReader.querySelector("#myt-snr-title").innerHTML = ""; SimpleNovelReader.querySelector("#myt-snr-content").innerHTML = ""; /** @type {HTMLButtonElement} */ const prev = SimpleNovelReader.querySelector("#myt-snr-prev"); prev.dataset.href = ""; prev.disabled = true; /** @type {HTMLButtonElement} */ const info = SimpleNovelReader.querySelector("#myt-snr-info"); info.dataset.href = ""; /** @type {HTMLButtonElement} */ const next = SimpleNovelReader.querySelector("#myt-snr-next"); next.dataset.href = ""; next.disabled = true; } } /** * @param {HTMLMediaElement} media */ function pause(media) { media.autoplay = false; media.pause(); } function loadPreload() { /** @type {HTMLIFrameElement} */ const preloadFrame = SimpleNovelReader.querySelector("#myt-snr-preload"); const doc = preloadFrame.contentWindow.document; doc.querySelectorAll("audio").forEach(pause); doc.querySelectorAll("video").forEach(pause); loadPageData(extractPageData(doc)); SimpleNovelReader.querySelector("#myt-snr-content").scrollTop = 0; } /** * @param {URL} url */ function loadUrl(url) { if (IsStandalonePage) { loadPageData(extractPageData(document)); } else if (IsDynamicPage) { /** @type {HTMLIFrameElement} */ const preloadFrame = SimpleNovelReader.querySelector("#myt-snr-preload"); url.hash = "disable-simple-novel-reader"; if (preloadFrame.contentWindow && preloadFrame.src == url.href) { loadPageData(extractPageData(preloadFrame.contentWindow.document)); SimpleNovelReader.querySelector("#myt-snr-content").scrollTop = 0; } else { loadPageData(null); preloadFrame.src = url.href; } } else { get(url).then( xhr => { loadPageData(extractPageData(xhr.response)); SimpleNovelReader.querySelector("#myt-snr-content").scrollTop = 0; } ); } } /** * GET 请求 * @param {string | URL} url 请求地址 * @param {XMLHttpRequestResponseType} responseType 响应类型 * @param {number} timeout 超时 * @returns {Promise} Promise 对象,其 resolve 和 reject 均传入请求所用的 XMLHttpRequest 对象 */ function get(url, responseType = "document", timeout = 0) { return new Promise(function (resolve, reject) { const xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.timeout = timeout; xhr.withCredentials = true; xhr.responseType = responseType; xhr.send(); xhr.ontimeout = () => reject(timeout); xhr.onload = () => { if (xhr.status < 300) { resolve(xhr); } else { reject(xhr); } }; }); } function detectHashChange() { if (window.location.hash == "#simple-novel-reader") { SimpleNovelReader.style.top = "0"; } else { SimpleNovelReader.style.top = "200%"; } } function toggle() { if (window.location.hash == "#simple-novel-reader") { hide(); } else { show(); } } let prevUrl = ""; /** * * @param {?string} url */ function show(url = undefined) { window.location.hash = "simple-novel-reader"; document.documentElement.style.overflow = "hidden"; document.body.style.overflow = "hidden"; if (url || prevUrl != window.location.href) { const newUrl = new URL(url ?? window.location.href); newUrl.hash = "simple-novel-reader"; history.pushState(null, "", newUrl.toString()); SimpleNovelReader.scrollTop = 0; loadUrl(newUrl); } } function hide() { const newUrl = window.location.origin + window.location.pathname + window.location.search; if (newUrl != OriginalUrl) { window.location.href = newUrl; } else { window.location.hash = ""; document.documentElement.style.overflow = ""; document.body.style.overflow = ""; } prevUrl = newUrl; } function toggleSettingDisplay() { /** @type {HTMLDivElement} */ const settings = SimpleNovelReader.querySelector("#myt-snr-setting-items"); /** @type {HTMLButtonElement} */ const settingBtn = SimpleNovelReader.querySelector("#myt-snr-setting"); if (settings.toggleAttribute("hidden")) { settingBtn.innerText = "展开样式设置"; } else { settingBtn.innerText = "收起样式设置"; } } /** * @param {Event} event */ function switchChapter(event) { /** @type {HTMLButtonElement} */ // @ts-ignore const btn = event.target; if (btn.dataset.href) { show(btn.dataset.href); } } function viewInfo() { /** @type {HTMLButtonElement} */ const e = SimpleNovelReader.querySelector("#myt-snr-info"); if (e?.dataset.href) { window.location.href = e.dataset.href; } } function updateCustomFontButtonStyle() { /** @type {HTMLLabelElement} */ const label = SimpleNovelReader.querySelector("[for=myt-snr-setting-font-family-custom]"); label.style.fontFamily = GM_getValue("config.font-family.custom", "sans-serif"); /** @type {HTMLInputElement} */ const input = SimpleNovelReader.querySelector("#myt-snr-setting-font-family-custom-name"); input.style.fontFamily = GM_getValue("config.font-family.custom", "sans-serif"); } function updateContentStyle() { const fontSizeStr = FontSizes[GM_getValue("config.font-size", 3)]; const lineHeightStr = GM_getValue("config.line-height", 1.5).toFixed(1); const maxWidthStr = GM_getValue("config.max-width", 40) + "em"; /** @type {HTMLSpanElement} */ const fontSizeE = SimpleNovelReader.querySelector("#myt-snr-setting-font-size-value"); fontSizeE.innerText = fontSizeStr[1]; /** @type {HTMLSpanElement} */ const lineHeightE = SimpleNovelReader.querySelector("#myt-snr-setting-line-height-value"); lineHeightE.innerText = lineHeightStr; /** @type {HTMLSpanElement} */ const maxWidthE = SimpleNovelReader.querySelector("#myt-snr-setting-max-width-value"); maxWidthE.innerText = maxWidthStr; SimpleNovelReader.querySelector("#myt-snr-content-style").innerHTML = ` #myt-snr-root * { font-family: ${GM_getValue("config.font-family.name", "sans-serif")}; font-size: ${fontSizeStr[0]}; line-height: ${lineHeightStr}; } #myt-snr-root { --x-max-width: ${maxWidthStr}; } `; } function updateCustomStyle() { if (GM_getValue("config.custom-style.enabled", false)) { SimpleNovelReader.querySelector("#myt-snr-custom-style").innerHTML = GM_getValue("config.custom-style", ""); } else { SimpleNovelReader.querySelector("#myt-snr-custom-style").innerHTML = ""; } } /** * @param {string} name * @param {string} value */ function updateRadioButtonGroup(name, value) { /** @type {HTMLInputElement} */ const radio = SimpleNovelReader.querySelector(`input[name=${name}][data-value=${CSS.escape(value)}]`); radio.checked = true; radio.dispatchEvent(new Event('change')); } /** * @param {Event} event */ function updateRadioButton(event) { /** @type {HTMLInputElement} */ // @ts-ignore const radio = event.target; SimpleNovelReader.querySelector(`label[for=${radio.id}]`).toggleAttribute("checked", true); for (const r of SimpleNovelReader.querySelectorAll(`input[name=${radio.name}]:not([id=${radio.id}])`)) { SimpleNovelReader.querySelector(`label[for=${r.id}]`).toggleAttribute("checked", false); } } /** * @param {Event} event */ function updateFontFamilyByRadio(event) { /** @type {HTMLInputElement} */ // @ts-ignore const radio = event.target; /** @type {HTMLInputElement} */ const customE = SimpleNovelReader.querySelector("#myt-snr-setting-font-family-custom-name"); const custom = customE.value; GM_setValue("config.font-family.custom", custom); GM_setValue("config.font-family", radio.dataset.value); if (radio.dataset.value == "custom") { GM_setValue("config.font-family.name", custom); } else { GM_setValue("config.font-family.name", radio.dataset.value); } updateCustomFontButtonStyle(); updateContentStyle(); } /** * @param {Event} event */ function updateFontFamilyByInput(event) { /** @type {HTMLInputElement} */ // @ts-ignore const input = event.target; // @ts-ignore if (GM_getValue("config.font-family", "sans-serif") == "custom") { GM_setValue("config.font-family.name", input.value); updateContentStyle(); } GM_setValue("config.font-family.custom", input.value); updateCustomFontButtonStyle(); } /** * @param {number} diff */ function updateFontSize(diff) { const min = 0; const max = FontSizes.length - 1; const oldVal = GM_getValue("config.font-size", 3) + diff; let newVal = oldVal; if (oldVal <= min) { newVal = min; SimpleNovelReader.querySelector("#myt-snr-setting-font-size-minus").toggleAttribute("disabled", true); } else { SimpleNovelReader.querySelector("#myt-snr-setting-font-size-minus").toggleAttribute("disabled", false); } if (oldVal >= max) { newVal = max; SimpleNovelReader.querySelector("#myt-snr-setting-font-size-plus").toggleAttribute("disabled", true); } else { SimpleNovelReader.querySelector("#myt-snr-setting-font-size-plus").toggleAttribute("disabled", false); } GM_setValue("config.font-size", newVal); updateContentStyle(); } /** * @param {number} diff */ function updateLineSpace(diff) { const min = 0.5; const max = 5; const oldVal = GM_getValue("config.line-height", 1.5) + diff; let newVal = oldVal; if (oldVal <= min) { newVal = min; SimpleNovelReader.querySelector("#myt-snr-setting-line-height-minus").toggleAttribute("disabled", true); } else { SimpleNovelReader.querySelector("#myt-snr-setting-line-height-minus").toggleAttribute("disabled", false); } if (oldVal >= max) { newVal = max; SimpleNovelReader.querySelector("#myt-snr-setting-line-height-plus").toggleAttribute("disabled", true); } else { SimpleNovelReader.querySelector("#myt-snr-setting-line-height-plus").toggleAttribute("disabled", false); } GM_setValue("config.line-height", parseFloat(newVal.toFixed(1))); updateContentStyle(); } /** * @param {number} diff */ function updateMaxWidth(diff) { const min = 5; const max = 10000; const oldVal = GM_getValue("config.max-width", 40) + diff; let newVal = oldVal; if (oldVal <= min) { newVal = min; SimpleNovelReader.querySelector("#myt-snr-setting-max-width-minus").toggleAttribute("disabled", true); } else { SimpleNovelReader.querySelector("#myt-snr-setting-max-width-minus").toggleAttribute("disabled", false); } if (oldVal >= max) { newVal = max; SimpleNovelReader.querySelector("#myt-snr-setting-max-width-plus").toggleAttribute("disabled", true); } else { SimpleNovelReader.querySelector("#myt-snr-setting-max-width-plus").toggleAttribute("disabled", false); } GM_setValue("config.max-width", newVal); updateContentStyle(); } /** * @param {Event} event */ function updateColorScheme(event) { /** @type {HTMLInputElement} */ // @ts-ignore const radio = event.target; GM_setValue("config.color-scheme", radio.dataset.value); SimpleNovelReader.dataset.colorScheme = radio.dataset.value; } /** * @param {Event} event */ function importCustomStyle(event) { /** @type {HTMLInputElement} */ // @ts-ignore const input = event.target; input.files[0].text().then( s => { /** @type {HTMLInputElement} */ const input = SimpleNovelReader.querySelector("#myt-snr-setting-custom-style"); input.value = s; GM_setValue("config.custom-style", s); } ); } function applyCustomStyle() { /** @type {HTMLInputElement} */ const input = SimpleNovelReader.querySelector("#myt-snr-setting-custom-style"); GM_setValue("config.custom-style", input.value); GM_setValue("config.custom-style.enabled", true); updateCustomStyle(); } function disableCustomStyle() { GM_setValue("config.custom-style.enabled", false); updateCustomStyle(); } function deleteData() { if (confirm("确认删除储存的样式数据?")) { GM_deleteValue("config.font-family"); GM_deleteValue("config.font-family.name"); GM_deleteValue("config.font-family.custom"); GM_deleteValue("config.font-size"); GM_deleteValue("config.line-height"); GM_deleteValue("config.max-width"); GM_deleteValue("config.color-scheme"); GM_deleteValue("config.custom-style"); GM_deleteValue("config.custom-style.enabled"); } } function main() { SimpleNovelReader.id = "myt-snr-root"; SimpleNovelReader.className = "x-scroll-container"; SimpleNovelReader.innerHTML = `

`; GM_registerMenuCommand("切换阅读模式", toggle); GM_registerMenuCommand("切换设置界面", toggleSettingDisplay); GM_registerMenuCommand("删除样式数据", deleteData); SimpleNovelReader.querySelector("#myt-snr-exit").addEventListener("click", hide); SimpleNovelReader.querySelector("#myt-snr-settings").addEventListener("click", toggleSettingDisplay); SimpleNovelReader.querySelector("#myt-snr-close-settings").addEventListener("click", toggleSettingDisplay); SimpleNovelReader.querySelector("#myt-snr-prev").addEventListener("click", switchChapter); SimpleNovelReader.querySelector("#myt-snr-info").addEventListener("click", viewInfo); SimpleNovelReader.querySelector("#myt-snr-next").addEventListener("click", switchChapter); SimpleNovelReader.querySelector("#myt-snr-setting-font-size-minus").addEventListener("click", () => updateFontSize(-1)); SimpleNovelReader.querySelector("#myt-snr-setting-font-size-plus").addEventListener("click", () => updateFontSize(1)); SimpleNovelReader.querySelector("#myt-snr-setting-line-height-minus").addEventListener("click", () => updateLineSpace(-0.1)); SimpleNovelReader.querySelector("#myt-snr-setting-line-height-plus").addEventListener("click", () => updateLineSpace(0.1)); SimpleNovelReader.querySelector("#myt-snr-setting-max-width-minus").addEventListener("click", () => updateMaxWidth(-1)); SimpleNovelReader.querySelector("#myt-snr-setting-max-width-plus").addEventListener("click", () => updateMaxWidth(1)); SimpleNovelReader.querySelector("#myt-snr-setting-custom-style-import").addEventListener("change", importCustomStyle); SimpleNovelReader.querySelector("#myt-snr-setting-custom-style-apply").addEventListener("click", applyCustomStyle); SimpleNovelReader.querySelector("#myt-snr-setting-custom-style-disable").addEventListener("click", disableCustomStyle); for (const btn of SimpleNovelReader.querySelectorAll(".x-myt-hidden-radio")) { btn.addEventListener("change", updateRadioButton); } for (const btn of SimpleNovelReader.querySelectorAll(".x-myt-snr-setting-font-family")) { btn.addEventListener("change", updateFontFamilyByRadio); } for (const btn of SimpleNovelReader.querySelectorAll(".x-myt-setting-color-scheme")) { btn.addEventListener("change", updateColorScheme); } /** @type {HTMLInputElement} */ const customFontFamily = SimpleNovelReader.querySelector("#myt-snr-setting-font-family-custom-name"); customFontFamily.value = GM_getValue("config.font-family.custom", ""); customFontFamily.addEventListener("input", updateFontFamilyByInput); SimpleNovelReader.querySelector("#myt-snr-preload").addEventListener("load", loadPreload); updateRadioButtonGroup("font-family", GM_getValue("config.font-family", "sans-serif")); updateRadioButtonGroup("color-scheme", GM_getValue("config.color-scheme", "auto")); updateCustomFontButtonStyle(); updateContentStyle(); updateCustomStyle(); if (!IsDynamicPage) { loadUrl(new URL(window.location.href)); } if (window.location.hash == "#simple-novel-reader") { SimpleNovelReader.style.top = "0"; show(); } document.body.appendChild(SimpleNovelReader); if (IsDynamicPage) { loadUrl(new URL(window.location.href)); } window.addEventListener("hashchange", detectHashChange); } if (!window.location.hash.includes("disable-simple-novel-reader")) { main(); }