fix theme...
|
|
@ -4,7 +4,50 @@
|
||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="de9fa6e3-30cd-4bd9-9de2-e5d7f0390fc8" name="更改" comment="" />
|
<list default="true" id="de9fa6e3-30cd-4bd9-9de2-e5d7f0390fc8" name="更改" comment="">
|
||||||
|
<change afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/_config.butterfly1.yml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/favicon.ico" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/512.png" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/algolia.svg" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/comment_bg.png" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/default_cover.jpg" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/favicon.ico" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/loading.gif" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/siteicon/16.png" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/siteicon/32.png" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/siteicon/apple-icon-180.png" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/siteicon/manifest-icon-192.maskable.png" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/img/siteicon/manifest-icon-512.maskable.png" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/js/anzhiyu/ai_abstract.js" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/js/anzhiyu/comment_barrage.js" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/js/anzhiyu/people.js" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/js/anzhiyu/random_friends_post.js" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/js/anzhiyu/right_click_menu.js" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/source/categories/index.md" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/source/tags/index.md" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/_config.anzhiyu.yml" beforeDir="false" afterPath="$PROJECT_DIR$/_config.anzhiyu.yml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/_config.butterfly.yml" beforeDir="false" afterPath="$PROJECT_DIR$/_config.butterfly.yml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/_config.yml" beforeDir="false" afterPath="$PROJECT_DIR$/_config.yml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/db.json" beforeDir="false" afterPath="$PROJECT_DIR$/db.json" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/2024/07/30/about/me/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/public/2024/07/30/about/me/index.html" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/2024/07/30/hello-world/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/public/2024/07/30/hello-world/index.html" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/404.html" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/archives/2024/07/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/public/archives/2024/07/index.html" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/archives/2024/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/public/archives/2024/index.html" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/archives/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/public/archives/index.html" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/css/index.css" beforeDir="false" afterPath="$PROJECT_DIR$/public/css/index.css" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/img/404.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/public/img/404.jpg" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/img/avatar.jpg" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/img/favicon.png" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/img/friend_404.gif" beforeDir="false" afterPath="$PROJECT_DIR$/public/img/friend_404.gif" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/public/index.html" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/js/main.js" beforeDir="false" afterPath="$PROJECT_DIR$/public/js/main.js" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/js/search/algolia.js" beforeDir="false" afterPath="$PROJECT_DIR$/public/js/search/algolia.js" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/js/search/local-search.js" beforeDir="false" afterPath="$PROJECT_DIR$/public/js/search/local-search.js" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/js/tw_cn.js" beforeDir="false" afterPath="$PROJECT_DIR$/public/js/tw_cn.js" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/js/utils.js" beforeDir="false" afterPath="$PROJECT_DIR$/public/js/utils.js" afterDir="false" />
|
||||||
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
|
@ -18,7 +61,7 @@
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="Git.Settings">
|
<component name="Git.Settings">
|
||||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/themes/butterfly" />
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="GitHubPullRequestSearchHistory">{
|
<component name="GitHubPullRequestSearchHistory">{
|
||||||
"lastFilter": {
|
"lastFilter": {
|
||||||
|
|
@ -37,17 +80,21 @@
|
||||||
"associatedIndex": 8
|
"associatedIndex": 8
|
||||||
}</component>
|
}</component>
|
||||||
<component name="ProjectId" id="2jxaBMaq32ZWf7XyMTBhC0qvzci" />
|
<component name="ProjectId" id="2jxaBMaq32ZWf7XyMTBhC0qvzci" />
|
||||||
|
<component name="ProjectLevelVcsManager">
|
||||||
|
<ConfirmationsSetting value="2" id="Add" />
|
||||||
|
</component>
|
||||||
<component name="ProjectViewState">
|
<component name="ProjectViewState">
|
||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">{
|
<component name="PropertiesComponent">{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
|
"ASKED_ADD_EXTERNAL_FILES": "true",
|
||||||
"DefaultHtmlFileTemplate": "HTML File",
|
"DefaultHtmlFileTemplate": "HTML File",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"git-widget-placeholder": ".invalid",
|
"git-widget-placeholder": "master",
|
||||||
"kotlin-language-version-configured": "true",
|
"kotlin-language-version-configured": "true",
|
||||||
"last_opened_file_path": "D:/JetBrainsToolProject/InteliJIDEA/qr-hexo",
|
"last_opened_file_path": "D:/JetBrainsToolProject/InteliJIDEA/test-qr/qr",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.detected.package.tslint": "true",
|
"node.js.detected.package.tslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
|
|
@ -114,10 +161,16 @@
|
||||||
<updated>1722331046875</updated>
|
<updated>1722331046875</updated>
|
||||||
<workItem from="1722331047325" duration="8230000" />
|
<workItem from="1722331047325" duration="8230000" />
|
||||||
<workItem from="1722339532652" duration="1879000" />
|
<workItem from="1722339532652" duration="1879000" />
|
||||||
|
<workItem from="1722346590186" duration="1768000" />
|
||||||
|
<workItem from="1722385471856" duration="1455000" />
|
||||||
|
<workItem from="1722405691335" duration="3656000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
<option name="version" value="3" />
|
<option name="version" value="3" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="VcsManagerConfiguration">
|
||||||
|
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
|
||||||
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
### anzhiyu主题
|
||||||
|
**启动**
|
||||||
|
```shell
|
||||||
|
hexo cl && hexo g && hexo s
|
||||||
|
```
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
menu:
|
menu:
|
||||||
# 文章:
|
文章:
|
||||||
# 隧道: /archives/ || anzhiyu-icon-box-archive
|
隧道: /archives/ || anzhiyu-icon-box-archive
|
||||||
# 分类: /categories/ || anzhiyu-icon-shapes
|
分类: /categories/ || anzhiyu-icon-shapes
|
||||||
# 标签: /tags/ || anzhiyu-icon-tags
|
标签: /tags/ || anzhiyu-icon-tags
|
||||||
|
|
||||||
# 友链:
|
友链:
|
||||||
# 友人帐: /link/ || anzhiyu-icon-link
|
友人帐: /link/ || anzhiyu-icon-link
|
||||||
# 朋友圈: /fcircle/ || anzhiyu-icon-artstation
|
朋友圈: /fcircle/ || anzhiyu-icon-artstation
|
||||||
# 留言板: /comments/ || anzhiyu-icon-envelope
|
留言板: /comments/ || anzhiyu-icon-envelope
|
||||||
|
|
||||||
# 我的:
|
我的:
|
||||||
# 音乐馆: /music/ || anzhiyu-icon-music
|
音乐馆: /music/ || anzhiyu-icon-music
|
||||||
# 追番页: /bangumis/ || anzhiyu-icon-bilibili
|
追番页: /bangumis/ || anzhiyu-icon-bilibili
|
||||||
# 相册集: /album/ || anzhiyu-icon-images
|
相册集: /album/ || anzhiyu-icon-images
|
||||||
# 小空调: /air-conditioner/ || anzhiyu-icon-fan
|
小空调: /air-conditioner/ || anzhiyu-icon-fan
|
||||||
|
|
||||||
# 关于:
|
关于:
|
||||||
# 关于本人: /about/ || anzhiyu-icon-paper-plane
|
关于本人: /about/ || anzhiyu-icon-paper-plane
|
||||||
# 闲言碎语: /essay/ || anzhiyu-icon-lightbulb
|
闲言碎语: /essay/ || anzhiyu-icon-lightbulb
|
||||||
# 随便逛逛: javascript:toRandomPost() || anzhiyu-icon-shoe-prints1
|
随便逛逛: javascript:toRandomPost() || anzhiyu-icon-shoe-prints1
|
||||||
|
|
||||||
# nav相关配置
|
# nav相关配置
|
||||||
nav:
|
nav:
|
||||||
enable: false
|
enable: enable
|
||||||
travelling: false
|
travelling: false
|
||||||
clock: false
|
clock: false
|
||||||
menu:
|
menu:
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ menu:
|
||||||
highlight_theme: mac # darker / pale night / light / ocean / mac / mac light / false
|
highlight_theme: mac # darker / pale night / light / ocean / mac / mac light / false
|
||||||
highlight_copy: true # copy button
|
highlight_copy: true # copy button
|
||||||
highlight_lang: true # show the code language
|
highlight_lang: true # show the code language
|
||||||
highlight_shrink: false # true: shrink the code blocks / false: expand the code blocks | none: expand code blocks and hide the button
|
highlight_shrink: true # true: shrink the code blocks / false: expand the code blocks | none: expand code blocks and hide the button
|
||||||
highlight_height_limit: false # unit: px
|
highlight_height_limit: false # unit: px
|
||||||
code_word_wrap: false
|
code_word_wrap: false
|
||||||
|
|
||||||
|
|
@ -207,8 +207,8 @@ noticeOutdate:
|
||||||
footer:
|
footer:
|
||||||
owner:
|
owner:
|
||||||
enable: true
|
enable: true
|
||||||
since: 2020
|
since: 2024
|
||||||
custom_text: <a href="icp链接"><img class="icp-icon" src="icp图片"><span>备案号:xxxxxx</span></a>
|
custom_text: <span>备案号:豫ICP备2023019300号</span>
|
||||||
|
|
||||||
# aside (側邊欄)
|
# aside (側邊欄)
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
|
|
@ -224,7 +224,7 @@ aside:
|
||||||
tag: false
|
tag: false
|
||||||
category: false
|
category: false
|
||||||
card_author:
|
card_author:
|
||||||
enable: false
|
enable: true
|
||||||
description:
|
description:
|
||||||
button:
|
button:
|
||||||
enable: true
|
enable: true
|
||||||
|
|
@ -232,7 +232,7 @@ aside:
|
||||||
text: Follow Me
|
text: Follow Me
|
||||||
link: https://github.com/shenjianz
|
link: https://github.com/shenjianz
|
||||||
card_announcement:
|
card_announcement:
|
||||||
enable: false
|
enable: true
|
||||||
content: '一个简单快捷的文档知识点查阅网站'
|
content: '一个简单快捷的文档知识点查阅网站'
|
||||||
card_recent_post:
|
card_recent_post:
|
||||||
enable: true
|
enable: true
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ subtitle: '实用知识文档'
|
||||||
description: '一份快捷简便的文档,便于查阅编程的细节'
|
description: '一份快捷简便的文档,便于查阅编程的细节'
|
||||||
keywords: doucment
|
keywords: doucment
|
||||||
author: shenjianZ
|
author: shenjianZ
|
||||||
language: zh-Hans
|
language: zh-CN
|
||||||
timezone: 'Asia/Shanghai'
|
timezone: 'Asia/Shanghai'
|
||||||
|
|
||||||
# URL
|
# URL
|
||||||
|
|
@ -97,7 +97,7 @@ ignore:
|
||||||
## Plugins: https://hexo.io/plugins/
|
## Plugins: https://hexo.io/plugins/
|
||||||
## Themes: https://hexo.io/themes/
|
## Themes: https://hexo.io/themes/
|
||||||
theme: butterfly
|
theme: butterfly
|
||||||
|
#theme: anzhiyu
|
||||||
# Deployment
|
# Deployment
|
||||||
## Docs: https://hexo.io/docs/one-command-deployment
|
## Docs: https://hexo.io/docs/one-command-deployment
|
||||||
deploy:
|
deploy:
|
||||||
|
|
|
||||||
154
public/404.html
|
|
@ -1,154 +0,0 @@
|
||||||
<!DOCTYPE html><html lang="zh-Hans" 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>Page Not Found | QuickReference</title><meta name="author" content="shenjianZ"><meta name="copyright" content="shenjianZ"><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="QuickReference">
|
|
||||||
<meta property="og:url" content="http://rq.shenjianl.cn/404.html">
|
|
||||||
<meta property="og:site_name" content="QuickReference">
|
|
||||||
<meta property="og:description" content="一份快捷简便的文档,便于查阅编程的细节">
|
|
||||||
<meta property="og:locale">
|
|
||||||
<meta property="og:image" content="http://rq.shenjianl.cn/img/avatar.jpg">
|
|
||||||
<meta property="article:author" content="shenjianZ">
|
|
||||||
<meta property="article:tag" content="doucment">
|
|
||||||
<meta name="twitter:card" content="summary">
|
|
||||||
<meta name="twitter:image" content="http://rq.shenjianl.cn/img/avatar.jpg"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://rq.shenjianl.cn/404.html"><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: 'Copy Successful',
|
|
||||||
error: 'Copy Error',
|
|
||||||
noSupport: 'Browser Not Supported'
|
|
||||||
},
|
|
||||||
relativeDate: {
|
|
||||||
homepage: false,
|
|
||||||
post: false
|
|
||||||
},
|
|
||||||
runtime: 'days',
|
|
||||||
dateSuffix: {
|
|
||||||
just: 'Just now',
|
|
||||||
min: 'minutes ago',
|
|
||||||
hour: 'hours ago',
|
|
||||||
day: 'days ago',
|
|
||||||
month: 'months ago'
|
|
||||||
},
|
|
||||||
copyright: undefined,
|
|
||||||
lightbox: 'fancybox',
|
|
||||||
Snackbar: undefined,
|
|
||||||
infinitegrid: {
|
|
||||||
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.11.1/dist/infinitegrid.min.js',
|
|
||||||
buttonText: 'Load More'
|
|
||||||
},
|
|
||||||
isPhotoFigcaption: false,
|
|
||||||
islazyload: false,
|
|
||||||
isAnchor: false,
|
|
||||||
percent: {
|
|
||||||
toc: true,
|
|
||||||
rightside: false,
|
|
||||||
},
|
|
||||||
autoDarkmode: false
|
|
||||||
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
|
|
||||||
title: 'Page Not Found',
|
|
||||||
isPost: false,
|
|
||||||
isHome: false,
|
|
||||||
isHighlightShrink: false,
|
|
||||||
isToc: false,
|
|
||||||
postUpdate: '2024-07-30 21:38:06'
|
|
||||||
}</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 7.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="/img/avatar.jpg" 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">Articles</div><div class="length-num">2</div></a><a href="/tags/"><div class="headline">Tags</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">Categories</div><div class="length-num">0</div></a></div><hr class="custom-hr"/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> Home</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> Archives</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> Tags</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> Categories</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> List</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/music/"><i class="fa-fw fas fa-music"></i><span> Music</span></a></li><li><a class="site-page child" href="/movies/"><i class="fa-fw fas fa-video"></i><span> Movie</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> Link</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> About</span></a></div></div></div></div><div class="error404" id="body-wrap"><header class="not-top-img fixed" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="QuickReference"><span class="site-name">QuickReference</span></a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> Home</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> Archives</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> Tags</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> Categories</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> List</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/music/"><i class="fa-fw fas fa-music"></i><span> Music</span></a></li><li><a class="site-page child" href="/movies/"><i class="fa-fw fas fa-video"></i><span> Movie</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> Link</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> About</span></a></div></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav></header><div id="error-wrap"><div class="error-content"><div class="error-img"><img src="https://i.loli.net/2020/05/19/aKOcLiyPl2JQdFD.png" alt="Page not found"></div><div class="error-info"><h1 class="error_title">404</h1><div class="error_subtitle">Page Not Found</div></div></div></div></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="Toggle Between Light And Dark Mode"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="Toggle between Single-column and Double-column"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="Setting"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="Back To Top"><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>
|
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
<!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>categories | QuickReference</title><meta name="author" content="shenjianZ"><meta name="copyright" content="shenjianZ"><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="categories">
|
||||||
|
<meta property="og:url" content="http://rq.shenjianl.cn/categories/index.html">
|
||||||
|
<meta property="og:site_name" content="QuickReference">
|
||||||
|
<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="2024-07-31T00:33:49.000Z">
|
||||||
|
<meta property="article:modified_time" content="2024-07-31T00:34:01.357Z">
|
||||||
|
<meta property="article:author" content="shenjianZ">
|
||||||
|
<meta property="article:tag" content="doucment">
|
||||||
|
<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="http://rq.shenjianl.cn/categories/index.html"><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: 'categories',
|
||||||
|
isPost: false,
|
||||||
|
isHome: false,
|
||||||
|
isHighlightShrink: false,
|
||||||
|
isToc: false,
|
||||||
|
postUpdate: '2024-07-31 08:34:01'
|
||||||
|
}</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 7.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">2</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-top-img" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="QuickReference"><span class="site-name">QuickReference</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></header><main class="layout hide-aside" id="content-inner"><div id="page"><h1 class="page-title">categories</h1><div class="category-lists"></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">©2020 - 2024 By shenjianZ</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></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><canvas class="fireworks" mobile="false"></canvas><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/dist/fireworks.min.js"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>
|
||||||
24543
public/css/index.css
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 590 KiB |
|
Before Width: | Height: | Size: 721 KiB After Width: | Height: | Size: 721 KiB |
|
Before Width: | Height: | Size: 283 B After Width: | Height: | Size: 283 B |
|
Before Width: | Height: | Size: 431 B After Width: | Height: | Size: 431 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
2089
public/js/main.js
|
|
@ -1,177 +1,192 @@
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener("load", () => {
|
||||||
const $searchMask = document.getElementById('search-mask')
|
const $searchMask = document.getElementById("search-mask");
|
||||||
const $searchDialog = document.querySelector('#algolia-search .search-dialog')
|
const $searchDialog = document.querySelector("#algolia-search .search-dialog");
|
||||||
|
|
||||||
const openSearch = () => {
|
const openSearch = () => {
|
||||||
const bodyStyle = document.body.style
|
anzhiyu.animateIn($searchMask, "to_show 0.5s");
|
||||||
bodyStyle.width = '100%'
|
$searchDialog.style.display = "block";
|
||||||
bodyStyle.overflow = 'hidden'
|
setTimeout(() => {
|
||||||
btf.animateIn($searchMask, 'to_show 0.5s')
|
document.querySelector("#algolia-search .ais-SearchBox-input").focus();
|
||||||
btf.animateIn($searchDialog, 'titleScale 0.5s')
|
}, 100);
|
||||||
setTimeout(() => { document.querySelector('#algolia-search .ais-SearchBox-input').focus() }, 100)
|
|
||||||
|
|
||||||
// shortcut: ESC
|
// shortcut: ESC
|
||||||
document.addEventListener('keydown', function f (event) {
|
document.addEventListener("keydown", function f(event) {
|
||||||
if (event.code === 'Escape') {
|
if (event.code === "Escape") {
|
||||||
closeSearch()
|
closeSearch();
|
||||||
document.removeEventListener('keydown', f)
|
document.removeEventListener("keydown", f);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
fixSafariHeight()
|
fixSafariHeight();
|
||||||
window.addEventListener('resize', fixSafariHeight)
|
window.addEventListener("resize", fixSafariHeight);
|
||||||
|
};
|
||||||
|
|
||||||
|
// shortcut: shift+S
|
||||||
|
if (anzhiyu_keyboard) {
|
||||||
|
window.addEventListener("keydown", function (event) {
|
||||||
|
if (event.keyCode == 83 && event.shiftKey) {
|
||||||
|
console.info(selectTextNow);
|
||||||
|
if (selectTextNow) {
|
||||||
|
openSearch();
|
||||||
|
const t = document.querySelector("#algolia-search-input > div > form > input");
|
||||||
|
t.value = selectTextNow;
|
||||||
|
t.dispatchEvent(new Event("input"));
|
||||||
|
setTimeout(() => {
|
||||||
|
document.querySelector("#algolia-search-input > div > form > button.ais-SearchBox-submit").click();
|
||||||
|
}, 64);
|
||||||
|
} else {
|
||||||
|
openSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const closeSearch = () => {
|
const closeSearch = () => {
|
||||||
const bodyStyle = document.body.style
|
anzhiyu.animateOut($searchDialog, "search_close .5s");
|
||||||
bodyStyle.width = ''
|
anzhiyu.animateOut($searchMask, "to_hide 0.5s");
|
||||||
bodyStyle.overflow = ''
|
window.removeEventListener("resize", fixSafariHeight);
|
||||||
btf.animateOut($searchDialog, 'search_close .5s')
|
};
|
||||||
btf.animateOut($searchMask, 'to_hide 0.5s')
|
|
||||||
window.removeEventListener('resize', fixSafariHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fix safari
|
// fix safari
|
||||||
const fixSafariHeight = () => {
|
const fixSafariHeight = () => {
|
||||||
if (window.innerWidth < 768) {
|
if (window.innerWidth < 768) {
|
||||||
$searchDialog.style.setProperty('--search-height', window.innerHeight + 'px')
|
$searchDialog.style.setProperty("--search-height", window.innerHeight + "px");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const searchClickFn = () => {
|
const searchClickFn = () => {
|
||||||
btf.addEventListenerPjax(document.querySelector('#search-button > .search'), 'click', openSearch)
|
anzhiyu.addEventListenerPjax(document.querySelector("#search-button > .search"), "click", openSearch);
|
||||||
}
|
};
|
||||||
|
|
||||||
const searchFnOnce = () => {
|
const searchFnOnce = () => {
|
||||||
$searchMask.addEventListener('click', closeSearch)
|
$searchMask.addEventListener("click", closeSearch);
|
||||||
document.querySelector('#algolia-search .search-close-button').addEventListener('click', closeSearch)
|
document.querySelector("#algolia-search .search-close-button").addEventListener("click", closeSearch);
|
||||||
}
|
};
|
||||||
|
|
||||||
const cutContent = content => {
|
const algolia = GLOBAL_CONFIG.algolia;
|
||||||
if (content === '') return ''
|
const isAlgoliaValid = algolia.appId && algolia.apiKey && algolia.indexName;
|
||||||
|
|
||||||
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) {
|
if (!isAlgoliaValid) {
|
||||||
return console.error('Algolia setting is invalid!')
|
return console.error("Algolia setting is invalid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
const search = instantsearch({
|
const search = instantsearch({
|
||||||
indexName: algolia.indexName,
|
indexName: algolia.indexName,
|
||||||
/* global algoliasearch */
|
/* global algoliasearch */
|
||||||
searchClient: algoliasearch(algolia.appId, algolia.apiKey),
|
searchClient: algoliasearch(algolia.appId, algolia.apiKey),
|
||||||
searchFunction (helper) {
|
searchFunction(helper) {
|
||||||
helper.state.query && helper.search()
|
if (helper.state.query) {
|
||||||
|
let innerLoading = '<i class="anzhiyufont anzhiyu-icon-spinner anzhiyu-spin"></i>';
|
||||||
|
document.getElementById("algolia-hits").innerHTML = innerLoading;
|
||||||
|
helper.search();
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const configure = instantsearch.widgets.configure({
|
const configure = instantsearch.widgets.configure({
|
||||||
hitsPerPage: 5
|
hitsPerPage: algolia.hits.per_page ?? 5,
|
||||||
})
|
});
|
||||||
|
|
||||||
const searchBox = instantsearch.widgets.searchBox({
|
const searchBox = instantsearch.widgets.searchBox({
|
||||||
container: '#algolia-search-input',
|
container: "#algolia-search-input",
|
||||||
showReset: false,
|
showReset: false,
|
||||||
showSubmit: false,
|
showSubmit: false,
|
||||||
placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder,
|
placeholder: algolia.languages.input_placeholder,
|
||||||
showLoadingIndicator: true
|
showLoadingIndicator: true,
|
||||||
})
|
searchOnEnterKeyPressOnly: true,
|
||||||
|
searchAsYouType: false,
|
||||||
|
});
|
||||||
|
|
||||||
const hits = instantsearch.widgets.hits({
|
const hits = instantsearch.widgets.hits({
|
||||||
container: '#algolia-hits',
|
container: "#algolia-hits",
|
||||||
templates: {
|
templates: {
|
||||||
item (data) {
|
item(data) {
|
||||||
const link = data.permalink ? data.permalink : (GLOBAL_CONFIG.root + data.path)
|
const link = data.permalink ? data.permalink : GLOBAL_CONFIG.root + data.path;
|
||||||
const result = data._highlightResult
|
const result = data._highlightResult;
|
||||||
const content = result.contentStripTruncate
|
const loadingLogo = document.querySelector("#algolia-hits .anzhiyu-spin");
|
||||||
? cutContent(result.contentStripTruncate.value)
|
if (loadingLogo) {
|
||||||
: result.contentStrip
|
loadingLogo.style.display = "none";
|
||||||
? cutContent(result.contentStrip.value)
|
}
|
||||||
: result.content
|
setTimeout(() => {
|
||||||
? cutContent(result.content.value)
|
document.querySelector("#algolia-search .ais-SearchBox-input").focus();
|
||||||
: ''
|
}, 200);
|
||||||
return `
|
return `
|
||||||
<a href="${link}" class="algolia-hit-item-link">
|
<a href="${link}" class="algolia-hit-item-link">
|
||||||
<span class="algolia-hits-item-title">${result.title.value || 'no-title'}</span>
|
<span class="algolia-hits-item-title">${result.title.value || "no-title"}</span>
|
||||||
<p class="algolia-hit-item-content">${content}</p>
|
</a>`;
|
||||||
</a>`
|
|
||||||
},
|
},
|
||||||
empty: function (data) {
|
empty: function (data) {
|
||||||
|
const loadingLogo = document.querySelector("#algolia-hits .anzhiyu-spin");
|
||||||
|
console.info(loadingLogo);
|
||||||
|
if (loadingLogo) {
|
||||||
|
loadingLogo.style.display = "none";
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
document.querySelector("#algolia-search .ais-SearchBox-input").focus();
|
||||||
|
}, 200);
|
||||||
return (
|
return (
|
||||||
'<div id="algolia-hits-empty">' +
|
'<div id="algolia-hits-empty">' +
|
||||||
GLOBAL_CONFIG.algolia.languages.hits_empty.replace(/\$\{query}/, data.query) +
|
GLOBAL_CONFIG.algolia.languages.hits_empty.replace(/\$\{query}/, data.query) +
|
||||||
'</div>'
|
"</div>"
|
||||||
)
|
);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
cssClasses: {
|
||||||
|
item: "algolia-hit-item",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const stats = instantsearch.widgets.stats({
|
const stats = instantsearch.widgets.stats({
|
||||||
container: '#algolia-info > .algolia-stats',
|
container: "#algolia-info > .algolia-stats",
|
||||||
templates: {
|
templates: {
|
||||||
text: function (data) {
|
text: function (data) {
|
||||||
const stats = GLOBAL_CONFIG.algolia.languages.hits_stats
|
const stats = GLOBAL_CONFIG.algolia.languages.hits_stats
|
||||||
.replace(/\$\{hits}/, data.nbHits)
|
.replace(/\$\{hits}/, data.nbHits)
|
||||||
.replace(/\$\{time}/, data.processingTimeMS)
|
.replace(/\$\{time}/, data.processingTimeMS);
|
||||||
return (
|
return `<hr>${stats}`;
|
||||||
`<hr>${stats}`
|
},
|
||||||
)
|
},
|
||||||
}
|
});
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const powerBy = instantsearch.widgets.poweredBy({
|
const powerBy = instantsearch.widgets.poweredBy({
|
||||||
container: '#algolia-info > .algolia-poweredBy'
|
container: "#algolia-info > .algolia-poweredBy",
|
||||||
})
|
});
|
||||||
|
|
||||||
const pagination = instantsearch.widgets.pagination({
|
const pagination = instantsearch.widgets.pagination({
|
||||||
container: '#algolia-pagination',
|
container: "#algolia-pagination",
|
||||||
totalPages: 5,
|
totalPages: algolia.hits.per_page ?? 5,
|
||||||
templates: {
|
templates: {
|
||||||
first: '<i class="fas fa-angle-double-left"></i>',
|
first: '<i class="anzhiyufont anzhiyu-icon-angle-double-left"></i>',
|
||||||
last: '<i class="fas fa-angle-double-right"></i>',
|
last: '<i class="anzhiyufont anzhiyu-icon-angle-double-right"></i>',
|
||||||
previous: '<i class="fas fa-angle-left"></i>',
|
previous: '<i class="anzhiyufont anzhiyu-icon-angle-left"></i>',
|
||||||
next: '<i class="fas fa-angle-right"></i>'
|
next: '<i class="anzhiyufont anzhiyu-icon-angle-right"></i>',
|
||||||
}
|
},
|
||||||
})
|
scrollTo: false,
|
||||||
|
showFirstLast: false,
|
||||||
|
cssClasses: {
|
||||||
|
root: "pagination",
|
||||||
|
item: "pagination-item",
|
||||||
|
link: "page-number",
|
||||||
|
active: "current",
|
||||||
|
disabled: "disabled-item",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
search.addWidgets([configure, searchBox, hits, stats, powerBy, pagination]) // add the widgets to the instantsearch instance
|
search.addWidgets([configure, searchBox, hits, stats, powerBy, pagination]); // add the widgets to the instantsearch instance
|
||||||
|
|
||||||
search.start()
|
search.start();
|
||||||
|
|
||||||
searchClickFn()
|
searchClickFn();
|
||||||
searchFnOnce()
|
searchFnOnce();
|
||||||
|
|
||||||
window.addEventListener('pjax:complete', () => {
|
window.addEventListener("pjax:complete", () => {
|
||||||
!btf.isHidden($searchMask) && closeSearch()
|
!anzhiyu.isHidden($searchMask) && closeSearch();
|
||||||
searchClickFn()
|
searchClickFn();
|
||||||
})
|
});
|
||||||
|
|
||||||
window.pjax && search.on('render', () => {
|
window.pjax &&
|
||||||
window.pjax.refresh(document.getElementById('algolia-hits'))
|
search.on("render", () => {
|
||||||
})
|
window.pjax.refresh(document.getElementById("algolia-hits"));
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,364 +1,270 @@
|
||||||
/**
|
window.addEventListener("load", () => {
|
||||||
* Refer to hexo-generator-searchdb
|
let loadFlag = false;
|
||||||
* https://github.com/next-theme/hexo-generator-searchdb/blob/main/dist/search.js
|
let dataObj = [];
|
||||||
* Modified by hexo-theme-butterfly
|
const $searchMask = document.getElementById("search-mask");
|
||||||
*/
|
|
||||||
|
|
||||||
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 openSearch = () => {
|
||||||
const bodyStyle = document.body.style
|
const bodyStyle = document.body.style;
|
||||||
bodyStyle.width = '100%'
|
bodyStyle.width = "100%";
|
||||||
bodyStyle.overflow = 'hidden'
|
bodyStyle.overflow = "hidden";
|
||||||
btf.animateIn($searchMask, 'to_show 0.5s')
|
anzhiyu.animateIn($searchMask, "to_show 0.5s");
|
||||||
btf.animateIn($searchDialog, 'titleScale 0.5s')
|
anzhiyu.animateIn(document.querySelector("#local-search .search-dialog"), "titleScale 0.5s");
|
||||||
setTimeout(() => { input.focus() }, 300)
|
setTimeout(() => {
|
||||||
|
document.querySelector("#local-search-input input").focus();
|
||||||
|
}, 100);
|
||||||
if (!loadFlag) {
|
if (!loadFlag) {
|
||||||
!localSearch.isfetched && localSearch.fetchData()
|
search();
|
||||||
input.addEventListener('input', inputEventFunction)
|
loadFlag = true;
|
||||||
loadFlag = true
|
|
||||||
}
|
}
|
||||||
// shortcut: ESC
|
// shortcut: ESC
|
||||||
document.addEventListener('keydown', function f (event) {
|
document.addEventListener("keydown", function f(event) {
|
||||||
if (event.code === 'Escape') {
|
if (event.code === "Escape") {
|
||||||
closeSearch()
|
closeSearch();
|
||||||
document.removeEventListener('keydown', f)
|
document.removeEventListener("keydown", f);
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
fixSafariHeight()
|
|
||||||
window.addEventListener('resize', fixSafariHeight)
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const closeSearch = () => {
|
const closeSearch = () => {
|
||||||
const bodyStyle = document.body.style
|
const bodyStyle = document.body.style;
|
||||||
bodyStyle.width = ''
|
bodyStyle.width = "";
|
||||||
bodyStyle.overflow = ''
|
bodyStyle.overflow = "";
|
||||||
btf.animateOut($searchDialog, 'search_close .5s')
|
anzhiyu.animateOut(document.querySelector("#local-search .search-dialog"), "search_close .5s");
|
||||||
btf.animateOut($searchMask, 'to_hide 0.5s')
|
anzhiyu.animateOut($searchMask, "to_hide 0.5s");
|
||||||
window.removeEventListener('resize', fixSafariHeight)
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const searchClickFn = () => {
|
const searchClickFn = () => {
|
||||||
btf.addEventListenerPjax(document.querySelector('#search-button > .search'), 'click', openSearch)
|
document.querySelector("#search-button > .search").addEventListener("click", openSearch);
|
||||||
|
document.querySelector("#menu-search").addEventListener("click", openSearch);
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchClickFnOnce = () => {
|
||||||
|
document.querySelector("#local-search .search-close-button").addEventListener("click", closeSearch);
|
||||||
|
$searchMask.addEventListener("click", closeSearch);
|
||||||
|
if (GLOBAL_CONFIG.localSearch.preload) dataObj = fetchData(GLOBAL_CONFIG.localSearch.path);
|
||||||
|
};
|
||||||
|
|
||||||
|
// check url is json or not
|
||||||
|
const isJson = url => {
|
||||||
|
const reg = /\.json$/;
|
||||||
|
return reg.test(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchData = async path => {
|
||||||
|
let data = [];
|
||||||
|
const response = await fetch(path);
|
||||||
|
if (isJson(path)) {
|
||||||
|
data = await response.json();
|
||||||
|
} else {
|
||||||
|
const res = await response.text();
|
||||||
|
const t = await new window.DOMParser().parseFromString(res, "text/xml");
|
||||||
|
const a = await t;
|
||||||
|
|
||||||
|
data = [...a.querySelectorAll("entry")].map(item => {
|
||||||
|
let tagsArr = [];
|
||||||
|
if (item.querySelector("tags") && item.querySelector("tags").getElementsByTagName("tag")) {
|
||||||
|
Array.prototype.forEach.call(item.querySelector("tags").getElementsByTagName("tag"), function (item, index) {
|
||||||
|
tagsArr.push(item.textContent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let content = item.querySelector("content") && item.querySelector("content").textContent;
|
||||||
|
let imgReg = /<img.*?(?:>|\/>)/gi; //匹配图片中的img标签
|
||||||
|
let srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i; // 匹配图片中的src
|
||||||
|
let arr = content.match(imgReg); //筛选出所有的img
|
||||||
|
|
||||||
|
let srcArr = [];
|
||||||
|
if (arr) {
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
let src = arr[i].match(srcReg);
|
||||||
|
// 获取图片地址
|
||||||
|
if (!src[1].indexOf("http")) srcArr.push(src[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const searchFnOnce = () => {
|
return {
|
||||||
document.querySelector('#local-search .search-close-button').addEventListener('click', closeSearch)
|
title: item.querySelector("title").textContent,
|
||||||
$searchMask.addEventListener('click', closeSearch)
|
content: content,
|
||||||
if (GLOBAL_CONFIG.localSearch.preload) {
|
url: item.querySelector("url").textContent,
|
||||||
localSearch.fetchData()
|
tags: tagsArr,
|
||||||
|
oneImage: srcArr && srcArr[0],
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
localSearch.highlightSearchWords(document.getElementById('article-container'))
|
if (response.ok) {
|
||||||
|
const $loadDataItem = document.getElementById("loading-database");
|
||||||
|
$loadDataItem.nextElementSibling.style.display = "block";
|
||||||
|
$loadDataItem.remove();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const search = () => {
|
||||||
|
if (!GLOBAL_CONFIG.localSearch.preload) {
|
||||||
|
dataObj = fetchData(GLOBAL_CONFIG.localSearch.path);
|
||||||
|
}
|
||||||
|
const $input = document.querySelector("#local-search-input input");
|
||||||
|
const $resultContent = document.getElementById("local-search-results");
|
||||||
|
const $loadingStatus = document.getElementById("loading-status");
|
||||||
|
|
||||||
|
$input.addEventListener("input", function () {
|
||||||
|
const keywords = this.value.trim().toLowerCase().split(/[\s]+/);
|
||||||
|
if (keywords[0] !== "")
|
||||||
|
$loadingStatus.innerHTML = '<i class="anzhiyufont anzhiyu-icon-spinner anzhiyu-pulse-icon"></i>';
|
||||||
|
|
||||||
|
$resultContent.innerHTML = "";
|
||||||
|
let str = '<div class="search-result-list">';
|
||||||
|
if (keywords.length <= 0) return;
|
||||||
|
let count = 0;
|
||||||
|
// perform local searching
|
||||||
|
dataObj.then(data => {
|
||||||
|
data.forEach(data => {
|
||||||
|
let isMatch = true;
|
||||||
|
let dataTitle = data.title ? data.title.trim().toLowerCase() : "";
|
||||||
|
let dataTags = data.tags;
|
||||||
|
let oneImage = data.oneImage ?? "";
|
||||||
|
const dataContent = data.content
|
||||||
|
? data.content
|
||||||
|
.trim()
|
||||||
|
.replace(/<[^>]+>/g, "")
|
||||||
|
.toLowerCase()
|
||||||
|
: "";
|
||||||
|
const dataUrl = data.url.startsWith("/") ? data.url : GLOBAL_CONFIG.root + data.url;
|
||||||
|
let indexTitle = -1;
|
||||||
|
let indexContent = -1;
|
||||||
|
let firstOccur = -1;
|
||||||
|
// only match articles with not empty titles and contents
|
||||||
|
if (dataTitle !== "" || dataContent !== "") {
|
||||||
|
keywords.forEach((keyword, i) => {
|
||||||
|
indexTitle = dataTitle.indexOf(keyword);
|
||||||
|
indexContent = dataContent.indexOf(keyword);
|
||||||
|
if (indexTitle < 0 && indexContent < 0) {
|
||||||
|
isMatch = false;
|
||||||
|
} else {
|
||||||
|
if (indexContent < 0) {
|
||||||
|
indexContent = 0;
|
||||||
|
}
|
||||||
|
if (i === 0) {
|
||||||
|
firstOccur = indexContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
isMatch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('search:loaded', () => {
|
// show search results
|
||||||
const $loadDataItem = document.getElementById('loading-database')
|
if (isMatch) {
|
||||||
$loadDataItem.nextElementSibling.style.display = 'block'
|
if (firstOccur >= 0) {
|
||||||
$loadDataItem.remove()
|
// cut out 130 characters
|
||||||
})
|
// let start = firstOccur - 30 < 0 ? 0 : firstOccur - 30
|
||||||
|
// let end = firstOccur + 50 > dataContent.length ? dataContent.length : firstOccur + 50
|
||||||
|
let start = firstOccur - 30;
|
||||||
|
let end = firstOccur + 100;
|
||||||
|
let pre = "";
|
||||||
|
let post = "";
|
||||||
|
|
||||||
searchClickFn()
|
if (start < 0) {
|
||||||
searchFnOnce()
|
start = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start === 0) {
|
||||||
|
end = 100;
|
||||||
|
} else {
|
||||||
|
pre = "...";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end > dataContent.length) {
|
||||||
|
end = dataContent.length;
|
||||||
|
} else {
|
||||||
|
post = "...";
|
||||||
|
}
|
||||||
|
|
||||||
|
let matchContent = dataContent.substring(start, end);
|
||||||
|
|
||||||
|
// highlight all keywords
|
||||||
|
keywords.forEach(keyword => {
|
||||||
|
const regS = new RegExp(keyword, "gi");
|
||||||
|
matchContent = matchContent.replace(regS, '<span class="search-keyword">' + keyword + "</span>");
|
||||||
|
dataTitle = dataTitle.replace(regS, '<span class="search-keyword">' + keyword + "</span>");
|
||||||
|
});
|
||||||
|
|
||||||
|
str += '<div class="local-search__hit-item">';
|
||||||
|
if (oneImage) {
|
||||||
|
str += `<div class="search-left"><img src=${oneImage} alt=${dataTitle} data-fancybox='gallery'>`;
|
||||||
|
} else {
|
||||||
|
str += '<div class="search-left" style="width:0">';
|
||||||
|
}
|
||||||
|
|
||||||
|
str += "</div>";
|
||||||
|
|
||||||
|
if (oneImage) {
|
||||||
|
str +=
|
||||||
|
'<div class="search-right"><a href="' +
|
||||||
|
dataUrl +
|
||||||
|
'" class="search-result-title">' +
|
||||||
|
dataTitle +
|
||||||
|
"</a>";
|
||||||
|
} else {
|
||||||
|
str +=
|
||||||
|
'<div class="search-right" style="width: 100%"><a href="' +
|
||||||
|
dataUrl +
|
||||||
|
'" class="search-result-title">' +
|
||||||
|
dataTitle +
|
||||||
|
"</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
count += 1;
|
||||||
|
|
||||||
|
if (dataContent !== "") {
|
||||||
|
str +=
|
||||||
|
'<p class="search-result" onclick="pjax.loadUrl(`' +
|
||||||
|
dataUrl +
|
||||||
|
'`)">' +
|
||||||
|
pre +
|
||||||
|
matchContent +
|
||||||
|
post +
|
||||||
|
"</p>";
|
||||||
|
}
|
||||||
|
if (dataTags.length) {
|
||||||
|
str += '<div class="search-result-tags">';
|
||||||
|
|
||||||
|
for (let i = 0; i < dataTags.length; i++) {
|
||||||
|
const element = dataTags[i].trim();
|
||||||
|
|
||||||
|
str +=
|
||||||
|
'<a class="tag-list" href="/tags/' +
|
||||||
|
element +
|
||||||
|
'/" data-pjax-state="" one-link-mark="yes">#' +
|
||||||
|
element +
|
||||||
|
"</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
str += "</div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str += "</div></div>";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (count === 0) {
|
||||||
|
str +=
|
||||||
|
'<div id="local-search__hits-empty">' +
|
||||||
|
GLOBAL_CONFIG.localSearch.languages.hits_empty.replace(/\$\{query}/, this.value.trim()) +
|
||||||
|
"</div>";
|
||||||
|
}
|
||||||
|
str += "</div>";
|
||||||
|
$resultContent.innerHTML = str;
|
||||||
|
if (keywords[0] !== "") $loadingStatus.innerHTML = "";
|
||||||
|
window.pjax && window.pjax.refresh($resultContent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
searchClickFn();
|
||||||
|
searchClickFnOnce();
|
||||||
|
|
||||||
// pjax
|
// pjax
|
||||||
window.addEventListener('pjax:complete', () => {
|
window.addEventListener("pjax:complete", () => {
|
||||||
!btf.isHidden($searchMask) && closeSearch()
|
!anzhiyu.isHidden($searchMask) && closeSearch();
|
||||||
localSearch.highlightSearchWords(document.getElementById('article-container'))
|
searchClickFn();
|
||||||
searchClickFn()
|
});
|
||||||
})
|
});
|
||||||
})
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||||
saveToLocal.get(targetEncodingCookie) === undefined
|
saveToLocal.get(targetEncodingCookie) === undefined
|
||||||
? defaultEncoding
|
? defaultEncoding
|
||||||
: Number(saveToLocal.get('translate-chn-cht'))
|
: Number(saveToLocal.get('translate-chn-cht'))
|
||||||
let translateButtonObject
|
let translateButtonObject, translateRightMenuButtonObject;
|
||||||
const isSnackbar = snackbarData !== undefined
|
const isSnackbar = snackbarData !== undefined
|
||||||
|
|
||||||
function setLang () {
|
function setLang () {
|
||||||
|
|
@ -56,12 +56,12 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||||
currentEncoding = 1
|
currentEncoding = 1
|
||||||
targetEncoding = 2
|
targetEncoding = 2
|
||||||
translateButtonObject.textContent = msgToTraditionalChinese
|
translateButtonObject.textContent = msgToTraditionalChinese
|
||||||
isSnackbar && btf.snackbarShow(snackbarData.cht_to_chs)
|
isSnackbar && anzhiyu.snackbarShow(snackbarData.cht_to_chs)
|
||||||
} else if (targetEncoding === 2) {
|
} else if (targetEncoding === 2) {
|
||||||
currentEncoding = 2
|
currentEncoding = 2
|
||||||
targetEncoding = 1
|
targetEncoding = 1
|
||||||
translateButtonObject.textContent = msgToSimplifiedChinese
|
translateButtonObject.textContent = msgToSimplifiedChinese
|
||||||
isSnackbar && btf.snackbarShow(snackbarData.chs_to_cht)
|
isSnackbar && anzhiyu.snackbarShow(snackbarData.chs_to_cht)
|
||||||
}
|
}
|
||||||
saveToLocal.set(targetEncodingCookie, targetEncoding, 2)
|
saveToLocal.set(targetEncodingCookie, targetEncoding, 2)
|
||||||
setLang()
|
setLang()
|
||||||
|
|
@ -97,16 +97,24 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
function translateInitialization () {
|
function translateInitialization() {
|
||||||
translateButtonObject = document.getElementById('translateLink')
|
translateButtonObject = document.getElementById('translateLink');
|
||||||
if (translateButtonObject) {
|
translateRightMenuButtonObject = document.getElementById('menu-translate').querySelector('span');
|
||||||
|
|
||||||
|
if (translateButtonObject || translateRightMenuButtonObject) {
|
||||||
if (currentEncoding !== targetEncoding) {
|
if (currentEncoding !== targetEncoding) {
|
||||||
translateButtonObject.textContent =
|
const textContent = targetEncoding === 1 ? msgToSimplifiedChinese : msgToTraditionalChinese;
|
||||||
targetEncoding === 1
|
|
||||||
? msgToSimplifiedChinese
|
if (translateButtonObject) {
|
||||||
: msgToTraditionalChinese
|
translateButtonObject.textContent = textContent;
|
||||||
setLang()
|
}
|
||||||
setTimeout(translateBody, translateDelay)
|
|
||||||
|
if (translateRightMenuButtonObject) {
|
||||||
|
translateRightMenuButtonObject.textContent = textContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLang();
|
||||||
|
setTimeout(translateBody, translateDelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1503
public/js/utils.js
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
title: categories
|
||||||
|
date: 2024-07-31 08:33:49
|
||||||
|
aside: false
|
||||||
|
top_img: false
|
||||||
|
type: "categories"
|
||||||
|
---
|
||||||
|
|
||||||
|
### category
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
title: tags
|
||||||
|
date: 2024-07-31 08:32:38
|
||||||
|
type: "tags"
|
||||||
|
comments: false
|
||||||
|
top_img: false
|
||||||
|
---
|
||||||