版本: 2.7 maintainability docs
日期: 2026-05-20
專案路徑: Webcoding-main/
WebPad++ 是一個本機優先的瀏覽器工具箱,功能涵蓋程式碼編輯、文件處理、OCR、QR、SEO 與離線/分析版發佈流程。它沒有自建文件處理後端;多數文件處理在瀏覽器內完成,但依照發佈模式仍可能載入 Google Analytics、CDN 備援、OCR 語言資料或其他第三方資源。
新維護者請先照這個順序讀:
| 順序 | 文件 | 用途 |
|---|---|---|
| 1 | SYSTEM_DOC.md |
專案總覽、模組地圖、載入順序與高風險區域。 |
| 2 | docs/MAINTAINERS_GUIDE.md |
日常修改流程、功能新增規則、提交前檢查。 |
| 3 | docs/ARCHITECTURE_MAP.md |
Runtime 架構圖、事件流、資料流與發佈流。 |
| 4 | docs/DEPENDENCY_MANAGER.md |
第三方套件載入規則與本地優先設定。 |
| 5 | docs/CENTRALIZED_EVENTS.md |
UI 事件綁定規則,避免回到 inline handler。 |
| 6 | docs/NAMESPACE_REFACTOR.md |
WebcodingApp 命名空間與舊全域函式相容層。 |
| 7 | docs/TESTING.md |
Smoke test、語法檢查、文件稽核與手動測試。 |
| 8 | docs/TROUBLESHOOTING.md |
QR、OCR、PDF、離線版、GA、套件載入常見問題。 |
| 9 | docs/RELEASE_CHECKLIST.md |
發佈前檢查清單。 |
| 10 | docs/PRIVACY_AND_LIMITATIONS.md |
對外隱私與離線說法邊界。 |
維護原則:不要為了快速修一個按鈕,把依賴載入、事件綁定、命名空間規則繞過去。 這個專案之前的主要故障多半不是演算法本身,而是載入順序、CDN 缺檔、裸露全域函式與文件過度宣稱造成的。
WebPad++ 是一個瀏覽器內的工具箱,主要使用情境:
- 程式碼與文字檔編輯。
- Markdown / HTML 預覽與視覺化編輯。
- PDF / DOCX / ODT / XLSX / CSV 等文件開啟、轉換與匯出輔助。
- 免費瀏覽器端 OCR,特別強化繁體中文圖片前處理。
- QR Code 產生、圖片解碼與相機掃描。
- Sitemap、robots.txt 與 HTML SEO 檢查。
- 本地優先與發佈版建置流程。
對外描述請使用:
- 「本機優先」
- 「沒有自建後端處理使用者文件」
- 「可建立嚴格離線發佈版,但需補齊 vendor 與 OCR 語言資料」
- 「可建立保留 Google Analytics 的公開部署版」
避免寫成:
- 使用者資料不會接觸任何第三方。
- 任一版本都不需網路。
- OCR 準確度可等同付費雲端 OCR。
- 大型文件或 OCR 可保證即時完成。
這些說法會與目前架構不一致,也會被 npm run docs:audit 擋下部分高風險語句。
Webcoding-main/
├── index.html # 主要 UI 與 classic script 載入順序
├── css/
│ ├── style.css # 主要樣式
│ └── offline-fallback.css # 離線/本地發佈版替代 Tailwind runtime 的基本樣式
├── js/
│ ├── core/
│ │ ├── app.js # WebcodingApp 命名空間與舊全域相容層
│ │ ├── loader.js # 本地優先 dependency manager
│ │ ├── events.js # data-* 集中事件處理
│ │ ├── tabs.js # 分頁狀態與 IndexedDB 儲存
│ │ ├── ui.js # 共用 UI、toast、reset 等
│ │ ├── save.js # 儲存/另存/下載流程
│ │ ├── filesystem.js # 虛擬檔案系統
│ │ └── fileio/
│ │ ├── constants.js # 檔案大小與二進位副檔名常數
│ │ ├── open.js # 開檔、開資料夾、副檔名路由
│ │ ├── templates.js # 新檔模板、Camera to Text、匯出捷徑
│ │ └── dnd.js # 拖放匯入
│ ├── features/
│ │ ├── visual.js # HTML 視覺化編輯模式
│ │ ├── panel.js # 底部/工具面板
│ │ ├── compare.js # 差異比對
│ │ ├── format.js # 格式化、重新命名、QR modal 入口
│ │ └── sidebar.js # 側欄互動
│ ├── tools/
│ │ ├── docutils.js # 文件工具共用方法
│ │ ├── spreadsheet.js # XLSX / XLS / CSV
│ │ ├── docx.js # DOCX / ODT
│ │ ├── pdf.js # PDF 讀取與匯出
│ │ ├── image-actions.js # 圖片進入 OCR / QR 的分流 UI
│ │ ├── qr.js # QR 產生、解碼、相機掃描
│ │ ├── ocr-engine.js # Tesseract、圖片前處理、辨識評分
│ │ ├── ocr.js # OCR UI 與相機/上傳/貼上流程
│ │ ├── seo-core.js # SEO modal 與共用 UI
│ │ ├── sitemap-utils.js # URL / XML / sitemap 共用工具
│ │ ├── sitemap-crawler.js # 外部網站探索
│ │ ├── sitemap.js # Sitemap / robots.txt UI
│ │ └── seo-audit.js # HTML SEO 診斷
│ ├── editor.js # CodeMirror 初始化與主入口
│ ├── i18n.js # i18next 初始化
│ └── recent.js # 最近開啟項目
├── libs/ # 本地核心套件與 vendor 目錄
│ ├── vendor/ # 由 vendor:fetch 補齊的第三方套件
│ └── tessdata/ # OCR 語言資料本地路徑說明
├── scripts/ # 測試、稽核、vendor、發佈腳本
├── tests/smoke/ # 無外部套件 smoke test
├── docs/ # 維護文件
├── dist/ # build:offline 產出的發佈資料夾
├── README.md
├── package.json
└── SYSTEM_DOC.md
index.html 使用 classic script,不是 bundler;因此載入順序就是依賴圖的一部分。
1. 基礎 CSS / 本地或外部啟動套件
2. js/core/app.js
3. js/core/loader.js
4. js/core/events.js
5. js/core/tabs.js, ui.js, save.js
6. js/core/fileio/constants.js → open.js → templates.js → dnd.js
7. js/features/visual.js → panel.js → compare.js → format.js
8. js/tools/seo-core.js → sitemap-utils.js → sitemap-crawler.js → sitemap.js → seo-audit.js
9. js/recent.js → js/i18n.js → js/core/filesystem.js → js/features/sidebar.js
10. js/tools/docutils.js → spreadsheet.js → docx.js → pdf.js → image-actions.js → qr.js → ocr-engine.js → ocr.js
11. js/editor.js
app.js必須早於會 expose namespace 的任何模組。loader.js必須早於需要ensureDependency()的工具模組。events.js必須早於使用者互動,但不需要早於所有 handler 定義;它會在點擊時動態 resolve。fileio/constants.js必須早於open.js與dnd.js。docutils.js必須早於spreadsheet.js、docx.js、pdf.js。seo-core.js必須早於 sitemap 與 audit 工具。qr.js必須早於ocr.js,因為圖片貼上/上傳會依 modal 狀態分流。editor.js保持最後載入,避免初始化時工具或核心狀態尚未就緒。
用途:統一管理重型或選用套件,避免每個功能各自載 CDN。
基本用法:
const ok = await window.ensureDependency('pdfjs', {
message: '載入 PDF 讀取引擎中...',
errorMessage: 'PDF 讀取引擎載入失敗'
});
if (!ok) return;新增第三方套件時:
- 在
loader.js使用defineDependency()註冊。 - 同時加到
scripts/vendor-dependencies.json。 - 更新
docs/DEPENDENCY_MANAGER.md與docs/LOCAL_FIRST_DEPENDENCIES.md。 - 執行
npm run vendor:audit。 - 若要嚴格離線發佈,執行
npm run vendor:audit:strict。
用途:所有主要 UI 操作改用 data-* 綁定,不回到 inline handler。
正確:
<button data-action="call" data-call="tools.qr.generate">產生 QR</button>避免:
<button onclick="generateQrCode()">產生 QR</button>新增 UI 按鈕時:
- HTML 寫
data-action="call"。 data-call使用命名空間路徑,例如tools.ocr.startRecognition。- 如果需要參數,使用
data-args='["value"]'。 - 如果需要事件物件,使用
data-pass-event="true"。 - 執行
npm test,確認 HTML event audit 通過。
用途:WebcodingApp 是正式命名空間;舊的 window.xxx 只作為相容層。
新增功能請使用:
WebcodingApp.namespace.expose('tools.example.run', runExample, {
legacyName: 'runExample' // 只有舊程式仍需要時才加
});UI 呼叫:
<button data-action="call" data-call="tools.example.run">Run</button>避免新增:
window.runExample = runExample;使用者選擇/拖放檔案
↓
core/fileio/open.js 或 dnd.js
↓
loadFileContent(file)
↓
依副檔名分流:
.pdf → tools/pdf.js + pdfjs
.docx → tools/docx.js + mammoth
.odt → tools/docx.js + jszip
.xlsx/.xls/.csv → tools/spreadsheet.js + xlsx
image → tools/image-actions.js → OCR 或 QR
other → TextDecoder → editor/tab
UI data-call="tools.qr.generate" / upload / camera
↓
events.js resolve callable
↓
tools/qr.js
↓
ensureDependency('qr') 或 ensureDependency('jsqr')
↓
qrcodejs 產生 / jsQR 解碼
UI 上傳/拍照/貼上圖片
↓
tools/ocr.js
↓
tools/ocr-engine.js
↓
ensureDependency('tesseract')
↓
圖片前處理 → Tesseract 辨識 → 中文友善評分 → 結果清理
TabManager
└── IndexedDB/localForage: webpad_tabs_v2
FileSystem
└── IndexedDB/localForage: webpad_fs_v1
Language preference
└── localStorage: webpad_lang
| 模式 | 指令 | 用途 | 注意事項 |
|---|---|---|---|
| 開發/一般網頁版 | 直接開 index.html 或本機 server |
最容易測試 | 可能使用 CDN 備援與 GA。 |
| 本地優先資產準備 | npm run vendor:fetch |
下載免費 vendor 檔 | 需有網路;完成後跑 vendor:audit。 |
| 無分析發佈版 | npm run build:offline |
敏感或需避免追蹤的發佈包 | 仍需補齊 vendor 與 OCR 語言資料後再做嚴格檢查。 |
| 保留 GA 發佈版 | npm run build:offline:analytics |
公開部署、需要流量追蹤 | 會連 Google Analytics;不應標示為無第三方請求。 |
| 嚴格檢查 | npm run offline:audit:strict |
確認無分析發佈版缺檔狀態 | 缺 vendor 或 tessdata 時會失敗。 |
| GA 版嚴格檢查 | npm run offline:audit:analytics:strict |
確認 GA 版只保留允許的外部請求 | Google Analytics 是刻意保留。 |
- 先讀對應文件:
docs/TROUBLESHOOTING.md與docs/DEPENDENCY_MANAGER.md。 - 確認功能是否需要第三方套件。
- 不要直接新增
<script src="https://...">到功能模組。 - 改用
ensureDependency()。 - 如果牽涉 UI,改
data-call與 namespace,不用 inline handler。 - 跑:
npm test
npm run test:syntax- 用真實檔案手動測一次。
- 新檔放在
js/tools/,若是核心狀態才放js/core/。 - 使用 IIFE 包住,避免洩漏區域變數。
- 對外入口用
WebcodingApp.namespace.expose()。 - UI 綁定使用
data-action/data-call。 - 第三方依賴加到
loader.js與vendor-dependencies.json。 - 更新對應 docs。
- 跑 smoke test。
- 避免過度承諾隱私、離線與速度。
- 跑:
npm run docs:audit- 若修改發佈模式,更新:
README.mdSYSTEM_DOC.mddocs/PRIVACY_AND_LIMITATIONS.mddocs/OFFLINE_RELEASE.mddocs/RELEASE_CHECKLIST.md
日常修改後至少跑:
npm test
npm run test:syntax
npm run docs:audit新增或升級第三方套件後跑:
npm run vendor:audit準備嚴格離線發佈前跑:
npm run vendor:fetch
npm run build:offline
npm run offline:audit:strict準備保留 GA 的公開發佈版前跑:
npm run vendor:fetch
npm run build:offline:analytics
npm run offline:audit:analytics:strictSmoke test 不取代瀏覽器實測。相機、OCR 準確度、檔案選擇器、拖放、實際 CDN 或 GA 請求仍需手動驗證。
- 不要重新宣告
MAX_FILE_SIZE;只在js/core/fileio/constants.js修改。 - 不要還原舊版大型檔並與拆分後模組同時載入。
- 不要在
index.html新增功能型onclick、onchange、ondrop等 inline handler。 - 不要新增裸露全域函式;使用
WebcodingApp.namespace.expose()。 - 不要直接在工具模組硬塞 CDN script;使用 dependency manager。
- 不要把 GA 版說成沒有第三方請求;它就是會連 Google Analytics。
- 不要把免費瀏覽器 OCR 包裝成專業級文件辨識。
- 不要只改
dist/內檔案;dist/由 build 腳本產生,源頭應改根目錄與docs/。 - 升級 vendor 後要同步更新
scripts/vendor-dependencies.json與文件。 - 改動載入順序時,一定要跑
npm test,因為 classic script 順序會直接影響 runtime。
# 全部 smoke test
npm test
# JS 語法檢查
npm run test:syntax
# 文件宣稱稽核
npm run docs:audit
# 檢查本地優先 vendor 設定
npm run vendor:audit
# 下載免費 vendor 檔
npm run vendor:fetch
# 嚴格檢查 vendor 是否補齊
npm run vendor:audit:strict
# 建立無分析發佈版
npm run build:offline
# 建立保留 Google Analytics 的發佈版
npm run build:offline:analytics
# 檢查無分析發佈版
npm run offline:audit
npm run offline:audit:strict
# 檢查 GA 發佈版
npm run offline:audit:analytics
npm run offline:audit:analytics:strictSYSTEM_DOC.md是總入口,保持精簡但要能帶路。- 新功能應在
docs/MAINTAINERS_GUIDE.md加入修改流程,或在對應專題文件補充。 - 發佈模式與隱私邊界改變時,必須同步更新
README.md與docs/PRIVACY_AND_LIMITATIONS.md。 - 測試指令改變時,必須同步更新
docs/TESTING.md與docs/RELEASE_CHECKLIST.md。 - 若文件內容會影響對外信任,請先跑
npm run docs:audit。