diff options
Diffstat (limited to 'themes/CodeIT/src')
-rw-r--r-- | themes/CodeIT/src/js/theme.js | 979 | ||||
-rw-r--r-- | themes/CodeIT/src/lib/lunr.segmentit.js | 12 |
2 files changed, 991 insertions, 0 deletions
diff --git a/themes/CodeIT/src/js/theme.js b/themes/CodeIT/src/js/theme.js new file mode 100644 index 0000000..6421e18 --- /dev/null +++ b/themes/CodeIT/src/js/theme.js @@ -0,0 +1,979 @@ +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 + ); + } + + isMobile() { + return window.matchMedia("only screen and (max-width: 680px)").matches; + } + + isTocStatic() { + return window.matchMedia("only screen and (max-width: 960px)").matches; + } + + animateCSS(element, animation, reserved, callback) { + if (!Array.isArray(animation)) animation = [animation]; + element.classList.add("animated", ...animation); + const handler = () => { + element.classList.remove("animated", ...animation); + element.removeEventListener("animationend", handler); + if (typeof callback === "function") callback(); + }; + if (!reserved) element.addEventListener("animationend", handler, false); + } +} + +class Theme { + constructor() { + this.config = window.config; + this.data = this.config.data; + this.isDark = document.body.getAttribute("theme") === "dark"; + this.util = new Util(); + this.newScrollTop = this.util.getScrollTop(); + this.oldScrollTop = this.newScrollTop; + this.scrollEventSet = new Set(); + this.resizeEventSet = new Set(); + this.switchThemeEventSet = new Set(); + this.clickMaskEventSet = new Set(); + if (window.objectFitImages) objectFitImages(); + } + + initSVGIcon() { + this.util.forEach(document.querySelectorAll("[data-svg-src]"), ($icon) => { + fetch($icon.getAttribute("data-svg-src")) + .then((response) => response.text()) + .then((svg) => { + const $temp = document.createElement("div"); + $temp.insertAdjacentHTML("afterbegin", svg); + const $svg = $temp.firstChild; + $svg.setAttribute("data-svg-src", $icon.getAttribute("data-svg-src")); + $svg.classList.add("icon"); + const $titleElements = $svg.getElementsByTagName("title"); + if ($titleElements.length) $svg.removeChild($titleElements[0]); + $icon.parentElement.replaceChild($svg, $icon); + }) + .catch((err) => { + console.error(err); + }); + }); + } + + initTwemoji() { + if (this.config.twemoji) twemoji.parse(document.body); + } + + initMenuMobile() { + const $menuToggleMobile = document.getElementById("menu-toggle-mobile"); + const $menuMobile = document.getElementById("menu-mobile"); + $menuToggleMobile.addEventListener( + "click", + () => { + document.body.classList.toggle("blur"); + $menuToggleMobile.classList.toggle("active"); + $menuMobile.classList.toggle("active"); + }, + false + ); + this._menuMobileOnClickMask = + this._menuMobileOnClickMask || + (() => { + $menuToggleMobile.classList.remove("active"); + $menuMobile.classList.remove("active"); + }); + this.clickMaskEventSet.add(this._menuMobileOnClickMask); + } + + initSwitchTheme() { + this.util.forEach( + document.getElementsByClassName("theme-switch"), + ($themeSwitch) => { + $themeSwitch.addEventListener( + "click", + () => { + if (document.body.getAttribute("theme") === "dark") + document.body.setAttribute("theme", "light"); + else document.body.setAttribute("theme", "dark"); + this.isDark = !this.isDark; + window.localStorage && + localStorage.setItem("theme", this.isDark ? "dark" : "light"); + for (let event of this.switchThemeEventSet) event(); + }, + false + ); + } + ); + } + + initSearch() { + const searchConfig = this.config.search; + const isMobile = this.util.isMobile(); + if ( + !searchConfig || + (isMobile && this._searchMobileOnce) || + (!isMobile && this._searchDesktopOnce) + ) + return; + + const maxResultLength = searchConfig.maxResultLength + ? searchConfig.maxResultLength + : 10; + const snippetLength = searchConfig.snippetLength + ? searchConfig.snippetLength + : 50; + const highlightTag = searchConfig.highlightTag + ? searchConfig.highlightTag + : "em"; + + const suffix = isMobile ? "mobile" : "desktop"; + const $header = document.getElementById(`header-${suffix}`); + const $searchInput = document.getElementById(`search-input-${suffix}`); + const $searchToggle = document.getElementById(`search-toggle-${suffix}`); + const $searchLoading = document.getElementById(`search-loading-${suffix}`); + const $searchClear = document.getElementById(`search-clear-${suffix}`); + if (isMobile) { + this._searchMobileOnce = true; + $searchInput.addEventListener( + "focus", + () => { + document.body.classList.add("blur"); + $header.classList.add("open"); + }, + false + ); + document.getElementById("search-cancel-mobile").addEventListener( + "click", + () => { + $header.classList.remove("open"); + document.body.classList.remove("blur"); + document + .getElementById("menu-toggle-mobile") + .classList.remove("active"); + document.getElementById("menu-mobile").classList.remove("active"); + $searchLoading.style.display = "none"; + $searchClear.style.display = "none"; + this._searchMobile && this._searchMobile.autocomplete.setVal(""); + }, + false + ); + $searchClear.addEventListener( + "click", + () => { + $searchClear.style.display = "none"; + this._searchMobile && this._searchMobile.autocomplete.setVal(""); + }, + false + ); + this._searchMobileOnClickMask = + this._searchMobileOnClickMask || + (() => { + $header.classList.remove("open"); + $searchLoading.style.display = "none"; + $searchClear.style.display = "none"; + this._searchMobile && this._searchMobile.autocomplete.setVal(""); + }); + this.clickMaskEventSet.add(this._searchMobileOnClickMask); + } else { + this._searchDesktopOnce = true; + $searchToggle.addEventListener( + "click", + () => { + document.body.classList.add("blur"); + $header.classList.add("open"); + $searchInput.focus(); + }, + false + ); + $searchClear.addEventListener( + "click", + () => { + $searchClear.style.display = "none"; + this._searchDesktop && this._searchDesktop.autocomplete.setVal(""); + }, + false + ); + this._searchDesktopOnClickMask = + this._searchDesktopOnClickMask || + (() => { + $header.classList.remove("open"); + $searchLoading.style.display = "none"; + $searchClear.style.display = "none"; + this._searchDesktop && this._searchDesktop.autocomplete.setVal(""); + }); + this.clickMaskEventSet.add(this._searchDesktopOnClickMask); + } + $searchInput.addEventListener( + "input", + () => { + if ($searchInput.value === "") $searchClear.style.display = "none"; + else $searchClear.style.display = "inline"; + }, + false + ); + + const initAutosearch = () => { + const autosearch = autocomplete( + `#search-input-${suffix}`, + { + hint: false, + autoselect: true, + dropdownMenuContainer: `#search-dropdown-${suffix}`, + clearOnSelected: true, + cssClasses: { noPrefix: true }, + debug: true, + }, + { + name: "search", + source: (query, callback) => { + $searchLoading.style.display = "inline"; + $searchClear.style.display = "none"; + const finish = (results) => { + $searchLoading.style.display = "none"; + $searchClear.style.display = "inline"; + callback(results); + }; + if (searchConfig.type === "lunr") { + const search = () => { + if (lunr.queryHandler) query = lunr.queryHandler(query); + const results = {}; + this._index + .search(query) + .forEach(({ ref, matchData: { metadata } }) => { + const matchData = this._indexData[ref]; + let { uri, title, content: context } = matchData; + if (results[uri]) return; + let position = 0; + Object.values(metadata).forEach(({ content }) => { + if (content) { + const matchPosition = content.position[0][0]; + if (matchPosition < position || position === 0) + position = matchPosition; + } + }); + position -= snippetLength / 5; + if (position > 0) { + position += + context.substr(position, 20).lastIndexOf(" ") + 1; + context = "..." + context.substr(position, snippetLength); + } else { + context = context.substr(0, snippetLength); + } + Object.keys(metadata).forEach((key) => { + title = title.replace( + new RegExp(`(${key})`, "gi"), + `<${highlightTag}>$1</${highlightTag}>` + ); + context = context.replace( + new RegExp(`(${key})`, "gi"), + `<${highlightTag}>$1</${highlightTag}>` + ); + }); + results[uri] = { + uri: uri, + title: title, + date: matchData.date, + context: context, + }; + }); + return Object.values(results).slice(0, maxResultLength); + }; + if (!this._index) { + fetch(searchConfig.lunrIndexURL) + .then((response) => response.json()) + .then((data) => { + const indexData = {}; + this._index = lunr(function () { + if (searchConfig.lunrLanguageCode) + this.use(lunr[searchConfig.lunrLanguageCode]); + this.ref("objectID"); + this.field("title", { boost: 50 }); + this.field("tags", { boost: 20 }); + this.field("categories", { boost: 20 }); + this.field("content", { boost: 10 }); + this.metadataWhitelist = ["position"]; + data.forEach((record) => { + indexData[record.objectID] = record; + this.add(record); + }); + }); + this._indexData = indexData; + finish(search()); + }) + .catch((err) => { + console.error(err); + finish([]); + }); + } else finish(search()); + } else if (searchConfig.type === "algolia") { + this._algoliaIndex = + this._algoliaIndex || + algoliasearch( + searchConfig.algoliaAppID, + searchConfig.algoliaSearchKey + ).initIndex(searchConfig.algoliaIndex); + this._algoliaIndex + .search(query, { + offset: 0, + length: maxResultLength * 8, + attributesToHighlight: ["title"], + attributesToSnippet: [`content:${snippetLength}`], + highlightPreTag: `<${highlightTag}>`, + highlightPostTag: `</${highlightTag}>`, + }) + .then(({ hits }) => { + const results = {}; + hits.forEach( + ({ + uri, + date, + _highlightResult: { title }, + _snippetResult: { content }, + }) => { + if ( + results[uri] && + results[uri].context.length > content.value + ) + return; + results[uri] = { + uri: uri, + title: title.value, + date: date, + context: content.value, + }; + } + ); + finish(Object.values(results).slice(0, maxResultLength)); + }) + .catch((err) => { + console.error(err); + finish([]); + }); + } + }, + templates: { + suggestion: ({ title, date, context }) => + `<div><span class="suggestion-title">${title}</span><span class="suggestion-date">${date}</span></div><div class="suggestion-context">${context}</div>`, + empty: ({ query }) => + `<div class="search-empty">${searchConfig.noResultsFound}: <span class="search-query">"${query}"</span></div>`, + footer: ({}) => { + const { searchType, icon, href } = + searchConfig.type === "algolia" + ? { + searchType: "algolia", + icon: '<i class="fab fa-algolia fa-fw"></i>', + href: "https://www.algolia.com/", + } + : { + searchType: "Lunr.js", + icon: "", + href: "https://lunrjs.com/", + }; + return `<div class="search-footer">Search by <a href="${href}" rel="noopener noreferrer" target="_blank">${icon} ${searchType}</a></div>`; + }, + }, + } + ); + autosearch.on( + "autocomplete:selected", + (_event, suggestion, _dataset, _context) => { + window.location.assign(suggestion.uri); + } + ); + if (isMobile) this._searchMobile = autosearch; + else this._searchDesktop = autosearch; + }; + if ( + searchConfig.lunrSegmentitURL && + !document.getElementById("lunr-segmentit") + ) { + const script = document.createElement("script"); + script.id = "lunr-segmentit"; + script.type = "text/javascript"; + script.src = searchConfig.lunrSegmentitURL; + script.async = true; + if (script.readyState) { + script.onreadystatechange = () => { + if ( + script.readyState == "loaded" || + script.readyState == "complete" + ) { + script.onreadystatechange = null; + initAutosearch(); + } + }; + } else { + script.onload = () => { + initAutosearch(); + }; + } + document.body.appendChild(script); + } else initAutosearch(); + } + + initDetails() { + this.util.forEach( + document.getElementsByClassName("details"), + ($details) => { + const $summary = $details.getElementsByClassName("details-summary")[0]; + $summary.addEventListener( + "click", + () => { + $details.classList.toggle("open"); + }, + false + ); + } + ); + } + + initLightGallery() { + if (this.config.lightGallery) + lightGallery( + document.getElementById("content"), + this.config.lightGallery + ); + } + + initHighlight() { + this.util.forEach( + document.querySelectorAll(".highlight > pre.chroma"), + ($preChroma) => { + const $chroma = document.createElement("div"); + $chroma.className = $preChroma.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); + $preChroma.parentElement.replaceChild($chroma, $preChroma); + $td.appendChild($preChroma); + } + ); + this.util.forEach( + document.querySelectorAll(".highlight > .chroma"), + ($chroma) => { + const $codeElements = $chroma.querySelectorAll("pre.chroma > code"); + if ($codeElements.length) { + const $code = $codeElements[$codeElements.length - 1]; + const $header = document.createElement("div"); + $header.className = "code-header " + $code.className.toLowerCase(); + const $title = document.createElement("span"); + $title.classList.add("code-title"); + $title.insertAdjacentHTML( + "afterbegin", + '<i class="arrow fas fa-chevron-right fa-fw"></i>' + ); + $title.addEventListener( + "click", + () => { + $chroma.classList.toggle("open"); + }, + false + ); + $header.appendChild($title); + const $ellipses = document.createElement("span"); + $ellipses.insertAdjacentHTML( + "afterbegin", + '<i class="fas fa-ellipsis-h fa-fw"></i>' + ); + $ellipses.classList.add("ellipses"); + $ellipses.addEventListener( + "click", + () => { + $chroma.classList.add("open"); + }, + false + ); + $header.appendChild($ellipses); + const $copy = document.createElement("span"); + $copy.insertAdjacentHTML( + "afterbegin", + '<i class="far fa-copy fa-fw"></i>' + ); + $copy.classList.add("copy"); + const code = $code.innerText; + if ( + this.config.code.maxShownLines < 0 || + code.split("\n").length < this.config.code.maxShownLines + 2 + ) + $chroma.classList.add("open"); + if (this.config.code.copyTitle) { + $copy.setAttribute("data-clipboard-text", code); + $copy.title = this.config.code.copyTitle; + const clipboard = new ClipboardJS($copy); + clipboard.on("success", (_e) => { + this.util.animateCSS($code, "flash"); + }); + $header.appendChild($copy); + } + $chroma.insertBefore($header, $chroma.firstChild); + } + } + ); + } + + 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(".single .content > h" + num), + ($header) => { + $header.classList.add("headerLink"); + $header.insertAdjacentHTML( + "afterbegin", + `<a href="#${$header.id}" class="header-mark"></a>` + ); + } + ); + } + } + + initToc() { + const $tocCore = document.getElementById("TableOfContents"); + if ($tocCore === null) return; + if ( + document.getElementById("toc-static").getAttribute("kept") || + this.util.isTocStatic() + ) { + const $tocContentStatic = document.getElementById("toc-content-static"); + if ($tocCore.parentElement !== $tocContentStatic) { + $tocCore.parentElement.removeChild($tocCore); + $tocContentStatic.appendChild($tocCore); + } + if (this._tocOnScroll) this.scrollEventSet.delete(this._tocOnScroll); + } else { + const $tocContentAuto = document.getElementById("toc-content-auto"); + if ($tocCore.parentElement !== $tocContentAuto) { + $tocCore.parentElement.removeChild($tocCore); + $tocContentAuto.appendChild($tocCore); + } + const $toc = document.getElementById("toc-auto"); + const $page = document.getElementsByClassName("page")[0]; + const rect = $page.getBoundingClientRect(); + $toc.style.left = `${rect.left + rect.width + 20}px`; + $toc.style.maxWidth = `${$page.getBoundingClientRect().left - 20}px`; + $toc.style.visibility = "visible"; + const $tocLinkElements = $tocCore.querySelectorAll("a:first-child"); + const $tocLiElements = $tocCore.getElementsByTagName("li"); + const $headerLinkElements = document.getElementsByClassName("headerLink"); + const headerIsFixed = + document.body.getAttribute("header-desktop") !== "normal"; + const headerHeight = document.getElementById("header-desktop") + .offsetHeight; + const TOP_SPACING = 20 + (headerIsFixed ? headerHeight : 0); + const minTocTop = $toc.offsetTop; + const minScrollTop = + minTocTop - TOP_SPACING + (headerIsFixed ? 0 : headerHeight); + this._tocOnScroll = + this._tocOnScroll || + (() => { + const footerTop = document.getElementById("post-footer").offsetTop; + const maxTocTop = footerTop - $toc.getBoundingClientRect().height; + const maxScrollTop = + maxTocTop - TOP_SPACING + (headerIsFixed ? 0 : headerHeight); + if (this.newScrollTop < minScrollTop) { + $toc.style.position = "absolute"; + $toc.style.top = `${minTocTop}px`; + } else if (this.newScrollTop > maxScrollTop) { + $toc.style.position = "absolute"; + $toc.style.top = `${maxTocTop}px`; + } else { + $toc.style.position = "fixed"; + $toc.style.top = `${TOP_SPACING}px`; + } + + this.util.forEach($tocLinkElements, ($tocLink) => { + $tocLink.classList.remove("active"); + }); + this.util.forEach($tocLiElements, ($tocLi) => { + $tocLi.classList.remove("has-active"); + }); + const INDEX_SPACING = 20 + (headerIsFixed ? headerHeight : 0); + let activeTocIndex = $headerLinkElements.length - 1; + for (let i = 0; i < $headerLinkElements.length - 1; i++) { + const thisTop = $headerLinkElements[i].getBoundingClientRect().top; + const nextTop = $headerLinkElements[i + 1].getBoundingClientRect() + .top; + if ( + (i == 0 && thisTop > INDEX_SPACING) || + (thisTop <= INDEX_SPACING && nextTop > INDEX_SPACING) + ) { + activeTocIndex = i; + break; + } + } + if (activeTocIndex !== -1) { + $tocLinkElements[activeTocIndex].classList.add("active"); + let $parent = $tocLinkElements[activeTocIndex].parentElement; + while ($parent !== $tocCore) { + $parent.classList.add("has-active"); + $parent = $parent.parentElement.parentElement; + } + } + }); + this._tocOnScroll(); + this.scrollEventSet.add(this._tocOnScroll); + } + } + + initMath() { + if (this.config.math) renderMathInElement(document.body, this.config.math); + } + + initMermaid() { + const $mermaidElements = document.getElementsByClassName("mermaid"); + if ($mermaidElements.length) { + mermaid.initialize({ startOnLoad: false, theme: "null" }); + this.util.forEach($mermaidElements, ($mermaid) => { + mermaid.mermaidAPI.render( + "svg-" + $mermaid.id, + this.data[$mermaid.id], + (svgCode) => { + $mermaid.insertAdjacentHTML("afterbegin", svgCode); + }, + $mermaid + ); + }); + } + } + + initEcharts() { + this._echartsOnSwitchTheme = + this._echartsOnSwitchTheme || + (() => { + this._echartsArr = this._echartsArr || []; + for (let i = 0; i < this._echartsArr.length; i++) { + this._echartsArr[i].dispose(); + } + this._echartsArr = []; + this.util.forEach( + document.getElementsByClassName("echarts"), + ($echarts) => { + const chart = echarts.init( + $echarts, + this.isDark ? "dark" : "macarons", + { renderer: "svg" } + ); + chart.setOption(JSON.parse(this.data[$echarts.id])); + this._echartsArr.push(chart); + } + ); + }); + this.switchThemeEventSet.add(this._echartsOnSwitchTheme); + this._echartsOnSwitchTheme(); + this._echartsOnResize = + this._echartsOnResize || + (() => { + for (let i = 0; i < this._echartsArr.length; i++) { + this._echartsArr[i].resize(); + } + }); + this.resizeEventSet.add(this._echartsOnResize); + } + + initMapbox() { + if (this.config.mapbox) { + mapboxgl.accessToken = this.config.mapbox.accessToken; + mapboxgl.setRTLTextPlugin(this.config.mapbox.RTLTextPlugin); + this._mapboxArr = this._mapboxArr || []; + this.util.forEach( + document.getElementsByClassName("mapbox"), + ($mapbox) => { + const { + lng, + lat, + zoom, + lightStyle, + darkStyle, + marked, + navigation, + geolocate, + scale, + fullscreen, + } = this.data[$mapbox.id]; + const mapbox = new mapboxgl.Map({ + container: $mapbox, + center: [lng, lat], + zoom: zoom, + minZoom: 0.2, + style: this.isDark ? darkStyle : lightStyle, + attributionControl: false, + }); + if (marked) { + new mapboxgl.Marker().setLngLat([lng, lat]).addTo(mapbox); + } + if (navigation) { + mapbox.addControl(new mapboxgl.NavigationControl(), "bottom-right"); + } + if (geolocate) { + mapbox.addControl( + new mapboxgl.GeolocateControl({ + positionOptions: { + enableHighAccuracy: true, + }, + showUserLocation: true, + trackUserLocation: true, + }), + "bottom-right" + ); + } + if (scale) { + mapbox.addControl(new mapboxgl.ScaleControl()); + } + if (fullscreen) { + mapbox.addControl(new mapboxgl.FullscreenControl()); + } + mapbox.addControl(new MapboxLanguage()); + this._mapboxArr.push(mapbox); + } + ); + this._mapboxOnSwitchTheme = + this._mapboxOnSwitchTheme || + (() => { + this.util.forEach(this._mapboxArr, (mapbox) => { + const $mapbox = mapbox.getContainer(); + const { lightStyle, darkStyle } = this.data[$mapbox.id]; + mapbox.setStyle(this.isDark ? darkStyle : lightStyle); + mapbox.addControl(new MapboxLanguage()); + }); + }); + this.switchThemeEventSet.add(this._mapboxOnSwitchTheme); + } + } + + initTypeit() { + if (this.config.typeit) { + const typeitConfig = this.config.typeit; + const speed = typeitConfig.speed ? typeitConfig.speed : 100; + const cursorSpeed = typeitConfig.cursorSpeed + ? typeitConfig.cursorSpeed + : 1000; + const cursorChar = typeitConfig.cursorChar + ? typeitConfig.cursorChar + : "|"; + Object.values(typeitConfig.data).forEach((group) => { + const typeone = (i) => { + const id = group[i]; + const instance = new TypeIt(`#${id}`, { + strings: this.data[id], + speed: speed, + lifeLike: true, + cursorSpeed: cursorSpeed, + cursorChar: cursorChar, + waitUntilVisible: true, + afterComplete: () => { + if (i === group.length - 1) { + if (typeitConfig.duration >= 0) + window.setTimeout(() => { + instance.destroy(); + }, typeitConfig.duration); + return; + } + instance.destroy(); + typeone(i + 1); + }, + }).go(); + }; + typeone(0); + }); + } + } + + initComment() { + if (this.config.comment) { + if (this.config.comment.gitalk) { + this.config.comment.gitalk.body = decodeURI(window.location.href); + const gitalk = new Gitalk(this.config.comment.gitalk); + gitalk.render("gitalk"); + } + if (this.config.comment.valine) new Valine(this.config.comment.valine); + if (this.config.comment.utterances) { + const utterancesConfig = this.config.comment.utterances; + const script = document.createElement("script"); + script.src = "https://utteranc.es/client.js"; + script.type = "text/javascript"; + script.setAttribute("repo", utterancesConfig.repo); + script.setAttribute("issue-term", utterancesConfig.issueTerm); + if (utterancesConfig.label) + script.setAttribute("label", utterancesConfig.label); + script.setAttribute( + "theme", + this.isDark ? utterancesConfig.darkTheme : utterancesConfig.lightTheme + ); + script.crossOrigin = "anonymous"; + script.async = true; + document.getElementById("utterances").appendChild(script); + this._utterancesOnSwitchTheme = + this._utterancesOnSwitchTheme || + (() => { + const message = { + type: "set-theme", + theme: this.isDark + ? utterancesConfig.darkTheme + : utterancesConfig.lightTheme, + }; + const iframe = document.querySelector(".utterances-frame"); + iframe.contentWindow.postMessage(message, "https://utteranc.es"); + }); + this.switchThemeEventSet.add(this._utterancesOnSwitchTheme); + } + } + } + + initSmoothScroll() { + if (SmoothScroll) + new SmoothScroll('[href^="#"]', { + speed: 300, + speedAsDuration: true, + header: "#header-desktop", + }); + } + + initCookieconsent() { + if (this.config.cookieconsent) + cookieconsent.initialise(this.config.cookieconsent); + } + + onScroll() { + const $headers = []; + if (document.body.getAttribute("header-desktop") === "auto") + $headers.push(document.getElementById("header-desktop")); + if (document.body.getAttribute("header-mobile") === "auto") + $headers.push(document.getElementById("header-mobile")); + if (document.getElementById("comments")) { + const $viewComments = document.getElementById("view-comments"); + $viewComments.href = `#comments`; + $viewComments.style.display = "block"; + } + const $fixedButtons = document.getElementById("fixed-buttons"); + const ACCURACY = 20, + MINIMUM = 100; + window.addEventListener( + "scroll", + () => { + this.newScrollTop = this.util.getScrollTop(); + const scroll = this.newScrollTop - this.oldScrollTop; + const isMobile = this.util.isMobile(); + this.util.forEach($headers, ($header) => { + if (scroll > ACCURACY) { + $header.classList.remove("fadeInDown"); + this.util.animateCSS($header, ["fadeOutUp", "faster"], true); + } else if (scroll < -ACCURACY) { + $header.classList.remove("fadeOutUp"); + this.util.animateCSS($header, ["fadeInDown", "faster"], true); + } + }); + if (this.newScrollTop > MINIMUM) { + if (isMobile && scroll > ACCURACY) { + $fixedButtons.classList.remove("fadeIn"); + this.util.animateCSS($fixedButtons, ["fadeOut", "faster"], true); + } else if (!isMobile || scroll < -ACCURACY) { + $fixedButtons.style.display = "block"; + $fixedButtons.classList.remove("fadeOut"); + this.util.animateCSS($fixedButtons, ["fadeIn", "faster"], true); + } + } else { + if (!isMobile) { + $fixedButtons.classList.remove("fadeIn"); + this.util.animateCSS($fixedButtons, ["fadeOut", "faster"], true); + } + $fixedButtons.style.display = "none"; + } + for (let event of this.scrollEventSet) event(); + this.oldScrollTop = this.newScrollTop; + }, + false + ); + } + + onResize() { + window.addEventListener( + "resize", + () => { + if (!this._resizeTimeout) { + this._resizeTimeout = window.setTimeout(() => { + this._resizeTimeout = null; + for (let event of this.resizeEventSet) event(); + this.initToc(); + this.initMermaid(); + this.initSearch(); + }, 100); + } + }, + false + ); + } + + onClickMask() { + document.getElementById("mask").addEventListener( + "click", + () => { + for (let event of this.clickMaskEventSet) event(); + document.body.classList.remove("blur"); + }, + false + ); + } + + init() { + try { + this.initSVGIcon(); + this.initTwemoji(); + this.initMenuMobile(); + this.initSwitchTheme(); + this.initSearch(); + this.initDetails(); + this.initLightGallery(); + this.initHighlight(); + this.initTable(); + this.initHeaderLink(); + this.initSmoothScroll(); + this.initMath(); + this.initMermaid(); + this.initEcharts(); + this.initTypeit(); + this.initMapbox(); + this.initCookieconsent(); + } catch (err) { + console.error(err); + } + + window.setTimeout(() => { + this.initToc(); + this.initComment(); + + this.onScroll(); + this.onResize(); + this.onClickMask(); + }, 100); + } +} + +const themeInit = () => { + const theme = new Theme(); + theme.init(); +}; + +if (document.readyState !== "loading") { + themeInit(); +} else { + document.addEventListener("DOMContentLoaded", themeInit, false); +} diff --git a/themes/CodeIT/src/lib/lunr.segmentit.js b/themes/CodeIT/src/lib/lunr.segmentit.js new file mode 100644 index 0000000..b9fdb37 --- /dev/null +++ b/themes/CodeIT/src/lib/lunr.segmentit.js @@ -0,0 +1,12 @@ +import { Segment, useDefault } from "segmentit"; + +const segmentit = useDefault(new Segment()); +lunr.segmentit = segmentit; +lunr.queryHandler = (query) => { + if (/^[\u4e00-\u9fa5]+$/.test(query)) + query = lunr.segmentit + .doSegment(query) + .map((seg) => "+" + seg.w) + .join(" "); + return query; +}; |