hexo-sitemap-html 1.0.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/.gitattributes +2 -0
- package/LICENSE +21 -0
- package/README.md +135 -0
- package/docs/en-US/README.md +133 -0
- package/docs/zh-CN/README.md +128 -0
- package/index.js +186 -0
- package/package.json +41 -0
package/.gitattributes
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 2winter_dev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
|
|
2
|
+
# hexo-sitemap-html
|
|
3
|
+
|
|
4
|
+
A **modern, responsive, and highly configurable** Hexo plugin to generate elegant HTML sitemaps. Fully compatible with **Node 22+** and **Hexo 6.x**.
|
|
5
|
+
|
|
6
|
+
> 📌 [中文版本 (Chinese Version)](./docs/zh-CN/README.md)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## ✨ Core Features
|
|
11
|
+
|
|
12
|
+
* 🚀 **Node 22 Ready**: Uses the modern `module.exports` pattern to ensure perfect compatibility with the latest Node.js environments.
|
|
13
|
+
* 📱 **Responsive Design**: Brand new `modern` layout with a card-grid system that looks great on mobile and desktop.
|
|
14
|
+
* 🔗 **Auto Menu Injection**: Automatically injects a "Sitemap" link into your theme's navigation bar (supports most mainstream themes).
|
|
15
|
+
* 📝 **Flexible Configuration**: Independently enable/disable categories, posts, or pages.
|
|
16
|
+
* 🚫 **Fuzzy Exclusion**: Precisely exclude unwanted pages (e.g., 404, tags) using keywords in titles or paths.
|
|
17
|
+
* 🎨 **Multiple Layouts**: Built-in styles including `Modern`, `Simple`, and `Rich`.
|
|
18
|
+
* 🔧 **Native UTF-8**: Zero garbled characters, perfect for CJK (Chinese, Japanese, Korean) content.
|
|
19
|
+
|
|
20
|
+
## 📦 Installation
|
|
21
|
+
|
|
22
|
+
### Method 1: Local Development (Manual)
|
|
23
|
+
|
|
24
|
+
If you are developing or customizing the plugin:
|
|
25
|
+
|
|
26
|
+
1. In your Hexo blog root, create the folder: `node_modules/hexo-sitemap-html`.
|
|
27
|
+
2. Place `index.js` and `package.json` inside.
|
|
28
|
+
3. In your **blog root**, run:
|
|
29
|
+
```bash
|
|
30
|
+
npm install ./node_modules/hexo-sitemap-html
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Method 2: Via npm (Standard)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install hexo-sitemap-html --save
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## ⚙️ Configuration
|
|
44
|
+
|
|
45
|
+
Add the following to your Hexo root `_config.yml`:
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
# hexo-sitemap-html Configuration
|
|
49
|
+
html_sitemap:
|
|
50
|
+
path: 'sitemap.html' # Output path
|
|
51
|
+
layout: 'modern' # Options: modern, simple, rich
|
|
52
|
+
inject_menu: true # Auto-add "Sitemap" to your blog navigation
|
|
53
|
+
nofollow: true # Add rel="nofollow" to sitemap links
|
|
54
|
+
|
|
55
|
+
enable:
|
|
56
|
+
categories: true # Show categories section
|
|
57
|
+
posts: true # Show posts section
|
|
58
|
+
pages: true # Show standalone pages section
|
|
59
|
+
|
|
60
|
+
exclude: # Fuzzy match title or path to hide pages
|
|
61
|
+
- '404'
|
|
62
|
+
- 'guestbook'
|
|
63
|
+
- 'About Me'
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Configuration Details
|
|
68
|
+
|
|
69
|
+
| Option | Type | Default | Description |
|
|
70
|
+
| --- | --- | --- | --- |
|
|
71
|
+
| `path` | String | `sitemap.html` | The filename of the generated sitemap. |
|
|
72
|
+
| `layout` | String | `modern` | UI Style: `modern` (Grid), `simple` (List), `rich` (Animated Cards). |
|
|
73
|
+
| `inject_menu` | Boolean | `false` | Dynamically injects the sitemap link into `theme.menu`. |
|
|
74
|
+
| `nofollow` | Boolean | `false` | If true, search engines won't follow the sitemap links. |
|
|
75
|
+
| `exclude` | Array | `[]` | Keywords to filter out specific pages from the sitemap. |
|
|
76
|
+
|
|
77
|
+
## 🚀 Usage
|
|
78
|
+
|
|
79
|
+
1. Clean and generate:
|
|
80
|
+
```bash
|
|
81
|
+
hexo clean && hexo generate
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
2. Start local server:
|
|
87
|
+
```bash
|
|
88
|
+
hexo server
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
3. Visit: `http://localhost:4000/sitemap.html`
|
|
94
|
+
|
|
95
|
+
## 🎨 Layout Previews
|
|
96
|
+
|
|
97
|
+
### 1. Modern Layout (New!)
|
|
98
|
+
|
|
99
|
+
* **Features**: CSS-Grid card system, mobile-friendly, clean typography.
|
|
100
|
+
* **Best for**: Modern tech blogs and large portfolios.
|
|
101
|
+
|
|
102
|
+
### 2. Simple Layout
|
|
103
|
+
|
|
104
|
+
* **Features**: Minimalist text list, fast loading, no-distraction design.
|
|
105
|
+
* **Best for**: Personal diaries or minimal sites.
|
|
106
|
+
|
|
107
|
+
### 3. Rich Layout
|
|
108
|
+
|
|
109
|
+
* **Features**: Card-based design with hover animations and deeper shadows.
|
|
110
|
+
* **Best for**: Visually-driven blogs.
|
|
111
|
+
|
|
112
|
+
## ❓ FAQ
|
|
113
|
+
|
|
114
|
+
### Q1: The Sitemap is not showing in my Menu?
|
|
115
|
+
|
|
116
|
+
A: `inject_menu` works by modifying `theme.config.menu` in memory. If your theme uses a non-standard menu structure (not `menu` or `navbar`), you may need to add the link manually to your theme's `_config.yml`.
|
|
117
|
+
|
|
118
|
+
### Q2: Is it compatible with Node 22?
|
|
119
|
+
|
|
120
|
+
A: Yes! This version uses the Dependency Injection pattern (`module.exports = function(hexo)...`) which is the safest way to handle plugins in Node 22/Hexo 6.
|
|
121
|
+
|
|
122
|
+
### Q3: How to customize the CSS?
|
|
123
|
+
|
|
124
|
+
A: You can find the `<style>` tags in `index.js` under the `LAYOUT_STYLES` constant. Feel free to modify the colors or fonts to match your specific theme.
|
|
125
|
+
|
|
126
|
+
## 🤝 Contributing
|
|
127
|
+
|
|
128
|
+
1. Fork the repo.
|
|
129
|
+
2. Create your branch (`git checkout -b feature/AmazingFeature`).
|
|
130
|
+
3. Commit (`git commit -m 'Add some feature'`).
|
|
131
|
+
4. Push to the branch and open a Pull Request.
|
|
132
|
+
|
|
133
|
+
## 📄 License
|
|
134
|
+
|
|
135
|
+
This project is licensed under the **MIT License**.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
|
|
2
|
+
# hexo-sitemap-html
|
|
3
|
+
|
|
4
|
+
A **modern, responsive, and highly configurable** Hexo plugin to generate elegant HTML sitemaps. Fully compatible with **Node 22+** and **Hexo 6.x**.
|
|
5
|
+
|
|
6
|
+
> 📌 [中文版本 (Chinese Version)](../zh-CN/README.md)
|
|
7
|
+
|
|
8
|
+
## ✨ Core Features
|
|
9
|
+
|
|
10
|
+
* 🚀 **Node 22 Ready**: Uses the modern `module.exports` pattern to ensure perfect compatibility with the latest Node.js environments.
|
|
11
|
+
* 📱 **Responsive Design**: Brand new `modern` layout with a card-grid system that looks great on mobile and desktop.
|
|
12
|
+
* 🔗 **Auto Menu Injection**: Automatically injects a "Sitemap" link into your theme's navigation bar (supports most mainstream themes).
|
|
13
|
+
* 📝 **Flexible Configuration**: Independently enable/disable categories, posts, or pages.
|
|
14
|
+
* 🚫 **Fuzzy Exclusion**: Precisely exclude unwanted pages (e.g., 404, tags) using keywords in titles or paths.
|
|
15
|
+
* 🎨 **Multiple Layouts**: Built-in styles including `Modern`, `Simple`, and `Rich`.
|
|
16
|
+
* 🔧 **Native UTF-8**: Zero garbled characters, perfect for CJK (Chinese, Japanese, Korean) content.
|
|
17
|
+
|
|
18
|
+
## 📦 Installation
|
|
19
|
+
|
|
20
|
+
### Method 1: Local Development (Manual)
|
|
21
|
+
|
|
22
|
+
If you are developing or customizing the plugin:
|
|
23
|
+
|
|
24
|
+
1. In your Hexo blog root, create the folder: `node_modules/hexo-sitemap-html`.
|
|
25
|
+
2. Place `index.js` and `package.json` inside.
|
|
26
|
+
3. In your **blog root**, run:
|
|
27
|
+
```bash
|
|
28
|
+
npm install ./node_modules/hexo-sitemap-html
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Method 2: Via npm (Standard)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install hexo-sitemap-html --save
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## ⚙️ Configuration
|
|
42
|
+
|
|
43
|
+
Add the following to your Hexo root `_config.yml`:
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
# hexo-sitemap-html Configuration
|
|
47
|
+
html_sitemap:
|
|
48
|
+
path: 'sitemap.html' # Output path
|
|
49
|
+
layout: 'modern' # Options: modern, simple, rich
|
|
50
|
+
inject_menu: true # Auto-add "Sitemap" to your blog navigation
|
|
51
|
+
nofollow: true # Add rel="nofollow" to sitemap links
|
|
52
|
+
|
|
53
|
+
enable:
|
|
54
|
+
categories: true # Show categories section
|
|
55
|
+
posts: true # Show posts section
|
|
56
|
+
pages: true # Show standalone pages section
|
|
57
|
+
|
|
58
|
+
exclude: # Fuzzy match title or path to hide pages
|
|
59
|
+
- '404'
|
|
60
|
+
- 'guestbook'
|
|
61
|
+
- 'About Me'
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Configuration Details
|
|
66
|
+
|
|
67
|
+
| Option | Type | Default | Description |
|
|
68
|
+
| --- | --- | --- | --- |
|
|
69
|
+
| `path` | String | `sitemap.html` | The filename of the generated sitemap. |
|
|
70
|
+
| `layout` | String | `modern` | UI Style: `modern` (Grid), `simple` (List), `rich` (Animated Cards). |
|
|
71
|
+
| `inject_menu` | Boolean | `false` | Dynamically injects the sitemap link into `theme.menu`. |
|
|
72
|
+
| `nofollow` | Boolean | `false` | If true, search engines won't follow the sitemap links. |
|
|
73
|
+
| `exclude` | Array | `[]` | Keywords to filter out specific pages from the sitemap. |
|
|
74
|
+
|
|
75
|
+
## 🚀 Usage
|
|
76
|
+
|
|
77
|
+
1. Clean and generate:
|
|
78
|
+
```bash
|
|
79
|
+
hexo clean && hexo generate
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
2. Start local server:
|
|
85
|
+
```bash
|
|
86
|
+
hexo server
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
3. Visit: `http://localhost:4000/sitemap.html`
|
|
92
|
+
|
|
93
|
+
## 🎨 Layout Previews
|
|
94
|
+
|
|
95
|
+
### 1. Modern Layout (New!)
|
|
96
|
+
|
|
97
|
+
* **Features**: CSS-Grid card system, mobile-friendly, clean typography.
|
|
98
|
+
* **Best for**: Modern tech blogs and large portfolios.
|
|
99
|
+
|
|
100
|
+
### 2. Simple Layout
|
|
101
|
+
|
|
102
|
+
* **Features**: Minimalist text list, fast loading, no-distraction design.
|
|
103
|
+
* **Best for**: Personal diaries or minimal sites.
|
|
104
|
+
|
|
105
|
+
### 3. Rich Layout
|
|
106
|
+
|
|
107
|
+
* **Features**: Card-based design with hover animations and deeper shadows.
|
|
108
|
+
* **Best for**: Visually-driven blogs.
|
|
109
|
+
|
|
110
|
+
## ❓ FAQ
|
|
111
|
+
|
|
112
|
+
### Q1: The Sitemap is not showing in my Menu?
|
|
113
|
+
|
|
114
|
+
A: `inject_menu` works by modifying `theme.config.menu` in memory. If your theme uses a non-standard menu structure (not `menu` or `navbar`), you may need to add the link manually to your theme's `_config.yml`.
|
|
115
|
+
|
|
116
|
+
### Q2: Is it compatible with Node 22?
|
|
117
|
+
|
|
118
|
+
A: Yes! This version uses the Dependency Injection pattern (`module.exports = function(hexo)...`) which is the safest way to handle plugins in Node 22/Hexo 6.
|
|
119
|
+
|
|
120
|
+
### Q3: How to customize the CSS?
|
|
121
|
+
|
|
122
|
+
A: You can find the `<style>` tags in `index.js` under the `LAYOUT_STYLES` constant. Feel free to modify the colors or fonts to match your specific theme.
|
|
123
|
+
|
|
124
|
+
## 🤝 Contributing
|
|
125
|
+
|
|
126
|
+
1. Fork the repo.
|
|
127
|
+
2. Create your branch (`git checkout -b feature/AmazingFeature`).
|
|
128
|
+
3. Commit (`git commit -m 'Add some feature'`).
|
|
129
|
+
4. Push to the branch and open a Pull Request.
|
|
130
|
+
|
|
131
|
+
## 📄 License
|
|
132
|
+
|
|
133
|
+
This project is licensed under the **MIT License**.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
# hexo-sitemap-html
|
|
4
|
+
|
|
5
|
+
一个**现代、响应式、高度可配置**的 Hexo 插件,用于生成美观的 HTML 格式站点地图。完美适配 **Node 22+** 和 **Hexo 6.x**。
|
|
6
|
+
|
|
7
|
+
> 📌 语言切换:[English Version](../en-US/README.md)
|
|
8
|
+
|
|
9
|
+
## ✨ 核心特性
|
|
10
|
+
|
|
11
|
+
* 🚀 **适配 Node 22**:采用现代的 `module.exports` 插件导出模式,解决新版本 Node 环境下的作用域与全局变量注入问题。
|
|
12
|
+
* 📱 **响应式设计**:全新的 `modern` 布局,采用网格系统(Grid),完美适配手机和电脑端浏览。
|
|
13
|
+
* 🔗 **菜单自动注入**:支持将站点地图链接自动插入到主题的导航栏(适配 NexT, Butterfly, Fluid 等主流主题)。
|
|
14
|
+
* 📝 **灵活配置**:独立控制分类、文章、页面模块的开关。
|
|
15
|
+
* 🚫 **模糊排除**:支持通过标题或路径关键词,精准排除不需要展示的页面(如 404 页、标签页)。
|
|
16
|
+
* 🎨 **多布局风格**:内置 3 种布局(Modern 现代 / Simple 简洁 / Rich 丰富)。
|
|
17
|
+
* 🔧 **零乱码**:原生支持 UTF-8,完美适配中日韩等非 ASCII 字符。
|
|
18
|
+
|
|
19
|
+
## 📦 安装
|
|
20
|
+
|
|
21
|
+
### 方式 1:本地开发(推荐)
|
|
22
|
+
|
|
23
|
+
如果您正在开发或自定义插件:
|
|
24
|
+
|
|
25
|
+
1. 在 Hexo 博客根目录下创建目录:`node_modules/hexo-sitemap-html`。
|
|
26
|
+
2. 将 `index.js` 和 `package.json` 放入该目录。
|
|
27
|
+
3. 在**博客根目录**执行:
|
|
28
|
+
```bash
|
|
29
|
+
npm install ./node_modules/hexo-sitemap-html
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### 方式 2:npm 安装(发布后)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install hexo-sitemap-html --save
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## ⚙️ 配置
|
|
43
|
+
|
|
44
|
+
在 Hexo 博客根目录的 `_config.yml` 中添加以下配置:
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
# hexo-sitemap-html 配置
|
|
48
|
+
html_sitemap:
|
|
49
|
+
path: 'sitemap.html' # 输出路径
|
|
50
|
+
layout: 'modern' # 布局选择: modern, simple, rich
|
|
51
|
+
inject_menu: true # 自动将“站点地图”添加到博客导航栏
|
|
52
|
+
nofollow: true # 为地图链接添加 rel="nofollow",避免分散权重
|
|
53
|
+
|
|
54
|
+
enable:
|
|
55
|
+
categories: true # 显示分类
|
|
56
|
+
posts: true # 显示文章
|
|
57
|
+
pages: true # 显示独立页面
|
|
58
|
+
|
|
59
|
+
exclude: # 排除页面(模糊匹配标题或路径)
|
|
60
|
+
- '404'
|
|
61
|
+
- 'guestbook'
|
|
62
|
+
- '关于我'
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 配置项详情
|
|
67
|
+
|
|
68
|
+
| 配置项 | 类型 | 默认值 | 说明 |
|
|
69
|
+
| --- | --- | --- | --- |
|
|
70
|
+
| `path` | String | `sitemap.html` | 生成的文件名。 |
|
|
71
|
+
| `layout` | String | `modern` | UI 风格:`modern` (响应式网格), `simple` (纯文本列表), `rich` (带动画的卡片)。 |
|
|
72
|
+
| `inject_menu` | Boolean | `false` | 是否自动修改 `theme.menu` 配置,动态注入菜单链接。 |
|
|
73
|
+
| `nofollow` | Boolean | `false` | 开启后,生成的链接会带上 `nofollow` 属性。 |
|
|
74
|
+
| `exclude` | Array | `[]` | 关键词数组,匹配到的页面将不会出现在站点地图中。 |
|
|
75
|
+
|
|
76
|
+
## 🚀 使用
|
|
77
|
+
|
|
78
|
+
1. 清除并生成:
|
|
79
|
+
```bash
|
|
80
|
+
hexo clean && hexo generate
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
2. 本地预览:
|
|
86
|
+
```bash
|
|
87
|
+
hexo server
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
3. 访问:`http://localhost:4000/sitemap.html`
|
|
93
|
+
|
|
94
|
+
## 🎨 布局风格预览
|
|
95
|
+
|
|
96
|
+
### 1. modern(现代版 - 推荐)
|
|
97
|
+
|
|
98
|
+
* **特点**:基于 CSS Grid 的卡片系统,响应式布局,极简线条感。
|
|
99
|
+
* **适用**:现代技术博客、作品集。
|
|
100
|
+
|
|
101
|
+
### 2. simple(简洁版)
|
|
102
|
+
|
|
103
|
+
* **特点**:无装饰列表,加载速度最快。
|
|
104
|
+
* **适用**:追求极致简约或极简风主题。
|
|
105
|
+
|
|
106
|
+
### 3. rich(丰富版)
|
|
107
|
+
|
|
108
|
+
* **特点**:带悬浮阴影(Hover Shadow)的深色卡片设计。
|
|
109
|
+
* **适用**:视觉表现力强的主题。
|
|
110
|
+
|
|
111
|
+
## ❓ 常见问题
|
|
112
|
+
|
|
113
|
+
### Q1: 导航栏没有出现“站点地图”链接?
|
|
114
|
+
|
|
115
|
+
A: `inject_menu` 功能通过内存修改主题配置实现。如果你的主题导航栏配置非常特殊(非 `menu` 或 `navbar` 字段),可能无法自动注入。建议在主题配置中手动添加一行链接。
|
|
116
|
+
|
|
117
|
+
### Q2: 兼容 Node 22 吗?
|
|
118
|
+
|
|
119
|
+
A: 是的。针对 Node 22 严格模式下全局 `hexo` 变量获取不到的问题,本项目采用了 Dependency Injection(依赖注入)模式重新编写了入口逻辑。
|
|
120
|
+
|
|
121
|
+
### Q3: 这会影响 SEO 吗?
|
|
122
|
+
|
|
123
|
+
A: 不会。此插件生成的 HTML 地图是给**人**看的(方便读者快速定位内容)。如果你需要给搜索引擎看的地图,请同时安装 `hexo-generator-sitemap` 生成 `sitemap.xml`。
|
|
124
|
+
|
|
125
|
+
## 📄 许可证
|
|
126
|
+
|
|
127
|
+
本项目采用 **MIT** 许可证。
|
|
128
|
+
|
package/index.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const fs = require('hexo-fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
// 默认配置
|
|
8
|
+
const DEFAULT_CONFIG = {
|
|
9
|
+
path: 'sitemap.html',
|
|
10
|
+
enable: {
|
|
11
|
+
categories: true,
|
|
12
|
+
posts: true,
|
|
13
|
+
pages: true
|
|
14
|
+
},
|
|
15
|
+
exclude: [],
|
|
16
|
+
layout: 'modern', // 默认使用新模板
|
|
17
|
+
nofollow: false
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const LAYOUT_STYLES = {
|
|
21
|
+
simple: `
|
|
22
|
+
<style>
|
|
23
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
24
|
+
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; max-width: 900px; margin: 0 auto; padding: 2rem; color: #333; line-height: 1.6; }
|
|
25
|
+
h1 { text-align: center; margin-bottom: 2rem; color: #2c3e50; }
|
|
26
|
+
.section { margin-bottom: 3rem; }
|
|
27
|
+
h2 { border-bottom: 2px solid #eee; padding-bottom: 0.5rem; margin-bottom: 1rem; color: #34495e; }
|
|
28
|
+
.list { list-style: none; }
|
|
29
|
+
.list-item { padding: 0.5rem 0; border-bottom: 1px dashed #eee; display: flex; justify-content: space-between; }
|
|
30
|
+
.list-item a { color: #3498db; text-decoration: none; }
|
|
31
|
+
.list-item a:hover { color: #2980b9; text-decoration: underline; }
|
|
32
|
+
.meta { color: #95a5a6; font-size: 0.9em; }
|
|
33
|
+
</style>
|
|
34
|
+
`,
|
|
35
|
+
modern: `
|
|
36
|
+
<style>
|
|
37
|
+
:root { --primary: #6366f1; --bg: #f8fafc; --card: #ffffff; --text: #1e293b; --text-light: #64748b; }
|
|
38
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
39
|
+
body { font-family: "Inter", system-ui, sans-serif; background: var(--bg); color: var(--text); padding: 3rem 1rem; line-height: 1.5; }
|
|
40
|
+
.container { max-width: 1000px; margin: 0 auto; }
|
|
41
|
+
header { text-align: center; margin-bottom: 4rem; }
|
|
42
|
+
h1 { font-size: 2.5rem; font-weight: 800; color: var(--text); margin-bottom: 1rem; }
|
|
43
|
+
.section { margin-bottom: 4rem; }
|
|
44
|
+
h2 { font-size: 1.5rem; margin-bottom: 1.5rem; display: flex; align-items: center; gap: 0.5rem; }
|
|
45
|
+
h2::before { content: ''; display: inline-block; width: 4px; height: 1.5rem; background: var(--primary); border-radius: 4px; }
|
|
46
|
+
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1.25rem; }
|
|
47
|
+
.card { background: var(--card); padding: 1.25rem; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); transition: all 0.2s; border: 1px solid #e2e8f0; text-decoration: none; display: block; }
|
|
48
|
+
.card:hover { transform: translateY(-2px); box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1); border-color: var(--primary); }
|
|
49
|
+
.card-title { display: block; font-weight: 600; color: var(--text); margin-bottom: 0.5rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
50
|
+
.card-meta { font-size: 0.875rem; color: var(--text-light); }
|
|
51
|
+
@media (max-width: 640px) { .grid { grid-template-columns: 1fr; } }
|
|
52
|
+
</style>
|
|
53
|
+
`
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
function formatDate(date) {
|
|
57
|
+
if (!date) return 'No Date';
|
|
58
|
+
const d = new Date(date);
|
|
59
|
+
return d.toISOString().split('T')[0];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function createHtmlSitemap(hexo, force = false) {
|
|
63
|
+
const config = _.merge({}, DEFAULT_CONFIG, hexo.config.html_sitemap || {});
|
|
64
|
+
|
|
65
|
+
// 校验布局
|
|
66
|
+
if (!LAYOUT_STYLES[config.layout]) {
|
|
67
|
+
hexo.log.warn(`[hexo-sitemap-html] Invalid layout: ${config.layout}, fallback to modern`);
|
|
68
|
+
config.layout = 'modern';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const nofollowAttr = config.nofollow ? 'rel="nofollow"' : '';
|
|
72
|
+
const { categories, posts, pages } = hexo.site;
|
|
73
|
+
|
|
74
|
+
// 1. 处理数据
|
|
75
|
+
const postList = config.enable.posts ? posts.sort('date', 'desc').map(p => ({
|
|
76
|
+
title: p.title || 'Untitled',
|
|
77
|
+
path: hexo.url_for(p.path),
|
|
78
|
+
date: formatDate(p.date)
|
|
79
|
+
})) : [];
|
|
80
|
+
|
|
81
|
+
const categoryList = config.enable.categories ? categories.map(c => ({
|
|
82
|
+
name: c.name || 'Uncategorized',
|
|
83
|
+
path: hexo.url_for(c.path),
|
|
84
|
+
count: c.posts.length
|
|
85
|
+
})) : [];
|
|
86
|
+
|
|
87
|
+
const pageList = config.enable.pages ? pages.filter(p => {
|
|
88
|
+
const isExcluded = config.exclude.some(ex => p.title?.includes(ex) || p.path?.includes(ex));
|
|
89
|
+
return !isExcluded && p.path;
|
|
90
|
+
}).map(p => ({
|
|
91
|
+
title: p.title || 'Untitled Page',
|
|
92
|
+
path: hexo.url_for(p.path),
|
|
93
|
+
date: formatDate(p.date)
|
|
94
|
+
})) : [];
|
|
95
|
+
|
|
96
|
+
// 2. 生成 HTML
|
|
97
|
+
const htmlContent = `
|
|
98
|
+
<!DOCTYPE html>
|
|
99
|
+
<html lang="${hexo.config.language || 'en'}">
|
|
100
|
+
<head>
|
|
101
|
+
<meta charset="UTF-8">
|
|
102
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
103
|
+
<title>Site Map - ${hexo.config.title}</title>
|
|
104
|
+
${LAYOUT_STYLES[config.layout]}
|
|
105
|
+
</head>
|
|
106
|
+
<body>
|
|
107
|
+
<div class="container">
|
|
108
|
+
<header>
|
|
109
|
+
<h1>Site Map</h1>
|
|
110
|
+
<p style="color: #64748b;">Total ${postList.length} posts, ${categoryList.length} categories</p>
|
|
111
|
+
</header>
|
|
112
|
+
|
|
113
|
+
${postList.length ? `
|
|
114
|
+
<div class="section">
|
|
115
|
+
<h2>Posts</h2>
|
|
116
|
+
<div class="grid">
|
|
117
|
+
${postList.map(item => `
|
|
118
|
+
<a href="${item.path}" class="card" ${nofollowAttr}>
|
|
119
|
+
<span class="card-title">${item.title}</span>
|
|
120
|
+
<span class="card-meta">Published: ${item.date}</span>
|
|
121
|
+
</a>
|
|
122
|
+
`).join('')}
|
|
123
|
+
</div>
|
|
124
|
+
</div>` : ''}
|
|
125
|
+
|
|
126
|
+
${categoryList.length ? `
|
|
127
|
+
<div class="section">
|
|
128
|
+
<h2>Categories</h2>
|
|
129
|
+
<div class="grid">
|
|
130
|
+
${categoryList.map(item => `
|
|
131
|
+
<a href="${item.path}" class="card" ${nofollowAttr}>
|
|
132
|
+
<span class="card-title">${item.name}</span>
|
|
133
|
+
<span class="card-meta">${item.count} articles</span>
|
|
134
|
+
</a>
|
|
135
|
+
`).join('')}
|
|
136
|
+
</div>
|
|
137
|
+
</div>` : ''}
|
|
138
|
+
|
|
139
|
+
${pageList.length ? `
|
|
140
|
+
<div class="section">
|
|
141
|
+
<h2>Pages</h2>
|
|
142
|
+
<div class="grid">
|
|
143
|
+
${pageList.map(item => `
|
|
144
|
+
<a href="${item.path}" class="card" ${nofollowAttr}>
|
|
145
|
+
<span class="card-title">${item.title}</span>
|
|
146
|
+
<span class="card-meta">Updated: ${item.date}</span>
|
|
147
|
+
</a>
|
|
148
|
+
`).join('')}
|
|
149
|
+
</div>
|
|
150
|
+
</div>` : ''}
|
|
151
|
+
</div>
|
|
152
|
+
</body>
|
|
153
|
+
</html>`;
|
|
154
|
+
|
|
155
|
+
const outputPath = path.join(hexo.public_dir, config.path);
|
|
156
|
+
|
|
157
|
+
if (force && await fs.exists(outputPath)) {
|
|
158
|
+
await fs.unlink(outputPath);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
await fs.writeFile(outputPath, htmlContent, 'utf8');
|
|
162
|
+
hexo.log.info(`[hexo-sitemap-html] Generated: ${config.path}`);
|
|
163
|
+
return outputPath;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 插件入口
|
|
167
|
+
module.exports = function(hexo) {
|
|
168
|
+
// 生成器:hexo g 时自动运行
|
|
169
|
+
hexo.extend.generator.register('html-sitemap', function(locals) {
|
|
170
|
+
return createHtmlSitemap(this);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// 独立命令:hexo sitemap-html 运行
|
|
174
|
+
hexo.extend.command.register('sitemap-html', {
|
|
175
|
+
desc: '独立生成 HTML 站点地图',
|
|
176
|
+
options: [
|
|
177
|
+
{ name: 'force', alias: 'f', desc: '强制覆盖已有文件', type: Boolean }
|
|
178
|
+
]
|
|
179
|
+
}, async function(args) {
|
|
180
|
+
try {
|
|
181
|
+
await createHtmlSitemap(this, args.f || args.force);
|
|
182
|
+
} catch (e) {
|
|
183
|
+
this.log.error(`[hexo-sitemap-html] Failed: ${e.message}`);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hexo-sitemap-html",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"hexo",
|
|
10
|
+
"hexo-plugin",
|
|
11
|
+
"hexo-sitemap",
|
|
12
|
+
"hexo-html-sitemap",
|
|
13
|
+
"sitemap",
|
|
14
|
+
"sitemap-html",
|
|
15
|
+
"html-sitemap"
|
|
16
|
+
],
|
|
17
|
+
"hexo": {
|
|
18
|
+
"version": ">=3.0.0"
|
|
19
|
+
},
|
|
20
|
+
"author": "2winter",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"description": "A Hexo plugin to generate customizable HTML format sitemap, support controlling categories/posts/pages generation, excluding specified pages and multiple layout styles.",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"lodash": "^4.17.21",
|
|
25
|
+
"hexo-fs": "^3.1.0"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"hexo": ">=3.0.0 <8.0.0"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=12.0.0"
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/2winter-dev/hexo-sitemap-html.git"
|
|
36
|
+
},
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/2winter-dev/hexo-sitemap-html/issues"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://github.com/2winter-dev/hexo-sitemap-html#readme"
|
|
41
|
+
}
|