{"version":3,"sources":["jsdelivr-header.js","/npm/hexo-theme-butterfly@5.5.4/source/js/main.js"],"names":[],"mappings":"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","file":"/npm/hexo-theme-butterfly@5.5.4/source/js/main.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/hexo-theme-butterfly@5.5.4/source/js/main.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","document.addEventListener('DOMContentLoaded', () => {\r\n  let headerContentWidth, $nav\r\n  let mobileSidebarOpen = false\r\n\r\n  const adjustMenu = init => {\r\n    const getAllWidth = ele => Array.from(ele).reduce((width, i) => width + i.offsetWidth, 0)\r\n\r\n    if (init) {\r\n      const blogInfoWidth = getAllWidth(document.querySelector('#blog-info > a').children)\r\n      const menusWidth = getAllWidth(document.getElementById('menus').children)\r\n      headerContentWidth = blogInfoWidth + menusWidth\r\n      $nav = document.getElementById('nav')\r\n    }\r\n\r\n    const hideMenuIndex = window.innerWidth <= 768 || headerContentWidth > $nav.offsetWidth - 120\r\n    $nav.classList.toggle('hide-menu', hideMenuIndex)\r\n  }\r\n\r\n  // 初始化header\r\n  const initAdjust = () => {\r\n    adjustMenu(true)\r\n    $nav.classList.add('show')\r\n  }\r\n\r\n  // sidebar menus\r\n  const sidebarFn = {\r\n    open: () => {\r\n      btf.overflowPaddingR.add()\r\n      btf.animateIn(document.getElementById('menu-mask'), 'to_show 0.5s')\r\n      document.getElementById('sidebar-menus').classList.add('open')\r\n      mobileSidebarOpen = true\r\n    },\r\n    close: () => {\r\n      btf.overflowPaddingR.remove()\r\n      btf.animateOut(document.getElementById('menu-mask'), 'to_hide 0.5s')\r\n      document.getElementById('sidebar-menus').classList.remove('open')\r\n      mobileSidebarOpen = false\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 首頁top_img底下的箭頭\r\n   */\r\n  const scrollDownInIndex = () => {\r\n    const handleScrollToDest = () => {\r\n      btf.scrollToDest(document.getElementById('content-inner').offsetTop, 300)\r\n    }\r\n\r\n    const $scrollDownEle = document.getElementById('scroll-down')\r\n    $scrollDownEle && btf.addEventListenerPjax($scrollDownEle, 'click', handleScrollToDest)\r\n  }\r\n\r\n  /**\r\n   * 代碼\r\n   * 只適用於Hexo默認的代碼渲染\r\n   */\r\n  const addHighlightTool = () => {\r\n    const highLight = GLOBAL_CONFIG.highlight\r\n    if (!highLight) return\r\n\r\n    const { highlightCopy, highlightLang, highlightHeightLimit, highlightFullpage, highlightMacStyle, plugin } = highLight\r\n    const isHighlightShrink = GLOBAL_CONFIG_SITE.isHighlightShrink\r\n    const isShowTool = highlightCopy || highlightLang || isHighlightShrink !== undefined || highlightFullpage || highlightMacStyle\r\n    const isNotHighlightJs = plugin !== 'highlight.js'\r\n    const isPrismjs = plugin === 'prismjs'\r\n    const $figureHighlight = isNotHighlightJs\r\n      ? Array.from(document.querySelectorAll('code[class*=\"language-\"]')).map(code => code.parentElement)\r\n      : document.querySelectorAll('figure.highlight')\r\n\r\n    if (!((isShowTool || highlightHeightLimit) && $figureHighlight.length)) return\r\n\r\n    const highlightShrinkClass = isHighlightShrink === true ? 'closed' : ''\r\n    const highlightShrinkEle = isHighlightShrink !== undefined ? '<i class=\"fas fa-angle-down expand\"></i>' : ''\r\n    const highlightCopyEle = highlightCopy ? '<i class=\"fas fa-paste copy-button\"></i>' : ''\r\n    const highlightMacStyleEle = '<div class=\"macStyle\"><div class=\"mac-close\"></div><div class=\"mac-minimize\"></div><div class=\"mac-maximize\"></div></div>'\r\n    const highlightFullpageEle = highlightFullpage ? '<i class=\"fa-solid fa-up-right-and-down-left-from-center fullpage-button\"></i>' : ''\r\n\r\n    const alertInfo = (ele, text) => {\r\n      if (GLOBAL_CONFIG.Snackbar !== undefined) {\r\n        btf.snackbarShow(text)\r\n      } else {\r\n        const newEle = document.createElement('div')\r\n        newEle.className = 'copy-notice'\r\n        newEle.textContent = text\r\n        document.body.appendChild(newEle)\r\n\r\n        const buttonRect = ele.getBoundingClientRect()\r\n        const scrollTop = window.pageYOffset || document.documentElement.scrollTop\r\n        const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft\r\n\r\n        // X-axis boundary check\r\n        const halfWidth = newEle.offsetWidth / 2\r\n        const centerLeft = buttonRect.left + scrollLeft + buttonRect.width / 2\r\n        const finalLeft = Math.max(halfWidth + 10, Math.min(window.innerWidth - halfWidth - 10, centerLeft))\r\n\r\n        // Show tooltip below button if too close to top\r\n        const normalTop = buttonRect.top + scrollTop - 40\r\n        const shouldShowBelow = buttonRect.top < 60 || normalTop < 10\r\n\r\n        const topValue = shouldShowBelow ? buttonRect.top + scrollTop + buttonRect.height + 10 : normalTop\r\n\r\n        newEle.style.cssText = `\r\n      top: ${topValue + 10}px;\r\n      left: ${finalLeft}px;\r\n      transform: translateX(-50%);\r\n      opacity: 0;\r\n      transition: opacity 0.3s ease, top 0.3s ease;\r\n    `\r\n\r\n        requestAnimationFrame(() => {\r\n          newEle.style.opacity = '1'\r\n          newEle.style.top = `${topValue}px`\r\n        })\r\n\r\n        setTimeout(() => {\r\n          newEle.style.opacity = '0'\r\n          newEle.style.top = `${topValue + 10}px`\r\n          setTimeout(() => {\r\n            newEle?.remove()\r\n          }, 300)\r\n        }, 800)\r\n      }\r\n    }\r\n\r\n    const copy = async (text, ctx) => {\r\n      try {\r\n        await navigator.clipboard.writeText(text)\r\n        alertInfo(ctx, GLOBAL_CONFIG.copy.success)\r\n      } catch (err) {\r\n        console.error('Failed to copy: ', err)\r\n        alertInfo(ctx, GLOBAL_CONFIG.copy.noSupport)\r\n      }\r\n    }\r\n\r\n    // click events\r\n    const highlightCopyFn = (ele, clickEle) => {\r\n      const $buttonParent = ele.parentNode\r\n      $buttonParent.classList.add('copy-true')\r\n      const preCodeSelector = isNotHighlightJs ? 'pre code' : 'table .code pre'\r\n      const codeElement = $buttonParent.querySelector(preCodeSelector)\r\n      if (!codeElement) return\r\n      copy(codeElement.innerText, clickEle)\r\n      $buttonParent.classList.remove('copy-true')\r\n    }\r\n\r\n    const highlightShrinkFn = ele => ele.classList.toggle('closed')\r\n\r\n    const codeFullpage = (item, clickEle) => {\r\n      const wrapEle = item.closest('figure.highlight')\r\n      const isFullpage = wrapEle.classList.toggle('code-fullpage')\r\n\r\n      document.body.style.overflow = isFullpage ? 'hidden' : ''\r\n      clickEle.classList.toggle('fa-down-left-and-up-right-to-center', isFullpage)\r\n      clickEle.classList.toggle('fa-up-right-and-down-left-from-center', !isFullpage)\r\n    }\r\n\r\n    const highlightToolsFn = e => {\r\n      const $target = e.target.classList\r\n      const currentElement = e.currentTarget\r\n      if ($target.contains('expand')) highlightShrinkFn(currentElement)\r\n      else if ($target.contains('copy-button')) highlightCopyFn(currentElement, e.target)\r\n      else if ($target.contains('fullpage-button')) codeFullpage(currentElement, e.target)\r\n    }\r\n\r\n    const expandCode = e => e.currentTarget.classList.toggle('expand-done')\r\n\r\n    // 獲取隱藏狀態下元素的真實高度\r\n    const getActualHeight = item => {\r\n      if (item.offsetHeight > 0) return item.offsetHeight\r\n      const hiddenElements = new Map()\r\n\r\n      const fix = () => {\r\n        let current = item\r\n        while (current !== document.body && current != null) {\r\n          if (window.getComputedStyle(current).display === 'none') {\r\n            hiddenElements.set(current, current.getAttribute('style') || '')\r\n          }\r\n          current = current.parentNode\r\n        }\r\n\r\n        const style = 'visibility: hidden !important; display: block !important;'\r\n        hiddenElements.forEach((originalStyle, elem) => {\r\n          elem.setAttribute('style', originalStyle ? originalStyle + ';' + style : style)\r\n        })\r\n      }\r\n\r\n      const restore = () => {\r\n        hiddenElements.forEach((originalStyle, elem) => {\r\n          if (originalStyle === '') elem.removeAttribute('style')\r\n          else elem.setAttribute('style', originalStyle)\r\n        })\r\n      }\r\n\r\n      fix()\r\n      const height = item.offsetHeight\r\n      restore()\r\n      return height\r\n    }\r\n\r\n    const createEle = (lang, item) => {\r\n      const fragment = document.createDocumentFragment()\r\n\r\n      if (isShowTool) {\r\n        const hlTools = document.createElement('div')\r\n        hlTools.className = `highlight-tools ${highlightShrinkClass}`\r\n        hlTools.innerHTML = highlightMacStyleEle + highlightShrinkEle + lang + highlightCopyEle + highlightFullpageEle\r\n        btf.addEventListenerPjax(hlTools, 'click', highlightToolsFn)\r\n        fragment.appendChild(hlTools)\r\n      }\r\n\r\n      if (highlightHeightLimit && getActualHeight(item) > highlightHeightLimit + 30) {\r\n        const ele = document.createElement('div')\r\n        ele.className = 'code-expand-btn'\r\n        ele.innerHTML = '<i class=\"fas fa-angle-double-down\"></i>'\r\n        btf.addEventListenerPjax(ele, 'click', expandCode)\r\n        fragment.appendChild(ele)\r\n      }\r\n\r\n      isNotHighlightJs ? item.parentNode.insertBefore(fragment, item) : item.insertBefore(fragment, item.firstChild)\r\n    }\r\n\r\n    $figureHighlight.forEach(item => {\r\n      let langName = ''\r\n      if (isNotHighlightJs) {\r\n        const newClassName = isPrismjs ? 'prismjs' : 'default'\r\n        btf.wrap(item, 'figure', { class: `highlight ${newClassName}` })\r\n      }\r\n\r\n      if (!highlightLang) {\r\n        createEle('', item)\r\n        return\r\n      }\r\n\r\n      if (isNotHighlightJs) {\r\n        langName = isPrismjs ? item.getAttribute('data-language') || 'Code' : item.querySelector('code').getAttribute('class').replace('language-', '')\r\n      } else {\r\n        langName = item.getAttribute('class').split(' ')[1]\r\n        if (langName === 'plain' || langName === undefined) langName = 'Code'\r\n      }\r\n      createEle(`<div class=\"code-lang\">${langName}</div>`, item)\r\n    })\r\n  }\r\n\r\n  /**\r\n   * PhotoFigcaption\r\n   */\r\n  const addPhotoFigcaption = () => {\r\n    if (!GLOBAL_CONFIG.isPhotoFigcaption) return\r\n    document.querySelectorAll('#article-container img').forEach(item => {\r\n      const altValue = item.title || item.alt\r\n      if (!altValue) return\r\n      const ele = document.createElement('div')\r\n      ele.className = 'img-alt text-center'\r\n      ele.textContent = altValue\r\n      item.insertAdjacentElement('afterend', ele)\r\n    })\r\n  }\r\n\r\n  /**\r\n   * Lightbox\r\n   */\r\n  const runLightbox = () => {\r\n    btf.loadLightbox(document.querySelectorAll('#article-container img:not(.no-lightbox)'))\r\n  }\r\n\r\n  /**\r\n   * justified-gallery 圖庫排版\r\n   */\r\n\r\n  const fetchUrl = async url => {\r\n    try {\r\n      const response = await fetch(url)\r\n      return await response.json()\r\n    } catch (error) {\r\n      console.error('Failed to fetch URL:', error)\r\n      return []\r\n    }\r\n  }\r\n\r\n  const runJustifiedGallery = (container, data, config) => {\r\n    const { isButton, limit, firstLimit, tabs } = config\r\n\r\n    const dataLength = data.length\r\n    const maxGroupKey = Math.ceil((dataLength - firstLimit) / limit + 1)\r\n\r\n    // Gallery configuration\r\n    const igConfig = {\r\n      gap: 5,\r\n      isConstantSize: true,\r\n      sizeRange: [150, 600],\r\n      // useResizeObserver: true,\r\n      // observeChildren: true,\r\n      useTransform: true\r\n      // useRecycle: false\r\n    }\r\n\r\n    const ig = new InfiniteGrid.JustifiedInfiniteGrid(container, igConfig)\r\n    let isLayoutHidden = false\r\n\r\n    // Utility functions\r\n    const sanitizeString = str => (str && str.replace(/\"/g, '&quot;')) || ''\r\n\r\n    const createImageItem = item => {\r\n      const alt = item.alt ? `alt=\"${sanitizeString(item.alt)}\"` : ''\r\n      const title = item.title ? `title=\"${sanitizeString(item.title)}\"` : ''\r\n      return `<div class=\"item\">\r\n        <img src=\"${item.url}\" data-grid-maintained-target=\"true\" ${alt} ${title} />\r\n      </div>`\r\n    }\r\n\r\n    const getItems = (nextGroupKey, count, isFirst = false) => {\r\n      const startIndex = isFirst ? (nextGroupKey - 1) * count : (nextGroupKey - 2) * count + firstLimit\r\n      return data.slice(startIndex, startIndex + count).map(createImageItem)\r\n    }\r\n\r\n    // Load more button\r\n    const addLoadMoreButton = container => {\r\n      const button = document.createElement('button')\r\n      button.innerHTML = `${GLOBAL_CONFIG.infinitegrid.buttonText}<i class=\"fa-solid fa-arrow-down\"></i>`\r\n\r\n      button.addEventListener('click', () => {\r\n        button.remove()\r\n        btf.setLoading.add(container)\r\n        appendItems(ig.getGroups().length + 1, limit)\r\n      }, { once: true })\r\n\r\n      container.insertAdjacentElement('afterend', button)\r\n    }\r\n\r\n    const appendItems = (nextGroupKey, count, isFirst) => {\r\n      ig.append(getItems(nextGroupKey, count, isFirst), nextGroupKey)\r\n    }\r\n\r\n    // Event handlers\r\n    const handleRenderComplete = e => {\r\n      if (tabs) {\r\n        const parentNode = container.parentNode\r\n        if (isLayoutHidden) {\r\n          parentNode.style.visibility = 'visible'\r\n        }\r\n        if (container.offsetHeight === 0) {\r\n          parentNode.style.visibility = 'hidden'\r\n          isLayoutHidden = true\r\n        }\r\n      }\r\n\r\n      const { updated, isResize, mounted } = e\r\n      if (!updated.length || !mounted.length || isResize) return\r\n\r\n      btf.loadLightbox(container.querySelectorAll('img:not(.medium-zoom-image)'))\r\n\r\n      if (ig.getGroups().length === maxGroupKey) {\r\n        btf.setLoading.remove(container)\r\n        !tabs && ig.off('renderComplete', handleRenderComplete)\r\n        return\r\n      }\r\n\r\n      if (isButton) {\r\n        btf.setLoading.remove(container)\r\n        addLoadMoreButton(container)\r\n      }\r\n    }\r\n\r\n    const handleRequestAppend = btf.debounce(e => {\r\n      const nextGroupKey = (+e.groupKey || 0) + 1\r\n\r\n      if (nextGroupKey === 1) appendItems(nextGroupKey, firstLimit, true)\r\n      else appendItems(nextGroupKey, limit)\r\n\r\n      if (nextGroupKey === maxGroupKey) ig.off('requestAppend', handleRequestAppend)\r\n    }, 300)\r\n\r\n    btf.setLoading.add(container)\r\n    ig.on('renderComplete', handleRenderComplete)\r\n\r\n    if (isButton) {\r\n      appendItems(1, firstLimit, true)\r\n    } else {\r\n      ig.on('requestAppend', handleRequestAppend)\r\n      ig.renderItems()\r\n    }\r\n\r\n    btf.addGlobalFn('pjaxSendOnce', () => ig.destroy())\r\n  }\r\n\r\n  const addJustifiedGallery = async (elements, tabs = false) => {\r\n    if (!elements.length) return\r\n\r\n    const initGallery = async () => {\r\n      for (const element of elements) {\r\n        if (btf.isHidden(element) || element.classList.contains('loaded')) continue\r\n\r\n        const config = {\r\n          isButton: element.getAttribute('data-button') === 'true',\r\n          limit: parseInt(element.getAttribute('data-limit'), 10),\r\n          firstLimit: parseInt(element.getAttribute('data-first'), 10),\r\n          tabs\r\n        }\r\n\r\n        const container = element.firstElementChild\r\n        const content = container.textContent\r\n        container.textContent = ''\r\n        element.classList.add('loaded')\r\n\r\n        try {\r\n          const data = element.getAttribute('data-type') === 'url' ? await fetchUrl(content) : JSON.parse(content)\r\n          runJustifiedGallery(container, data, config)\r\n        } catch (error) {\r\n          console.error('Gallery data parsing failed:', error)\r\n        }\r\n      }\r\n    }\r\n\r\n    if (typeof InfiniteGrid === 'function') {\r\n      await initGallery()\r\n    } else {\r\n      await btf.getScript(GLOBAL_CONFIG.infinitegrid.js)\r\n      await initGallery()\r\n    }\r\n  }\r\n\r\n  /**\r\n   * rightside scroll percent\r\n   */\r\n  const rightsideScrollPercent = currentTop => {\r\n    const scrollPercent = btf.getScrollPercent(currentTop, document.body)\r\n    const goUpElement = document.getElementById('go-up')\r\n\r\n    if (scrollPercent < 95) {\r\n      goUpElement.classList.add('show-percent')\r\n      goUpElement.querySelector('.scroll-percent').textContent = scrollPercent\r\n    } else {\r\n      goUpElement.classList.remove('show-percent')\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 滾動處理\r\n   */\r\n  const scrollFn = () => {\r\n    const $rightside = document.getElementById('rightside')\r\n    const innerHeight = window.innerHeight + 56\r\n    let initTop = 0\r\n    const $header = document.getElementById('page-header')\r\n    const isChatBtn = typeof chatBtn !== 'undefined'\r\n    const isShowPercent = GLOBAL_CONFIG.percent.rightside\r\n\r\n    // 檢查文檔高度是否小於視窗高度\r\n    const checkDocumentHeight = () => {\r\n      if (document.body.scrollHeight <= innerHeight) {\r\n        $rightside.classList.add('rightside-show')\r\n        return true\r\n      }\r\n      return false\r\n    }\r\n\r\n    // 如果文檔高度小於視窗高度,直接返回\r\n    if (checkDocumentHeight()) return\r\n\r\n    // find the scroll direction\r\n    const scrollDirection = currentTop => {\r\n      const result = currentTop > initTop // true is down & false is up\r\n      initTop = currentTop\r\n      return result\r\n    }\r\n\r\n    let flag = ''\r\n    const scrollTask = btf.throttle(() => {\r\n      const currentTop = window.scrollY || document.documentElement.scrollTop\r\n      const isDown = scrollDirection(currentTop)\r\n      if (currentTop > 56) {\r\n        if (flag === '') {\r\n          $header.classList.add('nav-fixed')\r\n          $rightside.classList.add('rightside-show')\r\n        }\r\n\r\n        if (isDown) {\r\n          if (flag !== 'down') {\r\n            $header.classList.remove('nav-visible')\r\n            isChatBtn && window.chatBtn.hide()\r\n            flag = 'down'\r\n          }\r\n        } else {\r\n          if (flag !== 'up') {\r\n            $header.classList.add('nav-visible')\r\n            isChatBtn && window.chatBtn.show()\r\n            flag = 'up'\r\n          }\r\n        }\r\n      } else {\r\n        flag = ''\r\n        if (currentTop === 0) {\r\n          $header.classList.remove('nav-fixed', 'nav-visible')\r\n        }\r\n        $rightside.classList.remove('rightside-show')\r\n      }\r\n\r\n      isShowPercent && rightsideScrollPercent(currentTop)\r\n      checkDocumentHeight()\r\n    }, 300)\r\n\r\n    btf.addEventListenerPjax(window, 'scroll', scrollTask, { passive: true })\r\n  }\r\n\r\n  /**\r\n  * toc,anchor\r\n  */\r\n  const scrollFnToDo = () => {\r\n    const isToc = GLOBAL_CONFIG_SITE.isToc\r\n    const isAnchor = GLOBAL_CONFIG.isAnchor\r\n    const $article = document.getElementById('article-container')\r\n\r\n    if (!($article && (isToc || isAnchor))) return\r\n\r\n    let $tocLink, $cardToc, autoScrollToc, $tocPercentage, isExpand\r\n\r\n    if (isToc) {\r\n      const $cardTocLayout = document.getElementById('card-toc')\r\n      $cardToc = $cardTocLayout.querySelector('.toc-content')\r\n      $tocLink = $cardToc.querySelectorAll('.toc-link')\r\n      $tocPercentage = $cardTocLayout.querySelector('.toc-percentage')\r\n      isExpand = $cardToc.classList.contains('is-expand')\r\n\r\n      // toc元素點擊\r\n      const tocItemClickFn = e => {\r\n        const target = e.target.closest('.toc-link')\r\n        if (!target) return\r\n\r\n        e.preventDefault()\r\n        btf.scrollToDest(btf.getEleTop(document.getElementById(decodeURI(target.getAttribute('href')).replace('#', ''))), 300)\r\n        if (window.innerWidth < 900) {\r\n          $cardTocLayout.classList.remove('open')\r\n        }\r\n      }\r\n\r\n      btf.addEventListenerPjax($cardToc, 'click', tocItemClickFn)\r\n\r\n      autoScrollToc = item => {\r\n        const sidebarHeight = $cardToc.clientHeight\r\n        const itemOffsetTop = item.offsetTop\r\n        const itemHeight = item.clientHeight\r\n        const scrollTop = $cardToc.scrollTop\r\n        const offset = itemOffsetTop - scrollTop\r\n        const middlePosition = (sidebarHeight - itemHeight) / 2\r\n\r\n        if (offset !== middlePosition) {\r\n          $cardToc.scrollTop = scrollTop + (offset - middlePosition)\r\n        }\r\n      }\r\n\r\n      // 處理 hexo-blog-encrypt 事件\r\n      $cardToc.style.display = 'block'\r\n    }\r\n\r\n    // find head position & add active class\r\n    const $articleList = $article.querySelectorAll('h1,h2,h3,h4,h5,h6')\r\n    let detectItem = ''\r\n\r\n    // Optimization: Cache header positions\r\n    let headerList = []\r\n    const updateHeaderPositions = () => {\r\n      headerList = Array.from($articleList).map(ele => ({\r\n        ele,\r\n        top: btf.getEleTop(ele),\r\n        id: ele.id\r\n      }))\r\n    }\r\n\r\n    updateHeaderPositions()\r\n    btf.addEventListenerPjax(window, 'resize', btf.throttle(updateHeaderPositions, 200))\r\n\r\n    const findHeadPosition = top => {\r\n      if (top === 0) return false\r\n\r\n      let currentId = ''\r\n      let currentIndex = ''\r\n\r\n      for (let i = 0; i < headerList.length; i++) {\r\n        const item = headerList[i]\r\n        if (top > item.top - 80) {\r\n          currentId = item.id ? '#' + encodeURI(item.id) : ''\r\n          currentIndex = i\r\n        } else {\r\n          break\r\n        }\r\n      }\r\n\r\n      if (detectItem === currentIndex) return\r\n\r\n      if (isAnchor) btf.updateAnchor(currentId)\r\n\r\n      detectItem = currentIndex\r\n\r\n      if (isToc) {\r\n        $cardToc.querySelectorAll('.active').forEach(i => i.classList.remove('active'))\r\n\r\n        if (currentId) {\r\n          const currentActive = $tocLink[currentIndex]\r\n          currentActive.classList.add('active')\r\n\r\n          setTimeout(() => autoScrollToc(currentActive), 0)\r\n\r\n          if (!isExpand) {\r\n            let parent = currentActive.parentNode\r\n            while (!parent.matches('.toc')) {\r\n              if (parent.matches('li')) parent.classList.add('active')\r\n              parent = parent.parentNode\r\n            }\r\n          }\r\n        }\r\n      }\r\n    }\r\n\r\n    // main of scroll\r\n    const tocScrollFn = btf.throttle(() => {\r\n      const currentTop = window.scrollY || document.documentElement.scrollTop\r\n      if (isToc && GLOBAL_CONFIG.percent.toc) {\r\n        $tocPercentage.textContent = btf.getScrollPercent(currentTop, $article)\r\n      }\r\n      findHeadPosition(currentTop)\r\n    }, 100)\r\n\r\n    btf.addEventListenerPjax(window, 'scroll', tocScrollFn, { passive: true })\r\n  }\r\n\r\n  const handleThemeChange = mode => {\r\n    const globalFn = window.globalFn || {}\r\n    const themeChange = globalFn.themeChange || {}\r\n    if (!themeChange) {\r\n      return\r\n    }\r\n\r\n    Object.keys(themeChange).forEach(key => {\r\n      const themeChangeFn = themeChange[key]\r\n      if (['disqus', 'disqusjs'].includes(key)) {\r\n        setTimeout(() => themeChangeFn(mode), 300)\r\n      } else {\r\n        themeChangeFn(mode)\r\n      }\r\n    })\r\n  }\r\n\r\n  /**\r\n   * Rightside\r\n   */\r\n  const rightSideFn = {\r\n    readmode: () => { // read mode\r\n      const $body = document.body\r\n      const newEle = document.createElement('button')\r\n\r\n      const exitReadMode = () => {\r\n        $body.classList.remove('read-mode')\r\n        newEle.remove()\r\n        newEle.removeEventListener('click', exitReadMode)\r\n      }\r\n\r\n      $body.classList.add('read-mode')\r\n      newEle.type = 'button'\r\n      newEle.className = 'exit-readmode'\r\n      newEle.innerHTML = '<i class=\"fas fa-sign-out-alt\"></i>'\r\n      newEle.addEventListener('click', exitReadMode)\r\n      $body.appendChild(newEle)\r\n    },\r\n    darkmode: () => { // switch between light and dark mode\r\n      const willChangeMode = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'\r\n      if (willChangeMode === 'dark') {\r\n        btf.activateDarkMode()\r\n        GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night)\r\n      } else {\r\n        btf.activateLightMode()\r\n        GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.night_to_day)\r\n      }\r\n      btf.saveToLocal.set('theme', willChangeMode, 2)\r\n      handleThemeChange(willChangeMode)\r\n    },\r\n    'rightside-config': item => { // Show or hide rightside-hide-btn\r\n      const hideLayout = item.firstElementChild\r\n      if (hideLayout.classList.contains('show')) {\r\n        hideLayout.classList.add('status')\r\n        setTimeout(() => {\r\n          hideLayout.classList.remove('status')\r\n        }, 300)\r\n      }\r\n\r\n      hideLayout.classList.toggle('show')\r\n    },\r\n    'go-up': () => { // Back to top\r\n      btf.scrollToDest(0, 500)\r\n    },\r\n    'hide-aside-btn': () => { // Hide aside\r\n      const $htmlDom = document.documentElement.classList\r\n      const saveStatus = $htmlDom.contains('hide-aside') ? 'show' : 'hide'\r\n      btf.saveToLocal.set('aside-status', saveStatus, 2)\r\n      $htmlDom.toggle('hide-aside')\r\n    },\r\n    'mobile-toc-button': (p, item) => { // Show mobile toc\r\n      const tocEle = document.getElementById('card-toc')\r\n      tocEle.style.transition = 'transform 0.3s ease-in-out'\r\n\r\n      const tocEleHeight = tocEle.clientHeight\r\n      const btData = item.getBoundingClientRect()\r\n\r\n      const tocEleBottom = window.innerHeight - btData.bottom - 30\r\n      if (tocEleHeight > tocEleBottom) {\r\n        tocEle.style.transformOrigin = `right ${tocEleHeight - tocEleBottom - btData.height / 2}px`\r\n      }\r\n\r\n      tocEle.classList.toggle('open')\r\n      tocEle.addEventListener('transitionend', () => {\r\n        tocEle.style.cssText = ''\r\n      }, { once: true })\r\n    },\r\n    'chat-btn': () => { // Show chat\r\n      window.chatBtnFn()\r\n    },\r\n    translateLink: () => { // switch between traditional and simplified chinese\r\n      window.translateFn.translatePage()\r\n    }\r\n  }\r\n\r\n  document.getElementById('rightside').addEventListener('click', e => {\r\n    const $target = e.target.closest('[id]')\r\n    if ($target && rightSideFn[$target.id]) {\r\n      rightSideFn[$target.id](e.currentTarget, $target)\r\n    }\r\n  })\r\n\r\n  /**\r\n   * menu\r\n   * 側邊欄sub-menu 展開/收縮\r\n   */\r\n  const clickFnOfSubMenu = () => {\r\n    const handleClickOfSubMenu = e => {\r\n      const target = e.target.closest('.site-page.group')\r\n      if (!target) return\r\n      target.classList.toggle('hide')\r\n    }\r\n\r\n    const menusItems = document.querySelector('#sidebar-menus .menus_items')\r\n    menusItems && menusItems.addEventListener('click', handleClickOfSubMenu)\r\n  }\r\n\r\n  /**\r\n   * 手机端目录点击\r\n   */\r\n  const openMobileMenu = () => {\r\n    const toggleMenu = document.getElementById('toggle-menu')\r\n    if (!toggleMenu) return\r\n    btf.addEventListenerPjax(toggleMenu, 'click', () => { sidebarFn.open() })\r\n  }\r\n\r\n  /**\r\n * 複製時加上版權信息\r\n */\r\n  const addCopyright = () => {\r\n    const { limitCount, languages } = GLOBAL_CONFIG.copyright\r\n\r\n    const handleCopy = e => {\r\n      e.preventDefault()\r\n      const copyFont = window.getSelection(0).toString()\r\n      let textFont = copyFont\r\n      if (copyFont.length > limitCount) {\r\n        textFont = `${copyFont}\\n\\n\\n${languages.author}\\n${languages.link}${window.location.href}\\n${languages.source}\\n${languages.info}`\r\n      }\r\n      if (e.clipboardData) {\r\n        return e.clipboardData.setData('text', textFont)\r\n      } else {\r\n        return window.clipboardData.setData('text', textFont)\r\n      }\r\n    }\r\n\r\n    document.body.addEventListener('copy', handleCopy)\r\n  }\r\n\r\n  /**\r\n   * 網頁運行時間\r\n   */\r\n  const addRuntime = () => {\r\n    const $runtimeCount = document.getElementById('runtimeshow')\r\n    if ($runtimeCount) {\r\n      const publishDate = $runtimeCount.getAttribute('data-publishDate')\r\n      $runtimeCount.textContent = `${btf.diffDate(publishDate)} ${GLOBAL_CONFIG.runtime}`\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 最後一次更新時間\r\n   */\r\n  const addLastPushDate = () => {\r\n    const $lastPushDateItem = document.getElementById('last-push-date')\r\n    if ($lastPushDateItem) {\r\n      const lastPushDate = $lastPushDateItem.getAttribute('data-lastPushDate')\r\n      $lastPushDateItem.textContent = btf.diffDate(lastPushDate, true)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * table overflow\r\n   */\r\n  const addTableWrap = () => {\r\n    const $table = document.querySelectorAll('#article-container table')\r\n    if (!$table.length) return\r\n\r\n    $table.forEach(item => {\r\n      if (!item.closest('.highlight')) {\r\n        btf.wrap(item, 'div', { class: 'table-wrap' })\r\n      }\r\n    })\r\n  }\r\n\r\n  /**\r\n   * tag-hide\r\n   */\r\n  const clickFnOfTagHide = () => {\r\n    const hideButtons = document.querySelectorAll('#article-container .hide-button')\r\n    if (!hideButtons.length) return\r\n    hideButtons.forEach(item => item.addEventListener('click', e => {\r\n      const currentTarget = e.currentTarget\r\n      currentTarget.classList.add('open')\r\n      addJustifiedGallery(currentTarget.nextElementSibling.querySelectorAll('.gallery-container'))\r\n    }, { once: true }))\r\n  }\r\n\r\n  const tabsFn = () => {\r\n    const navTabsElements = document.querySelectorAll('#article-container .tabs')\r\n    if (!navTabsElements.length) return\r\n\r\n    const setActiveClass = (elements, activeIndex) => {\r\n      elements.forEach((el, index) => {\r\n        el.classList.toggle('active', index === activeIndex)\r\n      })\r\n    }\r\n\r\n    const handleNavClick = e => {\r\n      const target = e.target.closest('button')\r\n      if (!target || target.classList.contains('active')) return\r\n\r\n      const navItems = [...e.currentTarget.children]\r\n      const tabContents = [...e.currentTarget.nextElementSibling.children]\r\n      const indexOfButton = navItems.indexOf(target)\r\n      setActiveClass(navItems, indexOfButton)\r\n      e.currentTarget.classList.remove('no-default')\r\n      setActiveClass(tabContents, indexOfButton)\r\n      addJustifiedGallery(tabContents[indexOfButton].querySelectorAll('.gallery-container'), true)\r\n    }\r\n\r\n    const handleToTopClick = tabElement => e => {\r\n      if (e.target.closest('button')) {\r\n        btf.scrollToDest(btf.getEleTop(tabElement), 300)\r\n      }\r\n    }\r\n\r\n    navTabsElements.forEach(tabElement => {\r\n      btf.addEventListenerPjax(tabElement.firstElementChild, 'click', handleNavClick)\r\n      btf.addEventListenerPjax(tabElement.lastElementChild, 'click', handleToTopClick(tabElement))\r\n    })\r\n  }\r\n\r\n  const toggleCardCategory = () => {\r\n    const cardCategory = document.querySelector('#aside-cat-list.expandBtn')\r\n    if (!cardCategory) return\r\n\r\n    const handleToggleBtn = e => {\r\n      const target = e.target\r\n      if (target.nodeName === 'I') {\r\n        e.preventDefault()\r\n        target.parentNode.classList.toggle('expand')\r\n      }\r\n    }\r\n    btf.addEventListenerPjax(cardCategory, 'click', handleToggleBtn, true)\r\n  }\r\n\r\n  const addPostOutdateNotice = () => {\r\n    const ele = document.getElementById('post-outdate-notice')\r\n    if (!ele) return\r\n\r\n    const { limitDay, messagePrev, messageNext, postUpdate } = JSON.parse(ele.getAttribute('data'))\r\n    const diffDay = btf.diffDate(postUpdate)\r\n    if (diffDay >= limitDay) {\r\n      ele.textContent = `${messagePrev} ${diffDay} ${messageNext}`\r\n      ele.hidden = false\r\n    }\r\n  }\r\n\r\n  const lazyloadImg = () => {\r\n    window.lazyLoadInstance = new LazyLoad({\r\n      elements_selector: 'img',\r\n      threshold: 0,\r\n      data_src: 'lazy-src'\r\n    })\r\n\r\n    btf.addGlobalFn('pjaxComplete', () => {\r\n      window.lazyLoadInstance.update()\r\n    }, 'lazyload')\r\n  }\r\n\r\n  const relativeDate = selector => {\r\n    selector.forEach(item => {\r\n      item.textContent = btf.diffDate(item.getAttribute('datetime'), true)\r\n      item.style.display = 'inline'\r\n    })\r\n  }\r\n\r\n  const justifiedIndexPostUI = () => {\r\n    const recentPostsElement = document.getElementById('recent-posts')\r\n    if (!(recentPostsElement && recentPostsElement.classList.contains('masonry'))) return\r\n\r\n    const init = () => {\r\n      const masonryItem = new InfiniteGrid.MasonryInfiniteGrid('.recent-post-items', {\r\n        gap: { horizontal: 10, vertical: 20 },\r\n        useTransform: true,\r\n        useResizeObserver: true\r\n      })\r\n      masonryItem.renderItems()\r\n      btf.addGlobalFn('pjaxCompleteOnce', () => { masonryItem.destroy() }, 'removeJustifiedIndexPostUI')\r\n    }\r\n\r\n    typeof InfiniteGrid === 'function' ? init() : btf.getScript(`${GLOBAL_CONFIG.infinitegrid.js}`).then(init)\r\n  }\r\n\r\n  const unRefreshFn = () => {\r\n    window.addEventListener('resize', () => {\r\n      adjustMenu(false)\r\n      mobileSidebarOpen && btf.isHidden(document.getElementById('toggle-menu')) && sidebarFn.close()\r\n    })\r\n\r\n    const menuMask = document.getElementById('menu-mask')\r\n    menuMask && menuMask.addEventListener('click', () => { sidebarFn.close() })\r\n\r\n    clickFnOfSubMenu()\r\n    GLOBAL_CONFIG.islazyloadPlugin && lazyloadImg()\r\n    GLOBAL_CONFIG.copyright !== undefined && addCopyright()\r\n\r\n    if (GLOBAL_CONFIG.autoDarkmode) {\r\n      window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {\r\n        if (btf.saveToLocal.get('theme') !== undefined) return\r\n        e.matches ? handleThemeChange('dark') : handleThemeChange('light')\r\n      })\r\n    }\r\n  }\r\n\r\n  const forPostFn = () => {\r\n    addHighlightTool()\r\n    addPhotoFigcaption()\r\n    addJustifiedGallery(document.querySelectorAll('#article-container .gallery-container'))\r\n    runLightbox()\r\n    scrollFnToDo()\r\n    addTableWrap()\r\n    clickFnOfTagHide()\r\n    tabsFn()\r\n  }\r\n\r\n  const refreshFn = () => {\r\n    initAdjust()\r\n    justifiedIndexPostUI()\r\n\r\n    if (GLOBAL_CONFIG_SITE.pageType === 'post') {\r\n      addPostOutdateNotice()\r\n      GLOBAL_CONFIG.relativeDate.post && relativeDate(document.querySelectorAll('#post-meta time'))\r\n    } else {\r\n      GLOBAL_CONFIG.relativeDate.homepage && relativeDate(document.querySelectorAll('#recent-posts time'))\r\n      GLOBAL_CONFIG.runtime && addRuntime()\r\n      addLastPushDate()\r\n      toggleCardCategory()\r\n    }\r\n\r\n    GLOBAL_CONFIG_SITE.pageType === 'home' && scrollDownInIndex()\r\n    scrollFn()\r\n\r\n    forPostFn()\r\n    GLOBAL_CONFIG_SITE.pageType !== 'shuoshuo' && btf.switchComments(document)\r\n    openMobileMenu()\r\n  }\r\n\r\n  btf.addGlobalFn('pjaxComplete', refreshFn, 'refreshFn')\r\n  refreshFn()\r\n  unRefreshFn()\r\n\r\n  // 處理 hexo-blog-encrypt 事件\r\n  window.addEventListener('hexo-blog-decrypt', e => {\r\n    forPostFn()\r\n    window.translateFn.translateInitialization()\r\n    Object.values(window.globalFn.encrypt).forEach(fn => {\r\n      fn()\r\n    })\r\n  })\r\n})\r\n"]}