# プラグイン貢献ガイド Voyager のプラグインシステムは、宣言的なプラグインを優先します。`plugin.json` でプラグイン情報と DOM 操作を記述し、CSS で見た目を調整します。プラグイン自体はリモート JavaScript を実行せず、Voyager 内蔵のプラグインエンジンがマニフェストとスタイルを解釈します。 これにより、プラグインのレビューと保守がしやすくなります。プラグインを貢献したい場合は、まずこの方式から始めてください。 ## 推奨フロー 1. そのアイデアがプラグイン向きか確認します。読み取り幅、レイアウト修正、テーマ調整、ページ要素の非表示やマーク、簡単なサイト適配はよい候補です。 2. Voyager 本体リポジトリで Issue または PR を先に作成し、解決する問題、対象サイト、既存プラグインとの差分を説明します。 3. `plugin.json` にメタデータ、対象サイト、設定、貢献内容を書きます。 4. スタイルは同じディレクトリの `style.css` に置き、`contributes.styles` から参照します。 5. ローカルでテストし、PR にテストページ、スクリーンショット、または短い録画を添えてください。公式 catalog に入れるかどうかは成熟度を見て判断します。 ## プラグインの粒度 プラグインは「ユーザーが解決したい問題」で区切るべきで、プラットフォームごとに機械的に分割する必要はありません。 同じ機能が複数プラットフォームでほぼ同じ体験と設定を持つなら、クロスプラットフォームの 1 つのプラグインを推奨します。たとえば「読み取り幅」「ページ送り体験」「コードブロックのレイアウト」は、複数の `matches` で Claude、ChatGPT などをカバーできます。 一方、プラットフォームごとに設定、DOM ロジック、ユーザー向け文言が大きく違う場合は、分けたほうが明確です。「全部入り」にするために無関係な機能を詰め込まないでください。1 つのプラグインは 1 つの明確な問題を解くのが理想です。 簡単な判断基準: - 同じユーザー目標、同じ設定、違うのはセレクタだけ:1 つのプラグインを優先。 - 同じテーマだが各プラットフォームの体験が大きく違う:分割してもよいが、名前と説明に関連性を持たせる。 - 機能目標が違う:統合しない。 ## 重複プラグインを避ける 提出前にプラグインマーケットと既存の公式プラグインを確認してください。すでによいプラグインがある場合は、似たものを新しく作るより、そのプラグインを改善する 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` はできるだけ狭くし、本当に必要なサイトだけに一致させます。 - 複数のプラットフォームが 1 つの明確な機能目標を共有している場合、1 つのプラグインに複数の `matches` を含められます。 - `category` は `render-fix`、`theme`、`layout`、`readability`、`productivity`、`integration`、`other` を推奨します。 - 必要なプラグインエンジンのバージョンを `engine` に明記します。公式プラグインを参考にできます。 - `i18n` には中国語、英語、その他よく使われる言語の名前、説明、設定文言をできるだけ追加してください。 ## CSS とリソース制限 宣言的プラグインは信頼されていない入力として検証されるため、リソースは自己完結にしてください。 - `@import` を使わない。 - リモート画像、外部フォント、リモート CSS を参照しない。 - 通常の CSS、カスタムプロパティ、Voyager が提供する設定値の置換は使用できます。 - クラス名には `gv-plugin-` プレフィックスを使い、ホストサイトや Voyager 本体のスタイルを汚染しないようにします。 設定が必要な場合は、まず数値設定から始めるのがおすすめです。たとえば読み取り幅プラグインは、設定値を CSS 変数に書き込み、その変数を CSS 側で使えます。 ## DOM 操作の範囲 現在の宣言的プラグインは次の操作をサポートします。 - `addClass`:対象要素にクラスを追加する。 - `setAttribute`:属性を設定する。 - `setStyle`:インラインスタイルまたは CSS 変数を設定する。 - `hide`:対象要素を非表示にする。 対象は CSS セレクタ、または Voyager のサイトアダプタが提供する意味的セレクタを使えます。意味的セレクタはより安定しますが、対象サイトに対応アダプタが必要です。 宣言的操作は、取り消し可能で、何度実行しても安全である必要があります。一度きりのページ状態に依存せず、DOM が永遠に変わらないとも仮定しないでください。 ## 通常プラグインに向かない場合 JavaScript の実行、リクエストの遮断、Voyager 内部データの読み書き、複雑な実行時ロジックが必要な機能は、通常の宣言的プラグインには向きません。 その場合はまず Issue を開いて要件を説明してください。本当に内蔵能力が必要な場合は、Formula Copy のような builtin/native プラグインとして Voyager 本体に実装することを検討します。 ## PR 前チェック - プラグインはデフォルトで無効で、ユーザーが自分で有効化する。 - ほぼ同じ既存プラグインがないか確認した。ある場合は既存プラグインの改善を優先した。 - 対象サイトのライトテーマとダークテーマでテストした。 - `matches` が無関係なサイトを含んでいない。 - リモートリソースを参照していない。 - プラグインディレクトリに `plugin.json`、必要な CSS ファイル、短い README がある。 - PR でテストページ、スクリーンショットまたは録画、影響を受けるページ領域を説明している。 シンプルで、控えめで、取り消し可能にしてください。1 つの明確な問題を解くプラグインほど、マージと保守がしやすくなります。