xfmpress 0.0.0-stage → 0.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/INSTALL.md +290 -0
- package/LICENSE +21 -0
- package/README.md +184 -2
- package/bin/xfm.js +273 -0
- package/lib/cli/scaffold.js +176 -0
- package/lib/engine/config.js +106 -0
- package/lib/engine/frontmatter.js +132 -0
- package/lib/engine/markdown.js +732 -0
- package/lib/engine/plugins.js +132 -0
- package/lib/engine/render.js +144 -0
- package/lib/engine/server.js +333 -0
- package/lib/engine/site.js +702 -0
- package/lib/engine/template.js +450 -0
- package/lib/engine/theme.js +132 -0
- package/lib/engine/worker.js +79 -0
- package/lib/index.js +56 -0
- package/lib/plugins/reading-stats.js +80 -0
- package/lib/plugins/rss.js +59 -0
- package/lib/plugins/sitemap.js +43 -0
- package/package.json +48 -4
- package/themes/default/assets/style.css +235 -0
- package/themes/default/layouts/base.html +47 -0
- package/themes/default/layouts/index.html +29 -0
- package/themes/default/layouts/page.html +10 -0
- package/themes/default/layouts/post.html +28 -0
- package/themes/default/layouts/taxonomy.html +16 -0
- package/themes/default/partials/post-list.html +7 -0
- package/themes/default/partials/toc.html +9 -0
- package/themes/docs/assets/style.css +252 -0
- package/themes/docs/layouts/base.html +36 -0
- package/themes/docs/layouts/index.html +13 -0
- package/themes/docs/layouts/page.html +10 -0
- package/themes/docs/layouts/post.html +28 -0
- package/themes/docs/layouts/taxonomy.html +16 -0
- package/themes/docs/partials/post-list.html +7 -0
- package/themes/docs/partials/toc.html +9 -0
package/INSTALL.md
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# xfm 安装与使用说明
|
|
2
|
+
|
|
3
|
+
> 面向 Node 22 环境,从零到跑起来大约 1 分钟。
|
|
4
|
+
> 项目地址:`https://github.com/xfm0797/xfm`
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 一、先决条件
|
|
9
|
+
|
|
10
|
+
| 项目 | 要求 | 检查命令 |
|
|
11
|
+
| --- | --- | --- |
|
|
12
|
+
| Node.js | **18 或更高**(推荐 22 LTS) | `node -v` |
|
|
13
|
+
| npm | 随 Node 附带(推荐 ≥ 9) | `npm -v` |
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
node -v # 期望 v22.x
|
|
17
|
+
npm -v # 期望 10.x 或 11.x
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Node 版本过旧会报 `EBADENGINE`,用 [nvm](https://github.com/nvm-sh/nvm) 或 [fnm](https://github.com/Schniz/fnm) 切到 22 即可:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
nvm install 22 && nvm use 22
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
xfm 是**零运行时依赖**的,安装时不会拉取任何第三方包,也因此不会出现依赖树冲突、`npm audit` 报警。
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 二、安装(三种方式,按需选一种)
|
|
31
|
+
|
|
32
|
+
### 方式 A:全局安装 —— 和 Hexo 一样用 `xfm` 命令
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g xfmpress
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
验证:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
xfm --help
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
看到 `⚡ xfm v0.1.0` 的版本横幅即安装成功。
|
|
45
|
+
|
|
46
|
+
> **命名说明**:npm 包名是 **`xfmpress`**,命令是 **`xfm`**(`npm i -g xfmpress` 之后用 `xfm` 调用)。定位是 Static Site Generator(静态站点生成器),与同系列的 `hexo-theme-xfm` 共用品牌。项目早期叫 `bolt`,`bolt`/`bolt-ssg` 已被占用,`xmssg` 与 `xfm` 又分别被 npm 的"名字过于相似"校验拦下(撞 `xss`、以及 `xo`/`xml`/`htm` 等一批短包名),0.1.0 起定为 `xfmpress`。
|
|
47
|
+
|
|
48
|
+
**权限报错怎么办**(`EACCES: permission denied`)?有两种正规解法,不要用 `sudo npm i -g`:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# 解法 1(推荐):把全局前缀改到用户目录
|
|
52
|
+
npm config set prefix ~/.npm-global
|
|
53
|
+
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc # bash 用户改成 ~/.bashrc
|
|
54
|
+
source ~/.zshrc
|
|
55
|
+
|
|
56
|
+
# 解法 2:用 nvm 管理 Node(全局包天然在用户目录,无需额外配置)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 方式 B:免安装运行 —— 只想先试试
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx xfmpress --help
|
|
63
|
+
npx xfmpress create my-blog --template=blog
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`npx` 会自动下载到临时缓存并执行,不在系统里留下全局命令。适合快速体验或 CI 里一次性构建。
|
|
67
|
+
|
|
68
|
+
### 方式 C:项目内安装 —— 团队协作推荐
|
|
69
|
+
|
|
70
|
+
把 xfm 作为开发依赖写进项目,任何人 `npm install` 后即可获得**完全一致**的版本:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
mkdir my-blog && cd my-blog
|
|
74
|
+
npm init -y
|
|
75
|
+
npm i -D xfm
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
然后在 `package.json` 里加脚本:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"scripts": {
|
|
83
|
+
"dev": "xfm dev",
|
|
84
|
+
"build": "xfm build",
|
|
85
|
+
"new": "xfm new",
|
|
86
|
+
"clean": "xfm clean"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
之后用 `npm run dev` / `npm run build` 即可;临时调用可用 `npx xfmpress info`。
|
|
92
|
+
|
|
93
|
+
> 方式 C 的缺点是不能在空目录里用 `xfm create` 生成脚手架(那时还没有 `node_modules`)。建议先用方式 A 或 B 生成站点,再进目录装成本地依赖。
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 三、快速上手
|
|
98
|
+
|
|
99
|
+
### 1. 创建站点
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
xfm create my-blog --template=blog
|
|
103
|
+
cd my-blog
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
可选模板:
|
|
107
|
+
|
|
108
|
+
| `--template` | 外观 | 适合 |
|
|
109
|
+
| --- | --- | --- |
|
|
110
|
+
| `blog`(默认) | 博客:首页列表 + 文章页 + 右侧目录 | 个人博客、技术随笔 |
|
|
111
|
+
| `docs` | 文档:左侧分组侧栏 + 正文 | 产品文档、知识库 |
|
|
112
|
+
|
|
113
|
+
也能指定站名:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
xfm create my-blog --template=docs --title="我的知识库"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
生成的结构:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
my-blog/
|
|
123
|
+
├── xfm.config.mjs # 站点配置(有合理默认值,可按需改)
|
|
124
|
+
├── content/ # 所有 Markdown 源文件
|
|
125
|
+
│ ├── index.md
|
|
126
|
+
│ ├── about.md
|
|
127
|
+
│ └── posts/
|
|
128
|
+
│ └── hello-world.md
|
|
129
|
+
├── plugins/ # 你自己的插件
|
|
130
|
+
├── public/ # 原样拷贝到产物根目录的静态文件
|
|
131
|
+
└── README.md
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 2. 本地开发
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
xfm dev
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
打开 `http://127.0.0.1:4000/`。改 `content/` 里的 Markdown 或 `themes/` 里的模板,保存后浏览器**自动刷新**(SSE 推送,无需装浏览器插件)。
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
xfm dev --port=5000 # 换端口
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 3. 写文章
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
xfm new "我的第一篇文章"
|
|
150
|
+
# ✓ 已创建 content/posts/我的第一篇文章.md (文件名由标题自动转为 slug)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
带空格或多语言的标题会自动处理文件名:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
xfm new "Hello, World!" # → content/posts/hello-world.md
|
|
157
|
+
xfm new "部署笔记" --slug=deploy-notes # → 手动指定文件名
|
|
158
|
+
xfm new "关于" --dir=pages # → 放到 content/pages/ 下
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
> **注意**:`xfm new` 生成的文章**默认可发布**,`xfm build` 立刻就能看到。想先写半成品,用 `xfm new --draft`(会写入 `draft: true`),这类文章不会出现在生产构建里;要发布时把 `draft` 改成 `false` 或删掉该行即可。
|
|
162
|
+
|
|
163
|
+
### 4. 生产构建
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
xfm build
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
产物在 `dist/`,纯静态,扔到 Nginx / 对象存储 / Vercel / Netlify / GitHub Pages 都能跑。
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
✓ 页面 5 个
|
|
173
|
+
✓ 附加产物 4 个(sitemap / rss 等)
|
|
174
|
+
✓ 输出目录 dist
|
|
175
|
+
耗时 30 ms
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
重构建会走增量缓存,只重新渲染改动过的页面:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
xfm build --dev # 开发模式下也启用增量缓存
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 5. 其他命令
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
xfm info # 查看当前站点解析后的配置(主题、内容目录、插件、Node 版本)
|
|
188
|
+
xfm clean # 清空 dist/ 与增量缓存
|
|
189
|
+
xfm --help # 全部命令与选项
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 四、写 Markdown
|
|
195
|
+
|
|
196
|
+
内容就是标准 Markdown,没有私有语法。常用增强:
|
|
197
|
+
|
|
198
|
+
````markdown
|
|
199
|
+
---
|
|
200
|
+
title: 文章标题
|
|
201
|
+
date: 2024-06-01
|
|
202
|
+
tags: [性能, Node]
|
|
203
|
+
description: 用于 SEO 与列表摘要
|
|
204
|
+
layout: post.html
|
|
205
|
+
draft: false
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## 二级标题会自动进右侧目录
|
|
209
|
+
|
|
210
|
+
普通段落支持 **加粗**、*斜体*、`行内代码`、~~删除线~~、[链接](/about/)。
|
|
211
|
+
|
|
212
|
+
| 语法 | 说明 |
|
|
213
|
+
| --- | --- |
|
|
214
|
+
| 表格 | 标准 GFM |
|
|
215
|
+
|
|
216
|
+
- [x] 任务列表已支持
|
|
217
|
+
- [ ] 未完成项
|
|
218
|
+
|
|
219
|
+
::: tip 提示容器
|
|
220
|
+
支持 `tip` / `info` / `warning` / `danger` 四种。
|
|
221
|
+
:::
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
const ok = true; // 代码块自动语法高亮
|
|
225
|
+
```
|
|
226
|
+
````
|
|
227
|
+
|
|
228
|
+
代码高亮支持:`js / javascript / jsx / ts / tsx / java / c / cpp / csharp / go / rust / swift / kotlin / scala / php / python / bash / sh / json / yaml / html / xml / svg / vue / css / scss / markdown`,大小写与常见别名都能识别;未知语言降级为纯文本,不会报错。围栏可加标题:`` ```js app.js ``。
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 五、配置
|
|
233
|
+
|
|
234
|
+
`xfm.config.mjs` 是一个普通 ESM 模块,导出对象即可,改动后 dev 服务器会自动重启:
|
|
235
|
+
|
|
236
|
+
```js
|
|
237
|
+
export default {
|
|
238
|
+
title: '我的博客',
|
|
239
|
+
description: '记录技术与生活',
|
|
240
|
+
url: 'https://example.com', // 用于 sitemap / rss 的绝对链接
|
|
241
|
+
theme: 'default', // 内置主题:default | docs;也可填本地路径
|
|
242
|
+
contentDir: 'content',
|
|
243
|
+
outputDir: 'dist',
|
|
244
|
+
plugins: [
|
|
245
|
+
'sitemap',
|
|
246
|
+
'rss',
|
|
247
|
+
'./plugins/my-plugin.js', // 本地插件
|
|
248
|
+
],
|
|
249
|
+
workers: 0, // 0 = 自动;渲染进程数
|
|
250
|
+
};
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
所有字段都有默认值,最小配置就是一个空对象。完整字段见 README。
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## 六、常见问题
|
|
258
|
+
|
|
259
|
+
**`xfm: command not found`**
|
|
260
|
+
全局 npm 的 `bin` 目录不在 `PATH` 里。执行 `npm bin -g`(旧版)或 `npm config get prefix`,把其下的 `bin` 加进 `PATH`。用 nvm 的话重开一个终端通常就能解决。
|
|
261
|
+
|
|
262
|
+
**安装时报 `EACCES: permission denied`**
|
|
263
|
+
见「方式 A」里的全局前缀改法,不要用 `sudo`。
|
|
264
|
+
|
|
265
|
+
**`node -v` 低于 18**
|
|
266
|
+
升级 Node 后重装:`npm i -g xfmpress --force`。
|
|
267
|
+
|
|
268
|
+
**`xfm new` 建了文章但页面上没有**
|
|
269
|
+
大概率是 `draft: true`。改成 `false` 后重新 `xfm build`。
|
|
270
|
+
|
|
271
|
+
**Windows 下 `xfm` 提示不是内部或外部命令**
|
|
272
|
+
用 Git Bash 或 PowerShell 重开终端;仍不行则检查 `%APPDATA%\npm` 是否在 `Path` 中。
|
|
273
|
+
|
|
274
|
+
**想升级**
|
|
275
|
+
```bash
|
|
276
|
+
npm i -g xfmpress@latest # 全局
|
|
277
|
+
npm i -D xfm@latest # 项目内
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## 七、一键脚本(复制即用)
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
# 全局安装 + 创建博客 + 本地预览
|
|
286
|
+
npm i -g xfmpress \
|
|
287
|
+
&& xfm create my-blog --template=blog \
|
|
288
|
+
&& cd my-blog \
|
|
289
|
+
&& xfm dev
|
|
290
|
+
```
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 xfm contributors
|
|
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
CHANGED
|
@@ -1,3 +1,185 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ⚡ xfm
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**A zero-dependency static site generator for Node.js.** 极致性能的静态站点生成器 —— 零运行时依赖、多线程渲染、Nunjucks 风格模板、即插即用的主题与插件。
|
|
4
|
+
|
|
5
|
+
## 安装与上手
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i -g xfmpress # 全局安装(Node ≥ 18),装完命令是 xfm
|
|
9
|
+
xfm create my-blog # 30 秒创建站点
|
|
10
|
+
cd my-blog && xfm dev # 毫秒级热更新
|
|
11
|
+
xfm build # 生产构建
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
> **包名 `xfmpress`,命令 `xfm`**(`npm i -g xfmpress` → 用 `xfm` 调用)。定位是 **Static Site Generator(静态站点生成器)**:把 Markdown 压成纯静态 HTML。
|
|
15
|
+
> 与同系列的 [hexo-theme-xfm](https://github.com/xfm0797/hexo-theme-xfm) 共用 `xfm` 品牌。
|
|
16
|
+
> 完整的三种安装方式、权限排错与 FAQ 见 **[INSTALL.md](./INSTALL.md)**。
|
|
17
|
+
|
|
18
|
+
## 性能
|
|
19
|
+
|
|
20
|
+
压测环境:32 核 Node 22,1000 篇中文文档(约 5MB HTML 产出)。运行 `npm run bench` 可复现。
|
|
21
|
+
|
|
22
|
+
| 指标 | 数值 |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| 全量冷构建 | **≈0.38–0.42 s**(≈2400–2700 页/秒) |
|
|
25
|
+
| 增量缓存命中后渲染阶段 | **1 ms**(1001 页) |
|
|
26
|
+
| dev 热更新单页重建 | **2–7 ms** |
|
|
27
|
+
| 产物运行时 | 纯静态 HTML + CSS,**零 JavaScript 依赖** |
|
|
28
|
+
|
|
29
|
+
分阶段耗时(1000 页):
|
|
30
|
+
|
|
31
|
+
| 阶段 | 耗时 | 优化手段 |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| 扫描与解析 | ~128 ms | 目录并行遍历 + 源文件并行读取,raw 只读一次 |
|
|
34
|
+
| 哈希 | ~9 ms | 复用已读入的源文本,无二次 IO |
|
|
35
|
+
| 渲染 | ~91 ms | worker 池复用线程,上下文只传一次 |
|
|
36
|
+
| 写盘 | ~132 ms | 同目录只 mkdir 一次,两阶段并行写 |
|
|
37
|
+
|
|
38
|
+
性能来自四层设计:
|
|
39
|
+
|
|
40
|
+
1. **线性扫描的 Markdown 引擎**:块级逐行推进 + 一次性行内正则,不构造 AST;内置中英文锚点、表格、任务列表(含续行与嵌套)、代码高亮、`::: callout` 容器。
|
|
41
|
+
2. **模板编译成函数**:Nunjucks 风格语法在构建期编译为 JS 函数,渲染只做字符串拼接,未定义变量安全返回 undefined。
|
|
42
|
+
3. **worker 池**:线程与模板编译缓存全程复用,站点上下文只序列化一次;并发度按"每线程最少工作量"标定(实测 2–4 个最优,堆到 8 个反而更慢)。
|
|
43
|
+
4. **增量构建**:`源文件哈希 + 主题指纹` 判定,未变页面直接复用缓存 HTML。
|
|
44
|
+
|
|
45
|
+
> 并发度不是越多越好:worker 的启动与上下文克隆成本约 30–60 ms/个,
|
|
46
|
+
> 在小任务量下会吃掉并行收益。`pickConcurrency()` 依据实测数据标定,而非按 CPU 核数堆线程。
|
|
47
|
+
|
|
48
|
+
## 特性
|
|
49
|
+
|
|
50
|
+
- **主题**:`{% extend %}` / `{% block %}` 模板继承、`{% include %}` 片段、CSS 变量深浅色主题;内置 `default`(博客)与 `docs`(侧栏文档)两套主题。
|
|
51
|
+
- **插件**:五个钩子(`extendContext` / `markdown` / `transformHtml` / `afterBuild` / `configureServer`),放进 `plugins/` 目录自动加载;内置 sitemap、RSS、阅读统计三个插件。
|
|
52
|
+
- **内容**:YAML front-matter、草稿、标签/分类/系列聚合、自动 prev/next、按 weight 排序、`.md` 相对链接自动解析。
|
|
53
|
+
- **开发体验**:`xfm dev` 内存构建 + SSE 热更新(保持滚动位置)、CSS 单独热替换、404 页列出可用路由。
|
|
54
|
+
- **易迁移**:模板语法兼容 Nunjucks/Liquid 习惯,配置文件支持 `.mjs/.js/.json`。
|
|
55
|
+
|
|
56
|
+
## 安装
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm i -g xfmpress # 全局安装,然后直接使用 xfm 命令(Node ≥ 18)
|
|
60
|
+
# 或免安装试用:npx xfmpress --help
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
> 包名是 `xfmpress`,命令是 `xfm`,装一次即可全局使用。
|
|
64
|
+
> 完整的安装、权限排错与三种安装方式见 **[INSTALL.md](./INSTALL.md)**。
|
|
65
|
+
|
|
66
|
+
## 命令
|
|
67
|
+
|
|
68
|
+
| 命令 | 说明 |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| `xfm create [目录]` | 创建站点(`--template=blog\|docs`,`--title=`) |
|
|
71
|
+
| `xfm dev [目录]` | 开发服务器(`--port=`) |
|
|
72
|
+
| `xfm build [目录]` | 生产构建(`--dev` 启用增量缓存) |
|
|
73
|
+
| `xfm new "标题"` | 新建文章(`--dir=posts --slug=xxx`) |
|
|
74
|
+
| `xfm clean` / `xfm info` | 清理产物 / 查看配置 |
|
|
75
|
+
|
|
76
|
+
## 配置示例(xfm.config.mjs)
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
export default {
|
|
80
|
+
site: {
|
|
81
|
+
title: 'XFM Notes',
|
|
82
|
+
description: '关于静态站点与前端的笔记',
|
|
83
|
+
lang: 'zh-CN',
|
|
84
|
+
base: '/',
|
|
85
|
+
url: 'https://example.com', // 供 sitemap/RSS 使用
|
|
86
|
+
nav: [{ title: '文章', url: '/' }],
|
|
87
|
+
},
|
|
88
|
+
theme: 'default', // 主题名或路径
|
|
89
|
+
plugins: ['sitemap', 'rss'], // 内置插件,也可写路径
|
|
90
|
+
defaults: { layout: 'post.html' },
|
|
91
|
+
workers: 0, // worker 并发数;0=自动按任务量标定
|
|
92
|
+
server: { port: 4321 },
|
|
93
|
+
};
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 写作(content/ 目录)
|
|
97
|
+
|
|
98
|
+
```markdown
|
|
99
|
+
---
|
|
100
|
+
title: 文章标题
|
|
101
|
+
date: 2026-10-28 09:00:00
|
|
102
|
+
tags: [Node.js, 性能]
|
|
103
|
+
description: 摘要(列表页与 RSS 使用)
|
|
104
|
+
draft: false
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
正文支持 GFM 全部常用语法,另加:
|
|
108
|
+
|
|
109
|
+
::: tip 提示容器
|
|
110
|
+
带标题的高亮提示框。
|
|
111
|
+
:::
|
|
112
|
+
|
|
113
|
+
\`\`\`js
|
|
114
|
+
const ok = true; // 内置语法高亮
|
|
115
|
+
\`\`\`
|
|
116
|
+
|
|
117
|
+
代码围栏语言标记(含别名归一,大小写不敏感):`js / javascript / jsx / ts / tsx / java / c / cpp / csharp / go / golang / rust / rs / swift / kotlin / scala / php / python / py / bash / sh / shell / json / yaml / yml / html / xml / svg / vue / css / scss / markdown / md / text`。未知语言降级为纯转义文本,不会报错。
|
|
118
|
+
|
|
119
|
+
围栏首行可附加标题:\`\`\`js app.js(元信息如 `{1,3-5}` 会被忽略)。
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`group: 使用指南` + `weight: 1` 字段可在 docs 主题生成侧栏导航。
|
|
123
|
+
|
|
124
|
+
## 钩子语义
|
|
125
|
+
|
|
126
|
+
| 钩子 | 参数 | 返回值处理 |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| `extendContext(ctx)` | 站点上下文 | 替换上下文(返回值写入 `site.*`) |
|
|
129
|
+
| `markdown(src, page)` | 当前源码 | 替换源码 |
|
|
130
|
+
| `transformHtml(html, ctx)` | 当前 HTML | 替换 HTML |
|
|
131
|
+
| `afterBuild(site)` | 站点实例(`site.documents[].html` 为**正文** HTML,不含布局) | 返回的 `[{path, contents}]` 被汇总写出 |
|
|
132
|
+
| `configureServer(server)` / `finish(site)` | 站点/服务器 | 忽略 |
|
|
133
|
+
|
|
134
|
+
## 插件示例
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
// plugins/search-index.js —— 放进 plugins/ 目录即生效
|
|
138
|
+
module.exports = () => ({
|
|
139
|
+
name: 'search-index',
|
|
140
|
+
afterBuild(site) {
|
|
141
|
+
const index = site.documents.map(d => ({
|
|
142
|
+
title: d.title, url: d.url,
|
|
143
|
+
text: d.html.replace(/<[^>]+>/g, ' ').slice(0, 800),
|
|
144
|
+
}));
|
|
145
|
+
return [{ path: 'search.json', contents: JSON.stringify(index) }];
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 主题结构
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
themes/my-theme/
|
|
154
|
+
├── layouts/ # base.html(骨架)、index/post/page.html(继承 base)
|
|
155
|
+
├── partials/ # 可复用片段(toc、卡片等)
|
|
156
|
+
└── assets/ # style.css 等,构建时复制到站点 /assets/
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
模板上下文:`site.*`(站点配置与聚合数据)、`page.*`(当前页元数据)、`content`(正文 HTML)、`headings`(目录)。
|
|
160
|
+
|
|
161
|
+
## 目录
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
xfm/
|
|
165
|
+
├── bin/xfm.js # CLI(build/dev/new/create/clean/info)
|
|
166
|
+
├── lib/engine/ # markdown / template / render / frontmatter / theme / plugins / site / worker / server / config
|
|
167
|
+
├── lib/plugins/ # 内置插件(sitemap / rss / reading-stats)
|
|
168
|
+
├── lib/cli/scaffold.js # create 脚手架
|
|
169
|
+
├── themes/default/ # 博客主题(深浅色)
|
|
170
|
+
├── themes/docs/ # 文档主题(侧栏导航)
|
|
171
|
+
├── examples/blog/ # 可构建的示例站点
|
|
172
|
+
├── bench/bench.js # 基准测试(分阶段耗时)
|
|
173
|
+
└── test/run.js # 72 项测试(零依赖)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## 本地开发
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
npm run test # 72 项测试
|
|
180
|
+
npm run bench # 1000 页基准(分阶段耗时)
|
|
181
|
+
npm run build:example # 构建示例站点
|
|
182
|
+
npm run dev # 开发示例站点
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
MIT License
|