diff options
author | Dillon <dillonzq@outlook.com> | 2020-02-16 19:41:08 +0300 |
---|---|---|
committer | Dillon <dillonzq@outlook.com> | 2020-02-16 19:41:08 +0300 |
commit | d87af711761d0ea8b2fc173407b45299e3314138 (patch) | |
tree | 30f42db3c1c22a36f8cd77ed6984e69d1afb80b8 /src | |
parent | 34cc26b94af4ccbc217c130f7f37a2d13ba292e1 (diff) |
chore(hook): add babel pre-commit hook
Diffstat (limited to 'src')
-rw-r--r-- | src/js/theme.js | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/src/js/theme.js b/src/js/theme.js new file mode 100644 index 0000000..7629260 --- /dev/null +++ b/src/js/theme.js @@ -0,0 +1,320 @@ +(() => { + 'use strict'; + + class Util { + forEach(elements, handler) { + elements = elements || []; + for (let i = 0; i < elements.length; i++) { + handler(elements[i]); + } + } + + getScrollTop() { + return (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop; + } + } + + class Theme { + constructor() { + this.util = new Util(); + this.scrollTop = 0; + this.scrollEvents = []; + } + + initMobileMenu() { + document.getElementById('menu-toggle').onclick = () => { + document.getElementById('menu-toggle').classList.toggle('active'); + document.getElementById('menu-mobile').classList.toggle('active'); + }; + } + + initSwitchTheme() { + this.util.forEach(document.getElementsByClassName('theme-switch'), (button) => { + button.onclick = () => { + document.body.classList.toggle('dark-theme'); + window.isDark = !window.isDark; + window.localStorage && window.localStorage.setItem('theme', window.isDark ? 'dark' : 'light'); + this.initEcharts(); + }; + }); + } + + initHighlight() { + this.util.forEach(document.querySelectorAll('.highlight > .chroma'), (block) => { + const codes = block.querySelectorAll('pre.chroma > code'); + const code = codes[codes.length - 1]; + const lang = code ? code.className.toLowerCase() : ''; + block.className += ' ' + lang; + }); + this.util.forEach(document.querySelectorAll('.highlight > pre.chroma'), (block) => { + const chroma = document.createElement('div'); + chroma.className = block.className; + const table = document.createElement('table'); + chroma.appendChild(table); + const tbody = document.createElement('tbody'); + table.appendChild(tbody); + const tr = document.createElement('tr'); + tbody.appendChild(tr); + const td = document.createElement('td'); + tr.appendChild(td); + block.parentElement.replaceChild(chroma, block); + td.appendChild(block); + }); + } + + initTable() { + this.util.forEach(document.querySelectorAll('.content table'), (table) => { + const wrapper = document.createElement('div'); + wrapper.className = 'table-wrapper'; + table.parentElement.replaceChild(wrapper, table); + wrapper.appendChild(table); + }); + } + + initHeaderLink() { + for (let num = 1; num <= 6; num++) { + this.util.forEach(document.querySelectorAll('.content > h' + num), (header) => { + header.classList.add('headerLink'); + header.innerHTML = `<a href="#${header.id}"></a>${header.innerHTML}`; + }); + } + } + + _refactorToc(toc) { + this.util.forEach(toc.querySelectorAll('a:first-child'), (link) => { + link.classList.add('toc-link'); + }); + + // when headings do not start with `h1` + const oldTocList = toc.children[0]; + let newTocList = oldTocList; + let temp; + while (newTocList.children.length === 1 + && (temp = newTocList.children[0].children[0]).tagName === 'UL') { + newTocList = temp; + } + if (newTocList !== oldTocList) toc.replaceChild(newTocList, oldTocList); + } + + _initTocState(tocContainer) { + if (window.getComputedStyle(tocContainer, null).display !== 'none') { + const fixed = window.desktopHeaderMode !== 'normal'; + const fixedHeight = document.getElementById('header-desktop').getBoundingClientRect().height; + const TOP_SPACING = 20 + (fixed ? fixedHeight : 0); + const minTop = tocContainer.offsetTop; + const minScrollTop = minTop - TOP_SPACING + (fixed ? 0 : fixedHeight); + const footerTop = document.getElementById('post-footer').offsetTop; + const toclinks = tocContainer.getElementsByClassName('toc-link'); + const headerLinks = document.getElementsByClassName('headerLink') || []; + const tocLinkLis = tocContainer.querySelectorAll('.post-toc-content li'); + const INDEX_SPACING = 5 + (fixed ? fixedHeight : 0); + + const changeTocState = () => { + const scrollTop = this.util.getScrollTop(); + const maxTop = footerTop - tocContainer.getBoundingClientRect().height; + const maxScrollTop = maxTop - TOP_SPACING + (fixed ? 0 : fixedHeight); + if (scrollTop < minScrollTop) { + tocContainer.style.position = 'absolute'; + tocContainer.style.top = `${minTop}px`; + } else if (scrollTop > maxScrollTop) { + tocContainer.style.position = 'absolute'; + tocContainer.style.top = `${maxTop}px`; + } else { + tocContainer.style.position = 'fixed'; + tocContainer.style.top = `${TOP_SPACING}px`; + } + + this.util.forEach(toclinks, (link) => { link.classList.remove('active'); }); + this.util.forEach(tocLinkLis, (link) => { link.classList.remove('has-active'); }); + let activeTocIndex = headerLinks.length - 1; + for (let i = 0; i < headerLinks.length - 1; i++) { + const thisTop = headerLinks[i].getBoundingClientRect().top; + const nextTop = headerLinks[i + 1].getBoundingClientRect().top; + if ((i == 0 && thisTop > INDEX_SPACING) + || (thisTop <= INDEX_SPACING && nextTop > INDEX_SPACING)) { + activeTocIndex = i; + break; + } + } + if (activeTocIndex !== -1) { + toclinks[activeTocIndex].classList.add('active'); + let parent = toclinks[activeTocIndex].parentElement; + while (parent.tagName !== 'NAV') { + parent.classList.add('has-active'); + parent = parent.parentElement.parentElement; + } + } + }; + changeTocState(); + + if (!this._initTocOnce) { + this.scrollEvents.push(changeTocState); + this._initTocOnce = true; + } + } + } + + initToc() { + const tocContainer = document.getElementById('post-toc'); + if (tocContainer !== null) { + const toc = document.getElementById('TableOfContents'); + if (toc === null) { + tocContainer.parentElement.removeChild(tocContainer); + } else { + this._refactorToc(toc); + this._initTocState(tocContainer); + window.addEventListener('resize', () => { + window.setTimeout(() => { + this._initTocState(tocContainer); + }, 0); + }, false); + } + } + } + + initMermaid() { + if (window.mermaidMap) { + mermaid.initialize({startOnLoad: false, theme: null}); + Object.keys(mermaidMap).forEach((id) => { + const element = document.getElementById(id); + mermaid.mermaidAPI.render("d" + id, mermaidMap[id], (svgCode) => { + element.innerHTML = svgCode; + const svg = element.firstChild; + svg.style.width = "100%" + }, element); + }); + } + } + + initEcharts() { + if (window.echartsMap) { + for (let i = 0; i < echartsArr.length; i++) { + echartsArr[i].dispose(); + } + echartsArr = []; + Object.keys(echartsMap).forEach((id) => { + let myChart = echarts.init(document.getElementById(id), window.isDark ? 'dark' : 'macarons', {renderer: 'svg'}); + myChart.setOption(echartsMap[id]); + echartsArr.push(myChart); + }); + window.addEventListener("resize", function () { + this.setTimeout(() => { + for (let i = 0; i < echartsArr.length; i++) { + echartsArr[i].resize(); + } + }, 0); + }, false); + } + } + + initTypeit() { + if (window.typeitArr) { + for (let i = 0; i < typeitArr.length; i++) { + const group = typeitArr[i]; + (function typeone(i) { + const content = document.getElementById(`r${group[i]}`).innerHTML; + if (i === group.length - 1) { + new TypeIt(`#${group[i]}`, { + strings: content, + }).go(); + return; + } + let instance = new TypeIt(`#${group[i]}`, { + strings: content, + afterComplete: () => { + instance.destroy(); + typeone(i + 1); + }, + }).go(); + })(0); + } + } + } + + initScroll() { + for (let i = 0; i < this.scrollEvents.length; i++) { + document.addEventListener('scroll', this.scrollEvents[i], false); + } + const initSmoothScroll = () => { + const isMobile = window.matchMedia('only screen and (max-width: 560px)').matches; + if ((!isMobile && window.desktopHeaderMode === 'normal') + || (isMobile && window.mobileHeaderMode === 'normal')) { + new SmoothScroll('[href^="#"]', {speed: 300, speedAsDuration: true}); + } else { + new SmoothScroll('[href^="#"]', {speed: 300, speedAsDuration: true, header: '#header-desktop'}); + } + }; + initSmoothScroll(); + window.addEventListener('resize', () => { + window.setTimeout(() => { + initSmoothScroll(); + }, 0); + }, false); + const headers = []; + if (window.desktopHeaderMode === 'auto') headers.push(document.getElementById('header-desktop')); + if (window.mobileHeaderMode === 'auto') headers.push(document.getElementById('header-mobile')); + this.util.forEach(headers, (header) => { + header.classList.add('animated'); + header.classList.add('faster'); + }); + const toTopButton = document.getElementById('dynamic-to-top'); + document.addEventListener('scroll', () => { + const scrollTop = this.util.getScrollTop(); + this.util.forEach(headers, (header) => { + if (this.scrollTop < scrollTop) { + if (!header.classList.contains('fadeOutUp')) { + header.classList.remove('fadeInDown'); + header.classList.add('fadeOutUp'); + } + } else { + if (!header.classList.contains('fadeInDown')) { + header.classList.remove('fadeOutUp'); + header.classList.add('fadeInDown'); + } + } + if (scrollTop > 600) { + if (this.scrollTop < scrollTop) { + if (!toTopButton.classList.contains('fadeOut')) { + toTopButton.classList.remove('fadeIn'); + toTopButton.classList.add('fadeOut'); + } + } else { + toTopButton.style.display = 'block'; + if (!toTopButton.classList.contains('fadeIn')) { + toTopButton.classList.remove('fadeOut'); + toTopButton.classList.add('fadeIn'); + } + } + } else { + toTopButton.style.display = 'none'; + } + }); + this.scrollTop = scrollTop; + }, false); + } + + init() { + this.initMobileMenu(); + this.initSwitchTheme(); + this.initHighlight(); + this.initTable(); + this.initHeaderLink(); + this.initMermaid(); + this.initEcharts(); + this.initTypeit(); + this.initToc(); + this.initScroll(); + } + } + + const themeInit = () => { + const theme = new Theme(); + theme.init(); + }; + + if (document.readyState !== 'loading') { + themeInit(); + } else { + document.addEventListener('DOMContentLoaded', themeInit, false); + } +})(); |