xfmpress 0.0.0-stage → 0.1.1

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/INSTALL.md +298 -0
  3. package/INSTALL_CN.md +298 -0
  4. package/LICENSE +21 -0
  5. package/README.md +188 -2
  6. package/README_CN.md +187 -0
  7. package/bin/xfm.js +273 -0
  8. package/lib/cli/scaffold.js +176 -0
  9. package/lib/engine/config.js +106 -0
  10. package/lib/engine/frontmatter.js +132 -0
  11. package/lib/engine/markdown.js +732 -0
  12. package/lib/engine/plugins.js +132 -0
  13. package/lib/engine/render.js +144 -0
  14. package/lib/engine/server.js +333 -0
  15. package/lib/engine/site.js +702 -0
  16. package/lib/engine/template.js +450 -0
  17. package/lib/engine/theme.js +132 -0
  18. package/lib/engine/worker.js +79 -0
  19. package/lib/index.js +56 -0
  20. package/lib/plugins/reading-stats.js +80 -0
  21. package/lib/plugins/rss.js +59 -0
  22. package/lib/plugins/sitemap.js +43 -0
  23. package/package.json +51 -4
  24. package/themes/default/assets/style.css +235 -0
  25. package/themes/default/layouts/base.html +47 -0
  26. package/themes/default/layouts/index.html +29 -0
  27. package/themes/default/layouts/page.html +10 -0
  28. package/themes/default/layouts/post.html +28 -0
  29. package/themes/default/layouts/taxonomy.html +16 -0
  30. package/themes/default/partials/post-list.html +7 -0
  31. package/themes/default/partials/toc.html +9 -0
  32. package/themes/docs/assets/style.css +252 -0
  33. package/themes/docs/layouts/base.html +36 -0
  34. package/themes/docs/layouts/index.html +13 -0
  35. package/themes/docs/layouts/page.html +10 -0
  36. package/themes/docs/layouts/post.html +28 -0
  37. package/themes/docs/layouts/taxonomy.html +16 -0
  38. package/themes/docs/partials/post-list.html +7 -0
  39. package/themes/docs/partials/toc.html +9 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,42 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
5
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.1.1] - 2026-11-03
8
+
9
+ ### Changed
10
+
11
+ - English `README.md` is now the default document shown on the npm page;
12
+ the Chinese version ships as `README_CN.md`, and both link to each other.
13
+ - Documentation split into English/Chinese pairs: `README` / `README_CN`,
14
+ `INSTALL` / `INSTALL_CN`, `PROGRAM` / `PROGRAM_CN`.
15
+ - Dev server port corrected to `4173` in all docs and scaffolds
16
+ (previously documented inconsistently as `4000` / `4321`).
17
+ - Package description rewritten in English to match the npm-facing README.
18
+
19
+ ### Fixed
20
+
21
+ - Docs referenced the wrong install target (`npm i -D xfm`); the installable
22
+ package is `xfmpress` while the CLI command remains `xfm`.
23
+ - Configuration examples now consistently use the `site: {}` shape with
24
+ a top-level `outDir`.
25
+
26
+ ## [0.1.0] - 2026-11-02
27
+
28
+ ### Added
29
+
30
+ - Initial release: zero-dependency static site generator with a shared
31
+ render pipeline used by both the main thread and worker threads.
32
+ - Multi-threaded page rendering with content-hashed incremental builds.
33
+ - Nunjucks-style template engine compiled to JavaScript functions at build
34
+ time, with optional-chaining guards generated at compile time.
35
+ - Plugin system with `markdown`, `transformHtml`, `extendContext`,
36
+ `afterBuild`, `configureServer` and `finish` hooks.
37
+ - Built-in `default` and `docs` themes, plus `xfm create` scaffolding.
38
+ - Dev server with SSE live reload and configuration hot reload.
39
+ - `xfm new`, `xfm build`, `xfm dev`, `xfm clean` commands.
40
+
41
+ [0.1.1]: https://github.com/xfm0797/xfm/compare/v0.1.0...v0.1.1
42
+ [0.1.0]: https://github.com/xfm0797/xfm/releases/tag/v0.1.0
package/INSTALL.md ADDED
@@ -0,0 +1,298 @@
1
+ # xfm — Installation & Usage
2
+
3
+ > Assumes a Node 22 environment. From zero to a running site takes about a minute.
4
+ > Repository: `https://github.com/xfm0797/xfm`
5
+
6
+ [English](./INSTALL.md) | [简体中文](./INSTALL_CN.md)
7
+
8
+ ---
9
+
10
+ ## 1. Prerequisites
11
+
12
+ | Item | Requirement | Check |
13
+ | --- | --- | --- |
14
+ | Node.js | **18 or newer** (22 LTS recommended) | `node -v` |
15
+ | npm | Ships with Node (>= 9 recommended) | `npm -v` |
16
+
17
+ ```bash
18
+ node -v # expect v22.x
19
+ npm -v # expect 10.x or 11.x
20
+ ```
21
+
22
+ An outdated Node version triggers `EBADENGINE`. Switch to 22 with [nvm](https://github.com/nvm-sh/nvm) or [fnm](https://github.com/Schniz/fnm):
23
+
24
+ ```bash
25
+ nvm install 22 && nvm use 22
26
+ ```
27
+
28
+ xfm has **zero runtime dependencies**, so installing it pulls no third-party packages — which also means no dependency-tree conflicts and no `npm audit` warnings.
29
+
30
+ ---
31
+
32
+ ## 2. Install (pick one of three methods)
33
+
34
+ ### Option A: Global install — use `xfm` like you use `hexo`
35
+
36
+ ```bash
37
+ npm install -g xfmpress
38
+ ```
39
+
40
+ Verify:
41
+
42
+ ```bash
43
+ xfm --help
44
+ ```
45
+
46
+ If you see the `⚡ xfm v0.1.0` banner, you are good to go.
47
+
48
+ > **About the name**: the npm package is **`xfmpress`**, the command is **`xfm`** (`npm i -g xfmpress`, then call `xfm`). It is a Static Site Generator, sharing the `xfm` brand with the `hexo-theme-xfm` family. The project was originally called `bolt`; `bolt`/`bolt-ssg` were taken, and `xmssg` and `xfm` were both rejected by npm's "too similar to an existing package" check (against `xss`, then against `xo`/`xml`/`htm` and friends), so `xfmpress` has been the name since 0.1.0.
49
+
50
+ **Hit `EACCES: permission denied`?** There are two proper fixes; do not use `sudo npm i -g`:
51
+
52
+ ```bash
53
+ # Fix 1 (recommended): move the global prefix into your home directory
54
+ npm config set prefix ~/.npm-global
55
+ echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc # use ~/.bashrc for bash
56
+ source ~/.zshrc
57
+
58
+ # Fix 2: manage Node with nvm (global packages already live in your home directory)
59
+ ```
60
+
61
+ ### Option B: Run without installing — just want to try it
62
+
63
+ ```bash
64
+ npx xfmpress --help
65
+ npx xfmpress create my-blog --template=blog
66
+ ```
67
+
68
+ `npx` downloads into a temporary cache and runs from there, leaving no global command behind. Good for a quick look or a one-off build in CI.
69
+
70
+ ### Option C: Install into a project — best for teams
71
+
72
+ Add xfm as a dev dependency so everyone gets the **exact same** version after `npm install`:
73
+
74
+ ```bash
75
+ mkdir my-blog && cd my-blog
76
+ npm init -y
77
+ npm i -D xfmpress
78
+ ```
79
+
80
+ Then add scripts to `package.json`:
81
+
82
+ ```json
83
+ {
84
+ "scripts": {
85
+ "dev": "xfm dev",
86
+ "build": "xfm build",
87
+ "new": "xfm new",
88
+ "clean": "xfm clean"
89
+ }
90
+ }
91
+ ```
92
+
93
+ From then on use `npm run dev` / `npm run build`; for a one-off command use `npx xfmpress info`.
94
+
95
+ > The downside of Option C: you cannot run `xfm create` in an empty directory, because there is no `node_modules` yet. Scaffold the site with Option A or B first, then install it locally.
96
+
97
+ ---
98
+
99
+ ## 3. Quick start
100
+
101
+ ### 1. Create a site
102
+
103
+ ```bash
104
+ xfm create my-blog --template=blog
105
+ cd my-blog
106
+ ```
107
+
108
+ Available templates:
109
+
110
+ | `--template` | Look | Good for |
111
+ | --- | --- | --- |
112
+ | `blog` (default) | Blog: post list on the home page, post pages, right-hand TOC | Personal blogs, tech notes |
113
+ | `docs` | Documentation: grouped left sidebar + body | Product docs, knowledge bases |
114
+
115
+ You can also set the site title:
116
+
117
+ ```bash
118
+ xfm create my-blog --template=docs --title="My Knowledge Base"
119
+ ```
120
+
121
+ Generated structure:
122
+
123
+ ```
124
+ my-blog/
125
+ ├── xfm.config.mjs # site config (sensible defaults, edit as needed)
126
+ ├── content/ # all Markdown sources
127
+ │ ├── index.md
128
+ │ ├── about.md
129
+ │ └── posts/
130
+ │ └── hello-world.md
131
+ ├── plugins/ # your own plugins
132
+ ├── public/ # static files copied verbatim to the output root
133
+ └── README.md
134
+ ```
135
+
136
+ ### 2. Local development
137
+
138
+ ```bash
139
+ xfm dev
140
+ ```
141
+
142
+ Open `http://127.0.0.1:4173/`. Edit Markdown under `content/` or templates under `themes/`, save, and the browser **refreshes itself** (SSE push, no browser extension needed).
143
+
144
+ ```bash
145
+ xfm dev --port=5000 # different port
146
+ ```
147
+
148
+ ### 3. Write a post
149
+
150
+ ```bash
151
+ xfm new "My First Post"
152
+ # ✓ created content/posts/my-first-post.md (the title is slugified into the filename)
153
+ ```
154
+
155
+ Titles with spaces or non-ASCII characters are handled automatically:
156
+
157
+ ```bash
158
+ xfm new "Hello, World!" # → content/posts/hello-world.md
159
+ xfm new "Deploy notes" --slug=deploy-notes # → explicit filename
160
+ xfm new "About" --dir=pages # → under content/pages/
161
+ ```
162
+
163
+ > **Note**: posts created by `xfm new` are **publishable by default** and show up on the next `xfm build`. To write a work in progress, use `xfm new --draft` (writes `draft: true`); such posts never appear in production builds. Set `draft` to `false` or delete the line when you are ready to publish.
164
+
165
+ ### 4. Production build
166
+
167
+ ```bash
168
+ xfm build
169
+ ```
170
+
171
+ Output goes to `dist/`, fully static — drop it on Nginx, object storage, Vercel, Netlify or GitHub Pages.
172
+
173
+ ```
174
+ ✓ pages 5
175
+ ✓ extra files 4 (sitemap / rss, etc.)
176
+ ✓ output dist
177
+ done in 30 ms
178
+ ```
179
+
180
+ Rebuilds use the incremental cache and only re-render changed pages:
181
+
182
+ ```bash
183
+ xfm build --dev # enable the incremental cache in dev mode too
184
+ ```
185
+
186
+ ### 5. Other commands
187
+
188
+ ```bash
189
+ xfm info # show the resolved config (theme, content dir, plugins, Node version)
190
+ xfm clean # wipe dist/ and the incremental cache
191
+ xfm --help # every command and option
192
+ ```
193
+
194
+ ---
195
+
196
+ ## 4. Writing Markdown
197
+
198
+ Content is plain Markdown — no proprietary syntax. Common extensions:
199
+
200
+ ````markdown
201
+ ---
202
+ title: Post title
203
+ date: 2024-06-01
204
+ tags: [performance, node]
205
+ description: Used for SEO and list summaries
206
+ layout: post.html
207
+ draft: false
208
+ ---
209
+
210
+ ## H2 headings land in the right-hand TOC automatically
211
+
212
+ Normal paragraphs support **bold**, *italic*, `inline code`, ~~strikethrough~~, [links](/about/).
213
+
214
+ | Syntax | Notes |
215
+ | --- | --- |
216
+ | Tables | Standard GFM |
217
+
218
+ - [x] Task lists work
219
+ - [ ] Unfinished item
220
+
221
+ ::: tip Callout
222
+ Four kinds: `tip` / `info` / `warning` / `danger`.
223
+ :::
224
+
225
+ ```js
226
+ const ok = true; // code blocks are highlighted automatically
227
+ ```
228
+ ````
229
+
230
+ Highlighting supports: `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`, case-insensitive and alias-aware; unknown languages degrade to plain text instead of failing. Fences can carry a title: `` ```js app.js ``.
231
+
232
+ ---
233
+
234
+ ## 5. Configuration
235
+
236
+ `xfm.config.mjs` is a plain ESM module — export an object and you are done. The dev server picks up changes automatically:
237
+
238
+ ```js
239
+ export default {
240
+ site: {
241
+ title: 'My Blog',
242
+ description: 'Notes on tech and life',
243
+ url: 'https://example.com', // absolute links for sitemap / rss
244
+ lang: 'en',
245
+ base: '/',
246
+ nav: [{ title: 'Home', url: '/' }],
247
+ },
248
+ contentDir: 'content',
249
+ outDir: 'dist',
250
+ theme: 'default', // built-in: default | docs; or a local path
251
+ plugins: [
252
+ 'sitemap',
253
+ 'rss',
254
+ './plugins/my-plugin.js', // local plugin
255
+ ],
256
+ workers: 0, // 0 = auto; number of render workers
257
+ server: { port: 4173 }, // dev port
258
+ };
259
+ ```
260
+
261
+ Every field has a default, so the minimal config is an empty object. Full reference: `README.md` (English) / `README_CN.md` (Chinese).
262
+
263
+ ---
264
+
265
+ ## 6. FAQ
266
+
267
+ **`xfm: command not found`**
268
+ The global npm `bin` directory is not on your `PATH`. Run `npm config get prefix` and add its `bin` subdirectory to `PATH`. With nvm, opening a fresh terminal usually fixes it.
269
+
270
+ **`EACCES: permission denied` during install**
271
+ See the global-prefix fix under Option A. Do not use `sudo`.
272
+
273
+ **`node -v` is below 18**
274
+ Upgrade Node, then reinstall: `npm i -g xfmpress --force`.
275
+
276
+ **`xfm new` created a post but it is not on the site**
277
+ Most likely `draft: true`. Change it to `false` and run `xfm build` again.
278
+
279
+ **On Windows, `xfm` is "not recognized as an internal or external command"**
280
+ Reopen your terminal in Git Bash or PowerShell. If it still fails, check that `%APPDATA%\npm` is on your `Path`.
281
+
282
+ **Upgrading**
283
+ ```bash
284
+ npm i -g xfmpress@latest # global
285
+ npm i -D xfmpress@latest # in a project
286
+ ```
287
+
288
+ ---
289
+
290
+ ## 7. One-liner (copy & paste)
291
+
292
+ ```bash
293
+ # install globally + scaffold a blog + start the dev server
294
+ npm i -g xfmpress \
295
+ && xfm create my-blog --template=blog \
296
+ && cd my-blog \
297
+ && xfm dev
298
+ ```
package/INSTALL_CN.md ADDED
@@ -0,0 +1,298 @@
1
+ # xfm 安装与使用说明
2
+
3
+ > 面向 Node 22 环境,从零到跑起来大约 1 分钟。
4
+ > 项目地址:`https://github.com/xfm0797/xfm`
5
+
6
+ [English](./INSTALL.md) | 简体中文
7
+
8
+ ---
9
+
10
+ ## 一、先决条件
11
+
12
+ | 项目 | 要求 | 检查命令 |
13
+ | --- | --- | --- |
14
+ | Node.js | **18 或更高**(推荐 22 LTS) | `node -v` |
15
+ | npm | 随 Node 附带(推荐 ≥ 9) | `npm -v` |
16
+
17
+ ```bash
18
+ node -v # 期望 v22.x
19
+ npm -v # 期望 10.x 或 11.x
20
+ ```
21
+
22
+ Node 版本过旧会报 `EBADENGINE`,用 [nvm](https://github.com/nvm-sh/nvm) 或 [fnm](https://github.com/Schniz/fnm) 切到 22 即可:
23
+
24
+ ```bash
25
+ nvm install 22 && nvm use 22
26
+ ```
27
+
28
+ xfm 是**零运行时依赖**的,安装时不会拉取任何第三方包,也因此不会出现依赖树冲突、`npm audit` 报警。
29
+
30
+ ---
31
+
32
+ ## 二、安装(三种方式,按需选一种)
33
+
34
+ ### 方式 A:全局安装 —— 和 Hexo 一样用 `xfm` 命令
35
+
36
+ ```bash
37
+ npm install -g xfmpress
38
+ ```
39
+
40
+ 验证:
41
+
42
+ ```bash
43
+ xfm --help
44
+ ```
45
+
46
+ 看到 `⚡ xfm v0.1.0` 的版本横幅即安装成功。
47
+
48
+ > **命名说明**: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`。
49
+
50
+ **权限报错怎么办**(`EACCES: permission denied`)?有两种正规解法,不要用 `sudo npm i -g`:
51
+
52
+ ```bash
53
+ # 解法 1(推荐):把全局前缀改到用户目录
54
+ npm config set prefix ~/.npm-global
55
+ echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc # bash 用户改成 ~/.bashrc
56
+ source ~/.zshrc
57
+
58
+ # 解法 2:用 nvm 管理 Node(全局包天然在用户目录,无需额外配置)
59
+ ```
60
+
61
+ ### 方式 B:免安装运行 —— 只想先试试
62
+
63
+ ```bash
64
+ npx xfmpress --help
65
+ npx xfmpress create my-blog --template=blog
66
+ ```
67
+
68
+ `npx` 会自动下载到临时缓存并执行,不在系统里留下全局命令。适合快速体验或 CI 里一次性构建。
69
+
70
+ ### 方式 C:项目内安装 —— 团队协作推荐
71
+
72
+ 把 xfm 作为开发依赖写进项目,任何人 `npm install` 后即可获得**完全一致**的版本:
73
+
74
+ ```bash
75
+ mkdir my-blog && cd my-blog
76
+ npm init -y
77
+ npm i -D xfmpress
78
+ ```
79
+
80
+ 然后在 `package.json` 里加脚本:
81
+
82
+ ```json
83
+ {
84
+ "scripts": {
85
+ "dev": "xfm dev",
86
+ "build": "xfm build",
87
+ "new": "xfm new",
88
+ "clean": "xfm clean"
89
+ }
90
+ }
91
+ ```
92
+
93
+ 之后用 `npm run dev` / `npm run build` 即可;临时调用可用 `npx xfmpress info`。
94
+
95
+ > 方式 C 的缺点是不能在空目录里用 `xfm create` 生成脚手架(那时还没有 `node_modules`)。建议先用方式 A 或 B 生成站点,再进目录装成本地依赖。
96
+
97
+ ---
98
+
99
+ ## 三、快速上手
100
+
101
+ ### 1. 创建站点
102
+
103
+ ```bash
104
+ xfm create my-blog --template=blog
105
+ cd my-blog
106
+ ```
107
+
108
+ 可选模板:
109
+
110
+ | `--template` | 外观 | 适合 |
111
+ | --- | --- | --- |
112
+ | `blog`(默认) | 博客:首页列表 + 文章页 + 右侧目录 | 个人博客、技术随笔 |
113
+ | `docs` | 文档:左侧分组侧栏 + 正文 | 产品文档、知识库 |
114
+
115
+ 也能指定站名:
116
+
117
+ ```bash
118
+ xfm create my-blog --template=docs --title="我的知识库"
119
+ ```
120
+
121
+ 生成的结构:
122
+
123
+ ```
124
+ my-blog/
125
+ ├── xfm.config.mjs # 站点配置(有合理默认值,可按需改)
126
+ ├── content/ # 所有 Markdown 源文件
127
+ │ ├── index.md
128
+ │ ├── about.md
129
+ │ └── posts/
130
+ │ └── hello-world.md
131
+ ├── plugins/ # 你自己的插件
132
+ ├── public/ # 原样拷贝到产物根目录的静态文件
133
+ └── README.md
134
+ ```
135
+
136
+ ### 2. 本地开发
137
+
138
+ ```bash
139
+ xfm dev
140
+ ```
141
+
142
+ 打开 `http://127.0.0.1:4173/`。改 `content/` 里的 Markdown 或 `themes/` 里的模板,保存后浏览器**自动刷新**(SSE 推送,无需装浏览器插件)。
143
+
144
+ ```bash
145
+ xfm dev --port=5000 # 换端口
146
+ ```
147
+
148
+ ### 3. 写文章
149
+
150
+ ```bash
151
+ xfm new "我的第一篇文章"
152
+ # ✓ 已创建 content/posts/我的第一篇文章.md (文件名由标题自动转为 slug)
153
+ ```
154
+
155
+ 带空格或多语言的标题会自动处理文件名:
156
+
157
+ ```bash
158
+ xfm new "Hello, World!" # → content/posts/hello-world.md
159
+ xfm new "部署笔记" --slug=deploy-notes # → 手动指定文件名
160
+ xfm new "关于" --dir=pages # → 放到 content/pages/ 下
161
+ ```
162
+
163
+ > **注意**:`xfm new` 生成的文章**默认可发布**,`xfm build` 立刻就能看到。想先写半成品,用 `xfm new --draft`(会写入 `draft: true`),这类文章不会出现在生产构建里;要发布时把 `draft` 改成 `false` 或删掉该行即可。
164
+
165
+ ### 4. 生产构建
166
+
167
+ ```bash
168
+ xfm build
169
+ ```
170
+
171
+ 产物在 `dist/`,纯静态,扔到 Nginx / 对象存储 / Vercel / Netlify / GitHub Pages 都能跑。
172
+
173
+ ```
174
+ ✓ 页面 5 个
175
+ ✓ 附加产物 4 个(sitemap / rss 等)
176
+ ✓ 输出目录 dist
177
+ 耗时 30 ms
178
+ ```
179
+
180
+ 重构建会走增量缓存,只重新渲染改动过的页面:
181
+
182
+ ```bash
183
+ xfm build --dev # 开发模式下也启用增量缓存
184
+ ```
185
+
186
+ ### 5. 其他命令
187
+
188
+ ```bash
189
+ xfm info # 查看当前站点解析后的配置(主题、内容目录、插件、Node 版本)
190
+ xfm clean # 清空 dist/ 与增量缓存
191
+ xfm --help # 全部命令与选项
192
+ ```
193
+
194
+ ---
195
+
196
+ ## 四、写 Markdown
197
+
198
+ 内容就是标准 Markdown,没有私有语法。常用增强:
199
+
200
+ ````markdown
201
+ ---
202
+ title: 文章标题
203
+ date: 2024-06-01
204
+ tags: [性能, Node]
205
+ description: 用于 SEO 与列表摘要
206
+ layout: post.html
207
+ draft: false
208
+ ---
209
+
210
+ ## 二级标题会自动进右侧目录
211
+
212
+ 普通段落支持 **加粗**、*斜体*、`行内代码`、~~删除线~~、[链接](/about/)。
213
+
214
+ | 语法 | 说明 |
215
+ | --- | --- |
216
+ | 表格 | 标准 GFM |
217
+
218
+ - [x] 任务列表已支持
219
+ - [ ] 未完成项
220
+
221
+ ::: tip 提示容器
222
+ 支持 `tip` / `info` / `warning` / `danger` 四种。
223
+ :::
224
+
225
+ ```js
226
+ const ok = true; // 代码块自动语法高亮
227
+ ```
228
+ ````
229
+
230
+ 代码高亮支持:`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 ``。
231
+
232
+ ---
233
+
234
+ ## 五、配置
235
+
236
+ `xfm.config.mjs` 是一个普通 ESM 模块,导出对象即可,改动后 dev 服务器会自动重启:
237
+
238
+ ```js
239
+ export default {
240
+ site: {
241
+ title: '我的博客',
242
+ description: '记录技术与生活',
243
+ url: 'https://example.com', // 用于 sitemap / rss 的绝对链接
244
+ lang: 'zh-CN',
245
+ base: '/',
246
+ nav: [{ title: '首页', url: '/' }],
247
+ },
248
+ contentDir: 'content',
249
+ outDir: 'dist',
250
+ theme: 'default', // 内置主题:default | docs;也可填本地路径
251
+ plugins: [
252
+ 'sitemap',
253
+ 'rss',
254
+ './plugins/my-plugin.js', // 本地插件
255
+ ],
256
+ workers: 0, // 0 = 自动;渲染进程数
257
+ server: { port: 4173 }, // dev 端口
258
+ };
259
+ ```
260
+
261
+ 所有字段都有默认值,最小配置就是一个空对象。完整字段见 `README_CN.md`(中文)/ `README.md`(English)。
262
+
263
+ ---
264
+
265
+ ## 六、常见问题
266
+
267
+ **`xfm: command not found`**
268
+ 全局 npm 的 `bin` 目录不在 `PATH` 里。执行 `npm bin -g`(旧版)或 `npm config get prefix`,把其下的 `bin` 加进 `PATH`。用 nvm 的话重开一个终端通常就能解决。
269
+
270
+ **安装时报 `EACCES: permission denied`**
271
+ 见「方式 A」里的全局前缀改法,不要用 `sudo`。
272
+
273
+ **`node -v` 低于 18**
274
+ 升级 Node 后重装:`npm i -g xfmpress --force`。
275
+
276
+ **`xfm new` 建了文章但页面上没有**
277
+ 大概率是 `draft: true`。改成 `false` 后重新 `xfm build`。
278
+
279
+ **Windows 下 `xfm` 提示不是内部或外部命令**
280
+ 用 Git Bash 或 PowerShell 重开终端;仍不行则检查 `%APPDATA%\npm` 是否在 `Path` 中。
281
+
282
+ **想升级**
283
+ ```bash
284
+ npm i -g xfmpress@latest # 全局
285
+ npm i -D xfmpress@latest # 项目内
286
+ ```
287
+
288
+ ---
289
+
290
+ ## 七、一键脚本(复制即用)
291
+
292
+ ```bash
293
+ # 全局安装 + 创建博客 + 本地预览
294
+ npm i -g xfmpress \
295
+ && xfm create my-blog --template=blog \
296
+ && cd my-blog \
297
+ && xfm dev
298
+ ```
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.