笔趣阁外观优化

专注阅读

目前為 2021-11-12 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name 笔趣阁外观优化
  3. // @namespace https://gitee.com/linhq1999/OhMyScript
  4. // @version 2.7
  5. // @description 专注阅读
  6. // @author LinHQ
  7. // @match http*://www.shuquge.com/*.html
  8. // @exclude http*://www.shuquge.com/*index.html
  9. // @match http*://www.sywx8.com/*.html
  10. // @match http*://www.biqugetv.com/*.html
  11. // @match http*://www.bqxs520.com/*.html
  12. // @grant GM_addStyle
  13. // @grant GM_xmlhttpRequest
  14. // @inject-into auto
  15. // @license MIT
  16. // ==/UserScript==
  17. 'use strict';
  18. (function () {
  19. var lineHeight = 1.3;
  20. var configs = {
  21. "sites": [
  22. {
  23. "desc": "shuquge",
  24. "main": "div.reader",
  25. "title": ".reader h1",
  26. "txt": "#content",
  27. "toc": "dd a",
  28. "tocJump": 12,
  29. "filter": ["div.header", "div.nav", "div.link"],
  30. "txtfilter": ["shuqu"] /*带有此关键字的行将被删除*/
  31. },
  32. {
  33. "desc": "sywx",
  34. "main": "div#container",
  35. "title": "div>h1",
  36. "toc": "li a",
  37. "tocJump": 0,
  38. "txt": "div#BookText",
  39. "filter": ["div.top", ".link.xb", "#footer"],
  40. "txtfilter": ["最快更新", "松语"]
  41. },
  42. {
  43. "desc": "bqxs",
  44. "main": ".box_con",
  45. "title": "div.content_read h1",
  46. "toc": "#list dd a",
  47. "tocJump": 9,
  48. "txt": "#content",
  49. "filter": [".ywtop", ".header", ".nav", ".bottem1", ".lm", "#page_set", ".bookname~.box_con"],
  50. "txtfilter": []
  51. },
  52. {
  53. "desc": "biqugetv",
  54. "main": ".box_con",
  55. "title": "div.content_read h1",
  56. "toc": "#list dd a",
  57. "tocJump": 0,
  58. "txt": "#content",
  59. "filter": [".ywtop", ".header", ".nav", ".bottem1", ".lm", "#page_set"],
  60. "txtfilter": []
  61. }
  62. ],
  63. "perDefault": {
  64. "fontSize": 16,
  65. "lineHeight": 16 * lineHeight
  66. },
  67. "style": "\n body {\n background-color: #EAEAEF !important;\n }\n\n .bqg.inject.win {\n width: 55vw !important;\n min-width: 600px;\n border: 2px double gray !important;\n border-radius: 8px;\n }\n\n .bqg.inject.txt {\n font-family: '\u6977\u4F53'!important;\n background-color: #EAEAEF !important;\n padding: 0.5em 1em !important;\n margin: 0.5em auto !important;\n width: auto !important;\n }\n\n .bqg.inject.title {\n color: black;\n background-color: #EAEAEF;\n font-family: '\u6977\u4F53' !important;\n cursor: pointer !important;\n }\n\n .bqg.inject.title:hover {\n color: #0258d8 !important;\n }\n \n .hq.inject.toc {\n font-family: \u5FAE\u8F6F\u96C5\u9ED1,\u6587\u6CC9\u9A7F\u5FAE\u7C73\u9ED1;\n width: 270px;\n position: fixed;\n top: 30px;\n padding: 5px;\n display: flex;\n flex-flow: column;\n transition: left 0.5s cubic-bezier(0.35, 1.06, 0.83, 0.99);\n background: rgb(246 246 246 / 60%);\n border-radius: 8px;\n }\n\n .hq.inject ul {\n max-height: 280px;\n width: 100%;\n /*offsetTop \u8BA1\u7B97\u9700\u8981*/\n position:relative;\n overflow: auto;\n }\n\n .hq.inject ul li {\n cursor: pointer;\n margin: 2px;\n width: 95%;\n padding: 1px 4px;\n font-size: 0.7rem;\n border-radius: 4px;\n }\n\n .hq.inject ul li:hover {\n background: #0258d8;\n color: #f6f6f6;\n }\n\n .hq.inject.toc>h3 {\n font-size: 1.1rem;\n font-weight: bold;\n border-radius: 2px;\n align-self: center;\n cursor: pointer;\n margin: 4px 0 8px 0;\n }\n\n .hq.inject.toc>h3:hover {\n color: #ffa631 !important;\n }\n "
  68. };
  69. // 查询已经保存的字体信息
  70. var oldPerCfg = localStorage.getItem("bqg_cfg");
  71. // 检查是否存在已有设置且和当前版本相符
  72. var perCfg;
  73. if (oldPerCfg !== null) {
  74. var cfg_1 = JSON.parse(oldPerCfg);
  75. if (Object.keys(cfg_1).length === Object.keys(configs.perDefault).length) {
  76. perCfg = cfg_1;
  77. }
  78. else {
  79. perCfg = configs.perDefault;
  80. console.warn("检测到版本变化,设置已重置");
  81. }
  82. }
  83. else {
  84. perCfg = configs.perDefault;
  85. console.warn("检测到版本变化,设置已重置");
  86. }
  87. // 检测当前的网址,应用对应的设置
  88. var tmp = configs.sites.filter(function (site) { return document.URL.includes(site.desc); });
  89. if (tmp.length == 0) {
  90. console.error("关键字匹配错误!");
  91. return;
  92. }
  93. var cfg = tmp[0];
  94. GM_addStyle(configs.style);
  95. // 对可变部分产生影响
  96. var doInject = function () {
  97. var _a, _b;
  98. // 执行元素过滤
  99. cfg.filter.forEach(function (filter) { var _a; return (_a = document.querySelectorAll(filter)) === null || _a === void 0 ? void 0 : _a.forEach(function (ele) { return ele.remove(); }); });
  100. // 应用已经保存的字体配置
  101. var textWin = document.querySelector(cfg.txt);
  102. textWin.setAttribute("style", "font-size:" + perCfg.fontSize + "px;line-height:" + perCfg.lineHeight + "px");
  103. textWin.classList.add("bqg", "inject", "txt");
  104. // 执行文字过滤
  105. if (cfg.txtfilter !== undefined) {
  106. textWin.innerText = (_b = (_a = textWin.innerText) === null || _a === void 0 ? void 0 : _a.split("\n\n")) === null || _b === void 0 ? void 0 : _b.filter(function (line) {
  107. for (var _i = 0, _a = cfg.txtfilter; _i < _a.length; _i++) {
  108. var key = _a[_i];
  109. if (line.includes(key)) {
  110. return false;
  111. }
  112. }
  113. return true;
  114. }).join("\n\n");
  115. }
  116. var mainWin = document.querySelector(cfg.main);
  117. mainWin.classList.add("bqg", "inject", "win");
  118. var title = document.querySelector(cfg.title);
  119. title.title = "点击显示目录";
  120. title.classList.add("bqg", "inject", "title");
  121. var saveFontCfg = function () {
  122. perCfg.lineHeight = perCfg.fontSize * lineHeight;
  123. textWin.style.lineHeight = perCfg.lineHeight + "px";
  124. localStorage.setItem("bqg_cfg", JSON.stringify(perCfg));
  125. };
  126. // 下一章
  127. var prevChapter = function () {
  128. var _a;
  129. var prevs = document.querySelectorAll("a");
  130. for (var _i = 0, prevs_1 = prevs; _i < prevs_1.length; _i++) {
  131. var prev = prevs_1[_i];
  132. if ((_a = prev.textContent) === null || _a === void 0 ? void 0 : _a.includes("上一")) {
  133. prev.click();
  134. break;
  135. }
  136. }
  137. };
  138. // 上一章
  139. var nextChapter = function () {
  140. var _a;
  141. var nexts = document.querySelectorAll("a");
  142. for (var _i = 0, nexts_1 = nexts; _i < nexts_1.length; _i++) {
  143. var next = nexts_1[_i];
  144. if ((_a = next.textContent) === null || _a === void 0 ? void 0 : _a.includes("下一")) {
  145. next.click();
  146. break;
  147. }
  148. }
  149. };
  150. // 目录开关
  151. var toggleToc = function () {
  152. var toc = document.querySelector(".hq.inject.toc");
  153. if (parseInt(toc.style.left) < 0) {
  154. toc.style.left = "15px";
  155. }
  156. else {
  157. toc.style.left = "-300px";
  158. }
  159. };
  160. title.onclick = function (ev) {
  161. toggleToc();
  162. // 避免跳到上一章
  163. // 比下面的更为具体,所以有效。
  164. ev.stopPropagation();
  165. };
  166. // 阻止双击事件被捕获(双击会回到顶部)
  167. document.body.ondblclick = function (ev) { return ev.stopImmediatePropagation(); };
  168. document.body.onclick = function (ev) {
  169. var root = document.documentElement;
  170. var winHeight = window.innerHeight;
  171. // 下半屏单击下滚,反之上滚
  172. if (ev.clientY > root.clientHeight / 2) {
  173. if (root.scrollTop + winHeight >= root.scrollHeight) {
  174. nextChapter();
  175. }
  176. window.scrollBy({ top: (window.innerHeight - lineHeight) * 1 });
  177. }
  178. else {
  179. if (root.scrollTop === 0) {
  180. prevChapter();
  181. }
  182. window.scrollBy({ top: (window.innerHeight - lineHeight) * -1 });
  183. }
  184. };
  185. document.body.onkeydown = function (ev) {
  186. switch (ev.key) {
  187. case "-":
  188. perCfg.fontSize -= 2;
  189. textWin.style.fontSize = perCfg.fontSize + "px";
  190. saveFontCfg();
  191. break;
  192. case "=":
  193. perCfg.fontSize += 2;
  194. textWin.style.fontSize = perCfg.fontSize + "px";
  195. saveFontCfg();
  196. break;
  197. case "j":
  198. window.scrollBy({ top: window.innerHeight - perCfg.lineHeight });
  199. break;
  200. case "k":
  201. window.scrollBy({ top: -1 * (window.innerHeight - perCfg.lineHeight) });
  202. break;
  203. case "h":
  204. prevChapter();
  205. break;
  206. case "l":
  207. nextChapter();
  208. break;
  209. case "t":
  210. toggleToc();
  211. break;
  212. default:
  213. break;
  214. }
  215. };
  216. };
  217. // 先调用一次,后面是有变化时才会触发,避免有时无法起作用
  218. doInject();
  219. // 强力覆盖
  220. new MutationObserver(function (_, ob) {
  221. doInject();
  222. }).observe(document.body, { childList: true });
  223. // 添加目录
  224. var toc = document.createElement("div");
  225. toc.className = "hq inject toc";
  226. toc.onclick = function (ev) { return ev.stopPropagation(); };
  227. toc.style.left = "-300px";
  228. document.body.append(toc);
  229. // 目录状态指示灯
  230. var pointer = document.createElement("h3");
  231. var pointerColors = { "loaded": "#afdd22", "loading": "#ffa631", "unload": "#ed5736" };
  232. pointer.title = "点击以重新加载目录";
  233. pointer.innerHTML = "目<span style='display: inline-block;width: 1em'></span>录";
  234. pointer.style.color = pointerColors.unload;
  235. toc.append(pointer);
  236. // 目录列表
  237. var ul = document.createElement("ul");
  238. toc.append(ul);
  239. // fetchTOC 获取目录信息并重新渲染
  240. var fetchTOC = function (currentBookLink, pointer) {
  241. // 修改指示灯状态
  242. pointer.style.color = pointerColors.loading;
  243. GM_xmlhttpRequest({
  244. url: currentBookLink,
  245. // 直接返回 dom
  246. responseType: "document",
  247. onload: function (resp) {
  248. var _a, _b;
  249. var doc = resp.response;
  250. var tocs = doc.querySelectorAll(cfg.toc);
  251. var data = [];
  252. // 序列化存储准备
  253. for (var _i = 0, tocs_1 = tocs; _i < tocs_1.length; _i++) {
  254. var link = tocs_1[_i];
  255. data.push({ "title": (_a = link.textContent) !== null && _a !== void 0 ? _a : "", "href": (_b = link.href) !== null && _b !== void 0 ? _b : "" });
  256. }
  257. if (cfg.tocJump)
  258. data = data.slice(cfg.tocJump + 1);
  259. // 缓存目录信息
  260. sessionStorage.setItem(currentBookLink, JSON.stringify(data));
  261. renderToc(data, ul);
  262. pointer.style.color = pointerColors.loaded;
  263. },
  264. onerror: function (_) { return pointer.style.color = pointerColors.unload; }
  265. });
  266. };
  267. var renderToc = function (toc, ul) {
  268. // 清空旧内容
  269. ul.innerHTML = "";
  270. var current = null;
  271. var _loop_1 = function (lnk) {
  272. var li = document.createElement("li");
  273. li.textContent = lnk.title;
  274. if (current == null && document.URL == lnk.href) {
  275. current = li;
  276. }
  277. li.onclick = function (ev) {
  278. document.location.href = lnk.href;
  279. ev.stopPropagation();
  280. };
  281. ul.append(li);
  282. };
  283. for (var _i = 0, toc_1 = toc; _i < toc_1.length; _i++) {
  284. var lnk = toc_1[_i];
  285. _loop_1(lnk);
  286. }
  287. // 滚动到当前位置,并高亮
  288. current === null || current === void 0 ? void 0 : current.setAttribute("style", "font-weight:bold;background: #0258d8;color: #f6f6f6");
  289. ul.scrollTo({ top: (current === null || current === void 0 ? void 0 : current.offsetTop) - 130 });
  290. };
  291. var source = document.URL.split("/");
  292. source.pop();
  293. // 最后加斜杠保险
  294. var currentBook = source.join("/") + "/";
  295. var currentBookToc = sessionStorage.getItem(currentBook);
  296. if (currentBookToc === null) {
  297. fetchTOC(currentBook, pointer);
  298. }
  299. else {
  300. pointer.style.color = pointerColors.loaded;
  301. renderToc(JSON.parse(currentBookToc), ul);
  302. }
  303. // 单击指示灯刷新目录缓存
  304. pointer.onclick = function () { return fetchTOC(currentBook, pointer); };
  305. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址