# 外掛貢獻說明 Voyager 的外掛系統優先支援宣告式外掛:用 `plugin.json` 描述外掛資訊與 DOM 操作,再用 CSS 描述樣式。外掛本身不執行遠端 JavaScript,而是由 Voyager 內建的外掛引擎解讀這些資料。 這讓外掛更容易審查與維護。如果你想貢獻外掛,建議先從這條路徑開始。 ## 建議流程 1. 先確認它適合做成外掛:閱讀寬度、排版修正、主題微調、隱藏或標記頁面元素、簡單的網站適配,通常都適合宣告式外掛。 2. 先在 Voyager 主倉庫提交 Issue 或 PR:說明它解決的問題、目標網站,以及和現有外掛相比的差異。 3. 使用 `plugin.json` 撰寫外掛中繼資料、匹配網站和貢獻內容。 4. 將樣式放進同目錄的 `style.css`,再由 `plugin.json` 的 `contributes.styles` 引用。 5. 本地測試後提交 PR,並附上測試頁面、截圖或錄影。維護者會依外掛成熟度決定是否進入官方 catalog。 ## 外掛粒度 外掛應該以「使用者想解決的問題」為邊界,而不是機械地按平台拆分。 如果同一個功能在多個平台上的體驗與設定大致一致,建議做成一個跨平台外掛。例如「閱讀寬度」「翻頁體驗」「程式碼區塊排版」這類功能,可以在同一個外掛裡透過多個 `matches` 覆蓋 Claude、ChatGPT 等平台。 但如果不同平台需要完全不同的設定、DOM 邏輯或使用者文案,拆成多個外掛會更清楚。不要為了「一個外掛管所有事」把無關功能硬塞在一起;一個外掛最好只解決一個明確問題。 簡單判斷: - 同一個使用者目標、同一組設定、只是網站選擇器不同:優先合併成一個外掛。 - 同一個主題但每個平台體驗差異很大:可以拆開,但名稱和說明保持關聯。 - 功能目標不同:不要合併。 ## 避免重複外掛 提交前請先看外掛市集和已有官方外掛。如果已經有一個好用的外掛,優先為它提交改進 PR,而不是再做一個類似外掛。 重複外掛只有在有明顯提升時才值得接受,例如: - 覆蓋了原外掛不支援的重要平台。 - 修復了原外掛長期無法解決的相容性問題。 - 有明顯更好的效能、可存取性或維護性。 - 提供了不同但足夠清楚的使用者體驗,而不只是換名字或微調樣式。 這樣外掛市集會更乾淨,使用者也更容易選擇。 ## 最小範例 ```json { "id": "your-name.example-plugin", "name": "Example Plugin", "version": "1.0.0", "description": "A short description of what this plugin improves.", "author": "your-name", "category": "readability", "license": "MIT", "engine": ">=1.0.0", "tier": "declarative", "matches": ["https://claude.ai/*"], "contributes": { "styles": [{ "file": "style.css" }], "domOps": [ { "op": "addClass", "target": "body", "className": "gv-plugin-example" } ] } } ``` `style.css` 可以像普通 CSS 一樣撰寫,但建議所有外掛樣式都掛在自己的 `gv-plugin-*` 類別下面: ```css .gv-plugin-example .some-target { max-width: 880px; } ``` ## Manifest 注意事項 - `id` 使用反向網域或作者前綴,例如 `your-name.reading-width`,避免和其他外掛衝突。 - `matches` 盡量收窄,只匹配外掛真正需要生效的網站。 - 同一外掛可以包含多個 `matches`,前提是這些平台共享同一個明確功能目標。 - `category` 建議使用 `render-fix`、`theme`、`layout`、`readability`、`productivity`、`integration` 或 `other`。 - `engine` 寫清楚需要的外掛引擎版本。官方外掛可參考目前目錄中的範例。 - `i18n` 推薦補齊中文、英文和其他常用語言的名稱、描述、設定項文案。 ## CSS 與資源限制 宣告式外掛會被當作不可信輸入驗證,所以請保持資源自包含: - 不要使用 `@import`。 - 不要引用外鏈圖片、外部字體或遠端 CSS。 - 可以使用普通 CSS、自訂屬性和 Voyager 提供的設定值替換。 - 類別名稱請使用 `gv-plugin-` 前綴,避免污染宿主網站或 Voyager 自身樣式。 如果外掛需要使用者設定,建議先使用數字型設定;例如閱讀寬度外掛可以用設定值寫入 CSS 變數,再由樣式消費。 ## DOM 操作邊界 目前宣告式外掛支援這些操作: - `addClass`:給目標元素添加類別名稱。 - `setAttribute`:設定屬性。 - `setStyle`:設定行內樣式或 CSS 變數。 - `hide`:隱藏目標元素。 目標可以是 CSS 選擇器,也可以使用 Voyager 網站適配器提供的語義選擇器。語義選擇器通常更穩定,但需要目前網站已有對應適配。 宣告式操作必須可撤銷、可重複執行。不要依賴一次性的頁面狀態,也不要假設頁面 DOM 永遠不變。 ## 什麼時候不適合做成普通外掛 如果功能必須執行 JavaScript、攔截請求、讀寫 Voyager 內部資料,或依賴複雜的執行期邏輯,它就不適合作為普通宣告式外掛提交。 這類功能請先開 Issue 說明需求。確實需要內建能力時,我們會考慮把它做成 Voyager 主倉庫裡的 builtin/native 外掛,例如 Formula Copy。 ## PR 前檢查 - 外掛預設關閉,使用者需要自己啟用。 - 已檢查沒有功能幾乎相同的現有外掛;如果有,優先改進現有外掛。 - 在目標網站的淺色和深色主題都測試過。 - `matches` 沒有覆蓋無關網站。 - 沒有遠端資源引用。 - 外掛目錄包含 `plugin.json`、必要的 CSS 檔案和簡短 README。 - PR 描述裡寫清楚測試頁面、截圖或錄影,以及可能影響的頁面區域。 保持簡單、克制、可撤銷。一個外掛只解決一個明確問題,通常會更容易合併和維護。