diff --git a/docs/en/unit.yaml b/docs/en/unit.yaml
new file mode 100644
index 0000000..718331a
--- /dev/null
+++ b/docs/en/unit.yaml
@@ -0,0 +1,6 @@
+unit:
+ - template: "documentor"
+ template_key: "redirect"
+ output: "index.html"
+ define:
+ target: "v2.4"
diff --git a/docs/en/v2.1/README.md b/docs/en/v2.1/README.md
index b41380b..5952dbe 100644
--- a/docs/en/v2.1/README.md
+++ b/docs/en/v2.1/README.md
@@ -1,4 +1,4 @@
-# Pagine v2
+# Pagine
Pagine is an high-performance website constructor that makes full use of multicore hardware.
diff --git a/docs/en/v2.2/README.md b/docs/en/v2.2/README.md
index 43edf45..687ea64 100644
--- a/docs/en/v2.2/README.md
+++ b/docs/en/v2.2/README.md
@@ -1,275 +1,3 @@
-# Pagine v2.2.0-alpha-50a1f7a-20240819
+# Pagine
-Pagine is an high-performance website constructor that makes full use of multicore hardware.
-
-Build jobs can be completed very fast.
-
-## Features
-
-- Parallel hierarchy processing and unit execution. Everything is executed in parallel from beginning to end.
-- Hierarchical metadata propagation which makes metadata management easy.
-- Manage templates and assets via Git. Every template can be distributed and used without modification.
-- In-template builtin functions
-- Interact with Pagine in templates.
-- Update on file change while running as HTTP server.
-
-Supported rich text formats:
-
-- [Asciidoc](https://asciidoc.org)
-- [Markdown](https://markdownguide.org)
-- [MathJax](https://www.mathjax.org) support provided in [Documentor](https://github.com/webpagine/documentor)
-
-## Install
-
-### Binaries
-
-Find the executable that matches your OS and architecture in [releases](https://github.com/webpagine/pagine/v2/releases).
-
-### Build from source
-
-```shell
-$ go install github.com/webpagine/pagine/v2/cmd/pagine@latest
-```
-
-> [!TIP]
-> Install Pagine via Go mod is recommended for non-amd64 platforms. Choose Go toolchain for your platform [here](https://go.dev/dl).
-
-## Usage
-
-Usage of pagine:
-- `-public` string
- - Location of public directory. (default `/tmp/$(basename $PWD).public`)
-- `-root` string
- - Site root. (default `$PWD`)
-- `-serve` string
- - Specify the port to listen and serve as HTTP.
-
-
-### Generate
-
-```shell
-$ cd ~/web/my_site
-$ pagine
-Generation complete.
-```
-
-### Run as HTTP server
-
-```shell
-$ cd ~/web/my_site
-$ pagine --serve :12450
-```
-
-It automatically executes generation when file changes are detected by `inotify`.
-
-> [!NOTE]
-> Incremental generation is not implemented yet.
-> Set the `--public` under `/tmp` is recommended to reduce hard disk writes.
-
-Since v2.1.0, the server provides a WebSocket interface at `/ws` to provide event monitoring for the client, such as page updates.
-
-> [!CAUTION]
-> Exposing your Pagine server to the public network might be risky!
-> You should deploy your final pages via static page services.
-
-## Structure
-
-### Template
-
-Template is a set of page frames (Go template file) and assets (e.g. SVGs, stylesheets and scripts).
-
-Manifest of one template looks like:
-```yaml
-manifest:
- canonical: "com.symboltics.pagine.genesis" # Canonical name
- patterns:
- - "/*html" # Matched files will be added as template file.
-
-templates:
- - name: "page" # Export as name `page`
- export: "page.html" # Export `page.html`
-
- - name: "post" # Export as name `post`
- export: "post.html" # Export `post.html`
-```
-
-To the Go templates files syntax, see [text/template](https://pkg.go.dev/text/template).
-
-Example: `page.html`
-```html
-
-
- {{ .title }}
-
-
-
-{{ template "header.html" . }}
-{{ render.ByFileExtName .content }}
-
-{{ template "footer.html" . }}
-
-```
-
-### Env
-
-"Environment" is the configuration of the details of the entire process.
-
-```yaml
-ignore: # Pattern matching. Matched files will not be **copied** to the public/destination.
- - "/.git*"
-
-use: # Load and set alias for the template.
- genesis: "/templates/genesis"
- documentor: "/templates/documentor"
-```
-
-Installing templates via Git submodule is recommended. Such as:
-
-```shell
-$ git submodule add https://github.com/webpagine/genesis templates/genesis
-```
-
-### Level
-
-Each "level" contains its metadata. And a set of units to be executed.
-
-For directories, metadata sets are stored in `metadata.toml` in the form of map, and units are stored in `unit.toml`
-
-Each template has its alias that defined in `env` as the namespace.
-
-Levels can override fields propagated from parents.
-
-Example: `/metadata.yaml`
-```yaml
-genesis:
- title: "Pagine"
-
- head:
- icon: "/favicon.ico"
-
- nav:
- items:
- - name: "Documentation"
- link: "/docs/"
-```
-
-### Unit
-
-Example: `/unit.yaml`
-```yaml
-unit:
- - template: "genesis" # Which template to use.
- template_key: "page" # Which the key refers to.
- output: "/index.html" # Where to save the result.
- define:
- title: "Pagine" # Unit-specified metadata.
- content: "README.md"
-
- - template: "genesis"
- template_key: "page"
- output: "/404.html"
- define:
- title: "Page not found"
- content: "404.md"
-```
-
-## Builtin functions
-
-### Arithmetic
-
-| Func | Args | Result |
-|-------|-----------|--------|
-| `add` | a, b: Int | Int |
-| `sub` | a, b: Int | Int |
-| `mul` | a, b: Int | Int |
-| `div` | a, b: Int | Int |
-| `mod` | a,b : Int | Int |
-
-### Engine API
-
-| Func | | Description |
-|-----------------|--------------------------------------------------------|--------------------------------------------------------------------------------------------------|
-| `api.Attr` | | Get meta information in the form of map about units, hierarchy and templates provided by engine. |
-| `api.Apply` | templateName, templateKey: String, data map[string]Any | Invoke a template. |
-| `api.ApplyFile` | apiVer, path: String, data map[string]any | Invoke single template file. |
-| `This` | | It returns the root node of metadata of the template. |
-
-| api.Attr. | Description |
-|----------------|-------------------------------------------------|
-| `isServing` | True if Pagine is running as server. |
-| `templateBase` | It tells the template where it has been stored. |
-| `unitBase` | Unit's level's base dir path. |
-
-> [!TIP]
-> `api.Attr.isServing` can be used to enable some debug code in templates such as page realtime update.
-
-### String processing
-
-| Func | Args | Result |
-|----------------------|-----------------------------|--------|
-| `strings.HasPrefix` | str: String, prefix: String | Bool |
-| `strings.TrimPrefix` | str: String, prefix: String | String |
-
-### Content rendering
-
-Path starts from where the unit is.
-
-| Func | Args | Description |
-|-------------------------|------------------------|-----------------------------------------------------|
-| `render.FileByExtName` | path: String | Query MIME type by file extension name then render. |
-| `render.FileByMimeType` | mimeType, path: String | Render file content by given MIME type. |
-
-| Format | MIME Type | File Extension Name |
-|----------|-----------------|---------------------|
-| Asciidoc | `text/asciidoc` | `adoc`, `asciidoc` |
-| Markdown | `text/markdown` | `md`, `markdown` |
-
-## Deploy
-
-### Manually
-
-```shell
-$ pagine --public ../public
-```
-
-Upload `public` to your server.
-
-### Deploy to GitHub Pages via GitHub Actions (recommended)
-
-GitHub Actions workflow configuration can be found in [Get Started](https://github.com/webpagine/get-started) repository.
-
-## FAQ
-
-### Why another generator? Isn't Hugo enough?
-
-Pagine is **not** Hugo, and is not aim to replace Hugo.
-
-Pagine does not embed page configurations in Markdown file, they are separated and should be separated.
-
-And Pagine does not focus on Markdown only, I hope to support various kinds of source.
-
-### Can I use Pagine for building complex web application?
-
-Yes. It can help you get rid of repetitive work about static contents.
-
-And templates can also increase productivity as long as Pagine well integrated with external tools via ***workflow***.
-
-### Co-operate with external tools such as TypeScript compiler or npx?
-
-It can be done via ***workflow***.
-
-### What is the origin of the logo and name?
-
-It is **neither** a browser engine, a layout engine **nor** a rendering engine.
-
-Page Gen × Engine ⇒ Pagine. It has similar pronunciation to "pagen".
-
-The logo is an opened book with a bookmark.
-
-### Rewrite it in other PL?
-
-*I expected somebody would ask.*
-
-It will not be taken unless it does bring obvious advantages.
-
-Thus: NO. It is not planned currently.
+v2.2 is a broken version.
diff --git a/docs/en/v2.3/README.md b/docs/en/v2.3/README.md
new file mode 100644
index 0000000..dda1abc
--- /dev/null
+++ b/docs/en/v2.3/README.md
@@ -0,0 +1,3 @@
+# Pagine
+
+v2.3 is a broken version.
diff --git a/docs/en/v2.3/unit.yaml b/docs/en/v2.3/unit.yaml
new file mode 100644
index 0000000..b0afd72
--- /dev/null
+++ b/docs/en/v2.3/unit.yaml
@@ -0,0 +1,7 @@
+unit:
+ - template: "documentor"
+ template_key: "doc"
+ output: "/index.html"
+ define:
+ title: "Documentation"
+ content: "/README.md"
\ No newline at end of file
diff --git a/docs/en/v2.4/README.md b/docs/en/v2.4/README.md
new file mode 100644
index 0000000..54f4480
--- /dev/null
+++ b/docs/en/v2.4/README.md
@@ -0,0 +1,368 @@
+# Pagine
+
+Pagine is an high-performance website constructor that makes full use of multicore hardware.
+
+Build jobs can be completed very fast.
+
+## Features
+
+- Parallel hierarchy processing and unit execution. Everything is executed in parallel from beginning to end.
+- Hierarchical metadata propagation which makes metadata management easy.
+- Manage templates and assets via Git. Every template can be distributed and used without modification.
+- In-template builtin functions
+- Interact with Pagine in templates.
+- Multi-stage workflow.
+
+As server: update web content on file change.
+
+Supported rich text formats:
+
+- [Asciidoc](https://asciidoc.org)
+- [Markdown](https://markdownguide.org)
+- [MathJax](https://www.mathjax.org) support provided in [Documentor](https://github.com/webpagine/documentor)
+
+## Install
+
+### Binaries
+
+Find the executable that matches your OS and architecture in [releases](https://github.com/webpagine/pagine/v2/releases).
+
+### Build from source
+
+```shell
+$ go install github.com/webpagine/pagine/v2/cmd/pagine@v2.4.0
+```
+
+> [!TIP]
+> Install Pagine via Go mod is recommended for non-amd64 platforms. Choose Go toolchain for your platform [here](https://go.dev/dl).
+
+## Usage
+
+Usage of pagine:
+- `-public` string
+ - Location of public directory. (default `/tmp/$(basename $PWD).public`)
+- `-root` string
+ - Site root. (default `$PWD`)
+- `-serve` string
+ - Specify the port to listen and serve as HTTP.
+
+
+### Generate
+
+```shell
+$ cd ~/web/my_site
+$ pagine
+Generation complete.
+```
+
+### Run as HTTP server
+
+```shell
+$ cd ~/web/my_site
+$ pagine --serve :12450
+```
+
+It automatically executes generation when file changes are detected by `inotify`.
+
+> [!NOTE]
+> Incremental generation is not implemented yet.
+> Set the `--public` under `/tmp` is recommended to reduce hard disk writes.
+
+Since v2.1.0, the server provides a WebSocket interface at `/ws` to provide event monitoring for the client, such as page updates.
+
+> [!CAUTION]
+> Exposing your Pagine server to the public network might be risky!
+> You should deploy your final pages via static page services.
+
+## Structure
+
+### Template
+
+Template is a set of page frames (Go template file) and assets (e.g. SVGs, stylesheets and scripts).
+
+Manifest of one template looks like:
+```yaml
+manifest:
+ canonical: "com.symboltics.pagine.genesis" # Canonical name
+ patterns:
+ - "/*html" # Matched files will be added as template file.
+
+templates:
+ - name: "page" # Export as name `page`
+ export: "page.html" # Export `page.html`
+
+ - name: "post" # Export as name `post`
+ export: "post.html" # Export `post.html`
+```
+
+To the Go templates files syntax, see [text/template](https://pkg.go.dev/text/template).
+
+Example: `page.html`
+```html
+
+
+ {{ .title }}
+
+
+
+{{ template "header.html" . }}
+{{ render.ByFileExtName .content }}
+
+{{ template "footer.html" . }}
+
+```
+
+### Env
+
+"Environment" is the configuration of the details of the entire process.
+
+```yaml
+ignore: # Pattern matching. Matched files will not be **copied** to the public/destination.
+ - "/.git*"
+
+use: # Load and set alias for the template.
+ genesis: "/templates/genesis"
+ documentor: "/templates/documentor"
+```
+
+Installing templates via Git submodule is recommended. Such as:
+
+```shell
+$ git submodule add https://github.com/webpagine/genesis templates/genesis
+```
+
+### Level
+
+Each "level" contains its metadata. And a set of units to be executed.
+
+For directories, metadata sets are stored in `metadata.toml` in the form of map, and units are stored in `unit.toml`
+
+Each template has its alias that defined in `env` as the namespace.
+
+Levels can override fields propagated from parents.
+
+Example: `/metadata.yaml`
+```yaml
+genesis:
+ title: "Pagine"
+
+ head:
+ icon: "/favicon.ico"
+
+ nav:
+ items:
+ - name: "Documentation"
+ link: "/docs/"
+```
+
+### Unit
+
+Example: `/unit.yaml`
+```yaml
+unit:
+ - template: "genesis" # Which template to use.
+ template_key: "page" # Which the key refers to.
+ output: "/index.html" # Where to save the result.
+ define:
+ title: "Pagine" # Unit-specified metadata.
+ content: "README.md"
+
+ - template: "genesis"
+ template_key: "page"
+ output: "/404.html"
+ define:
+ title: "Page not found"
+ content: "404.md"
+```
+
+## Multi-stage Workflow
+
+All paths are based on the directory where the `workflow.yaml` is located.
+
+### Workflow
+
+Workflows are executed in parallel.
+
+Example: `workflow.yaml`
+```yaml
+stage:
+ - job:
+ - type: "tsc/v1"
+ title: "Build TypeScript"
+ path: "/script/"
+```
+
+### Stage
+
+Stages are executed in order.
+Each stage contains a set of jobs.
+
+### Job
+
+Jobs are executed in parallel.
+
+## Builtin Job Types
+
+### TypeScript compiler (tsc)
+
+```yaml
+type: "tsc/v1"
+title: "Build TypeScript"
+path: "/script/"
+```
+
+Make sure `tsc` had been installed on target machine.
+
+## Builtin functions
+
+### Arithmetic
+
+| Func | Args | Result |
+|-------|-----------|--------|
+| `add` | a, b: Int | Int |
+| `sub` | a, b: Int | Int |
+| `mul` | a, b: Int | Int |
+| `div` | a, b: Int | Int |
+| `mod` | a,b : Int | Int |
+
+### Engine API
+
+| Func | | Description |
+|-----------------|--------------------------------------------------------|--------------------------------------------------------------------------------------------------|
+| `api.Attr` | | Get meta information in the form of map about units, hierarchy and templates provided by engine. |
+| `api.Apply` | templateName, templateKey: String, data map[string]Any | Invoke a template. |
+| `api.ApplyFile` | apiVer, path: String, data map[string]any | Invoke single template file. |
+| `This` | | It returns the root node of metadata of the template. |
+
+| api.Attr. | Description |
+|----------------|-------------------------------------------------|
+| `isServing` | True if Pagine is running as server. |
+| `templateBase` | It tells the template where it has been stored. |
+| `unitBase` | Unit's level's base dir path. |
+
+> [!TIP]
+> `api.Attr.isServing` can be used to enable some debug code in templates such as page realtime update.
+
+### String processing
+
+| Func | Args | Result |
+|----------------------|-----------------------------|--------|
+| `strings.HasPrefix` | str: String, prefix: String | Bool |
+| `strings.TrimPrefix` | str: String, prefix: String | String |
+
+### Content rendering
+
+Path starts from where the unit is.
+
+| Func | Args | Description |
+|-------------------------|------------------------|-----------------------------------------------------|
+| `render.FileByExtName` | path: String | Query MIME type by file extension name then render. |
+| `render.FileByMimeType` | mimeType, path: String | Render file content by given MIME type. |
+
+| Format | MIME Type | File Extension Name |
+|----------|-----------------|---------------------|
+| Asciidoc | `text/asciidoc` | `adoc`, `asciidoc` |
+| Markdown | `text/markdown` | `md`, `markdown` |
+
+## Deploy
+
+### Manually
+
+```shell
+$ pagine --public ../public
+```
+
+Upload `../public` to your server.
+
+### Deploy to GitHub Pages via GitHub Actions (recommended)
+
+GitHub Actions workflow file content: `.github/workflows/pagine.yml`
+```yaml
+name: Deploy
+
+on:
+ push:
+ branches:
+ - master
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install TypeScript Compiler
+ run: sudo apt install node-typescript -y
+
+ - name: Install Pagine
+ run: go install github.com/webpagine/pagine/v2/cmd/pagine@v2.4.0
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ fetch-depth: 0
+
+ - name: Setup Pages
+ id: pages
+ uses: actions/configure-pages@v4
+
+ - name: Build with Pagine
+ run: ~/go/bin/pagine --public ../public/
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: ../public/
+
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
+```
+
+## FAQ
+
+### Why another generator? Isn't Hugo enough?
+
+Pagine is **not** Hugo, and is not aim to replace Hugo.
+
+Pagine does not embed page configurations in Markdown file, they are separated and should be separated.
+
+And Pagine does not focus on Markdown only, I hope to support various kinds of source.
+
+### Can I use Pagine for building complex web application?
+
+Yes. It can help you get rid of repetitive work about static contents.
+
+And templates can also increase productivity as long as Pagine well integrated with external tools via ***workflow***.
+
+### Co-operate with external tools such as TypeScript compiler or npx?
+
+It can be done via ***workflow***.
+
+### What is the origin of the logo and name?
+
+It is **neither** a browser engine, a layout engine **nor** a rendering engine.
+
+Page Gen × Engine ⇒ Pagine. It has similar pronunciation to "pagen".
+
+The logo is an opened book with a bookmark.
+
+### Rewrite it in other PL?
+
+*I expected somebody would ask.*
+
+It will not be taken unless it does bring obvious advantages.
+
+Thus: NO. It is not planned currently.
diff --git a/docs/en/v2.4/unit.yaml b/docs/en/v2.4/unit.yaml
new file mode 100644
index 0000000..b0afd72
--- /dev/null
+++ b/docs/en/v2.4/unit.yaml
@@ -0,0 +1,7 @@
+unit:
+ - template: "documentor"
+ template_key: "doc"
+ output: "/index.html"
+ define:
+ title: "Documentation"
+ content: "/README.md"
\ No newline at end of file
diff --git a/docs/metadata.yaml b/docs/metadata.yaml
index d1704ab..88f6ae7 100644
--- a/docs/metadata.yaml
+++ b/docs/metadata.yaml
@@ -6,6 +6,7 @@ documentor:
versions:
- "v2.1"
+ - "v2.4"
locales:
- locale: "en"
diff --git a/docs/zh/metadata.yaml b/docs/zh/metadata.yaml
index f202307..0a42712 100644
--- a/docs/zh/metadata.yaml
+++ b/docs/zh/metadata.yaml
@@ -1,13 +1,2 @@
documentor:
lang: "zh"
-
- header:
- title: 'Pagine Docs'
-
- logo:
- src: "/assets/img/pagine_icon_fit.svg"
- height: 50
-
- nav:
- - title: "Repositories"
- link: "https://github.com/webpagine"
diff --git a/docs/zh/unit.yaml b/docs/zh/unit.yaml
index 415d9ec..718331a 100644
--- a/docs/zh/unit.yaml
+++ b/docs/zh/unit.yaml
@@ -3,4 +3,4 @@ unit:
template_key: "redirect"
output: "index.html"
define:
- target: "v2.2"
+ target: "v2.4"
diff --git a/docs/zh/v2.1/README.md b/docs/zh/v2.1/README.md
index 15069e2..6ad0e0c 100644
--- a/docs/zh/v2.1/README.md
+++ b/docs/zh/v2.1/README.md
@@ -1,4 +1,4 @@
-# Pagine v2
+# Pagine
Pagine 是一个充分利用多核设施条件的高性能网站内容构建器,
页面构建任务可以在很短时间内完成。
diff --git a/docs/zh/v2.2/README.md b/docs/zh/v2.2/README.md
index c6f1522..687ea64 100644
--- a/docs/zh/v2.2/README.md
+++ b/docs/zh/v2.2/README.md
@@ -1,277 +1,3 @@
-# Pagine v2.2.0-alpha-50a1f7a-20240819
+# Pagine
-Pagine 是一个充分利用多核设施条件的高性能网站内容构建器,
-页面构建任务可以在很短时间内完成。
-
-## 特性
-
-- 并行层次化处理和单元任务执行,从头到尾都如此
-- 层次化元数据传播使元数据管理简化
-- 借助 Git 管理模板和素材,所有模板都可以被分发使用而无需改动
-- 模板内建函数
-- 在模板中与引擎交互
-- 以 HTTP 服务器运行时,在文件发生变动时更新内容
-
-已支持的富文本格式:
-
-- [Asciidoc](https://asciidoc.org)
-- [Markdown](https://markdownguide.org)
-- [MathJax](https://www.mathjax.org) 在 [Documentor](https://github.com/webpagine/documentor) 提供
-
-## 安装
-
-### 已构建的二进制档
-
-在 [releases](https://github.com/webpagine/pagine/v2/releases) 中选择匹配你操作系统和处理器架构的二进制档。
-
-### 从源码构建
-
-```shell
-$ go install github.com/webpagine/pagine/v2/cmd/pagine@v2.2.0-alpha
-```
-
-> [!TIP]
-> 在非 amd64 平台上建议借助 Go mod 安装 Pagine。 [在此](https://go.dev/dl)选择适用你平台的 Go 工具链。
-
-## CLI 用法
-
-Usage of pagine:
-- `-public` string
- - Location of public directory. (default `/tmp/$(basename $PWD).public`)
-- `-root` string
- - Site root. (default `$PWD`)
-- `-serve` string
- - Specify the port to listen and serve as HTTP.
-
-
-### 生成
-
-```shell
-$ cd ~/web/my_site
-$ pagine
-Generation complete.
-```
-
-### 以 HTTP 服务器运行
-
-```shell
-$ cd ~/web/my_site
-$ pagine --serve :12450
-```
-
-文件变动被 `inotify` 捕获后,Pagine 会自动执行生成。
-
-> [!NOTE]
-> 增量生成尚未实现。
-> 建议将 `--public` 设在 `/tmp` 下以减少硬盘写入。
-
-自版本 v2.1.0,服务器提供一个 WebSocket 位于 `/ws` 的接口以提供事件监听,例如页面更新。
-
-> [!CAUTION]
-> 在公共网络暴露你的 Pagine 服务器可能是有风险的,你应该将生成的页面结果部署到静态页面服务。
-
-## 构成
-
-### 模板
-
-模板是一组页面框架(Go 模板文件)和素材(比如 SVG,样式表和脚本)。
-
-一个木板的自述文件看起来应该像: `manifest.yaml`
-```yaml
-manifest:
- canonical: "com.symboltics.pagine.genesis" # Canonical name
- patterns:
- - "/*html" # Matched files will be added as template file.
-
-templates:
- - name: "page" # Export as name `page`
- export: "page.html" # Export `page.html`
-
- - name: "post" # Export as name `post`
- export: "post.html" # Export `post.html`
-```
-
-至于 Go 模板语法,见 [text/template](https://pkg.go.dev/text/template)。
-
-样例: `page.html`
-```html
-
-
- {{ .title }}
-
-
-
-{{ template "header.html" . }}
-{{ render.ByFileExtName .content }}
-
-{{ template "footer.html" . }}
-
-```
-
-### 环境
-
-环境是对任务全过程的细节配置。
-
-```yaml
-ignore: # Pattern matching. Matched files will not be **copied** to the public/destination.
- - "/.git*"
-
-use: # Load and set alias for the template.
- genesis: "/templates/genesis"
- documentor: "/templates/documentor"
-```
-
-建议通过 Git submodule 安装现有模板,例如:
-
-```shell
-$ git submodule add https://github.com/webpagine/genesis templates/genesis
-```
-
-### 层级
-
-每一“层”拥有元数据和一组将要执行的单元任务。
-
-对于目录,元数据被以表的形式储存在 `metadata.yaml`,单元任务则被储存在 `unit.yaml`。
-
-每一个模板都有其在“环境”中定义的别名作为命名空间。
-
-层级可以覆盖父层级传播的元数据。
-
-样例: `/metadata.yaml`
-```yaml
-genesis:
- title: "Pagine"
-
- head:
- icon: "/favicon.ico"
-
- nav:
- items:
- - name: "Documentation"
- link: "/docs/"
-```
-
-### 单元
-
-样例: `/unit.yaml`
-```yaml
-unit:
- - template: "genesis" # Which template to use.
- template_key: "page" # Which the key refers to.
- output: "/index.html" # Where to save the result.
- define:
- title: "Pagine" # Unit-specified metadata.
- content: "README.md"
-
- - template: "genesis"
- template_key: "page"
- output: "/404.html"
- define:
- title: "Page not found"
- content: "404.md"
-```
-
-## 内建函数
-
-### 算术
-
-| Func | Args | Result |
-|-------|-----------|--------|
-| `add` | a, b: Int | Int |
-| `sub` | a, b: Int | Int |
-| `mul` | a, b: Int | Int |
-| `div` | a, b: Int | Int |
-| `mod` | a,b : Int | Int |
-
-### 引擎 API
-
-| Func | | Description |
-|-----------------|--------------------------------------------------------|------------------------|
-| `api.Attr` | | 以映射表形式提供有关模板、单元和服务器的信息 |
-| `api.Apply` | templateName, templateKey: String, data map[string]Any | 调用一个模板 |
-| `api.ApplyFile` | apiVer, path: String, data map[string]any | 调用单模板文件 |
-| `This` | | 模板拥有的元数据的根节点 |
-
-| api.Attr. | Description |
-|----------------|------------------------|
-| `isServing` | 若 Pagine 以服务器运行则为 true |
-| `templateBase` | 它告诉模板被存放到了哪里 |
-| `unitBase` | 模板所在层级的基目录路径 |
-
-> [!TIP]
-> `api.Attr.isServing` 可以被用来启用一些模板中的调试代码,例如页面实时更新。
-
-### 字符串处理
-
-| Func | Args | Result |
-|----------------------|-----------------------------|--------|
-| `strings.HasPrefix` | str: String, prefix: String | Bool |
-| `strings.TrimPrefix` | str: String, prefix: String | String |
-
-### 内容渲染
-
-以单元所在路径为基。
-
-| Func | Args | Description |
-|-------------------------|------------------------|---------------------|
-| `render.FileByExtName` | path: String | 据文件扩展名查询 MIME 类型并渲染 |
-| `render.FileByMimeType` | mimeType, path: String | 据给定 MIME 类型渲染文件内容 |
-
-| Format | MIME Type | File Extension Name |
-|----------|-----------------|---------------------|
-| Asciidoc | `text/asciidoc` | `adoc`, `asciidoc` |
-| Markdown | `text/markdown` | `md`, `markdown` |
-
-## 部署
-
-### 手动
-
-```shell
-$ pagine --public ../public
-```
-
-上传 `public` 到你的服务器。
-
-### 通过 GitHub Actions 部署到 GitHub Pages(推荐)
-
-GitHub Actions 工作流配置可以在 [Get Started](https://github.com/webpagine/get-started) 仓库找到。
-
-## 问答
-
-### 为什么要搓另一个生成器?Hugo 不够用吗?
-
-Pagine **不是** Hugo,也不旨在替代 Hugo。
-
-明显的一点是:Pagine 不会在内容中嵌入页面配置(元数据),他们被分开而且理应分开。
-
-Pagine 不止关注 Markdown,我希望能够支持多种来源。
-
-### 我是否能够用 Pagine 来构建复杂的 Web 应用?
-
-它只能帮你摆脱关于静态内容的重复工作。
-
-如果 Pagine 与外部工具集成得好,模板则还可以继续提高生产力。
-
-所以,**这要视情况而定**。
-
-### 与外部工具互操作,比如 npx?
-
-这是可能的,但这一步应该对外部工具透明。
-
-也许需要在 Pagine 完成生成后运行 `npx`。
-
-### Logo 和命名的来源是?
-
-它**不是**浏览器引擎,**也不是**渲染引擎。
-
-Page Gen × Engine ⇒ Pagine. 与 "pagen" 发音相似。
-
-Logo 是一个带书签的打开的书本。
-
-### 以其他编程语言重写?
-
-*我料到会有人这么说*
-
-除非这样做有明显优势,这不会被采纳。
-
-因此:不。目前不在计划内。
+v2.2 is a broken version.
diff --git a/docs/zh/v2.3/README.md b/docs/zh/v2.3/README.md
new file mode 100644
index 0000000..dda1abc
--- /dev/null
+++ b/docs/zh/v2.3/README.md
@@ -0,0 +1,3 @@
+# Pagine
+
+v2.3 is a broken version.
diff --git a/docs/zh/v2.3/unit.yaml b/docs/zh/v2.3/unit.yaml
new file mode 100644
index 0000000..b0afd72
--- /dev/null
+++ b/docs/zh/v2.3/unit.yaml
@@ -0,0 +1,7 @@
+unit:
+ - template: "documentor"
+ template_key: "doc"
+ output: "/index.html"
+ define:
+ title: "Documentation"
+ content: "/README.md"
\ No newline at end of file
diff --git a/docs/zh/v2.4/README.md b/docs/zh/v2.4/README.md
new file mode 100644
index 0000000..ab6a98b
--- /dev/null
+++ b/docs/zh/v2.4/README.md
@@ -0,0 +1,368 @@
+# Pagine
+
+Pagine 是一个充分利用多核设施条件的高性能网站内容构建器,
+页面构建任务可以在很短时间内完成。
+
+## 特性
+
+- 并行层次化处理和单元任务执行,从头到尾都如此
+- 层次化元数据传播使元数据管理简化
+- 借助 Git 管理模板和素材,所有模板都可以被分发使用而无需改动
+- 模板内建函数
+- 在模板中与引擎交互
+- 以 HTTP 服务器运行时,在文件发生变动时更新内容
+- 多阶段工作流
+
+已支持的富文本格式:
+
+- [Asciidoc](https://asciidoc.org)
+- [Markdown](https://markdownguide.org)
+- [MathJax](https://www.mathjax.org) 在 [Documentor](https://github.com/webpagine/documentor) 提供
+
+## 安装
+
+### 已构建的二进制档
+
+在 [releases](https://github.com/webpagine/pagine/v2/releases) 中选择匹配你操作系统和处理器架构的二进制档。
+
+### 从源码构建
+
+```shell
+$ go install github.com/webpagine/pagine/v2/cmd/pagine@v2.4.0
+```
+
+> [!TIP]
+> 在非 amd64 平台上建议借助 Go mod 安装 Pagine。 [在此](https://go.dev/dl)选择适用你平台的 Go 工具链。
+
+## CLI 用法
+
+Usage of pagine:
+- `-public` string
+ - Location of public directory. (default `/tmp/$(basename $PWD).public`)
+- `-root` string
+ - Site root. (default `$PWD`)
+- `-serve` string
+ - Specify the port to listen and serve as HTTP.
+
+
+### 生成
+
+```shell
+$ cd ~/web/my_site
+$ pagine
+Generation complete.
+```
+
+### 以 HTTP 服务器运行
+
+```shell
+$ cd ~/web/my_site
+$ pagine --serve :12450
+```
+
+文件变动被 `inotify` 捕获后,Pagine 会自动执行生成。
+
+> [!NOTE]
+> 增量生成尚未实现。
+> 建议将 `--public` 设在 `/tmp` 下以减少硬盘写入。
+
+自版本 v2.1.0,服务器提供一个 WebSocket 位于 `/ws` 的接口以提供事件监听,例如页面更新。
+
+> [!CAUTION]
+> 在公共网络暴露你的 Pagine 服务器可能是有风险的,你应该将生成的页面结果部署到静态页面服务。
+
+## 构成
+
+### 模板
+
+模板是一组页面框架(Go 模板文件)和素材(比如 SVG,样式表和脚本)。
+
+一个木板的自述文件看起来应该像: `manifest.yaml`
+```yaml
+manifest:
+ canonical: "com.symboltics.pagine.genesis" # Canonical name
+ patterns:
+ - "/*html" # Matched files will be added as template file.
+
+templates:
+ - name: "page" # Export as name `page`
+ export: "page.html" # Export `page.html`
+
+ - name: "post" # Export as name `post`
+ export: "post.html" # Export `post.html`
+```
+
+至于 Go 模板语法,见 [text/template](https://pkg.go.dev/text/template)。
+
+样例: `page.html`
+```html
+
+
+ {{ .title }}
+
+
+
+{{ template "header.html" . }}
+{{ render.ByFileExtName .content }}
+
+{{ template "footer.html" . }}
+
+```
+
+### 环境
+
+环境是对任务全过程的细节配置。
+
+```yaml
+ignore: # Pattern matching. Matched files will not be **copied** to the public/destination.
+ - "/.git*"
+
+use: # Load and set alias for the template.
+ genesis: "/templates/genesis"
+ documentor: "/templates/documentor"
+```
+
+建议通过 Git submodule 安装现有模板,例如:
+
+```shell
+$ git submodule add https://github.com/webpagine/genesis templates/genesis
+```
+
+### 层级
+
+每一“层”拥有元数据和一组将要执行的单元任务。
+
+对于目录,元数据被以表的形式储存在 `metadata.yaml`,单元任务则被储存在 `unit.yaml`。
+
+每一个模板都有其在“环境”中定义的别名作为命名空间。
+
+层级可以覆盖父层级传播的元数据。
+
+样例: `/metadata.yaml`
+```yaml
+genesis:
+ title: "Pagine"
+
+ head:
+ icon: "/favicon.ico"
+
+ nav:
+ items:
+ - name: "Documentation"
+ link: "/docs/"
+```
+
+### 单元
+
+样例: `/unit.yaml`
+```yaml
+unit:
+ - template: "genesis" # Which template to use.
+ template_key: "page" # Which the key refers to.
+ output: "/index.html" # Where to save the result.
+ define:
+ title: "Pagine" # Unit-specified metadata.
+ content: "README.md"
+
+ - template: "genesis"
+ template_key: "page"
+ output: "/404.html"
+ define:
+ title: "Page not found"
+ content: "404.md"
+```
+
+## 多阶段工作流
+
+所有路径以 `wotkflow.yaml` 所在目录为根。
+
+### 工作流
+
+工作流是并行的。
+
+示例:`workflow.yaml`
+```yaml
+stage:
+ - job:
+ - type: "tsc/v1"
+ title: "Build TypeScript"
+ path: "/script/"
+```
+
+### 阶段
+
+阶段是有序的。每个阶段有一组作业。
+
+### 作业
+
+作业是并行的。
+
+## 内置作业类型
+
+### TypeScript compiler (tsc)
+
+```yaml
+type: "tsc/v1"
+title: "Build TypeScript"
+path: "/script/"
+```
+
+确保目标机器上已经安装了 `tsc`。
+
+## 内建函数
+
+### 算术
+
+| Func | Args | Result |
+|-------|-----------|--------|
+| `add` | a, b: Int | Int |
+| `sub` | a, b: Int | Int |
+| `mul` | a, b: Int | Int |
+| `div` | a, b: Int | Int |
+| `mod` | a,b : Int | Int |
+
+### 引擎 API
+
+| Func | | Description |
+|-----------------|--------------------------------------------------------|------------------------|
+| `api.Attr` | | 以映射表形式提供有关模板、单元和服务器的信息 |
+| `api.Apply` | templateName, templateKey: String, data map[string]Any | 调用一个模板 |
+| `api.ApplyFile` | apiVer, path: String, data map[string]any | 调用单模板文件 |
+| `This` | | 模板拥有的元数据的根节点 |
+
+| api.Attr. | Description |
+|----------------|------------------------|
+| `isServing` | 若 Pagine 以服务器运行则为 true |
+| `templateBase` | 它告诉模板被存放到了哪里 |
+| `unitBase` | 模板所在层级的基目录路径 |
+
+> [!TIP]
+> `api.Attr.isServing` 可以被用来启用一些模板中的调试代码,例如页面实时更新。
+
+### 字符串处理
+
+| Func | Args | Result |
+|----------------------|-----------------------------|--------|
+| `strings.HasPrefix` | str: String, prefix: String | Bool |
+| `strings.TrimPrefix` | str: String, prefix: String | String |
+
+### 内容渲染
+
+以单元所在路径为基。
+
+| Func | Args | Description |
+|-------------------------|------------------------|---------------------|
+| `render.FileByExtName` | path: String | 据文件扩展名查询 MIME 类型并渲染 |
+| `render.FileByMimeType` | mimeType, path: String | 据给定 MIME 类型渲染文件内容 |
+
+| Format | MIME Type | File Extension Name |
+|----------|-----------------|---------------------|
+| Asciidoc | `text/asciidoc` | `adoc`, `asciidoc` |
+| Markdown | `text/markdown` | `md`, `markdown` |
+
+## 部署
+
+### 手动
+
+```shell
+$ pagine --public ../public
+```
+
+上传 `../public` 到你的服务器。
+
+### 通过 GitHub Actions 部署到 GitHub Pages(推荐)
+
+GitHub Actions 工作流配置文件内容:`.github/workflows/pagine.yml`
+```yaml
+name: Deploy
+
+on:
+ push:
+ branches:
+ - master
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install TypeScript Compiler
+ run: sudo apt install node-typescript -y
+
+ - name: Install Pagine
+ run: go install github.com/webpagine/pagine/v2/cmd/pagine@v2.4.0
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ fetch-depth: 0
+
+ - name: Setup Pages
+ id: pages
+ uses: actions/configure-pages@v4
+
+ - name: Build with Pagine
+ run: ~/go/bin/pagine --public ../public/
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: ../public/
+
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
+```
+
+## 问答
+
+### 为什么要搓另一个生成器?Hugo 不够用吗?
+
+Pagine **不是** Hugo,也不旨在替代 Hugo。
+
+明显的一点是:Pagine 不会在内容中嵌入页面配置(元数据),他们被分开而且理应分开。
+
+Pagine 不止关注 Markdown,我希望能够支持多种来源。
+
+### 我是否能够用 Pagine 来构建复杂的 Web 应用?
+
+它只能帮你摆脱关于静态内容的重复工作。
+
+如果 Pagine 与外部工具集成得好,模板则还可以继续提高生产力。
+
+所以,**这要视情况而定**。
+
+### 与外部工具互操作,比如 npx?
+
+这是可能的,但这一步应该对外部工具透明。
+
+也许需要在 Pagine 完成生成后运行 `npx`。
+
+### Logo 和命名的来源是?
+
+它**不是**浏览器引擎,**也不是**渲染引擎。
+
+Page Gen × Engine ⇒ Pagine. 与 "pagen" 发音相似。
+
+Logo 是一个带书签的打开的书本。
+
+### 以其他编程语言重写?
+
+*我料到会有人这么说*
+
+除非这样做有明显优势,这不会被采纳。
+
+因此:不。目前不在计划内。
diff --git a/docs/zh/v2.4/unit.yaml b/docs/zh/v2.4/unit.yaml
new file mode 100644
index 0000000..b0afd72
--- /dev/null
+++ b/docs/zh/v2.4/unit.yaml
@@ -0,0 +1,7 @@
+unit:
+ - template: "documentor"
+ template_key: "doc"
+ output: "/index.html"
+ define:
+ title: "Documentation"
+ content: "/README.md"
\ No newline at end of file
diff --git a/en-US/mainpage.html b/en-US/mainpage.html
index 46153b5..eea736c 100644
--- a/en-US/mainpage.html
+++ b/en-US/mainpage.html
@@ -17,7 +17,7 @@
{{ define "flip" }}
-{{ if . }} class="section-filled" style="text-align: left" {{ else }} style="text-align: right" {{ end }}
+{{ if . }} class="filled" style="text-align: left" {{ else }} style="text-align: right" {{ end }}
{{ end }}
{{ $flip := false }}
diff --git a/metadata.yaml b/metadata.yaml
index 1a8f3d1..7a944fd 100644
--- a/metadata.yaml
+++ b/metadata.yaml
@@ -10,8 +10,7 @@ genesis:
- locale: "zh-CN"
title: "简体中文"
- head:
- icon: "https://avatars.githubusercontent.com/u/168826426"
+ icon: "https://avatars.githubusercontent.com/u/168826426"
header:
logo:
@@ -84,3 +83,6 @@ genesis:
- icon: "telegram"
link: "https://t.me/webpagine"
+
+documentor:
+ icon: "https://avatars.githubusercontent.com/u/168826426"
\ No newline at end of file
diff --git a/templates/documentor b/templates/documentor
index 0e8e69c..4b87b44 160000
--- a/templates/documentor
+++ b/templates/documentor
@@ -1 +1 @@
-Subproject commit 0e8e69c268292b3cbc17e986b4235e7c0b8035a6
+Subproject commit 4b87b4433df419746cf1691132ebdb1a15c98c79
diff --git a/templates/genesis b/templates/genesis
index 1e277a9..d984423 160000
--- a/templates/genesis
+++ b/templates/genesis
@@ -1 +1 @@
-Subproject commit 1e277a90ed885350a43b4b2be3690ea96c6632d9
+Subproject commit d98442354cbd04949aa20de9e20542c82bfa49d4
diff --git a/zh-CN/mainpage.html b/zh-CN/mainpage.html
index 4f4d608..7d40106 100644
--- a/zh-CN/mainpage.html
+++ b/zh-CN/mainpage.html
@@ -17,7 +17,7 @@
{{ define "flip" }}
-{{ if . }} class="section-filled" style="text-align: left" {{ else }} style="text-align: right" {{ end }}
+{{ if . }} class="filled" style="text-align: left" {{ else }} style="text-align: right" {{ end }}
{{ end }}
{{ $flip := false }}