Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35263fd99d | ||
|
|
f7ea52be7f | ||
|
|
8beb6d388a | ||
|
|
9f02e2620b | ||
|
|
6722f61728 | ||
|
|
2e78ea21dc | ||
|
|
f2916398ce | ||
|
|
1ff10bc070 | ||
|
|
82cd2aee91 | ||
|
|
15d5ea1e7d | ||
|
|
f733212c4b | ||
|
|
841223f4f3 | ||
|
|
72df0007a9 | ||
|
|
1efcf279d5 | ||
|
|
ee38206dbb | ||
|
|
b3ad18e700 | ||
|
|
94fbc885b4 | ||
|
|
caeccdb4ce | ||
|
|
5016b545de | ||
|
|
fb5cedb23e | ||
|
|
a2daa78448 | ||
|
|
a2e40e84d4 | ||
|
|
0e2ba5db7a | ||
|
|
148a6aaf78 | ||
|
|
30e09c6aab | ||
|
|
a23cfe26be | ||
|
|
1bb985b92e | ||
|
|
39ae055491 | ||
|
|
ffd230c109 | ||
|
|
bd7ec11c32 | ||
|
|
0841323a0d | ||
|
|
78ce8e048b | ||
|
|
6affa0c5e1 | ||
|
|
fdfbf2a42e | ||
|
|
600898f139 | ||
|
|
4d9fe5ac8f | ||
|
|
e93fd1b946 | ||
|
|
ad55a2b0c0 | ||
|
|
00574fa648 | ||
|
|
4341f82b5d | ||
|
|
f24c0743e9 | ||
|
|
49a4a46eb0 | ||
|
|
9eaeb4ad9f | ||
|
|
8e6813fd7c | ||
|
|
4b25932edc | ||
|
|
7c3232fcb1 | ||
|
|
245d9af1ca | ||
|
|
1ed8b84565 | ||
|
|
1636f68819 | ||
|
|
f8fcd03fdb | ||
|
|
b3c7e297c4 | ||
|
|
61d2309b2a | ||
|
|
a7e4e685c0 | ||
|
|
88e434cb26 | ||
|
|
be545404f2 | ||
|
|
e0c5923dcb | ||
|
|
0cc2674a4d | ||
|
|
52a9d3b67c | ||
|
|
8131149b55 |
43
.github/workflows/static.yml
vendored
Normal file
43
.github/workflows/static.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
# Simple workflow for deploying static content to GitHub Pages
|
||||
name: Deploy static content to Pages
|
||||
|
||||
on:
|
||||
# Runs on pushes targeting the default branch
|
||||
push:
|
||||
branches: ["main"]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
||||
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
# Single deploy job since we're just deploying
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v5
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
# Upload entire repository
|
||||
path: '.'
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
82
Gmeek.py
82
Gmeek.py
@ -8,6 +8,7 @@ import shutil
|
||||
import urllib
|
||||
import requests
|
||||
import argparse
|
||||
import html
|
||||
from github import Github
|
||||
from xpinyin import Pinyin
|
||||
from feedgen.feed import FeedGenerator
|
||||
@ -29,7 +30,9 @@ IconBase={
|
||||
"upload":"M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z M11.78 4.72a.749.749 0 1 1-1.06 1.06L8.75 3.811V9.5a.75.75 0 0 1-1.5 0V3.811L5.28 5.78a.749.749 0 1 1-1.06-1.06l3.25-3.25a.749.749 0 0 1 1.06 0l3.25 3.25Z",
|
||||
"github":"M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z",
|
||||
"home":"M6.906.664a1.749 1.749 0 0 1 2.187 0l5.25 4.2c.415.332.657.835.657 1.367v7.019A1.75 1.75 0 0 1 13.25 15h-3.5a.75.75 0 0 1-.75-.75V9H7v5.25a.75.75 0 0 1-.75.75h-3.5A1.75 1.75 0 0 1 1 13.25V6.23c0-.531.242-1.034.657-1.366l5.25-4.2Zm1.25 1.171a.25.25 0 0 0-.312 0l-5.25 4.2a.25.25 0 0 0-.094.196v7.019c0 .138.112.25.25.25H5.5V8.25a.75.75 0 0 1 .75-.75h3.5a.75.75 0 0 1 .75.75v5.25h2.75a.25.25 0 0 0 .25-.25V6.23a.25.25 0 0 0-.094-.195Z",
|
||||
"sync":"M1.705 8.005a.75.75 0 0 1 .834.656 5.5 5.5 0 0 0 9.592 2.97l-1.204-1.204a.25.25 0 0 1 .177-.427h3.646a.25.25 0 0 1 .25.25v3.646a.25.25 0 0 1-.427.177l-1.38-1.38A7.002 7.002 0 0 1 1.05 8.84a.75.75 0 0 1 .656-.834ZM8 2.5a5.487 5.487 0 0 0-4.131 1.869l1.204 1.204A.25.25 0 0 1 4.896 6H1.25A.25.25 0 0 1 1 5.75V2.104a.25.25 0 0 1 .427-.177l1.38 1.38A7.002 7.002 0 0 1 14.95 7.16a.75.75 0 0 1-1.49.178A5.5 5.5 0 0 0 8 2.5Z"
|
||||
"sync":"M1.705 8.005a.75.75 0 0 1 .834.656 5.5 5.5 0 0 0 9.592 2.97l-1.204-1.204a.25.25 0 0 1 .177-.427h3.646a.25.25 0 0 1 .25.25v3.646a.25.25 0 0 1-.427.177l-1.38-1.38A7.002 7.002 0 0 1 1.05 8.84a.75.75 0 0 1 .656-.834ZM8 2.5a5.487 5.487 0 0 0-4.131 1.869l1.204 1.204A.25.25 0 0 1 4.896 6H1.25A.25.25 0 0 1 1 5.75V2.104a.25.25 0 0 1 .427-.177l1.38 1.38A7.002 7.002 0 0 1 14.95 7.16a.75.75 0 0 1-1.49.178A5.5 5.5 0 0 0 8 2.5Z",
|
||||
"copy":"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z",
|
||||
"check":"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"
|
||||
}
|
||||
######################################################################################
|
||||
class GMEEK():
|
||||
@ -37,6 +40,7 @@ class GMEEK():
|
||||
self.options=options
|
||||
|
||||
self.root_dir='docs/'
|
||||
self.static_dir='static/'
|
||||
self.post_folder='post/'
|
||||
self.backup_dir='backup/'
|
||||
self.post_dir=self.root_dir+self.post_folder
|
||||
@ -50,7 +54,6 @@ class GMEEK():
|
||||
for label in self.repo.get_labels():
|
||||
self.labelColorDict[label.name]='#'+label.color
|
||||
print(self.labelColorDict)
|
||||
|
||||
self.defaultConfig()
|
||||
|
||||
def cleanFile(self):
|
||||
@ -71,8 +74,21 @@ class GMEEK():
|
||||
os.mkdir(self.root_dir)
|
||||
os.mkdir(self.post_dir)
|
||||
|
||||
if os.path.exists(self.static_dir):
|
||||
for item in os.listdir(self.static_dir):
|
||||
src = os.path.join(self.static_dir, item)
|
||||
dst = os.path.join(self.root_dir, item)
|
||||
if os.path.isfile(src):
|
||||
shutil.copy(src, dst)
|
||||
print(f"Copied {item} to docs")
|
||||
elif os.path.isdir(src):
|
||||
shutil.copytree(src, dst)
|
||||
print(f"Copied directory {item} to docs")
|
||||
else:
|
||||
print("static does not exist")
|
||||
|
||||
def defaultConfig(self):
|
||||
dconfig={"singlePage":[],"startSite":"","filingNum":"","onePageListNum":15,"commentLabelColor":"#006b75","yearColorList":["#bc4c00", "#0969da", "#1f883d", "#A333D0"],"i18n":"CN","themeMode":"manual","dayTheme":"light","nightTheme":"dark","urlMode":"pinyin","script":"","style":"","bottomText":"","showPostSource":1,"iconList":{},"UTC":+8,"rssSplit":"sentence","exlink":{}}
|
||||
dconfig={"singlePage":[],"startSite":"","filingNum":"","onePageListNum":15,"commentLabelColor":"#006b75","yearColorList":["#bc4c00", "#0969da", "#1f883d", "#A333D0"],"i18n":"CN","themeMode":"manual","dayTheme":"light","nightTheme":"dark","urlMode":"pinyin","script":"","style":"","head":"","indexScript":"","indexStyle":"","bottomText":"","showPostSource":1,"iconList":{},"UTC":+8,"rssSplit":"sentence","exlink":{},"needComment":1,"allHead":""}
|
||||
config=json.loads(open('config.json', 'r', encoding='utf-8').read())
|
||||
self.blogBase={**dconfig,**config}.copy()
|
||||
self.blogBase["postListJson"]=json.loads('{}')
|
||||
@ -87,6 +103,9 @@ class GMEEK():
|
||||
if "ogImage" not in self.blogBase:
|
||||
self.blogBase["ogImage"]=self.blogBase["avatarUrl"]
|
||||
|
||||
if "primerCSS" not in self.blogBase:
|
||||
self.blogBase["primerCSS"]="<link href='https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/Primer/21.0.7/primer.css' rel='stylesheet' />"
|
||||
|
||||
if "homeUrl" not in self.blogBase:
|
||||
if str(self.repo.name).lower() == (str(self.repo.owner.login) + ".github.io").lower():
|
||||
self.blogBase["homeUrl"] = f"https://{self.repo.name}"
|
||||
@ -138,6 +157,29 @@ class GMEEK():
|
||||
post_body=re.sub(r'</math-renderer>','',post_body)
|
||||
issue["script"]=issue["script"]+'<script>MathJax = {tex: {inlineMath: [["$", "$"]]}};</script><script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>'
|
||||
|
||||
if '<p class="markdown-alert-title">' in post_body:
|
||||
issue["style"]=issue["style"]+'<style>.markdown-alert{padding:0.5rem 1rem;margin-bottom:1rem;border-left:.25em solid var(--borderColor-default,var(--color-border-default));}.markdown-alert .markdown-alert-title {display:flex;font-weight:var(--base-text-weight-medium,500);align-items:center;line-height:1;}.markdown-alert>:first-child {margin-top:0;}.markdown-alert>:last-child {margin-bottom:0;}</style>'
|
||||
alerts = {
|
||||
'note': 'accent',
|
||||
'tip': 'success',
|
||||
'important': 'done',
|
||||
'warning': 'attention',
|
||||
'caution': 'danger'
|
||||
}
|
||||
|
||||
for alert, style in alerts.items():
|
||||
if f'markdown-alert-{alert}' in post_body:
|
||||
issue["style"] += (
|
||||
f'<style>.markdown-alert.markdown-alert-{alert} {{'
|
||||
f'border-left-color:var(--borderColor-{style}-emphasis, var(--color-{style}-emphasis));'
|
||||
f'background-color:var(--color-{style}-subtle);}}'
|
||||
f'.markdown-alert.markdown-alert-{alert} .markdown-alert-title {{'
|
||||
f'color: var(--fgColor-{style},var(--color-{style}-fg));}}</style>'
|
||||
)
|
||||
|
||||
if '<code class="notranslate">Gmeek-html' in post_body:
|
||||
post_body = re.sub(r'<code class="notranslate">Gmeek-html(.*?)</code>', lambda match: html.unescape(match.group(1)), post_body, flags=re.DOTALL)
|
||||
|
||||
postBase["postTitle"]=issue["postTitle"]
|
||||
postBase["postUrl"]=self.blogBase["homeUrl"]+"/"+issue["postUrl"]
|
||||
postBase["description"]=issue["description"]
|
||||
@ -146,19 +188,24 @@ class GMEEK():
|
||||
postBase["commentNum"]=issue["commentNum"]
|
||||
postBase["style"]=issue["style"]
|
||||
postBase["script"]=issue["script"]
|
||||
postBase["head"]=issue["head"]
|
||||
postBase["top"]=issue["top"]
|
||||
postBase["postSourceUrl"]=issue["postSourceUrl"]
|
||||
postBase["repoName"]=options.repo_name
|
||||
|
||||
if "highlight" in post_body:
|
||||
postBase["highlight"]=1
|
||||
else:
|
||||
postBase["highlight"]=0
|
||||
|
||||
if issue["labels"][0] in self.blogBase["singlePage"]:
|
||||
postBase["bottomText"]=''
|
||||
|
||||
if '<pre class="notranslate">' in post_body:
|
||||
keys=['sun','moon','sync','home','github','copy','check']
|
||||
if '<div class="highlight' in post_body:
|
||||
postBase["highlight"]=1
|
||||
else:
|
||||
postBase["highlight"]=2
|
||||
else:
|
||||
keys=['sun','moon','sync','home','github']
|
||||
postBase["highlight"]=0
|
||||
|
||||
postIcon=dict(zip(keys, map(IconBase.get, keys)))
|
||||
self.renderHtml('post.html',postBase,{},issue["htmlDir"],postIcon)
|
||||
print("create postPage title=%s file=%s " % (issue["postTitle"],issue["htmlDir"]))
|
||||
@ -279,17 +326,17 @@ class GMEEK():
|
||||
self.blogBase[listJsonName][postNum]=json.loads('{}')
|
||||
self.blogBase[listJsonName][postNum]["htmlDir"]=gen_Html
|
||||
self.blogBase[listJsonName][postNum]["labels"]=[label.name for label in issue.labels]
|
||||
# self.blogBase[listJsonName][postNum]["labelColor"]=self.labelColorDict[issue.labels[0].name]
|
||||
self.blogBase[listJsonName][postNum]["postTitle"]=issue.title
|
||||
self.blogBase[listJsonName][postNum]["postUrl"]=urllib.parse.quote(gen_Html[len(self.root_dir):])
|
||||
|
||||
self.blogBase[listJsonName][postNum]["postSourceUrl"]="https://github.com/"+options.repo_name+"/issues/"+str(issue.number)
|
||||
self.blogBase[listJsonName][postNum]["commentNum"]=issue.get_comments().totalCount
|
||||
self.blogBase[listJsonName][postNum]["wordCount"]=len(issue.body)
|
||||
|
||||
if issue.body==None:
|
||||
self.blogBase[listJsonName][postNum]["description"]=''
|
||||
self.blogBase[listJsonName][postNum]["wordCount"]=0
|
||||
else:
|
||||
self.blogBase[listJsonName][postNum]["wordCount"]=len(issue.body)
|
||||
if self.blogBase["rssSplit"]=="sentence":
|
||||
if self.blogBase["i18n"]=="CN":
|
||||
period="。"
|
||||
@ -297,7 +344,7 @@ class GMEEK():
|
||||
period="."
|
||||
else:
|
||||
period=self.blogBase["rssSplit"]
|
||||
self.blogBase[listJsonName][postNum]["description"]=issue.body.split(period)[0]+period
|
||||
self.blogBase[listJsonName][postNum]["description"]=issue.body.split(period)[0].replace("\"", "\'")+period
|
||||
|
||||
self.blogBase[listJsonName][postNum]["top"]=0
|
||||
for event in issue.get_events():
|
||||
@ -328,6 +375,11 @@ class GMEEK():
|
||||
else:
|
||||
self.blogBase[listJsonName][postNum]["script"]=self.blogBase["script"]
|
||||
|
||||
if "head" in postConfig:
|
||||
self.blogBase[listJsonName][postNum]["head"]=self.blogBase["head"]+str(postConfig["head"])
|
||||
else:
|
||||
self.blogBase[listJsonName][postNum]["head"]=self.blogBase["head"]
|
||||
|
||||
if "ogImage" in postConfig:
|
||||
self.blogBase[listJsonName][postNum]["ogImage"]=postConfig["ogImage"]
|
||||
else:
|
||||
@ -370,11 +422,14 @@ class GMEEK():
|
||||
def runOne(self,number_str):
|
||||
print("====== start create static html ======")
|
||||
issue=self.repo.get_issue(int(number_str))
|
||||
if issue.state == "open":
|
||||
listJsonName=self.addOnePostJson(issue)
|
||||
self.createPostHtml(self.blogBase[listJsonName]["P"+number_str])
|
||||
self.createPlistHtml()
|
||||
self.createFeedXml()
|
||||
print("====== create static html end ======")
|
||||
else:
|
||||
print("====== issue is closed ======")
|
||||
|
||||
def createFileName(self,issue,useLabel=False):
|
||||
if useLabel==True:
|
||||
@ -416,8 +471,8 @@ else:
|
||||
oldBlogBase=json.loads(f.read())
|
||||
for key, value in oldBlogBase.items():
|
||||
blog.blogBase[key] = value
|
||||
|
||||
f.close()
|
||||
blog.blogBase["labelColorDict"]=blog.labelColorDict
|
||||
blog.runOne(options.issue_number)
|
||||
|
||||
listFile=open("blogBase.json","w")
|
||||
@ -438,6 +493,9 @@ for i in blog.blogBase["postListJson"]:
|
||||
del blog.blogBase["postListJson"][i]["top"]
|
||||
del blog.blogBase["postListJson"][i]["ogImage"]
|
||||
|
||||
if 'head' in blog.blogBase["postListJson"][i]:
|
||||
del blog.blogBase["postListJson"][i]["head"]
|
||||
|
||||
if 'commentNum' in blog.blogBase["postListJson"][i]:
|
||||
commentNumSum=commentNumSum+blog.blogBase["postListJson"][i]["commentNum"]
|
||||
del blog.blogBase["postListJson"][i]["commentNum"]
|
||||
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Meekdai
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -34,6 +34,12 @@
|
||||
- 评论系统引入[utteranc.es](https://utteranc.es/)
|
||||
- 使用`jinja2`对html进行渲染,可通过模板自定义UI主题
|
||||
|
||||
### 赞赏
|
||||
|
||||
如果本项目对你有帮助,可以用微信赞赏一下作者,让项目有继续更新维护下去的动力,谢谢!
|
||||
|
||||

|
||||
|
||||
### 鸣谢
|
||||
- [jinja2](https://jinja.palletsprojects.com/)
|
||||
- [utteranc.es](https://utteranc.es/)
|
||||
@ -43,3 +49,4 @@
|
||||
### License
|
||||
|
||||
请保留页面底部和console界面版权信息,谢谢!
|
||||
|
||||
|
||||
BIN
img/赞赏码.jpg
Normal file
BIN
img/赞赏码.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
16
plugins/GmeekBSZ.js
Normal file
16
plugins/GmeekBSZ.js
Normal file
@ -0,0 +1,16 @@
|
||||
function createBSZ() {
|
||||
var postBody = document.getElementById('postBody');
|
||||
if (postBody){
|
||||
postBody.insertAdjacentHTML('afterend','<div id="busuanzi_container_page_pv" style="display:none;float:left;margin-top:8px;font-size:small;">本文浏览量<span id="busuanzi_value_page_pv"></span>次</div>');
|
||||
}
|
||||
var runday = document.getElementById('runday');
|
||||
runday.insertAdjacentHTML('afterend', '<div id="busuanzi_container_site_pv" style="display:none;">总浏览量<span id="busuanzi_value_site_pv"></span>次 • </div>');
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
createBSZ();
|
||||
var element = document.createElement('script');
|
||||
element.src = '//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js';
|
||||
document.head.appendChild(element);
|
||||
console.log("\n %c GmeekBSZ Plugins https://github.com/Meekdai/Gmeek \n","padding:5px 0;background:#bc4c00;color:#fff");
|
||||
});
|
||||
100
plugins/GmeekTOC.js
Normal file
100
plugins/GmeekTOC.js
Normal file
@ -0,0 +1,100 @@
|
||||
function createTOC() {
|
||||
var tocElement = document.createElement('div');
|
||||
tocElement.className = 'toc';
|
||||
var contentContainer = document.getElementById('content');
|
||||
|
||||
const headings = contentContainer.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
||||
|
||||
if (headings.length === 0) {
|
||||
return; // 如果没有标题元素,则不创建TOC
|
||||
}
|
||||
|
||||
tocElement.insertAdjacentHTML('afterbegin', '<div class="toc-title">文章目录</div>');
|
||||
|
||||
headings.forEach(heading => {
|
||||
if (!heading.id) {
|
||||
heading.id = heading.textContent.trim().replace(/\s+/g, '-').toLowerCase();
|
||||
}
|
||||
const link = document.createElement('a');
|
||||
link.href = '#' + heading.id;
|
||||
link.textContent = heading.textContent;
|
||||
link.className = 'toc-link';
|
||||
link.style.paddingLeft = `${(parseInt(heading.tagName.charAt(1)) - 1) * 10}px`;
|
||||
tocElement.appendChild(link);
|
||||
});
|
||||
|
||||
tocElement.insertAdjacentHTML('beforeend', '<a class="toc-end" onclick="window.scrollTo({top:0,behavior: \'smooth\'});">Top</a>');
|
||||
contentContainer.prepend(tocElement);
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
createTOC();
|
||||
var css = `
|
||||
.toc {
|
||||
position:fixed;
|
||||
top:130px;
|
||||
left:50%;
|
||||
transform: translateX(50%) translateX(320px);
|
||||
width:200px;
|
||||
border: 1px solid #e1e4e8;
|
||||
border-radius: 6px;
|
||||
padding: 10px;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
max-height: 70vh;
|
||||
}
|
||||
.toc-title{
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.toc-end{
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
visibility: hidden;
|
||||
}
|
||||
.toc a {
|
||||
display: block;
|
||||
color: var(--color-diff-blob-addition-num-text);
|
||||
text-decoration: none;
|
||||
padding: 5px 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
border-bottom: 1px solid #e1e4e8;
|
||||
}
|
||||
.toc a:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.toc a:hover {
|
||||
background-color:var(--color-select-menu-tap-focus-bg);
|
||||
}
|
||||
|
||||
@media (max-width: 1249px)
|
||||
{
|
||||
.toc{
|
||||
position:static;
|
||||
top:auto;
|
||||
left:auto;
|
||||
transform:none;
|
||||
padding:10px;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
}`;
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.textContent = css;
|
||||
document.head.appendChild(style);
|
||||
|
||||
window.onscroll = function() {
|
||||
const backToTopButton = document.querySelector('.toc-end');
|
||||
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
|
||||
backToTopButton.style="visibility: visible;"
|
||||
} else {
|
||||
backToTopButton.style="visibility: hidden;"
|
||||
}
|
||||
};
|
||||
|
||||
console.log("\n %c GmeekTOC Plugins https://github.com/Meekdai/Gmeek \n","padding:5px 0;background:#C333D0;color:#fff");
|
||||
});
|
||||
59
plugins/GmeekTocBot.js
Normal file
59
plugins/GmeekTocBot.js
Normal file
@ -0,0 +1,59 @@
|
||||
function loadResource(type, attributes, callback) {
|
||||
var element;
|
||||
if (type === 'script') {
|
||||
element = document.createElement('script');
|
||||
element.src = attributes.src;
|
||||
element.onload = callback;
|
||||
} else if (type === 'link') {
|
||||
element = document.createElement('link');
|
||||
element.rel = attributes.rel;
|
||||
element.href = attributes.href;
|
||||
} else if (type === 'style') {
|
||||
element = document.createElement('style');
|
||||
element.rel = 'stylesheet';
|
||||
element.appendChild(document.createTextNode(attributes.css));
|
||||
}
|
||||
document.head.appendChild(element);
|
||||
}
|
||||
|
||||
function createTOC() {
|
||||
var tocElement = document.createElement('div');
|
||||
tocElement.className = 'toc';
|
||||
var contentContainer = document.getElementById('content');
|
||||
if (contentContainer.firstChild) {
|
||||
contentContainer.insertBefore(tocElement, contentContainer.firstChild);
|
||||
} else {
|
||||
contentContainer.appendChild(tocElement);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
createTOC();
|
||||
var css = '.toc {position:fixed;top:130px;left:50%;transform: translateX(50%) translateX(300px);width:200px;padding-left:30px;}@media (max-width: 1249px) {.toc{position:static;top:auto;left:auto;transform:none;padding:10px;margin-bottom:20px;background-color:var(--color-open-muted);}}';
|
||||
loadResource('style', {css: css});
|
||||
|
||||
loadResource('script', { src: 'https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.27.4/tocbot.min.js' }, function() {
|
||||
tocbot.init({
|
||||
tocSelector: '.toc',
|
||||
contentSelector: '.markdown-body',
|
||||
headingSelector: 'h1, h2, h3, h4, h5, h6',
|
||||
scrollSmooth: true,
|
||||
scrollSmoothOffset: -10,
|
||||
headingsOffset: 10,
|
||||
});
|
||||
});
|
||||
|
||||
loadResource('link', { rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.27.4/tocbot.css' });
|
||||
|
||||
const headings = document.querySelectorAll('.markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6');
|
||||
headings.forEach((heading) => {
|
||||
if (!heading.id) {
|
||||
heading.id = heading.textContent.trim().replace(/\s+/g, '-');
|
||||
}
|
||||
});
|
||||
|
||||
var footerPlaceholder = document.createElement('div');
|
||||
footerPlaceholder.style.height = window.innerHeight + 'px';
|
||||
document.body.appendChild(footerPlaceholder);
|
||||
console.log("\n %c GmeekTocBot Plugins https://github.com/Meekdai/Gmeek \n","padding:5px 0;background:#C333D0;color:#fff");
|
||||
});
|
||||
16
plugins/GmeekVercount.js
Normal file
16
plugins/GmeekVercount.js
Normal file
@ -0,0 +1,16 @@
|
||||
function createVercount() {
|
||||
var postBody = document.getElementById('postBody');
|
||||
if (postBody){
|
||||
postBody.insertAdjacentHTML('afterend','<div id="busuanzi_container_page_pv" style="display:none;float:left;margin-top:8px;font-size:small;">本文浏览量<span id="busuanzi_value_page_pv"></span>次</div>');
|
||||
}
|
||||
var runday = document.getElementById('runday');
|
||||
runday.insertAdjacentHTML('afterend', '<span id="busuanzi_container_site_pv" style="display:none">总浏览量<span id="busuanzi_value_site_pv"></span>次 • </span>');
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
createVercount();
|
||||
var element = document.createElement('script');
|
||||
element.src = 'https://vercount.one/js';
|
||||
document.head.appendChild(element);
|
||||
console.log("\n %c GmeekVercount Plugins https://github.com/Meekdai/Gmeek \n","padding:5px 0;background:#bc4c00;color:#fff");
|
||||
});
|
||||
158
plugins/articletoc.js
Normal file
158
plugins/articletoc.js
Normal file
@ -0,0 +1,158 @@
|
||||
function loadResource(type, attributes) {
|
||||
if (type === 'style') {
|
||||
const style = document.createElement('style');
|
||||
style.textContent = attributes.css;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
}
|
||||
|
||||
function createTOC() {
|
||||
const tocElement = document.createElement('div');
|
||||
tocElement.className = 'toc';
|
||||
const contentContainer = document.querySelector('.markdown-body');
|
||||
contentContainer.appendChild(tocElement);
|
||||
|
||||
const headings = contentContainer.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
||||
headings.forEach(heading => {
|
||||
if (!heading.id) {
|
||||
heading.id = heading.textContent.trim().replace(/\s+/g, '-').toLowerCase();
|
||||
}
|
||||
const link = document.createElement('a');
|
||||
link.href = '#' + heading.id;
|
||||
link.textContent = heading.textContent;
|
||||
link.className = 'toc-link';
|
||||
link.style.paddingLeft = `${(parseInt(heading.tagName.charAt(1)) - 1) * 10}px`;
|
||||
tocElement.appendChild(link);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleTOC() {
|
||||
const tocElement = document.querySelector('.toc');
|
||||
const tocIcon = document.querySelector('.toc-icon');
|
||||
if (tocElement) {
|
||||
tocElement.classList.toggle('show');
|
||||
tocIcon.classList.toggle('active');
|
||||
tocIcon.textContent = tocElement.classList.contains('show') ? '✖' : '☰';
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
createTOC();
|
||||
const css = `
|
||||
:root {
|
||||
--toc-bg: #fff;
|
||||
--toc-border: #e1e4e8;
|
||||
--toc-text: #24292e;
|
||||
--toc-hover: #f6f8fa;
|
||||
--toc-icon-bg: #fff;
|
||||
--toc-icon-color: #ad6598;
|
||||
--toc-icon-active-bg: #813c85;
|
||||
--toc-icon-active-color: #fff;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--toc-bg: #2d333b;
|
||||
--toc-border: #444c56;
|
||||
--toc-text: #adbac7;
|
||||
--toc-hover: #373e47;
|
||||
--toc-icon-bg: #22272e;
|
||||
--toc-icon-color: #ad6598;
|
||||
--toc-icon-active-bg: #813c85;
|
||||
--toc-icon-active-color: #adbac7;
|
||||
}
|
||||
}
|
||||
|
||||
.toc {
|
||||
position: fixed;
|
||||
bottom: 60px;
|
||||
right: 20px;
|
||||
width: 250px;
|
||||
max-height: 70vh;
|
||||
background-color: var(--toc-bg);
|
||||
border: 1px solid var(--toc-border);
|
||||
border-radius: 6px;
|
||||
padding: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
overflow-y: auto;
|
||||
z-index: 1000;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(20px) scale(0.9);
|
||||
transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;
|
||||
}
|
||||
.toc.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
.toc a {
|
||||
display: block;
|
||||
color: var(--toc-text);
|
||||
text-decoration: none;
|
||||
padding: 5px 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
border-bottom: 1px solid var(--toc-border);
|
||||
transition: background-color 0.2s ease, padding-left 0.2s ease;
|
||||
}
|
||||
.toc a:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.toc a:hover {
|
||||
background-color: var(--toc-hover);
|
||||
padding-left: 5px;
|
||||
}
|
||||
.toc-icon {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
cursor: pointer;
|
||||
font-size: 24px;
|
||||
background-color: var(--toc-icon-bg);
|
||||
color: var(--toc-icon-color);
|
||||
border: 2px solid var(--toc-icon-color);
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.12);
|
||||
z-index: 1001;
|
||||
transition: all 0.3s ease;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
outline: none;
|
||||
}
|
||||
.toc-icon:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
.toc-icon:active {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
.toc-icon.active {
|
||||
background-color: var(--toc-icon-active-bg);
|
||||
color: var(--toc-icon-active-color);
|
||||
border-color: var(--toc-icon-active-bg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
`;
|
||||
loadResource('style', {css: css});
|
||||
|
||||
const tocIcon = document.createElement('div');
|
||||
tocIcon.className = 'toc-icon';
|
||||
tocIcon.textContent = '☰';
|
||||
tocIcon.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
toggleTOC();
|
||||
};
|
||||
document.body.appendChild(tocIcon);
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
const tocElement = document.querySelector('.toc');
|
||||
if (tocElement && tocElement.classList.contains('show') && !tocElement.contains(e.target) && !e.target.classList.contains('toc-icon')) {
|
||||
toggleTOC();
|
||||
}
|
||||
});
|
||||
});
|
||||
357
plugins/lightbox.js
Normal file
357
plugins/lightbox.js
Normal file
@ -0,0 +1,357 @@
|
||||
(function() {
|
||||
class Lightbox {
|
||||
constructor(options = {}) {
|
||||
this.options = Object.assign({
|
||||
animationDuration: 300,
|
||||
closeOnOverlayClick: true,
|
||||
onOpen: null,
|
||||
onClose: null,
|
||||
onNavigate: null
|
||||
}, options);
|
||||
|
||||
this.images = [];
|
||||
this.currentIndex = 0;
|
||||
this.isOpen = false;
|
||||
this.zoomLevel = 1;
|
||||
this.touchStartX = 0;
|
||||
this.touchEndX = 0;
|
||||
this.wheelTimer = null;
|
||||
this.preloadedImages = {};
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.createStyles();
|
||||
this.createLightbox();
|
||||
this.bindEvents();
|
||||
}
|
||||
|
||||
createStyles() {
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.lb-lightbox-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: transparent;
|
||||
backdrop-filter: blur(5px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
transition: opacity ${this.options.animationDuration}ms ease;
|
||||
pointer-events: none;
|
||||
z-index: 10000;
|
||||
}
|
||||
.lb-lightbox-overlay.active {
|
||||
pointer-events: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
.lb-lightbox-content-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.lb-lightbox-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
transition: transform ${this.options.animationDuration}ms cubic-bezier(0.25, 0.1, 0.25, 1);
|
||||
overflow: hidden;
|
||||
}
|
||||
.lb-lightbox-image-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
.lb-lightbox-image {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
||||
transition: transform ${this.options.animationDuration}ms cubic-bezier(0.25, 0.1, 0.25, 1), opacity ${this.options.animationDuration}ms ease;
|
||||
opacity: 0;
|
||||
}
|
||||
.lb-lightbox-nav, .lb-lightbox-close {
|
||||
position: absolute;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
color: #333;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 30px;
|
||||
z-index: 2;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.lb-lightbox-nav:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
.lb-lightbox-prev {
|
||||
left: 20px;
|
||||
top: calc(50% - 25px);
|
||||
}
|
||||
.lb-lightbox-next {
|
||||
right: 20px;
|
||||
top: calc(50% - 25px);
|
||||
}
|
||||
.lb-lightbox-close {
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.lb-lightbox-nav, .lb-lightbox-close {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
createLightbox() {
|
||||
this.overlay = document.createElement('div');
|
||||
this.overlay.className = 'lb-lightbox-overlay';
|
||||
|
||||
this.contentWrapper = document.createElement('div');
|
||||
this.contentWrapper.className = 'lb-lightbox-content-wrapper';
|
||||
|
||||
this.container = document.createElement('div');
|
||||
this.container.className = 'lb-lightbox-container';
|
||||
|
||||
this.imageWrapper = document.createElement('div');
|
||||
this.imageWrapper.className = 'lb-lightbox-image-wrapper';
|
||||
|
||||
this.image = document.createElement('img');
|
||||
this.image.className = 'lb-lightbox-image';
|
||||
|
||||
this.prevButton = document.createElement('button');
|
||||
this.prevButton.className = 'lb-lightbox-nav lb-lightbox-prev';
|
||||
this.prevButton.innerHTML = '❮';
|
||||
|
||||
this.nextButton = document.createElement('button');
|
||||
this.nextButton.className = 'lb-lightbox-nav lb-lightbox-next';
|
||||
this.nextButton.innerHTML = '❯';
|
||||
|
||||
this.closeButton = document.createElement('button');
|
||||
this.closeButton.className = 'lb-lightbox-close';
|
||||
this.closeButton.innerHTML = '×';
|
||||
|
||||
this.imageWrapper.appendChild(this.image);
|
||||
this.container.appendChild(this.imageWrapper);
|
||||
this.contentWrapper.appendChild(this.container);
|
||||
this.contentWrapper.appendChild(this.prevButton);
|
||||
this.contentWrapper.appendChild(this.nextButton);
|
||||
this.contentWrapper.appendChild(this.closeButton);
|
||||
|
||||
this.overlay.appendChild(this.contentWrapper);
|
||||
document.body.appendChild(this.overlay);
|
||||
|
||||
this.closeButton.addEventListener('click', this.close.bind(this));
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
document.addEventListener('click', this.handleImageClick.bind(this), true);
|
||||
this.overlay.addEventListener('click', this.handleOverlayClick.bind(this));
|
||||
this.prevButton.addEventListener('click', this.showPreviousImage.bind(this));
|
||||
this.nextButton.addEventListener('click', this.showNextImage.bind(this));
|
||||
this.closeButton.addEventListener('click', this.close.bind(this));
|
||||
document.addEventListener('keydown', this.handleKeyDown.bind(this));
|
||||
this.overlay.addEventListener('wheel', this.handleWheel.bind(this));
|
||||
this.overlay.addEventListener('touchstart', this.handleTouchStart.bind(this));
|
||||
this.overlay.addEventListener('touchmove', this.handleTouchMove.bind(this));
|
||||
this.overlay.addEventListener('touchend', this.handleTouchEnd.bind(this));
|
||||
}
|
||||
|
||||
handleImageClick(event) {
|
||||
const clickedImage = event.target.closest('img');
|
||||
if (clickedImage && !this.isOpen) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.images = Array.from(document.querySelectorAll('.markdown-body img, table img'));
|
||||
this.currentIndex = this.images.indexOf(clickedImage);
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
handleOverlayClick(event) {
|
||||
if (event.target === this.overlay && this.options.closeOnOverlayClick) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyDown(event) {
|
||||
if (!this.isOpen) return;
|
||||
switch (event.key) {
|
||||
case 'ArrowLeft':
|
||||
this.showPreviousImage();
|
||||
break;
|
||||
case 'ArrowRight':
|
||||
this.showNextImage();
|
||||
break;
|
||||
case 'Escape':
|
||||
this.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleWheel(event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (event.ctrlKey) {
|
||||
this.zoomLevel += event.deltaY > 0 ? -0.1 : 0.1;
|
||||
this.zoomLevel = Math.max(1, this.zoomLevel);
|
||||
this.image.style.transform = `scale(${this.zoomLevel})`;
|
||||
} else {
|
||||
clearTimeout(this.wheelTimer);
|
||||
this.wheelTimer = setTimeout(() => {
|
||||
const delta = Math.sign(event.deltaY);
|
||||
if (delta > 0) {
|
||||
this.showNextImage();
|
||||
} else {
|
||||
this.showPreviousImage();
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
|
||||
handleTouchStart(event) {
|
||||
this.touchStartX = event.touches[0].clientX;
|
||||
}
|
||||
|
||||
handleTouchMove(event) {
|
||||
this.touchEndX = event.touches[0].clientX;
|
||||
}
|
||||
|
||||
handleTouchEnd() {
|
||||
const difference = this.touchStartX - this.touchEndX;
|
||||
if (Math.abs(difference) > 50) {
|
||||
difference > 0 ? this.showNextImage() : this.showPreviousImage();
|
||||
}
|
||||
}
|
||||
|
||||
open() {
|
||||
this.isOpen = true;
|
||||
this.overlay.classList.add('active');
|
||||
this.showImage(this.images[this.currentIndex].src);
|
||||
document.body.style.overflow = 'hidden';
|
||||
if (typeof this.options.onOpen === 'function') {
|
||||
this.options.onOpen();
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
document.body.style.overflow = '';
|
||||
this.overlay.classList.remove('active');
|
||||
this.isOpen = false;
|
||||
this.clearPreloadedImages();
|
||||
if (typeof this.options.onClose === 'function') {
|
||||
this.options.onClose();
|
||||
}
|
||||
this.unbindEvents();
|
||||
}
|
||||
|
||||
showPreviousImage() {
|
||||
if (this.currentIndex > 0) {
|
||||
this.currentIndex--;
|
||||
this.showImage(this.images[this.currentIndex].src);
|
||||
this.resetButtonScale(this.prevButton);
|
||||
}
|
||||
}
|
||||
|
||||
showNextImage() {
|
||||
if (this.currentIndex < this.images.length - 1) {
|
||||
this.currentIndex++;
|
||||
this.showImage(this.images[this.currentIndex].src);
|
||||
this.resetButtonScale(this.nextButton);
|
||||
}
|
||||
}
|
||||
|
||||
resetButtonScale(button) {
|
||||
button.style.transform = 'scale(1.1)';
|
||||
setTimeout(() => {
|
||||
button.style.transform = 'scale(1)';
|
||||
}, 200);
|
||||
}
|
||||
|
||||
showImage(imgSrc) {
|
||||
const newImage = new Image();
|
||||
newImage.src = imgSrc;
|
||||
|
||||
newImage.onload = () => {
|
||||
this.image.style.transition = `opacity ${this.options.animationDuration}ms ease`;
|
||||
this.image.style.transform = 'scale(1)';
|
||||
this.image.src = imgSrc;
|
||||
this.image.style.opacity = '1';
|
||||
|
||||
this.preloadImages();
|
||||
this.prevButton.style.display = this.currentIndex === 0 ? 'none' : 'block';
|
||||
this.nextButton.style.display = this.currentIndex === this.images.length - 1 ? 'none' : 'block';
|
||||
};
|
||||
|
||||
newImage.onerror = () => {
|
||||
console.error('Failed to load image:', imgSrc);
|
||||
};
|
||||
}
|
||||
|
||||
preloadImages() {
|
||||
const preloadNext = this.currentIndex + 1;
|
||||
const preloadPrev = this.currentIndex - 1;
|
||||
|
||||
if (preloadNext < this.images.length) {
|
||||
this.preloadedImages[preloadNext] = new Image();
|
||||
this.preloadedImages[preloadNext].src = this.images[preloadNext].src;
|
||||
}
|
||||
|
||||
if (preloadPrev >= 0) {
|
||||
this.preloadedImages[preloadPrev] = new Image();
|
||||
this.preloadedImages[preloadPrev].src = this.images[preloadPrev].src;
|
||||
}
|
||||
}
|
||||
|
||||
clearPreloadedImages() {
|
||||
Object.keys(this.preloadedImages).forEach(key => {
|
||||
this.preloadedImages[key].src = '';
|
||||
});
|
||||
this.preloadedImages = {};
|
||||
}
|
||||
|
||||
unbindEvents() {
|
||||
document.removeEventListener('click', this.handleImageClick.bind(this), true);
|
||||
this.overlay.removeEventListener('click', this.handleOverlayClick.bind(this));
|
||||
this.prevButton.removeEventListener('click', this.showPreviousImage.bind(this));
|
||||
this.nextButton.removeEventListener('click', this.showNextImage.bind(this));
|
||||
this.closeButton.removeEventListener('click', this.close.bind(this));
|
||||
document.removeEventListener('keydown', this.handleKeyDown.bind(this));
|
||||
this.overlay.removeEventListener('wheel', this.handleWheel.bind(this));
|
||||
this.overlay.removeEventListener('touchstart', this.handleTouchStart.bind(this));
|
||||
this.overlay.removeEventListener('touchmove', this.handleTouchMove.bind(this));
|
||||
this.overlay.removeEventListener('touchend', this.handleTouchEnd.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
window.Lightbox = Lightbox;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new Lightbox();
|
||||
});
|
||||
})();
|
||||
@ -4,7 +4,8 @@
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link href="//cdn.staticfile.net/Primer/21.0.7/primer.css" rel="stylesheet" />
|
||||
{{ blogBase['primerCSS'] }}
|
||||
{{ blogBase['allHead'] }}
|
||||
<link rel="icon" href="{{ blogBase['faviconUrl'] }}">
|
||||
{%- if blogBase['themeMode']=='manual' -%}
|
||||
<script>
|
||||
@ -57,9 +58,8 @@ function utterancesTheme(theme){
|
||||
}
|
||||
if(themeSettings[theme]){changeTheme(...themeSettings[theme]);}
|
||||
{%- endif %}
|
||||
console.log("\n %c Gmeek {{ blogBase['GMEEK_VERSION'] }} https://github.com/Meekdai/Gmeek \n\n","padding:5px 0;background:#02d81d;color:#fff");
|
||||
console.log("\n %c Gmeek {{ blogBase['GMEEK_VERSION'] }} https://github.com/Meekdai/Gmeek \n","padding:5px 0;background:#02d81d;color:#fff");
|
||||
</script>
|
||||
{% block script %}{% endblock %}
|
||||
{{ blogBase['script'] }}
|
||||
</html>
|
||||
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
Copyright © <span id="year"></span><a href="{{ blogBase['homeUrl'] }}"> {{ blogBase['title'] }} </a>
|
||||
<p>
|
||||
{%- if blogBase['filingNum']!='' -%}
|
||||
<a href="https://beian.miit.gov.cn/" target="_blank">{{ blogBase['filingNum'] }}</a>
|
||||
{%- endif %}
|
||||
<span id="runday"></span>Powered by <a href="https://meekdai.com/Gmeek.html" target="_blank">Gmeek</a>
|
||||
</p>
|
||||
<div id="footer1">Copyright © <span id="copyrightYear"></span> <a href="{{ blogBase['homeUrl'] }}">{{ blogBase['title'] }}</a></div>
|
||||
<div id="footer2">
|
||||
{%- if blogBase['filingNum']!='' -%}
|
||||
<span id="filingNum"><a href="https://beian.miit.gov.cn/" target="_blank">{{ blogBase['filingNum'] }}</a> • </span>
|
||||
{%- endif %}
|
||||
<span id="runday"></span><span>Powered by <a href="https://meekdai.com/Gmeek.html" target="_blank">Gmeek</a></span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var now=new Date();
|
||||
document.getElementById("copyrightYear").innerHTML=now.getFullYear();
|
||||
|
||||
if("{{ blogBase['startSite'] }}"!=""){
|
||||
var now=new Date();
|
||||
var startSite=new Date("{{ blogBase['startSite'] }}");
|
||||
var diff=now.getTime()-startSite.getTime();
|
||||
var diffDay=Math.floor(diff/(1000*60*60*24));
|
||||
document.getElementById("year").innerHTML=now.getFullYear();
|
||||
if("{{ blogBase['filingNum'] }}"!=""){document.getElementById("runday").innerHTML=" • "+"{{ i18n['run'] }}"+diffDay+"{{ i18n['days'] }}"+" • ";}
|
||||
else{document.getElementById("runday").innerHTML="{{ i18n['run'] }}"+diffDay+"{{ i18n['days'] }}"+" • ";}
|
||||
document.getElementById("runday").innerHTML="{{ i18n['run'] }}"+diffDay+"{{ i18n['days'] }}"+" • ";
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<style>
|
||||
.avatar {transition: 0.8s;width:64px;height:64px;object-fit: cover;}
|
||||
.avatar:hover{transform: scale(1.15) rotate(360deg);}
|
||||
#header h1 a{color:inherit;text-decoration:none;vertical-align: bottom;font-size:40px;font-family:Monaco;margin-left:8px;}
|
||||
.title-left a{color:inherit;text-decoration:none;vertical-align: bottom;font-size:40px;font-weight: bold;font-family:Monaco;margin-left:8px;}
|
||||
.title-right{display:flex;margin:auto 0 0 auto;}
|
||||
.title-right button{margin-right:8px;padding:16px;}
|
||||
.title-right .circle{padding: 14px 16px;}
|
||||
@ -34,17 +34,18 @@
|
||||
.LabelTime{display:none;}
|
||||
}
|
||||
</style>
|
||||
{{ blogBase['indexStyle'] }}
|
||||
{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
<h1>
|
||||
<div class="title-left">
|
||||
<img src="{{ blogBase['avatarUrl'] }}" class="avatar circle" id="avatarImg" alt="avatar">
|
||||
{%- if blogBase['displayTitle']=='eekdai' -%}
|
||||
<a class="blogTitle" href="https://meekdai.com">{{ blogBase['displayTitle'] }}</a>
|
||||
{%- if blogBase['displayTitle']=='Meekdai' -%}
|
||||
<a class="blogTitle" href="https://meekdai.com"><span style="font-size:0;">M</span>eekdai</a>
|
||||
{% else -%}
|
||||
<a class="blogTitle">{{ blogBase['displayTitle'] }}</a>
|
||||
{%- endif -%}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="title-right">
|
||||
<a href="{{ blogBase['homeUrl'] }}/tag.html" id="buttonSearch" class="btn btn-invisible circle" title="{{ i18n['Search'] }}">
|
||||
<svg class="octicon" width="16" height="16" >
|
||||
@ -140,4 +141,5 @@ document.getElementById("{{ key }}").setAttribute("d",value=IconList["{{ key }}"
|
||||
document.getElementById("{{ blogBase['singeListJson'][num]['postTitle'] }}").setAttribute("d",value=IconList["{{ blogBase['singeListJson'][num]['labels'][0] }}"]);
|
||||
{%- endfor %}
|
||||
</script>
|
||||
{{ blogBase['indexScript'] }}
|
||||
{% endblock %}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
<meta property="og:image" content="{{ blogBase['ogImage'] }}">
|
||||
<title>{{ blogBase['postTitle'] }}</title>
|
||||
{% if blogBase['highlight']==1 %}<link href="//unpkg.com/@wooorm/starry-night@2.1.1/style/both.css" rel="stylesheet" />{% endif %}
|
||||
{{ blogBase['head'] }}
|
||||
{% endblock %}
|
||||
|
||||
{% block style %}
|
||||
@ -25,6 +26,18 @@
|
||||
body {padding: 8px;}
|
||||
.postTitle{font-size:24px;}
|
||||
}
|
||||
{% if blogBase['highlight']!=0 -%}
|
||||
.copy-feedback {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 50px;
|
||||
color: var(--color-fg-on-emphasis);
|
||||
background-color: var(--color-fg-muted);
|
||||
border-radius: 3px;
|
||||
padding: 5px 8px;
|
||||
font-size: 12px;
|
||||
}{% endif %}
|
||||
</style>
|
||||
{{ blogBase['style'] }}
|
||||
|
||||
@ -57,14 +70,16 @@
|
||||
{% block content %}
|
||||
<div class="markdown-body" id="postBody">{{ blogBase['postBody'] }}</div>
|
||||
<div style="font-size:small;margin-top:8px;float:right;">{{ blogBase['bottomText'] }}</div>
|
||||
{% if blogBase['needComment']==1 %}
|
||||
<button class="btn btn-block" type="button" onclick="openComments()" id="cmButton">{{ i18n['comments'] }}</button>
|
||||
<div class="comments" id="comments"></div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
document.getElementById("pathHome").setAttribute("d",IconList["home"]);
|
||||
document.getElementById("pathIssue").setAttribute("d",IconList["github"]);
|
||||
{% if blogBase['showPostSource']==1 %}document.getElementById("pathIssue").setAttribute("d",IconList["github"]);{% endif %}
|
||||
{% if blogBase['commentNum']>0 -%}
|
||||
cmButton=document.getElementById("cmButton");
|
||||
span=document.createElement("span");
|
||||
@ -72,6 +87,8 @@ document.getElementById("pathIssue").setAttribute("d",IconList["github"]);
|
||||
span.innerHTML="{{ blogBase['commentNum'] }}";
|
||||
cmButton.appendChild(span);
|
||||
{%- endif %}
|
||||
|
||||
{% if blogBase['needComment']==1 %}
|
||||
function openComments(){
|
||||
cm=document.getElementById("comments");
|
||||
cmButton=document.getElementById("cmButton");
|
||||
@ -109,6 +126,75 @@ function iFrameLoading(){
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{%- endif %}
|
||||
|
||||
{% if blogBase['highlight']!=0 -%}
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const createClipboardHTML = (codeContent, additionalClasses = '') => `
|
||||
<pre class="notranslate"><code class="notranslate">${codeContent}</code></pre>
|
||||
<div class="clipboard-container position-absolute right-0 top-0 ${additionalClasses}">
|
||||
<clipboard-copy class="ClipboardButton btn m-2 p-0" role="button" style="display: inherit;">
|
||||
<svg height="16" width="16" class="octicon octicon-copy m-2"><path d="${IconList["copy"]}"></path></svg>
|
||||
<svg height="16" width="16" class="octicon octicon-check color-fg-success m-2 d-none"><path d="${IconList["check"]}"></path></svg>
|
||||
</clipboard-copy>
|
||||
<div class="copy-feedback">Copied!</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const handleCodeElements = (selector = '') => {
|
||||
document.querySelectorAll(selector).forEach(codeElement => {
|
||||
const codeContent = codeElement.innerHTML;
|
||||
const newStructure = document.createElement('div');
|
||||
newStructure.className = 'snippet-clipboard-content position-relative overflow-auto';
|
||||
newStructure.innerHTML = createClipboardHTML(codeContent);
|
||||
|
||||
const parentElement = codeElement.parentElement;
|
||||
if (selector.includes('highlight')) {
|
||||
parentElement.insertBefore(newStructure, codeElement.nextSibling);
|
||||
parentElement.removeChild(codeElement);
|
||||
} else {
|
||||
parentElement.parentElement.replaceChild(newStructure, parentElement);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleCodeElements('pre.notranslate > code.notranslate');
|
||||
handleCodeElements('div.highlight > pre.notranslate');
|
||||
|
||||
let currentFeedback = null;
|
||||
document.querySelectorAll('clipboard-copy').forEach(copyButton => {
|
||||
copyButton.addEventListener('click', () => {
|
||||
const codeContent = copyButton.closest('.snippet-clipboard-content').innerText;
|
||||
const tempTextArea = document.createElement('textarea');
|
||||
tempTextArea.value = codeContent;
|
||||
document.body.appendChild(tempTextArea);
|
||||
tempTextArea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(tempTextArea);
|
||||
|
||||
const copyIcon = copyButton.querySelector('.octicon-copy');
|
||||
const checkIcon = copyButton.querySelector('.octicon-check');
|
||||
const copyFeedback = copyButton.nextElementSibling;
|
||||
|
||||
if (currentFeedback && currentFeedback !== copyFeedback) {currentFeedback.style.display = 'none';}
|
||||
currentFeedback = copyFeedback;
|
||||
|
||||
copyIcon.classList.add('d-none');
|
||||
checkIcon.classList.remove('d-none');
|
||||
copyFeedback.style.display = 'block';
|
||||
copyButton.style.borderColor = 'var(--color-success-fg)';
|
||||
|
||||
setTimeout(() => {
|
||||
copyIcon.classList.remove('d-none');
|
||||
checkIcon.classList.add('d-none');
|
||||
copyFeedback.style.display = 'none';
|
||||
copyButton.style.borderColor = '';
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
});
|
||||
{%- endif %}
|
||||
|
||||
</script>
|
||||
{{ blogBase['script'] }}
|
||||
{% endblock %}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user