zhangdocs 1.1.26 → 1.1.28
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/README.md +219 -23
- package/index.html +2 -2
- package/lib/build.js +30 -0
- package/package.json +2 -2
- package/theme/handbook/layout.ejs +70 -0
- package/theme/handbook/source/css/main.styl +50 -1
package/README.md
CHANGED
|
@@ -1,40 +1,236 @@
|
|
|
1
|
-
#
|
|
1
|
+
# zhangdocs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
一个简单易用的文档生成工具,可以将 Markdown 文件编译成美观的 HTML 静态文档网站。
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## ✨ 功能特性
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
- 📝 **Markdown 支持** - 完整的 Markdown 语法支持,包括 GFM(GitHub Flavored Markdown)
|
|
8
|
+
- 🎨 **代码高亮** - 基于 highlight.js 的代码语法高亮,支持多种编程语言
|
|
9
|
+
- 📊 **Mermaid 图表** - 支持流程图、类图、时序图等多种图表类型
|
|
10
|
+
- 🔢 **数学公式** - 支持 LaTeX 数学公式渲染(行内和块级)
|
|
11
|
+
- 📑 **自动目录** - 自动生成页面目录导航和全局导航菜单
|
|
12
|
+
- 🔄 **章节导航** - 支持上一节/下一节按钮和键盘快捷键(`Ctrl + ←/→`)
|
|
13
|
+
- 🏠 **目录首页** - 自动生成文档目录索引页面
|
|
14
|
+
- 🎯 **文件排序** - 支持按文件名前缀数字自动排序章节
|
|
15
|
+
- 🔒 **访问控制** - 支持 Token 验证保护文档内容
|
|
16
|
+
- 🖼️ **图片预览** - 集成 Viewer.js 支持图片点击预览
|
|
17
|
+
- 👀 **实时预览** - 支持文件监听和自动重新构建
|
|
18
|
+
- 🎨 **主题定制** - 支持自定义主题和样式
|
|
19
|
+
- 📱 **响应式设计** - 适配桌面和移动设备
|
|
20
|
+
|
|
21
|
+
## 📦 安装
|
|
22
|
+
|
|
23
|
+
### 全局安装
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g zhangdocs
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 本地安装
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install zhangdocs
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 🚀 快速开始
|
|
36
|
+
|
|
37
|
+
### 1. 初始化项目
|
|
38
|
+
|
|
39
|
+
在项目目录下运行:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
zhangdocs init
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
或者指定项目名称:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
zhangdocs init --Create my-docs
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
初始化过程会引导你配置项目信息,包括:
|
|
52
|
+
- 项目名称
|
|
53
|
+
- 版本号
|
|
54
|
+
- 描述
|
|
55
|
+
- 关键词
|
|
56
|
+
- 许可证
|
|
57
|
+
- 主题选择
|
|
58
|
+
|
|
59
|
+
### 2. 编写文档
|
|
60
|
+
|
|
61
|
+
在 `md/` 目录下创建 Markdown 文件,例如:
|
|
62
|
+
|
|
63
|
+
```markdown
|
|
64
|
+
# 第一章 介绍
|
|
65
|
+
|
|
66
|
+
这是第一章的内容。
|
|
67
|
+
|
|
68
|
+
## 1.1 概述
|
|
69
|
+
|
|
70
|
+
概述内容...
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**文件命名建议**:使用 `数字.标题.md` 格式(如 `1.介绍.md`),工具会自动按数字排序。
|
|
74
|
+
|
|
75
|
+
### 3. 构建文档
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
zhangdocs build
|
|
12
79
|
```
|
|
13
80
|
|
|
14
|
-
|
|
81
|
+
构建完成后,HTML 文件将生成在 `html/` 目录下,首页 `index.html` 会生成在项目根目录。
|
|
82
|
+
|
|
83
|
+
### 4. 启动开发服务器
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
zhangdocs server
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
这将启动一个本地服务器,并监听文件变化自动重新构建。
|
|
90
|
+
|
|
91
|
+
### 5. 监听文件变化
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
zhangdocs watch
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
监听 `md/` 目录下的文件变化,自动重新构建。
|
|
98
|
+
|
|
99
|
+
## 📖 命令说明
|
|
100
|
+
|
|
101
|
+
| 命令 | 说明 |
|
|
102
|
+
|------|------|
|
|
103
|
+
| `zhangdocs init` | 初始化项目 |
|
|
104
|
+
| `zhangdocs build` | 构建静态页面 |
|
|
105
|
+
| `zhangdocs watch` | 监听文件变化并自动构建 |
|
|
106
|
+
| `zhangdocs server` | 启动开发服务器(包含 watch 功能) |
|
|
107
|
+
| `zhangdocs clean` | 清理构建文件 |
|
|
108
|
+
| `zhangdocs deploy` | 部署文档 |
|
|
109
|
+
| `zhangdocs theme` | 主题管理 |
|
|
110
|
+
| `zhangdocs -V` | 查看版本号 |
|
|
111
|
+
|
|
112
|
+
## ⚙️ 配置说明
|
|
113
|
+
|
|
114
|
+
项目配置在 `package.json` 的 `zhangdocs` 字段中:
|
|
15
115
|
|
|
16
116
|
```json
|
|
17
117
|
{
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
118
|
+
"zhangdocs": {
|
|
119
|
+
"theme": "handbook",
|
|
120
|
+
"md": [
|
|
121
|
+
"README.md"
|
|
122
|
+
]
|
|
123
|
+
}
|
|
23
124
|
}
|
|
24
125
|
```
|
|
25
126
|
|
|
26
|
-
|
|
127
|
+
- `theme`: 使用的主题名称(位于 `theme/` 目录下)
|
|
128
|
+
- `md`: 文档入口文件列表(相对于 `md/` 目录)
|
|
27
129
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
130
|
+
## 📁 项目结构
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
项目根目录/
|
|
134
|
+
├── md/ # Markdown 源文件目录
|
|
135
|
+
│ ├── README.md
|
|
136
|
+
│ └── ...
|
|
137
|
+
├── html/ # 生成的 HTML 文件目录
|
|
138
|
+
│ └── ...
|
|
139
|
+
├── static/ # 静态资源目录(CSS、图片等)
|
|
140
|
+
│ ├── css/
|
|
141
|
+
│ └── img/
|
|
142
|
+
├── theme/ # 主题目录
|
|
143
|
+
│ └── handbook/
|
|
144
|
+
│ ├── layout.ejs # 布局模板
|
|
145
|
+
│ ├── header.ejs # 头部模板
|
|
146
|
+
│ ├── footer.ejs # 底部模板
|
|
147
|
+
│ └── source/ # 主题源文件
|
|
148
|
+
├── index.html # 生成的目录首页
|
|
149
|
+
└── package.json # 项目配置
|
|
32
150
|
```
|
|
33
151
|
|
|
34
|
-
##
|
|
152
|
+
## 🎯 主要功能
|
|
153
|
+
|
|
154
|
+
### 代码高亮
|
|
155
|
+
|
|
156
|
+
支持多种编程语言的代码高亮:
|
|
157
|
+
|
|
158
|
+
````markdown
|
|
159
|
+
```javascript
|
|
160
|
+
function hello() {
|
|
161
|
+
console.log("Hello, World!");
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
````
|
|
165
|
+
|
|
166
|
+
### Mermaid 图表
|
|
167
|
+
|
|
168
|
+
支持多种图表类型:
|
|
169
|
+
|
|
170
|
+
````markdown
|
|
171
|
+
```mermaid
|
|
172
|
+
graph TD
|
|
173
|
+
A[开始] --> B{判断}
|
|
174
|
+
B -->|是| C[执行]
|
|
175
|
+
B -->|否| D[结束]
|
|
176
|
+
```
|
|
177
|
+
````
|
|
178
|
+
|
|
179
|
+
### 数学公式
|
|
180
|
+
|
|
181
|
+
支持行内公式和块级公式:
|
|
182
|
+
|
|
183
|
+
```markdown
|
|
184
|
+
行内公式:$E = mc^2$
|
|
185
|
+
|
|
186
|
+
块级公式:
|
|
187
|
+
$$\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$$
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 章节导航
|
|
191
|
+
|
|
192
|
+
- 每个页面底部有"上一节"和"下一节"按钮
|
|
193
|
+
- 支持键盘快捷键:
|
|
194
|
+
- `Ctrl + ←`:上一节
|
|
195
|
+
- `Ctrl + →`:下一节
|
|
196
|
+
|
|
197
|
+
### 文件排序
|
|
198
|
+
|
|
199
|
+
工具会自动按文件名前缀的数字排序:
|
|
200
|
+
- `1.介绍.md` → `2.使用.md` → `3.API.md`
|
|
201
|
+
- 没有数字前缀的文件会排在有序号文件的后面
|
|
202
|
+
|
|
203
|
+
## 🔒 访问控制
|
|
204
|
+
|
|
205
|
+
文档支持 Token 验证功能,可以在模板中配置访问令牌验证逻辑,保护文档内容不被未授权访问。
|
|
206
|
+
|
|
207
|
+
## 🎨 主题定制
|
|
208
|
+
|
|
209
|
+
项目支持自定义主题,主题文件位于 `theme/` 目录下。你可以:
|
|
210
|
+
|
|
211
|
+
1. 修改现有主题的样式和模板
|
|
212
|
+
2. 创建新主题
|
|
213
|
+
3. 使用 `zhangdocs theme` 命令管理主题
|
|
214
|
+
|
|
215
|
+
## 📝 注意事项
|
|
216
|
+
|
|
217
|
+
1. **文件命名**:建议使用 `数字.标题.md` 格式,便于自动排序
|
|
218
|
+
2. **图片路径**:图片应放在 `static/img/` 目录下,在 Markdown 中使用相对路径引用
|
|
219
|
+
3. **数学公式**:使用 `$...$` 表示行内公式,`$$...$$` 表示块级公式
|
|
220
|
+
4. **Mermaid 图表**:在代码块中指定语言为 `mermaid`,工具会自动处理特殊字符转义
|
|
221
|
+
|
|
222
|
+
## 📄 许可证
|
|
223
|
+
|
|
224
|
+
MIT License
|
|
225
|
+
|
|
226
|
+
## 👤 作者
|
|
227
|
+
|
|
228
|
+
kenny wang <wowohoo@qq.com>
|
|
229
|
+
|
|
230
|
+
## 🔗 相关链接
|
|
35
231
|
|
|
36
|
-
|
|
232
|
+
- [GitHub 仓库](https://github.com/zhangrenyang/zhangdocs.git)
|
|
37
233
|
|
|
38
|
-
|
|
234
|
+
---
|
|
39
235
|
|
|
40
|
-
|
|
236
|
+
**Happy Documenting! 📚**
|
package/index.html
CHANGED
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
</div>
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
<div class="forkgithub"><a target="_blank" href="https://github.com/
|
|
74
|
+
<div class="forkgithub"><a target="_blank" href="https://github.com/zhangrenyang/zhangdocs.git">fork on github</a></div>
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
<section class="zhangdocs_nav_btn">
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
<p>这是一个块级公式:</p>
|
|
124
124
|
<p>$$\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$$</p>
|
|
125
125
|
|
|
126
|
-
<div class="copyright">Powered by <a href="https://github.com/
|
|
126
|
+
<div class="copyright">Powered by <a href="https://github.com/zhangrenyang/zhangdocs"
|
|
127
127
|
target="_blank">zhangdocs</a>. Dependence <a href="https://nodejs.org">Node.js</a> run.</div>
|
|
128
128
|
</div>
|
|
129
129
|
|
package/lib/build.js
CHANGED
|
@@ -149,6 +149,36 @@ function build(commander, changeFile) {
|
|
|
149
149
|
|
|
150
150
|
if (changeFile) pathArr = [changeFile];
|
|
151
151
|
|
|
152
|
+
// 按文件名前面的数字排序
|
|
153
|
+
// 如果文件名以数字开头(格式:数字.标题.md),按数字排序
|
|
154
|
+
// 如果文件名不以数字开头,排在有序号的后面
|
|
155
|
+
pathArr.sort(function(a, b) {
|
|
156
|
+
var aBasename = path.basename(a, '.md');
|
|
157
|
+
var bBasename = path.basename(b, '.md');
|
|
158
|
+
|
|
159
|
+
// 提取文件名开头的数字
|
|
160
|
+
var aMatch = aBasename.match(/^(\d+)/);
|
|
161
|
+
var bMatch = bBasename.match(/^(\d+)/);
|
|
162
|
+
|
|
163
|
+
var aNum = aMatch ? parseInt(aMatch[1], 10) : null;
|
|
164
|
+
var bNum = bMatch ? parseInt(bMatch[1], 10) : null;
|
|
165
|
+
|
|
166
|
+
// 如果两个都有数字,按数字排序
|
|
167
|
+
if (aNum !== null && bNum !== null) {
|
|
168
|
+
return aNum - bNum;
|
|
169
|
+
}
|
|
170
|
+
// 如果只有a有数字,a排在前面
|
|
171
|
+
if (aNum !== null && bNum === null) {
|
|
172
|
+
return -1;
|
|
173
|
+
}
|
|
174
|
+
// 如果只有b有数字,b排在前面
|
|
175
|
+
if (aNum === null && bNum !== null) {
|
|
176
|
+
return 1;
|
|
177
|
+
}
|
|
178
|
+
// 如果两个都没有数字,保持原顺序(或按文件名排序)
|
|
179
|
+
return aBasename.localeCompare(bBasename);
|
|
180
|
+
});
|
|
181
|
+
|
|
152
182
|
// 先处理所有md文件,包括第一个md文件
|
|
153
183
|
pathArr.forEach(function (item, idx) {
|
|
154
184
|
//菜单层级
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zhangdocs",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.28",
|
|
4
4
|
"description": "Simple document generation tool. Dependence Node.js run.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "https://github.com/
|
|
7
|
+
"url": "https://github.com/zhangrenyang/zhangdocs.git"
|
|
8
8
|
},
|
|
9
9
|
"main": "index.js",
|
|
10
10
|
"bin": {
|
|
@@ -52,6 +52,13 @@
|
|
|
52
52
|
</div>
|
|
53
53
|
</div>
|
|
54
54
|
|
|
55
|
+
<!-- 滚动到底部按钮 -->
|
|
56
|
+
<button class="scroll-to-bottom" id="scroll-to-bottom" aria-label="滚动到底部" title="滚动到底部">
|
|
57
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
58
|
+
<path d="M6 9l6 6 6-6"></path>
|
|
59
|
+
</svg>
|
|
60
|
+
</button>
|
|
61
|
+
|
|
55
62
|
<!-- Token输入弹窗 -->
|
|
56
63
|
<div id="token-modal"
|
|
57
64
|
style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 9999; display: none; justify-content: center; align-items: center;">
|
|
@@ -449,5 +456,68 @@ style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background:
|
|
|
449
456
|
}
|
|
450
457
|
});
|
|
451
458
|
})();
|
|
459
|
+
|
|
460
|
+
// 滚动到底部功能
|
|
461
|
+
(function() {
|
|
462
|
+
var scrollToBottomBtn = document.getElementById('scroll-to-bottom');
|
|
463
|
+
if (!scrollToBottomBtn) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// 检查是否在页面底部
|
|
468
|
+
function isAtBottom() {
|
|
469
|
+
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
470
|
+
var scrollHeight = document.documentElement.scrollHeight;
|
|
471
|
+
var clientHeight = document.documentElement.clientHeight;
|
|
472
|
+
// 允许5px的误差
|
|
473
|
+
return scrollHeight - scrollTop - clientHeight <= 5;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// 显示/隐藏按钮
|
|
477
|
+
function toggleButton() {
|
|
478
|
+
if (isAtBottom()) {
|
|
479
|
+
scrollToBottomBtn.classList.remove('show');
|
|
480
|
+
} else {
|
|
481
|
+
scrollToBottomBtn.classList.add('show');
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// 滚动到底部
|
|
486
|
+
function scrollToBottom() {
|
|
487
|
+
window.scrollTo({
|
|
488
|
+
top: document.documentElement.scrollHeight,
|
|
489
|
+
behavior: 'smooth'
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// 绑定点击事件
|
|
494
|
+
scrollToBottomBtn.addEventListener('click', function(e) {
|
|
495
|
+
e.preventDefault();
|
|
496
|
+
scrollToBottom();
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
// 监听滚动事件
|
|
500
|
+
var scrollTimer = null;
|
|
501
|
+
window.addEventListener('scroll', function() {
|
|
502
|
+
// 使用节流,减少频繁检查
|
|
503
|
+
if (scrollTimer) {
|
|
504
|
+
clearTimeout(scrollTimer);
|
|
505
|
+
}
|
|
506
|
+
scrollTimer = setTimeout(toggleButton, 100);
|
|
507
|
+
}, { passive: true });
|
|
508
|
+
|
|
509
|
+
// 初始检查
|
|
510
|
+
setTimeout(toggleButton, 500);
|
|
511
|
+
|
|
512
|
+
// 监听内容变化(处理动态加载的内容)
|
|
513
|
+
var observer = new MutationObserver(function() {
|
|
514
|
+
setTimeout(toggleButton, 100);
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
observer.observe(document.body, {
|
|
518
|
+
childList: true,
|
|
519
|
+
subtree: true
|
|
520
|
+
});
|
|
521
|
+
})();
|
|
452
522
|
</script>
|
|
453
523
|
<% include footer.ejs %>
|
|
@@ -512,4 +512,53 @@ table
|
|
|
512
512
|
|
|
513
513
|
.nav-button
|
|
514
514
|
max-width: 100%
|
|
515
|
-
width: 100%
|
|
515
|
+
width: 100%
|
|
516
|
+
|
|
517
|
+
// 滚动到底部按钮
|
|
518
|
+
.scroll-to-bottom
|
|
519
|
+
position: fixed
|
|
520
|
+
bottom: 30px
|
|
521
|
+
right: 30px
|
|
522
|
+
width: 48px
|
|
523
|
+
height: 48px
|
|
524
|
+
background: #fff
|
|
525
|
+
border: 1px solid $border-color
|
|
526
|
+
border-radius: 50%
|
|
527
|
+
cursor: pointer
|
|
528
|
+
z-index: 999
|
|
529
|
+
display: none
|
|
530
|
+
align-items: center
|
|
531
|
+
justify-content: center
|
|
532
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15)
|
|
533
|
+
transition: all 0.3s ease
|
|
534
|
+
color: $text-color
|
|
535
|
+
padding: 0
|
|
536
|
+
-webkit-tap-highlight-color: transparent
|
|
537
|
+
|
|
538
|
+
&:hover
|
|
539
|
+
background: $primary-color
|
|
540
|
+
border-color: $primary-color
|
|
541
|
+
color: #fff
|
|
542
|
+
transform: translateY(-3px)
|
|
543
|
+
box-shadow: 0 4px 12px rgba(74, 144, 226, 0.4)
|
|
544
|
+
|
|
545
|
+
&:active
|
|
546
|
+
transform: translateY(-1px)
|
|
547
|
+
box-shadow: 0 2px 6px rgba(74, 144, 226, 0.3)
|
|
548
|
+
|
|
549
|
+
svg
|
|
550
|
+
width: 20px
|
|
551
|
+
height: 20px
|
|
552
|
+
|
|
553
|
+
&.show
|
|
554
|
+
display: flex
|
|
555
|
+
|
|
556
|
+
@media mq-mobile
|
|
557
|
+
bottom: 20px
|
|
558
|
+
right: 20px
|
|
559
|
+
width: 44px
|
|
560
|
+
height: 44px
|
|
561
|
+
|
|
562
|
+
svg
|
|
563
|
+
width: 18px
|
|
564
|
+
height: 18px
|