Compare commits
68 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 | ||
|
|
039e785ef5 | ||
|
|
03ee911f40 | ||
|
|
d7b5949340 | ||
|
|
aaf6d1670f | ||
|
|
98b8114b32 | ||
|
|
d2aff31483 | ||
|
|
4959661d0b | ||
|
|
d7f01816ba | ||
|
|
91dacffe12 |
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
|
||||||
109
Gmeek.py
109
Gmeek.py
@ -8,6 +8,7 @@ import shutil
|
|||||||
import urllib
|
import urllib
|
||||||
import requests
|
import requests
|
||||||
import argparse
|
import argparse
|
||||||
|
import html
|
||||||
from github import Github
|
from github import Github
|
||||||
from xpinyin import Pinyin
|
from xpinyin import Pinyin
|
||||||
from feedgen.feed import FeedGenerator
|
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",
|
"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",
|
"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",
|
"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():
|
class GMEEK():
|
||||||
@ -37,6 +40,7 @@ class GMEEK():
|
|||||||
self.options=options
|
self.options=options
|
||||||
|
|
||||||
self.root_dir='docs/'
|
self.root_dir='docs/'
|
||||||
|
self.static_dir='static/'
|
||||||
self.post_folder='post/'
|
self.post_folder='post/'
|
||||||
self.backup_dir='backup/'
|
self.backup_dir='backup/'
|
||||||
self.post_dir=self.root_dir+self.post_folder
|
self.post_dir=self.root_dir+self.post_folder
|
||||||
@ -50,9 +54,8 @@ class GMEEK():
|
|||||||
for label in self.repo.get_labels():
|
for label in self.repo.get_labels():
|
||||||
self.labelColorDict[label.name]='#'+label.color
|
self.labelColorDict[label.name]='#'+label.color
|
||||||
print(self.labelColorDict)
|
print(self.labelColorDict)
|
||||||
|
|
||||||
self.defaultConfig()
|
self.defaultConfig()
|
||||||
|
|
||||||
def cleanFile(self):
|
def cleanFile(self):
|
||||||
workspace_path = os.environ.get('GITHUB_WORKSPACE')
|
workspace_path = os.environ.get('GITHUB_WORKSPACE')
|
||||||
if os.path.exists(workspace_path+"/"+self.backup_dir):
|
if os.path.exists(workspace_path+"/"+self.backup_dir):
|
||||||
@ -71,8 +74,21 @@ class GMEEK():
|
|||||||
os.mkdir(self.root_dir)
|
os.mkdir(self.root_dir)
|
||||||
os.mkdir(self.post_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):
|
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())
|
config=json.loads(open('config.json', 'r', encoding='utf-8').read())
|
||||||
self.blogBase={**dconfig,**config}.copy()
|
self.blogBase={**dconfig,**config}.copy()
|
||||||
self.blogBase["postListJson"]=json.loads('{}')
|
self.blogBase["postListJson"]=json.loads('{}')
|
||||||
@ -84,8 +100,14 @@ class GMEEK():
|
|||||||
if "faviconUrl" not in self.blogBase:
|
if "faviconUrl" not in self.blogBase:
|
||||||
self.blogBase["faviconUrl"]=self.blogBase["avatarUrl"]
|
self.blogBase["faviconUrl"]=self.blogBase["avatarUrl"]
|
||||||
|
|
||||||
|
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 "homeUrl" not in self.blogBase:
|
||||||
if str(self.repo.name) == (str(self.repo.owner.login)+".github.io"):
|
if str(self.repo.name).lower() == (str(self.repo.owner.login) + ".github.io").lower():
|
||||||
self.blogBase["homeUrl"] = f"https://{self.repo.name}"
|
self.blogBase["homeUrl"] = f"https://{self.repo.name}"
|
||||||
else:
|
else:
|
||||||
self.blogBase["homeUrl"] = f"https://{self.repo.owner.login}.github.io/{self.repo.name}"
|
self.blogBase["homeUrl"] = f"https://{self.repo.owner.login}.github.io/{self.repo.name}"
|
||||||
@ -134,25 +156,56 @@ class GMEEK():
|
|||||||
post_body=re.sub(r'<math-renderer.*?>','',post_body)
|
post_body=re.sub(r'<math-renderer.*?>','',post_body)
|
||||||
post_body=re.sub(r'</math-renderer>','',post_body)
|
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>'
|
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["postTitle"]=issue["postTitle"]
|
||||||
|
postBase["postUrl"]=self.blogBase["homeUrl"]+"/"+issue["postUrl"]
|
||||||
|
postBase["description"]=issue["description"]
|
||||||
|
postBase["ogImage"]=issue["ogImage"]
|
||||||
postBase["postBody"]=post_body
|
postBase["postBody"]=post_body
|
||||||
postBase["commentNum"]=issue["commentNum"]
|
postBase["commentNum"]=issue["commentNum"]
|
||||||
postBase["style"]=issue["style"]
|
postBase["style"]=issue["style"]
|
||||||
postBase["script"]=issue["script"]
|
postBase["script"]=issue["script"]
|
||||||
|
postBase["head"]=issue["head"]
|
||||||
postBase["top"]=issue["top"]
|
postBase["top"]=issue["top"]
|
||||||
postBase["postSourceUrl"]=issue["postSourceUrl"]
|
postBase["postSourceUrl"]=issue["postSourceUrl"]
|
||||||
postBase["repoName"]=options.repo_name
|
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"]:
|
if issue["labels"][0] in self.blogBase["singlePage"]:
|
||||||
postBase["bottomText"]=''
|
postBase["bottomText"]=''
|
||||||
|
|
||||||
keys=['sun','moon','sync','home','github']
|
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)))
|
postIcon=dict(zip(keys, map(IconBase.get, keys)))
|
||||||
self.renderHtml('post.html',postBase,{},issue["htmlDir"],postIcon)
|
self.renderHtml('post.html',postBase,{},issue["htmlDir"],postIcon)
|
||||||
print("create postPage title=%s file=%s " % (issue["postTitle"],issue["htmlDir"]))
|
print("create postPage title=%s file=%s " % (issue["postTitle"],issue["htmlDir"]))
|
||||||
@ -273,17 +326,17 @@ class GMEEK():
|
|||||||
self.blogBase[listJsonName][postNum]=json.loads('{}')
|
self.blogBase[listJsonName][postNum]=json.loads('{}')
|
||||||
self.blogBase[listJsonName][postNum]["htmlDir"]=gen_Html
|
self.blogBase[listJsonName][postNum]["htmlDir"]=gen_Html
|
||||||
self.blogBase[listJsonName][postNum]["labels"]=[label.name for label in issue.labels]
|
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]["postTitle"]=issue.title
|
||||||
self.blogBase[listJsonName][postNum]["postUrl"]=urllib.parse.quote(gen_Html[len(self.root_dir):])
|
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]["postSourceUrl"]="https://github.com/"+options.repo_name+"/issues/"+str(issue.number)
|
||||||
self.blogBase[listJsonName][postNum]["commentNum"]=issue.get_comments().totalCount
|
self.blogBase[listJsonName][postNum]["commentNum"]=issue.get_comments().totalCount
|
||||||
self.blogBase[listJsonName][postNum]["wordCount"]=len(issue.body)
|
|
||||||
|
|
||||||
if issue.body==None:
|
if issue.body==None:
|
||||||
self.blogBase[listJsonName][postNum]["description"]=''
|
self.blogBase[listJsonName][postNum]["description"]=''
|
||||||
|
self.blogBase[listJsonName][postNum]["wordCount"]=0
|
||||||
else:
|
else:
|
||||||
|
self.blogBase[listJsonName][postNum]["wordCount"]=len(issue.body)
|
||||||
if self.blogBase["rssSplit"]=="sentence":
|
if self.blogBase["rssSplit"]=="sentence":
|
||||||
if self.blogBase["i18n"]=="CN":
|
if self.blogBase["i18n"]=="CN":
|
||||||
period="。"
|
period="。"
|
||||||
@ -291,7 +344,7 @@ class GMEEK():
|
|||||||
period="."
|
period="."
|
||||||
else:
|
else:
|
||||||
period=self.blogBase["rssSplit"]
|
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
|
self.blogBase[listJsonName][postNum]["top"]=0
|
||||||
for event in issue.get_events():
|
for event in issue.get_events():
|
||||||
@ -322,6 +375,15 @@ class GMEEK():
|
|||||||
else:
|
else:
|
||||||
self.blogBase[listJsonName][postNum]["script"]=self.blogBase["script"]
|
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:
|
||||||
|
self.blogBase[listJsonName][postNum]["ogImage"]=self.blogBase["ogImage"]
|
||||||
|
|
||||||
thisTime=datetime.datetime.fromtimestamp(self.blogBase[listJsonName][postNum]["createdAt"])
|
thisTime=datetime.datetime.fromtimestamp(self.blogBase[listJsonName][postNum]["createdAt"])
|
||||||
thisTime=thisTime.astimezone(self.TZ)
|
thisTime=thisTime.astimezone(self.TZ)
|
||||||
@ -360,11 +422,14 @@ class GMEEK():
|
|||||||
def runOne(self,number_str):
|
def runOne(self,number_str):
|
||||||
print("====== start create static html ======")
|
print("====== start create static html ======")
|
||||||
issue=self.repo.get_issue(int(number_str))
|
issue=self.repo.get_issue(int(number_str))
|
||||||
listJsonName=self.addOnePostJson(issue)
|
if issue.state == "open":
|
||||||
self.createPostHtml(self.blogBase[listJsonName]["P"+number_str])
|
listJsonName=self.addOnePostJson(issue)
|
||||||
self.createPlistHtml()
|
self.createPostHtml(self.blogBase[listJsonName]["P"+number_str])
|
||||||
self.createFeedXml()
|
self.createPlistHtml()
|
||||||
print("====== create static html end ======")
|
self.createFeedXml()
|
||||||
|
print("====== create static html end ======")
|
||||||
|
else:
|
||||||
|
print("====== issue is closed ======")
|
||||||
|
|
||||||
def createFileName(self,issue,useLabel=False):
|
def createFileName(self,issue,useLabel=False):
|
||||||
if useLabel==True:
|
if useLabel==True:
|
||||||
@ -406,8 +471,8 @@ else:
|
|||||||
oldBlogBase=json.loads(f.read())
|
oldBlogBase=json.loads(f.read())
|
||||||
for key, value in oldBlogBase.items():
|
for key, value in oldBlogBase.items():
|
||||||
blog.blogBase[key] = value
|
blog.blogBase[key] = value
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
blog.blogBase["labelColorDict"]=blog.labelColorDict
|
||||||
blog.runOne(options.issue_number)
|
blog.runOne(options.issue_number)
|
||||||
|
|
||||||
listFile=open("blogBase.json","w")
|
listFile=open("blogBase.json","w")
|
||||||
@ -426,6 +491,10 @@ for i in blog.blogBase["postListJson"]:
|
|||||||
del blog.blogBase["postListJson"][i]["script"]
|
del blog.blogBase["postListJson"][i]["script"]
|
||||||
del blog.blogBase["postListJson"][i]["style"]
|
del blog.blogBase["postListJson"][i]["style"]
|
||||||
del blog.blogBase["postListJson"][i]["top"]
|
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]:
|
if 'commentNum' in blog.blogBase["postListJson"][i]:
|
||||||
commentNumSum=commentNumSum+blog.blogBase["postListJson"][i]["commentNum"]
|
commentNumSum=commentNumSum+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.
|
||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
2. 【启用Pages】在仓库的`Settings`中`Pages->Build and deployment->Source`下面选择`Github Actions`。
|
2. 【启用Pages】在仓库的`Settings`中`Pages->Build and deployment->Source`下面选择`Github Actions`。
|
||||||
|
|
||||||
3. 【开始写作】打开一篇issue,开始写作,并且**必须**添加一个`标签Label`(至少添加一个),再保存issue后会自动创建博客内容,片刻后可通过https://XXX.github.io 访问。
|
3. 【开始写作】打开一篇issue,开始写作,并且**必须**添加一个`标签Label`(至少添加一个),再保存issue后会自动创建博客内容,片刻后可通过https://XXX.github.io 访问(可进入Actions页面查看构建进度)。
|
||||||
|
|
||||||
4. 【手动全局生成】这个步骤只有在修改`config.json`文件或者出现奇怪问题的时候,需要执行。
|
4. 【手动全局生成】这个步骤只有在修改`config.json`文件或者出现奇怪问题的时候,需要执行。
|
||||||
```
|
```
|
||||||
@ -34,6 +34,12 @@
|
|||||||
- 评论系统引入[utteranc.es](https://utteranc.es/)
|
- 评论系统引入[utteranc.es](https://utteranc.es/)
|
||||||
- 使用`jinja2`对html进行渲染,可通过模板自定义UI主题
|
- 使用`jinja2`对html进行渲染,可通过模板自定义UI主题
|
||||||
|
|
||||||
|
### 赞赏
|
||||||
|
|
||||||
|
如果本项目对你有帮助,可以用微信赞赏一下作者,让项目有继续更新维护下去的动力,谢谢!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### 鸣谢
|
### 鸣谢
|
||||||
- [jinja2](https://jinja.palletsprojects.com/)
|
- [jinja2](https://jinja.palletsprojects.com/)
|
||||||
- [utteranc.es](https://utteranc.es/)
|
- [utteranc.es](https://utteranc.es/)
|
||||||
@ -43,3 +49,4 @@
|
|||||||
### License
|
### License
|
||||||
|
|
||||||
请保留页面底部和console界面版权信息,谢谢!
|
请保留页面底部和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 content="text/html; charset=utf-8" http-equiv="content-type" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<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'] }}">
|
<link rel="icon" href="{{ blogBase['faviconUrl'] }}">
|
||||||
{%- if blogBase['themeMode']=='manual' -%}
|
{%- if blogBase['themeMode']=='manual' -%}
|
||||||
<script>
|
<script>
|
||||||
@ -57,9 +58,8 @@ function utterancesTheme(theme){
|
|||||||
}
|
}
|
||||||
if(themeSettings[theme]){changeTheme(...themeSettings[theme]);}
|
if(themeSettings[theme]){changeTheme(...themeSettings[theme]);}
|
||||||
{%- endif %}
|
{%- 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>
|
</script>
|
||||||
{% block script %}{% endblock %}
|
{% block script %}{% endblock %}
|
||||||
{{ blogBase['script'] }}
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,19 @@
|
|||||||
Copyright © <span id="year"></span><a href="{{ blogBase['homeUrl'] }}"> {{ blogBase['title'] }} </a>
|
<div id="footer1">Copyright © <span id="copyrightYear"></span> <a href="{{ blogBase['homeUrl'] }}">{{ blogBase['title'] }}</a></div>
|
||||||
<p>
|
<div id="footer2">
|
||||||
{%- if blogBase['filingNum']!='' -%}
|
{%- if blogBase['filingNum']!='' -%}
|
||||||
<a href="https://beian.miit.gov.cn/" target="_blank">{{ blogBase['filingNum'] }}</a>
|
<span id="filingNum"><a href="https://beian.miit.gov.cn/" target="_blank">{{ blogBase['filingNum'] }}</a> • </span>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
<span id="runday"></span>Powered by <a href="https://meekdai.com/Gmeek.html" target="_blank">Gmeek</a>
|
<span id="runday"></span><span>Powered by <a href="https://meekdai.com/Gmeek.html" target="_blank">Gmeek</a></span>
|
||||||
</p>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
var now=new Date();
|
||||||
|
document.getElementById("copyrightYear").innerHTML=now.getFullYear();
|
||||||
|
|
||||||
if("{{ blogBase['startSite'] }}"!=""){
|
if("{{ blogBase['startSite'] }}"!=""){
|
||||||
var now=new Date();
|
|
||||||
var startSite=new Date("{{ blogBase['startSite'] }}");
|
var startSite=new Date("{{ blogBase['startSite'] }}");
|
||||||
var diff=now.getTime()-startSite.getTime();
|
var diff=now.getTime()-startSite.getTime();
|
||||||
var diffDay=Math.floor(diff/(1000*60*60*24));
|
var diffDay=Math.floor(diff/(1000*60*60*24));
|
||||||
document.getElementById("year").innerHTML=now.getFullYear();
|
document.getElementById("runday").innerHTML="{{ i18n['run'] }}"+diffDay+"{{ i18n['days'] }}"+" • ";
|
||||||
if("{{ blogBase['filingNum'] }}"!=""){document.getElementById("runday").innerHTML=" • "+"{{ i18n['run'] }}"+diffDay+"{{ i18n['days'] }}"+" • ";}
|
|
||||||
else{document.getElementById("runday").innerHTML="{{ i18n['run'] }}"+diffDay+"{{ i18n['days'] }}"+" • ";}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<meta name="description" content="{{ blogBase['subTitle'] }}">
|
<meta name="description" content="{{ blogBase['subTitle'] }}">
|
||||||
|
<meta property="og:title" content="{{ blogBase['title'] }}">
|
||||||
|
<meta property="og:description" content="{{ blogBase['subTitle'] }}">
|
||||||
|
<meta property="og:type" content="blog">
|
||||||
|
<meta property="og:url" content="{{ blogBase['homeUrl'] }}">
|
||||||
|
<meta property="og:image" content="{{ blogBase['ogImage'] }}">
|
||||||
<title>{{ blogBase['title'] }}</title>
|
<title>{{ blogBase['title'] }}</title>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@ -8,7 +13,7 @@
|
|||||||
<style>
|
<style>
|
||||||
.avatar {transition: 0.8s;width:64px;height:64px;object-fit: cover;}
|
.avatar {transition: 0.8s;width:64px;height:64px;object-fit: cover;}
|
||||||
.avatar:hover{transform: scale(1.15) rotate(360deg);}
|
.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{display:flex;margin:auto 0 0 auto;}
|
||||||
.title-right button{margin-right:8px;padding:16px;}
|
.title-right button{margin-right:8px;padding:16px;}
|
||||||
.title-right .circle{padding: 14px 16px;}
|
.title-right .circle{padding: 14px 16px;}
|
||||||
@ -29,17 +34,18 @@
|
|||||||
.LabelTime{display:none;}
|
.LabelTime{display:none;}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
{{ blogBase['indexStyle'] }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
<h1>
|
<div class="title-left">
|
||||||
<img src="{{ blogBase['avatarUrl'] }}" class="avatar circle" id="avatarImg" alt="avatar">
|
<img src="{{ blogBase['avatarUrl'] }}" class="avatar circle" id="avatarImg" alt="avatar">
|
||||||
{%- if blogBase['displayTitle']=='eekdai' -%}
|
{%- if blogBase['displayTitle']=='Meekdai' -%}
|
||||||
<a class="blogTitle" href="https://meekdai.com">{{ blogBase['displayTitle'] }}</a>
|
<a class="blogTitle" href="https://meekdai.com"><span style="font-size:0;">M</span>eekdai</a>
|
||||||
{% else -%}
|
{% else -%}
|
||||||
<a class="blogTitle">{{ blogBase['displayTitle'] }}</a>
|
<a class="blogTitle">{{ blogBase['displayTitle'] }}</a>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
</h1>
|
</div>
|
||||||
<div class="title-right">
|
<div class="title-right">
|
||||||
<a href="{{ blogBase['homeUrl'] }}/tag.html" id="buttonSearch" class="btn btn-invisible circle" title="{{ i18n['Search'] }}">
|
<a href="{{ blogBase['homeUrl'] }}/tag.html" id="buttonSearch" class="btn btn-invisible circle" title="{{ i18n['Search'] }}">
|
||||||
<svg class="octicon" width="16" height="16" >
|
<svg class="octicon" width="16" height="16" >
|
||||||
@ -135,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] }}"]);
|
document.getElementById("{{ blogBase['singeListJson'][num]['postTitle'] }}").setAttribute("d",value=IconList["{{ blogBase['singeListJson'][num]['labels'][0] }}"]);
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
</script>
|
</script>
|
||||||
|
{{ blogBase['indexScript'] }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<meta name="description" content="{{ blogBase['postTitle'] }}">
|
<meta name="description" content="{{ blogBase['description'] }}">
|
||||||
|
<meta property="og:title" content="{{ blogBase['postTitle'] }}">
|
||||||
|
<meta property="og:description" content="{{ blogBase['description'] }}">
|
||||||
|
<meta property="og:type" content="article">
|
||||||
|
<meta property="og:url" content="{{ blogBase['postUrl'] }}">
|
||||||
|
<meta property="og:image" content="{{ blogBase['ogImage'] }}">
|
||||||
<title>{{ blogBase['postTitle'] }}</title>
|
<title>{{ blogBase['postTitle'] }}</title>
|
||||||
{% if blogBase['highlight']==1 %}<link href="//unpkg.com/@wooorm/starry-night@2.1.1/style/both.css" rel="stylesheet" />{% endif %}
|
{% if blogBase['highlight']==1 %}<link href="//unpkg.com/@wooorm/starry-night@2.1.1/style/both.css" rel="stylesheet" />{% endif %}
|
||||||
|
{{ blogBase['head'] }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block style %}
|
{% block style %}
|
||||||
@ -20,6 +26,18 @@
|
|||||||
body {padding: 8px;}
|
body {padding: 8px;}
|
||||||
.postTitle{font-size:24px;}
|
.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>
|
</style>
|
||||||
{{ blogBase['style'] }}
|
{{ blogBase['style'] }}
|
||||||
|
|
||||||
@ -52,14 +70,16 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="markdown-body" id="postBody">{{ blogBase['postBody'] }}</div>
|
<div class="markdown-body" id="postBody">{{ blogBase['postBody'] }}</div>
|
||||||
<div style="font-size:small;margin-top:8px;float:right;">{{ blogBase['bottomText'] }}</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>
|
<button class="btn btn-block" type="button" onclick="openComments()" id="cmButton">{{ i18n['comments'] }}</button>
|
||||||
<div class="comments" id="comments"></div>
|
<div class="comments" id="comments"></div>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block script %}
|
{% block script %}
|
||||||
<script>
|
<script>
|
||||||
document.getElementById("pathHome").setAttribute("d",IconList["home"]);
|
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 -%}
|
{% if blogBase['commentNum']>0 -%}
|
||||||
cmButton=document.getElementById("cmButton");
|
cmButton=document.getElementById("cmButton");
|
||||||
span=document.createElement("span");
|
span=document.createElement("span");
|
||||||
@ -67,6 +87,8 @@ document.getElementById("pathIssue").setAttribute("d",IconList["github"]);
|
|||||||
span.innerHTML="{{ blogBase['commentNum'] }}";
|
span.innerHTML="{{ blogBase['commentNum'] }}";
|
||||||
cmButton.appendChild(span);
|
cmButton.appendChild(span);
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
|
{% if blogBase['needComment']==1 %}
|
||||||
function openComments(){
|
function openComments(){
|
||||||
cm=document.getElementById("comments");
|
cm=document.getElementById("comments");
|
||||||
cmButton=document.getElementById("cmButton");
|
cmButton=document.getElementById("cmButton");
|
||||||
@ -104,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 %}
|
{% endblock %}
|
||||||
|
|||||||
@ -128,7 +128,7 @@ function showList(labelsCount){
|
|||||||
path=document.createElementNS("http://www.w3.org/2000/svg","path");
|
path=document.createElementNS("http://www.w3.org/2000/svg","path");
|
||||||
span=document.createElement("span");
|
span=document.createElement("span");
|
||||||
svg.setAttributeNS(null,"class","SideNav-icon octicon");
|
svg.setAttributeNS(null,"class","SideNav-icon octicon");
|
||||||
svg.setAttributeNS(null,"style","witdh:16px;height:16px");
|
svg.setAttributeNS(null,"style","width:16px;height:16px");
|
||||||
path.setAttributeNS(null, "d", IconList["post"]);
|
path.setAttributeNS(null, "d", IconList["post"]);
|
||||||
svg.appendChild(path);
|
svg.appendChild(path);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user