diff --git a/_config.yml b/_config.yml
index 56b75e7..a391495 100644
--- a/_config.yml
+++ b/_config.yml
@@ -86,7 +86,7 @@ website_count:
# See: https://github.com/theme-next/hexo-generator-searchdb
# ---------------------------------------------------------------------------------------
local_search:
- enable: true
+ enable: false
# If auto, trigger search by changing input.
# If manual, trigger search by pressing enter key or search button.
@@ -141,7 +141,7 @@ side_tools:
# Back to top
# ---------------------------------------------------------------------------------------
back2top:
- enable: false
+ enable: true
# ---------------------------------------------------------------------------------------
diff --git a/layout/_partial/head.ejs b/layout/_partial/head.ejs
index d3fcd8e..2b57725 100644
--- a/layout/_partial/head.ejs
+++ b/layout/_partial/head.ejs
@@ -15,10 +15,14 @@
title = __('tag') + ': ' + page.tag;
} else if (page.title === 'about') {
title = __('about');
+ } else if (page.title === 'links') {
+ title = __('links');
}
%>
- <% if (title){ %><%= title %> | <% } %><%= config.title %>
+ <% if (title){ %><%= title %> |
+ <% } %>
+ <%= config.title %>
<% if (theme.style.favicon){ %>
diff --git a/layout/_partial/scripts.ejs b/layout/_partial/scripts.ejs
index da7c3d3..f7cb5fe 100644
--- a/layout/_partial/scripts.ejs
+++ b/layout/_partial/scripts.ejs
@@ -1,21 +1,24 @@
<%- js([
- 'js/main.js',
+ 'js/utils.js',
'js/header-shrink.js',
- 'js/toggle-mode.js'
+ 'js/dark-light-toggle.js',
+ 'js/main.js'
]) %>
<% if (theme.back2top.enable) { %>
- <%- js('js/scroll-to-top.js') %>
+ <%- js('js/back2top.js') %>
<% } %>
<% if (is_post()) { %>
+ <%- js('js/left-side-toggle.js') %>
+
<% if (theme.code_copy.enable) { %>
<%- js('js/code-copy.js') %>
<% } %>
<% if (theme.toc.enable) { %>
- <%- js(['lib/anime.min.js', 'js/toc.js', 'js/post-toc.js']) %>
+ <%- js(['lib/anime.min.js', 'js/toc.js']) %>
<% } %>
<% } %>
diff --git a/scripts/helpers/export-config.js b/scripts/helpers/export-config.js
index c8af5bc..2f39c2e 100644
--- a/scripts/helpers/export-config.js
+++ b/scripts/helpers/export-config.js
@@ -8,18 +8,21 @@ const url = require('url');
* Export theme config to js
*/
hexo.extend.helper.register('export_config', function () {
- let {config, theme} = this;
- let exportConfig = {
- hostname: url.parse(config.url).hostname || config.url,
- root: config.root,
- localsearch: theme.local_search,
- themeInfo: theme.theme_info,
- codeblock: theme.codeblock
- };
- if (config.search) {
- exportConfig.path = config.search.path;
- }
- return ``;
});
diff --git a/source/css/layout/common/markdown.styl b/source/css/layout/common/markdown.styl
index a2abf83..1d1b0a4 100644
--- a/source/css/layout/common/markdown.styl
+++ b/source/css/layout/common/markdown.styl
@@ -69,15 +69,14 @@
h1, h2, h3, h4, h5, h6 {
- // TODO: ...
}
h1 {
color: var(--second-text-color);
font-size: 2em;
font-weight: 600;
- margin-block-start: 1.1em;
- margin-block-end: 1.1em;
+ margin-block-start: 1.4em;
+ margin-block-end: 1.0em;
}
@@ -85,16 +84,16 @@
color: var(--second-text-color);
font-size: 1.8em;
font-weight: 600;
- margin-block-start: 1.1em;
- margin-block-end: 1.1em;
+ margin-block-start: 1.4em;
+ margin-block-end: 1.0em;
}
h3 {
color: var(--second-text-color);
font-size: 1.6em;
font-weight: 550;
- margin-block-start: 1em;
- margin-block-end: 1em;
+ margin-block-start: 1.2em;
+ margin-block-end: 0.8em;
}
@@ -102,16 +101,16 @@
color: var(--second-text-color);
font-size: 1.4em;
font-weight: 550;
- margin-block-start: 1em;
- margin-block-end: 1em;
+ margin-block-start: 1.2em;
+ margin-block-end: 0.8em;
}
h5 {
color: var(--second-text-color);
font-size: 1.2em;
font-weight: 500;
- margin-block-start: 0.9em;
- margin-block-end: 0.9em;
+ margin-block-start: 1.0em;
+ margin-block-end: 0.6em;
}
@@ -119,8 +118,8 @@
color: var(--second-text-color);
font-size: 1.2em;
font-weight: 500;
- margin-block-start: 0.9em;
- margin-block-end: 0.9em;
+ margin-block-start: 1.0em;
+ margin-block-end: 0.6em;
}
diff --git a/source/js/back2top.js b/source/js/back2top.js
new file mode 100644
index 0000000..10f512f
--- /dev/null
+++ b/source/js/back2top.js
@@ -0,0 +1,35 @@
+window.addEventListener('DOMContentLoaded', () => {
+ ILS.utils = {
+
+ ...ILS.utils,
+
+ back2TopButton_dom: document.querySelector('.scroll-to-top'),
+
+ back2top() {
+ const scrollTopTimer = setInterval(function () {
+ let top = document.body.scrollTop || document.documentElement.scrollTop;
+ let speed = top / 2;
+ if (document.body.scrollTop !== 0) {
+ document.body.scrollTop -= speed;
+ } else {
+ document.documentElement.scrollTop -= speed;
+ }
+ if (top === 0) {
+ clearInterval(scrollTopTimer);
+ }
+ }, 30);
+ },
+
+ initBack2TopButton() {
+ if (ILS.utils.back2TopButton_dom) {
+ ILS.utils.back2TopButton_dom.addEventListener('click', () => {
+ this.back2top();
+ });
+ }
+ },
+ }
+
+ ILS.utils.initBack2TopButton();
+});
+
+
diff --git a/source/js/code-copy.js b/source/js/code-copy.js
index 5e09bc9..8a36266 100644
--- a/source/js/code-copy.js
+++ b/source/js/code-copy.js
@@ -1,45 +1,45 @@
HTMLElement.prototype.wrap = function (wrapper) {
- this.parentNode.insertBefore(wrapper, this);
- this.parentNode.removeChild(this);
- wrapper.appendChild(this);
+ this.parentNode.insertBefore(wrapper, this);
+ this.parentNode.removeChild(this);
+ wrapper.appendChild(this);
};
window.addEventListener('DOMContentLoaded', () => {
- document.querySelectorAll('figure.highlight').forEach(element => {
- const box = document.createElement('div');
- element.wrap(box);
- box.classList.add('highlight-container');
- box.insertAdjacentHTML('beforeend', '
');
- var button = element.parentNode.querySelector('.copy-btn');
- button.addEventListener('click', event => {
- var target = event.currentTarget;
- var code = [...target.parentNode.querySelectorAll('.code .line')].map(line => line.innerText).join('\n');
- var ta = document.createElement('textarea');
- ta.style.top = window.scrollY + 'px'; // Prevent page scrolling
- ta.style.position = 'absolute';
- ta.style.opacity = '0';
- ta.readOnly = true;
- ta.value = code;
- document.body.append(ta);
- const selection = document.getSelection();
- const selected = selection.rangeCount > 0 ? selection.getRangeAt(0) : false;
- ta.select();
- ta.setSelectionRange(0, code.length);
- ta.readOnly = false;
- var result = document.execCommand('copy');
- target.querySelector('i').className = result ? 'fa fa-check' : 'fa fa-times';
- ta.blur(); // For iOS
- target.blur();
- if (selected) {
- selection.removeAllRanges();
- selection.addRange(selected);
- }
- document.body.removeChild(ta);
- });
- button.addEventListener('mouseleave', event => {
- setTimeout(() => {
- event.target.querySelector('i').className = 'fa fa-clipboard';
- }, 300);
- });
+ document.querySelectorAll('figure.highlight').forEach(element => {
+ const box = document.createElement('div');
+ element.wrap(box);
+ box.classList.add('highlight-container');
+ box.insertAdjacentHTML('beforeend', '
');
+ var button = element.parentNode.querySelector('.copy-btn');
+ button.addEventListener('click', event => {
+ var target = event.currentTarget;
+ var code = [...target.parentNode.querySelectorAll('.code .line')].map(line => line.innerText).join('\n');
+ var ta = document.createElement('textarea');
+ ta.style.top = window.scrollY + 'px'; // Prevent page scrolling
+ ta.style.position = 'absolute';
+ ta.style.opacity = '0';
+ ta.readOnly = true;
+ ta.value = code;
+ document.body.append(ta);
+ const selection = document.getSelection();
+ const selected = selection.rangeCount > 0 ? selection.getRangeAt(0) : false;
+ ta.select();
+ ta.setSelectionRange(0, code.length);
+ ta.readOnly = false;
+ var result = document.execCommand('copy');
+ target.querySelector('i').className = result ? 'fa fa-check' : 'fa fa-times';
+ ta.blur(); // For iOS
+ target.blur();
+ if (selected) {
+ selection.removeAllRanges();
+ selection.addRange(selected);
+ }
+ document.body.removeChild(ta);
});
+ button.addEventListener('mouseleave', event => {
+ setTimeout(() => {
+ event.target.querySelector('i').className = 'fa fa-clipboard';
+ }, 300);
+ });
+ });
});
diff --git a/source/js/dark-light-toggle.js b/source/js/dark-light-toggle.js
new file mode 100644
index 0000000..398bfcb
--- /dev/null
+++ b/source/js/dark-light-toggle.js
@@ -0,0 +1,72 @@
+window.addEventListener('DOMContentLoaded', () => {
+ ILS.utils.modeToggle = {
+
+ localStorageKey: 'MAGIC',
+ modeToggleButton_dom: document.querySelector('.mode-toggle'),
+ iconDom: document.querySelector('.mode-toggle i'),
+ articleContent: document.querySelector('.main-content'),
+
+ setItemUtil(modeClass, prefersColorScheme) {
+ document.body.classList.toggle(modeClass);
+ const isDark = document.body.className.indexOf(modeClass) === -1;
+
+ if (isDark) {
+ this.iconDom.className = 'fa fa-moon-o';
+ this.articleContent.classList.remove('night-code-theme');
+ } else {
+ this.iconDom.className = 'fa fa-lightbulb-o';
+ this.articleContent.classList.add('night-code-theme');
+ }
+ localStorage.setItem(this.localStorageKey, JSON.stringify(
+ {
+ prefersColorScheme: prefersColorScheme,
+ isDark: isDark
+ }
+ ));
+ },
+
+ initModeStatus() {
+ this.modeConfig = JSON.parse(localStorage.getItem(this.localStorageKey));
+ if (this.modeConfig) {
+ if (this.modeConfig.prefersColorScheme === 'dark') {
+ if (this.modeConfig.isDark) {
+ document.body.classList.remove('light-mode');
+ this.articleContent.classList.remove('night-code-theme');
+ this.iconDom.className = 'fa fa-lightbulb-o';
+ } else {
+ document.body.classList.add('light-mode');
+ this.articleContent.classList.add('night-code-theme');
+ this.iconDom.className = 'fa fa-moon-o';
+ }
+ } else {
+
+ if (this.modeConfig.isDark) {
+ document.body.classList.remove('dark-mode');
+ this.articleContent.classList.remove('night-code-theme');
+ this.iconDom.className = 'fa fa-moon-o';
+ } else {
+ document.body.classList.add('dark-mode');
+ this.articleContent.classList.add('night-code-theme');
+ this.iconDom.className = 'fa fa-lightbulb-o';
+ }
+
+ }
+
+ }
+ },
+
+ initModeToggleButton() {
+ this.modeToggleButton_dom.addEventListener('click', () => {
+ if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
+ this.setItemUtil('light-mode', 'dark');
+ } else {
+ this.setItemUtil('dark-mode', 'light');
+ }
+ });
+ }
+
+ }
+
+ ILS.utils.modeToggle.initModeStatus();
+ ILS.utils.modeToggle.initModeToggleButton();
+});
diff --git a/source/js/header-shrink.js b/source/js/header-shrink.js
index f5ba5a3..19b5ab3 100644
--- a/source/js/header-shrink.js
+++ b/source/js/header-shrink.js
@@ -1,36 +1,50 @@
-const pageTemplateDom = document.querySelector('.page-main-content');
-const sidebarToolsDom = document.querySelector('.sidebar-tools');
-const headerDom = document.querySelector('.header-wrapper');
-const menuBarDom = document.querySelector('.menu-bar');
-const windowMaskDom = document.querySelector('.window-mask');
+window.addEventListener('DOMContentLoaded', () => {
+ ILS.utils.headerShrink = {
+ pageTemplateDom: document.querySelector('.page-main-content'),
+ sidebarToolsDom: document.querySelector('.sidebar-tools'),
+ headerDom: document.querySelector('.header-wrapper'),
+ menuBarDom: document.querySelector('.menu-bar'),
+ windowMaskDom: document.querySelector('.window-mask'),
-let isHeaderShrink = false;
-const headerHeight = headerDom.getBoundingClientRect().height;
+ isHeaderShrink: false,
-window.addEventListener('scroll', function (_e) {
- const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
- if (!isHeaderShrink && scrollTop > headerHeight) {
- isHeaderShrink = true;
- headerDom.classList.add('header-wrapper-shrink');
- pageTemplateDom.classList.add('page-main-content-top-shrink');
- sidebarToolsDom.classList.add('sidebar-tools-shrink');
+ init() {
+ this.headerHeight = this.headerDom.getBoundingClientRect().height;
+ },
- } else if (isHeaderShrink && scrollTop <= headerHeight) {
- isHeaderShrink = false;
- headerDom.classList.remove('header-wrapper-shrink');
- pageTemplateDom.classList.remove('page-main-content-top-shrink');
- sidebarToolsDom.classList.remove('sidebar-tools-shrink');
+ headerShrink() {
+
+ const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
+
+ if (!this.isHeaderShrink && scrollTop > this.headerHeight) {
+ this.isHeaderShrink = true;
+ this.headerDom.classList.add('header-wrapper-shrink');
+ this.pageTemplateDom.classList.add('page-main-content-top-shrink');
+ this.sidebarToolsDom.classList.add('sidebar-tools-shrink');
+
+ } else if (this.isHeaderShrink && scrollTop <= this.headerHeight) {
+ this.isHeaderShrink = false;
+ this.headerDom.classList.remove('header-wrapper-shrink');
+ this.pageTemplateDom.classList.remove('page-main-content-top-shrink');
+ this.sidebarToolsDom.classList.remove('sidebar-tools-shrink');
+ }
+
+ },
+
+ initMenuBarButton() {
+ this.menuBarDom.addEventListener('click', () => {
+ this.headerDom.classList.toggle('header-drawer-show');
+ });
+ },
+
+ initWindowMask() {
+ this.windowMaskDom.addEventListener('click', () => {
+ this.headerDom.classList.toggle('header-drawer-show');
+ });
+ },
}
+ ILS.utils.headerShrink.init();
+ ILS.utils.headerShrink.initMenuBarButton();
+ ILS.utils.headerShrink.initWindowMask();
});
-
-
-menuBarDom.addEventListener('click', function (_e) {
- headerDom.classList.toggle('header-drawer-show');
-});
-
-windowMaskDom.addEventListener('click', function (_e) {
- headerDom.classList.toggle('header-drawer-show');
-});
-
-
diff --git a/source/js/left-side-toggle.js b/source/js/left-side-toggle.js
new file mode 100644
index 0000000..a68d200
--- /dev/null
+++ b/source/js/left-side-toggle.js
@@ -0,0 +1,38 @@
+window.addEventListener('DOMContentLoaded', () => {
+
+ ILS.utils.leftSideToggle = {
+
+ init() {
+ this.toggleBar = document.querySelector('.page-aside-toggle');
+ this.pageTopDom = document.querySelector('.page-main-content-top');
+ this.containerDom = document.querySelector('.page-container');
+ this.leftAsideDom = document.querySelector('.page-aside');
+ this.headerContentDom = document.querySelector('.header-wrapper .header-content');
+ this.mainContentDom = document.querySelector('.page-main-content-middle .main-content');
+ this.isOpenPageAside = false;
+ },
+
+ initToggleBarButton() {
+ if (this.toggleBar) {
+ this.toggleBar.addEventListener('click', () => {
+ this.isOpenPageAside = !this.isOpenPageAside;
+ this.changePageLayoutWhenOpenToggle(this.isOpenPageAside);
+ })
+ }
+ },
+
+ changePageLayoutWhenOpenToggle(isOpen) {
+ const pageAsideWidth = '258px';
+ this.containerDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
+ this.pageTopDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
+ this.pageTopDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
+ this.leftAsideDom.style.left = isOpen ? '0' : `-${pageAsideWidth}`;
+ this.headerContentDom.style.width = isOpen ? '76%' : '62%';
+ this.mainContentDom.style.width = isOpen ? '76%' : '62%';
+ },
+ }
+
+ ILS.utils.leftSideToggle.init();
+ ILS.utils.leftSideToggle.initToggleBarButton();
+
+});
diff --git a/source/js/main.js b/source/js/main.js
index d0b32f2..08c99ee 100644
--- a/source/js/main.js
+++ b/source/js/main.js
@@ -1,47 +1,8 @@
window.addEventListener('DOMContentLoaded', () => {
- console.log(`${CONFIG.themeInfo.name} v${CONFIG.themeInfo.version}`);
+ // print theme info
+ ILS.utils.printThemeInfo();
- pageAsideOpenToggle();
+ // init scroll
+ ILS.utils.initWindowScroll();
});
-
-
-const pageAsideOpenToggle = () => {
-
- const toggleDom = document.querySelector('.page-aside-toggle');
- const pageTopDom = document.querySelector('.page-main-content-top');
- const containerDom = document.querySelector('.page-container');
- const leftAsideDom = document.querySelector('.page-aside');
-
- const headerContentDom = document.querySelector('.header-wrapper .header-content');
- const mainContentDom = document.querySelector('.page-main-content-middle .main-content');
-
- let isOpen = false;
- const openToggle = (isOpen) => {
-
- const pageAsideWidth = '258px';
- containerDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
- pageTopDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
- pageTopDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
- leftAsideDom.style.left = isOpen ? '0' : `-${pageAsideWidth}`;
-
- headerContentDom.style.width = isOpen ? '76%' : '62%';
- mainContentDom.style.width = isOpen ? '76%' : '62%';
-
- }
-
-
- toggleDom.addEventListener('click', () => {
- isOpen = !isOpen;
- openToggle(isOpen);
- })
-
-
- window.utils = {
- openToggle: () => {
- isOpen = true;
- openToggle(isOpen);
- }
- }
-
-}
diff --git a/source/js/post-toc.js b/source/js/post-toc.js
deleted file mode 100644
index e404f3c..0000000
--- a/source/js/post-toc.js
+++ /dev/null
@@ -1,10 +0,0 @@
-window.addEventListener('DOMContentLoaded', () => {
- const navItems = document.querySelectorAll('.post-toc-wrap .post-toc li');
- const toggleDom = document.querySelector('.page-aside-toggle');
-
- if (navItems.length) {
- toggleDom.style.display = 'flex';
- window.utils.openToggle();
- }
-
-});
diff --git a/source/js/scroll-to-top.js b/source/js/scroll-to-top.js
deleted file mode 100644
index eb95d22..0000000
--- a/source/js/scroll-to-top.js
+++ /dev/null
@@ -1,53 +0,0 @@
-(function () {
- const scrollToTopDom = document.querySelector('.scroll-to-top');
- const headerProgressDom = document.querySelector('.header-progress');
- const headerWrapper = document.querySelector('.header-wrapper');
-
- const backToTop = () => {
- let scrollTopTimer = setInterval(function () {
- let top = document.body.scrollTop || document.documentElement.scrollTop;
- let speed = top / 2;
- if (document.body.scrollTop !== 0) {
- document.body.scrollTop -= speed;
- } else {
- document.documentElement.scrollTop -= speed;
- }
- if (top === 0) {
- clearInterval(scrollTopTimer);
- }
- }, 30);
- };
-
- scrollToTopDom.addEventListener('click', () => {
- backToTop();
- });
-
- let prevScroll = 0;
- window.addEventListener('scroll', function (_e) {
- // back to top & show scroll percent
- const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
- const scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight;
- const clientHeight = window.innerHeight || document.documentElement.clientHeight;
- const percent = Math.round(scrollTop / (scrollHeight - clientHeight) * 100).toFixed(0);
- const ProgressPercent = (scrollTop / (scrollHeight - clientHeight) * 100).toFixed(3);
-
- if (percent === '0') {
- scrollToTopDom.style.display = 'none';
- headerProgressDom.style.display = 'none';
- } else {
- scrollToTopDom.style.display = 'flex';
- headerProgressDom.style.display = 'block';
- headerProgressDom.style.width = `${ProgressPercent}%`;
- }
-
- // hide header handle
- const opacity = headerWrapper.style.opacity
- if (scrollTop > prevScroll && scrollTop > 360) {
- if (opacity > 0) headerWrapper.style.opacity = '0';
- } else {
- if (opacity < 1) headerWrapper.style.opacity = '1';
- }
- prevScroll = scrollTop
- });
-
-})();
diff --git a/source/js/toc.js b/source/js/toc.js
index e5158d6..89424d9 100644
--- a/source/js/toc.js
+++ b/source/js/toc.js
@@ -1,107 +1,95 @@
window.addEventListener('DOMContentLoaded', () => {
- const articleToc = document.querySelector('.article-toc');
- const postTocWrap = document.querySelector('.post-toc-wrap');
- const navItems = postTocWrap.querySelectorAll('.post-toc li');
- const headerWrapper = document.querySelector('.header-wrapper');
+ ILS.utils.navItems = document.querySelectorAll('.post-toc-wrap .post-toc li');
+ ILS.utils.articleToc_dom = document.querySelector('.article-toc');
+ ILS.utils.postTocWrap_dom = document.querySelector('.post-toc-wrap');
+ ILS.utils.headerWrapper_dom = document.querySelector('.header-wrapper');
- if (navItems.length > 0) {
+ if (ILS.utils.navItems.length > 0) {
- const sections = [...navItems].map(element => {
- let link = element.querySelector('a.nav-link');
- // TOC item animation navigate.
- link.addEventListener('click', event => {
- event.preventDefault();
- let target = document.getElementById(event.currentTarget.getAttribute('href').replace('#', ''));
- let offset = target.getBoundingClientRect().top + window.scrollY - 18;
- window.anime({
- targets: document.scrollingElement,
- duration: 500,
- easing: 'linear',
- scrollTop: offset,
- complete: function () {
- setTimeout(() => {
- if (headerWrapper.style.opacity !== '0') headerWrapper.style.opacity = '0'
- }, 100)
- }
+ ILS.utils = {
+
+ ...ILS.utils,
+
+ findActiveIndexByTOC() {
+ if (!Array.isArray(ILS.utils.sections)) return;
+ let index = ILS.utils.sections.findIndex(element => {
+ return element && element.getBoundingClientRect().top - 20 > 0;
});
- });
- return document.getElementById(link.getAttribute('href').replace('#', ''));
- });
-
-
- function activateNavByIndex(target) {
- if (target.classList.contains('active-current')) return;
- document.querySelectorAll('.post-toc .active').forEach(element => {
- element.classList.remove('active', 'active-current');
- });
- target.classList.add('active', 'active-current');
- let parent = target.parentNode;
- while (!parent.matches('.post-toc')) {
- if (parent.matches('li')) parent.classList.add('active');
- parent = parent.parentNode;
- }
- // Scrolling to center active TOC element if TOC content is taller then viewport.
- window.anime({
- targets: postTocWrap,
- duration: 200,
- easing: 'linear',
- scrollTop: postTocWrap.scrollTop - (postTocWrap.offsetHeight / 2) + target.getBoundingClientRect().top - postTocWrap.getBoundingClientRect().top
- });
- }
-
- function findIndex(entries) {
- let index = 0;
- let entry = entries[index];
- if (entry.boundingClientRect.top > 0) {
- index = sections.indexOf(entry.target);
- return index === 0 ? 0 : index - 1;
- }
- for (; index < entries.length; index++) {
- if (entries[index].boundingClientRect.top <= 0) {
- entry = entries[index];
- } else {
- return sections.indexOf(entry.target);
+ if (index === -1) {
+ index = ILS.utils.sections.length - 1;
+ } else if (index > 0) {
+ index--;
}
- }
- return sections.indexOf(entry.target);
- }
+ ILS.utils.activateNavByIndex(index);
+ },
- function createIntersectionObserver(marginTop) {
+ registerSidebarTOC() {
+ ILS.utils.sections = [...document.querySelectorAll('.post-toc li a.nav-link')].map(element => {
+ const target = document.getElementById(decodeURI(element.getAttribute('href')).replace('#', ''));
+ element.addEventListener('click', event => {
+ event.preventDefault();
+ const offset = target.getBoundingClientRect().top + window.scrollY;
+ window.anime({
+ targets: document.scrollingElement,
+ duration: 500,
+ easing: 'linear',
+ scrollTop: offset - 10,
+ complete: function () {
+ setTimeout(() => {
+ if (ILS.utils.headerWrapper_dom.style.opacity !== '0') ILS.utils.headerWrapper_dom.style.opacity = '0'
+ }, 100)
+ }
+ });
+ });
+ return target;
+ });
+ },
- marginTop = Math.floor(marginTop + 10000);
- let intersectionObserver = new IntersectionObserver((entries, observe) => {
- let scrollHeight = document.documentElement.scrollHeight + 100;
- if (scrollHeight > marginTop) {
- observe.disconnect();
- createIntersectionObserver(scrollHeight);
- return;
+ activateNavByIndex: function (index) {
+ const target = document.querySelectorAll('.post-toc li a.nav-link')[index];
+ if (!target || target.classList.contains('active-current')) return;
+
+ document.querySelectorAll('.post-toc .active').forEach(element => {
+ element.classList.remove('active', 'active-current');
+ });
+ target.classList.add('active', 'active-current');
+ let parent = target.parentNode;
+ while (!parent.matches('.post-toc')) {
+ if (parent.matches('li')) parent.classList.add('active');
+ parent = parent.parentNode;
}
- let index = findIndex(entries);
- activateNavByIndex(navItems[index]);
- }, {
- rootMargin: marginTop + 'px 0px -100% 0px',
- threshold: 0
- });
- sections.forEach(element => {
- element && intersectionObserver.observe(element);
- });
+ // Scrolling to center active TOC element if TOC content is taller then viewport.
+ const tocElement = document.querySelector('.post-toc-wrap');
+ window.anime({
+ targets: tocElement,
+ duration: 200,
+ easing: 'linear',
+ scrollTop: tocElement.scrollTop - (tocElement.offsetHeight / 2) + target.getBoundingClientRect().top - tocElement.getBoundingClientRect().top
+ });
+ },
+
+ showPageAsideWhenHasTOC() {
+ ILS.utils.leftSideToggle.toggleBar.style.display = 'flex';
+ ILS.utils.leftSideToggle.isOpenPageAside = true;
+ ILS.utils.leftSideToggle.changePageLayoutWhenOpenToggle(ILS.utils.leftSideToggle.isOpenPageAside);
+ }
}
- createIntersectionObserver(document.documentElement.scrollHeight);
+ ILS.utils.showPageAsideWhenHasTOC();
+ ILS.utils.registerSidebarTOC();
+
} else {
- if (postTocWrap) {
- postTocWrap.innerHTML = '';
- postTocWrap.style.display = 'none';
+ if (ILS.utils.postTocWrap_dom) {
+ ILS.utils.postTocWrap_dom.innerHTML = '';
+ ILS.utils.postTocWrap_dom.style.display = 'none';
}
- if (articleToc) {
- articleToc.style.display = 'none';
+ if (ILS.utils.articleToc_dom) {
+ ILS.utils.articleToc_dom.style.display = 'none';
}
}
-
-
});
diff --git a/source/js/toggle-mode.js b/source/js/toggle-mode.js
deleted file mode 100644
index 9d09bff..0000000
--- a/source/js/toggle-mode.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * 日间/夜间 模式切换
- */
-const localStorageKey = 'MAGIC'
-const modeToggleBtn = document.querySelector('.mode-toggle');
-const iconDom = modeToggleBtn.querySelector('i');
-const articleContent = document.querySelector('.main-content');
-const modeConfig = JSON.parse(localStorage.getItem(localStorageKey));
-if (modeConfig) {
-
- if (modeConfig.prefersColorScheme === 'dark') {
-
- if (modeConfig.isDark) {
- document.body.classList.remove('light-mode');
- articleContent.classList.remove('night-code-theme');
- iconDom.className = 'fa fa-lightbulb-o';
- } else {
- iconDom.className = 'fa fa-moon-o';
- document.body.classList.add('light-mode');
- articleContent.classList.add('night-code-theme');
- }
-
- } else {
-
- if (modeConfig.isDark) {
- document.body.classList.remove('dark-mode');
- articleContent.classList.remove('night-code-theme');
- iconDom.className = 'fa fa-moon-o';
- } else {
- document.body.classList.add('dark-mode');
- iconDom.className = 'fa fa-lightbulb-o';
- articleContent.classList.add('night-code-theme');
- }
-
- }
-
-}
-
-const setItemUtil = (modeClass, prefersColorScheme) => {
- document.body.classList.toggle(modeClass);
- const isDark = document.body.className.indexOf(modeClass) === -1;
-
- if (isDark) {
- iconDom.className = 'fa fa-moon-o';
- articleContent.classList.remove('night-code-theme');
- } else {
- iconDom.className = 'fa fa-lightbulb-o';
- articleContent.classList.add('night-code-theme');
- }
- localStorage.setItem(localStorageKey, JSON.stringify(
- {
- prefersColorScheme: prefersColorScheme,
- isDark: isDark
- }
- ));
-
-
-};
-
-modeToggleBtn.addEventListener('click', function (e) {
-
- if (
- window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
- ) {
- setItemUtil('light-mode', 'dark');
- } else {
- setItemUtil('dark-mode', 'light');
- }
-
-});
diff --git a/source/js/utils.js b/source/js/utils.js
new file mode 100644
index 0000000..075021b
--- /dev/null
+++ b/source/js/utils.js
@@ -0,0 +1,60 @@
+ILS.utils = {
+ printThemeInfo() {
+ console.log(`${CONFIG.themeInfo.name} v${CONFIG.themeInfo.version}`);
+ }
+}
+
+ILS.utils = {
+
+ ...ILS.utils,
+
+ headerProgress_dom: document.querySelector('.header-progress'),
+ headerWrapper_dom: document.querySelector('.header-wrapper'),
+
+ // Scroll Style Handle
+ prevScrollValue: 0,
+ styleHandleWhenScroll() {
+ const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
+ const scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight;
+ const clientHeight = window.innerHeight || document.documentElement.clientHeight;
+ const percent = Math.round(scrollTop / (scrollHeight - clientHeight) * 100).toFixed(0);
+ const ProgressPercent = (scrollTop / (scrollHeight - clientHeight) * 100).toFixed(3);
+
+ if (CONFIG.back2top.enable && ILS.utils.back2TopButton_dom) {
+ ILS.utils.back2TopButton_dom.style.display = percent === '0' ? 'none' : 'flex';
+ }
+
+ if (ILS.utils.headerProgress_dom) {
+ ILS.utils.headerProgress_dom.style.display = percent === '0' ? 'none' : 'block';
+ ILS.utils.headerProgress_dom.style.width = `${ProgressPercent}%`;
+ }
+
+ // hide header handle
+ const opacity = ILS.utils.headerWrapper_dom.style.opacity;
+ if (scrollTop > ILS.utils.prevScrollValue && scrollTop > 500) {
+ if (opacity !== '0') ILS.utils.headerWrapper_dom.style.opacity = '0';
+ } else {
+ if (opacity !== '1') ILS.utils.headerWrapper_dom.style.opacity = '1';
+ }
+ ILS.utils.prevScrollValue = scrollTop;
+ },
+
+ // 初始 window scroll 事件
+ initWindowScroll() {
+ window.addEventListener('scroll', function (_e) {
+ // style handle when scroll
+ ILS.utils.styleHandleWhenScroll();
+
+ // TOC scroll handle
+ if (CONFIG.toc.enable && ILS.utils.hasOwnProperty('findActiveIndexByTOC')) {
+ ILS.utils.findActiveIndexByTOC();
+ }
+
+ // header shrink
+ ILS.utils.headerShrink.headerShrink();
+ });
+ },
+}
+
+
+