1const sidebarFn = () => { 2 const $toggleMenu = document.getElementById("toggle-menu"); 3 const $mobileSidebarMenus = document.getElementById("sidebar-menus"); 4 const $menuMask = document.getElementById("menu-mask"); 5 const $body = document.body; 6 7 const toggleMobileSidebar = (isOpen) => { 8 $body.style.overflow = isOpen ? "hidden" : ""; 9 utils[isOpen ? "fadeIn" : "fadeOut"]($menuMask, 0.5); 10 $mobileSidebarMenus.classList.toggle("open", isOpen); 11 }; 12 13 const closeMobileSidebar = () => { 14 if ($mobileSidebarMenus.classList.contains("open")) { 15 toggleMobileSidebar(false); 16 } 17 }; 18 19 $toggleMenu.addEventListener("click", () => toggleMobileSidebar(true)); 20 $menuMask.addEventListener("click", closeMobileSidebar); 21 22 window.addEventListener("resize", () => { 23 if ( 24 utils.isHidden($toggleMenu) && 25 $mobileSidebarMenus.classList.contains("open") 26 ) { 27 closeMobileSidebar(); 28 } 29 sco.refreshWaterFall(); 30 }); 31}; 32 33const scrollFn = () => { 34 const $rightside = document.getElementById("rightside"); 35 const $header = document.getElementById("page-header"); 36 let initTop = 0; 37 38 const updateHeaderAndRightside = (isDown, currentTop) => { 39 if (currentTop > 0) { 40 $header.classList.toggle("nav-visible", !isDown); 41 $header.classList.add("nav-fixed"); 42 if ($rightside) { 43 $rightside.style.opacity = "0.8"; 44 $rightside.style.transform = "translateX(-58px)"; 45 } 46 } else { 47 $header.classList.remove("nav-fixed", "nav-visible"); 48 if ($rightside) { 49 $rightside.style.opacity = ""; 50 $rightside.style.transform = ""; 51 } 52 } 53 }; 54 55 const throttledScroll = utils.throttle(() => { 56 initThemeColor(); 57 const currentTop = window.scrollY || document.documentElement.scrollTop; 58 const isDown = currentTop > initTop; 59 initTop = currentTop; 60 updateHeaderAndRightside(isDown, currentTop); 61 }, 200); 62 63 window.addEventListener("scroll", (e) => { 64 throttledScroll(e); 65 if (window.scrollY === 0) { 66 $header.classList.remove("nav-fixed", "nav-visible"); 67 if ($rightside) { 68 $rightside.style.cssText = "opacity: ''; transform: ''"; 69 } 70 } 71 }); 72}; 73 74const percent = () => { 75 const docEl = document.documentElement; 76 const body = document.body; 77 const scrollPos = window.pageYOffset || docEl.scrollTop; 78 const totalScrollableHeight = 79 Math.max( 80 body.scrollHeight, 81 docEl.scrollHeight, 82 body.offsetHeight, 83 docEl.offsetHeight, 84 body.clientHeight, 85 docEl.clientHeight 86 ) - docEl.clientHeight; 87 const scrolledPercent = Math.round((scrollPos / totalScrollableHeight) * 100); 88 const navToTop = document.querySelector("#nav-totop"); 89 const rsToTop = document.querySelector(".rs_show .top i"); 90 const percentDisplay = document.querySelector("#percent"); 91 const isNearEnd = 92 window.scrollY + docEl.clientHeight >= 93 ( 94 document.getElementById("post-comment") || 95 document.getElementById("footer") 96 ).offsetTop; 97 98 navToTop?.classList.toggle("long", isNearEnd || scrolledPercent > 90); 99 rsToTop?.classList.toggle("show", isNearEnd || scrolledPercent > 90); 100 percentDisplay.textContent = 101 isNearEnd || scrolledPercent > 90 102 ? navToTop 103 ? GLOBAL_CONFIG.lang.backtop 104 : "" 105 : scrolledPercent; 106 107 document 108 .querySelectorAll(".needEndHide") 109 .forEach((item) => 110 item.classList.toggle("hide", totalScrollableHeight - scrollPos < 100) 111 ); 112}; 113 114const showTodayCard = () => { 115 const el = document.getElementById("todayCard"); 116 const topGroup = document.querySelector(".topGroup"); 117 topGroup?.addEventListener("mouseleave", () => el?.classList.remove("hide")); 118}; 119 120const initObserver = () => { 121 const commentElement = document.getElementById("post-comment"); 122 const paginationElement = document.getElementById("pagination"); 123 const commentBarrageElement = document.querySelector(".comment-barrage"); 124 125 if (commentElement && paginationElement) { 126 const observer = new IntersectionObserver((entries) => { 127 entries.forEach((entry) => { 128 paginationElement.classList.toggle("show-window", entry.isIntersecting); 129 if (GLOBAL_CONFIG.comment.commentBarrage) { 130 commentBarrageElement.style.bottom = entry.isIntersecting 131 ? "-200px" 132 : "0px"; 133 } 134 }); 135 }); 136 observer.observe(commentElement); 137 } 138}; 139 140const addCopyright = () => { 141 if (!GLOBAL_CONFIG.copyright) return; 142 const { limit, author, link, source, info } = GLOBAL_CONFIG.copyright; 143 144 document.body.addEventListener("copy", (e) => { 145 e.preventDefault(); 146 const copyText = window.getSelection().toString(); 147 const text = 148 copyText.length > limit 149 ? `${copyText}\n\n${author}\n${link}${window.location.href}\n${source}\n${info}` 150 : copyText; 151 e.clipboardData.setData("text", text); 152 }); 153}; 154 155const asideStatus = () => { 156 const status = utils.saveToLocal.get("aside-status"); 157 document.documentElement.classList.toggle("hide-aside", status === "hide"); 158}; 159 160function initThemeColor() { 161 const currentTop = window.scrollY || document.documentElement.scrollTop;
162 const themeColor = 163 currentTop > 0 164 ? "--efu-card-bg" 165 : PAGE_CONFIG.is_post 166 ? "--efu-main" 167 : "--efu-background"; 168 applyThemeColor( 169 getComputedStyle(document.documentElement).getPropertyValue(themeColor) 170 ); 171} 172 173function applyThemeColor(color) { 174 const themeColorMeta = document.querySelector('meta[name="theme-color"]'); 175 const appleMobileWebAppMeta = document.querySelector( 176 'meta[name="apple-mobile-web-app-status-bar-style"]' 177 ); 178 themeColorMeta?.setAttribute("content", color); 179 appleMobileWebAppMeta?.setAttribute("content", color); 180 if (window.matchMedia("(display-mode: standalone)").matches) { 181 document.body.style.backgroundColor = color; 182 } 183} 184 185const handleThemeChange = (mode) => { 186 const themeChange = window.globalFn?.themeChange || {}; 187 Object.values(themeChange).forEach((fn) => fn(mode)); 188}; 189 190const sco = { 191 lastWittyWord: "", 192 wasPageHidden: false, 193 musicPlaying: false, 194 scrollTo(elementId) { 195 const targetElement = document.getElementById(elementId); 196 if (targetElement) { 197 const targetPosition = 198 targetElement.getBoundingClientRect().top + window.pageYOffset - 80; 199 window.scroll({ top: targetPosition, behavior: "smooth" }); 200 } 201 }, 202 musicToggle(isMeting = true) { 203 if (!this.isMusicBind) { 204 this.musicBind(); 205 } 206 const $music = document.querySelector("#nav-music"); 207 const $meting = document.querySelector("meting-js"); 208 const $console = document.getElementById("consoleMusic"); 209 const $rmText = document.querySelector("#menu-music-toggle span"); 210 const $rmIcon = document.querySelector("#menu-music-toggle i"); 211 212 this.musicPlaying = !this.musicPlaying; 213 $music.classList.toggle("playing", this.musicPlaying); 214 $music.classList.toggle("stretch", this.musicPlaying); 215 $console?.classList.toggle("on", this.musicPlaying); 216 217 if (typeof rm !== "undefined" && rm?.menuItems.music[0]) { 218 $rmText.textContent = this.musicPlaying 219 ? GLOBAL_CONFIG.right_menu.music.stop 220 : GLOBAL_CONFIG.right_menu.music.start; 221 $rmIcon.className = this.musicPlaying 222 ? "solitude fas fa-pause" 223 : "solitude fas fa-play"; 224 } 225 226 if (isMeting) { 227 this.musicPlaying ? $meting.aplayer.play() : $meting.aplayer.pause(); 228 } 229 }, 230 musicBind() { 231 const $music = document.querySelector("#nav-music"); 232 const $name = document.querySelector("#nav-music .aplayer-music"); 233 const $button = document.querySelector("#nav-music .aplayer-button"); 234 235 $name?.addEventListener("click", () => { 236 $music.classList.toggle("stretch"); 237 }); 238 239 $button?.addEventListener("click", () => { 240 this.musicToggle(false); 241 }); 242 243 this.isMusicBind = true; 244 }, 245 switchCommentBarrage() { 246 const commentBarrageElement = document.querySelector(".comment-barrage"); 247 const consoleCommentBarrage = document.querySelector( 248 "#consoleCommentBarrage" 249 ); 250 if (!commentBarrageElement) return; 251 252 const isDisplayed = 253 window.getComputedStyle(commentBarrageElement).display === "flex"; 254 commentBarrageElement.style.display = isDisplayed ? "none" : "flex"; 255 consoleCommentBarrage?.classList.toggle("on", !isDisplayed); 256 utils.saveToLocal.set("commentBarrageSwitch", !isDisplayed, 0.2); 257 rm?.menuItems.barrage && rm.barrage(isDisplayed); 258 }, 259 switchHideAside() { 260 const htmlClassList = document.documentElement.classList; 261 const consoleHideAside = document.querySelector("#consoleHideAside"); 262 const isHideAside = htmlClassList.contains("hide-aside"); 263 utils.saveToLocal.set("aside-status", isHideAside ? "show" : "hide", 1); 264 htmlClassList.toggle("hide-aside"); 265 consoleHideAside.classList.toggle("on", !isHideAside); 266 }, 267 switchKeyboard() { 268 this.sco_keyboards = !this.sco_keyboards; 269 const consoleKeyboard = document.querySelector("#consoleKeyboard"); 270 const keyboardFunction = this.sco_keyboards ? openKeyboard : closeKeyboard; 271 consoleKeyboard?.classList.toggle("on", this.sco_keyboards); 272 keyboardFunction(); 273 localStorage.setItem("keyboard", this.sco_keyboards); 274 document.getElementById("keyboard-tips")?.classList.remove("show"); 275 }, 276 initConsoleState() { 277 const consoleHideAside = document.querySelector("#consoleHideAside"); 278 if (!consoleHideAside) return; 279 consoleHideAside.classList.toggle( 280 "on", 281 document.documentElement.classList.contains("hide-aside") 282 ); 283 }, 284 changeWittyWord() { 285 const greetings = GLOBAL_CONFIG.aside.witty_words; 286 const greetingElement = document.getElementById("sayhi"); 287 let randomGreeting; 288 do { 289 randomGreeting = greetings[Math.floor(Math.random() * greetings.length)]; 290 } while (randomGreeting === this.lastWittyWord); 291 greetingElement.textContent = randomGreeting; 292 this.lastWittyWord = randomGreeting; 293 }, 294 switchDarkMode() { 295 const isDarkMode = 296 document.documentElement.getAttribute("data-theme") === "dark"; 297 const newMode = isDarkMode ? "light" : "dark"; 298 document.documentElement.setAttribute("data-theme", newMode); 299 utils.saveToLocal.set("theme", newMode, 0.02); 300 utils.snackbarShow(GLOBAL_CONFIG.lang.theme[newMode], false, 2000); 301 if (typeof rm === "object") rm.mode(!isDarkMode) && rm.hideRightMenu(); 302 handleThemeChange(newMode); 303 }, 304 hideTodayCard: () => 305 document.getElementById("todayCard").classList.add("hide"), 306 toTop: () => utils.scrollToDest(0), 307 showConsole: () => 308 document.getElementById("console")?.classList.toggle("show", true), 309 hideConsole: () => 310 document.getElementById("console")?.classList.remove("show"), 311 refreshWaterFall() { 312 const observer = new IntersectionObserver((entries) => {
313 entries.forEach((entry) => { 314 if (entry.isIntersecting) { 315 setTimeout(() => { 316 waterfall(entry.target).then(() => { 317 entry.target.classList.add("show"); 318 }); 319 }, 300); 320 } 321 }); 322 }); 323 document 324 .querySelectorAll(".waterfall") 325 .forEach((el) => observer.observe(el)); 326 }, 327 addRuntime() { 328 const el = document.getElementById("runtimeshow"); 329 if (el && GLOBAL_CONFIG.runtime) { 330 el.innerText = 331 utils.timeDiff(new Date(GLOBAL_CONFIG.runtime), new Date()) + 332 GLOBAL_CONFIG.lang.day; 333 } 334 }, 335 toTalk(txt) { 336 const inputs = [ 337 "#wl-edit", 338 ".el-textarea__inner", 339 "#veditor", 340 ".atk-textarea", 341 ]; 342 inputs.forEach((selector) => { 343 const el = document.querySelector(selector); 344 if (el) { 345 el.dispatchEvent( 346 new Event("input", { bubble: true, cancelable: true }) 347 ); 348 el.value = "> " + txt.replace(/\n/g, "\n> ") + "\n\n"; 349 utils.scrollToDest( 350 utils.getEleTop(document.getElementById("post-comment")), 351 300 352 ); 353 el.focus(); 354 el.setSelectionRange(-1, -1); 355 } 356 }); 357 utils.snackbarShow(GLOBAL_CONFIG.lang.totalk, false, 2000); 358 }, 359 initbbtalk() { 360 const bberTalkElement = document.querySelector("#bber-talk"); 361 if (bberTalkElement) { 362 new Swiper(".swiper-container", { 363 direction: "vertical", 364 loop: true, 365 autoplay: { 366 delay: 3000, 367 pauseOnMouseEnter: true, 368 }, 369 }); 370 } 371 }, 372 addPhotoFigcaption() { 373 document 374 .querySelectorAll(".article-container img:not(.gallery-item img)") 375 .forEach((image) => { 376 const captionText = image.getAttribute("alt"); 377 if (captionText) { 378 image.insertAdjacentHTML( 379 "afterend",
380 `<div class="img-alt is-center">${utils.escapeHtml( 381 captionText 382 )}</div>` 383 ); 384 } 385 }); 386 }, 387 scrollToComment: () => 388 utils.scrollToDest( 389 utils.getEleTop(document.getElementById("post-comment")), 390 300 391 ), 392 setTimeState() { 393 const el = document.getElementById("sayhi"); 394 if (el) { 395 const hours = new Date().getHours(); 396 const lang = GLOBAL_CONFIG.aside.state; 397 398 const localData = getLocalData([ 399 "twikoo", 400 "WALINE_USER_META", 401 "WALINE_USER", 402 "_v_Cache_Meta", 403 "ArtalkUser", 404 ]); 405 406 function getLocalData(keys) { 407 for (let key of keys) { 408 const data = localStorage.getItem(key); 409 if (data) { 410 return JSON.parse(data); 411 } 412 } 413 return null; 414 } 415 const nick = localData ? localData.nick || localData.display_name : null; 416 417 const prefix = this.wasPageHidden 418 ? GLOBAL_CONFIG.aside.witty_comment.back + nick 419 : GLOBAL_CONFIG.aside.witty_comment.prefix + nick; 420 421 const greetings = [ 422 { start: 0, end: 5, text: nick ? prefix : lang.goodnight }, 423 { start: 6, end: 10, text: nick ? prefix : lang.morning }, 424 { start: 11, end: 14, text: nick ? prefix : lang.noon }, 425 { start: 15, end: 18, text: nick ? prefix : lang.afternoon }, 426 { start: 19, end: 24, text: nick ? prefix : lang.night }, 427 ]; 428 const greeting = greetings.find( 429 (g) => hours >= g.start && hours <= g.end 430 ); 431 el.innerText = greeting.text; 432 } 433 }, 434 tagPageActive() { 435 const decodedPath = decodeURIComponent(window.location.pathname); 436 const isTagPage = /\/tags\/.*?\//.test(decodedPath); 437 if (isTagPage) { 438 const tag = decodedPath.split("/").slice(-2, -1)[0]; 439 const tagElement = document.getElementById(tag); 440 if (tagElement) { 441 document.querySelectorAll("a.select").forEach((link) => { 442 link.classList.remove("select"); 443 }); 444 tagElement.classList.add("select"); 445 } 446 } 447 }, 448 categoriesBarActive() { 449 const categoryBar = document.querySelector("#category-bar"); 450 const currentPath = decodeURIComponent(window.location.pathname); 451 const isHomePage = currentPath === GLOBAL_CONFIG.root; 452 if (categoryBar) { 453 const categoryItems = categoryBar.querySelectorAll(".category-bar-item"); 454 categoryItems.forEach((item) => item.classList.remove("select")); 455 const activeItemId = isHomePage 456 ? "category-bar-home" 457 : currentPath.split("/").slice(-2, -1)[0]; 458 const activeItem = document.getElementById(activeItemId); 459 if (activeItem) { 460 activeItem.classList.add("select"); 461 } 462 } 463 }, 464 scrollCategoryBarToRight() { 465 const scrollBar = document.getElementById("category-bar-items"); 466 const nextElement = document.getElementById("category-bar-next"); 467 if (scrollBar) { 468 const isScrollBarAtEnd = () => 469 scrollBar.scrollLeft + scrollBar.clientWidth >= 470 scrollBar.scrollWidth - 8; 471 const scroll = () => { 472 scrollBar.scroll({ 473 left: isScrollBarAtEnd() ? 0 : scrollBar.clientWidth, 474 behavior: "smooth", 475 }); 476 }; 477 scrollBar.addEventListener("scroll", () => { 478 clearTimeout(this.timeoutId); 479 this.timeoutId = setTimeout(() => { 480 nextElement.style.transform = isScrollBarAtEnd() 481 ? "rotate(180deg)" 482 : ""; 483 }, 150); 484 }); 485 scroll(); 486 } 487 }, 488 openAllTags() { 489 document 490 .querySelectorAll(".card-allinfo .card-tag-cloud") 491 .forEach((tagCloudElement) => tagCloudElement.classList.add("all-tags")); 492 document.getElementById("more-tags-btn")?.remove(); 493 }, 494 listenToPageInputPress() { 495 const toGroup = document.querySelector(".toPageGroup"); 496 const pageText = document.getElementById("toPageText"); 497 if (!pageText) return; 498 const pageButton = document.getElementById("toPageButton"); 499 const pageNumbers = document.querySelectorAll(".page-number"); 500 const lastPageNumber = +pageNumbers[pageNumbers.length - 1].textContent; 501 if (!pageText || lastPageNumber === 1) { 502 toGroup.style.display = "none"; 503 return; 504 } 505 pageText.addEventListener("keydown", (event) => { 506 if (event.key === "Enter") { 507 sco.toPage(); 508 pjax.loadUrl(pageButton.href); 509 } 510 }); 511 pageText.addEventListener("input", () => { 512 pageButton.classList.toggle( 513 "haveValue", 514 pageText.value !== "" && pageText.value !== "0" 515 ); 516 if (+pageText.value > lastPageNumber) { 517 pageText.value = lastPageNumber; 518 } 519 }); 520 },
521 addNavBackgroundInit() { 522 const scrollTop = document.documentElement.scrollTop; 523 if (scrollTop !== 0) { 524 document 525 .getElementById("page-header") 526 .classList.add("nav-fixed", "nav-visible"); 527 } 528 }, 529 toPage() { 530 const pageNumbers = document.querySelectorAll(".page-number"); 531 const maxPageNumber = parseInt( 532 pageNumbers[pageNumbers.length - 1].innerHTML 533 ); 534 const inputElement = document.getElementById("toPageText"); 535 const inputPageNumber = parseInt(inputElement.value); 536 document.getElementById("toPageButton").href = 537 !isNaN(inputPageNumber) && 538 inputPageNumber <= maxPageNumber && 539 inputPageNumber > 1 540 ? window.location.href.replace(/\/page\/\d+\/$/, "/") + 541 "page/" + 542 inputPageNumber + 543 "/" 544 : "/"; 545 }, 546 owoBig(owoSelector) { 547 let owoBig = document.getElementById("owo-big"); 548 if (!owoBig) { 549 owoBig = document.createElement("div"); 550 owoBig.id = "owo-big"; 551 document.body.appendChild(owoBig); 552 } 553 const showOwoBig = (event) => { 554 const target = event.target; 555 const owoItem = target.closest(owoSelector.item); 556 if (owoItem && target.closest(owoSelector.body)) { 557 const imgSrc = owoItem.querySelector("img")?.src; 558 if (imgSrc) { 559 owoBig.innerHTML = `<img src="${imgSrc}" style="max-width: 100%; height: auto;">`; 560 owoBig.style.display = "block"; 561 positionOwoBig(owoItem); 562 } 563 } 564 }; 565 const hideOwoBig = (event) => { 566 if ( 567 event.target.closest(owoSelector.item) && 568 event.target.closest(owoSelector.body) 569 ) { 570 owoBig.style.display = "none"; 571 } 572 }; 573 const positionOwoBig = (owoItem) => { 574 const itemRect = owoItem.getBoundingClientRect(); 575 owoBig.style.left = `${itemRect.left - owoBig.offsetWidth / 4}px`; 576 owoBig.style.top = `${itemRect.top}px`; 577 }; 578 document.addEventListener("mouseover", showOwoBig); 579 document.addEventListener("mouseout", hideOwoBig); 580 }, 581 changeTimeFormat(selector) { 582 selector.forEach((item) => { 583 const timeVal = item.getAttribute("datetime"); 584 item.textContent = utils.diffDate(timeVal, true); 585 item.style.display = "inline"; 586 }); 587 }, 588 switchComments() { 589 const switchBtn = document.getElementById("switch-btn"); 590 if (!switchBtn) return; 591 let switchDone = false; 592 const commentContainer = document.getElementById("post-comment"); 593 const handleSwitchBtn = () => { 594 commentContainer.classList.toggle("move"); 595 if (!switchDone && typeof loadTwoComment === "function") { 596 switchDone = true; 597 loadTwoComment(); 598 } 599 }; 600 utils.addEventListenerPjax(switchBtn, "click", handleSwitchBtn); 601 }, 602 homeTypeit() { 603 if (typeof home_subtitle === "undefined") return; 604 const ty = new TypeIt(".banners-title-small", { 605 speed: 200, 606 waitUntilVisible: true, 607 loop: true, 608 lifeLike: true, 609 }); 610 home_subtitle.forEach((item) => { 611 ty.type(item).pause(500).delete(item); 612 }); 613 ty.go(); 614 }, 615}; 616 617const addHighlight = () => { 618 const highlight = GLOBAL_CONFIG.highlight; 619 if (!highlight) return; 620 const { copy, expand, limit, syntax } = highlight; 621 const $isPrismjs = syntax === "prismjs"; 622 const $isShowTool = highlight.enable || copy || expand || limit; 623 const expandClass = expand ? "" : "closed"; 624 const $syntaxHighlight = 625 syntax === "highlight.js" 626 ? document.querySelectorAll("figure.highlight") 627 : document.querySelectorAll('pre[class*="language-"]'); 628 629 if (!(($isShowTool || limit) && $syntaxHighlight.length)) return; 630 631 const copyEle = copy 632 ? `<i class="solitude fas fa-copy copy-button"></i>` 633 : "<i></i>";
634 const expandEle = `<i class="solitude fas fa-angle-down expand"></i>`; 635 const limitEle = limit 636 ? `<i class="solitude fas fa-angles-down"></i>` 637 : "<i></i>"; 638 639 const alertInfo = (ele, text) => utils.snackbarShow(text, false, 2000); 640 641 const copyFn = (e) => { 642 const $buttonParent = e.parentNode; 643 $buttonParent.classList.add("copy-true"); 644 const selection = window.getSelection(); 645 const range = document.createRange(); 646 const preCodeSelector = $isPrismjs ? "pre code" : "table .code pre"; 647 range.selectNodeContents( 648 $buttonParent.querySelectorAll(`${preCodeSelector}`)[0] 649 ); 650 selection.removeAllRanges(); 651 selection.addRange(range); 652 document.execCommand("copy"); 653 alertInfo(e.lastChild, GLOBAL_CONFIG.lang.copy.success); 654 selection.removeAllRanges(); 655 $buttonParent.classList.remove("copy-true"); 656 }; 657 658 const expandClose = (e) => e.classList.toggle("closed"); 659 const shrinkEle = function () { 660 this.classList.toggle("expand-done"); 661 }; 662 663 const ToolsFn = function (e) { 664 const $target = e.target.classList; 665 if ($target.contains("expand")) expandClose(this); 666 else if ($target.contains("copy-button")) copyFn(this); 667 }; 668 669 const createEle = (lang, item, service) => { 670 const fragment = document.createDocumentFragment(); 671 if ($isShowTool) { 672 const captionItem = item.querySelector("figcaption"); 673 let caption = ""; 674 if (captionItem) { 675 caption = `<div class="caption">${captionItem.innerHTML}</div>`; 676 item.removeChild(captionItem); 677 } 678 const hlTools = document.createElement("div"); 679 hlTools.className = `highlight-tools ${expandClass}`; 680 hlTools.innerHTML = expandEle + lang + caption + copyEle; 681 utils.addEventListenerPjax(hlTools, "click", ToolsFn); 682 fragment.appendChild(hlTools); 683 } 684 if (limit && item.offsetHeight > limit + 30) { 685 const ele = document.createElement("div"); 686 ele.className = "code-expand-btn"; 687 ele.innerHTML = limitEle; 688 utils.addEventListenerPjax(ele, "click", shrinkEle); 689 fragment.appendChild(ele); 690 } 691 if (service === "hl") { 692 item.insertBefore(fragment, item.firstChild); 693 } else { 694 item.parentNode.insertBefore(fragment, item); 695 } 696 }; 697 698 if ($isPrismjs) { 699 $syntaxHighlight.forEach((item) => { 700 const langName = item.getAttribute("data-language") || "Code"; 701 const highlightLangEle = `<div class="code-lang">${utils.escapeHtml( 702 langName 703 )}</div>`; 704 utils.wrap(item, "figure", { class: "highlight" }); 705 createEle(highlightLangEle, item); 706 }); 707 } else { 708 $syntaxHighlight.forEach((item) => { 709 let langName = item.getAttribute("class").split(" ")[1]; 710 if (langName === "plain" || langName === undefined) langName = "Code"; 711 const highlightLangEle = `<div class="code-lang">${utils.escapeHtml( 712 langName 713 )}</div>`; 714 createEle(highlightLangEle, item, "hl"); 715 }); 716 } 717}; 718 719class toc { 720 static init() { 721 const tocContainer = document.getElementById("card-toc"); 722 if (!tocContainer || !tocContainer.querySelector(".toc a")) { 723 tocContainer.style.display = "none"; 724 return; 725 } 726 const el = document.querySelectorAll(".toc a"); 727 el.forEach((e) => { 728 e.addEventListener("click", (event) => { 729 event.preventDefault(); 730 utils.scrollToDest( 731 utils.getEleTop( 732 document.getElementById( 733 decodeURI( 734 (event.target.className === "toc-text" 735 ? event.target.parentNode.hash 736 : event.target.hash 737 ).replace("#", "") 738 ) 739 ) 740 ), 741 300 742 ); 743 }); 744 }); 745 this.active(el); 746 } 747 748 static active(toc) { 749 const $article = document.querySelector(".article-container"); 750 const $tocContent = document.getElementById("toc-content"); 751 const list = $article.querySelectorAll("h1,h2,h3,h4,h5,h6"); 752 let detectItem = ""; 753 754 const autoScroll = (el) => { 755 const activePosition = el.getBoundingClientRect().top; 756 const sidebarScrollTop = $tocContent.scrollTop; 757 if (activePosition > document.documentElement.clientHeight - 100) { 758 $tocContent.scrollTop = sidebarScrollTop + 150; 759 } 760 if (activePosition < 100) { 761 $tocContent.scrollTop = sidebarScrollTop - 150; 762 } 763 }; 764
765 const findHeadPosition = (top) => { 766 if (top === 0) return false; 767 let currentIndex = ""; 768 list.forEach((ele, index) => { 769 if (top > utils.getEleTop(ele) - 80) { 770 currentIndex = index; 771 } 772 }); 773 if (detectItem === currentIndex) return; 774 detectItem = currentIndex; 775 document.querySelectorAll(".toc .active").forEach((i) => { 776 i.classList.remove("active"); 777 }); 778 const activeitem = toc[detectItem]; 779 if (activeitem) { 780 let parent = toc[detectItem].parentNode; 781 activeitem.classList.add("active"); 782 autoScroll(activeitem); 783 for (; !parent.matches(".toc"); parent = parent.parentNode) { 784 if (parent.matches("li")) parent.classList.add("active"); 785 } 786 } 787 }; 788 789 window.tocScrollFn = utils.throttle(() => { 790 const currentTop = window.scrollY || document.documentElement.scrollTop; 791 findHeadPosition(currentTop); 792 }, 100); 793 window.addEventListener("scroll", tocScrollFn); 794 } 795} 796 797class tabs { 798 static init() { 799 this.clickFnOfTabs(); 800 } 801 802 static clickFnOfTabs() { 803 document 804 .querySelectorAll(".article-container .tab > button") 805 .forEach((item) => { 806 item.addEventListener("click", function () { 807 const $tabItem = this.parentNode; 808 if (!$tabItem.classList.contains("active")) { 809 const $tabContent = $tabItem.parentNode.nextElementSibling; 810 const $siblings = utils.siblings($tabItem, ".active")[0]; 811 $siblings && $siblings.classList.remove("active"); 812 $tabItem.classList.add("active"); 813 const tabId = this.getAttribute("data-href").replace("#", ""); 814 [...$tabContent.children].forEach((item) => { 815 item.classList.toggle("active", item.id === tabId); 816 }); 817 } 818 }); 819 }); 820 } 821 822 static lureAddListener() { 823 if (!GLOBAL_CONFIG.lure) return; 824 const title = document.title; 825 document.addEventListener("visibilitychange", () => { 826 const { lure } = GLOBAL_CONFIG; 827 document.title = 828 document.visibilityState === "hidden" ? lure.jump : lure.back; 829 if (document.visibilityState === "visible") { 830 setTimeout(() => { 831 document.title = title; 832 }, 2000); 833 } 834 }); 835 } 836 837 static expireAddListener() { 838 const { expire } = GLOBAL_CONFIG; 839 if (!expire) return; 840 const list = document.querySelectorAll(".post-meta-date time"); 841 const post_date = list.length 842 ? list[list.length - 1] 843 : document.querySelector(".datetime"); 844 if (!post_date) return; 845 const ex = Math.ceil( 846 (new Date().getTime() - 847 new Date(post_date.getAttribute("datetime")).getTime()) / 848 1000 / 849 60 / 850 60 / 851 24 852 ); 853 if (expire.time > ex) return; 854 const ele = document.createElement("div"); 855 ele.className = "expire"; 856 ele.innerHTML = `<i class="solitude fas fa-circle-exclamation"></i>${ 857 expire.text_prev 858 }${-(expire.time - ex)}${expire.text_next}`; 859 const articleContainer = document.querySelector(".article-container"); 860 articleContainer.insertAdjacentElement( 861 expire.position === "top" ? "afterbegin" : "beforeend", 862 ele 863 ); 864 } 865} 866 867const scrollFnToDo = () => { 868 const { toc } = PAGE_CONFIG; 869 870 if (toc) { 871 const $cardTocLayout = document.getElementById("card-toc"); 872 const $cardToc = $cardTocLayout.querySelector(".toc-content"); 873 const $tocLink = $cardToc.querySelectorAll(".toc-link"); 874 const $tocPercentage = $cardTocLayout.querySelector(".toc-percentage"); 875 const isExpand = $cardToc.classList.contains("is-expand"); 876 877 const tocItemClickFn = (e) => { 878 const target = e.target.closest(".toc-link"); 879 if (!target) return; 880 881 e.preventDefault(); 882 utils.scrollToDest( 883 utils.getEleTop( 884 document.getElementById( 885 decodeURI(target.getAttribute("href")).replace("#", "") 886 ) 887 ), 888 300 889 ); 890 if (window.innerWidth < 900) { 891 $cardTocLayout.classList.remove("open"); 892 } 893 }; 894 utils.addEventListenerPjax($cardToc, "click", tocItemClickFn); 895 } 896}; 897 898const forPostFn = () => { 899 scrollFnToDo(); 900}; 901 902window.refreshFn = () => { 903 const { is_home, is_page, page, is_post, ai_text } = PAGE_CONFIG; 904 const { runtime, lazyload, lightbox, randomlink, covercolor, lure, expire } = 905 GLOBAL_CONFIG; 906 const timeSelector = ".datetime, .webinfo-item time, .post-meta-date time"; 907 document.body.setAttribute("data-type", page); 908 sco.changeTimeFormat(document.querySelectorAll(timeSelector)); 909 runtime && sco.addRuntime(); 910 [ 911 scrollFn, 912 sidebarFn, 913 sco.addPhotoFigcaption, 914 sco.setTimeState, 915 sco.tagPageActive, 916 sco.categoriesBarActive, 917 sco.listenToPageInputPress,
918 sco.addNavBackgroundInit, 919 sco.refreshWaterFall, 920 ].forEach((fn) => fn()); 921 lazyload.enable && utils.lazyloadImg(); 922 lightbox && 923 utils.lightbox( 924 document.querySelectorAll( 925 ".article-container img:not(.flink-avatar,.gallery-group img, .no-lightbox)" 926 ) 927 ); 928 randomlink && randomLinksList(); 929 if (is_post) { 930 if (ai_text) { 931 ai.init(); 932 } 933 } 934 sco.switchComments(); 935 initObserver(); 936 if (is_home) { 937 showTodayCard(); 938 sco.homeTypeit(); 939 } 940 typeof updatePostsBasedOnComments === "function" && 941 updatePostsBasedOnComments(); 942 if (is_post || is_page) { 943 addHighlight(); 944 tabs.init(); 945 } 946 if (is_post && expire) { 947 tabs.expireAddListener(); 948 } 949 if (covercolor.enable) coverColor(); 950 if (PAGE_CONFIG.toc) toc.init(); 951 if (lure) tabs.lureAddListener(); 952 page === "music" && initializeMusicPlayer(); 953 forPostFn(); 954}; 955 956document.addEventListener("DOMContentLoaded", () => { 957 [ 958 addCopyright, 959 window.refreshFn, 960 asideStatus, 961 () => (window.onscroll = percent), 962 sco.initConsoleState, 963 ].forEach((fn) => fn()); 964}); 965 966document.addEventListener("visibilitychange", () => { 967 if (document.hidden) { 968 sco.wasPageHidden = true; 969 } 970}); 971 972window.onkeydown = (e) => { 973 const { code, ctrlKey, shiftKey } = e; 974 if ( 975 code === "F12" || 976 (ctrlKey && shiftKey && (code === "KeyI" || code === "KeyC")) 977 ) { 978 utils.snackbarShow(GLOBAL_CONFIG.lang.f12, false, 3000); 979 } 980 if (code === "Escape") { 981 sco.hideConsole(); 982 } 983}; 984 985document.addEventListener("copy", () => { 986 utils.snackbarShow(GLOBAL_CONFIG.lang.copy.success, false, 3000); 987});
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.