1let halo = { 2 darkComment: () => { 3 if (document.querySelector('#comment div').shadowRoot.querySelector('.halo-comment-widget').classList != null) { 4 let commentDOMclass = document.querySelector('#comment div').shadowRoot.querySelector('.halo-comment-widget').classList 5 if (commentDOMclass.contains('light')) 6 commentDOMclass.replace('light', 'dark') 7 else 8 commentDOMclass.replace('dark', 'light') 9 } 10 11 }, 12 13 dataCodeTheme: () => { 14 15 var t = document.documentElement.getAttribute('data-theme') 16 var e = document.querySelector("link[data-code-theme=light]"), 17 o = document.querySelector("link[data-code-theme=dark]"); 18 (o || e) && ("light" === t ? (o.disabled = !0, e.disabled = !1) : (e.disabled = !0, o.disabled = !1)) 19 20 }, 21 22 /** 23 * 代ç 24 * åªéç¨äºhaloçä»£ç æ¸²æ 25 */ 26 addPrismTool: () => { 27 if (typeof Prism === 'undefined' || typeof document === 'undefined') { 28 return; 29 } 30 31 if (!Prism.plugins.toolbar) { 32 console.warn('Copy to Clipboard plugin loaded before Toolbar plugin.'); 33 34 return; 35 } 36 37 const enable = GLOBAL_CONFIG.prism.enable; 38 if (!enable) return; 39 const isEnableTitle = GLOBAL_CONFIG.prism.enable_title; 40 const isEnableHr = GLOBAL_CONFIG.prism.enable_hr; 41 const isEnableLine = GLOBAL_CONFIG.prism.enable_line; 42 const isEnableCopy = GLOBAL_CONFIG.prism.enable_copy; 43 const isEnableExpander = GLOBAL_CONFIG.prism.enable_expander; 44 const prismLimit = GLOBAL_CONFIG.prism.prism_limit; 45 const isEnableHeightLimit = GLOBAL_CONFIG.prism.enable_height_limit; 46 47 // https://stackoverflow.com/a/30810322/7595472 48 49 /** @param {CopyInfo} copyInfo */ 50 function fallbackCopyTextToClipboard(copyInfo) { 51 var textArea = document.createElement('textarea'); 52 textArea.value = copyInfo.getText(); 53 54 // Avoid scrolling to bottom 55 textArea.style.top = '0'; 56 textArea.style.left = '0'; 57 textArea.style.position = 'fixed'; 58 59 document.body.appendChild(textArea); 60 textArea.focus(); 61 textArea.select(); 62 63 try { 64 var successful = document.execCommand('copy'); 65 setTimeout(function () { 66 if (successful) { 67 copyInfo.success(); 68 } else { 69 copyInfo.error(); 70 } 71 }, 1); 72 } catch (err) { 73 setTimeout(function () { 74 copyInfo.error(err); 75 }, 1); 76 } 77 78 document.body.removeChild(textArea); 79 } 80 81 /** @param {CopyInfo} copyInfo */ 82 function copyTextToClipboard(copyInfo) { 83 if (navigator.clipboard) { 84 navigator.clipboard.writeText(copyInfo.getText()).then(copyInfo.success, function () { 85 // try the fallback in case `writeText` didn't work 86 fallbackCopyTextToClipboard(copyInfo); 87 }); 88 } else { 89 fallbackCopyTextToClipboard(copyInfo); 90 } 91 } 92 93 /** 94 * Selects the text content of the given element. 95 * 96 * @param {Element} element 97 */ 98 function selectElementText(element) { 99 // https://stackoverflow.com/a/20079910/7595472 100 window.getSelection().selectAllChildren(element); 101 } 102 103 /** 104 * Traverses up the DOM tree to find data attributes that override the default plugin settings. 105 * 106 * @param {Element} startElement An element to start from. 107 * @returns {Settings} The plugin settings. 108 * @typedef {Record<"copy" | "copy-error" | "copy-success" | "copy-timeout", string | number>} Settings 109 */ 110 function getSettings(startElement) { 111 /** @type {Settings} */ 112 var settings = { 113 'copy': 'Copy', 114 'copy-error': 'Press Ctrl+C to copy', 115 'copy-success': 'Copied!', 116 'copy-timeout': 5000 117 }; 118
119 var prefix = 'data-prismjs-'; 120 for (var key in settings) { 121 var attr = prefix + key; 122 var element = startElement; 123 while (element && !element.hasAttribute(attr)) { 124 element = element.parentElement; 125 } 126 if (element) { 127 settings[key] = element.getAttribute(attr); 128 } 129 } 130 return settings; 131 } 132 133 var r = Prism.plugins.toolbar.hook = function (a) { 134 135 136 var r = a.element.parentNode; 137 var toolbar = r.nextElementSibling; 138 139 //æ é¢ 140 isEnableTitle && toolbar.classList.add("c-title") 141 //æ é¢åå²çº¿ 142 isEnableHr && toolbar.classList.add("c-hr") 143 var customItem = document.createElement("div"); 144 customItem.className = 'custom-item absolute top-0' 145 146 //å¤å¶ 147 if (isEnableCopy) { 148 var copy = document.createElement("i"); 149 150 copy.className = 'haofont hao-icon-paste copy-button code-copy cursor-pointer' 151 customItem.appendChild(copy) 152 153 copy.addEventListener('click', function () { 154 copyTextToClipboard({ 155 getText: function () { 156 return a.element.textContent; 157 }, 158 success: function () { 159 btf.snackbarShow('å¤å¶æå') 160 setState('copy-success'); 161 resetText(); 162 }, 163 error: function () { 164 setState('copy-error'); 165 166 setTimeout(function () { 167 selectElementText(a.element); 168 }, 1); 169 170 resetText(); 171 } 172 }); 173 174 }); 175 176 } 177 178 const prismToolsFn = function (e) { 179 const $target = e.target.classList; 180 if ($target.contains("code-expander")) prismShrinkFn(this); 181 }; 182 183 //æå 184 if (isEnableExpander) { 185 var expander = document.createElement("i"); 186 expander.className = 'fa-sharp fa-solid haofont hao-icon-angle-down code-expander cursor-pointer' 187 customItem.appendChild(expander) 188 189 expander.addEventListener('click', prismToolsFn) 190 191 192 } 193 194 const expandCode = function () { 195 this.classList.toggle("expand-done"); 196 this.style.display = "none"; 197 r.classList.toggle("expand-done"); 198 }; 199 200 if (isEnableHeightLimit && r.offsetHeight > prismLimit) { 201 202 r.classList.add("close") 203 const ele = document.createElement("div"); 204 ele.className = "code-expand-btn"; 205 ele.innerHTML = '<i class="haofont hao-icon-angle-double-down"></i>'; 206 ele.addEventListener("click", expandCode); 207 r.offsetParent.appendChild(ele); 208 } 209 210 const prismShrinkFn = ele => { 211 const $nextEle = r.offsetParent.lastElementChild.classList 212 toolbar.classList.toggle('c-expander') 213 r.classList.toggle("expand-done-expander"); 214 if (toolbar.classList.contains('c-expander')) { 215 r.firstElementChild.style.display = "none"; 216 if ($nextEle.contains('code-expand-btn')) { 217 r.offsetParent.lastElementChild.style.display = "none"; 218 } 219 } else { 220 r.firstElementChild.style.display = "block"; 221 if ($nextEle.contains('code-expand-btn') && !r.classList.contains('expand-done')) { 222 r.offsetParent.lastElementChild.style.display = "block"; 223 } 224 } 225 226 }; 227 228 229 toolbar.appendChild(customItem) 230 231 var settings = getSettings(a.element); 232 233 234 function resetText() { 235 setTimeout(function () { 236 setState('copy'); 237 }, settings['copy-timeout']); 238 } 239 240 /** @param {"copy" | "copy-error" | "copy-success"} state */ 241 function setState(state) { 242 copy.setAttribute('data-copy-state', state); 243 } 244 245 }; 246 Prism.hooks.add("complete", r) 247 }, 248 249 addScript: (e, t, n) => { 250 if (document.getElementById(e)) 251 return n ? n() : void 0; 252 let a = document.createElement("script"); 253 a.src = t, 254 a.id = e, 255 n && (a.onload = n), 256 document.head.appendChild(a) 257 }, 258 259 danmu: () => { 260 const e = new EasyDanmakuMin({ 261 el: "#danmu", 262 line: 10, 263 speed: 20, 264 hover: !0, 265 loop: !0 266 }); 267 let t = saveToLocal.get("danmu"); 268 if (t) 269 e.batchSend(t, !0); 270 else { 271 let n = []; 272 if (GLOBAL_CONFIG.source.comments.use == 'Twikoo') { 273 fetch(GLOBAL_CONFIG.source.twikoo.twikooUrl, { 274 method: "POST", 275 body: JSON.stringify({ 276 event: "GET_RECENT_COMMENTS", 277 accessToken: GLOBAL_CONFIG.source.twikoo.accessToken, 278 includeReply: !1, 279 pageSize: 5 280 }), 281 headers: { 282 "Content-Type": "application/json" 283 } 284 }).then((e => e.json())).then((({data: t}) => { 285 t.forEach((e => { 286 null == e.avatar && (e.avatar = "https://cravatar.cn/avatar/d615d5793929e8c7d70eab5f00f7f5f1?d=mp"), 287 n.push({ 288 avatar: e.avatar, 289 content: e.nick + "ï¼" + btf.changeContent(e.comment), 290 href: e.url + '#' + e.id 291 292 }) 293 } 294 )), 295 e.batchSend(n, !0), 296 saveToLocal.set("danmu", n, .02) 297 } 298 )) 299 } 300 if (GLOBAL_CONFIG.source.comments.use == 'Artalk') { 301 const statheaderList = { 302 method: 'POST', 303 headers: { 304 'Content-Type': 'application/x-www-form-urlencoded', 305 'Origin': window.location.origin 306 }, 307 body: new URLSearchParams({ 308 'site_name': GLOBAL_CONFIG.source.artalk.siteName, 309 'limit': '100', 310 'type': 'latest_comments' 311 }) 312 } 313 fetch(GLOBAL_CONFIG.source.artalk.artalkUrl + 'api/stat', statheaderList) 314 .then((e => e.json())).then((({data: t}) => { 315 t.forEach((e => { 316 n.push({ 317 avatar: 'https://cravatar.cn/avatar/' + e.email_encrypted + '?d=mp&s=240', 318 content: e.nick + "ï¼" + btf.changeContent(e.content_marked), 319 href: e.page_url + '#atk-comment-' + e.id 320 321 }) 322 } 323 )), 324 e.batchSend(n, !0), 325 saveToLocal.set("danmu", n, .02) 326 } 327 )) 328 } 329 if (GLOBAL_CONFIG.source.comments.use == 'Waline') { 330 const loadWaline = () => { 331 Waline.RecentComments({ 332 serverURL: GLOBAL_CONFIG.source.waline.serverURL, 333 count: 50 334 }).then(({comments}) => { 335 const walineArray = comments.map(e => { 336 return { 337 'content': e.nick + "ï¼" + btf.changeContent(e.comment), 338 'avatar': e.avatar, 339 'href': e.url + '#' + e.objectId, 340 } 341 }) 342 e.batchSend(walineArray, !0), 343 saveToLocal.set("danmu", walineArray, .02) 344 }) 345 } 346 if (typeof Waline === 'object') loadWaline() 347 else getScript(GLOBAL_CONFIG.source.waline.js).then(loadWaline) 348 } 349 350 } 351 document.getElementById("danmuBtn").innerHTML = "<button class=\"hideBtn\" onclick=\"document.getElementById('danmu').
351classList.remove('hidedanmu')\">æ¾ç¤ºå¼¹å¹</button> <button class=\"hideBtn\" onclick=\"document.getElementById('danmu').classList.add('hidedanmu')\">éèå¼¹å¹</button>" 352 }, 353 354 changeMarginLeft(element) { 355 var randomMargin = Math.floor(Math.random() * 901) + 100; // çæ100-1000ä¹é´çéæºæ° 356 element.style.marginLeft = randomMargin + 'px'; 357 }, 358 359 getTopSponsors() { 360 361 var show_num = GLOBAL_CONFIG.source.power.showNum 362 363 364 function getPower() { 365 const url = "/apis/api.plugin.halo.run/v1alpha1/plugins/plugin-afdian/afdian/getSponsorList" 366 fetch(url) 367 .then(res => res.json()) 368 .then(data => { 369 console.log(data) 370 if (200 === data["ec"]) { 371 const values = data["data"]["list"]; 372 saveToLocal.set('power-data', JSON.stringify(values), 10 / (60 * 24)) 373 renderer(values); 374 } 375 376 }) 377 } 378 379 function renderer(values) { 380 var data = getArrayItems(values, 1); 381 let powerStar = document.getElementById("power-star") 382 if (values.length === 0) { 383 powerStar.href = GLOBAL_CONFIG.source.power.powerLink + GLOBAL_CONFIG.source.power.username 384 powerStar.innerHTML = ` 385 <div id="power-star-image" style="background-image: url('/themes/theme-hao/assets/images/afadian/afadian.webp')"> 386 </div> 387 <div class="power-star-body"> 388 <div id="power-star-title">è¿æ²¡æäººèµå©ï½</div> 389 <div id="power-star-desc">为ç±åçµï¼ç¹å»èµå©</div> 390 </div>`; 391 } else { 392 if (powerStar) { 393 powerStar.href = GLOBAL_CONFIG.source.power.powerLink + data[0]["user"].user_id 394 powerStar.innerHTML = ` 395 <div id="power-star-image" style="background-image: url(${data[0]["user"].avatar})"> 396 </div> 397 <div class="power-star-body"> 398 <div id="power-star-title">${data[0]["user"].name}</div> 399 <div id="power-star-desc">æ´å¤æ¯æï¼ä¸ºç±åçµ</div> 400 </div>`; 401 } 402 403 if (values.length > 1) { 404 var i = 0; 405 var htmlText = ''; 406 for (let value of values) { 407 if (i > parseInt(show_num)) { 408 break; 409 } 410 htmlText += ` <a href="${"https://afdian.net/u/" + value["user"]["user_id"]}" rel="external nofollow" target="_blank" th:title="${value["user"]["name"]}">${value["user"]["name"]}</a>`; 411 i = i + 1; 412 } 413 if (document.getElementById("power-item-link")) { 414 document.getElementById("power-item-link").innerHTML = htmlText; 415 } 416 } 417 } 418 } 419 420 function init() { 421 const data = saveToLocal.get('power-data') 422 if (data) { 423 renderer(JSON.parse(data)) 424 } else { 425 getPower() 426 } 427 } 428 429 document.getElementById("power-star") && init() 430 } 431 , 432 433 checkAd() { 434 var default_enable = GLOBAL_CONFIG.source.footer.default_enable 435 if (default_enable) { 436 var adElement = document.getElementById("footer-banner"); 437 var notMusic = document.body.getAttribute("data-type") != "music"; // æ£æµæ¯å¦ä¸ºé³ä¹é¡µé¢ 438 if ((adElement.offsetWidth <= 0 || adElement.offsetHeight <= 0) && notMusic) { 439 // å ç´ ä¸å¯è§ï¼å¯è½è¢«æ¦æª 440 console.log("Element may be blocked by AdBlocker Ultimate"); 441 alert("页èä¿¡æ¯å¯è½è¢«AdBlocker Ultimateæ¦æªï¼è¯·æ£æ¥å¹¿åæ¦æªæä»¶ï¼") 442 } 443 } 444 }, 445 446}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.