cnblogs garden

better cnblogs

As of 2024-02-20. See the latest version.

  1. // ==UserScript==
  2. // @name cnblogs garden
  3. // @name:zh 博客花园(cnblogs 博客园美化)
  4. // @namespace http://github.com/yuhanawa/UserScript
  5. // @name:zh-CN 博客花园(cnblogs 博客园美化)
  6. // @description better cnblogs
  7. // @description:zh cnblogs 博客园 美化 增强
  8. // @description:zh-CN cnblogs 博客园 美化 增强
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // @grant GM_addStyle
  12. // @grant GM_registerMenuCommand
  13. // @grant GM_openInTab
  14. // @grant unsafeWindow
  15. // @match *://cnblogs.com/*
  16. // @match *://yuhan-script-config.netlify.app/*
  17. // @match *://user-script-config-form.vercel.app/*
  18. // @match *://yuhanawa.github.io/tools/userscriptconfig/*
  19. // @version 0.1.4
  20. // @author Yuhanawa
  21. // @license GPL-3.0
  22. // @icon none
  23. // @run-at document-start
  24. // ==/UserScript==
  25.  
  26. /*
  27. cnblogs v.0.1.4 by Yuhanawa
  28. Source: https://github.com/Yuhanawa/UserScript
  29. */
  30.  
  31. isLoaded=!1,onload(()=>isLoaded=!0);const __props__=new Map;
  32. function $get(k,d){return GM_getValue(k,void 0===d?__props__.get(k):d)}
  33. function $set(k,v){return GM_setValue(k,v)}
  34. function getOptionKeyAndName(optionStr){var key=optionStr.match(/\$([^ ]+)/)?.[0];return key?{key:key.replace("$",""),name:optionStr.replace(key,"")}:{key:optionStr,name:optionStr}}
  35. function findFastestSite(sites){return new Promise((resolve,reject)=>{let fastestSite=null,fastestTime=1/0,completedRequests=0;sites.forEach(function(site){const xhr=new XMLHttpRequest,startTime=(new Date).getTime();xhr.onreadystatechange=()=>{var timeElapsed;fastestTime<100&&(xhr.abort(),resolve(fastestSite)),xhr.readyState===XMLHttpRequest.DONE&&(timeElapsed=(new Date).getTime()-startTime,console.log(`Ping ${site} took ${timeElapsed}ms`),console.log("Status: "+xhr.status),xhr.status<400&&timeElapsed<fastestTime&&(fastestTime=timeElapsed,fastestSite=site),++completedRequests===sites.length)&&resolve(fastestSite)},xhr.onprogress=()=>{fastestTime<100&&(xhr.abort(),resolve(fastestSite))},xhr.onload=()=>{console.log("Pinging "+site)},xhr.open("GET",site,!0),xhr.timeout=2e3,xhr.send()})})}
  36. function getConfigPage(){return findFastestSite(["https://user-script-config-form.vercel.app","https://yuhan-script-config.netlify.app","https://yuhanawa.github.io/tools/userscriptconfig/"]).then(fastestSite=>fastestSite).catch(error=>(console.error("Error:",error),null))}
  37. function showConfigPage(){document.querySelector("#config-page-awa")?document.querySelector("#config-page-awa").style.display="block":getConfigPage().then(fastestSite=>{void 0!==GM_openInTab?GM_openInTab(fastestSite,{active:!0}):location.href=fastestSite})}
  38. function LoadConfigPage(name){if(!document.querySelector("#config-page-awa"))return style(`
  39. .config-page-awa {
  40. position: fixed;
  41. background-color: rgba(245, 200, 200, 0.2);
  42. z-index: 9999;
  43. top: 0;
  44. left: 0;
  45. width: 100vw;
  46. height: 100vh;
  47. display: block;
  48. justify-content: center;
  49. align-items: center;
  50. flex-direction: column;
  51. backdrop-filter: blur(20px);
  52. }
  53. .config-page-container {
  54. width: 60%;
  55. height: 60%;
  56. position: absolute;
  57. top: 15%;
  58. left: 15%;
  59. cursor: auto;
  60. border: 1px thin #cccccc10;
  61. border-radius: 20px;
  62. box-shadow: 0 0 10px rgba(0, 0, 0, 0.65);
  63. background-color: rgba(255, 255, 255, 0.6);
  64. overflow: hidden;
  65. padding: 15px;
  66. box-sizing: border-box;
  67. overflow-y: hidden;
  68. min-width: 360px;
  69. min-height: 420px;
  70. resize: both;
  71. }
  72. .config-page-drag-area {
  73. position: absolute;
  74. width: 100%;
  75. height: 100%;
  76. top: 0;
  77. left: 0;
  78. cursor: move;
  79. background-color: transparent;
  80. }
  81. .config-page-iframe {
  82. border: 0;
  83. border-radius: 18px;
  84. overflow: hidden;
  85. box-sizing: border-box;
  86. overflow-y: auto;
  87. opacity: 0.95;
  88. width: 100%;
  89. height: 100%;
  90. box-shadow: 1px 1px 4px rgba(185, 185, 185, 0.2);
  91. background-color: rgba(255, 255, 255, 0.25);
  92. margin: -1px;
  93. }
  94. .config-page-close-btn {
  95. position: absolute;
  96. top: 4px;
  97. right: 5px;
  98. font-size: 20px;
  99. background-color: transparent;
  100. border: 0;
  101. color: #C00;
  102. cursor: pointer;
  103. outline: none;
  104. padding: 0;
  105. margin: 0;
  106. }
  107. .config-page-close-btn:hover {
  108. color: #A00;
  109. }
  110. .config-page-close-btn:active {
  111. color: #f00;
  112. transform: scale(0.8);
  113. transition: 0.15s;
  114. }
  115. `),getConfigPage().then(fastestSite=>{document.body.insertAdjacentHTML("afterend",`
  116. <div class="config-page-awa" id="config-page-awa" style="display: none;">
  117. <div class="config-page-container">
  118. <div class="config-page-drag-area"></div>
  119. <iframe class="config-page-iframe"
  120. src="${fastestSite}?menuKey=${name}&iniframe"></iframe>
  121.  
  122. <button class="config-page-close-btn">⭕</button>
  123. </div>
  124. </div>`);const configPage=document.querySelector("#config-page-awa"),container=configPage.querySelector(".config-page-container"),iframe=configPage.querySelector(".config-page-iframe");var fastestSite=configPage.querySelector(".config-page-drag-area"),pos1=0,pos2=0,pos3=0,pos4=0;
  125. function elementDrag(e){(e=e||window.event).preventDefault(),pos1=pos3-e.clientX,pos2=pos4-e.clientY,pos3=e.clientX,pos4=e.clientY,container.style.top=container.offsetTop-pos2+"px",container.style.left=container.offsetLeft-pos1+"px"}
  126. function closeDragElement(){iframe.style.pointerEvents="auto",configPage.onmouseup=null,configPage.onmousemove=null}return fastestSite.onmousedown=function(e){(e=e||window.event).preventDefault(),pos3=e.clientX,pos4=e.clientY,iframe.style.pointerEvents="none",configPage.onmouseup=closeDragElement,configPage.onmousemove=elementDrag;e=window.getComputedStyle(event.target).cursor;console.log("当前鼠标样式:"+e)},configPage.querySelector(".config-page-close-btn").onclick=function(){configPage.style.display="none"},Promise.resolve()});showConfigPage()}
  127. function loadConfig(name,properties){GM_registerMenuCommand("在新窗口打开配置界面",()=>{showConfigPage()}),GM_registerMenuCommand("在页面内镶嵌配置界面(BETA)",()=>{LoadConfigPage(name).then(()=>showConfigPage())}),anchors=[];for(const key of Object.keys(properties))__props__.set(name+"_"+key,properties[key].default),key.startsWith("#")&&anchors.push({key:key,href:properties[key].href||key,title:properties[key].title||properties[key].description||key});(location.href.match("yuhan-script-config.netlify.app")||location.href.match("user-script-config-form.vercel.app")||location.href.match("yuhanawa.github.io/tools/userscriptconfig")||location.href.match("localhost"))&&(void 0===unsafeWindow.userscript&&(unsafeWindow.userscript={}),unsafeWindow.userscript[name]={props:properties,anchors:anchors,get:$get,set:$set})}
  128. function style(css){var node;"undefined"!=typeof GM_addStyle?GM_addStyle(css):((node=document.createElement("style")).appendChild(document.createTextNode(css)),document.body.appendChild(node))}
  129. function option(name,key,options,current,index,onclick){return null!=current&&null!=index||(current=$set(key,getOptionKeyAndName(options[0]).key),index=options.indexOf(options.filter(x=>getOptionKeyAndName(x).key==current)[0])),-1!==index&&void 0!==index||($set(key,getOptionKeyAndName(options[0]).key),current=getOptionKeyAndName(options[index=0]).key),name+=`:${getOptionKeyAndName(options[index]).name}[${index+1}/${options.length}]<点击切换模式`,GM_registerMenuCommand(name,()=>{if(index+1>=options.length?$set(key,getOptionKeyAndName(options[0]).key):$set(key,getOptionKeyAndName(options[index+1]).key),onclick)try{onclick()}catch{}location.reload()}),index}
  130. function onload(f){isLoaded?f():document.addEventListener("DOMContentLoaded",()=>f())}
  131. function timeoutOnLoad(f,t){onload(()=>setTimeout(()=>f(),t))}
  132. function intervalOnLoad(f,timeout){onload(()=>setInterval(f,timeout))}
  133. function run(fts){void 0===fts&&(fts=features);for(const key of Object.keys(fts)){var feature=fts[key];0!==feature.match.filter(m=>"string"==typeof m?null!==window.location.href.match(m):m.test(window.location.href)).length&&addFeature(key,feature)}}
  134. function addFeature(key,feature){var{name,values}=feature;if("$"===name)try{"function"==typeof values?"string"==typeof(result=values(feature))&&style(result):"string"==typeof values&&style(value)}catch(e){console.error(e)}else{var result=Object.keys(values),key0=getOptionKeyAndName(result[0]).key;let current=$get(key,key0),index=result.findIndex(x=>getOptionKeyAndName(x).key===current);-1!==index&&void 0!==index||($set(key,key0),index=0,current=key0),option(name,key,result,current,index);try{const value=values[result[index]];if(null!==value&&void 0!==value)if("function"==typeof value){const result=value(feature);"string"==typeof result&&style(result)}else"string"==typeof value&&style(value)}catch(e){console.error(e)}}}
  135.  
  136.  
  137. loadConfig('cnblogs', {"num":{"title":"复杂数字输入框","type":"number","defaultValue":250,"props":{"placeholder":"520","addonBefore":"前置","addonAfter":"后置"},"description":"描述","tooltip":{"title":"tooltip提示"},"extra":"补充","required":true,"message":{"required":"必须填哦~"},"widget":"inputNumber"},"color":{"title":"颜色选择","type":"string","widget":"color"}})
  138.  
  139. let features_cnblogs_183289398={
  140. cnblogs_example:{name:"example示例",match:["."],values:{"已关闭$off":null,"已开启$on":""}},
  141. cnblogs_base:{name:"美化",match:["."],values:{"已关闭$off":null,"已开启$on":".sidenav{width:fit-content;font-size:larger;padding-top:14px}.sidenav .sidenav-item{margin:2px!important;padding:14px;border-radius:16px}.sidenav .sidenav-item img{width:24px;height:24px}.sidenav .sidenav-item:hover:not(.current-nav){background:rgba(204,204,204,.8)}.sidenav-category-active,.sidenav-item.current-nav{padding:14px!important;margin:2px 4px 2px 2px!important;font-weight:700}.sidenav-category-active img,.sidenav-item.current-nav img{width:26px;height:26px;box-shadow:inset 0 0 12px 32px rgba(205,255,255,.8509803922),-6px 3px 12px 6px rgba(0,255,255,.1215686275);border-radius:18px}#sidenav_more .dropdown-menu{left:6px;top:85%;font-size:large}#sidenav_more .dropdown-menu:hover{box-shadow:2px 5px 16px 4px #ccc}.post-list>.post-item>.post-item-body>.post-item-text>.post-item-title{font-weight:700;font-size:18px}.post-list>.post-item>.post-item-body>.post-item-text>.post-item-summary{font-size:14px}.card.headline{background:rgba(240,248,255,.8705882353);border-radius:16px;box-shadow:2px 2px 14px 1px rgba(240,248,255,.8705882353)}.card.headline a{font-size:14px;color:#003aae}.card.headline .headline-label{font-size:16px;color:#4242fb}.post-list{border-top:1px dashed #dcdcdc;margin-top:20px}"}}
  142. };
  143. run(features_cnblogs_183289398);