build(deps): use prettier to format js code

This commit is contained in:
XPoet 2022-09-30 11:40:30 +08:00
parent 622f5d1b2b
commit 300b709c52
17 changed files with 712 additions and 691 deletions

10
.prettierrc Normal file
View File

@ -0,0 +1,10 @@
{
"useTabs": false,
"endOfLine": "auto",
"tabWidth": 2,
"printWidth": 100,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"semi": false
}

View File

@ -5,7 +5,8 @@
"description": "A simple and elegant theme for Hexo.", "description": "A simple and elegant theme for Hexo.",
"scripts": { "scripts": {
"npm:publish": "npm publish", "npm:publish": "npm publish",
"lint:style": "stylelint --fix source/css/**/**/**/*.styl", "format": "prettier --write ./source/js/*.js ./scripts",
"lint:style": "stylelint --fix ./source/css",
"git:push": "git push --tag && git push -u origin dev", "git:push": "git push --tag && git push -u origin dev",
"git:add": "npm run lint:style && git add ." "git:add": "npm run lint:style && git add ."
}, },
@ -29,6 +30,7 @@
}, },
"homepage": "https://github.com/XPoet/hexo-theme-keep#readme", "homepage": "https://github.com/XPoet/hexo-theme-keep#readme",
"devDependencies": { "devDependencies": {
"prettier": "^2.7.1",
"stylelint": "^14.13.0", "stylelint": "^14.13.0",
"stylelint-config-rational-order": "^0.1.2", "stylelint-config-rational-order": "^0.1.2",
"stylelint-stylus": "^0.17.0" "stylelint-stylus": "^0.17.0"

View File

@ -2,14 +2,14 @@
hexo.extend.filter.register( hexo.extend.filter.register(
'after_post_render', 'after_post_render',
function (data) { function (data) {
const theme = hexo.theme.config; const theme = hexo.theme.config
if (!theme.lazyload || !theme.lazyload.enable) return; if (!theme.lazyload || !theme.lazyload.enable) return
data.content = data.content.replace( data.content = data.content.replace(
// Match 'img' tags width the src attribute. // Match 'img' tags width the src attribute.
/<img([^>]*)src="([^"]*)"([^>\/]*)\/?\s*>/gim, /<img([^>]*)src="([^"]*)"([^>\/]*)\/?\s*>/gim,
function (match, attrBegin, src, attrEnd) { function (match, attrBegin, src, attrEnd) {
// Exit if the src doesn't exists. // Exit if the src doesn't exists.
if (!src) return match; if (!src) return match
return `<img ${attrBegin} return `<img ${attrBegin}
lazyload lazyload
@ -21,4 +21,4 @@ hexo.extend.filter.register(
) )
}, },
1 1
); )

View File

@ -2,40 +2,36 @@
'use strict' 'use strict'
hexo.extend.filter.register('after_post_render', function (data) { hexo.extend.filter.register(
'after_post_render',
const config = this.config; function (data) {
const url = new URL(config.url); const config = this.config
const siteHost = url.hostname || config.url; const url = new URL(config.url)
const siteHost = url.hostname || config.url
// Match 'a' tags that don't contain html children. // Match 'a' tags that don't contain html children.
const regPureATag = /<a([^>]*)href="([^"]*)"([^>]*)>([^<]*)<\/a>/gim const regPureATag = /<a([^>]*)href="([^"]*)"([^>]*)>([^<]*)<\/a>/gim
data.content = data.content.replace(regPureATag, function ( data.content = data.content.replace(
match, regPureATag,
attrBegin, function (match, attrBegin, href, attrEnd, html) {
href,
attrEnd,
html
) {
// Exit if the href attribute doesn't exists. // Exit if the href attribute doesn't exists.
if (!href) return match; if (!href) return match
let link = ''; let link = ''
try { try {
link = new URL(href); link = new URL(href)
} catch (e) { } catch (e) {
// Invalid url, e.g. Anchor link. // Invalid url, e.g. Anchor link.
return match; return match
} }
// Exit if the url has same host with `config.url`, which means isn't an external link. // Exit if the url has same host with `config.url`, which means isn't an external link.
if (!link.protocol || link.hostname === siteHost) return match; if (!link.protocol || link.hostname === siteHost) return match
return ( return `<a class="link" ${attrBegin} href="${href}" ${attrEnd}>${html}<i class="fas fa-external-link-alt"></i></a>`
`<a class="link" ${attrBegin} href="${href}" ${attrEnd}>${html}<i class="fas fa-external-link-alt"></i></a>` }
) )
})
}, },
0 0
) )

View File

@ -1,40 +1,38 @@
/* global hexo */ /* global hexo */
'use strict'; 'use strict'
const url = require('url'); const url = require('url')
const fs = require('fs'); const fs = require('fs')
const path = require('path'); const path = require('path')
const yaml = require('js-yaml'); const yaml = require('js-yaml')
/** /**
* Export theme config to js * Export theme config to js
*/ */
hexo.extend.helper.register('export_config', function () { hexo.extend.helper.register('export_config', function () {
const { config, theme } = this
const { config, theme } = this;
// ------------------------ export language to js ------------------------ // ------------------------ export language to js ------------------------
const languageDir = path.join(__dirname, '../../languages'); const languageDir = path.join(__dirname, '../../languages')
let file = fs.readdirSync(languageDir).find(v => v === `${config.language}.yml`); let file = fs.readdirSync(languageDir).find((v) => v === `${config.language}.yml`)
file = languageDir + '/' + (file ? file : 'en.yml'); file = languageDir + '/' + (file ? file : 'en.yml')
let languageContent = fs.readFileSync(file, 'utf8'); let languageContent = fs.readFileSync(file, 'utf8')
try { try {
languageContent = yaml.load(languageContent); languageContent = yaml.load(languageContent)
} catch (err) { } catch (err) {
console.log(err); console.log(err)
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
let hexo_config = { let hexo_config = {
hostname: url.parse(config.url).hostname || config.url, hostname: url.parse(config.url).hostname || config.url,
root: config.root, root: config.root,
language: config.language language: config.language
}; }
if (config.search) { if (config.search) {
hexo_config.path = config.search.path; hexo_config.path = config.search.path
} }
let theme_config = { let theme_config = {
@ -55,5 +53,5 @@ hexo.extend.helper.register('export_config', function () {
KEEP.theme_config = ${JSON.stringify(theme_config)}; KEEP.theme_config = ${JSON.stringify(theme_config)};
KEEP.language_ago = ${JSON.stringify(languageContent['ago'])}; KEEP.language_ago = ${JSON.stringify(languageContent['ago'])};
KEEP.language_code_block = ${JSON.stringify(languageContent['code_block'])}; KEEP.language_code_block = ${JSON.stringify(languageContent['code_block'])};
</script>`; </script>`
}); })

View File

@ -2,103 +2,102 @@
'use strict' 'use strict'
const url = require('url'); const url = require('url')
hexo.extend.helper.register('isInHomePaging', function (pagePath, route) { hexo.extend.helper.register('isInHomePaging', function (pagePath, route) {
if (pagePath.length > 5 && route === '/') { if (pagePath.length > 5 && route === '/') {
return pagePath.slice(0, 5) === 'page/'; return pagePath.slice(0, 5) === 'page/'
} else { } else {
return false; return false
} }
}); })
hexo.extend.helper.register('createNewArchivePosts', function (posts) { hexo.extend.helper.register('createNewArchivePosts', function (posts) {
const postList = [], postYearList = []; const postList = [],
posts.forEach(post => postYearList.push(post.date.year())); postYearList = []
Array.from(new Set(postYearList)).forEach(year => { posts.forEach((post) => postYearList.push(post.date.year()))
Array.from(new Set(postYearList)).forEach((year) => {
postList.push({ postList.push({
year: year, year: year,
postList: [] postList: []
}) })
}); })
postList.sort((a, b) => b.year - a.year) postList.sort((a, b) => b.year - a.year)
postList.forEach(item => { postList.forEach((item) => {
posts.forEach(post => item.year === post.date.year() && item.postList.push(post)) posts.forEach((post) => item.year === post.date.year() && item.postList.push(post))
}); })
postList.forEach(item => item.postList.sort((a, b) => b.date.unix() - a.date.unix())); postList.forEach((item) => item.postList.sort((a, b) => b.date.unix() - a.date.unix()))
return postList; return postList
}); })
hexo.extend.helper.register('getAuthorLabel', function (postCount, isAuto, labelList) { hexo.extend.helper.register('getAuthorLabel', function (postCount, isAuto, labelList) {
let level = Math.floor(Math.log2(postCount))
let level = Math.floor(Math.log2(postCount)); level = level < 2 ? 1 : level - 1
level = level < 2 ? 1 : level - 1;
if (isAuto === false && Array.isArray(labelList) && labelList.length > 0) { if (isAuto === false && Array.isArray(labelList) && labelList.length > 0) {
return level > labelList.length ? labelList[labelList.length - 1] : labelList[level - 1]; return level > labelList.length ? labelList[labelList.length - 1] : labelList[level - 1]
} else { } else {
return `Lv${level}`; return `Lv${level}`
} }
})
});
hexo.extend.helper.register('getPostUrl', function (rootUrl, path) { hexo.extend.helper.register('getPostUrl', function (rootUrl, path) {
if (rootUrl) { if (rootUrl) {
let { href } = url.parse(rootUrl); let { href } = url.parse(rootUrl)
if (href.substr(href.length - 1, 1) !== '/') { if (href.substr(href.length - 1, 1) !== '/') {
href = href + '/'; href = href + '/'
} }
return href + path; return href + path
} else { } else {
return path; return path
} }
}); })
const getSourceCdnUrl = (tyle, themeConfig, path) => { const getSourceCdnUrl = (tyle, themeConfig, path) => {
const version = require('../../package.json').version; const version = require('../../package.json').version
const { provider = 'jsdelivr' } = themeConfig?.cdn; const { provider = 'jsdelivr' } = themeConfig?.cdn
let urlPrefix = ''; let urlPrefix = ''
switch (provider.toLocaleLowerCase()) { switch (provider.toLocaleLowerCase()) {
case 'jsdelivr': case 'jsdelivr':
urlPrefix = '//cdn.jsdelivr.net/npm/hexo-theme-keep' urlPrefix = '//cdn.jsdelivr.net/npm/hexo-theme-keep'
if (tyle === 'js') { if (tyle === 'js') {
return `<script src="${urlPrefix}@${version}/source/${path}"></script>`; return `<script src="${urlPrefix}@${version}/source/${path}"></script>`
} else { } else {
return `<link rel="stylesheet" href="${urlPrefix}@${version}/source/${path}">`; return `<link rel="stylesheet" href="${urlPrefix}@${version}/source/${path}">`
} }
case 'unpkg': case 'unpkg':
urlPrefix = '//unpkg.com/hexo-theme-keep' urlPrefix = '//unpkg.com/hexo-theme-keep'
if (tyle === 'js') { if (tyle === 'js') {
return `<script src="${urlPrefix}@${version}/source/${path}"></script>`; return `<script src="${urlPrefix}@${version}/source/${path}"></script>`
} else { } else {
return `<link rel="stylesheet" href="${urlPrefix}@${version}/source/${path}">`; return `<link rel="stylesheet" href="${urlPrefix}@${version}/source/${path}">`
} }
} }
} }
hexo.extend.helper.register('__js', function (path) { hexo.extend.helper.register('__js', function (path) {
const { enable } = this.theme.cdn const { enable } = this.theme.cdn
const _js = hexo.extend.helper.get('js').bind(hexo); const _js = hexo.extend.helper.get('js').bind(hexo)
const cdnPathHandle = (pa) => { const cdnPathHandle = (pa) => {
return enable ? getSourceCdnUrl('js', this.theme, pa) : _js(pa); return enable ? getSourceCdnUrl('js', this.theme, pa) : _js(pa)
} }
let t = ``; let t = ``
if (Array.isArray(path)) { if (Array.isArray(path)) {
for (const p of path) { for (const p of path) {
t += cdnPathHandle(p); t += cdnPathHandle(p)
} }
} else { } else {
t = cdnPathHandle(path); t = cdnPathHandle(path)
} }
return t; return t
}); })
hexo.extend.helper.register('__css', function (path) { hexo.extend.helper.register('__css', function (path) {
const { enable } = this.theme.cdn const { enable } = this.theme.cdn
const _css = hexo.extend.helper.get('css').bind(hexo); const _css = hexo.extend.helper.get('css').bind(hexo)
return enable ? getSourceCdnUrl('css', this.theme, path) : _css(path); return enable ? getSourceCdnUrl('css', this.theme, path) : _css(path)
}); })

View File

@ -1,26 +1,21 @@
hexo.on('generateBefore', function () { hexo.on('generateBefore', function () {
if (hexo.locals.get) { if (hexo.locals.get) {
const data = hexo.locals.get('data'); const data = hexo.locals.get('data')
if (data) { if (data) {
// theme config file handle // theme config file handle
if (data._config) { if (data._config) {
hexo.theme.config = data._config; hexo.theme.config = data._config
} else if (data.keep) { } else if (data.keep) {
hexo.theme.config = data.keep; hexo.theme.config = data.keep
} else if (data._keep) { } else if (data._keep) {
hexo.theme.config = data._keep; hexo.theme.config = data._keep
} }
// friends link file handle // friends link file handle
if (data.links || data.link) { if (data.links || data.link) {
hexo.theme.config.links = (data.links || data.link); hexo.theme.config.links = data.links || data.link
}
} }
} }
}); }
})

View File

@ -1,55 +1,52 @@
/* global KEEP */ /* global KEEP */
KEEP.initBack2Top = () => { KEEP.initBack2Top = () => {
KEEP.utils = { KEEP.utils = {
...KEEP.utils, ...KEEP.utils,
back2BottomButton_dom: document.querySelector('.tool-scroll-to-bottom'), back2BottomButton_dom: document.querySelector('.tool-scroll-to-bottom'),
back2top() { back2top() {
const scrollTopTimer = setInterval(function () { const scrollTopTimer = setInterval(function () {
let top = document.body.scrollTop || document.documentElement.scrollTop; let top = document.body.scrollTop || document.documentElement.scrollTop
let speed = top / 2; let speed = top / 2
if (document.body.scrollTop !== 0) { if (document.body.scrollTop !== 0) {
document.body.scrollTop -= speed; document.body.scrollTop -= speed
} else { } else {
document.documentElement.scrollTop -= speed; document.documentElement.scrollTop -= speed
} }
if (top === 0) { if (top === 0) {
clearInterval(scrollTopTimer); clearInterval(scrollTopTimer)
} }
}, 50); }, 50)
}, },
back2Bottom() { back2Bottom() {
let scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight; let scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop; let scrollTop = document.body.scrollTop || document.documentElement.scrollTop
const scrollBottomTimer = setInterval(function () { const scrollBottomTimer = setInterval(function () {
if (!scrollTop) scrollTop = 10; if (!scrollTop) scrollTop = 10
scrollTop = Math.floor(scrollTop + scrollTop / 2); scrollTop = Math.floor(scrollTop + scrollTop / 2)
window.scrollTo(0, scrollTop); window.scrollTo(0, scrollTop)
if (scrollTop >= scrollHeight) { if (scrollTop >= scrollHeight) {
clearInterval(scrollBottomTimer); clearInterval(scrollBottomTimer)
} }
}, 50); }, 50)
}, },
initBack2Top() { initBack2Top() {
this.back2TopButton_dom.addEventListener('click', () => { this.back2TopButton_dom.addEventListener('click', () => {
this.back2top(); this.back2top()
}); })
}, },
initBack2Bottom() { initBack2Bottom() {
this.back2BottomButton_dom.addEventListener('click', () => { this.back2BottomButton_dom.addEventListener('click', () => {
this.back2Bottom(); this.back2Bottom()
}); })
}, }
} }
KEEP.utils.initBack2Top(); KEEP.utils.initBack2Top()
KEEP.utils.initBack2Bottom(); KEEP.utils.initBack2Bottom()
} }

View File

@ -2,25 +2,31 @@
KEEP.initCodeBlockTools = () => { KEEP.initCodeBlockTools = () => {
HTMLElement.prototype.wrap = function (wrapper) { HTMLElement.prototype.wrap = function (wrapper) {
this.parentNode.insertBefore(wrapper, this); this.parentNode.insertBefore(wrapper, this)
this.parentNode.removeChild(this); this.parentNode.removeChild(this)
wrapper.appendChild(this); wrapper.appendChild(this)
}; }
const { style: codeCopyStyle } = KEEP.theme_config?.code_copy; const { style: codeCopyStyle } = KEEP.theme_config?.code_copy
const { style: codeBlockStyle } = KEEP.theme_config?.code_block_tools; const { style: codeBlockStyle } = KEEP.theme_config?.code_block_tools
const isMac = (codeBlockStyle || codeCopyStyle || 'default') === 'mac'; const isMac = (codeBlockStyle || codeCopyStyle || 'default') === 'mac'
const foldedIconClassName = isMac ? 'fas fa-chevron-left' : 'fas fa-chevron-right'; const foldedIconClassName = isMac ? 'fas fa-chevron-left' : 'fas fa-chevron-right'
const { copy: copyLang, copied: copiedLang, fold: foldLang, folded: foldedLang } = KEEP.language_code_block; const {
copy: copyLang,
copied: copiedLang,
fold: foldLang,
folded: foldedLang
} = KEEP.language_code_block
const foldDom = `<span class="tool fold tooltip" data-content="${foldLang}"><i class="fas fa-chevron-down"></i></span>` const foldDom = `<span class="tool fold tooltip" data-content="${foldLang}"><i class="fas fa-chevron-down"></i></span>`
document.querySelectorAll('figure.highlight').forEach(element => { document.querySelectorAll('figure.highlight').forEach((element) => {
let codeLang = element.classList.length ? element.classList[1].toUpperCase() : ''; let codeLang = element.classList.length ? element.classList[1].toUpperCase() : ''
if (codeLang === 'PLAINTEXT') { codeLang = '' } if (codeLang === 'PLAINTEXT') {
const highlightContainer = document.createElement('div'); codeLang = ''
highlightContainer.classList.add('highlight-container'); }
element.wrap(highlightContainer); const highlightContainer = document.createElement('div')
highlightContainer.classList.add('highlight-container')
element.wrap(highlightContainer)
const codeLangDom = `${codeLang ? '<span class="code-lang">' + codeLang + '</span>' : ''}` const codeLangDom = `${codeLang ? '<span class="code-lang">' + codeLang + '</span>' : ''}`
@ -30,72 +36,74 @@ KEEP.initCodeBlockTools = () => {
${isMac ? foldDom + codeLangDom : '<span>' + foldDom + codeLangDom + '</span>'} ${isMac ? foldDom + codeLangDom : '<span>' + foldDom + codeLangDom + '</span>'}
<span class="tool copy tooltip" data-content="${copyLang}"><i class="fas fa-copy"></i></span> <span class="tool copy tooltip" data-content="${copyLang}"><i class="fas fa-copy"></i></span>
</div>` </div>`
); )
const codeToolsBox = element.parentNode.querySelector('.code-tools-box'); const codeToolsBox = element.parentNode.querySelector('.code-tools-box')
const copyDom = codeToolsBox.querySelector('.copy'); const copyDom = codeToolsBox.querySelector('.copy')
const targetFoldDom = codeToolsBox.querySelector('.fold'); const targetFoldDom = codeToolsBox.querySelector('.fold')
copyDom.addEventListener('click', event => { copyDom.addEventListener('click', (event) => {
const target = event.currentTarget; const target = event.currentTarget
const code = [...element.querySelectorAll('.code .line')].map(line => line.innerText).join('\n'); const code = [...element.querySelectorAll('.code .line')]
const tta = document.createElement('textarea'); .map((line) => line.innerText)
tta.style.top = window.scrollY + 'px'; .join('\n')
tta.style.position = 'absolute'; const tta = document.createElement('textarea')
tta.style.opacity = '0'; tta.style.top = window.scrollY + 'px'
tta.readOnly = true; tta.style.position = 'absolute'
tta.value = code; tta.style.opacity = '0'
document.body.append(tta); tta.readOnly = true
const selection = document.getSelection(); tta.value = code
const selected = selection.rangeCount > 0 ? selection.getRangeAt(0) : false; document.body.append(tta)
tta.select(); const selection = document.getSelection()
tta.setSelectionRange(0, code.length); const selected = selection.rangeCount > 0 ? selection.getRangeAt(0) : false
tta.readOnly = false; tta.select()
const result = document.execCommand('copy'); tta.setSelectionRange(0, code.length)
tta.readOnly = false
const result = document.execCommand('copy')
const copyIconDom = target.querySelector('i'); const copyIconDom = target.querySelector('i')
const copyTooltipDom = codeToolsBox.querySelector('.copy .tooltip-content'); const copyTooltipDom = codeToolsBox.querySelector('.copy .tooltip-content')
if (result) { if (result) {
copyIconDom.className = 'fas fa-check'; copyIconDom.className = 'fas fa-check'
copyTooltipDom && (copyTooltipDom.innerHTML = copiedLang); copyTooltipDom && (copyTooltipDom.innerHTML = copiedLang)
} else { } else {
copyIconDom.className = 'fas fa-times'; copyIconDom.className = 'fas fa-times'
} }
tta.blur(); tta.blur()
target.blur(); target.blur()
if (selected) { if (selected) {
selection.removeAllRanges(); selection.removeAllRanges()
selection.addRange(selected); selection.addRange(selected)
} }
document.body.removeChild(tta); document.body.removeChild(tta)
}); })
copyDom.addEventListener('mouseleave', event => { copyDom.addEventListener('mouseleave', (event) => {
setTimeout(() => { setTimeout(() => {
event.target.querySelector('i').className = 'fas fa-copy'; event.target.querySelector('i').className = 'fas fa-copy'
const copyTooltipDom = codeToolsBox.querySelector('.copy .tooltip-content'); const copyTooltipDom = codeToolsBox.querySelector('.copy .tooltip-content')
copyTooltipDom && (copyTooltipDom.innerHTML = copyLang); copyTooltipDom && (copyTooltipDom.innerHTML = copyLang)
}, 500); }, 500)
}); })
let isFold = false let isFold = false
targetFoldDom.addEventListener('click', event => { targetFoldDom.addEventListener('click', (event) => {
const target = event.currentTarget; const target = event.currentTarget
const icon = target.querySelector('i'); const icon = target.querySelector('i')
const foldTooltipDom = codeToolsBox.querySelector('.fold .tooltip-content'); const foldTooltipDom = codeToolsBox.querySelector('.fold .tooltip-content')
isFold = !isFold; isFold = !isFold
if (isFold) { if (isFold) {
icon.className = foldedIconClassName; icon.className = foldedIconClassName
element.classList.add('folded'); element.classList.add('folded')
codeToolsBox.classList.add('folded'); codeToolsBox.classList.add('folded')
foldTooltipDom && (foldTooltipDom.innerHTML = foldedLang) foldTooltipDom && (foldTooltipDom.innerHTML = foldedLang)
} else { } else {
icon.className = 'fas fa-chevron-down'; icon.className = 'fas fa-chevron-down'
element.classList.remove('folded'); element.classList.remove('folded')
codeToolsBox.classList.remove('folded'); codeToolsBox.classList.remove('folded')
foldTooltipDom && (foldTooltipDom.innerHTML = foldLang) foldTooltipDom && (foldTooltipDom.innerHTML = foldLang)
} }
}); })
}); })
} }

View File

@ -1,58 +1,56 @@
/* global KEEP */ /* global KEEP */
KEEP.initModeToggle = () => { KEEP.initModeToggle = () => {
KEEP.utils.modeToggle = { KEEP.utils.modeToggle = {
modeToggleButton_dom: document.querySelector('.tool-dark-light-toggle'), modeToggleButton_dom: document.querySelector('.tool-dark-light-toggle'),
iconDom: document.querySelector('.tool-dark-light-toggle i'), iconDom: document.querySelector('.tool-dark-light-toggle i'),
enableLightMode() { enableLightMode() {
document.body.classList.remove('dark-mode'); document.body.classList.remove('dark-mode')
document.body.classList.add('light-mode'); document.body.classList.add('light-mode')
this.iconDom.className = 'fas fa-moon'; this.iconDom.className = 'fas fa-moon'
KEEP.styleStatus.isDark = false; KEEP.styleStatus.isDark = false
KEEP.setStyleStatus(); KEEP.setStyleStatus()
}, },
enableDarkMode() { enableDarkMode() {
document.body.classList.add('dark-mode'); document.body.classList.add('dark-mode')
document.body.classList.remove('light-mode'); document.body.classList.remove('light-mode')
this.iconDom.className = 'fas fa-sun'; this.iconDom.className = 'fas fa-sun'
KEEP.styleStatus.isDark = true; KEEP.styleStatus.isDark = true
KEEP.setStyleStatus(); KEEP.setStyleStatus()
}, },
isDarkPrefersColorScheme() { isDarkPrefersColorScheme() {
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)'); return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)')
}, },
initModeStatus() { initModeStatus() {
const styleStatus = KEEP.getStyleStatus(); const styleStatus = KEEP.getStyleStatus()
if (styleStatus) { if (styleStatus) {
styleStatus.isDark ? this.enableDarkMode() : this.enableLightMode(); styleStatus.isDark ? this.enableDarkMode() : this.enableLightMode()
} else { } else {
this.isDarkPrefersColorScheme().matches ? this.enableDarkMode() : this.enableLightMode(); this.isDarkPrefersColorScheme().matches ? this.enableDarkMode() : this.enableLightMode()
} }
}, },
initModeToggleButton() { initModeToggleButton() {
this.modeToggleButton_dom.addEventListener('click', () => { this.modeToggleButton_dom.addEventListener('click', () => {
const isDark = document.body.classList.contains('dark-mode'); const isDark = document.body.classList.contains('dark-mode')
isDark ? this.enableLightMode() : this.enableDarkMode(); isDark ? this.enableLightMode() : this.enableDarkMode()
}); })
}, },
initModeAutoTrigger() { initModeAutoTrigger() {
const isDarkMode = this.isDarkPrefersColorScheme(); const isDarkMode = this.isDarkPrefersColorScheme()
isDarkMode.addEventListener('change', e => { isDarkMode.addEventListener('change', (e) => {
e.matches ? this.enableDarkMode() : this.enableLightMode(); e.matches ? this.enableDarkMode() : this.enableLightMode()
}); })
} }
} }
KEEP.utils.modeToggle.initModeStatus(); KEEP.utils.modeToggle.initModeStatus()
KEEP.utils.modeToggle.initModeToggleButton(); KEEP.utils.modeToggle.initModeToggleButton()
KEEP.utils.modeToggle.initModeAutoTrigger(); KEEP.utils.modeToggle.initModeAutoTrigger()
}; }

View File

@ -6,43 +6,45 @@ KEEP.initHeaderShrink = () => {
isHeaderShrink: false, isHeaderShrink: false,
init() { init() {
this.headerHeight = this.headerDom.getBoundingClientRect().height; this.headerHeight = this.headerDom.getBoundingClientRect().height
}, },
headerShrink() { headerShrink() {
const scrollTop = document.body.scrollTop || document.documentElement.scrollTop; const scrollTop = document.body.scrollTop || document.documentElement.scrollTop
const headerWrapperDom = document.querySelector('.header-wrapper'); const headerWrapperDom = document.querySelector('.header-wrapper')
const { enable, header_transparent } = KEEP.theme_config.style.first_screen; const { enable, header_transparent } = KEEP.theme_config.style.first_screen
if (!this.isHeaderShrink && scrollTop > this.headerHeight) { if (!this.isHeaderShrink && scrollTop > this.headerHeight) {
this.isHeaderShrink = true; this.isHeaderShrink = true
document.body.classList.add('header-shrink'); document.body.classList.add('header-shrink')
if (enable === true && header_transparent === true) { if (enable === true && header_transparent === true) {
headerWrapperDom.classList.add('transparent-2'); headerWrapperDom.classList.add('transparent-2')
} }
} else if (this.isHeaderShrink && scrollTop <= this.headerHeight) { } else if (this.isHeaderShrink && scrollTop <= this.headerHeight) {
this.isHeaderShrink = false; this.isHeaderShrink = false
document.body.classList.remove('header-shrink'); document.body.classList.remove('header-shrink')
if (enable === true && header_transparent === true) { if (enable === true && header_transparent === true) {
headerWrapperDom.classList.remove('transparent-2'); headerWrapperDom.classList.remove('transparent-2')
} }
} }
}, },
toggleHeaderDrawerShow() { toggleHeaderDrawerShow() {
const domList = [document.querySelector('.window-mask'), document.querySelector('.menu-bar')]; const domList = [document.querySelector('.window-mask'), document.querySelector('.menu-bar')]
if (KEEP.theme_config.pjax.enable === true) { if (KEEP.theme_config.pjax.enable === true) {
domList.push(...document.querySelectorAll('.header-drawer .drawer-menu-list .drawer-menu-item')); domList.push(
...document.querySelectorAll('.header-drawer .drawer-menu-list .drawer-menu-item')
)
} }
domList.forEach(v => { domList.forEach((v) => {
v.addEventListener('click', () => { v.addEventListener('click', () => {
document.body.classList.toggle('header-drawer-show'); document.body.classList.toggle('header-drawer-show')
}); })
}); })
} }
} }
KEEP.utils.headerShrink.init(); KEEP.utils.headerShrink.init()
KEEP.utils.headerShrink.headerShrink(); KEEP.utils.headerShrink.headerShrink()
KEEP.utils.headerShrink.toggleHeaderDrawerShow(); KEEP.utils.headerShrink.toggleHeaderDrawerShow()
} }

View File

@ -1,43 +1,42 @@
/* global KEEP */ /* global KEEP */
KEEP.initLazyLoad = () => { KEEP.initLazyLoad = () => {
const imgs = document.querySelectorAll('img'); const imgs = document.querySelectorAll('img')
let now = Date.now(); let now = Date.now()
let needLoad = true; let needLoad = true
function lazyload(imgs) { function lazyload(imgs) {
now = Date.now(); now = Date.now()
needLoad = Array.from(imgs).some(i => i.hasAttribute('lazyload')); needLoad = Array.from(imgs).some((i) => i.hasAttribute('lazyload'))
const h = window.innerHeight; const h = window.innerHeight
const s = document.documentElement.scrollTop || document.body.scrollTop; const s = document.documentElement.scrollTop || document.body.scrollTop
imgs.forEach(img => { imgs.forEach((img) => {
if (img.hasAttribute('lazyload') && !img.hasAttribute('loading')) { if (img.hasAttribute('lazyload') && !img.hasAttribute('loading')) {
if (h + s > img.offsetTop) {
if ((h + s) > img.offsetTop) { img.setAttribute('loading', true)
img.setAttribute('loading', true);
const loadImageTimeout = setTimeout(() => { const loadImageTimeout = setTimeout(() => {
const temp = new Image(); const temp = new Image()
const src = img.getAttribute('data-src'); const src = img.getAttribute('data-src')
temp.src = src; temp.src = src
temp.onload = () => { temp.onload = () => {
img.src = src; img.src = src
img.removeAttribute('lazyload'); img.removeAttribute('lazyload')
img.removeAttribute('loading'); img.removeAttribute('loading')
clearTimeout(loadImageTimeout); clearTimeout(loadImageTimeout)
} }
}, 500); }, 500)
} }
} }
}); })
} }
lazyload(imgs); lazyload(imgs)
window.onscroll = () => { window.onscroll = () => {
if (Date.now() - now > 50 && needLoad) { if (Date.now() - now > 50 && needLoad) {
lazyload(imgs); lazyload(imgs)
} }
} }
} }

View File

@ -2,7 +2,6 @@
function initLeftSideToggle() { function initLeftSideToggle() {
KEEP.utils.leftSideToggle = { KEEP.utils.leftSideToggle = {
toggleBar: document.querySelector('.page-aside-toggle'), toggleBar: document.querySelector('.page-aside-toggle'),
pageTopDom: document.querySelector('.page-main-content-top'), pageTopDom: document.querySelector('.page-main-content-top'),
containerDom: document.querySelector('.page-container'), containerDom: document.querySelector('.page-container'),
@ -12,33 +11,35 @@ function initLeftSideToggle() {
isOpenPageAside: false, isOpenPageAside: false,
initToggleBarButton() { initToggleBarButton() {
this.toggleBar && this.toggleBar.addEventListener('click', () => { this.toggleBar &&
this.isOpenPageAside = !this.isOpenPageAside; this.toggleBar.addEventListener('click', () => {
KEEP.styleStatus.isOpenPageAside = this.isOpenPageAside; this.isOpenPageAside = !this.isOpenPageAside
KEEP.setStyleStatus(); KEEP.styleStatus.isOpenPageAside = this.isOpenPageAside
this.changePageLayoutWhenOpenToggle(this.isOpenPageAside); KEEP.setStyleStatus()
}); this.changePageLayoutWhenOpenToggle(this.isOpenPageAside)
})
}, },
changePageLayoutWhenOpenToggle(isOpen) { changePageLayoutWhenOpenToggle(isOpen) {
this.toggleBarIcon && (this.toggleBarIcon.className = isOpen ? 'fas fa-outdent' : 'fas fa-indent'); this.toggleBarIcon &&
const pageAsideWidth = KEEP.theme_config.style.left_side_width || '260px'; (this.toggleBarIcon.className = isOpen ? 'fas fa-outdent' : 'fas fa-indent')
this.containerDom.style.paddingLeft = isOpen ? pageAsideWidth : '0'; const pageAsideWidth = KEEP.theme_config.style.left_side_width || '260px'
this.pageTopDom.style.paddingLeft = isOpen ? pageAsideWidth : '0'; this.containerDom.style.paddingLeft = isOpen ? pageAsideWidth : '0'
this.leftAsideDom.style.left = isOpen ? '0' : `-${pageAsideWidth}`; this.pageTopDom.style.paddingLeft = isOpen ? pageAsideWidth : '0'
this.leftAsideDom.style.left = isOpen ? '0' : `-${pageAsideWidth}`
}, },
pageAsideHandleOfTOC(isOpen) { pageAsideHandleOfTOC(isOpen) {
this.toggleBar.style.display = 'flex'; this.toggleBar.style.display = 'flex'
this.isOpenPageAside = isOpen; this.isOpenPageAside = isOpen
this.changePageLayoutWhenOpenToggle(isOpen); this.changePageLayoutWhenOpenToggle(isOpen)
} }
} }
KEEP.utils.leftSideToggle.initToggleBarButton(); KEEP.utils.leftSideToggle.initToggleBarButton()
} }
if (KEEP.theme_config.pjax.enable === true && KEEP.utils) { if (KEEP.theme_config.pjax.enable === true && KEEP.utils) {
initLeftSideToggle(); initLeftSideToggle()
} else { } else {
window.addEventListener('DOMContentLoaded', initLeftSideToggle); window.addEventListener('DOMContentLoaded', initLeftSideToggle)
} }

View File

@ -1,68 +1,69 @@
KEEP.initLocalSearch = () => { /* global KEEP */
KEEP.initLocalSearch = () => {
// Search DB path // Search DB path
let searchPath = KEEP.hexo_config.path; let searchPath = KEEP.hexo_config.path
if (!searchPath) { if (!searchPath) {
// Search DB path // Search DB path
console.warn('`hexo-generator-searchdb` plugin is not installed!'); console.warn('`hexo-generator-searchdb` plugin is not installed!')
return; return
} }
// Popup Window // Popup Window
let isfetched = false; let isfetched = false
let datas; let datas
let isXml = true; let isXml = true
if (searchPath.length === 0) { if (searchPath.length === 0) {
searchPath = 'search.xml'; searchPath = 'search.xml'
} else if (searchPath.endsWith('json')) { } else if (searchPath.endsWith('json')) {
isXml = false; isXml = false
} }
const searchInputDom = document.querySelector('.search-input'); const searchInputDom = document.querySelector('.search-input')
const resultContent = document.getElementById('search-result'); const resultContent = document.getElementById('search-result')
const getIndexByWord = (word, text, caseSensitive) => { const getIndexByWord = (word, text, caseSensitive) => {
let wordLen = word.length; let wordLen = word.length
if (wordLen === 0) return []; if (wordLen === 0) return []
let startPosition = 0; let startPosition = 0
let position = []; let position = []
let index = []; let index = []
if (!caseSensitive) { if (!caseSensitive) {
text = text.toLowerCase(); text = text.toLowerCase()
word = word.toLowerCase(); word = word.toLowerCase()
} }
while ((position = text.indexOf(word, startPosition)) > -1) { while ((position = text.indexOf(word, startPosition)) > -1) {
index.push({position, word}); index.push({ position, word })
startPosition = position + wordLen; startPosition = position + wordLen
}
return index
} }
return index;
};
// Merge hits into slices // Merge hits into slices
const mergeIntoSlice = (start, end, index, searchText) => { const mergeIntoSlice = (start, end, index, searchText) => {
let item = index[index.length - 1]; let item = index[index.length - 1]
let {position, word} = item; let { position, word } = item
let hits = []; let hits = []
let searchTextCountInSlice = 0; let searchTextCountInSlice = 0
while (position + word.length <= end && index.length !== 0) { while (position + word.length <= end && index.length !== 0) {
if (word === searchText) { if (word === searchText) {
searchTextCountInSlice++; searchTextCountInSlice++
} }
hits.push({ hits.push({
position, position,
length: word.length length: word.length
}); })
let wordEnd = position + word.length; let wordEnd = position + word.length
// Move to next position of hit // Move to next position of hit
index.pop(); index.pop()
while (index.length !== 0) { while (index.length !== 0) {
item = index[index.length - 1]; item = index[index.length - 1]
position = item.position; position = item.position
word = item.word; word = item.word
if (wordEnd > position) { if (wordEnd > position) {
index.pop(); index.pop()
} else { } else {
break; break
} }
} }
} }
@ -71,212 +72,228 @@ KEEP.initLocalSearch = () => {
start, start,
end, end,
searchTextCount: searchTextCountInSlice searchTextCount: searchTextCountInSlice
}; }
}; }
// Highlight title and content // Highlight title and content
const highlightKeyword = (text, slice) => { const highlightKeyword = (text, slice) => {
let result = ''; let result = ''
let prevEnd = slice.start; let prevEnd = slice.start
slice.hits.forEach(hit => { slice.hits.forEach((hit) => {
result += text.substring(prevEnd, hit.position); result += text.substring(prevEnd, hit.position)
let end = hit.position + hit.length; let end = hit.position + hit.length
result += `<b class="search-keyword">${text.substring(hit.position, end)}</b>`; result += `<b class="search-keyword">${text.substring(hit.position, end)}</b>`
prevEnd = end; prevEnd = end
}); })
result += text.substring(prevEnd, slice.end); result += text.substring(prevEnd, slice.end)
return result; return result
}; }
const inputEventFunction = () => { const inputEventFunction = () => {
if (!isfetched) return; if (!isfetched) return
let searchText = searchInputDom.value.trim().toLowerCase(); let searchText = searchInputDom.value.trim().toLowerCase()
let keywords = searchText.split(/[-\s]+/); let keywords = searchText.split(/[-\s]+/)
if (keywords.length > 1) { if (keywords.length > 1) {
keywords.push(searchText); keywords.push(searchText)
} }
let resultItems = []; let resultItems = []
if (searchText.length > 0) { if (searchText.length > 0) {
// Perform local searching // Perform local searching
datas.forEach(({ title, content, url }) => { datas.forEach(({ title, content, url }) => {
let titleInLowerCase = title.toLowerCase(); let titleInLowerCase = title.toLowerCase()
let contentInLowerCase = content.toLowerCase(); let contentInLowerCase = content.toLowerCase()
let indexOfTitle = []; let indexOfTitle = []
let indexOfContent = []; let indexOfContent = []
let searchTextCount = 0; let searchTextCount = 0
keywords.forEach(keyword => { keywords.forEach((keyword) => {
indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false)); indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false))
indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false)); indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false))
}); })
// Show search results // Show search results
if (indexOfTitle.length > 0 || indexOfContent.length > 0) { if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
let hitCount = indexOfTitle.length + indexOfContent.length; let hitCount = indexOfTitle.length + indexOfContent.length
// Sort index by position of keyword // Sort index by position of keyword
[indexOfTitle, indexOfContent].forEach(index => { ;[indexOfTitle, indexOfContent].forEach((index) => {
index.sort((itemLeft, itemRight) => { index.sort((itemLeft, itemRight) => {
if (itemRight.position !== itemLeft.position) { if (itemRight.position !== itemLeft.position) {
return itemRight.position - itemLeft.position; return itemRight.position - itemLeft.position
} }
return itemLeft.word.length - itemRight.word.length; return itemLeft.word.length - itemRight.word.length
}); })
}); })
let slicesOfTitle = []; let slicesOfTitle = []
if (indexOfTitle.length !== 0) { if (indexOfTitle.length !== 0) {
let tmp = mergeIntoSlice(0, title.length, indexOfTitle, searchText); let tmp = mergeIntoSlice(0, title.length, indexOfTitle, searchText)
searchTextCount += tmp.searchTextCountInSlice; searchTextCount += tmp.searchTextCountInSlice
slicesOfTitle.push(tmp); slicesOfTitle.push(tmp)
} }
let slicesOfContent = []; let slicesOfContent = []
while (indexOfContent.length !== 0) { while (indexOfContent.length !== 0) {
let item = indexOfContent[indexOfContent.length - 1]; let item = indexOfContent[indexOfContent.length - 1]
let {position, word} = item; let { position, word } = item
// Cut out 100 characters // Cut out 100 characters
let start = position - 20; let start = position - 20
let end = position + 80; let end = position + 80
if (start < 0) { if (start < 0) {
start = 0; start = 0
} }
if (end < position + word.length) { if (end < position + word.length) {
end = position + word.length; end = position + word.length
} }
if (end > content.length) { if (end > content.length) {
end = content.length; end = content.length
} }
let tmp = mergeIntoSlice(start, end, indexOfContent, searchText); let tmp = mergeIntoSlice(start, end, indexOfContent, searchText)
searchTextCount += tmp.searchTextCountInSlice; searchTextCount += tmp.searchTextCountInSlice
slicesOfContent.push(tmp); slicesOfContent.push(tmp)
} }
// Sort slices in content by search text's count and hits' count // Sort slices in content by search text's count and hits' count
slicesOfContent.sort((sliceLeft, sliceRight) => { slicesOfContent.sort((sliceLeft, sliceRight) => {
if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) { if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
return sliceRight.searchTextCount - sliceLeft.searchTextCount; return sliceRight.searchTextCount - sliceLeft.searchTextCount
} else if (sliceLeft.hits.length !== sliceRight.hits.length) { } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
return sliceRight.hits.length - sliceLeft.hits.length; return sliceRight.hits.length - sliceLeft.hits.length
} }
return sliceLeft.start - sliceRight.start; return sliceLeft.start - sliceRight.start
}); })
// Select top N slices in content // Select top N slices in content
let upperBound = parseInt(KEEP.theme_config.local_search.top_n_per_article ? KEEP.theme_config.local_search.top_n_per_article : 1, 10); let upperBound = parseInt(
KEEP.theme_config.local_search.top_n_per_article
? KEEP.theme_config.local_search.top_n_per_article
: 1,
10
)
if (upperBound >= 0) { if (upperBound >= 0) {
slicesOfContent = slicesOfContent.slice(0, upperBound); slicesOfContent = slicesOfContent.slice(0, upperBound)
} }
let resultItem = ''; let resultItem = ''
if (slicesOfTitle.length !== 0) { if (slicesOfTitle.length !== 0) {
resultItem += `<li><a href="${url}" class="search-result-title">${highlightKeyword(title, slicesOfTitle[0])}</a>`; resultItem += `<li><a href="${url}" class="search-result-title">${highlightKeyword(
title,
slicesOfTitle[0]
)}</a>`
} else { } else {
resultItem += `<li><a href="${url}" class="search-result-title">${title}</a>`; resultItem += `<li><a href="${url}" class="search-result-title">${title}</a>`
} }
slicesOfContent.forEach(slice => { slicesOfContent.forEach((slice) => {
resultItem += `<a href="${url}"><p class="search-result">${highlightKeyword(content, slice)}...</p></a>`; resultItem += `<a href="${url}"><p class="search-result">${highlightKeyword(
}); content,
slice
)}...</p></a>`
})
resultItem += '</li>'; resultItem += '</li>'
resultItems.push({ resultItems.push({
item: resultItem, item: resultItem,
id: resultItems.length, id: resultItems.length,
hitCount, hitCount,
searchTextCount searchTextCount
}); })
} }
}); })
} }
if (keywords.length === 1 && keywords[0] === '') { if (keywords.length === 1 && keywords[0] === '') {
resultContent.innerHTML = '<div id="no-result"><i class="fas fa-search fa-5x"></i></div>'; resultContent.innerHTML = '<div id="no-result"><i class="fas fa-search fa-5x"></i></div>'
} else if (resultItems.length === 0) { } else if (resultItems.length === 0) {
resultContent.innerHTML = '<div id="no-result"><i class="fas fa-box-open fa-5x"></i></div>'; resultContent.innerHTML = '<div id="no-result"><i class="fas fa-box-open fa-5x"></i></div>'
} else { } else {
resultItems.sort((resultLeft, resultRight) => { resultItems.sort((resultLeft, resultRight) => {
if (resultLeft.searchTextCount !== resultRight.searchTextCount) { if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
return resultRight.searchTextCount - resultLeft.searchTextCount; return resultRight.searchTextCount - resultLeft.searchTextCount
} else if (resultLeft.hitCount !== resultRight.hitCount) { } else if (resultLeft.hitCount !== resultRight.hitCount) {
return resultRight.hitCount - resultLeft.hitCount; return resultRight.hitCount - resultLeft.hitCount
}
return resultRight.id - resultLeft.id
})
let searchResultList = '<ul class="search-result-list">'
resultItems.forEach((result) => {
searchResultList += result.item
})
searchResultList += '</ul>'
resultContent.innerHTML = searchResultList
window.pjax && window.pjax.refresh(resultContent)
} }
return resultRight.id - resultLeft.id;
});
let searchResultList = '<ul class="search-result-list">';
resultItems.forEach(result => {
searchResultList += result.item;
});
searchResultList += '</ul>';
resultContent.innerHTML = searchResultList;
window.pjax && window.pjax.refresh(resultContent);
} }
};
const fetchData = () => { const fetchData = () => {
fetch(KEEP.hexo_config.root + searchPath) fetch(KEEP.hexo_config.root + searchPath)
.then(response => response.text()) .then((response) => response.text())
.then(res => { .then((res) => {
// Get the contents from search data // Get the contents from search data
isfetched = true; isfetched = true
datas = isXml ? [...new DOMParser().parseFromString(res, 'text/xml').querySelectorAll('entry')].map(element => { datas = isXml
? [...new DOMParser().parseFromString(res, 'text/xml').querySelectorAll('entry')].map(
(element) => {
return { return {
title: element.querySelector('title').textContent, title: element.querySelector('title').textContent,
content: element.querySelector('content').textContent, content: element.querySelector('content').textContent,
url: element.querySelector('url').textContent url: element.querySelector('url').textContent
}; }
}) : JSON.parse(res); }
)
: JSON.parse(res)
// Only match articles with not empty titles // Only match articles with not empty titles
datas = datas.filter(data => data.title).map(data => { datas = datas
data.title = data.title.trim(); .filter((data) => data.title)
data.content = data.content ? data.content.trim().replace(/<[^>]+>/g, '') : ''; .map((data) => {
data.url = decodeURIComponent(data.url).replace(/\/{2,}/g, '/'); data.title = data.title.trim()
return data; data.content = data.content ? data.content.trim().replace(/<[^>]+>/g, '') : ''
}); data.url = decodeURIComponent(data.url).replace(/\/{2,}/g, '/')
return data
})
// Remove loading animation // Remove loading animation
const noResultDom = document.querySelector('#no-result'); const noResultDom = document.querySelector('#no-result')
noResultDom && (noResultDom.innerHTML = '<i class="fas fa-search fa-5x"></i>'); noResultDom && (noResultDom.innerHTML = '<i class="fas fa-search fa-5x"></i>')
}); })
}; }
if (KEEP.theme_config.local_search.preload) { if (KEEP.theme_config.local_search.preload) {
fetchData(); fetchData()
} }
if (searchInputDom) { if (searchInputDom) {
searchInputDom.addEventListener('input', inputEventFunction); searchInputDom.addEventListener('input', inputEventFunction)
} }
// Handle and trigger popup window // Handle and trigger popup window
document.querySelectorAll('.search-popup-trigger').forEach(element => { document.querySelectorAll('.search-popup-trigger').forEach((element) => {
element.addEventListener('click', () => { element.addEventListener('click', () => {
document.body.style.overflow = 'hidden'; document.body.style.overflow = 'hidden'
document.querySelector('.search-pop-overlay').classList.add('active'); document.querySelector('.search-pop-overlay').classList.add('active')
setTimeout(() => searchInputDom.focus(), 500); setTimeout(() => searchInputDom.focus(), 500)
if (!isfetched) fetchData(); if (!isfetched) fetchData()
}); })
}); })
// Monitor main search box // Monitor main search box
const onPopupClose = () => { const onPopupClose = () => {
document.body.style.overflow = ''; document.body.style.overflow = ''
document.querySelector('.search-pop-overlay').classList.remove('active'); document.querySelector('.search-pop-overlay').classList.remove('active')
}; }
document.querySelector('.search-pop-overlay').addEventListener('click', event => { document.querySelector('.search-pop-overlay').addEventListener('click', (event) => {
if (event.target === document.querySelector('.search-pop-overlay')) { if (event.target === document.querySelector('.search-pop-overlay')) {
onPopupClose(); onPopupClose()
} }
}); })
document.querySelector('.search-input-field-pre').addEventListener('click', () => { document.querySelector('.search-input-field-pre').addEventListener('click', () => {
searchInputDom.value = ''; searchInputDom.value = ''
searchInputDom.focus(); searchInputDom.focus()
inputEventFunction(); inputEventFunction()
}); })
document.querySelector('.close-popup-btn').addEventListener('click', onPopupClose); document.querySelector('.close-popup-btn').addEventListener('click', onPopupClose)
window.addEventListener('pjax:success', onPopupClose); window.addEventListener('pjax:success', onPopupClose)
window.addEventListener('keyup', event => { window.addEventListener('keyup', (event) => {
if (event.key === 'Escape') { if (event.key === 'Escape') {
onPopupClose(); onPopupClose()
} }
}); })
} }

View File

@ -9,7 +9,7 @@ window.addEventListener('DOMContentLoaded', () => {
repository: 'https://github.com/XPoet/hexo-theme-keep' repository: 'https://github.com/XPoet/hexo-theme-keep'
} }
KEEP.localStorageKey = 'KEEP-THEME-STATUS'; KEEP.localStorageKey = 'KEEP-THEME-STATUS'
KEEP.styleStatus = { KEEP.styleStatus = {
isExpandPageWidth: false, isExpandPageWidth: false,
@ -22,48 +22,49 @@ window.addEventListener('DOMContentLoaded', () => {
KEEP.printThemeInfo = () => { KEEP.printThemeInfo = () => {
console.log( console.log(
`\n %c ${KEEP.themeInfo.theme} %c ${KEEP.themeInfo.repository} \n`, `\n %c ${KEEP.themeInfo.theme} %c ${KEEP.themeInfo.repository} \n`,
`color: #fadfa3; background: #333; padding: 6px 0;`, `padding: 6px 0;` `color: #fadfa3; background: #333; padding: 6px 0;`,
); `padding: 6px 0;`
)
} }
// set styleStatus to localStorage // set styleStatus to localStorage
KEEP.setStyleStatus = () => { KEEP.setStyleStatus = () => {
localStorage.setItem(KEEP.localStorageKey, JSON.stringify(KEEP.styleStatus)); localStorage.setItem(KEEP.localStorageKey, JSON.stringify(KEEP.styleStatus))
} }
// get styleStatus from localStorage // get styleStatus from localStorage
KEEP.getStyleStatus = () => { KEEP.getStyleStatus = () => {
let temp = localStorage.getItem(KEEP.localStorageKey); let temp = localStorage.getItem(KEEP.localStorageKey)
if (temp) { if (temp) {
temp = JSON.parse(temp); temp = JSON.parse(temp)
for (let key in KEEP.styleStatus) { for (let key in KEEP.styleStatus) {
KEEP.styleStatus[key] = temp[key]; KEEP.styleStatus[key] = temp[key]
} }
return temp; return temp
} else { } else {
return null; return null
} }
} }
KEEP.refresh = () => { KEEP.refresh = () => {
KEEP.initUtils(); KEEP.initUtils()
KEEP.initHeaderShrink(); KEEP.initHeaderShrink()
KEEP.initModeToggle(); KEEP.initModeToggle()
KEEP.initBack2Top(); KEEP.initBack2Top()
if (local_search?.enable === true) { if (local_search?.enable === true) {
KEEP.initLocalSearch(); KEEP.initLocalSearch()
} }
if (code_block_tools?.enable === true || code_copy?.enable === true) { if (code_block_tools?.enable === true || code_copy?.enable === true) {
KEEP.initCodeBlockTools(); KEEP.initCodeBlockTools()
} }
if (lazyload?.enable === true) { if (lazyload?.enable === true) {
KEEP.initLazyLoad(); KEEP.initLazyLoad()
} }
} }
KEEP.printThemeInfo(); KEEP.printThemeInfo()
KEEP.refresh(); KEEP.refresh()
}); })

View File

@ -1,32 +1,34 @@
/* global KEEP */ /* global KEEP */
function initTOC() { function initTOC() {
KEEP.utils.navItems = document.querySelectorAll('.post-toc-wrap .post-toc li'); KEEP.utils.navItems = document.querySelectorAll('.post-toc-wrap .post-toc li')
if (KEEP.utils.navItems.length > 0) { if (KEEP.utils.navItems.length > 0) {
KEEP.utils = { KEEP.utils = {
...KEEP.utils, ...KEEP.utils,
findActiveIndexByTOC() { findActiveIndexByTOC() {
if (!Array.isArray(KEEP.utils.sections)) return; if (!Array.isArray(KEEP.utils.sections)) return
let index = KEEP.utils.sections.findIndex(element => { let index = KEEP.utils.sections.findIndex((element) => {
return element && element.getBoundingClientRect().top - 20 > 0; return element && element.getBoundingClientRect().top - 20 > 0
}); })
if (index === -1) { if (index === -1) {
index = KEEP.utils.sections.length - 1; index = KEEP.utils.sections.length - 1
} else if (index > 0) { } else if (index > 0) {
index--; index--
} }
this.activateNavByIndex(index); this.activateNavByIndex(index)
}, },
registerSidebarTOC() { registerSidebarTOC() {
KEEP.utils.sections = [...document.querySelectorAll('.post-toc li a.nav-link')].map(element => { KEEP.utils.sections = [...document.querySelectorAll('.post-toc li a.nav-link')].map(
const target = document.getElementById(decodeURI(element.getAttribute('href')).replace('#', '')); (element) => {
element.addEventListener('click', event => { const target = document.getElementById(
event.preventDefault(); decodeURI(element.getAttribute('href')).replace('#', '')
const offset = target.getBoundingClientRect().top + window.scrollY; )
element.addEventListener('click', (event) => {
event.preventDefault()
const offset = target.getBoundingClientRect().top + window.scrollY
window.anime({ window.anime({
targets: document.scrollingElement, targets: document.scrollingElement,
duration: 500, duration: 500,
@ -34,73 +36,76 @@ function initTOC() {
scrollTop: offset - 10, scrollTop: offset - 10,
complete: function () { complete: function () {
setTimeout(() => { setTimeout(() => {
KEEP.utils.pageTop_dom.classList.add('hide'); KEEP.utils.pageTop_dom.classList.add('hide')
}, 100) }, 100)
} }
}); })
}); })
return target; return target
}); }
)
}, },
activateNavByIndex(index) { activateNavByIndex(index) {
const target = document.querySelectorAll('.post-toc li a.nav-link')[index]; const target = document.querySelectorAll('.post-toc li a.nav-link')[index]
if (!target || target.classList.contains('active-current')) return; if (!target || target.classList.contains('active-current')) return
document.querySelectorAll('.post-toc .active').forEach(element => { document.querySelectorAll('.post-toc .active').forEach((element) => {
element.classList.remove('active', 'active-current'); element.classList.remove('active', 'active-current')
}); })
target.classList.add('active', 'active-current'); target.classList.add('active', 'active-current')
let parent = target.parentNode; let parent = target.parentNode
while (!parent.matches('.post-toc')) { while (!parent.matches('.post-toc')) {
if (parent.matches('li')) parent.classList.add('active'); if (parent.matches('li')) parent.classList.add('active')
parent = parent.parentNode; parent = parent.parentNode
} }
// Scrolling to center active TOC element if TOC content is taller then viewport. // Scrolling to center active TOC element if TOC content is taller then viewport.
const tocElement = document.querySelector('.post-toc-wrap'); const tocElement = document.querySelector('.post-toc-wrap')
window.anime({ window.anime({
targets: tocElement, targets: tocElement,
duration: 200, duration: 200,
easing: 'linear', easing: 'linear',
scrollTop: tocElement.scrollTop - (tocElement.offsetHeight / 2) + target.getBoundingClientRect().top - tocElement.getBoundingClientRect().top scrollTop:
}); tocElement.scrollTop -
tocElement.offsetHeight / 2 +
target.getBoundingClientRect().top -
tocElement.getBoundingClientRect().top
})
}, },
showPageAsideWhenHasTOC() { showPageAsideWhenHasTOC() {
const openHandle = () => { const openHandle = () => {
const styleStatus = KEEP.getStyleStatus(); const styleStatus = KEEP.getStyleStatus()
const key = 'isOpenPageAside'; const key = 'isOpenPageAside'
if (styleStatus && styleStatus.hasOwnProperty(key)) { if (styleStatus && styleStatus.hasOwnProperty(key)) {
KEEP.utils.leftSideToggle.pageAsideHandleOfTOC(styleStatus[key]); KEEP.utils.leftSideToggle.pageAsideHandleOfTOC(styleStatus[key])
} else { } else {
KEEP.utils.leftSideToggle.pageAsideHandleOfTOC(true); KEEP.utils.leftSideToggle.pageAsideHandleOfTOC(true)
} }
} }
const initOpenKey = 'init_open'; const initOpenKey = 'init_open'
if (KEEP.theme_config.toc.hasOwnProperty(initOpenKey)) { if (KEEP.theme_config.toc.hasOwnProperty(initOpenKey)) {
KEEP.theme_config.toc[initOpenKey] ? openHandle() : KEEP.utils.leftSideToggle.pageAsideHandleOfTOC(false); KEEP.theme_config.toc[initOpenKey]
? openHandle()
: KEEP.utils.leftSideToggle.pageAsideHandleOfTOC(false)
} else { } else {
openHandle(); openHandle()
} }
} }
} }
KEEP.utils.showPageAsideWhenHasTOC(); KEEP.utils.showPageAsideWhenHasTOC()
KEEP.utils.registerSidebarTOC(); KEEP.utils.registerSidebarTOC()
} else { } else {
const pageAsideDom = document.querySelector('.page-aside'); const pageAsideDom = document.querySelector('.page-aside')
pageAsideDom && KEEP.utils.pageContainer_dom.removeChild(pageAsideDom); pageAsideDom && KEEP.utils.pageContainer_dom.removeChild(pageAsideDom)
} }
} }
if (KEEP.theme_config.pjax.enable === true && KEEP.utils) { if (KEEP.theme_config.pjax.enable === true && KEEP.utils) {
initTOC(); initTOC()
} else { } else {
window.addEventListener('DOMContentLoaded', initTOC); window.addEventListener('DOMContentLoaded', initTOC)
} }

View File

@ -1,7 +1,6 @@
/* global KEEP */ /* global KEEP */
KEEP.initUtils = () => { KEEP.initUtils = () => {
KEEP.utils = { KEEP.utils = {
html_root_dom: document.querySelector('html'), html_root_dom: document.querySelector('html'),
pageContainer_dom: document.querySelector('.page-container'), pageContainer_dom: document.querySelector('.page-container'),
@ -22,56 +21,55 @@ KEEP.initUtils = () => {
isHeaderTransparent: false, isHeaderTransparent: false,
initData() { initData() {
const { scroll, first_screen } = KEEP.theme_config.style; const { scroll, first_screen } = KEEP.theme_config.style
this.isHasScrollProgressBar = scroll.progress_bar.enable === true; this.isHasScrollProgressBar = scroll.progress_bar.enable === true
this.isHasScrollPercent = scroll.percent.enable === true; this.isHasScrollPercent = scroll.percent.enable === true
const { enable, header_transparent } = first_screen; const { enable, header_transparent } = first_screen
this.isHeaderTransparent = enable === true && header_transparent === true; this.isHeaderTransparent = enable === true && header_transparent === true
}, },
// Scroll Style Handle // Scroll Style Handle
styleHandleWhenScroll() { styleHandleWhenScroll() {
const scrollTop = document.body.scrollTop || document.documentElement.scrollTop; const scrollTop = document.body.scrollTop || document.documentElement.scrollTop
const scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight; const scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight
const clientHeight = window.innerHeight || document.documentElement.clientHeight; const clientHeight = window.innerHeight || document.documentElement.clientHeight
const percent = Math.round(scrollTop / (scrollHeight - clientHeight) * 100); const percent = Math.round((scrollTop / (scrollHeight - clientHeight)) * 100)
if (this.isHasScrollProgressBar) { if (this.isHasScrollProgressBar) {
const ProgressPercent = (scrollTop / (scrollHeight - clientHeight) * 100).toFixed(3); const ProgressPercent = ((scrollTop / (scrollHeight - clientHeight)) * 100).toFixed(3)
this.scrollProgressBar_dom.style.visibility = percent === 0 ? 'hidden' : 'visible'; this.scrollProgressBar_dom.style.visibility = percent === 0 ? 'hidden' : 'visible'
this.scrollProgressBar_dom.style.width = `${ProgressPercent}%`; this.scrollProgressBar_dom.style.width = `${ProgressPercent}%`
} }
if (this.isHasScrollPercent) { if (this.isHasScrollPercent) {
const percent_dom = this.back2TopButton_dom.querySelector('.percent'); const percent_dom = this.back2TopButton_dom.querySelector('.percent')
if (percent === 0 || percent === undefined) { if (percent === 0 || percent === undefined) {
this.back2TopButton_dom.classList.remove('show'); this.back2TopButton_dom.classList.remove('show')
} else { } else {
this.back2TopButton_dom.classList.add('show'); this.back2TopButton_dom.classList.add('show')
percent_dom.innerHTML = percent.toFixed(0); percent_dom.innerHTML = percent.toFixed(0)
} }
} }
// hide header handle // hide header handle
if (scrollTop > this.prevScrollValue && scrollTop > this.innerHeight) { if (scrollTop > this.prevScrollValue && scrollTop > this.innerHeight) {
this.pageTop_dom.classList.add('hide'); this.pageTop_dom.classList.add('hide')
if (this.isHeaderTransparent) { if (this.isHeaderTransparent) {
this.headerWrapper_dom.classList.remove('transparent-1', 'transparent-2'); this.headerWrapper_dom.classList.remove('transparent-1', 'transparent-2')
} }
} else { } else {
this.pageTop_dom.classList.remove('hide'); this.pageTop_dom.classList.remove('hide')
if (this.isHeaderTransparent) { if (this.isHeaderTransparent) {
if (scrollTop <= this.headerWrapper_dom.getBoundingClientRect().height) { if (scrollTop <= this.headerWrapper_dom.getBoundingClientRect().height) {
this.headerWrapper_dom.classList.remove('transparent-2'); this.headerWrapper_dom.classList.remove('transparent-2')
this.headerWrapper_dom.classList.add('transparent-1'); this.headerWrapper_dom.classList.add('transparent-1')
} else if (scrollTop < this.innerHeight) { } else if (scrollTop < this.innerHeight) {
this.headerWrapper_dom.classList.add('transparent-2'); this.headerWrapper_dom.classList.add('transparent-2')
} }
} }
} }
this.prevScrollValue = scrollTop; this.prevScrollValue = scrollTop
}, },
// register window scroll event // register window scroll event
@ -79,182 +77,183 @@ KEEP.initUtils = () => {
window.addEventListener('scroll', () => { window.addEventListener('scroll', () => {
// style handle when scroll // style handle when scroll
if (this.isHasScrollPercent || this.isHasScrollProgressBar) { if (this.isHasScrollPercent || this.isHasScrollProgressBar) {
this.styleHandleWhenScroll(); this.styleHandleWhenScroll()
} }
// TOC scroll handle // TOC scroll handle
if (KEEP.theme_config.toc.enable && KEEP.utils.hasOwnProperty('findActiveIndexByTOC')) { if (KEEP.theme_config.toc.enable && KEEP.utils.hasOwnProperty('findActiveIndexByTOC')) {
KEEP.utils.findActiveIndexByTOC(); KEEP.utils.findActiveIndexByTOC()
} }
// header shrink // header shrink
KEEP.utils.headerShrink.headerShrink(); KEEP.utils.headerShrink.headerShrink()
}); })
}, },
// toggle show tools list // toggle show tools list
toggleShowToolsList() { toggleShowToolsList() {
document.querySelector('.tool-toggle-show').addEventListener('click', () => { document.querySelector('.tool-toggle-show').addEventListener('click', () => {
document.querySelector('.side-tools-list').classList.toggle('show'); document.querySelector('.side-tools-list').classList.toggle('show')
}); })
}, },
// global font adjust // global font adjust
globalFontAdjust() { globalFontAdjust() {
const fontSize = document.defaultView.getComputedStyle(document.body).fontSize; const fontSize = document.defaultView.getComputedStyle(document.body).fontSize
const fs = parseFloat(fontSize); const fs = parseFloat(fontSize)
const initFontSize = () => { const initFontSize = () => {
const styleStatus = KEEP.getStyleStatus(); const styleStatus = KEEP.getStyleStatus()
if (styleStatus) { if (styleStatus) {
this.fontSizeLevel = styleStatus.fontSizeLevel; this.fontSizeLevel = styleStatus.fontSizeLevel
setFontSize(this.fontSizeLevel); setFontSize(this.fontSizeLevel)
} }
} }
const setFontSize = (fontSizeLevel) => { const setFontSize = (fontSizeLevel) => {
this.html_root_dom.style.fontSize = `${fs * (1 + fontSizeLevel * 0.05)}px`; this.html_root_dom.style.fontSize = `${fs * (1 + fontSizeLevel * 0.05)}px`
KEEP.styleStatus.fontSizeLevel = fontSizeLevel; KEEP.styleStatus.fontSizeLevel = fontSizeLevel
KEEP.setStyleStatus(); KEEP.setStyleStatus()
} }
initFontSize(); initFontSize()
document.querySelector('.tool-font-adjust-plus').addEventListener('click', () => { document.querySelector('.tool-font-adjust-plus').addEventListener('click', () => {
if (this.fontSizeLevel === 5) return; if (this.fontSizeLevel === 5) return
this.fontSizeLevel++; this.fontSizeLevel++
setFontSize(this.fontSizeLevel); setFontSize(this.fontSizeLevel)
}); })
document.querySelector('.tool-font-adjust-minus').addEventListener('click', () => { document.querySelector('.tool-font-adjust-minus').addEventListener('click', () => {
if (this.fontSizeLevel <= 0) return; if (this.fontSizeLevel <= 0) return
this.fontSizeLevel--; this.fontSizeLevel--
setFontSize(this.fontSizeLevel); setFontSize(this.fontSizeLevel)
}); })
}, },
// toggle content area width // toggle content area width
contentAreaWidthAdjust() { contentAreaWidthAdjust() {
const toolExpandDom = document.querySelector('.tool-expand-width'); const toolExpandDom = document.querySelector('.tool-expand-width')
const headerContentDom = document.querySelector('.header-content'); const headerContentDom = document.querySelector('.header-content')
const mainContentDom = document.querySelector('.main-content'); const mainContentDom = document.querySelector('.main-content')
const iconDom = toolExpandDom.querySelector('i'); const iconDom = toolExpandDom.querySelector('i')
const defaultMaxWidth = KEEP.theme_config.style.content_max_width || '1000px'; const defaultMaxWidth = KEEP.theme_config.style.content_max_width || '1000px'
const expandMaxWidth = '90%'; const expandMaxWidth = '90%'
let headerMaxWidth = defaultMaxWidth; let headerMaxWidth = defaultMaxWidth
let isExpand = false; let isExpand = false
if (KEEP.theme_config.style.first_screen.enable === true && window.location.pathname === '/') { if (
headerMaxWidth = parseInt(defaultMaxWidth) * 1.2 + 'px'; KEEP.theme_config.style.first_screen.enable === true &&
window.location.pathname === '/'
) {
headerMaxWidth = parseInt(defaultMaxWidth) * 1.2 + 'px'
} }
const setPageWidth = (isExpand) => { const setPageWidth = (isExpand) => {
KEEP.styleStatus.isExpandPageWidth = isExpand; KEEP.styleStatus.isExpandPageWidth = isExpand
KEEP.setStyleStatus(); KEEP.setStyleStatus()
if (isExpand) { if (isExpand) {
iconDom.classList.remove('fa-up-right-and-down-left-from-center'); iconDom.classList.remove('fa-up-right-and-down-left-from-center')
iconDom.classList.add('fa-down-left-and-up-right-to-center'); iconDom.classList.add('fa-down-left-and-up-right-to-center')
headerContentDom.style.maxWidth = expandMaxWidth; headerContentDom.style.maxWidth = expandMaxWidth
mainContentDom.style.maxWidth = expandMaxWidth; mainContentDom.style.maxWidth = expandMaxWidth
} else { } else {
iconDom.classList.remove('fa-down-left-and-up-right-to-center'); iconDom.classList.remove('fa-down-left-and-up-right-to-center')
iconDom.classList.add('fa-up-right-and-down-left-from-center'); iconDom.classList.add('fa-up-right-and-down-left-from-center')
headerContentDom.style.maxWidth = headerMaxWidth; headerContentDom.style.maxWidth = headerMaxWidth
mainContentDom.style.maxWidth = defaultMaxWidth; mainContentDom.style.maxWidth = defaultMaxWidth
} }
} }
const initPageWidth = () => { const initPageWidth = () => {
const styleStatus = KEEP.getStyleStatus(); const styleStatus = KEEP.getStyleStatus()
if (styleStatus) { if (styleStatus) {
isExpand = styleStatus.isExpandPageWidth; isExpand = styleStatus.isExpandPageWidth
setPageWidth(isExpand); setPageWidth(isExpand)
} }
} }
initPageWidth(); initPageWidth()
toolExpandDom.addEventListener('click', () => { toolExpandDom.addEventListener('click', () => {
isExpand = !isExpand; isExpand = !isExpand
setPageWidth(isExpand) setPageWidth(isExpand)
}); })
}, },
// go comment anchor // go comment anchor
goComment() { goComment() {
this.goComment_dom = document.querySelector('.go-comment'); this.goComment_dom = document.querySelector('.go-comment')
if (this.goComment_dom) { if (this.goComment_dom) {
this.goComment_dom.addEventListener('click', () => { this.goComment_dom.addEventListener('click', () => {
document.querySelector('#comment-anchor').scrollIntoView(); document.querySelector('#comment-anchor').scrollIntoView()
}); })
} }
}, },
// get dom element height // get dom element height
getElementHeight(selectors) { getElementHeight(selectors) {
const dom = document.querySelector(selectors); const dom = document.querySelector(selectors)
return dom ? dom.getBoundingClientRect().height : 0; return dom ? dom.getBoundingClientRect().height : 0
}, },
// init first screen height // init first screen height
initFirstScreenHeight() { initFirstScreenHeight() {
this.firstScreen_dom && (this.firstScreen_dom.style.height = this.innerHeight + 'px'); this.firstScreen_dom && (this.firstScreen_dom.style.height = this.innerHeight + 'px')
}, },
// init page height handle // init page height handle
initPageHeightHandle() { initPageHeightHandle() {
if (this.firstScreen_dom) return; if (this.firstScreen_dom) return
const temp_h1 = this.getElementHeight('.page-main-content-top'); const temp_h1 = this.getElementHeight('.page-main-content-top')
const temp_h2 = this.getElementHeight('.page-main-content-middle'); const temp_h2 = this.getElementHeight('.page-main-content-middle')
const temp_h3 = this.getElementHeight('.page-main-content-bottom'); const temp_h3 = this.getElementHeight('.page-main-content-bottom')
const allDomHeight = temp_h1 + temp_h2 + temp_h3; const allDomHeight = temp_h1 + temp_h2 + temp_h3
const innerHeight = window.innerHeight; const innerHeight = window.innerHeight
const pb_dom = document.querySelector('.page-main-content-bottom'); const pb_dom = document.querySelector('.page-main-content-bottom')
if (allDomHeight < innerHeight) { if (allDomHeight < innerHeight) {
const marginTopValue = Math.floor(innerHeight - allDomHeight); const marginTopValue = Math.floor(innerHeight - allDomHeight)
if (marginTopValue > 0) { if (marginTopValue > 0) {
pb_dom.style.marginTop = `${marginTopValue - 2}px`; pb_dom.style.marginTop = `${marginTopValue - 2}px`
} }
} }
}, },
// big image viewer // big image viewer
imageViewer() { imageViewer() {
let isBigImage = false; let isBigImage = false
const showHandle = (maskDom, isShow) => { const showHandle = (maskDom, isShow) => {
document.body.style.overflow = isShow ? 'hidden' : 'auto'; document.body.style.overflow = isShow ? 'hidden' : 'auto'
if (isShow) { if (isShow) {
maskDom.classList.add('active'); maskDom.classList.add('active')
} else { } else {
maskDom.classList.remove('active'); maskDom.classList.remove('active')
} }
} }
const imageViewerDom = document.querySelector('.image-viewer-container'); const imageViewerDom = document.querySelector('.image-viewer-container')
const targetImg = document.querySelector('.image-viewer-container img'); const targetImg = document.querySelector('.image-viewer-container img')
imageViewerDom && imageViewerDom.addEventListener('click', () => { imageViewerDom &&
isBigImage = false; imageViewerDom.addEventListener('click', () => {
showHandle(imageViewerDom, isBigImage); isBigImage = false
}); showHandle(imageViewerDom, isBigImage)
})
const imgDoms = document.querySelectorAll('.markdown-body img'); const imgDoms = document.querySelectorAll('.markdown-body img')
if (imgDoms.length) { if (imgDoms.length) {
imgDoms.forEach(img => { imgDoms.forEach((img) => {
img.addEventListener('click', () => { img.addEventListener('click', () => {
isBigImage = true; isBigImage = true
showHandle(imageViewerDom, isBigImage); showHandle(imageViewerDom, isBigImage)
targetImg.setAttribute('src', img.getAttribute('src')); targetImg.setAttribute('src', img.getAttribute('src'))
}); })
}); })
} else { } else {
this.pageContainer_dom.removeChild(imageViewerDom); this.pageContainer_dom.removeChild(imageViewerDom)
} }
}, },
@ -264,140 +263,134 @@ KEEP.initUtils = () => {
}, },
getHowLongAgo(timestamp) { getHowLongAgo(timestamp) {
const lang = KEEP.language_ago; const lang = KEEP.language_ago
const __Y = Math.floor(timestamp / (60 * 60 * 24 * 30) / 12); const __Y = Math.floor(timestamp / (60 * 60 * 24 * 30) / 12)
const __M = Math.floor(timestamp / (60 * 60 * 24 * 30)); const __M = Math.floor(timestamp / (60 * 60 * 24 * 30))
const __W = Math.floor(timestamp / (60 * 60 * 24) / 7); const __W = Math.floor(timestamp / (60 * 60 * 24) / 7)
const __d = Math.floor(timestamp / (60 * 60 * 24)); const __d = Math.floor(timestamp / (60 * 60 * 24))
const __h = Math.floor(timestamp / (60 * 60) % 24); const __h = Math.floor((timestamp / (60 * 60)) % 24)
const __m = Math.floor(timestamp / 60 % 60); const __m = Math.floor((timestamp / 60) % 60)
const __s = Math.floor(timestamp % 60); const __s = Math.floor(timestamp % 60)
if (__Y > 0) { if (__Y > 0) {
return this.setHowLongAgoLanguage(__Y, lang.year); return this.setHowLongAgoLanguage(__Y, lang.year)
} else if (__M > 0) { } else if (__M > 0) {
return this.setHowLongAgoLanguage(__M, lang.month); return this.setHowLongAgoLanguage(__M, lang.month)
} else if (__W > 0) { } else if (__W > 0) {
return this.setHowLongAgoLanguage(__W, lang.week); return this.setHowLongAgoLanguage(__W, lang.week)
} else if (__d > 0) { } else if (__d > 0) {
return this.setHowLongAgoLanguage(__d, lang.day); return this.setHowLongAgoLanguage(__d, lang.day)
} else if (__h > 0) { } else if (__h > 0) {
return this.setHowLongAgoLanguage(__h, lang.hour); return this.setHowLongAgoLanguage(__h, lang.hour)
} else if (__m > 0) { } else if (__m > 0) {
return this.setHowLongAgoLanguage(__m, lang.minute); return this.setHowLongAgoLanguage(__m, lang.minute)
} else if (__s > 0) { } else if (__s > 0) {
return this.setHowLongAgoLanguage(__s, lang.second); return this.setHowLongAgoLanguage(__s, lang.second)
} }
}, },
setHowLongAgoInHome() { setHowLongAgoInHome() {
const post = document.querySelectorAll('.home-article-meta-info .home-article-date'); const post = document.querySelectorAll('.home-article-meta-info .home-article-date')
post && post.forEach(v => { post &&
const nowDate = Date.now(); post.forEach((v) => {
const postDate = new Date(v.dataset.date.split(' GMT')[0]).getTime(); const nowDate = Date.now()
v.innerHTML = this.getHowLongAgo(Math.floor((nowDate - postDate) / 1000)); const postDate = new Date(v.dataset.date.split(' GMT')[0]).getTime()
}); v.innerHTML = this.getHowLongAgo(Math.floor((nowDate - postDate) / 1000))
})
}, },
// loading progress bar start // loading progress bar start
pjaxProgressBarStart() { pjaxProgressBarStart() {
this.pjaxProgressBarTimer && clearInterval(this.pjaxProgressBarTimer); this.pjaxProgressBarTimer && clearInterval(this.pjaxProgressBarTimer)
if (this.isHasScrollProgressBar) { if (this.isHasScrollProgressBar) {
this.scrollProgressBar_dom.classList.add('hide'); this.scrollProgressBar_dom.classList.add('hide')
} }
this.pjaxProgressBar_dom.style.width = '0'; this.pjaxProgressBar_dom.style.width = '0'
this.pjaxProgressIcon_dom.classList.add('show'); this.pjaxProgressIcon_dom.classList.add('show')
let width = 1; let width = 1
const maxWidth = 99; const maxWidth = 99
this.pjaxProgressBar_dom.classList.add('show'); this.pjaxProgressBar_dom.classList.add('show')
this.pjaxProgressBar_dom.style.width = width + '%'; this.pjaxProgressBar_dom.style.width = width + '%'
this.pjaxProgressBarTimer = setInterval(() => { this.pjaxProgressBarTimer = setInterval(() => {
width += 5; width += 5
if (width > maxWidth) width = maxWidth; if (width > maxWidth) width = maxWidth
this.pjaxProgressBar_dom.style.width = width + '%'; this.pjaxProgressBar_dom.style.width = width + '%'
}, 100); }, 100)
}, },
// loading progress bar end // loading progress bar end
pjaxProgressBarEnd() { pjaxProgressBarEnd() {
this.pjaxProgressBarTimer && clearInterval(this.pjaxProgressBarTimer); this.pjaxProgressBarTimer && clearInterval(this.pjaxProgressBarTimer)
this.pjaxProgressBar_dom.style.width = '100%'; this.pjaxProgressBar_dom.style.width = '100%'
const temp_1 = setTimeout(() => { const temp_1 = setTimeout(() => {
this.pjaxProgressBar_dom.classList.remove('show'); this.pjaxProgressBar_dom.classList.remove('show')
this.pjaxProgressIcon_dom.classList.remove('show'); this.pjaxProgressIcon_dom.classList.remove('show')
if (this.isHasScrollProgressBar) { if (this.isHasScrollProgressBar) {
this.scrollProgressBar_dom.classList.remove('hide'); this.scrollProgressBar_dom.classList.remove('hide')
} }
const temp_2 = setTimeout(() => { const temp_2 = setTimeout(() => {
this.pjaxProgressBar_dom.style.width = '0'; this.pjaxProgressBar_dom.style.width = '0'
clearTimeout(temp_1), clearTimeout(temp_2); clearTimeout(temp_1), clearTimeout(temp_2)
}, 200); }, 200)
}, 200)
}, 200);
}, },
// insert tooltip content dom // insert tooltip content dom
insertTooltipContent() { insertTooltipContent() {
const init = () => { const init = () => {
document.querySelectorAll('.tooltip').forEach(element => { document.querySelectorAll('.tooltip').forEach((element) => {
const { content } = element.dataset; const { content } = element.dataset
if (content) { if (content) {
element.insertAdjacentHTML( element.insertAdjacentHTML(
'afterbegin', 'afterbegin',
`<span class="tooltip-content">${content}</span>` `<span class="tooltip-content">${content}</span>`
); )
} }
}); })
} }
setTimeout(() => { setTimeout(() => {
init(); init()
}, 1000); }, 1000)
} }
} }
// init data // init data
KEEP.utils.initData(); KEEP.utils.initData()
// init scroll // init scroll
KEEP.utils.registerWindowScroll(); KEEP.utils.registerWindowScroll()
// toggle show tools list // toggle show tools list
KEEP.utils.toggleShowToolsList(); KEEP.utils.toggleShowToolsList()
// global font adjust // global font adjust
KEEP.utils.globalFontAdjust(); KEEP.utils.globalFontAdjust()
// adjust content area width // adjust content area width
KEEP.utils.contentAreaWidthAdjust(); KEEP.utils.contentAreaWidthAdjust()
// go comment // go comment
KEEP.utils.goComment(); KEEP.utils.goComment()
// init page height handle // init page height handle
KEEP.utils.initPageHeightHandle(); KEEP.utils.initPageHeightHandle()
// init first screen height // init first screen height
KEEP.utils.initFirstScreenHeight(); KEEP.utils.initFirstScreenHeight()
// big image viewer handle // big image viewer handle
KEEP.utils.imageViewer(); KEEP.utils.imageViewer()
// set how long age in home article block // set how long age in home article block
KEEP.utils.setHowLongAgoInHome(); KEEP.utils.setHowLongAgoInHome()
// insert tooltip content dom // insert tooltip content dom
KEEP.utils.insertTooltipContent(); KEEP.utils.insertTooltipContent()
} }