beautifier

自定义页面背景图,布局优化

当前为 2022-08-27 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/450211/1086451/beautifier.js

  1. /* eslint-disable no-multi-spaces */
  2. /* eslint-disable no-implicit-globals */
  3. /* eslint-disable userscripts/no-invalid-headers */
  4. /* eslint-disable userscripts/no-invalid-grant */
  5.  
  6. // ==UserScript==
  7. // @name beautifier
  8. // @displayname 页面美化
  9. // @namespace Wenku8++
  10. // @version 0.2.6
  11. // @description 自定义页面背景图,布局优化
  12. // @author PY-DNG
  13. // @license GPL-v3
  14. // @regurl https?://www\.wenku8\.net/.*
  15. // @require https://greasyfork.org/scripts/449412-basic-functions/code/Basic%20Functions.js?version=1085783
  16. // @require https://greasyfork.org/scripts/449583-configmanager/code/ConfigManager.js?version=1085902
  17. // @grant GM_getValue
  18. // @grant GM_setValue
  19. // @grant GM_listValues
  20. // @grant GM_deleteValue
  21. // ==/UserScript==
  22.  
  23. (function __MAIN__() {
  24. const alertify = require('alertify');
  25. const settings = require('settings');
  26. const SettingPanel = require('SettingPanel');
  27.  
  28. const CONST = {
  29. Text: {
  30. CommonBeautify: '通用页面美化',
  31. NovelBeautify: '阅读页面美化',
  32. ReviewBeautify: '书评页面美化',
  33. DefaultBeautify: '默认页面美化图片',
  34. Enable: '启用',
  35. BackgroundImage: '背景图片',
  36. AlertTitle: '页面美化设置',
  37. InvalidImageUrl: '图片链接格式错误</br>仅仅接受http/https/data链接',
  38. },
  39. ClassName: {
  40. BgImage: 'plus_cbty_image',
  41. BgCover: 'plus_cbty_cover',
  42. CSS: 'plus_beautifier'
  43. },
  44. CSS: {
  45. Common: '.plus_cbty_image {position: fixed;top: 0;left: 0;z-index: -2;}.plus_cbty_cover {position: fixed;top: 0;left: calc((100vw - 960px) / 2);z-Index: -1;background-color: rgba(255,255,255,0.7);width: 960px;height: 100vh;}body {overflow: auto;}body>.main {position: relative;margin-left: 0;margin-right: 0;left: calc((100vw - 960px) / 2);}body.plus_cbty table.grid td, body.plus_cbty .odd, body.plus_cbty .even, body.plus_cbty .blockcontent {background-color: rgba(255,255,255,0) !important;}.textarea, .text {background-color: rgba(255,255,255,0.9);}#headlink{background-color: rgba(255,255,255,0.7);}',
  46. Novel: 'html{background-image: url({BGI});}body {width: 100vw;height: 100vh;overflow: overlay;margin: 0px;background-color: rgba(255,255,255,0.7);}#contentmain {overflow-y: auto;height: calc(100vh - {H});max-width: 100%;min-width: 0px;max-width: 100vw;}#adv1, #adtop, #headlink, #footlink, #adbottom {overflow: overlay;min-width: 0px;max-width: 100vw;}#adv900, #adv5 {max-width: 100vw;}'
  47. },
  48. Config_Ruleset: {
  49. 'version-key': 'config-version',
  50. 'ignores': ["LOCAL-CDN"],
  51. 'defaultValues': {
  52. //'config-key': {},
  53. common: {
  54. enable: false,
  55. image: null
  56. },
  57. novel: {
  58. enable: false,
  59. image: null
  60. },
  61. review: {
  62. enable: false,
  63. image: null
  64. },
  65. image: null
  66. },
  67. 'updaters': {
  68. /*'config-key': [
  69. function() {
  70. // This function contains updater for config['config-key'] from v0 to v1
  71. },
  72. function() {
  73. // This function contains updater for config['config-key'] from v1 to v2
  74. }
  75. ]*/
  76. }
  77. }
  78. };
  79.  
  80. // Config
  81. const CM = new ConfigManager(CONST.Config_Ruleset);
  82. const CONFIG = CM.Config;
  83. CM.setDefaults();
  84.  
  85. // Settings
  86. settings.registerSettings(MODULE_IDENTIFIER, setter);
  87.  
  88. // Beautifier pages
  89. const API = getAPI();
  90. if (API[0] === 'novel' && [...API].pop() !== 'index.htm') {
  91. CONFIG.novel.enable && novel();
  92. } else if (API.join('/') === 'modules/article/reviewshow.php') {
  93. CONFIG.review.enable && review();
  94. } else {
  95. CONFIG.common.enable && common();
  96. }
  97.  
  98. exports = {
  99. //
  100. };
  101.  
  102. // Beautifier for all wenku pages
  103. function common() {
  104. const src = CONFIG.common.image || CONFIG.image;
  105.  
  106. const img = $CrE('img');
  107. img.src = src;
  108. img.classList.add(CONST.ClassName.BgImage);
  109. document.body.appendChild(img);
  110.  
  111. const cover = $CrE('div');
  112. cover.classList.add(CONST.ClassName.BgCover);
  113. document.body.appendChild(cover);
  114.  
  115. document.body.classList.add('plus_cbty');
  116. addStyle(CONST.CSS.Common, CONST.ClassName.CSS);
  117. return true;
  118. }
  119.  
  120. // Novel reading page
  121. function novel() {
  122. const src = CONFIG.novel.image || CONFIG.image;
  123. const config = CONFIG.BeautifierCfg.getConfig();
  124. const usedHeight = getRestHeight();
  125.  
  126. addStyle(CONST.CSS.Novel
  127. .replaceAll('{BGI}', src)
  128. .replaceAll('{H}', usedHeight), CONST.ClassName.CSS
  129. );
  130.  
  131. unsafeWindow.scrolling = beautiful_scrolling;
  132.  
  133. // Get rest height without #contentmain
  134. function getRestHeight() {
  135. let usedHeight = 0;
  136. ['adv1', 'adtop', 'headlink', 'footlink', 'adbottom'].forEach((id) => {
  137. const node = $('#'+id);
  138. if (node instanceof Element && node.id !== 'contentmain') {
  139. const cs = getComputedStyle(node);
  140. ['height', 'marginTop', 'marginBottom', 'paddingTop', 'paddingBottom', 'borderTop', 'borderBottom'].forEach((style) => {
  141. const reg = cs[style].match(/([\.\d]+)px/);
  142. reg && (usedHeight += Number(reg[1]));
  143. });
  144. };
  145. });
  146. usedHeight = usedHeight.toString() + 'px';
  147. return usedHeight;
  148. }
  149.  
  150. // Mouse dblclick scroll with beautifier applied
  151. function beautiful_scrolling() {
  152. var contentmain = pageResource.elements.contentmain;
  153. var currentpos = contentmain.scrollTop || 0;
  154. contentmain.scrollTo(0, ++currentpos);
  155. var nowpos = contentmain.scrollTop || 0;
  156. if(currentpos != nowpos) unsafeWindow.clearInterval(timer);
  157. }
  158. }
  159.  
  160. // Review reading page
  161. function review() {}
  162.  
  163. // Settings
  164. function setter() {
  165. const storage = {
  166. GM_getValue: GM_getValue,
  167. GM_setValue: GM_setValue,
  168. GM_listValues: GM_listValues,
  169. GM_deleteValue: GM_deleteValue
  170. };
  171. const Panel = SettingPanel.SettingPanel;
  172. const SetPanel = new Panel({
  173. tables: [{
  174. rows: [{
  175. blocks: [{
  176. isHeader: true,
  177. colSpan: 2,
  178. innerText: CONST.Text.CommonBeautify
  179. }]
  180. },{
  181. blocks: [{
  182. innerText: CONST.Text.Enable
  183. },{
  184. options: [{
  185. path: 'common/enable',
  186. type: 'boolean'
  187. }]
  188. }]
  189. },{
  190. blocks: [{
  191. innerText: CONST.Text.BackgroundImage
  192. },{
  193. options: [{
  194. path: 'common/image',
  195. type: 'string',
  196. checker: imageUrlChecker,
  197. }]
  198. }]
  199. }]
  200. },{
  201. rows: [{
  202. blocks: [{
  203. isHeader: true,
  204. colSpan: 2,
  205. innerText: CONST.Text.NovelBeautify
  206. }]
  207. },{
  208. blocks: [{
  209. innerText: CONST.Text.Enable
  210. },{
  211. options: [{
  212. path: 'novel/enable',
  213. type: 'boolean'
  214. }]
  215. }]
  216. },{
  217. blocks: [{
  218. innerText: CONST.Text.BackgroundImage
  219. },{
  220. options: [{
  221. path: 'novel/image',
  222. type: 'string',
  223. checker: imageUrlChecker,
  224. }]
  225. }]
  226. }]
  227. },{
  228. rows: [{
  229. blocks: [{
  230. isHeader: true,
  231. colSpan: 2,
  232. innerText: CONST.Text.ReviewBeautify
  233. }]
  234. },{
  235. blocks: [{
  236. innerText: CONST.Text.Enable
  237. },{
  238. options: [{
  239. path: 'review/enable',
  240. type: 'boolean'
  241. }]
  242. }]
  243. },{
  244. blocks: [{
  245. innerText: CONST.Text.BackgroundImage
  246. },{
  247. options: [{
  248. path: 'review/image',
  249. type: 'string',
  250. checker: imageUrlChecker,
  251. }]
  252. }]
  253. }]
  254. },{
  255. rows: [{
  256. blocks: [{
  257. isHeader: true,
  258. colSpan: 2,
  259. innerText: CONST.Text.DefaultBeautify
  260. }]
  261. },{
  262. blocks: [{
  263. innerText: CONST.Text.BackgroundImage
  264. },{
  265. options: [{
  266. path: 'image',
  267. type: 'string',
  268. checker: imageUrlChecker,
  269. }]
  270. }]
  271. }]
  272. }]
  273. }, storage);
  274.  
  275. function imageUrlChecker(e, value) {
  276. if (!value.match(/.+:/)) {
  277. alertify.alert(CONST.Text.AlertTitle, CONST.Text.InvalidImageUrl);
  278. return false;
  279. }
  280. e.target.value = value || null;
  281. return true;
  282. }
  283. }
  284. })();