Site updated: 2024-06-02 22:03:12
This commit is contained in:
parent
71e1d6c0a3
commit
1a17cf173a
163
about/index.html
Normal file
163
about/index.html
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>关于SharwOrange橙夜 | SharwOrangeのBlog小屋</title><meta name="author" content="SharwOrange"><meta name="copyright" content="SharwOrange"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="个人介绍是树叶Leafлистья的服主也是一名B站UP主还是某个不知名小工作室(希望在即HopeNow)的创始人(官方吐槽: B工作室屁用没有那种 ( ̄ ‘i  ̄;)平时爱搞一些技术类的东西有DN42,可与我Peer,发邮件给我 头像下面有邮件的链接 (如果无法发件就发送给&#x6b;&#x75;&#108;&#x69;&#x61;&#x6e;&#x67;&#x63;&#x68;&#97;&#x">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="关于SharwOrange橙夜">
|
||||||
|
<meta property="og:url" content="https://blog.hope-now.top:8443/about/">
|
||||||
|
<meta property="og:site_name" content="SharwOrangeのBlog小屋">
|
||||||
|
<meta property="og:description" content="个人介绍是树叶Leafлистья的服主也是一名B站UP主还是某个不知名小工作室(希望在即HopeNow)的创始人(官方吐槽: B工作室屁用没有那种 ( ̄ ‘i  ̄;)平时爱搞一些技术类的东西有DN42,可与我Peer,发邮件给我 头像下面有邮件的链接 (如果无法发件就发送给&#x6b;&#x75;&#108;&#x69;&#x61;&#x6e;&#x67;&#x63;&#x68;&#97;&#x">
|
||||||
|
<meta property="og:locale" content="zh_CN">
|
||||||
|
<meta property="og:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png">
|
||||||
|
<meta property="article:published_time" content="2023-06-09T07:49:44.000Z">
|
||||||
|
<meta property="article:modified_time" content="2024-06-02T13:47:08.702Z">
|
||||||
|
<meta property="article:author" content="SharwOrange">
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta name="twitter:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://blog.hope-now.top:8443/about/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css?v=4.13.0"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.1/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.33/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
|
||||||
|
root: '/',
|
||||||
|
algolia: undefined,
|
||||||
|
localSearch: undefined,
|
||||||
|
translate: undefined,
|
||||||
|
noticeOutdate: undefined,
|
||||||
|
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
|
||||||
|
copy: {
|
||||||
|
success: '复制成功',
|
||||||
|
error: '复制错误',
|
||||||
|
noSupport: '浏览器不支持'
|
||||||
|
},
|
||||||
|
relativeDate: {
|
||||||
|
homepage: false,
|
||||||
|
post: false
|
||||||
|
},
|
||||||
|
runtime: '',
|
||||||
|
dateSuffix: {
|
||||||
|
just: '刚刚',
|
||||||
|
min: '分钟前',
|
||||||
|
hour: '小时前',
|
||||||
|
day: '天前',
|
||||||
|
month: '个月前'
|
||||||
|
},
|
||||||
|
copyright: undefined,
|
||||||
|
lightbox: 'fancybox',
|
||||||
|
Snackbar: undefined,
|
||||||
|
infinitegrid: {
|
||||||
|
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.11.1/dist/infinitegrid.min.js',
|
||||||
|
buttonText: '加载更多'
|
||||||
|
},
|
||||||
|
isPhotoFigcaption: false,
|
||||||
|
islazyload: false,
|
||||||
|
isAnchor: false,
|
||||||
|
percent: {
|
||||||
|
toc: true,
|
||||||
|
rightside: false,
|
||||||
|
},
|
||||||
|
autoDarkmode: false
|
||||||
|
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
|
||||||
|
title: '关于SharwOrange橙夜',
|
||||||
|
isPost: false,
|
||||||
|
isHome: false,
|
||||||
|
isHighlightShrink: false,
|
||||||
|
isToc: false,
|
||||||
|
postUpdate: '2024-06-02 21:47:08'
|
||||||
|
}</script><script>(win=>{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
win.activateDarkMode = () => {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'dark')
|
||||||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||||||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
win.activateLightMode = () => {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'light')
|
||||||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||||||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const t = saveToLocal.get('theme')
|
||||||
|
|
||||||
|
if (t === 'dark') activateDarkMode()
|
||||||
|
else if (t === 'light') activateLightMode()
|
||||||
|
|
||||||
|
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 detectApple = () => {
|
||||||
|
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
|
||||||
|
document.documentElement.classList.add('apple')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detectApple()
|
||||||
|
})(window)</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">3</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><hr class="custom-hr"/></div></div><div class="page" id="body-wrap"><header class="not-home-page" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="SharwOrangeのBlog小屋"><span class="site-name">SharwOrangeのBlog小屋</span></a></span><div id="menus"><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="page-site-info"><h1 id="site-title">关于SharwOrange橙夜</h1></div></header><main class="layout" id="content-inner"><div id="page"><div id="article-container"><h3 id="个人介绍"><a href="#个人介绍" class="headerlink" title="个人介绍"></a>个人介绍</h3><p>是<a target="_blank" rel="noopener" href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=HoS2K7jUufbHIcF-MkxiW-_zMJGxXiTx&authKey=EUYchu+6pQc0hLRkWqrX69V5MZ5q1p6AJBeenzaRBQKeWPeh+Aox8gkfBlOXTm+1&noverify=0&group_code=839355963">树叶Leafлистья</a>的服主<br>也是一名<a target="_blank" rel="noopener" href="https://space.bilibili.com/551097042">B站UP主</a><br>还是某个不知名小工作室(希望在即HopeNow)的创始人(官方吐槽: <strong>B工作室屁用没有那种</strong> ( ̄ ‘i  ̄;)<br>平时爱搞一些技术类的东西<br>有DN42,可与我Peer,发邮件给我 <strong>头像下面有邮件的链接</strong> (如果无法发件就发送给<a href="mailto:kuliangcha@qq.com">kuliangcha@qq.com</a>)<br>当然这个懒人到现在还没弄好一个可用的接入点 (;´д`)ゞ</p>
|
||||||
|
<h3 id="站点简介"><a href="#站点简介" class="headerlink" title="站点简介"></a>站点简介</h3><p>什么方面的东西都会写一点,可能今天写OpenWRT,明天就又跑去折腾Proxmox了<br>站点搭建在Github Pages(实在是没有80端口的机器了〒▽〒)<br>使用双仓库运行,所以需要过两遍Actions,在更新的时候大概会有一分钟左右的延迟<br>可以稍作等待<br>如果Github 404 就代表网站挂了(bushi</p>
|
||||||
|
<h3 id="友链"><a href="#友链" class="headerlink" title="友链"></a>友链</h3><p>只需要按照下面的格式发送到我的邮箱就行啦</p>
|
||||||
|
<ul>
|
||||||
|
<li>网站名:Example Sites</li>
|
||||||
|
<li>简介:XXXX</li>
|
||||||
|
<li>链接:https://example.com </li>
|
||||||
|
<li>图片:https://example.com/favicon.png </li>
|
||||||
|
</ul></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">SharwOrange</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">3</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230904214934" title="御三家启动器外置使用教程(PCL2、HMCL、BakaXL)">御三家启动器外置使用教程(PCL2、HMCL、BakaXL)</a><time datetime="2023-09-04T13:49:34.000Z" title="发表于 2023-09-04 21:49:34">2023-09-04</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230902142755" title="让Geyser用上外置登录(使用Authlib-Injector)">让Geyser用上外置登录(使用Authlib-Injector)</a><time datetime="2023-09-02T06:27:55.000Z" title="发表于 2023-09-02 14:27:55">2023-09-02</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230609182444" title="Blog终于弄好了">Blog终于弄好了</a><time datetime="2023-06-09T10:24:44.000Z" title="发表于 2023-06-09 18:24:44">2023-06-09</time></div></div></div></div><div class="card-widget card-archives"><div class="item-headline"><i class="fas fa-archive"></i><span>归档</span></div><ul class="card-archive-list"><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/09/"><span class="card-archive-list-date">九月 2023</span><span class="card-archive-list-count">2</span></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/06/"><span class="card-archive-list-date">六月 2023</span><span class="card-archive-list-count">1</span></a></li></ul></div><div class="card-widget card-webinfo"><div class="item-headline"><i class="fas fa-chart-line"></i><span>网站资讯</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">文章数目 :</div><div class="item-count">3</div></div><div class="webinfo-item"><div class="item-name">本站访客数 :</div><div class="item-count" id="busuanzi_value_site_uv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">本站总访问量 :</div><div class="item-count" id="busuanzi_value_site_pv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">最后更新时间 :</div><div class="item-count" id="last-push-date" data-lastPushDate="2024-06-02T14:03:11.318Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">©2020 - 2024 By SharwOrange</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js?v=4.13.0"></script><script src="/js/main.js?v=4.13.0"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.33/dist/fancybox/fancybox.umd.min.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>
|
151
archives/2023/06/index.html
Normal file
151
archives/2023/06/index.html
Normal file
File diff suppressed because one or more lines are too long
151
archives/2023/09/index.html
Normal file
151
archives/2023/09/index.html
Normal file
File diff suppressed because one or more lines are too long
151
archives/2023/index.html
Normal file
151
archives/2023/index.html
Normal file
File diff suppressed because one or more lines are too long
151
archives/index.html
Normal file
151
archives/index.html
Normal file
File diff suppressed because one or more lines are too long
167
bb/index.html
Normal file
167
bb/index.html
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>哔哔啥呢🤤 | SharwOrangeのBlog小屋</title><meta name="author" content="SharwOrange"><meta name="copyright" content="SharwOrange"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="new Artitalk({ appId: 'naAdv4hZmJch7RmD6SujumaQ-MdYXbMMI', appKey: 'H4pjGCKivNAWuZp9sj1Ourws', serverURL: 'https://bbtalk.hope-now.top' })">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="哔哔啥呢🤤">
|
||||||
|
<meta property="og:url" content="https://blog.hope-now.top:8443/bb/">
|
||||||
|
<meta property="og:site_name" content="SharwOrangeのBlog小屋">
|
||||||
|
<meta property="og:description" content="new Artitalk({ appId: 'naAdv4hZmJch7RmD6SujumaQ-MdYXbMMI', appKey: 'H4pjGCKivNAWuZp9sj1Ourws', serverURL: 'https://bbtalk.hope-now.top' })">
|
||||||
|
<meta property="og:locale" content="zh_CN">
|
||||||
|
<meta property="og:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png">
|
||||||
|
<meta property="article:published_time" content="2023-06-13T15:06:24.000Z">
|
||||||
|
<meta property="article:modified_time" content="2024-06-02T13:47:08.702Z">
|
||||||
|
<meta property="article:author" content="SharwOrange">
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta name="twitter:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://blog.hope-now.top:8443/bb/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css?v=4.13.0"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.1/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.33/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
|
||||||
|
root: '/',
|
||||||
|
algolia: undefined,
|
||||||
|
localSearch: undefined,
|
||||||
|
translate: undefined,
|
||||||
|
noticeOutdate: undefined,
|
||||||
|
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
|
||||||
|
copy: {
|
||||||
|
success: '复制成功',
|
||||||
|
error: '复制错误',
|
||||||
|
noSupport: '浏览器不支持'
|
||||||
|
},
|
||||||
|
relativeDate: {
|
||||||
|
homepage: false,
|
||||||
|
post: false
|
||||||
|
},
|
||||||
|
runtime: '',
|
||||||
|
dateSuffix: {
|
||||||
|
just: '刚刚',
|
||||||
|
min: '分钟前',
|
||||||
|
hour: '小时前',
|
||||||
|
day: '天前',
|
||||||
|
month: '个月前'
|
||||||
|
},
|
||||||
|
copyright: undefined,
|
||||||
|
lightbox: 'fancybox',
|
||||||
|
Snackbar: undefined,
|
||||||
|
infinitegrid: {
|
||||||
|
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.11.1/dist/infinitegrid.min.js',
|
||||||
|
buttonText: '加载更多'
|
||||||
|
},
|
||||||
|
isPhotoFigcaption: false,
|
||||||
|
islazyload: false,
|
||||||
|
isAnchor: false,
|
||||||
|
percent: {
|
||||||
|
toc: true,
|
||||||
|
rightside: false,
|
||||||
|
},
|
||||||
|
autoDarkmode: false
|
||||||
|
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
|
||||||
|
title: '哔哔啥呢🤤',
|
||||||
|
isPost: false,
|
||||||
|
isHome: false,
|
||||||
|
isHighlightShrink: false,
|
||||||
|
isToc: false,
|
||||||
|
postUpdate: '2024-06-02 21:47:08'
|
||||||
|
}</script><script>(win=>{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
win.activateDarkMode = () => {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'dark')
|
||||||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||||||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
win.activateLightMode = () => {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'light')
|
||||||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||||||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const t = saveToLocal.get('theme')
|
||||||
|
|
||||||
|
if (t === 'dark') activateDarkMode()
|
||||||
|
else if (t === 'light') activateLightMode()
|
||||||
|
|
||||||
|
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 detectApple = () => {
|
||||||
|
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
|
||||||
|
document.documentElement.classList.add('apple')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detectApple()
|
||||||
|
})(window)</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">3</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><hr class="custom-hr"/></div></div><div class="page" id="body-wrap"><header class="not-home-page" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="SharwOrangeのBlog小屋"><span class="site-name">SharwOrangeのBlog小屋</span></a></span><div id="menus"><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="page-site-info"><h1 id="site-title">哔哔啥呢🤤</h1></div></header><main class="layout" id="content-inner"><div id="page"><div id="article-container"><!-- 引用 artitalk -->
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/artitalk"></script>
|
||||||
|
<!-- 存放说说的容器 -->
|
||||||
|
<div id="artitalk_main"></div>
|
||||||
|
<script>
|
||||||
|
new Artitalk({
|
||||||
|
appId: 'naAdv4hZmJch7RmD6SujumaQ-MdYXbMMI',
|
||||||
|
appKey: 'H4pjGCKivNAWuZp9sj1Ourws',
|
||||||
|
serverURL: 'https://bbtalk.hope-now.top'
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">SharwOrange</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">3</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230904214934" title="御三家启动器外置使用教程(PCL2、HMCL、BakaXL)">御三家启动器外置使用教程(PCL2、HMCL、BakaXL)</a><time datetime="2023-09-04T13:49:34.000Z" title="发表于 2023-09-04 21:49:34">2023-09-04</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230902142755" title="让Geyser用上外置登录(使用Authlib-Injector)">让Geyser用上外置登录(使用Authlib-Injector)</a><time datetime="2023-09-02T06:27:55.000Z" title="发表于 2023-09-02 14:27:55">2023-09-02</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230609182444" title="Blog终于弄好了">Blog终于弄好了</a><time datetime="2023-06-09T10:24:44.000Z" title="发表于 2023-06-09 18:24:44">2023-06-09</time></div></div></div></div><div class="card-widget card-archives"><div class="item-headline"><i class="fas fa-archive"></i><span>归档</span></div><ul class="card-archive-list"><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/09/"><span class="card-archive-list-date">九月 2023</span><span class="card-archive-list-count">2</span></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/06/"><span class="card-archive-list-date">六月 2023</span><span class="card-archive-list-count">1</span></a></li></ul></div><div class="card-widget card-webinfo"><div class="item-headline"><i class="fas fa-chart-line"></i><span>网站资讯</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">文章数目 :</div><div class="item-count">3</div></div><div class="webinfo-item"><div class="item-name">本站访客数 :</div><div class="item-count" id="busuanzi_value_site_uv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">本站总访问量 :</div><div class="item-count" id="busuanzi_value_site_pv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">最后更新时间 :</div><div class="item-count" id="last-push-date" data-lastPushDate="2024-06-02T14:03:11.318Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">©2020 - 2024 By SharwOrange</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js?v=4.13.0"></script><script src="/js/main.js?v=4.13.0"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.33/dist/fancybox/fancybox.umd.min.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>
|
6136
css/index.css
Normal file
6136
css/index.css
Normal file
File diff suppressed because it is too large
Load Diff
0
css/var.css
Normal file
0
css/var.css
Normal file
BIN
img/404.jpg
Normal file
BIN
img/404.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
img/blog_avatar.png
Normal file
BIN
img/blog_avatar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1021 KiB |
BIN
img/favicon.png
Normal file
BIN
img/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 323 B |
BIN
img/friend_404.gif
Normal file
BIN
img/friend_404.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
165
index.html
Normal file
165
index.html
Normal file
File diff suppressed because one or more lines are too long
31
js/duration.js
Normal file
31
js/duration.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
!(function() {
|
||||||
|
/** 计时起始时间,自行修改 **/
|
||||||
|
var start = new Date("2023/06/10 00:00:00");
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var now = new Date();
|
||||||
|
now.setTime(now.getTime()+250);
|
||||||
|
days = (now - start) / 1000 / 60 / 60 / 24;
|
||||||
|
dnum = Math.floor(days);
|
||||||
|
hours = (now - start) / 1000 / 60 / 60 - (24 * dnum);
|
||||||
|
hnum = Math.floor(hours);
|
||||||
|
if(String(hnum).length === 1 ){
|
||||||
|
hnum = "0" + hnum;
|
||||||
|
}
|
||||||
|
minutes = (now - start) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum);
|
||||||
|
mnum = Math.floor(minutes);
|
||||||
|
if(String(mnum).length === 1 ){
|
||||||
|
mnum = "0" + mnum;
|
||||||
|
}
|
||||||
|
seconds = (now - start) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
|
||||||
|
snum = Math.round(seconds);
|
||||||
|
if(String(snum).length === 1 ){
|
||||||
|
snum = "0" + snum;
|
||||||
|
}
|
||||||
|
document.getElementById("timeDate").innerHTML = "本站安全运行 "+dnum+" 天";
|
||||||
|
document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
setInterval(update, 1000);
|
||||||
|
})();
|
878
js/main.js
Normal file
878
js/main.js
Normal file
|
@ -0,0 +1,878 @@
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
let headerContentWidth, $nav
|
||||||
|
let mobileSidebarOpen = false
|
||||||
|
|
||||||
|
const adjustMenu = init => {
|
||||||
|
const getAllWidth = ele => {
|
||||||
|
return Array.from(ele).reduce((width, i) => width + i.offsetWidth, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init) {
|
||||||
|
const blogInfoWidth = getAllWidth(document.querySelector('#blog-info > a').children)
|
||||||
|
const menusWidth = getAllWidth(document.getElementById('menus').children)
|
||||||
|
headerContentWidth = blogInfoWidth + menusWidth
|
||||||
|
$nav = document.getElementById('nav')
|
||||||
|
}
|
||||||
|
|
||||||
|
const hideMenuIndex = window.innerWidth <= 768 || headerContentWidth > $nav.offsetWidth - 120
|
||||||
|
$nav.classList.toggle('hide-menu', hideMenuIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化header
|
||||||
|
const initAdjust = () => {
|
||||||
|
adjustMenu(true)
|
||||||
|
$nav.classList.add('show')
|
||||||
|
}
|
||||||
|
|
||||||
|
// sidebar menus
|
||||||
|
const sidebarFn = {
|
||||||
|
open: () => {
|
||||||
|
btf.sidebarPaddingR()
|
||||||
|
document.body.style.overflow = 'hidden'
|
||||||
|
btf.animateIn(document.getElementById('menu-mask'), 'to_show 0.5s')
|
||||||
|
document.getElementById('sidebar-menus').classList.add('open')
|
||||||
|
mobileSidebarOpen = true
|
||||||
|
},
|
||||||
|
close: () => {
|
||||||
|
const $body = document.body
|
||||||
|
$body.style.overflow = ''
|
||||||
|
$body.style.paddingRight = ''
|
||||||
|
btf.animateOut(document.getElementById('menu-mask'), 'to_hide 0.5s')
|
||||||
|
document.getElementById('sidebar-menus').classList.remove('open')
|
||||||
|
mobileSidebarOpen = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首頁top_img底下的箭頭
|
||||||
|
*/
|
||||||
|
const scrollDownInIndex = () => {
|
||||||
|
const handleScrollToDest = () => {
|
||||||
|
btf.scrollToDest(document.getElementById('content-inner').offsetTop, 300)
|
||||||
|
}
|
||||||
|
|
||||||
|
const $scrollDownEle = document.getElementById('scroll-down')
|
||||||
|
$scrollDownEle && btf.addEventListenerPjax($scrollDownEle, 'click', handleScrollToDest)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代碼
|
||||||
|
* 只適用於Hexo默認的代碼渲染
|
||||||
|
*/
|
||||||
|
const addHighlightTool = () => {
|
||||||
|
const highLight = GLOBAL_CONFIG.highlight
|
||||||
|
if (!highLight) return
|
||||||
|
|
||||||
|
const { highlightCopy, highlightLang, highlightHeightLimit, plugin } = highLight
|
||||||
|
const isHighlightShrink = GLOBAL_CONFIG_SITE.isHighlightShrink
|
||||||
|
const isShowTool = highlightCopy || highlightLang || isHighlightShrink !== undefined
|
||||||
|
const $figureHighlight = plugin === 'highlight.js' ? document.querySelectorAll('figure.highlight') : document.querySelectorAll('pre[class*="language-"]')
|
||||||
|
|
||||||
|
if (!((isShowTool || highlightHeightLimit) && $figureHighlight.length)) return
|
||||||
|
|
||||||
|
const isPrismjs = plugin === 'prismjs'
|
||||||
|
const highlightShrinkClass = isHighlightShrink === true ? 'closed' : ''
|
||||||
|
const highlightShrinkEle = isHighlightShrink !== undefined ? '<i class="fas fa-angle-down expand"></i>' : ''
|
||||||
|
const highlightCopyEle = highlightCopy ? '<div class="copy-notice"></div><i class="fas fa-paste copy-button"></i>' : ''
|
||||||
|
|
||||||
|
const alertInfo = (ele, text) => {
|
||||||
|
if (GLOBAL_CONFIG.Snackbar !== undefined) {
|
||||||
|
btf.snackbarShow(text)
|
||||||
|
} else {
|
||||||
|
const prevEle = ele.previousElementSibling
|
||||||
|
prevEle.textContent = text
|
||||||
|
prevEle.style.opacity = 1
|
||||||
|
setTimeout(() => { prevEle.style.opacity = 0 }, 800)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const copy = ctx => {
|
||||||
|
if (document.queryCommandSupported && document.queryCommandSupported('copy')) {
|
||||||
|
document.execCommand('copy')
|
||||||
|
alertInfo(ctx, GLOBAL_CONFIG.copy.success)
|
||||||
|
} else {
|
||||||
|
alertInfo(ctx, GLOBAL_CONFIG.copy.noSupport)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// click events
|
||||||
|
const highlightCopyFn = ele => {
|
||||||
|
const $buttonParent = ele.parentNode
|
||||||
|
$buttonParent.classList.add('copy-true')
|
||||||
|
const selection = window.getSelection()
|
||||||
|
const range = document.createRange()
|
||||||
|
const preCodeSelector = isPrismjs ? 'pre code' : 'table .code pre'
|
||||||
|
range.selectNodeContents($buttonParent.querySelectorAll(`${preCodeSelector}`)[0])
|
||||||
|
selection.removeAllRanges()
|
||||||
|
selection.addRange(range)
|
||||||
|
copy(ele.lastChild)
|
||||||
|
selection.removeAllRanges()
|
||||||
|
$buttonParent.classList.remove('copy-true')
|
||||||
|
}
|
||||||
|
|
||||||
|
const highlightShrinkFn = ele => {
|
||||||
|
ele.classList.toggle('closed')
|
||||||
|
}
|
||||||
|
|
||||||
|
const highlightToolsFn = function (e) {
|
||||||
|
const $target = e.target.classList
|
||||||
|
if ($target.contains('expand')) highlightShrinkFn(this)
|
||||||
|
else if ($target.contains('copy-button')) highlightCopyFn(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
const expandCode = function () {
|
||||||
|
this.classList.toggle('expand-done')
|
||||||
|
}
|
||||||
|
|
||||||
|
const createEle = (lang, item, service) => {
|
||||||
|
const fragment = document.createDocumentFragment()
|
||||||
|
|
||||||
|
if (isShowTool) {
|
||||||
|
const hlTools = document.createElement('div')
|
||||||
|
hlTools.className = `highlight-tools ${highlightShrinkClass}`
|
||||||
|
hlTools.innerHTML = highlightShrinkEle + lang + highlightCopyEle
|
||||||
|
btf.addEventListenerPjax(hlTools, 'click', highlightToolsFn)
|
||||||
|
fragment.appendChild(hlTools)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highlightHeightLimit && item.offsetHeight > highlightHeightLimit + 30) {
|
||||||
|
const ele = document.createElement('div')
|
||||||
|
ele.className = 'code-expand-btn'
|
||||||
|
ele.innerHTML = '<i class="fas fa-angle-double-down"></i>'
|
||||||
|
btf.addEventListenerPjax(ele, 'click', expandCode)
|
||||||
|
fragment.appendChild(ele)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (service === 'hl') {
|
||||||
|
item.insertBefore(fragment, item.firstChild)
|
||||||
|
} else {
|
||||||
|
item.parentNode.insertBefore(fragment, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPrismjs) {
|
||||||
|
$figureHighlight.forEach(item => {
|
||||||
|
if (highlightLang) {
|
||||||
|
const langName = item.getAttribute('data-language') || 'Code'
|
||||||
|
const highlightLangEle = `<div class="code-lang">${langName}</div>`
|
||||||
|
btf.wrap(item, 'figure', { class: 'highlight' })
|
||||||
|
createEle(highlightLangEle, item)
|
||||||
|
} else {
|
||||||
|
btf.wrap(item, 'figure', { class: 'highlight' })
|
||||||
|
createEle('', item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
$figureHighlight.forEach(item => {
|
||||||
|
if (highlightLang) {
|
||||||
|
let langName = item.getAttribute('class').split(' ')[1]
|
||||||
|
if (langName === 'plain' || langName === undefined) langName = 'Code'
|
||||||
|
const highlightLangEle = `<div class="code-lang">${langName}</div>`
|
||||||
|
createEle(highlightLangEle, item, 'hl')
|
||||||
|
} else {
|
||||||
|
createEle('', item, 'hl')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PhotoFigcaption
|
||||||
|
*/
|
||||||
|
const addPhotoFigcaption = () => {
|
||||||
|
document.querySelectorAll('#article-container img').forEach(item => {
|
||||||
|
const altValue = item.title || item.alt
|
||||||
|
if (!altValue) return
|
||||||
|
const ele = document.createElement('div')
|
||||||
|
ele.className = 'img-alt is-center'
|
||||||
|
ele.textContent = altValue
|
||||||
|
item.insertAdjacentElement('afterend', ele)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lightbox
|
||||||
|
*/
|
||||||
|
const runLightbox = () => {
|
||||||
|
btf.loadLightbox(document.querySelectorAll('#article-container img:not(.no-lightbox)'))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* justified-gallery 圖庫排版
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fetchUrl = async (url) => {
|
||||||
|
const response = await fetch(url)
|
||||||
|
return await response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
const runJustifiedGallery = (item, data, isButton = false, tabs) => {
|
||||||
|
const dataLength = data.length
|
||||||
|
|
||||||
|
const ig = new InfiniteGrid.JustifiedInfiniteGrid(item, {
|
||||||
|
gap: 5,
|
||||||
|
isConstantSize: true,
|
||||||
|
sizeRange: [150, 600],
|
||||||
|
useResizeObserver: true,
|
||||||
|
observeChildren: true,
|
||||||
|
useTransform: true
|
||||||
|
// useRecycle: false
|
||||||
|
})
|
||||||
|
|
||||||
|
if (tabs) {
|
||||||
|
btf.addGlobalFn('igOfTabs', () => { ig.destroy() }, false, tabs)
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceDq = str => str.replace(/"/g, '"') // replace double quotes to "
|
||||||
|
|
||||||
|
const getItems = (nextGroupKey, count) => {
|
||||||
|
const nextItems = []
|
||||||
|
const startCount = (nextGroupKey - 1) * count
|
||||||
|
|
||||||
|
for (let i = 0; i < count; ++i) {
|
||||||
|
const num = startCount + i
|
||||||
|
if (num >= dataLength) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
const item = data[num]
|
||||||
|
const alt = item.alt ? `alt="${replaceDq(item.alt)}"` : ''
|
||||||
|
const title = item.title ? `title="${replaceDq(item.title)}"` : ''
|
||||||
|
|
||||||
|
nextItems.push(`<div class="item ">
|
||||||
|
<img src="${item.url}" data-grid-maintained-target="true" ${alt + title} />
|
||||||
|
</div>`)
|
||||||
|
}
|
||||||
|
return nextItems
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonText = GLOBAL_CONFIG.infinitegrid.buttonText
|
||||||
|
const addButton = item => {
|
||||||
|
const button = document.createElement('button')
|
||||||
|
button.textContent = buttonText
|
||||||
|
|
||||||
|
const buttonFn = e => {
|
||||||
|
e.target.removeEventListener('click', buttonFn)
|
||||||
|
e.target.remove()
|
||||||
|
btf.setLoading.add(item)
|
||||||
|
appendItem(ig.getGroups().length + 1, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
button.addEventListener('click', buttonFn)
|
||||||
|
item.insertAdjacentElement('afterend', button)
|
||||||
|
}
|
||||||
|
|
||||||
|
const appendItem = (nextGroupKey, count) => {
|
||||||
|
ig.append(getItems(nextGroupKey, count), nextGroupKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxGroupKey = Math.ceil(dataLength / 10)
|
||||||
|
|
||||||
|
const completeFn = e => {
|
||||||
|
const { updated, isResize, mounted } = e
|
||||||
|
if (!updated.length || !mounted.length || isResize) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
btf.loadLightbox(item.querySelectorAll('img:not(.medium-zoom-image)'))
|
||||||
|
|
||||||
|
if (ig.getGroups().length === maxGroupKey) {
|
||||||
|
btf.setLoading.remove(item)
|
||||||
|
ig.off('renderComplete', completeFn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isButton) {
|
||||||
|
btf.setLoading.remove(item)
|
||||||
|
addButton(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestAppendFn = btf.debounce(e => {
|
||||||
|
const nextGroupKey = (+e.groupKey || 0) + 1
|
||||||
|
appendItem(nextGroupKey, 10)
|
||||||
|
|
||||||
|
if (nextGroupKey === maxGroupKey) {
|
||||||
|
ig.off('requestAppend', requestAppendFn)
|
||||||
|
}
|
||||||
|
}, 300)
|
||||||
|
|
||||||
|
btf.setLoading.add(item)
|
||||||
|
ig.on('renderComplete', completeFn)
|
||||||
|
|
||||||
|
if (isButton) {
|
||||||
|
appendItem(1, 10)
|
||||||
|
} else {
|
||||||
|
ig.on('requestAppend', requestAppendFn)
|
||||||
|
ig.renderItems()
|
||||||
|
}
|
||||||
|
|
||||||
|
btf.addGlobalFn('justifiedGallery', () => { ig.destroy() })
|
||||||
|
}
|
||||||
|
|
||||||
|
const addJustifiedGallery = async (ele, tabs = false) => {
|
||||||
|
const init = async () => {
|
||||||
|
for (const item of ele) {
|
||||||
|
if (btf.isHidden(item)) continue
|
||||||
|
if (tabs && item.classList.contains('loaded')) {
|
||||||
|
item.querySelector('.gallery-items').innerHTML = ''
|
||||||
|
const button = item.querySelector(':scope > button')
|
||||||
|
const loadingContainer = item.querySelector(':scope > .loading-container')
|
||||||
|
button && button.remove()
|
||||||
|
loadingContainer && loadingContainer.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
const isButton = item.getAttribute('data-button') === 'true'
|
||||||
|
const text = item.firstElementChild.textContent
|
||||||
|
item.classList.add('loaded')
|
||||||
|
const content = item.getAttribute('data-type') === 'url' ? await fetchUrl(text) : JSON.parse(text)
|
||||||
|
runJustifiedGallery(item.lastElementChild, content, isButton, tabs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof InfiniteGrid === 'function') {
|
||||||
|
init()
|
||||||
|
} else {
|
||||||
|
await getScript(`${GLOBAL_CONFIG.infinitegrid.js}`)
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rightside scroll percent
|
||||||
|
*/
|
||||||
|
const rightsideScrollPercent = currentTop => {
|
||||||
|
const scrollPercent = btf.getScrollPercent(currentTop, document.body)
|
||||||
|
const goUpElement = document.getElementById('go-up')
|
||||||
|
|
||||||
|
if (scrollPercent < 95) {
|
||||||
|
goUpElement.classList.add('show-percent')
|
||||||
|
goUpElement.querySelector('.scroll-percent').textContent = scrollPercent
|
||||||
|
} else {
|
||||||
|
goUpElement.classList.remove('show-percent')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 滾動處理
|
||||||
|
*/
|
||||||
|
const scrollFn = () => {
|
||||||
|
const $rightside = document.getElementById('rightside')
|
||||||
|
const innerHeight = window.innerHeight + 56
|
||||||
|
let initTop = 0
|
||||||
|
const $header = document.getElementById('page-header')
|
||||||
|
const isChatBtn = typeof chatBtn !== 'undefined'
|
||||||
|
const isShowPercent = GLOBAL_CONFIG.percent.rightside
|
||||||
|
|
||||||
|
// 當滾動條小于 56 的時候
|
||||||
|
if (document.body.scrollHeight <= innerHeight) {
|
||||||
|
$rightside.classList.add('rightside-show')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the scroll direction
|
||||||
|
const scrollDirection = currentTop => {
|
||||||
|
const result = currentTop > initTop // true is down & false is up
|
||||||
|
initTop = currentTop
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
let flag = ''
|
||||||
|
const scrollTask = btf.throttle(() => {
|
||||||
|
const currentTop = window.scrollY || document.documentElement.scrollTop
|
||||||
|
const isDown = scrollDirection(currentTop)
|
||||||
|
if (currentTop > 56) {
|
||||||
|
if (flag === '') {
|
||||||
|
$header.classList.add('nav-fixed')
|
||||||
|
$rightside.classList.add('rightside-show')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDown) {
|
||||||
|
if (flag !== 'down') {
|
||||||
|
$header.classList.remove('nav-visible')
|
||||||
|
isChatBtn && window.chatBtn.hide()
|
||||||
|
flag = 'down'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (flag !== 'up') {
|
||||||
|
$header.classList.add('nav-visible')
|
||||||
|
isChatBtn && window.chatBtn.show()
|
||||||
|
flag = 'up'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
flag = ''
|
||||||
|
if (currentTop === 0) {
|
||||||
|
$header.classList.remove('nav-fixed', 'nav-visible')
|
||||||
|
}
|
||||||
|
$rightside.classList.remove('rightside-show')
|
||||||
|
}
|
||||||
|
|
||||||
|
isShowPercent && rightsideScrollPercent(currentTop)
|
||||||
|
|
||||||
|
if (document.body.scrollHeight <= innerHeight) {
|
||||||
|
$rightside.classList.add('rightside-show')
|
||||||
|
}
|
||||||
|
}, 300)
|
||||||
|
|
||||||
|
btf.addEventListenerPjax(window, 'scroll', scrollTask, { passive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* toc,anchor
|
||||||
|
*/
|
||||||
|
const scrollFnToDo = () => {
|
||||||
|
const isToc = GLOBAL_CONFIG_SITE.isToc
|
||||||
|
const isAnchor = GLOBAL_CONFIG.isAnchor
|
||||||
|
const $article = document.getElementById('article-container')
|
||||||
|
|
||||||
|
if (!($article && (isToc || isAnchor))) return
|
||||||
|
|
||||||
|
let $tocLink, $cardToc, autoScrollToc, $tocPercentage, isExpand
|
||||||
|
|
||||||
|
if (isToc) {
|
||||||
|
const $cardTocLayout = document.getElementById('card-toc')
|
||||||
|
$cardToc = $cardTocLayout.querySelector('.toc-content')
|
||||||
|
$tocLink = $cardToc.querySelectorAll('.toc-link')
|
||||||
|
$tocPercentage = $cardTocLayout.querySelector('.toc-percentage')
|
||||||
|
isExpand = $cardToc.classList.contains('is-expand')
|
||||||
|
|
||||||
|
// toc元素點擊
|
||||||
|
const tocItemClickFn = e => {
|
||||||
|
const target = e.target.closest('.toc-link')
|
||||||
|
if (!target) return
|
||||||
|
|
||||||
|
e.preventDefault()
|
||||||
|
btf.scrollToDest(btf.getEleTop(document.getElementById(decodeURI(target.getAttribute('href')).replace('#', ''))), 300)
|
||||||
|
if (window.innerWidth < 900) {
|
||||||
|
$cardTocLayout.classList.remove('open')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btf.addEventListenerPjax($cardToc, 'click', tocItemClickFn)
|
||||||
|
|
||||||
|
autoScrollToc = item => {
|
||||||
|
const activePosition = item.getBoundingClientRect().top
|
||||||
|
const sidebarScrollTop = $cardToc.scrollTop
|
||||||
|
if (activePosition > (document.documentElement.clientHeight - 100)) {
|
||||||
|
$cardToc.scrollTop = sidebarScrollTop + 150
|
||||||
|
}
|
||||||
|
if (activePosition < 100) {
|
||||||
|
$cardToc.scrollTop = sidebarScrollTop - 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find head position & add active class
|
||||||
|
const $articleList = $article.querySelectorAll('h1,h2,h3,h4,h5,h6')
|
||||||
|
let detectItem = ''
|
||||||
|
const findHeadPosition = top => {
|
||||||
|
if (top === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentId = ''
|
||||||
|
let currentIndex = ''
|
||||||
|
|
||||||
|
$articleList.forEach((ele, index) => {
|
||||||
|
if (top > btf.getEleTop(ele) - 80) {
|
||||||
|
const id = ele.id
|
||||||
|
currentId = id ? '#' + encodeURI(id) : ''
|
||||||
|
currentIndex = index
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (detectItem === currentIndex) return
|
||||||
|
|
||||||
|
if (isAnchor) btf.updateAnchor(currentId)
|
||||||
|
|
||||||
|
detectItem = currentIndex
|
||||||
|
|
||||||
|
if (isToc) {
|
||||||
|
$cardToc.querySelectorAll('.active').forEach(i => { i.classList.remove('active') })
|
||||||
|
|
||||||
|
if (currentId === '') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentActive = $tocLink[currentIndex]
|
||||||
|
currentActive.classList.add('active')
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
autoScrollToc(currentActive)
|
||||||
|
}, 0)
|
||||||
|
|
||||||
|
if (isExpand) return
|
||||||
|
let parent = currentActive.parentNode
|
||||||
|
|
||||||
|
for (; !parent.matches('.toc'); parent = parent.parentNode) {
|
||||||
|
if (parent.matches('li')) parent.classList.add('active')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// main of scroll
|
||||||
|
const tocScrollFn = btf.throttle(() => {
|
||||||
|
const currentTop = window.scrollY || document.documentElement.scrollTop
|
||||||
|
if (isToc && GLOBAL_CONFIG.percent.toc) {
|
||||||
|
$tocPercentage.textContent = btf.getScrollPercent(currentTop, $article)
|
||||||
|
}
|
||||||
|
findHeadPosition(currentTop)
|
||||||
|
}, 100)
|
||||||
|
|
||||||
|
btf.addEventListenerPjax(window, 'scroll', tocScrollFn, { passive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleThemeChange = mode => {
|
||||||
|
const globalFn = window.globalFn || {}
|
||||||
|
const themeChange = globalFn.themeChange || {}
|
||||||
|
if (!themeChange) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(themeChange).forEach(key => {
|
||||||
|
const themeChangeFn = themeChange[key]
|
||||||
|
if (['disqus', 'disqusjs'].includes(key)) {
|
||||||
|
setTimeout(() => themeChangeFn(mode), 300)
|
||||||
|
} else {
|
||||||
|
themeChangeFn(mode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rightside
|
||||||
|
*/
|
||||||
|
const rightSideFn = {
|
||||||
|
readmode: () => { // read mode
|
||||||
|
const $body = document.body
|
||||||
|
$body.classList.add('read-mode')
|
||||||
|
const newEle = document.createElement('button')
|
||||||
|
newEle.type = 'button'
|
||||||
|
newEle.className = 'fas fa-sign-out-alt exit-readmode'
|
||||||
|
$body.appendChild(newEle)
|
||||||
|
|
||||||
|
const clickFn = () => {
|
||||||
|
$body.classList.remove('read-mode')
|
||||||
|
newEle.remove()
|
||||||
|
newEle.removeEventListener('click', clickFn)
|
||||||
|
}
|
||||||
|
|
||||||
|
newEle.addEventListener('click', clickFn)
|
||||||
|
},
|
||||||
|
darkmode: () => { // switch between light and dark mode
|
||||||
|
const willChangeMode = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'
|
||||||
|
if (willChangeMode === 'dark') {
|
||||||
|
activateDarkMode()
|
||||||
|
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night)
|
||||||
|
} else {
|
||||||
|
activateLightMode()
|
||||||
|
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.night_to_day)
|
||||||
|
}
|
||||||
|
saveToLocal.set('theme', willChangeMode, 2)
|
||||||
|
handleThemeChange(willChangeMode)
|
||||||
|
},
|
||||||
|
'rightside-config': item => { // Show or hide rightside-hide-btn
|
||||||
|
const hideLayout = item.firstElementChild
|
||||||
|
if (hideLayout.classList.contains('show')) {
|
||||||
|
hideLayout.classList.add('status')
|
||||||
|
setTimeout(() => {
|
||||||
|
hideLayout.classList.remove('status')
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
|
||||||
|
hideLayout.classList.toggle('show')
|
||||||
|
},
|
||||||
|
'go-up': () => { // Back to top
|
||||||
|
btf.scrollToDest(0, 500)
|
||||||
|
},
|
||||||
|
'hide-aside-btn': () => { // Hide aside
|
||||||
|
const $htmlDom = document.documentElement.classList
|
||||||
|
const saveStatus = $htmlDom.contains('hide-aside') ? 'show' : 'hide'
|
||||||
|
saveToLocal.set('aside-status', saveStatus, 2)
|
||||||
|
$htmlDom.toggle('hide-aside')
|
||||||
|
},
|
||||||
|
'mobile-toc-button': item => { // Show mobile toc
|
||||||
|
const tocEle = document.getElementById('card-toc')
|
||||||
|
tocEle.style.transition = 'transform 0.3s ease-in-out'
|
||||||
|
tocEle.classList.toggle('open')
|
||||||
|
tocEle.addEventListener('transitionend', () => {
|
||||||
|
tocEle.style.transition = ''
|
||||||
|
}, { once: true })
|
||||||
|
},
|
||||||
|
'chat-btn': () => { // Show chat
|
||||||
|
window.chatBtnFn()
|
||||||
|
},
|
||||||
|
translateLink: () => { // switch between traditional and simplified chinese
|
||||||
|
window.translateFn.translatePage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('rightside').addEventListener('click', function (e) {
|
||||||
|
const $target = e.target.closest('[id]')
|
||||||
|
if ($target && rightSideFn[$target.id]) {
|
||||||
|
rightSideFn[$target.id](this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* menu
|
||||||
|
* 側邊欄sub-menu 展開/收縮
|
||||||
|
*/
|
||||||
|
const clickFnOfSubMenu = () => {
|
||||||
|
const handleClickOfSubMenu = e => {
|
||||||
|
const target = e.target.closest('.site-page.group')
|
||||||
|
if (!target) return
|
||||||
|
target.classList.toggle('hide')
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelector('#sidebar-menus .menus_items').addEventListener('click', handleClickOfSubMenu)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机端目录点击
|
||||||
|
*/
|
||||||
|
const openMobileMenu = () => {
|
||||||
|
const handleClick = () => { sidebarFn.open() }
|
||||||
|
btf.addEventListenerPjax(document.getElementById('toggle-menu'), 'click', handleClick)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 複製時加上版權信息
|
||||||
|
*/
|
||||||
|
const addCopyright = () => {
|
||||||
|
const { limitCount, languages } = GLOBAL_CONFIG.copyright
|
||||||
|
|
||||||
|
const handleCopy = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
const copyFont = window.getSelection(0).toString()
|
||||||
|
let textFont = copyFont
|
||||||
|
if (copyFont.length > limitCount) {
|
||||||
|
textFont = `${copyFont}\n\n\n${languages.author}\n${languages.link}${window.location.href}\n${languages.source}\n${languages.info}`
|
||||||
|
}
|
||||||
|
if (e.clipboardData) {
|
||||||
|
return e.clipboardData.setData('text', textFont)
|
||||||
|
} else {
|
||||||
|
return window.clipboardData.setData('text', textFont)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.addEventListener('copy', handleCopy)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 網頁運行時間
|
||||||
|
*/
|
||||||
|
const addRuntime = () => {
|
||||||
|
const $runtimeCount = document.getElementById('runtimeshow')
|
||||||
|
if ($runtimeCount) {
|
||||||
|
const publishDate = $runtimeCount.getAttribute('data-publishDate')
|
||||||
|
$runtimeCount.textContent = `${btf.diffDate(publishDate)} ${GLOBAL_CONFIG.runtime}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最後一次更新時間
|
||||||
|
*/
|
||||||
|
const addLastPushDate = () => {
|
||||||
|
const $lastPushDateItem = document.getElementById('last-push-date')
|
||||||
|
if ($lastPushDateItem) {
|
||||||
|
const lastPushDate = $lastPushDateItem.getAttribute('data-lastPushDate')
|
||||||
|
$lastPushDateItem.textContent = btf.diffDate(lastPushDate, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* table overflow
|
||||||
|
*/
|
||||||
|
const addTableWrap = () => {
|
||||||
|
const $table = document.querySelectorAll('#article-container table')
|
||||||
|
if (!$table.length) return
|
||||||
|
|
||||||
|
$table.forEach(item => {
|
||||||
|
if (!item.closest('.highlight')) {
|
||||||
|
btf.wrap(item, 'div', { class: 'table-wrap' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tag-hide
|
||||||
|
*/
|
||||||
|
const clickFnOfTagHide = () => {
|
||||||
|
const hideButtons = document.querySelectorAll('#article-container .hide-button')
|
||||||
|
if (!hideButtons.length) return
|
||||||
|
const handleClick = function (e) {
|
||||||
|
const $this = this
|
||||||
|
$this.classList.add('open')
|
||||||
|
const $fjGallery = $this.nextElementSibling.querySelectorAll('.gallery-container')
|
||||||
|
$fjGallery.length && addJustifiedGallery($fjGallery)
|
||||||
|
}
|
||||||
|
|
||||||
|
hideButtons.forEach(item => {
|
||||||
|
item.addEventListener('click', handleClick, { once: true })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabsFn = () => {
|
||||||
|
const navTabsElement = document.querySelectorAll('#article-container .tabs')
|
||||||
|
if (!navTabsElement.length) return
|
||||||
|
|
||||||
|
const removeAndAddActiveClass = (elements, detect) => {
|
||||||
|
Array.from(elements).forEach(element => {
|
||||||
|
element.classList.remove('active')
|
||||||
|
if (element === detect || element.id === detect) {
|
||||||
|
element.classList.add('active')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const addTabNavEventListener = (item, isJustifiedGallery) => {
|
||||||
|
const navClickHandler = function (e) {
|
||||||
|
const target = e.target.closest('button')
|
||||||
|
if (target.classList.contains('active')) return
|
||||||
|
removeAndAddActiveClass(this.children, target)
|
||||||
|
this.classList.remove('no-default')
|
||||||
|
const tabId = target.getAttribute('data-href')
|
||||||
|
const tabContent = this.nextElementSibling
|
||||||
|
removeAndAddActiveClass(tabContent.children, tabId)
|
||||||
|
if (isJustifiedGallery) {
|
||||||
|
btf.removeGlobalFnEvent('igOfTabs', this)
|
||||||
|
const justifiedGalleryItems = tabContent.querySelectorAll(`:scope > #${tabId} .gallery-container`)
|
||||||
|
justifiedGalleryItems.length && addJustifiedGallery(justifiedGalleryItems, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
btf.addEventListenerPjax(item.firstElementChild, 'click', navClickHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addTabToTopEventListener = item => {
|
||||||
|
const btnClickHandler = (e) => {
|
||||||
|
const target = e.target.closest('button')
|
||||||
|
if (!target) return
|
||||||
|
btf.scrollToDest(btf.getEleTop(item), 300)
|
||||||
|
}
|
||||||
|
btf.addEventListenerPjax(item.lastElementChild, 'click', btnClickHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
navTabsElement.forEach(item => {
|
||||||
|
const isJustifiedGallery = !!item.querySelectorAll('.gallery-container')
|
||||||
|
addTabNavEventListener(item, isJustifiedGallery)
|
||||||
|
addTabToTopEventListener(item)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleCardCategory = () => {
|
||||||
|
const cardCategory = document.querySelector('#aside-cat-list.expandBtn')
|
||||||
|
if (!cardCategory) return
|
||||||
|
|
||||||
|
const handleToggleBtn = (e) => {
|
||||||
|
const target = e.target
|
||||||
|
if (target.nodeName === 'I') {
|
||||||
|
e.preventDefault()
|
||||||
|
target.parentNode.classList.toggle('expand')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
btf.addEventListenerPjax(cardCategory, 'click', handleToggleBtn, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const switchComments = () => {
|
||||||
|
const switchBtn = document.getElementById('switch-btn')
|
||||||
|
if (!switchBtn) return
|
||||||
|
let switchDone = false
|
||||||
|
const commentContainer = document.getElementById('post-comment')
|
||||||
|
const handleSwitchBtn = () => {
|
||||||
|
commentContainer.classList.toggle('move')
|
||||||
|
if (!switchDone && typeof loadOtherComment === 'function') {
|
||||||
|
switchDone = true
|
||||||
|
loadOtherComment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
btf.addEventListenerPjax(switchBtn, 'click', handleSwitchBtn)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addPostOutdateNotice = () => {
|
||||||
|
const { limitDay, messagePrev, messageNext, position } = GLOBAL_CONFIG.noticeOutdate
|
||||||
|
const diffDay = btf.diffDate(GLOBAL_CONFIG_SITE.postUpdate)
|
||||||
|
if (diffDay >= limitDay) {
|
||||||
|
const ele = document.createElement('div')
|
||||||
|
ele.className = 'post-outdate-notice'
|
||||||
|
ele.textContent = `${messagePrev} ${diffDay} ${messageNext}`
|
||||||
|
const $targetEle = document.getElementById('article-container')
|
||||||
|
if (position === 'top') {
|
||||||
|
$targetEle.insertBefore(ele, $targetEle.firstChild)
|
||||||
|
} else {
|
||||||
|
$targetEle.appendChild(ele)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const lazyloadImg = () => {
|
||||||
|
window.lazyLoadInstance = new LazyLoad({
|
||||||
|
elements_selector: 'img',
|
||||||
|
threshold: 0,
|
||||||
|
data_src: 'lazy-src'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const relativeDate = function (selector) {
|
||||||
|
selector.forEach(item => {
|
||||||
|
const timeVal = item.getAttribute('datetime')
|
||||||
|
item.textContent = btf.diffDate(timeVal, true)
|
||||||
|
item.style.display = 'inline'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const unRefreshFn = function () {
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
adjustMenu(false)
|
||||||
|
mobileSidebarOpen && btf.isHidden(document.getElementById('toggle-menu')) && sidebarFn.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
document.getElementById('menu-mask').addEventListener('click', e => { sidebarFn.close() })
|
||||||
|
|
||||||
|
clickFnOfSubMenu()
|
||||||
|
GLOBAL_CONFIG.islazyload && lazyloadImg()
|
||||||
|
GLOBAL_CONFIG.copyright !== undefined && addCopyright()
|
||||||
|
|
||||||
|
if (GLOBAL_CONFIG.autoDarkmode) {
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
|
||||||
|
if (saveToLocal.get('theme') !== undefined) return
|
||||||
|
e.matches ? handleThemeChange('dark') : handleThemeChange('light')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.refreshFn = function () {
|
||||||
|
initAdjust()
|
||||||
|
|
||||||
|
if (GLOBAL_CONFIG_SITE.isPost) {
|
||||||
|
GLOBAL_CONFIG.noticeOutdate !== undefined && addPostOutdateNotice()
|
||||||
|
GLOBAL_CONFIG.relativeDate.post && relativeDate(document.querySelectorAll('#post-meta time'))
|
||||||
|
} else {
|
||||||
|
GLOBAL_CONFIG.relativeDate.homepage && relativeDate(document.querySelectorAll('#recent-posts time'))
|
||||||
|
GLOBAL_CONFIG.runtime && addRuntime()
|
||||||
|
addLastPushDate()
|
||||||
|
toggleCardCategory()
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollFnToDo()
|
||||||
|
GLOBAL_CONFIG_SITE.isHome && scrollDownInIndex()
|
||||||
|
addHighlightTool()
|
||||||
|
GLOBAL_CONFIG.isPhotoFigcaption && addPhotoFigcaption()
|
||||||
|
scrollFn()
|
||||||
|
|
||||||
|
btf.removeGlobalFnEvent('justifiedGallery')
|
||||||
|
const galleryContainer = document.querySelectorAll('#article-container .gallery-container')
|
||||||
|
galleryContainer.length && addJustifiedGallery(galleryContainer)
|
||||||
|
|
||||||
|
runLightbox()
|
||||||
|
addTableWrap()
|
||||||
|
clickFnOfTagHide()
|
||||||
|
tabsFn()
|
||||||
|
switchComments()
|
||||||
|
openMobileMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshFn()
|
||||||
|
unRefreshFn()
|
||||||
|
})
|
177
js/search/algolia.js
Normal file
177
js/search/algolia.js
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
const $searchMask = document.getElementById('search-mask')
|
||||||
|
const $searchDialog = document.querySelector('#algolia-search .search-dialog')
|
||||||
|
|
||||||
|
const openSearch = () => {
|
||||||
|
const bodyStyle = document.body.style
|
||||||
|
bodyStyle.width = '100%'
|
||||||
|
bodyStyle.overflow = 'hidden'
|
||||||
|
btf.animateIn($searchMask, 'to_show 0.5s')
|
||||||
|
btf.animateIn($searchDialog, 'titleScale 0.5s')
|
||||||
|
setTimeout(() => { document.querySelector('#algolia-search .ais-SearchBox-input').focus() }, 100)
|
||||||
|
|
||||||
|
// shortcut: ESC
|
||||||
|
document.addEventListener('keydown', function f (event) {
|
||||||
|
if (event.code === 'Escape') {
|
||||||
|
closeSearch()
|
||||||
|
document.removeEventListener('keydown', f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
fixSafariHeight()
|
||||||
|
window.addEventListener('resize', fixSafariHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeSearch = () => {
|
||||||
|
const bodyStyle = document.body.style
|
||||||
|
bodyStyle.width = ''
|
||||||
|
bodyStyle.overflow = ''
|
||||||
|
btf.animateOut($searchDialog, 'search_close .5s')
|
||||||
|
btf.animateOut($searchMask, 'to_hide 0.5s')
|
||||||
|
window.removeEventListener('resize', fixSafariHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix safari
|
||||||
|
const fixSafariHeight = () => {
|
||||||
|
if (window.innerWidth < 768) {
|
||||||
|
$searchDialog.style.setProperty('--search-height', window.innerHeight + 'px')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchClickFn = () => {
|
||||||
|
btf.addEventListenerPjax(document.querySelector('#search-button > .search'), 'click', openSearch)
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchFnOnce = () => {
|
||||||
|
$searchMask.addEventListener('click', closeSearch)
|
||||||
|
document.querySelector('#algolia-search .search-close-button').addEventListener('click', closeSearch)
|
||||||
|
}
|
||||||
|
|
||||||
|
const cutContent = content => {
|
||||||
|
if (content === '') return ''
|
||||||
|
|
||||||
|
const firstOccur = content.indexOf('<mark>')
|
||||||
|
|
||||||
|
let start = firstOccur - 30
|
||||||
|
let end = firstOccur + 120
|
||||||
|
let pre = ''
|
||||||
|
let post = ''
|
||||||
|
|
||||||
|
if (start <= 0) {
|
||||||
|
start = 0
|
||||||
|
end = 140
|
||||||
|
} else {
|
||||||
|
pre = '...'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end > content.length) {
|
||||||
|
end = content.length
|
||||||
|
} else {
|
||||||
|
post = '...'
|
||||||
|
}
|
||||||
|
|
||||||
|
const matchContent = pre + content.substring(start, end) + post
|
||||||
|
return matchContent
|
||||||
|
}
|
||||||
|
|
||||||
|
const algolia = GLOBAL_CONFIG.algolia
|
||||||
|
const isAlgoliaValid = algolia.appId && algolia.apiKey && algolia.indexName
|
||||||
|
if (!isAlgoliaValid) {
|
||||||
|
return console.error('Algolia setting is invalid!')
|
||||||
|
}
|
||||||
|
|
||||||
|
const search = instantsearch({
|
||||||
|
indexName: algolia.indexName,
|
||||||
|
/* global algoliasearch */
|
||||||
|
searchClient: algoliasearch(algolia.appId, algolia.apiKey),
|
||||||
|
searchFunction (helper) {
|
||||||
|
helper.state.query && helper.search()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const configure = instantsearch.widgets.configure({
|
||||||
|
hitsPerPage: 5
|
||||||
|
})
|
||||||
|
|
||||||
|
const searchBox = instantsearch.widgets.searchBox({
|
||||||
|
container: '#algolia-search-input',
|
||||||
|
showReset: false,
|
||||||
|
showSubmit: false,
|
||||||
|
placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder,
|
||||||
|
showLoadingIndicator: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const hits = instantsearch.widgets.hits({
|
||||||
|
container: '#algolia-hits',
|
||||||
|
templates: {
|
||||||
|
item (data) {
|
||||||
|
const link = data.permalink ? data.permalink : (GLOBAL_CONFIG.root + data.path)
|
||||||
|
const result = data._highlightResult
|
||||||
|
const content = result.contentStripTruncate
|
||||||
|
? cutContent(result.contentStripTruncate.value)
|
||||||
|
: result.contentStrip
|
||||||
|
? cutContent(result.contentStrip.value)
|
||||||
|
: result.content
|
||||||
|
? cutContent(result.content.value)
|
||||||
|
: ''
|
||||||
|
return `
|
||||||
|
<a href="${link}" class="algolia-hit-item-link">
|
||||||
|
<span class="algolia-hits-item-title">${result.title.value || 'no-title'}</span>
|
||||||
|
<p class="algolia-hit-item-content">${content}</p>
|
||||||
|
</a>`
|
||||||
|
},
|
||||||
|
empty: function (data) {
|
||||||
|
return (
|
||||||
|
'<div id="algolia-hits-empty">' +
|
||||||
|
GLOBAL_CONFIG.algolia.languages.hits_empty.replace(/\$\{query}/, data.query) +
|
||||||
|
'</div>'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const stats = instantsearch.widgets.stats({
|
||||||
|
container: '#algolia-info > .algolia-stats',
|
||||||
|
templates: {
|
||||||
|
text: function (data) {
|
||||||
|
const stats = GLOBAL_CONFIG.algolia.languages.hits_stats
|
||||||
|
.replace(/\$\{hits}/, data.nbHits)
|
||||||
|
.replace(/\$\{time}/, data.processingTimeMS)
|
||||||
|
return (
|
||||||
|
`<hr>${stats}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const powerBy = instantsearch.widgets.poweredBy({
|
||||||
|
container: '#algolia-info > .algolia-poweredBy'
|
||||||
|
})
|
||||||
|
|
||||||
|
const pagination = instantsearch.widgets.pagination({
|
||||||
|
container: '#algolia-pagination',
|
||||||
|
totalPages: 5,
|
||||||
|
templates: {
|
||||||
|
first: '<i class="fas fa-angle-double-left"></i>',
|
||||||
|
last: '<i class="fas fa-angle-double-right"></i>',
|
||||||
|
previous: '<i class="fas fa-angle-left"></i>',
|
||||||
|
next: '<i class="fas fa-angle-right"></i>'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
search.addWidgets([configure, searchBox, hits, stats, powerBy, pagination]) // add the widgets to the instantsearch instance
|
||||||
|
|
||||||
|
search.start()
|
||||||
|
|
||||||
|
searchClickFn()
|
||||||
|
searchFnOnce()
|
||||||
|
|
||||||
|
window.addEventListener('pjax:complete', () => {
|
||||||
|
!btf.isHidden($searchMask) && closeSearch()
|
||||||
|
searchClickFn()
|
||||||
|
})
|
||||||
|
|
||||||
|
window.pjax && search.on('render', () => {
|
||||||
|
window.pjax.refresh(document.getElementById('algolia-hits'))
|
||||||
|
})
|
||||||
|
})
|
364
js/search/local-search.js
Normal file
364
js/search/local-search.js
Normal file
|
@ -0,0 +1,364 @@
|
||||||
|
/**
|
||||||
|
* Refer to hexo-generator-searchdb
|
||||||
|
* https://github.com/next-theme/hexo-generator-searchdb/blob/main/dist/search.js
|
||||||
|
* Modified by hexo-theme-butterfly
|
||||||
|
*/
|
||||||
|
|
||||||
|
class LocalSearch {
|
||||||
|
constructor ({
|
||||||
|
path = '',
|
||||||
|
unescape = false,
|
||||||
|
top_n_per_article = 1
|
||||||
|
}) {
|
||||||
|
this.path = path
|
||||||
|
this.unescape = unescape
|
||||||
|
this.top_n_per_article = top_n_per_article
|
||||||
|
this.isfetched = false
|
||||||
|
this.datas = null
|
||||||
|
}
|
||||||
|
|
||||||
|
getIndexByWord (words, text, caseSensitive = false) {
|
||||||
|
const index = []
|
||||||
|
const included = new Set()
|
||||||
|
|
||||||
|
if (!caseSensitive) {
|
||||||
|
text = text.toLowerCase()
|
||||||
|
}
|
||||||
|
words.forEach(word => {
|
||||||
|
if (this.unescape) {
|
||||||
|
const div = document.createElement('div')
|
||||||
|
div.innerText = word
|
||||||
|
word = div.innerHTML
|
||||||
|
}
|
||||||
|
const wordLen = word.length
|
||||||
|
if (wordLen === 0) return
|
||||||
|
let startPosition = 0
|
||||||
|
let position = -1
|
||||||
|
if (!caseSensitive) {
|
||||||
|
word = word.toLowerCase()
|
||||||
|
}
|
||||||
|
while ((position = text.indexOf(word, startPosition)) > -1) {
|
||||||
|
index.push({ position, word })
|
||||||
|
included.add(word)
|
||||||
|
startPosition = position + wordLen
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Sort index by position of keyword
|
||||||
|
index.sort((left, right) => {
|
||||||
|
if (left.position !== right.position) {
|
||||||
|
return left.position - right.position
|
||||||
|
}
|
||||||
|
return right.word.length - left.word.length
|
||||||
|
})
|
||||||
|
return [index, included]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge hits into slices
|
||||||
|
mergeIntoSlice (start, end, index) {
|
||||||
|
let item = index[0]
|
||||||
|
let { position, word } = item
|
||||||
|
const hits = []
|
||||||
|
const count = new Set()
|
||||||
|
while (position + word.length <= end && index.length !== 0) {
|
||||||
|
count.add(word)
|
||||||
|
hits.push({
|
||||||
|
position,
|
||||||
|
length: word.length
|
||||||
|
})
|
||||||
|
const wordEnd = position + word.length
|
||||||
|
|
||||||
|
// Move to next position of hit
|
||||||
|
index.shift()
|
||||||
|
while (index.length !== 0) {
|
||||||
|
item = index[0]
|
||||||
|
position = item.position
|
||||||
|
word = item.word
|
||||||
|
if (wordEnd > position) {
|
||||||
|
index.shift()
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
hits,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
count: count.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highlight title and content
|
||||||
|
highlightKeyword (val, slice) {
|
||||||
|
let result = ''
|
||||||
|
let index = slice.start
|
||||||
|
for (const { position, length } of slice.hits) {
|
||||||
|
result += val.substring(index, position)
|
||||||
|
index = position + length
|
||||||
|
result += `<mark class="search-keyword">${val.substr(position, length)}</mark>`
|
||||||
|
}
|
||||||
|
result += val.substring(index, slice.end)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
getResultItems (keywords) {
|
||||||
|
const resultItems = []
|
||||||
|
this.datas.forEach(({ title, content, url }) => {
|
||||||
|
// The number of different keywords included in the article.
|
||||||
|
const [indexOfTitle, keysOfTitle] = this.getIndexByWord(keywords, title)
|
||||||
|
const [indexOfContent, keysOfContent] = this.getIndexByWord(keywords, content)
|
||||||
|
const includedCount = new Set([...keysOfTitle, ...keysOfContent]).size
|
||||||
|
|
||||||
|
// Show search results
|
||||||
|
const hitCount = indexOfTitle.length + indexOfContent.length
|
||||||
|
if (hitCount === 0) return
|
||||||
|
|
||||||
|
const slicesOfTitle = []
|
||||||
|
if (indexOfTitle.length !== 0) {
|
||||||
|
slicesOfTitle.push(this.mergeIntoSlice(0, title.length, indexOfTitle))
|
||||||
|
}
|
||||||
|
|
||||||
|
let slicesOfContent = []
|
||||||
|
while (indexOfContent.length !== 0) {
|
||||||
|
const item = indexOfContent[0]
|
||||||
|
const { position } = item
|
||||||
|
// Cut out 120 characters. The maxlength of .search-input is 80.
|
||||||
|
const start = Math.max(0, position - 20)
|
||||||
|
const end = Math.min(content.length, position + 100)
|
||||||
|
slicesOfContent.push(this.mergeIntoSlice(start, end, indexOfContent))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort slices in content by included keywords' count and hits' count
|
||||||
|
slicesOfContent.sort((left, right) => {
|
||||||
|
if (left.count !== right.count) {
|
||||||
|
return right.count - left.count
|
||||||
|
} else if (left.hits.length !== right.hits.length) {
|
||||||
|
return right.hits.length - left.hits.length
|
||||||
|
}
|
||||||
|
return left.start - right.start
|
||||||
|
})
|
||||||
|
|
||||||
|
// Select top N slices in content
|
||||||
|
const upperBound = parseInt(this.top_n_per_article, 10)
|
||||||
|
if (upperBound >= 0) {
|
||||||
|
slicesOfContent = slicesOfContent.slice(0, upperBound)
|
||||||
|
}
|
||||||
|
|
||||||
|
let resultItem = ''
|
||||||
|
|
||||||
|
url = new URL(url, location.origin)
|
||||||
|
url.searchParams.append('highlight', keywords.join(' '))
|
||||||
|
|
||||||
|
if (slicesOfTitle.length !== 0) {
|
||||||
|
resultItem += `<div class="local-search-hit-item"><a href="${url.href}"><span class="search-result-title">${this.highlightKeyword(title, slicesOfTitle[0])}</span>`
|
||||||
|
} else {
|
||||||
|
resultItem += `<div class="local-search-hit-item"><a href="${url.href}"><span class="search-result-title">${title}</span>`
|
||||||
|
}
|
||||||
|
|
||||||
|
slicesOfContent.forEach(slice => {
|
||||||
|
resultItem += `<p class="search-result">${this.highlightKeyword(content, slice)}...</p></a>`
|
||||||
|
})
|
||||||
|
|
||||||
|
resultItem += '</div>'
|
||||||
|
resultItems.push({
|
||||||
|
item: resultItem,
|
||||||
|
id: resultItems.length,
|
||||||
|
hitCount,
|
||||||
|
includedCount
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return resultItems
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchData () {
|
||||||
|
const isXml = !this.path.endsWith('json')
|
||||||
|
fetch(this.path)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(res => {
|
||||||
|
// Get the contents from search data
|
||||||
|
this.isfetched = true
|
||||||
|
this.datas = isXml
|
||||||
|
? [...new DOMParser().parseFromString(res, 'text/xml').querySelectorAll('entry')].map(element => ({
|
||||||
|
title: element.querySelector('title').textContent,
|
||||||
|
content: element.querySelector('content').textContent,
|
||||||
|
url: element.querySelector('url').textContent
|
||||||
|
}))
|
||||||
|
: JSON.parse(res)
|
||||||
|
// Only match articles with non-empty titles
|
||||||
|
this.datas = this.datas.filter(data => data.title).map(data => {
|
||||||
|
data.title = data.title.trim()
|
||||||
|
data.content = data.content ? data.content.trim().replace(/<[^>]+>/g, '') : ''
|
||||||
|
data.url = decodeURIComponent(data.url).replace(/\/{2,}/g, '/')
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
// Remove loading animation
|
||||||
|
window.dispatchEvent(new Event('search:loaded'))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highlight by wrapping node in mark elements with the given class name
|
||||||
|
highlightText (node, slice, className) {
|
||||||
|
const val = node.nodeValue
|
||||||
|
let index = slice.start
|
||||||
|
const children = []
|
||||||
|
for (const { position, length } of slice.hits) {
|
||||||
|
const text = document.createTextNode(val.substring(index, position))
|
||||||
|
index = position + length
|
||||||
|
const mark = document.createElement('mark')
|
||||||
|
mark.className = className
|
||||||
|
mark.appendChild(document.createTextNode(val.substr(position, length)))
|
||||||
|
children.push(text, mark)
|
||||||
|
}
|
||||||
|
node.nodeValue = val.substring(index, slice.end)
|
||||||
|
children.forEach(element => {
|
||||||
|
node.parentNode.insertBefore(element, node)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highlight the search words provided in the url in the text
|
||||||
|
highlightSearchWords (body) {
|
||||||
|
const params = new URL(location.href).searchParams.get('highlight')
|
||||||
|
const keywords = params ? params.split(' ') : []
|
||||||
|
if (!keywords.length || !body) return
|
||||||
|
const walk = document.createTreeWalker(body, NodeFilter.SHOW_TEXT, null)
|
||||||
|
const allNodes = []
|
||||||
|
while (walk.nextNode()) {
|
||||||
|
if (!walk.currentNode.parentNode.matches('button, select, textarea, .mermaid')) allNodes.push(walk.currentNode)
|
||||||
|
}
|
||||||
|
allNodes.forEach(node => {
|
||||||
|
const [indexOfNode] = this.getIndexByWord(keywords, node.nodeValue)
|
||||||
|
if (!indexOfNode.length) return
|
||||||
|
const slice = this.mergeIntoSlice(0, node.nodeValue.length, indexOfNode)
|
||||||
|
this.highlightText(node, slice, 'search-keyword')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
// Search
|
||||||
|
const { path, top_n_per_article, unescape, languages } = GLOBAL_CONFIG.localSearch
|
||||||
|
const localSearch = new LocalSearch({
|
||||||
|
path,
|
||||||
|
top_n_per_article,
|
||||||
|
unescape
|
||||||
|
})
|
||||||
|
|
||||||
|
const input = document.querySelector('#local-search-input input')
|
||||||
|
const statsItem = document.getElementById('local-search-stats-wrap')
|
||||||
|
const $loadingStatus = document.getElementById('loading-status')
|
||||||
|
const isXml = !path.endsWith('json')
|
||||||
|
|
||||||
|
const inputEventFunction = () => {
|
||||||
|
if (!localSearch.isfetched) return
|
||||||
|
let searchText = input.value.trim().toLowerCase()
|
||||||
|
isXml && (searchText = searchText.replace(/</g, '<').replace(/>/g, '>'))
|
||||||
|
if (searchText !== '') $loadingStatus.innerHTML = '<i class="fas fa-spinner fa-pulse"></i>'
|
||||||
|
const keywords = searchText.split(/[-\s]+/)
|
||||||
|
const container = document.getElementById('local-search-results')
|
||||||
|
let resultItems = []
|
||||||
|
if (searchText.length > 0) {
|
||||||
|
// Perform local searching
|
||||||
|
resultItems = localSearch.getResultItems(keywords)
|
||||||
|
}
|
||||||
|
if (keywords.length === 1 && keywords[0] === '') {
|
||||||
|
container.textContent = ''
|
||||||
|
statsItem.textContent = ''
|
||||||
|
} else if (resultItems.length === 0) {
|
||||||
|
container.textContent = ''
|
||||||
|
const statsDiv = document.createElement('div')
|
||||||
|
statsDiv.className = 'search-result-stats'
|
||||||
|
statsDiv.textContent = languages.hits_empty.replace(/\$\{query}/, searchText)
|
||||||
|
statsItem.innerHTML = statsDiv.outerHTML
|
||||||
|
} else {
|
||||||
|
resultItems.sort((left, right) => {
|
||||||
|
if (left.includedCount !== right.includedCount) {
|
||||||
|
return right.includedCount - left.includedCount
|
||||||
|
} else if (left.hitCount !== right.hitCount) {
|
||||||
|
return right.hitCount - left.hitCount
|
||||||
|
}
|
||||||
|
return right.id - left.id
|
||||||
|
})
|
||||||
|
|
||||||
|
const stats = languages.hits_stats.replace(/\$\{hits}/, resultItems.length)
|
||||||
|
|
||||||
|
container.innerHTML = `<div class="search-result-list">${resultItems.map(result => result.item).join('')}</div>`
|
||||||
|
statsItem.innerHTML = `<hr><div class="search-result-stats">${stats}</div>`
|
||||||
|
window.pjax && window.pjax.refresh(container)
|
||||||
|
}
|
||||||
|
|
||||||
|
$loadingStatus.textContent = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
let loadFlag = false
|
||||||
|
const $searchMask = document.getElementById('search-mask')
|
||||||
|
const $searchDialog = document.querySelector('#local-search .search-dialog')
|
||||||
|
|
||||||
|
// fix safari
|
||||||
|
const fixSafariHeight = () => {
|
||||||
|
if (window.innerWidth < 768) {
|
||||||
|
$searchDialog.style.setProperty('--search-height', window.innerHeight + 'px')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const openSearch = () => {
|
||||||
|
const bodyStyle = document.body.style
|
||||||
|
bodyStyle.width = '100%'
|
||||||
|
bodyStyle.overflow = 'hidden'
|
||||||
|
btf.animateIn($searchMask, 'to_show 0.5s')
|
||||||
|
btf.animateIn($searchDialog, 'titleScale 0.5s')
|
||||||
|
setTimeout(() => { input.focus() }, 300)
|
||||||
|
if (!loadFlag) {
|
||||||
|
!localSearch.isfetched && localSearch.fetchData()
|
||||||
|
input.addEventListener('input', inputEventFunction)
|
||||||
|
loadFlag = true
|
||||||
|
}
|
||||||
|
// shortcut: ESC
|
||||||
|
document.addEventListener('keydown', function f (event) {
|
||||||
|
if (event.code === 'Escape') {
|
||||||
|
closeSearch()
|
||||||
|
document.removeEventListener('keydown', f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
fixSafariHeight()
|
||||||
|
window.addEventListener('resize', fixSafariHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeSearch = () => {
|
||||||
|
const bodyStyle = document.body.style
|
||||||
|
bodyStyle.width = ''
|
||||||
|
bodyStyle.overflow = ''
|
||||||
|
btf.animateOut($searchDialog, 'search_close .5s')
|
||||||
|
btf.animateOut($searchMask, 'to_hide 0.5s')
|
||||||
|
window.removeEventListener('resize', fixSafariHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchClickFn = () => {
|
||||||
|
btf.addEventListenerPjax(document.querySelector('#search-button > .search'), 'click', openSearch)
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchFnOnce = () => {
|
||||||
|
document.querySelector('#local-search .search-close-button').addEventListener('click', closeSearch)
|
||||||
|
$searchMask.addEventListener('click', closeSearch)
|
||||||
|
if (GLOBAL_CONFIG.localSearch.preload) {
|
||||||
|
localSearch.fetchData()
|
||||||
|
}
|
||||||
|
localSearch.highlightSearchWords(document.getElementById('article-container'))
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('search:loaded', () => {
|
||||||
|
const $loadDataItem = document.getElementById('loading-database')
|
||||||
|
$loadDataItem.nextElementSibling.style.display = 'block'
|
||||||
|
$loadDataItem.remove()
|
||||||
|
})
|
||||||
|
|
||||||
|
searchClickFn()
|
||||||
|
searchFnOnce()
|
||||||
|
|
||||||
|
// pjax
|
||||||
|
window.addEventListener('pjax:complete', () => {
|
||||||
|
!btf.isHidden($searchMask) && closeSearch()
|
||||||
|
localSearch.highlightSearchWords(document.getElementById('article-container'))
|
||||||
|
searchClickFn()
|
||||||
|
})
|
||||||
|
})
|
122
js/tw_cn.js
Normal file
122
js/tw_cn.js
Normal file
File diff suppressed because one or more lines are too long
296
js/utils.js
Normal file
296
js/utils.js
Normal file
|
@ -0,0 +1,296 @@
|
||||||
|
const btf = {
|
||||||
|
debounce: (func, wait = 0, immediate = false) => {
|
||||||
|
let timeout
|
||||||
|
return (...args) => {
|
||||||
|
const later = () => {
|
||||||
|
timeout = null
|
||||||
|
if (!immediate) func(...args)
|
||||||
|
}
|
||||||
|
const callNow = immediate && !timeout
|
||||||
|
clearTimeout(timeout)
|
||||||
|
timeout = setTimeout(later, wait)
|
||||||
|
if (callNow) func(...args)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
throttle: function (func, wait, options = {}) {
|
||||||
|
let timeout, context, args
|
||||||
|
let previous = 0
|
||||||
|
|
||||||
|
const later = () => {
|
||||||
|
previous = options.leading === false ? 0 : new Date().getTime()
|
||||||
|
timeout = null
|
||||||
|
func.apply(context, args)
|
||||||
|
if (!timeout) context = args = null
|
||||||
|
}
|
||||||
|
|
||||||
|
const throttled = (...params) => {
|
||||||
|
const now = new Date().getTime()
|
||||||
|
if (!previous && options.leading === false) previous = now
|
||||||
|
const remaining = wait - (now - previous)
|
||||||
|
context = this
|
||||||
|
args = params
|
||||||
|
if (remaining <= 0 || remaining > wait) {
|
||||||
|
if (timeout) {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
timeout = null
|
||||||
|
}
|
||||||
|
previous = now
|
||||||
|
func.apply(context, args)
|
||||||
|
if (!timeout) context = args = null
|
||||||
|
} else if (!timeout && options.trailing !== false) {
|
||||||
|
timeout = setTimeout(later, remaining)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return throttled
|
||||||
|
},
|
||||||
|
|
||||||
|
sidebarPaddingR: () => {
|
||||||
|
const innerWidth = window.innerWidth
|
||||||
|
const clientWidth = document.body.clientWidth
|
||||||
|
const paddingRight = innerWidth - clientWidth
|
||||||
|
if (innerWidth !== clientWidth) {
|
||||||
|
document.body.style.paddingRight = paddingRight + 'px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
snackbarShow: (text, showAction = false, duration = 2000) => {
|
||||||
|
const { position, bgLight, bgDark } = GLOBAL_CONFIG.Snackbar
|
||||||
|
const bg = document.documentElement.getAttribute('data-theme') === 'light' ? bgLight : bgDark
|
||||||
|
Snackbar.show({
|
||||||
|
text,
|
||||||
|
backgroundColor: bg,
|
||||||
|
showAction,
|
||||||
|
duration,
|
||||||
|
pos: position,
|
||||||
|
customClass: 'snackbar-css'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
diffDate: (d, more = false) => {
|
||||||
|
const dateNow = new Date()
|
||||||
|
const datePost = new Date(d)
|
||||||
|
const dateDiff = dateNow.getTime() - datePost.getTime()
|
||||||
|
const minute = 1000 * 60
|
||||||
|
const hour = minute * 60
|
||||||
|
const day = hour * 24
|
||||||
|
const month = day * 30
|
||||||
|
const { dateSuffix } = GLOBAL_CONFIG
|
||||||
|
|
||||||
|
if (!more) return parseInt(dateDiff / day)
|
||||||
|
|
||||||
|
const monthCount = dateDiff / month
|
||||||
|
const dayCount = dateDiff / day
|
||||||
|
const hourCount = dateDiff / hour
|
||||||
|
const minuteCount = dateDiff / minute
|
||||||
|
|
||||||
|
if (monthCount > 12) return datePost.toISOString().slice(0, 10)
|
||||||
|
if (monthCount >= 1) return `${parseInt(monthCount)} ${dateSuffix.month}`
|
||||||
|
if (dayCount >= 1) return `${parseInt(dayCount)} ${dateSuffix.day}`
|
||||||
|
if (hourCount >= 1) return `${parseInt(hourCount)} ${dateSuffix.hour}`
|
||||||
|
if (minuteCount >= 1) return `${parseInt(minuteCount)} ${dateSuffix.min}`
|
||||||
|
return dateSuffix.just
|
||||||
|
},
|
||||||
|
|
||||||
|
loadComment: (dom, callback) => {
|
||||||
|
if ('IntersectionObserver' in window) {
|
||||||
|
const observerItem = new IntersectionObserver((entries) => {
|
||||||
|
if (entries[0].isIntersecting) {
|
||||||
|
callback()
|
||||||
|
observerItem.disconnect()
|
||||||
|
}
|
||||||
|
}, { threshold: [0] })
|
||||||
|
observerItem.observe(dom)
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollToDest: (pos, time = 500) => {
|
||||||
|
const currentPos = window.pageYOffset
|
||||||
|
const isNavFixed = document.getElementById('page-header').classList.contains('fixed')
|
||||||
|
if (currentPos > pos || isNavFixed) pos = pos - 70
|
||||||
|
|
||||||
|
if ('scrollBehavior' in document.documentElement.style) {
|
||||||
|
window.scrollTo({
|
||||||
|
top: pos,
|
||||||
|
behavior: 'smooth'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = null
|
||||||
|
pos = +pos
|
||||||
|
window.requestAnimationFrame(function step (currentTime) {
|
||||||
|
start = !start ? currentTime : start
|
||||||
|
const progress = currentTime - start
|
||||||
|
if (currentPos < pos) {
|
||||||
|
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos)
|
||||||
|
} else {
|
||||||
|
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time))
|
||||||
|
}
|
||||||
|
if (progress < time) {
|
||||||
|
window.requestAnimationFrame(step)
|
||||||
|
} else {
|
||||||
|
window.scrollTo(0, pos)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
animateIn: (ele, text) => {
|
||||||
|
ele.style.display = 'block'
|
||||||
|
ele.style.animation = text
|
||||||
|
},
|
||||||
|
|
||||||
|
animateOut: (ele, text) => {
|
||||||
|
ele.addEventListener('animationend', function f () {
|
||||||
|
ele.style.display = ''
|
||||||
|
ele.style.animation = ''
|
||||||
|
ele.removeEventListener('animationend', f)
|
||||||
|
})
|
||||||
|
ele.style.animation = text
|
||||||
|
},
|
||||||
|
|
||||||
|
wrap: (selector, eleType, options) => {
|
||||||
|
const createEle = document.createElement(eleType)
|
||||||
|
for (const [key, value] of Object.entries(options)) {
|
||||||
|
createEle.setAttribute(key, value)
|
||||||
|
}
|
||||||
|
selector.parentNode.insertBefore(createEle, selector)
|
||||||
|
createEle.appendChild(selector)
|
||||||
|
},
|
||||||
|
|
||||||
|
isHidden: ele => ele.offsetHeight === 0 && ele.offsetWidth === 0,
|
||||||
|
|
||||||
|
getEleTop: ele => {
|
||||||
|
let actualTop = ele.offsetTop
|
||||||
|
let current = ele.offsetParent
|
||||||
|
|
||||||
|
while (current !== null) {
|
||||||
|
actualTop += current.offsetTop
|
||||||
|
current = current.offsetParent
|
||||||
|
}
|
||||||
|
|
||||||
|
return actualTop
|
||||||
|
},
|
||||||
|
|
||||||
|
loadLightbox: ele => {
|
||||||
|
const service = GLOBAL_CONFIG.lightbox
|
||||||
|
|
||||||
|
if (service === 'mediumZoom') {
|
||||||
|
mediumZoom(ele, { background: 'var(--zoom-bg)' })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (service === 'fancybox') {
|
||||||
|
Array.from(ele).forEach(i => {
|
||||||
|
if (i.parentNode.tagName !== 'A') {
|
||||||
|
const dataSrc = i.dataset.lazySrc || i.src
|
||||||
|
const dataCaption = i.title || i.alt || ''
|
||||||
|
btf.wrap(i, 'a', { href: dataSrc, 'data-fancybox': 'gallery', 'data-caption': dataCaption, 'data-thumb': dataSrc })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!window.fancyboxRun) {
|
||||||
|
Fancybox.bind('[data-fancybox]', {
|
||||||
|
Hash: false,
|
||||||
|
Thumbs: {
|
||||||
|
showOnStart: false
|
||||||
|
},
|
||||||
|
Images: {
|
||||||
|
Panzoom: {
|
||||||
|
maxScale: 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Carousel: {
|
||||||
|
transition: 'slide'
|
||||||
|
},
|
||||||
|
Toolbar: {
|
||||||
|
display: {
|
||||||
|
left: ['infobar'],
|
||||||
|
middle: [
|
||||||
|
'zoomIn',
|
||||||
|
'zoomOut',
|
||||||
|
'toggle1to1',
|
||||||
|
'rotateCCW',
|
||||||
|
'rotateCW',
|
||||||
|
'flipX',
|
||||||
|
'flipY'
|
||||||
|
],
|
||||||
|
right: ['slideshow', 'thumbs', 'close']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
window.fancyboxRun = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setLoading: {
|
||||||
|
add: ele => {
|
||||||
|
const html = `
|
||||||
|
<div class="loading-container">
|
||||||
|
<div class="loading-item">
|
||||||
|
<div></div><div></div><div></div><div></div><div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
ele.insertAdjacentHTML('afterend', html)
|
||||||
|
},
|
||||||
|
remove: ele => {
|
||||||
|
ele.nextElementSibling.remove()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateAnchor: (anchor) => {
|
||||||
|
if (anchor !== window.location.hash) {
|
||||||
|
if (!anchor) anchor = location.pathname
|
||||||
|
const title = GLOBAL_CONFIG_SITE.title
|
||||||
|
window.history.replaceState({
|
||||||
|
url: location.href,
|
||||||
|
title
|
||||||
|
}, title, anchor)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getScrollPercent: (currentTop, ele) => {
|
||||||
|
const docHeight = ele.clientHeight
|
||||||
|
const winHeight = document.documentElement.clientHeight
|
||||||
|
const headerHeight = ele.offsetTop
|
||||||
|
const contentMath = (docHeight > winHeight) ? (docHeight - winHeight) : (document.documentElement.scrollHeight - winHeight)
|
||||||
|
const scrollPercent = (currentTop - headerHeight) / (contentMath)
|
||||||
|
const scrollPercentRounded = Math.round(scrollPercent * 100)
|
||||||
|
const percentage = (scrollPercentRounded > 100) ? 100 : (scrollPercentRounded <= 0) ? 0 : scrollPercentRounded
|
||||||
|
return percentage
|
||||||
|
},
|
||||||
|
|
||||||
|
addGlobalFn: (key, fn, name = false, parent = window) => {
|
||||||
|
const globalFn = parent.globalFn || {}
|
||||||
|
const keyObj = globalFn[key] || {}
|
||||||
|
|
||||||
|
if (name && keyObj[name]) return
|
||||||
|
|
||||||
|
name = name || Object.keys(keyObj).length
|
||||||
|
keyObj[name] = fn
|
||||||
|
globalFn[key] = keyObj
|
||||||
|
parent.globalFn = globalFn
|
||||||
|
},
|
||||||
|
|
||||||
|
addEventListenerPjax: (ele, event, fn, option = false) => {
|
||||||
|
ele.addEventListener(event, fn, option)
|
||||||
|
btf.addGlobalFn('pjax', () => {
|
||||||
|
ele.removeEventListener(event, fn, option)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
removeGlobalFnEvent: (key, parent = window) => {
|
||||||
|
const { globalFn = {} } = parent
|
||||||
|
const keyObj = globalFn[key] || {}
|
||||||
|
const keyArr = Object.keys(keyObj)
|
||||||
|
if (!keyArr.length) return
|
||||||
|
keyArr.forEach(i => {
|
||||||
|
keyObj[i]()
|
||||||
|
})
|
||||||
|
delete parent.globalFn[key]
|
||||||
|
}
|
||||||
|
}
|
161
message/index.html
Normal file
161
message/index.html
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>留言板,想留言什么呢?🧐 | SharwOrangeのBlog小屋</title><meta name="author" content="SharwOrange"><meta name="copyright" content="SharwOrange"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="这是一个留言板 你可以在这里用评论功能将你 想问的 、 想说的 发送到评论区如果有回复,会使用邮件通知 如果想加友链,到 友情链接 进行申请">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="留言板,想留言什么呢?🧐">
|
||||||
|
<meta property="og:url" content="https://blog.hope-now.top:8443/message/">
|
||||||
|
<meta property="og:site_name" content="SharwOrangeのBlog小屋">
|
||||||
|
<meta property="og:description" content="这是一个留言板 你可以在这里用评论功能将你 想问的 、 想说的 发送到评论区如果有回复,会使用邮件通知 如果想加友链,到 友情链接 进行申请">
|
||||||
|
<meta property="og:locale" content="zh_CN">
|
||||||
|
<meta property="og:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png">
|
||||||
|
<meta property="article:published_time" content="2023-06-11T13:53:59.000Z">
|
||||||
|
<meta property="article:modified_time" content="2024-06-02T13:47:08.705Z">
|
||||||
|
<meta property="article:author" content="SharwOrange">
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta name="twitter:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://blog.hope-now.top:8443/message/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css?v=4.13.0"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.1/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.33/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
|
||||||
|
root: '/',
|
||||||
|
algolia: undefined,
|
||||||
|
localSearch: undefined,
|
||||||
|
translate: undefined,
|
||||||
|
noticeOutdate: undefined,
|
||||||
|
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
|
||||||
|
copy: {
|
||||||
|
success: '复制成功',
|
||||||
|
error: '复制错误',
|
||||||
|
noSupport: '浏览器不支持'
|
||||||
|
},
|
||||||
|
relativeDate: {
|
||||||
|
homepage: false,
|
||||||
|
post: false
|
||||||
|
},
|
||||||
|
runtime: '',
|
||||||
|
dateSuffix: {
|
||||||
|
just: '刚刚',
|
||||||
|
min: '分钟前',
|
||||||
|
hour: '小时前',
|
||||||
|
day: '天前',
|
||||||
|
month: '个月前'
|
||||||
|
},
|
||||||
|
copyright: undefined,
|
||||||
|
lightbox: 'fancybox',
|
||||||
|
Snackbar: undefined,
|
||||||
|
infinitegrid: {
|
||||||
|
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.11.1/dist/infinitegrid.min.js',
|
||||||
|
buttonText: '加载更多'
|
||||||
|
},
|
||||||
|
isPhotoFigcaption: false,
|
||||||
|
islazyload: false,
|
||||||
|
isAnchor: false,
|
||||||
|
percent: {
|
||||||
|
toc: true,
|
||||||
|
rightside: false,
|
||||||
|
},
|
||||||
|
autoDarkmode: false
|
||||||
|
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
|
||||||
|
title: '留言板,想留言什么呢?🧐',
|
||||||
|
isPost: false,
|
||||||
|
isHome: false,
|
||||||
|
isHighlightShrink: false,
|
||||||
|
isToc: false,
|
||||||
|
postUpdate: '2024-06-02 21:47:08'
|
||||||
|
}</script><script>(win=>{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
win.activateDarkMode = () => {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'dark')
|
||||||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||||||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
win.activateLightMode = () => {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'light')
|
||||||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||||||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const t = saveToLocal.get('theme')
|
||||||
|
|
||||||
|
if (t === 'dark') activateDarkMode()
|
||||||
|
else if (t === 'light') activateLightMode()
|
||||||
|
|
||||||
|
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 detectApple = () => {
|
||||||
|
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
|
||||||
|
document.documentElement.classList.add('apple')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detectApple()
|
||||||
|
})(window)</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">3</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><hr class="custom-hr"/></div></div><div class="page" id="body-wrap"><header class="not-home-page" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="SharwOrangeのBlog小屋"><span class="site-name">SharwOrangeのBlog小屋</span></a></span><div id="menus"><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="page-site-info"><h1 id="site-title">留言板,想留言什么呢?🧐</h1></div></header><main class="layout" id="content-inner"><div id="page"><div id="article-container"><h3 id="这是一个留言板"><a href="#这是一个留言板" class="headerlink" title="这是一个留言板"></a>这是一个留言板</h3><hr>
|
||||||
|
<p>你可以在这里用评论功能将你 <strong>想问的</strong> 、 <strong>想说的</strong> 发送到评论区<br>如果有回复,会使用邮件通知</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>如果想加友链,到 <a href="https://blog.hope-now.top/links">友情链接</a> 进行申请</p>
|
||||||
|
</blockquote>
|
||||||
|
<hr>
|
||||||
|
</div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">SharwOrange</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">3</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230904214934" title="御三家启动器外置使用教程(PCL2、HMCL、BakaXL)">御三家启动器外置使用教程(PCL2、HMCL、BakaXL)</a><time datetime="2023-09-04T13:49:34.000Z" title="发表于 2023-09-04 21:49:34">2023-09-04</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230902142755" title="让Geyser用上外置登录(使用Authlib-Injector)">让Geyser用上外置登录(使用Authlib-Injector)</a><time datetime="2023-09-02T06:27:55.000Z" title="发表于 2023-09-02 14:27:55">2023-09-02</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230609182444" title="Blog终于弄好了">Blog终于弄好了</a><time datetime="2023-06-09T10:24:44.000Z" title="发表于 2023-06-09 18:24:44">2023-06-09</time></div></div></div></div><div class="card-widget card-archives"><div class="item-headline"><i class="fas fa-archive"></i><span>归档</span></div><ul class="card-archive-list"><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/09/"><span class="card-archive-list-date">九月 2023</span><span class="card-archive-list-count">2</span></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/06/"><span class="card-archive-list-date">六月 2023</span><span class="card-archive-list-count">1</span></a></li></ul></div><div class="card-widget card-webinfo"><div class="item-headline"><i class="fas fa-chart-line"></i><span>网站资讯</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">文章数目 :</div><div class="item-count">3</div></div><div class="webinfo-item"><div class="item-name">本站访客数 :</div><div class="item-count" id="busuanzi_value_site_uv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">本站总访问量 :</div><div class="item-count" id="busuanzi_value_site_pv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">最后更新时间 :</div><div class="item-count" id="last-push-date" data-lastPushDate="2024-06-02T14:03:11.318Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">©2020 - 2024 By SharwOrange</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js?v=4.13.0"></script><script src="/js/main.js?v=4.13.0"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.33/dist/fancybox/fancybox.umd.min.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>
|
158
posts/20230609182444.html
Normal file
158
posts/20230609182444.html
Normal file
File diff suppressed because one or more lines are too long
178
posts/20230902142755.html
Normal file
178
posts/20230902142755.html
Normal file
File diff suppressed because one or more lines are too long
198
posts/20230904214934.html
Normal file
198
posts/20230904214934.html
Normal file
File diff suppressed because one or more lines are too long
165
sakurasnow/index.html
Normal file
165
sakurasnow/index.html
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>SakuraSnow 春樱冬雪 | SharwOrangeのBlog小屋</title><meta name="author" content="SharwOrange"><meta name="copyright" content="SharwOrange"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="SakuraSnow 春樱冬雪 关于Minecraft春樱冬雪春樱冬雪(SakuraSnow)前身是树叶Leafлистья服务器,但春樱冬雪与树叶Leafлистья并不同源,这就代表着春樱冬雪可以以一种全新的状态呈现在大家的眼前 人话:之前的一大堆屎山可以推倒重来了 截至2023/07/05,服务器为 高版本Mod服务器 服务器交流群 一群:871582333 KOOK:">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="SakuraSnow 春樱冬雪">
|
||||||
|
<meta property="og:url" content="https://blog.hope-now.top:8443/sakurasnow/">
|
||||||
|
<meta property="og:site_name" content="SharwOrangeのBlog小屋">
|
||||||
|
<meta property="og:description" content="SakuraSnow 春樱冬雪 关于Minecraft春樱冬雪春樱冬雪(SakuraSnow)前身是树叶Leafлистья服务器,但春樱冬雪与树叶Leafлистья并不同源,这就代表着春樱冬雪可以以一种全新的状态呈现在大家的眼前 人话:之前的一大堆屎山可以推倒重来了 截至2023/07/05,服务器为 高版本Mod服务器 服务器交流群 一群:871582333 KOOK:">
|
||||||
|
<meta property="og:locale" content="zh_CN">
|
||||||
|
<meta property="og:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png">
|
||||||
|
<meta property="article:published_time" content="2023-06-23T12:58:05.000Z">
|
||||||
|
<meta property="article:modified_time" content="2024-06-02T13:47:08.705Z">
|
||||||
|
<meta property="article:author" content="SharwOrange">
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta name="twitter:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://blog.hope-now.top:8443/sakurasnow/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css?v=4.13.0"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.1/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.33/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
|
||||||
|
root: '/',
|
||||||
|
algolia: undefined,
|
||||||
|
localSearch: undefined,
|
||||||
|
translate: undefined,
|
||||||
|
noticeOutdate: undefined,
|
||||||
|
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
|
||||||
|
copy: {
|
||||||
|
success: '复制成功',
|
||||||
|
error: '复制错误',
|
||||||
|
noSupport: '浏览器不支持'
|
||||||
|
},
|
||||||
|
relativeDate: {
|
||||||
|
homepage: false,
|
||||||
|
post: false
|
||||||
|
},
|
||||||
|
runtime: '',
|
||||||
|
dateSuffix: {
|
||||||
|
just: '刚刚',
|
||||||
|
min: '分钟前',
|
||||||
|
hour: '小时前',
|
||||||
|
day: '天前',
|
||||||
|
month: '个月前'
|
||||||
|
},
|
||||||
|
copyright: undefined,
|
||||||
|
lightbox: 'fancybox',
|
||||||
|
Snackbar: undefined,
|
||||||
|
infinitegrid: {
|
||||||
|
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.11.1/dist/infinitegrid.min.js',
|
||||||
|
buttonText: '加载更多'
|
||||||
|
},
|
||||||
|
isPhotoFigcaption: false,
|
||||||
|
islazyload: false,
|
||||||
|
isAnchor: false,
|
||||||
|
percent: {
|
||||||
|
toc: true,
|
||||||
|
rightside: false,
|
||||||
|
},
|
||||||
|
autoDarkmode: false
|
||||||
|
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
|
||||||
|
title: 'SakuraSnow 春樱冬雪',
|
||||||
|
isPost: false,
|
||||||
|
isHome: false,
|
||||||
|
isHighlightShrink: false,
|
||||||
|
isToc: false,
|
||||||
|
postUpdate: '2024-06-02 21:47:08'
|
||||||
|
}</script><script>(win=>{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
win.activateDarkMode = () => {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'dark')
|
||||||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||||||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
win.activateLightMode = () => {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'light')
|
||||||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||||||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const t = saveToLocal.get('theme')
|
||||||
|
|
||||||
|
if (t === 'dark') activateDarkMode()
|
||||||
|
else if (t === 'light') activateLightMode()
|
||||||
|
|
||||||
|
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 detectApple = () => {
|
||||||
|
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
|
||||||
|
document.documentElement.classList.add('apple')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detectApple()
|
||||||
|
})(window)</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">3</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><hr class="custom-hr"/></div></div><div class="page" id="body-wrap"><header class="not-home-page" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="SharwOrangeのBlog小屋"><span class="site-name">SharwOrangeのBlog小屋</span></a></span><div id="menus"><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="page-site-info"><h1 id="site-title">SakuraSnow 春樱冬雪</h1></div></header><main class="layout" id="content-inner"><div id="page"><div id="article-container"><h2 id="SakuraSnow-春樱冬雪"><a href="#SakuraSnow-春樱冬雪" class="headerlink" title="SakuraSnow 春樱冬雪"></a>SakuraSnow 春樱冬雪</h2><hr>
|
||||||
|
<h3 id="关于Minecraft春樱冬雪"><a href="#关于Minecraft春樱冬雪" class="headerlink" title="关于Minecraft春樱冬雪"></a>关于Minecraft春樱冬雪</h3><p>春樱冬雪(SakuraSnow)前身是树叶Leafлистья服务器,但春樱冬雪与树叶Leafлистья并不同源,这就代表着春樱冬雪可以以一种全新的状态呈现在大家的眼前 <del>人话:之前的一大堆屎山可以推倒重来了</del></p>
|
||||||
|
<p>截至2023/07/05,服务器为 高版本Mod服务器</p>
|
||||||
|
<hr>
|
||||||
|
<h3 id="服务器交流群"><a href="#服务器交流群" class="headerlink" title="服务器交流群"></a>服务器交流群</h3><ul>
|
||||||
|
<li>一群:871582333</li>
|
||||||
|
<li>KOOK:<a target="_blank" rel="noopener" href="https://kook.top/dCe2oG">dCe2oG</a></li>
|
||||||
|
</ul>
|
||||||
|
<hr>
|
||||||
|
<h3 id="资源下载"><a href="#资源下载" class="headerlink" title="资源下载"></a>资源下载</h3><p>下面的链接将会带往文件站,一般情况请下载最新文件(即带有latest字样的压缩包)<br>(一般情况下下载客户端即可,另外一个modpack的压缩包是不包含MC本体的,请不要下载,除非你知道你在干什么)<br><strong><a target="_blank" rel="noopener" href="https://files.sakurasnow.top/SakuraSnow/SakuraSnow1.18.2ModClient/">客户端</a></strong><br>如果浏览器自带下载器速度过慢,可以选择使用IDM,或者将files.sakurasnow.top换成link.hope-now.top:25543以使用直连链接</p>
|
||||||
|
</div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">SharwOrange</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">3</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230904214934" title="御三家启动器外置使用教程(PCL2、HMCL、BakaXL)">御三家启动器外置使用教程(PCL2、HMCL、BakaXL)</a><time datetime="2023-09-04T13:49:34.000Z" title="发表于 2023-09-04 21:49:34">2023-09-04</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230902142755" title="让Geyser用上外置登录(使用Authlib-Injector)">让Geyser用上外置登录(使用Authlib-Injector)</a><time datetime="2023-09-02T06:27:55.000Z" title="发表于 2023-09-02 14:27:55">2023-09-02</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230609182444" title="Blog终于弄好了">Blog终于弄好了</a><time datetime="2023-06-09T10:24:44.000Z" title="发表于 2023-06-09 18:24:44">2023-06-09</time></div></div></div></div><div class="card-widget card-archives"><div class="item-headline"><i class="fas fa-archive"></i><span>归档</span></div><ul class="card-archive-list"><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/09/"><span class="card-archive-list-date">九月 2023</span><span class="card-archive-list-count">2</span></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/06/"><span class="card-archive-list-date">六月 2023</span><span class="card-archive-list-count">1</span></a></li></ul></div><div class="card-widget card-webinfo"><div class="item-headline"><i class="fas fa-chart-line"></i><span>网站资讯</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">文章数目 :</div><div class="item-count">3</div></div><div class="webinfo-item"><div class="item-name">本站访客数 :</div><div class="item-count" id="busuanzi_value_site_uv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">本站总访问量 :</div><div class="item-count" id="busuanzi_value_site_pv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">最后更新时间 :</div><div class="item-count" id="last-push-date" data-lastPushDate="2024-06-02T14:03:11.318Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">©2020 - 2024 By SharwOrange</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js?v=4.13.0"></script><script src="/js/main.js?v=4.13.0"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.33/dist/fancybox/fancybox.umd.min.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>
|
157
sites/index.html
Normal file
157
sites/index.html
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>居然有人闲得慌搭建这么多网站😢 | SharwOrangeのBlog小屋</title><meta name="author" content="SharwOrange"><meta name="copyright" content="SharwOrange"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="- 树叶Leafлистья验证系统- 希望在即官方网站- 希望在即文件系统- SharwOrangeのBlog小屋 嗯哼?你问我为什么都是同一个域名不同端口因为根本就没有公网80机器啦!只能一个机器加上多个端口">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="居然有人闲得慌搭建这么多网站😢">
|
||||||
|
<meta property="og:url" content="https://blog.hope-now.top:8443/sites/">
|
||||||
|
<meta property="og:site_name" content="SharwOrangeのBlog小屋">
|
||||||
|
<meta property="og:description" content="- 树叶Leafлистья验证系统- 希望在即官方网站- 希望在即文件系统- SharwOrangeのBlog小屋 嗯哼?你问我为什么都是同一个域名不同端口因为根本就没有公网80机器啦!只能一个机器加上多个端口">
|
||||||
|
<meta property="og:locale" content="zh_CN">
|
||||||
|
<meta property="og:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png">
|
||||||
|
<meta property="article:published_time" content="2023-06-09T09:33:45.000Z">
|
||||||
|
<meta property="article:modified_time" content="2024-06-02T13:47:08.705Z">
|
||||||
|
<meta property="article:author" content="SharwOrange">
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta name="twitter:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://blog.hope-now.top:8443/sites/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css?v=4.13.0"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.1/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.33/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
|
||||||
|
root: '/',
|
||||||
|
algolia: undefined,
|
||||||
|
localSearch: undefined,
|
||||||
|
translate: undefined,
|
||||||
|
noticeOutdate: undefined,
|
||||||
|
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
|
||||||
|
copy: {
|
||||||
|
success: '复制成功',
|
||||||
|
error: '复制错误',
|
||||||
|
noSupport: '浏览器不支持'
|
||||||
|
},
|
||||||
|
relativeDate: {
|
||||||
|
homepage: false,
|
||||||
|
post: false
|
||||||
|
},
|
||||||
|
runtime: '',
|
||||||
|
dateSuffix: {
|
||||||
|
just: '刚刚',
|
||||||
|
min: '分钟前',
|
||||||
|
hour: '小时前',
|
||||||
|
day: '天前',
|
||||||
|
month: '个月前'
|
||||||
|
},
|
||||||
|
copyright: undefined,
|
||||||
|
lightbox: 'fancybox',
|
||||||
|
Snackbar: undefined,
|
||||||
|
infinitegrid: {
|
||||||
|
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.11.1/dist/infinitegrid.min.js',
|
||||||
|
buttonText: '加载更多'
|
||||||
|
},
|
||||||
|
isPhotoFigcaption: false,
|
||||||
|
islazyload: false,
|
||||||
|
isAnchor: false,
|
||||||
|
percent: {
|
||||||
|
toc: true,
|
||||||
|
rightside: false,
|
||||||
|
},
|
||||||
|
autoDarkmode: false
|
||||||
|
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
|
||||||
|
title: '居然有人闲得慌搭建这么多网站😢',
|
||||||
|
isPost: false,
|
||||||
|
isHome: false,
|
||||||
|
isHighlightShrink: false,
|
||||||
|
isToc: false,
|
||||||
|
postUpdate: '2024-06-02 21:47:08'
|
||||||
|
}</script><script>(win=>{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
win.activateDarkMode = () => {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'dark')
|
||||||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||||||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
win.activateLightMode = () => {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'light')
|
||||||
|
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||||||
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const t = saveToLocal.get('theme')
|
||||||
|
|
||||||
|
if (t === 'dark') activateDarkMode()
|
||||||
|
else if (t === 'light') activateLightMode()
|
||||||
|
|
||||||
|
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 detectApple = () => {
|
||||||
|
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
|
||||||
|
document.documentElement.classList.add('apple')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detectApple()
|
||||||
|
})(window)</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">3</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><hr class="custom-hr"/></div></div><div class="page" id="body-wrap"><header class="not-home-page" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="SharwOrangeのBlog小屋"><span class="site-name">SharwOrangeのBlog小屋</span></a></span><div id="menus"><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="page-site-info"><h1 id="site-title">居然有人闲得慌搭建这么多网站😢</h1></div></header><main class="layout" id="content-inner"><div id="page"><div id="article-container"><h4 id="树叶Leafлистья验证系统"><a href="#树叶Leafлистья验证系统" class="headerlink" title="- 树叶Leafлистья验证系统"></a>- <a target="_blank" rel="noopener" href="http://link.hope-now.top:25542/">树叶Leafлистья验证系统</a></h4><h4 id="希望在即官方网站"><a href="#希望在即官方网站" class="headerlink" title="- 希望在即官方网站"></a>- <a target="_blank" rel="noopener" href="http://link.hope-now.top:25538/">希望在即官方网站</a></h4><h4 id="希望在即文件系统"><a href="#希望在即文件系统" class="headerlink" title="- 希望在即文件系统"></a>- <a target="_blank" rel="noopener" href="http://link.hope-now.top:25539/">希望在即文件系统</a></h4><h4 id="SharwOrangeのBlog小屋"><a href="#SharwOrangeのBlog小屋" class="headerlink" title="- SharwOrangeのBlog小屋"></a>- <a href="https://blog.hope-now.top/">SharwOrangeのBlog小屋</a></h4><hr>
|
||||||
|
<p>嗯哼?你问我为什么都是同一个域名不同端口<br>因为根本就没有公网80机器啦!只能一个机器加上多个端口</p>
|
||||||
|
</div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">SharwOrange</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">3</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230904214934" title="御三家启动器外置使用教程(PCL2、HMCL、BakaXL)">御三家启动器外置使用教程(PCL2、HMCL、BakaXL)</a><time datetime="2023-09-04T13:49:34.000Z" title="发表于 2023-09-04 21:49:34">2023-09-04</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230902142755" title="让Geyser用上外置登录(使用Authlib-Injector)">让Geyser用上外置登录(使用Authlib-Injector)</a><time datetime="2023-09-02T06:27:55.000Z" title="发表于 2023-09-02 14:27:55">2023-09-02</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/20230609182444" title="Blog终于弄好了">Blog终于弄好了</a><time datetime="2023-06-09T10:24:44.000Z" title="发表于 2023-06-09 18:24:44">2023-06-09</time></div></div></div></div><div class="card-widget card-archives"><div class="item-headline"><i class="fas fa-archive"></i><span>归档</span></div><ul class="card-archive-list"><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/09/"><span class="card-archive-list-date">九月 2023</span><span class="card-archive-list-count">2</span></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/06/"><span class="card-archive-list-date">六月 2023</span><span class="card-archive-list-count">1</span></a></li></ul></div><div class="card-widget card-webinfo"><div class="item-headline"><i class="fas fa-chart-line"></i><span>网站资讯</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">文章数目 :</div><div class="item-count">3</div></div><div class="webinfo-item"><div class="item-name">本站访客数 :</div><div class="item-count" id="busuanzi_value_site_uv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">本站总访问量 :</div><div class="item-count" id="busuanzi_value_site_pv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">最后更新时间 :</div><div class="item-count" id="last-push-date" data-lastPushDate="2024-06-02T14:03:11.318Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">©2020 - 2024 By SharwOrange</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js?v=4.13.0"></script><script src="/js/main.js?v=4.13.0"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.33/dist/fancybox/fancybox.umd.min.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>
|
Loading…
Reference in New Issue
Block a user