hexo-theme-hydrogen 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +10 -0
- package/README.md +34 -0
- package/_config.yml +82 -0
- package/layout/_partial/footer.ejs +71 -0
- package/layout/_partial/head.ejs +55 -0
- package/layout/_partial/header.ejs +84 -0
- package/layout/_partial/pagination.ejs +66 -0
- package/layout/_partial/post-meta.ejs +81 -0
- package/layout/_partial/search.ejs +46 -0
- package/layout/_partial/sidebar.ejs +93 -0
- package/layout/archive.ejs +45 -0
- package/layout/index.ejs +53 -0
- package/layout/layout.ejs +37 -0
- package/layout/page.ejs +13 -0
- package/layout/post.ejs +78 -0
- package/layout/tag.ejs +28 -0
- package/layout/tags.ejs +21 -0
- package/package.json +12 -0
- package/scripts/generator.js +87 -0
- package/scripts/helpers.js +229 -0
- package/source/css/_markdown.css +313 -0
- package/source/css/_responsive.css +282 -0
- package/source/css/_variables.css +125 -0
- package/source/css/style.css +1857 -0
- package/source/js/main.js +366 -0
- package/source/js/search.js +267 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
---
|
|
3
|
+
|
|
4
|
+
Copyright © 2026 `Frish2021`
|
|
5
|
+
|
|
6
|
+
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:
|
|
7
|
+
|
|
8
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
9
|
+
|
|
10
|
+
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# hexo-theme-hydrogen
|
|
2
|
+
|
|
3
|
+
基于`hexo-theme-starter`主题制作,其中文译名为`氢博客`,致力于制作轻量、简介的博客。
|
|
4
|
+
|
|
5
|
+
## 1 | 如何下载
|
|
6
|
+
|
|
7
|
+
### 1.1 | 初始化Hexo(可选)
|
|
8
|
+
如果你已经有成型的hexo框架的话可以不需要初始化
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
hexo init
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### 1.2 | 下载主题
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
git clone https://github.com/CoderFrish/hexo-theme-hydrogen.git themes/hydrogen
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 1.3 | 设置主题
|
|
21
|
+
|
|
22
|
+
在文件`_config.yml`下,找到`theme`项,将其修改成以下:
|
|
23
|
+
```diff
|
|
24
|
+
theme: hydrogen
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 1.4 | 更多方法
|
|
28
|
+
|
|
29
|
+
可以用npm来安装
|
|
30
|
+
```bash
|
|
31
|
+
npm install hexo-theme-hydrogen
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
剩下同理
|
package/_config.yml
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Starter Theme Configuration
|
|
2
|
+
# 主题配置文件
|
|
3
|
+
|
|
4
|
+
# ===== 站点信息 =====
|
|
5
|
+
# 这些信息会覆盖 Hexo 根目录的配置
|
|
6
|
+
favicon: /images/favicon.ico
|
|
7
|
+
|
|
8
|
+
# ===== 导航菜单 =====
|
|
9
|
+
menu:
|
|
10
|
+
首页: /
|
|
11
|
+
归档: /archives
|
|
12
|
+
标签: /tags
|
|
13
|
+
|
|
14
|
+
# ===== 社交链接 =====
|
|
15
|
+
social:
|
|
16
|
+
github: https://github.com/CoderFrish
|
|
17
|
+
email: mailto:1573880184@qq.com
|
|
18
|
+
|
|
19
|
+
# ===== 侧边栏配置 =====
|
|
20
|
+
sidebar:
|
|
21
|
+
# 显示最新文章数量
|
|
22
|
+
recent_posts: 5
|
|
23
|
+
# 是否显示标签云
|
|
24
|
+
show_tags: true
|
|
25
|
+
# 是否显示归档
|
|
26
|
+
show_archives: true
|
|
27
|
+
|
|
28
|
+
post:
|
|
29
|
+
# 字数统计
|
|
30
|
+
word_count: true
|
|
31
|
+
# 阅读时间估算
|
|
32
|
+
reading_time: true
|
|
33
|
+
# 每分钟阅读字数
|
|
34
|
+
words_per_minute: 300
|
|
35
|
+
# 显示更新时间
|
|
36
|
+
show_updated: true
|
|
37
|
+
# 显示版权信息
|
|
38
|
+
copyright: true
|
|
39
|
+
|
|
40
|
+
# ===== 搜索配置 =====
|
|
41
|
+
search:
|
|
42
|
+
enable: true
|
|
43
|
+
# 搜索内容:title, content, tags
|
|
44
|
+
fields:
|
|
45
|
+
- title
|
|
46
|
+
- content
|
|
47
|
+
- tags
|
|
48
|
+
# 搜索结果摘要长度
|
|
49
|
+
excerpt_length: 100
|
|
50
|
+
|
|
51
|
+
# ===== 图片设置 =====
|
|
52
|
+
images:
|
|
53
|
+
# 图片懒加载
|
|
54
|
+
lazyload: true
|
|
55
|
+
# 图片灯箱效果
|
|
56
|
+
lightbox: true
|
|
57
|
+
|
|
58
|
+
# ===== 主题外观 =====
|
|
59
|
+
appearance:
|
|
60
|
+
# 默认主题:light / dark / auto
|
|
61
|
+
default_theme: auto
|
|
62
|
+
# 主题色
|
|
63
|
+
primary_color: "#2563eb"
|
|
64
|
+
# 是否显示主题切换按钮
|
|
65
|
+
theme_toggle: true
|
|
66
|
+
|
|
67
|
+
# ===== 页脚配置 =====
|
|
68
|
+
footer:
|
|
69
|
+
# 建站年份
|
|
70
|
+
since: 2025
|
|
71
|
+
# 备案信息(中国大陆)
|
|
72
|
+
icp:
|
|
73
|
+
# 自定义内容(支持 HTML)
|
|
74
|
+
custom:
|
|
75
|
+
|
|
76
|
+
# ===== TOC 目录 =====
|
|
77
|
+
toc:
|
|
78
|
+
enable: true
|
|
79
|
+
# 最大深度
|
|
80
|
+
max_depth: 3
|
|
81
|
+
# 自动编号
|
|
82
|
+
number: true
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<footer class="site-footer">
|
|
2
|
+
<div class="footer-container">
|
|
3
|
+
<div class="footer-content">
|
|
4
|
+
<!-- 版权信息 -->
|
|
5
|
+
<div class="footer-copyright">
|
|
6
|
+
<p>
|
|
7
|
+
©
|
|
8
|
+
<% if (theme.footer.since && theme.footer.since != new Date().getFullYear()) { %>
|
|
9
|
+
<%= theme.footer.since %> -
|
|
10
|
+
<% } %>
|
|
11
|
+
<%= new Date().getFullYear() %>
|
|
12
|
+
<a href="<%- url_for('/') %>"><%= config.author || config.title %></a>
|
|
13
|
+
</p>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<!-- 社交链接 -->
|
|
17
|
+
<% if (theme.social) { %>
|
|
18
|
+
<div class="footer-social">
|
|
19
|
+
<% if (theme.social.github) { %>
|
|
20
|
+
<a href="<%= theme.social.github %>" target="_blank" rel="noopener noreferrer" aria-label="GitHub" title="GitHub">
|
|
21
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
22
|
+
<path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"></path>
|
|
23
|
+
<path d="M9 18c-4.51 2-5-2-7-2"></path>
|
|
24
|
+
</svg>
|
|
25
|
+
</a>
|
|
26
|
+
<% } %>
|
|
27
|
+
<% if (theme.social.twitter) { %>
|
|
28
|
+
<a href="<%= theme.social.twitter %>" target="_blank" rel="noopener noreferrer" aria-label="Twitter" title="Twitter">
|
|
29
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
30
|
+
<path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"></path>
|
|
31
|
+
</svg>
|
|
32
|
+
</a>
|
|
33
|
+
<% } %>
|
|
34
|
+
<% if (theme.social.email) { %>
|
|
35
|
+
<a href="<%= theme.social.email %>" aria-label="Email" title="Email">
|
|
36
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
37
|
+
<rect width="20" height="16" x="2" y="4" rx="2"></rect>
|
|
38
|
+
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"></path>
|
|
39
|
+
</svg>
|
|
40
|
+
</a>
|
|
41
|
+
<% } %>
|
|
42
|
+
</div>
|
|
43
|
+
<% } %>
|
|
44
|
+
|
|
45
|
+
<!-- 技术支持 -->
|
|
46
|
+
<div class="footer-powered">
|
|
47
|
+
<p>
|
|
48
|
+
Powered by <a href="https://hexo.io" target="_blank" rel="noopener noreferrer">Hexo</a>
|
|
49
|
+
<span class="separator">|</span>
|
|
50
|
+
Theme Hydrogen
|
|
51
|
+
</p>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<!-- 备案信息 -->
|
|
55
|
+
<% if (theme.footer.icp) { %>
|
|
56
|
+
<div class="footer-icp">
|
|
57
|
+
<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener noreferrer">
|
|
58
|
+
<%= theme.footer.icp %>
|
|
59
|
+
</a>
|
|
60
|
+
</div>
|
|
61
|
+
<% } %>
|
|
62
|
+
|
|
63
|
+
<!-- 自定义内容 -->
|
|
64
|
+
<% if (theme.footer.custom) { %>
|
|
65
|
+
<div class="footer-custom">
|
|
66
|
+
<%- theme.footer.custom %>
|
|
67
|
+
</div>
|
|
68
|
+
<% } %>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</footer>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<meta charset="UTF-8">
|
|
2
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
3
|
+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
4
|
+
|
|
5
|
+
<!-- 标题 -->
|
|
6
|
+
<title><%= page.title ? page.title + ' | ' + config.title : config.title %></title>
|
|
7
|
+
|
|
8
|
+
<!-- 网站描述 -->
|
|
9
|
+
<meta name="description" content="<%= page.description || page.excerpt || config.description %>">
|
|
10
|
+
<meta name="keywords" content="<%= page.tags ? page.tags.map(t => t.name).join(',') : config.keywords %>">
|
|
11
|
+
<meta name="author" content="<%= config.author %>">
|
|
12
|
+
|
|
13
|
+
<!-- Open Graph -->
|
|
14
|
+
<meta property="og:type" content="<%= is_post() ? 'article' : 'website' %>">
|
|
15
|
+
<meta property="og:title" content="<%= page.title || config.title %>">
|
|
16
|
+
<meta property="og:description" content="<%= page.description || page.excerpt || config.description %>">
|
|
17
|
+
<meta property="og:url" content="<%= url %>">
|
|
18
|
+
<meta property="og:site_name" content="<%= config.title %>">
|
|
19
|
+
<% if (page.cover) { %>
|
|
20
|
+
<meta property="og:image" content="<%= page.cover %>">
|
|
21
|
+
<% } %>
|
|
22
|
+
|
|
23
|
+
<!-- Favicon -->
|
|
24
|
+
<% if (theme.favicon) { %>
|
|
25
|
+
<link rel="icon" href="<%= url_for(theme.favicon) %>">
|
|
26
|
+
<% } %>
|
|
27
|
+
|
|
28
|
+
<!-- 预连接 -->
|
|
29
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
30
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
31
|
+
|
|
32
|
+
<!-- 字体 -->
|
|
33
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Noto+Sans+SC:wght@400;500;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
34
|
+
|
|
35
|
+
<!-- 样式表 -->
|
|
36
|
+
<%- css('css/style.css') %>
|
|
37
|
+
|
|
38
|
+
<!-- RSS -->
|
|
39
|
+
<% if (config.feed && config.feed.path) { %>
|
|
40
|
+
<link rel="alternate" type="application/rss+xml" title="<%= config.title %>" href="<%= url_for(config.feed.path) %>">
|
|
41
|
+
<% } %>
|
|
42
|
+
|
|
43
|
+
<!-- 规范链接 -->
|
|
44
|
+
<link rel="canonical" href="<%= url %>">
|
|
45
|
+
|
|
46
|
+
<!-- 主题色 -->
|
|
47
|
+
<meta name="theme-color" content="<%= theme.appearance.primary_color || '#2563eb' %>" media="(prefers-color-scheme: light)">
|
|
48
|
+
<meta name="theme-color" content="#1e293b" media="(prefers-color-scheme: dark)">
|
|
49
|
+
|
|
50
|
+
<!-- 自定义样式变量 -->
|
|
51
|
+
<style>
|
|
52
|
+
:root {
|
|
53
|
+
--primary-color: <%= theme.appearance.primary_color || '#2563eb' %>;
|
|
54
|
+
}
|
|
55
|
+
</style>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<header class="site-header">
|
|
2
|
+
<div class="header-container">
|
|
3
|
+
<!-- Logo / 站点标题 -->
|
|
4
|
+
<div class="site-brand">
|
|
5
|
+
<a href="<%- url_for('/') %>" class="site-logo">
|
|
6
|
+
<% if (theme.logo) { %>
|
|
7
|
+
<img src="<%- url_for(theme.logo) %>" alt="<%= config.title %>">
|
|
8
|
+
<% } else { %>
|
|
9
|
+
<span class="site-title"><%= config.title %></span>
|
|
10
|
+
<% } %>
|
|
11
|
+
</a>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<!-- 导航菜单 -->
|
|
15
|
+
<nav class="site-nav">
|
|
16
|
+
<ul class="nav-list">
|
|
17
|
+
<% for (let name in theme.menu) { %>
|
|
18
|
+
<li class="nav-item">
|
|
19
|
+
<a href="<%- url_for(theme.menu[name]) %>"
|
|
20
|
+
class="nav-link <%= is_current(theme.menu[name]) ? 'active' : '' %>">
|
|
21
|
+
<%= name %>
|
|
22
|
+
</a>
|
|
23
|
+
</li>
|
|
24
|
+
<% } %>
|
|
25
|
+
</ul>
|
|
26
|
+
</nav>
|
|
27
|
+
|
|
28
|
+
<!-- 工具栏 -->
|
|
29
|
+
<div class="header-tools">
|
|
30
|
+
<!-- 搜索按钮 -->
|
|
31
|
+
<% if (theme.search.enable) { %>
|
|
32
|
+
<button class="tool-btn search-toggle" aria-label="搜索" title="搜索">
|
|
33
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
34
|
+
<circle cx="11" cy="11" r="8"></circle>
|
|
35
|
+
<path d="m21 21-4.3-4.3"></path>
|
|
36
|
+
</svg>
|
|
37
|
+
</button>
|
|
38
|
+
<% } %>
|
|
39
|
+
|
|
40
|
+
<!-- 主题切换 -->
|
|
41
|
+
<% if (theme.appearance.theme_toggle) { %>
|
|
42
|
+
<button class="tool-btn theme-toggle" aria-label="切换主题" title="切换主题">
|
|
43
|
+
<svg class="icon-sun" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
44
|
+
<circle cx="12" cy="12" r="4"></circle>
|
|
45
|
+
<path d="M12 2v2"></path>
|
|
46
|
+
<path d="M12 20v2"></path>
|
|
47
|
+
<path d="m4.93 4.93 1.41 1.41"></path>
|
|
48
|
+
<path d="m17.66 17.66 1.41 1.41"></path>
|
|
49
|
+
<path d="M2 12h2"></path>
|
|
50
|
+
<path d="M20 12h2"></path>
|
|
51
|
+
<path d="m6.34 17.66-1.41 1.41"></path>
|
|
52
|
+
<path d="m19.07 4.93-1.41 1.41"></path>
|
|
53
|
+
</svg>
|
|
54
|
+
<svg class="icon-moon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
55
|
+
<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path>
|
|
56
|
+
</svg>
|
|
57
|
+
</button>
|
|
58
|
+
<% } %>
|
|
59
|
+
|
|
60
|
+
<!-- 移动端菜单按钮 -->
|
|
61
|
+
<button class="tool-btn menu-toggle" aria-label="菜单" title="菜单">
|
|
62
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
63
|
+
<line x1="4" x2="20" y1="12" y2="12"></line>
|
|
64
|
+
<line x1="4" x2="20" y1="6" y2="6"></line>
|
|
65
|
+
<line x1="4" x2="20" y1="18" y2="18"></line>
|
|
66
|
+
</svg>
|
|
67
|
+
</button>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<!-- 移动端导航 -->
|
|
72
|
+
<div class="mobile-nav">
|
|
73
|
+
<ul class="mobile-nav-list">
|
|
74
|
+
<% for (let name in theme.menu) { %>
|
|
75
|
+
<li class="mobile-nav-item">
|
|
76
|
+
<a href="<%- url_for(theme.menu[name]) %>"
|
|
77
|
+
class="mobile-nav-link <%= is_current(theme.menu[name]) ? 'active' : '' %>">
|
|
78
|
+
<%= name %>
|
|
79
|
+
</a>
|
|
80
|
+
</li>
|
|
81
|
+
<% } %>
|
|
82
|
+
</ul>
|
|
83
|
+
</div>
|
|
84
|
+
</header>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<% if (page.total > 1) { %>
|
|
2
|
+
<nav class="pagination">
|
|
3
|
+
<% if (page.prev) { %>
|
|
4
|
+
<a href="<%- url_for(page.prev_link) %>" class="page-link prev">
|
|
5
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
6
|
+
<path d="m15 18-6-6 6-6"></path>
|
|
7
|
+
</svg>
|
|
8
|
+
上一页
|
|
9
|
+
</a>
|
|
10
|
+
<% } else { %>
|
|
11
|
+
<span class="page-link prev disabled">
|
|
12
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
13
|
+
<path d="m15 18-6-6 6-6"></path>
|
|
14
|
+
</svg>
|
|
15
|
+
上一页
|
|
16
|
+
</span>
|
|
17
|
+
<% } %>
|
|
18
|
+
|
|
19
|
+
<div class="page-numbers">
|
|
20
|
+
<%
|
|
21
|
+
const current = page.current;
|
|
22
|
+
const total = page.total;
|
|
23
|
+
const start = Math.max(1, current - 2);
|
|
24
|
+
const end = Math.min(total, current + 2);
|
|
25
|
+
%>
|
|
26
|
+
|
|
27
|
+
<% if (start > 1) { %>
|
|
28
|
+
<a href="<%- url_for(page.base) %>" class="page-number">1</a>
|
|
29
|
+
<% if (start > 2) { %>
|
|
30
|
+
<span class="page-ellipsis">...</span>
|
|
31
|
+
<% } %>
|
|
32
|
+
<% } %>
|
|
33
|
+
|
|
34
|
+
<% for (let i = start; i <= end; i++) { %>
|
|
35
|
+
<% if (i === current) { %>
|
|
36
|
+
<span class="page-number current"><%= i %></span>
|
|
37
|
+
<% } else { %>
|
|
38
|
+
<a href="<%- url_for(page.base + (i === 1 ? '' : config.pagination_dir + '/' + i + '/')) %>" class="page-number"><%= i %></a>
|
|
39
|
+
<% } %>
|
|
40
|
+
<% } %>
|
|
41
|
+
|
|
42
|
+
<% if (end < total) { %>
|
|
43
|
+
<% if (end < total - 1) { %>
|
|
44
|
+
<span class="page-ellipsis">...</span>
|
|
45
|
+
<% } %>
|
|
46
|
+
<a href="<%- url_for(page.base + config.pagination_dir + '/' + total + '/') %>" class="page-number"><%= total %></a>
|
|
47
|
+
<% } %>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<% if (page.next) { %>
|
|
51
|
+
<a href="<%- url_for(page.next_link) %>" class="page-link next">
|
|
52
|
+
下一页
|
|
53
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
54
|
+
<path d="m9 18 6-6-6-6"></path>
|
|
55
|
+
</svg>
|
|
56
|
+
</a>
|
|
57
|
+
<% } else { %>
|
|
58
|
+
<span class="page-link next disabled">
|
|
59
|
+
下一页
|
|
60
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
61
|
+
<path d="m9 18 6-6-6-6"></path>
|
|
62
|
+
</svg>
|
|
63
|
+
</span>
|
|
64
|
+
<% } %>
|
|
65
|
+
</nav>
|
|
66
|
+
<% } %>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<div class="post-meta">
|
|
2
|
+
<!-- 发布日期 -->
|
|
3
|
+
<span class="meta-item meta-date">
|
|
4
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
5
|
+
<rect width="18" height="18" x="3" y="4" rx="2" ry="2"></rect>
|
|
6
|
+
<line x1="16" x2="16" y1="2" y2="6"></line>
|
|
7
|
+
<line x1="8" x2="8" y1="2" y2="6"></line>
|
|
8
|
+
<line x1="3" x2="21" y1="10" y2="10"></line>
|
|
9
|
+
</svg>
|
|
10
|
+
<time datetime="<%= date(post.date, 'YYYY-MM-DD') %>">
|
|
11
|
+
<%= date(post.date, 'YYYY-MM-DD') %>
|
|
12
|
+
</time>
|
|
13
|
+
</span>
|
|
14
|
+
|
|
15
|
+
<!-- 更新日期 -->
|
|
16
|
+
<% if (typeof showFull !== 'undefined' && showFull && theme.post.show_updated && post.updated && post.updated.valueOf() !== post.date.valueOf()) { %>
|
|
17
|
+
<span class="meta-item meta-updated">
|
|
18
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
19
|
+
<path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"></path>
|
|
20
|
+
<path d="M21 3v5h-5"></path>
|
|
21
|
+
</svg>
|
|
22
|
+
<time datetime="<%= date(post.updated, 'YYYY-MM-DD') %>">
|
|
23
|
+
更新于 <%= date(post.updated, 'YYYY-MM-DD') %>
|
|
24
|
+
</time>
|
|
25
|
+
</span>
|
|
26
|
+
<% } %>
|
|
27
|
+
|
|
28
|
+
<!-- 字数统计 -->
|
|
29
|
+
<% if (theme.post.word_count) { %>
|
|
30
|
+
<span class="meta-item meta-wordcount">
|
|
31
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
32
|
+
<path d="M17 6.1H3"></path>
|
|
33
|
+
<path d="M21 12.1H3"></path>
|
|
34
|
+
<path d="M15.1 18H3"></path>
|
|
35
|
+
</svg>
|
|
36
|
+
<%
|
|
37
|
+
const content = strip_html(post.content);
|
|
38
|
+
const wordCount = content.length;
|
|
39
|
+
const displayCount = wordCount >= 1000 ? (wordCount / 1000).toFixed(1) + 'k' : wordCount;
|
|
40
|
+
%>
|
|
41
|
+
<%= displayCount %> 字
|
|
42
|
+
</span>
|
|
43
|
+
<% } %>
|
|
44
|
+
|
|
45
|
+
<!-- 阅读时间 -->
|
|
46
|
+
<% if (theme.post.reading_time) { %>
|
|
47
|
+
<span class="meta-item meta-readtime">
|
|
48
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
49
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
50
|
+
<polyline points="12 6 12 12 16 14"></polyline>
|
|
51
|
+
</svg>
|
|
52
|
+
<%
|
|
53
|
+
const wpm = theme.post.words_per_minute || 300;
|
|
54
|
+
const text = strip_html(post.content);
|
|
55
|
+
const minutes = Math.ceil(text.length / wpm);
|
|
56
|
+
%>
|
|
57
|
+
约 <%= minutes %> 分钟
|
|
58
|
+
</span>
|
|
59
|
+
<% } %>
|
|
60
|
+
|
|
61
|
+
<!-- 标签(仅在列表页显示前几个) -->
|
|
62
|
+
<% if (post.tags && post.tags.length && (typeof showFull === 'undefined' || !showFull)) { %>
|
|
63
|
+
<span class="meta-item meta-tags">
|
|
64
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
65
|
+
<path d="M12 2H2v10l9.29 9.29c.94.94 2.48.94 3.42 0l6.58-6.58c.94-.94.94-2.48 0-3.42L12 2Z"></path>
|
|
66
|
+
<path d="M7 7h.01"></path>
|
|
67
|
+
</svg>
|
|
68
|
+
<%
|
|
69
|
+
let tagCount = 0;
|
|
70
|
+
post.tags.each(function(tag) {
|
|
71
|
+
if (tagCount < 3) {
|
|
72
|
+
%>
|
|
73
|
+
<a href="<%- url_for(tag.path) %>"><%= tag.name %></a>
|
|
74
|
+
<%
|
|
75
|
+
tagCount++;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
%>
|
|
79
|
+
</span>
|
|
80
|
+
<% } %>
|
|
81
|
+
</div>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<div id="search-modal" class="search-modal">
|
|
2
|
+
<div class="search-container">
|
|
3
|
+
<!-- 搜索头部 -->
|
|
4
|
+
<div class="search-header">
|
|
5
|
+
<div class="search-input-wrapper">
|
|
6
|
+
<svg class="search-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
7
|
+
<circle cx="11" cy="11" r="8"></circle>
|
|
8
|
+
<path d="m21 21-4.3-4.3"></path>
|
|
9
|
+
</svg>
|
|
10
|
+
<input
|
|
11
|
+
type="text"
|
|
12
|
+
id="search-input"
|
|
13
|
+
class="search-input"
|
|
14
|
+
placeholder="搜索文章、文档..."
|
|
15
|
+
autocomplete="off"
|
|
16
|
+
autofocus
|
|
17
|
+
>
|
|
18
|
+
<button class="search-close" aria-label="关闭">
|
|
19
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
20
|
+
<path d="M18 6 6 18"></path>
|
|
21
|
+
<path d="m6 6 12 12"></path>
|
|
22
|
+
</svg>
|
|
23
|
+
</button>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="search-shortcut">
|
|
26
|
+
<kbd>ESC</kbd> 关闭
|
|
27
|
+
<span class="shortcut-divider">|</span>
|
|
28
|
+
<kbd>↑</kbd><kbd>↓</kbd> 导航
|
|
29
|
+
<span class="shortcut-divider">|</span>
|
|
30
|
+
<kbd>Enter</kbd> 打开
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<!-- 搜索结果 -->
|
|
35
|
+
<div id="search-results" class="search-results">
|
|
36
|
+
<div class="search-tip">输入关键词开始搜索</div>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<!-- 搜索页脚 -->
|
|
40
|
+
<div class="search-footer">
|
|
41
|
+
<span class="search-footer-text">
|
|
42
|
+
<kbd>Ctrl</kbd> + <kbd>K</kbd> 快速搜索
|
|
43
|
+
</span>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<aside class="blog-sidebar">
|
|
2
|
+
<!-- 作者信息 -->
|
|
3
|
+
<div class="sidebar-widget author-widget">
|
|
4
|
+
<div class="author-avatar">
|
|
5
|
+
<% if (config.author_avatar) { %>
|
|
6
|
+
<img src="<%- url_for(config.author_avatar) %>" alt="<%= config.author %>">
|
|
7
|
+
<% } else { %>
|
|
8
|
+
<div class="avatar-placeholder">
|
|
9
|
+
<%= config.author ? config.author.charAt(0).toUpperCase() : 'A' %>
|
|
10
|
+
</div>
|
|
11
|
+
<% } %>
|
|
12
|
+
</div>
|
|
13
|
+
<h3 class="author-name"><%= config.author || config.title %></h3>
|
|
14
|
+
<p class="author-desc"><%= config.description %></p>
|
|
15
|
+
<div class="author-stats">
|
|
16
|
+
<div class="stat-item">
|
|
17
|
+
<span class="stat-count"><%= site.posts.length %></span>
|
|
18
|
+
<span class="stat-label">文章</span>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="stat-item">
|
|
21
|
+
<span class="stat-count"><%= site.tags.length %></span>
|
|
22
|
+
<span class="stat-label">标签</span>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="stat-item">
|
|
25
|
+
<span class="stat-count"><%= site.categories.length %></span>
|
|
26
|
+
<span class="stat-label">分类</span>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<a class="author-about" href="/about">
|
|
31
|
+
关于我
|
|
32
|
+
</a>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<!-- 最新文章 -->
|
|
36
|
+
<% if (theme.sidebar.recent_posts) { %>
|
|
37
|
+
<div class="sidebar-widget recent-posts-widget">
|
|
38
|
+
<h3 class="widget-title">最新文章</h3>
|
|
39
|
+
<ul class="recent-posts-list">
|
|
40
|
+
<% site.posts.sort('date', 'desc').limit(theme.sidebar.recent_posts).each(function(post) { %>
|
|
41
|
+
<li class="recent-post-item">
|
|
42
|
+
<a href="<%- url_for(post.path) %>">
|
|
43
|
+
<span class="recent-post-title"><%= post.title %></span>
|
|
44
|
+
<span class="recent-post-date"><%= date(post.date, 'MM-DD') %></span>
|
|
45
|
+
</a>
|
|
46
|
+
</li>
|
|
47
|
+
<% }) %>
|
|
48
|
+
</ul>
|
|
49
|
+
</div>
|
|
50
|
+
<% } %>
|
|
51
|
+
|
|
52
|
+
<!-- 标签云 -->
|
|
53
|
+
<% if (theme.sidebar.show_tags && site.tags.length) { %>
|
|
54
|
+
<div class="sidebar-widget tags-widget">
|
|
55
|
+
<h3 class="widget-title">标签</h3>
|
|
56
|
+
<div class="sidebar-tags">
|
|
57
|
+
<% site.tags.sort('name').each(function(tag) { %>
|
|
58
|
+
<a href="<%- url_for(tag.path) %>" class="sidebar-tag">
|
|
59
|
+
<%= tag.name %><span class="tag-count"><%= tag.posts.length %></span>
|
|
60
|
+
</a>
|
|
61
|
+
<% }) %>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
<% } %>
|
|
65
|
+
|
|
66
|
+
<!-- 归档 -->
|
|
67
|
+
<% if (theme.sidebar.show_archives) { %>
|
|
68
|
+
<div class="sidebar-widget archives-widget">
|
|
69
|
+
<h3 class="widget-title">归档</h3>
|
|
70
|
+
<ul class="archives-list">
|
|
71
|
+
<%
|
|
72
|
+
const archives = {};
|
|
73
|
+
site.posts.each(function(post) {
|
|
74
|
+
const key = date(post.date, 'YYYY-MM');
|
|
75
|
+
if (!archives[key]) {
|
|
76
|
+
archives[key] = { date: post.date, count: 0 };
|
|
77
|
+
}
|
|
78
|
+
archives[key].count++;
|
|
79
|
+
});
|
|
80
|
+
const sortedArchives = Object.keys(archives).sort().reverse().slice(0, 12);
|
|
81
|
+
%>
|
|
82
|
+
<% sortedArchives.forEach(function(key) { %>
|
|
83
|
+
<li class="archive-item">
|
|
84
|
+
<a href="<%- url_for('/archives/' + key.replace('-', '/') + '/') %>">
|
|
85
|
+
<span class="archive-date"><%= key %></span>
|
|
86
|
+
<span class="archive-count">(<%= archives[key].count %>)</span>
|
|
87
|
+
</a>
|
|
88
|
+
</li>
|
|
89
|
+
<% }) %>
|
|
90
|
+
</ul>
|
|
91
|
+
</div>
|
|
92
|
+
<% } %>
|
|
93
|
+
</aside>
|