Files
html-transform/README.md
T
2026-06-08 11:53:46 +08:00

420 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## HTML Transform
HTML Transform 是 prototype evidence 工具。現行 MVP 只做兩件事:
- `doctor`:檢查執行 `scan` 需要的前置條件。
- `scan`:讀取 HTML prototype、prototype guide 與 backend API docs,產生瀏覽器證據、頁面級 UI Contract 與 implementation contract。
- `app-map.json`:推論每個 prototype 的頁面角色、layout 使用策略、API 對應、維護頁建議範本,並用 `prototype/*.md` 的人工 domain guide 輔助補上舊系統對照。
不提供 `plan``run``diff``verify``go``status`。這些舊骨架已移除,避免把尚未完成的自動化流程誤認成可用功能。
## MVP 範圍
`scan` 會執行:
```text
Stage 1 Capture
Stage 3-lite Page Contract
Stage 4-lite Contract Validation
API Catalog
Maintenance Contract
```
Stage 2 decomposition 不執行。現有 prototype 主要是後台系統頁面,重點是表單、查詢條件、表格、actions 與資訊架構;切 region screenshot 對 MVP 價值不高。
目前沒有 Codex slash command。也就是說,在 repo 根目錄輸入 `/scan` 不會自動執行本工具。
## 指令
`packages/html-transform` 目錄內:
```bash
node src/cli.js doctor
node src/cli.js scan
```
在 repo 根目錄:
```bash
node packages/html-transform/src/cli.js doctor
node packages/html-transform/src/cli.js scan
```
若要在根目錄用簡短指令,建議由根目錄 `package.json` 包一層:
```json
{
"scripts": {
"scan": "node packages/html-transform/src/cli.js doctor && node packages/html-transform/src/cli.js scan"
}
}
```
之後即可執行:
```bash
pnpm scan
```
## 前置需求
需要 Node.js 20 以上。
```bash
node --version
pnpm --version
```
安裝相依套件:
```bash
pnpm install
```
[playwright](https://playwright.dev/agent-cli/installation)
確認 `playwright-cli` 可用:
```bash
pnpm --filter html-transform exec playwright-cli --version
```
若環境還沒有 Chromium
```bash
HOME=/tmp \
XDG_CACHE_HOME=/tmp \
PLAYWRIGHT_DAEMON_SESSION_DIR=/tmp/ms-playwright/daemon \
pnpm --filter html-transform exec playwright-cli install-browser chromium
```
若是在受限制環境中執行(例如 home directory 唯讀、sandbox 不允許寫入 `~/.cache`),建議同時指定:
```bash
HOME=/tmp
XDG_CACHE_HOME=/tmp
PLAYWRIGHT_DAEMON_SESSION_DIR=/tmp/ms-playwright/daemon
PLAYWRIGHT_BROWSERS_PATH=/tmp/ms-playwright
```
這樣 Playwright 的 browser、cache 與 daemon session 都會寫到可寫目錄。
## 設定檔
設定檔不是工具執行的絕對必要條件;沒有設定檔時,工具會使用內建預設並讀取:
```text
packages/prototype/
```
本 repo 的 HTML prototype 位於根目錄 `./prototype`,不是 `./packages/prototype`。因此從 repo 根目錄執行 `node packages/html-transform/src/cli.js scan` 時,需要根目錄 `ht.config.mjs` 覆寫 `prototype` 路徑。
本 repo 根目錄目前使用最小設定:
```js
export default {
prototype: "./prototype",
};
```
`scan` 目前使用:
- `prototype`HTML prototype 與 `prototype/*.md` domain guide 來源。
- `backendDocs`backend API markdown / OpenAPI JSON/YAML docs 來源,預設 `./apps/backend`
本 repo 的 `backendDocs` 使用預設值即可。若其他專案的 backend docs 不在 `./apps/backend`,可明確指定:
```js
export default {
prototype: "./prototype",
backendDocs: "./docs/backend",
};
```
若要同時讀取多個 backend docs 來源,或混用 markdown 與 OpenAPI JSON/YAML,可使用陣列:
```js
export default {
prototype: "./prototype",
backendDocs: ["./apps/backend", "./docs/openapi"],
};
```
若只有 prototype、沒有 backend docs,可只指定 prototype
```js
export default {
prototype: "./prototype",
};
```
`backendDocs` 目錄不存在或沒有 markdown/OpenAPI 文件,`scan` 仍會完成,只是 `.ht/api-catalog.json` 會沒有 endpoints,頁面 spec 的 `apiContract.endpoints` 也會是空陣列。
`frontend``backend``output``plan` 等欄位不會被 `doctor``scan` 使用,不需要為本 MVP 加入設定檔。
## 本 repo 實際執行
這個 monorepo 目前要能穩定跑 `scan`,至少需要處理三件事:
1. 根目錄 `ht.config.mjs` 將 prototype 指到 `./prototype`
2. Playwright Chromium 已安裝
3. 若根目錄 `.playwright/cli.config.json` 有指定 `channel`,需避免 `scan` 誤走系統 Chrome
目前本 repo 的最小設定是:
```js
export default {
prototype: "./prototype",
};
```
若根目錄 `.playwright/cli.config.json` 類似:
```json
{
"browser": {
"browserName": "chromium",
"launchOptions": {
"channel": "chromium"
}
}
}
```
`scan` 可能會失敗,並出現類似:
```text
Chromium distribution 'chrome' is not found at /opt/google/chrome/chrome
```
原因是 `html-transform` 會在 `.ht/cache/playwright-cli` 底下呼叫 `playwright-cli`。在這種情況下,可在該工作目錄放一份最小覆寫設定:
```text
.ht/cache/playwright-cli/.playwright/cli.config.json
```
內容:
```json
{
"browser": {
"browserName": "chromium"
}
}
```
在這個 repo 內,實際可重現的流程如下。
1. 確認設定與 CLI
```bash
pnpm --filter html-transform exec playwright-cli --version
HOME=/tmp \
XDG_CACHE_HOME=/tmp \
PLAYWRIGHT_DAEMON_SESSION_DIR=/tmp/ms-playwright/daemon \
PLAYWRIGHT_BROWSERS_PATH=/tmp/ms-playwright \
node packages/html-transform/src/cli.js doctor
```
2. 安裝 Chromium
```bash
HOME=/tmp \
XDG_CACHE_HOME=/tmp \
PLAYWRIGHT_DAEMON_SESSION_DIR=/tmp/ms-playwright/daemon \
PLAYWRIGHT_BROWSERS_PATH=/tmp/ms-playwright \
pnpm --filter html-transform exec playwright-cli install-browser chromium
```
3. 準備 Playwright CLI 的本地覆寫設定(只有在根目錄 `.playwright/cli.config.json``channel` 時需要):
```bash
mkdir -p .ht/cache/playwright-cli/.playwright
printf '%s\n' '{' ' "browser": {' ' "browserName": "chromium"' ' }' '}' > .ht/cache/playwright-cli/.playwright/cli.config.json
```
4. 執行 scan
```bash
HOME=/tmp \
XDG_CACHE_HOME=/tmp \
PLAYWRIGHT_DAEMON_SESSION_DIR=/tmp/ms-playwright/daemon \
PLAYWRIGHT_BROWSERS_PATH=/tmp/ms-playwright \
node packages/html-transform/src/cli.js scan
```
在受限制 sandbox 中,`scan` 可能因為 Vite 無法綁定本機 port、或 Chromium 啟動時的系統呼叫受限而失敗。這種情況下,需要在不受 sandbox 限制的 shell 執行上面的 `scan` 指令。
## Doctor
```bash
node packages/html-transform/src/cli.js doctor
```
檢查項目:
- `prototype` directory
- package-local `vite`
- `playwright-cli`
- `pnpm`
## Scan
```bash
node packages/html-transform/src/cli.js scan
```
在本 repo 的受限制環境中,建議實際使用:
```bash
HOME=/tmp \
XDG_CACHE_HOME=/tmp \
PLAYWRIGHT_DAEMON_SESSION_DIR=/tmp/ms-playwright/daemon \
PLAYWRIGHT_BROWSERS_PATH=/tmp/ms-playwright \
node packages/html-transform/src/cli.js scan
```
`scan` 會自動:
- 用 Vite static server 提供 prototype。
-`playwright-cli` 開啟每個 HTML。
- 等待 `networkidle`,再等待 500ms。
- 截取 desktop `1440 x 900` full-page screenshot。
- 產生 DOM summary。
- 產生 accessibility snapshot。
- 記錄 resource failure 與 console error/warning。
- 建立頁面級 `pageContract`
- 驗證 contract 與 DOM evidence 是否明顯衝突。
- 讀取 `prototype/*.md` 的對照表與 checklist,擷取 prototype 檔、舊 JSP、舊 PB、對應 Vue view、功能描述與人工 checklist。
- 讀取 `prototype/*.md` 的 legacy flow code block,產出可對照每個 prototype 的 `flowRefs`,避免 prompt 需要硬編特定 domain 的 JSP 流程知識。
- 讀取 backend API markdown docs,建立 endpoint catalog、schema 摘要、欄位規則與錯誤格式。
- 依 prototype evidence、guide 與 API catalog 建立 `apiContract`
- 依頁面 evidence 建立 `maintenanceContract`,推論頁面型態、操作能力、row action 啟用條件與 checklist 衍生的 business rules。
- 產出 `.ht/app-map.json`,供通用 prompt 判斷 auth、legacy shell、feature page、layout 策略、API 對應與舊系統對照。
## 產物
每個 HTML 的 capture artifact
```text
.ht/cache/prototype/{page}/desktop-default.png
.ht/cache/prototype/{page}/dom-summary.json
.ht/cache/prototype/{page}/accessibility-tree.json
.ht/cache/prototype/{page}/capture-metadata.json
```
每個 HTML 的 contract artifact
```text
.ht/api-catalog.json
.ht/app-map.json
.ht/spec/{page}.spec.json
.ht/spec/{page}.validation.json
```
`.ht/api-catalog.json` 是跨頁面的 backend API catalog,來源是 `backendDocs` 目錄下的 markdown 文件。它會包含:
- `endpoints`
- `schemas`
- `fieldRules`
- `errorContract`
`.spec.json` 會包含:
- `pageContract`:頁面文字、欄位、表格、actions、layout evidence 與 Vuetify checklist。
- `captureArtifacts`screenshot、DOM summary、accessibility tree 與 capture metadata 的可追溯路徑。
- `browserEvidence`:瀏覽器 resource failure 與 console warning/error。
- `apiContract`:與該頁匹配的 API endpoints、用途分類、rejected candidates 與錯誤格式。
- `prototypeGuide`:該 prototype 對應的人工 guide、舊 JSP/PB、target view 與 checklist。
- `prototypeGuide.flowRefs`:從 guide 的 legacy flow code block 比對出的相關流程節點,包含 menu、task、nodeType、JSP、PB、動作與原始流程行。
- `maintenanceContract`:頁面型態、capabilities、data model、row actions、business rules 與 warnings。
- `bddContract`:以頁面 evidence 產生的 Gherkin 草稿、scenario evidence trace 與人工 review warnings。
- `regions`:目前仍保留,目的是相容既有資料形狀;不要把它視為 Stage 2 decomposition。
`.ht/app-map.json` 是跨頁面的應用結構推論。通用 prompt 應先讀它,再決定每個 prototype 是 `auth``legacy-shell-reference``feature-page` 或其他角色。MVP 固定策略是 template layout/style 優先,prototype 只提供內容與功能證據。
route 也會包含 implementation hints,例如:
```json
{
"prototype": "venue/applications-list.html",
"kind": "feature-page",
"pageKind": "maintenance",
"primaryEntity": "ApplicationsList",
"capabilities": ["back", "search", "edit", "delete", "print"],
"apiCount": 8
}
```
`prototype/*.md` 內有 markdown table 對照 prototype HTML,例如 `venue/query-room.html``scan` 會把匹配結果寫進 route
```json
{
"prototype": "venue/query-room.html",
"guide": {
"source": "venue.md",
"legacyJsp": "zte_pro/zte451_02.jsp + zte451_02_1.jsp",
"legacyPb": "n_zte451.of_zte451_02 / of_zte451_02_1",
"targetView": "RoomQueryView.vue",
"description": null,
"checklist": []
},
"evidence": {
"prototypeGuide": "venue.md",
"apiCount": 2
},
"guide": {
"flowRefs": [
{
"tasks": ["場地查詢"],
"matchedKeys": ["zte451_02.jsp", "zte451_02_1.jsp"],
"nodes": [
{
"task": "場地查詢",
"nodeType": "query",
"jsp": ["zte451_02.jsp"],
"pb": ["of_zte451_02"]
}
]
}
]
}
}
```
這些 guide 欄位輔助 route、舊系統對照與 checklist 理解;HTML capture、DOM summary、UI contract 與 screenshot 仍是畫面內容的主要 evidence。API catalog 與 `apiContract` 則用來降低 endpoint、DTO 與欄位規則的猜測。
## 使用方式是否改變
CLI 使用方式沒有改,仍然是:
```bash
node packages/html-transform/src/cli.js doctor
node packages/html-transform/src/cli.js scan
```
有改變的是 `scan` 的輸入與輸出:
- 新增可選輸入:`backendDocs`,預設 `./apps/backend`
- 新增輸出:`.ht/api-catalog.json`
- `.ht/spec/{page}.spec.json` 新增 `apiContract``prototypeGuide``maintenanceContract`
- `.ht/app-map.json` route 新增 `pageKind``capabilities``primaryEntity``apiCount`
因此既有 `doctor` / `scan` 指令不用改;但使用 `.ht` 產物的 prompt 或下游工具,應改讀新增欄位。
## 產物中的路徑
`.spec.json``source``screenshot``domSummary``accessibilityTree``metadata` 等欄位使用絕對路徑,而非相對路徑。這是 scan pipeline 的自然結果:`config.prototypeDir``config.htDir` 都以 `path.resolve(cwd, ...)` 轉為絕對路徑,後續 `listFiles``path.join` 產出的路徑字串均繼承絕對形式,不做 `path.relative` 轉換。
因為 `.ht/` 目錄已由 `.gitignore` 排除,這些檔案不會進入版本控制,每個開發者在自己機器上跑 `scan` 會重新生成,路徑自然指向自己的專案目錄,因此不影響可攜性。
## 驗證
修改本 package 後至少執行:
```bash
pnpm --filter html-transform typecheck
pnpm --filter html-transform test
HOME=/tmp XDG_CACHE_HOME=/tmp PLAYWRIGHT_DAEMON_SESSION_DIR=/tmp/ms-playwright/daemon PLAYWRIGHT_BROWSERS_PATH=/tmp/ms-playwright node packages/html-transform/src/cli.js doctor
HOME=/tmp XDG_CACHE_HOME=/tmp PLAYWRIGHT_DAEMON_SESSION_DIR=/tmp/ms-playwright/daemon PLAYWRIGHT_BROWSERS_PATH=/tmp/ms-playwright node packages/html-transform/src/cli.js scan
```