You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
5.9 KiB
184 lines
5.9 KiB
9 months ago
|
/**
|
||
|
* Butterfly
|
||
|
* inject js to head
|
||
|
*/
|
||
|
|
||
|
'use strict'
|
||
|
|
||
|
hexo.extend.helper.register('inject_head_js', function () {
|
||
|
const { darkmode, aside } = this.theme
|
||
|
const start = darkmode.start || 6
|
||
|
const end = darkmode.end || 18
|
||
|
const { theme_color } = hexo.theme.config
|
||
|
const themeColorLight = (theme_color && theme_color.enable && theme_color.meta_theme_color_light) || '#ffffff'
|
||
|
const themeColorDark = (theme_color && theme_color.enable && theme_color.meta_theme_color_dark) || '#0d0d0d'
|
||
|
|
||
|
const createLocalStore = () => {
|
||
|
return `
|
||
|
win.saveToLocal = {
|
||
|
set: (key, value, ttl) => {
|
||
|
if (ttl === 0) return
|
||
|
const now = Date.now()
|
||
|
const expiry = now + ttl * 86400000
|
||
|
const item = {
|
||
|
value,
|
||
|
expiry
|
||
|
}
|
||
|
localStorage.setItem(key, JSON.stringify(item))
|
||
|
},
|
||
|
|
||
|
get: key => {
|
||
|
const itemStr = localStorage.getItem(key)
|
||
|
|
||
|
if (!itemStr) {
|
||
|
return undefined
|
||
|
}
|
||
|
const item = JSON.parse(itemStr)
|
||
|
const now = Date.now()
|
||
|
|
||
|
if (now > item.expiry) {
|
||
|
localStorage.removeItem(key)
|
||
|
return undefined
|
||
|
}
|
||
|
return item.value
|
||
|
}
|
||
|
}
|
||
|
`
|
||
|
}
|
||
|
|
||
|
// https://stackoverflow.com/questions/16839698/jquery-getscript-alternative-in-native-javascript
|
||
|
const createGetScript = () => {
|
||
|
return `
|
||
|
win.getScript = (url, attr = {}) => new Promise((resolve, reject) => {
|
||
|
const script = document.createElement('script')
|
||
|
script.src = url
|
||
|
script.async = true
|
||
|
script.onerror = reject
|
||
|
script.onload = script.onreadystatechange = function() {
|
||
|
const loadState = this.readyState
|
||
|
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
|
||
|
script.onload = script.onreadystatechange = null
|
||
|
resolve()
|
||
|
}
|
||
|
|
||
|
Object.keys(attr).forEach(key => {
|
||
|
script.setAttribute(key, attr[key])
|
||
|
})
|
||
|
|
||
|
document.head.appendChild(script)
|
||
|
})
|
||
|
`
|
||
|
}
|
||
|
|
||
|
const createGetCSS = () => {
|
||
|
return `
|
||
|
win.getCSS = (url, id = false) => new Promise((resolve, reject) => {
|
||
|
const link = document.createElement('link')
|
||
|
link.rel = 'stylesheet'
|
||
|
link.href = url
|
||
|
if (id) link.id = id
|
||
|
link.onerror = reject
|
||
|
link.onload = link.onreadystatechange = function() {
|
||
|
const loadState = this.readyState
|
||
|
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
|
||
|
link.onload = link.onreadystatechange = null
|
||
|
resolve()
|
||
|
}
|
||
|
document.head.appendChild(link)
|
||
|
})
|
||
|
`
|
||
|
}
|
||
|
|
||
|
const createDarkmodeJs = () => {
|
||
|
if (!darkmode.enable) return ''
|
||
|
|
||
|
let darkmodeJs = `
|
||
|
win.activateDarkMode = () => {
|
||
|
document.documentElement.setAttribute('data-theme', 'dark')
|
||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '${themeColorDark}')
|
||
|
}
|
||
|
}
|
||
|
win.activateLightMode = () => {
|
||
|
document.documentElement.setAttribute('data-theme', 'light')
|
||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '${themeColorLight}')
|
||
|
}
|
||
|
}
|
||
|
const t = saveToLocal.get('theme')
|
||
|
`
|
||
|
|
||
|
const autoChangeMode = darkmode.autoChangeMode
|
||
|
|
||
|
if (autoChangeMode === 1) {
|
||
|
darkmodeJs += `
|
||
|
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||
|
const isLightMode = window.matchMedia('(prefers-color-scheme: light)').matches
|
||
|
const isNotSpecified = window.matchMedia('(prefers-color-scheme: no-preference)').matches
|
||
|
const hasNoSupport = !isDarkMode && !isLightMode && !isNotSpecified
|
||
|
|
||
|
if (t === undefined) {
|
||
|
if (isLightMode) activateLightMode()
|
||
|
else if (isDarkMode) activateDarkMode()
|
||
|
else if (isNotSpecified || hasNoSupport) {
|
||
|
const now = new Date()
|
||
|
const hour = now.getHours()
|
||
|
const isNight = hour <= ${start} || hour >= ${end}
|
||
|
isNight ? activateDarkMode() : activateLightMode()
|
||
|
}
|
||
|
window.matchMedia('(prefers-color-scheme: dark)').addListener(e => {
|
||
|
if (saveToLocal.get('theme') === undefined) {
|
||
|
e.matches ? activateDarkMode() : activateLightMode()
|
||
|
}
|
||
|
})
|
||
|
} else if (t === 'light') activateLightMode()
|
||
|
else activateDarkMode()
|
||
|
`
|
||
|
} else if (autoChangeMode === 2) {
|
||
|
darkmodeJs += `
|
||
|
const now = new Date()
|
||
|
const hour = now.getHours()
|
||
|
const isNight = hour <= ${start} || hour >= ${end}
|
||
|
if (t === undefined) isNight ? activateDarkMode() : activateLightMode()
|
||
|
else if (t === 'light') activateLightMode()
|
||
|
else activateDarkMode()
|
||
|
`
|
||
|
} else {
|
||
|
darkmodeJs += `
|
||
|
if (t === 'dark') activateDarkMode()
|
||
|
else if (t === 'light') activateLightMode()
|
||
|
`
|
||
|
}
|
||
|
|
||
|
return darkmodeJs
|
||
|
}
|
||
|
|
||
|
const createAsideStatus = () => {
|
||
|
if (!aside.enable || !aside.button) return ''
|
||
|
|
||
|
return `
|
||
|
const asideStatus = saveToLocal.get('aside-status')
|
||
|
if (asideStatus !== undefined) {
|
||
|
if (asideStatus === 'hide') {
|
||
|
document.documentElement.classList.add('hide-aside')
|
||
|
} else {
|
||
|
document.documentElement.classList.remove('hide-aside')
|
||
|
}
|
||
|
}
|
||
|
`
|
||
|
}
|
||
|
|
||
|
const createDetectApple = () => {
|
||
|
return `
|
||
|
const detectApple = () => {
|
||
|
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
|
||
|
document.documentElement.classList.add('apple')
|
||
|
}
|
||
|
}
|
||
|
detectApple()
|
||
|
`
|
||
|
}
|
||
|
|
||
|
return `<script>(win=>{${createLocalStore() + createGetScript() + createGetCSS() + createDarkmodeJs() + createAsideStatus() + createDetectApple()}})(window)</script>`
|
||
|
})
|