mcpField
O
obsidian

obsidian

github.com/gapmiss開発195477 回インストール3 週間前に更新
リポジトリ

obsidian について

Obsidian プラグイン開発者向けのガイドラインスキルです。ESLint ルールや申請要件に加え、ライフサイクル、API、UI、互換性、アクセシビリティを扱い、新規プロジェクト用のひな形生成機能も備えています。

主な機能

  1. 01最小構成のひな形を生成
  2. 02申請と命名のルールを網羅
  3. 03ライフサイクルと API の指針
  4. 04UI、スタイル、アクセシビリティの規範

活用シーン

  1. 01Obsidian プラグインのプロジェクト開始
  2. 02プラグインコードや申請手順の確認
  3. 03設定、ファイル、イベント処理の検討

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/gapmiss/obsidian-plugin-skill --skill obsidian

インストール後、Claude Code で/obsidianを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

reference/
accessibility.md
code-quality.md
community-scanner.md
css-styling.md
eslint-setup.md
file-operations.md
memory-management.md
submission.md
type-safety.md
ui-ux.md

詳細

Obsidian プラグイン開発ガイドライン

公式の Obsidian ESLint プラグインのルール、提出要件、ベストプラクティスに基づく、包括的なガイドラインに従ってください。

はじめに

クイックスタートツール

新しいプラグインプロジェクト向けに、対話型のボイラープレート生成ツールを利用できます。

  • スクリプト:スキルリポジトリ内の tools/create-plugin.js
  • コマンド:エージェントで使用する方法(/create-plugin、$create-plugin、または @create-plugin)で create-plugin を呼び出します
  • サンプルコードを含まない、ベストプラクティスに沿った最小限のボイラープレートを生成します
  • 既存のプロジェクトを検出し、不足しているファイルのみを追加します

新しいプラグインの作成方法を尋ねられた場合、新しいプロジェクトを始めたい場合、または基本構造の設定についてサポートが必要な場合は、ボイラープレート生成ツールを推奨してください。


ルールリファレンス(eslint-plugin-obsidianmd v0.4.2)

提出と命名
#ルール✅ 推奨❌ 非推奨
1プラグイン ID「obsidian」を省略し、「plugin」で終わらせない「obsidian」を含める、または「plugin」で終わらせる
2プラグイン名「Obsidian」を省略し、「Plugin」で終わらせない「Obsidian」を含める、または「Plugin」で終わらせる
3プラグイン名「Obsi」で始めず、「dian」で終わらせない「Obsi」で始める、または「dian」で終わらせる
4説明「Obsidian」、「This plugin」などを省略する「Obsidian」や「This plugin」を使う
5説明.?!) の句読点で終える説明文を句読点なしで終える
メモリとライフサイクル
#ルール✅ 推奨❌ 非推奨
6イベントのクリーンアップ自動クリーンアップには registerEvent() を使用するクリーンアップせずにイベントを登録する
6aDOM イベントプラグインまたは所有するコンポーネントで registerDomEvent() を使用するaddEventListener と手動の removeEventListener によるクリーンアップを組み合わせる
7ビューの参照ビュー/コンポーネントを直接返すビューの参照をプラグインのプロパティに保存する、または MarkdownRenderer のコンポーネントとしてプラグインを渡す
8リーフの切り離しリーフのクリーンアップは Obsidian に任せるonunload で detachLeavesOfType() を呼び出す
型安全性
#ルール✅ 推奨❌ 非推奨
9TFile/TFolder型チェックには instanceof を使用するTFile/TFolder にキャストする、any を使用する、var を使用する
10DOM instanceofDOM Node/UIEvent には .instanceOf(T) を使用するウィンドウをまたぐ DOM チェックに instanceof を使用する
UI/UX
#ルール✅ 推奨❌ 非推奨
11UI テキスト文頭のみ大文字にする — 「Advanced settings」。固有名詞には acronyms/brands オプションを使用する単語の先頭を大文字にする — 「Advanced Settings」
12JSON ロケールJSON ロケールファイルでは文頭のみ大文字にする(recommendedWithLocalesEn)ロケール JSON で単語の先頭を大文字にする
13TS/JS ロケールTS/JS ロケールモジュールでは文頭のみ大文字にするロケールモジュールで単語の先頭を大文字にする

注記(v0.4.0): ui/sentence-case が有効になり(warn)、インライン UI 文字列に適用されるようになりました。v0.3.0 では無効でした。英語のロケールファイルもチェックするには、recommendedWithLocalesEn 設定を使用してください(ルール 12~13)。 | 14 | コマンド名 | コマンド名/IDでは「command」を省略する | 名前/IDに「command」を含める | | 15 | コマンド ID | コマンド ID/名前からプラグイン ID/名前を省略する | コマンド ID にプラグイン ID を重複して含める | | 16 | ホットキー | デフォルトのホットキーを設定しない | デフォルトのホットキーを設定する | | 17 | 設定の見出し | .setHeading() を使用する | 手動で HTML の見出しを作成する、見出しに「General」、「settings」、またはプラグイン名を使用する |

宣言型設定(1.13.0+)

4 つの settings-tab ルールはすべて、recommended では warn として提供されます。ルール 17a/17c/17d は manifest.json の minAppVersion を読み取ります。17b はバージョンによる制限がありません。

#ルール✅ 推奨❌ 非推奨
17asettings-tab/require-displayminAppVersion < 1.13.0 の場合は display() を残します古い Obsidian で何も表示されない宣言型設定だけを提供します
17bsettings-tab/prefer-setting-definitionsすべての PluginSettingTab に getSettingDefinitions() を実装しますdisplay() のみに依存します。1.13 以降のグローバル検索に設定が表示されません
17csettings-tab/prefer-update-over-display宣言型設定を再描画するには this.update() を呼び出しますthis.display() を呼び出します。定義が空でない場合は実行されません
17dsettings-tab/no-deprecated-displayminAppVersion >= 1.13.0 で定義が存在する場合は、display() を削除します使われない display() を残します(自動修正可能)
—設定データ永続化されるデータはすべて plugin.settings 内に保持しますsaveData() で兄弟キーを保存します。自動永続化によって上書きされます

検出上の注意点: これらのルールが一致するのは、extends PluginSettingTab のみです。extends obsidian.PluginSettingTab は対象外で、警告されません。ただし、基本的なガイダンスは引き続き適用されます。

API のベストプラクティス
#ルール✅ 推奨❌ 非推奨
18アクティブファイルの編集Editor API を使用しますアクティブファイルの編集に Vault.modify() を使用します
19バックグラウンドでのファイル変更Vault.process() を使用しますバックグラウンドでの変更に Vault.modify() を使用します
20ファイルの削除FileManager.trashFile() を使用しますVault.trash() または Vault.delete() を直接使用します
21ファイルの検索Vault.getAbstractFileByPath() を使用しますVault.getFiles().find() ですべてのファイルを反復処理します
22ユーザーパスnormalizePath() を使用します.obsidian のパスをハードコードします。または、ユーザーパスをそのまま使用します
23OS の検出Platform API を使用しますnavigator.platform/userAgent を使用します
24ネットワークリクエストrequestUrl() を使用しますfetch() を使用します
24aレスポンスの型付けAPI 境界で response.text を解析し、検証/型変換を一度行いますany 型の response.json をプラグインコードに渡します
25ロギングコンソールへのログ出力は最小限にし、本番環境の onload/onunload では出力しませんonload/onunload で console.log を使用します
26入力候補組み込みの AbstractInputSuggest を使用しますLiam の TextInputSuggest 実装をコピーします
27API の互換性minAppVersion を確認して API が利用可能か判断します(例:getSettingDefinitions() には 1.13.0 が必要です)宣言した minAppVersion では利用できない API を使用します
28言語の検出Obsidian の getLanguage() を使用しますlocalStorage.getItem('language') または i18next-browser-languagedetector を使用します
ポップアウトウィンドウの互換性
#ルール✅ 推奨❌ 非推奨
29ドキュメント/ウィンドウactiveDocument と activeWindow を使用するグローバルな document と window を使用する
29aゲッターの取得同じドキュメントを後で使用する場合は、activeDocument を変数に取得しておくセットアップ時とクリーンアップ時に activeDocument を呼び出す — フォーカスに追従するため、異なるドキュメントが返されることがあります
30タイマーwindow.setTimeout()、window.setInterval()、window.requestAnimationFrame() などを使用する(ルール 29 の例外)setTimeout()/setInterval() をそのまま使用する、または activeWindow.setTimeout() を使用する — どちらも prefer-window-timers で警告されます
31メインワークスペース UI設定画面から this.app.workspace.containerEl.ownerDocument を使用する設定ウィンドウからメインワークスペースを更新するために activeDocument を使用する

注(v0.4.0): prefer-active-doc は引き続きデフォルトで無効です — off として提供されている唯一の Obsidian ルールです。ポップアウトウィンドウをサポートするには、手動で有効にしてください。

注(v1.13.0): 設定が新しいウィンドウで開くようになりました。設定コールバック内の activeDocument はメインの保管庫ではなく、設定ウィンドウを指します。メインワークスペース UI を対象にするには、this.app.workspace.containerEl.ownerDocument を使用してください。

注: activeDocument/activeWindow は、フォーカスされたウィンドウを追跡する動的なゲッターです。セットアップ時に activeDocument.addEventListener() で追加したリスナーは、クリーンアップ時に activeDocument.removeEventListener() で確実に削除できるとは限りません。登録時に対象を取得する registerDomEvent()(ルール 6a)を使用してください。

イベント処理
#ルール✅ 推奨❌ 非推奨
31エディターでのドロップ/貼り付けevt.defaultPrevented を確認し、evt.preventDefault() を呼び出すdefaultPrevented を確認せずにエディターでのドロップ/貼り付けを処理する
スタイリング
#ルール✅ 推奨❌ 非推奨
32CSS 変数すべてのスタイリングに Obsidian の CSS 変数を使用する色、サイズ、間隔をハードコードする
33CSS のスコープCSS の対象をプラグインのコンテナーに限定する範囲の広い CSS セレクターを使用する
34要素のスタイル設定styles.css ファイルを使用する(no-forbidden-elements)<link> 要素または <style> 要素を作成する、JavaScript でスタイルを設定する
34a!importantセレクターの詳細度を上げるか、CSS 変数を使用する!important を使用する — ユーザーのテーマやスニペットを上書きします
34b:has セレクター条件の変化に応じて TypeScript からクラスを切り替える:has を使用する — 範囲の広いセレクターの無効化を引き起こし、パフォーマンス上の問題が発生します
セキュリティと互換性
#ルール✅ 推奨❌ 非推奨
35DOM の作成prefer-create-el を介して Obsidian の DOM ヘルパー(createEl()、createDiv()、createSpan()、createSvg()、createFragment())を使用する。リンターは activeDocument.createElement() を activeWindow.createEl() に自動修正します(v0.4.1)document.createElement()、document.createDocumentFragment() などを使用する
36Node.js モジュールPlatform.isDesktop チェックで Node.js のインポートを保護する(no-nodejs-modules)プラットフォームチェックなしで Node.js モジュールをインポートする
37iOS 互換性正規表現の後読みを避ける(iOS < 16.4 との非互換性)正規表現の後読みを使用する
アクセシビリティ(必須)
#ルール✅ 推奨❌ 非推奨
38キーボード操作すべてのインタラクティブ要素をキーボードで操作できるようにする。すべての要素を Tab で移動できるようにするキーボードで操作できないインタラクティブ要素を作成する
39ARIA ラベルアイコンボタンに ARIA ラベルを指定する。ツールチップには data-tooltip-position を使用するARIA ラベルのないアイコンボタンを使用する
40フォーカスインジケーターObsidian の CSS 変数と :focus-visible を使用する。タッチ対象を 44×44px 以上にするフォーカスインジケーターを削除する。タッチ対象を 44×44px 未満にする
コード品質
ルール✅ 推奨❌ 非推奨
サンプルコードサンプル/テンプレートコードをすべて削除するMyPlugin、SampleModal のようなクラス名を残す
Object.assignObject.assign({}, defaults, overrides) (object-assign)Object.assign(defaultsVar, other) — defaults を変更します
LICENSE著作権者に「Dynalist Inc.」を指定せず、年は現在の年にする (validate-license)著作権者に「Dynalist Inc.」を指定したままにする、または古い年を使用する
非同期処理async/await を使用するPromise チェーンを使用する
非推奨パッケージ指摘された npm パッケージを Node.js の組み込み機能に置き換える(例:builtin-modules → import { builtinModules } from "node:module")スキャナーが置き換え可能と指摘するパッケージを使用する

詳細ガイドライン

特定のトピックの詳細については、以下のリファレンスファイルをご覧ください。

メモリ管理とライフサイクル
  • registerEvent()、addCommand()、registerDomEvent()、registerInterval() の使用
  • registerDomEvent() と手動の addEventListener の比較(および activeDocument のずれに関するバグ)
  • プラグイン内でビューへの参照を保持しない
  • プラグインをコンポーネントとして使用しない
  • リーフを適切にクリーンアップする
型安全性
  • 型キャストではなく instanceof を使用する
  • any 型を避ける
  • var よりも const と let を使用する
UI/UX 標準
  • センテンスケースの徹底(TypeScript、JSON ロケール、TS/JS ロケールモジュール)
  • ロケールファイルのチェックに recommendedWithLocalesEn 設定を使用する
  • コマンドの命名規則(「command」、プラグイン名、プラグイン ID を含めない)
  • 設定に関するベストプラクティス
  • 宣言的な設定 API(1.13 以降):移行パス、コントロールの種類、注意点
ファイルと Vault の操作
  • ビューへのアクセスパターン
  • Editor API と Vault API
  • アトミックなファイル操作
  • ファイル管理
  • パスの処理
CSS スタイリングのベストプラクティス
  • インラインスタイルを避ける
  • Obsidian の CSS 変数を使用する
  • !important を避ける(詳細度または CSS 変数を使用する)
  • :has セレクターを避ける(代わりに TypeScript からクラスを切り替える)
  • プラグインのスタイルをスコープ化する
  • テーマへの対応
  • 間隔とレイアウト
アクセシビリティ(A11y)
  • キーボード操作(必須)
  • ARIA ラベルとロール(必須)
  • ツールチップとアクセシビリティ
  • フォーカス管理(必須)
  • フォーカス表示スタイル(必須)
  • スクリーンリーダーへの対応(必須)
  • モバイルとタッチ操作のアクセシビリティ(必須)
  • アクセシビリティのチェックリスト
コード品質とベストプラクティス
  • サンプルコードの削除
  • セキュリティのベストプラクティス
  • プラットフォーム互換性
  • API 使用のベストプラクティス
  • async/await のパターン
  • DOM ヘルパー
  • 非推奨/置き換え可能なパッケージ(例:builtin-modules → node:module)
プラグインの提出要件
  • リポジトリの構成
  • 提出プロセス
  • セマンティックバージョニング
  • テストのチェックリスト
  • 追加リソースと重要な注意事項
Community Plugin Scanner
  • スキャナーが実行する内容(ESLint ルールセットと ESLint 以外のチェック)
  • スコアカードシステム(健全性、レビュー、開示事項、改善のヒント)
  • バージョンスタンプ付き — スキャナーの進化に合わせて更新する単一のファイル
ESLint 設定ガイド
  • Community Plugin Scanner への準拠に必要な ESLint 設定一式
  • typescript-eslint の recommendedTypeChecked が必須である理由
  • よくある違反と修正方法(未処理の Promise、require インポートなど)
  • ポップアウトウィンドウの互換性ルール

プラグイン提出の検証ワークフロー

プラグインを提出する前に、次の手順に従ってください。

  1. ESLint を実行する — eslint-plugin-obsidianmd を使用して npx eslint . を実行し、すべてのエラーと警告を修正します(警告はスコアカードに影響します)。
  2. マニフェストを検証する — id、name、description、version、minAppVersion が命名規則と書式ルール(ルール 1~5)に準拠していることを確認します。
  3. LICENSE を確認する — 著作権者が「Dynalist Inc.」ではなく、年が現在の年であることを確認します。
  4. モバイルでテストする — 正規表現の後読み、fetch()、および 44×44px 未満のタッチターゲットがないことを確認します(プラグインがデスクトップ専用と宣言されている場合のみ省略できます)。
  5. キーボードアクセシビリティを監査する — すべてのインタラクティブ要素を Tab キーで移動し、フォーカスインジケーターと ARIA ラベルがあることを確認します。
  6. GitHub Release を作成する — タグが manifest.json のバージョンと一致する必要があります。main.js、manifest.json、および styles.css(任意)を添付します。
  7. community.obsidian.md から提出する — サインインし、GitHub アカウントをリンクして、「Plugins → New plugin」に移動し、リポジトリの URL を入力します。開発者ポリシーを確認してから提出してください。

修正後に ESLint が新たなエラーを報告した場合は、ステップ 1 から再実行してください。


スコアカードシステム

公開されたプラグインには、community.obsidian.md に表示されるスコアカードが付与されます。スコアカードはユーザーからの信頼と見つけやすさに影響します。スコアが低いと、ユーザーがインストールをためらう原因になります。

重要なポイント:

  • 総合スコア 90%以上を目指してください。
  • エラーだけでなく、すべての ESLint 警告を修正してください。警告は公開されます。
  • 型を考慮したチェックには typescript-eslint/recommendedTypeChecked を使用してください。
  • リリースに GitHub アーティファクト証明を追加してください。

スキャナーのチェック、ヘルスメトリクス、レビューのチェック、よくある警告、改善のヒントの詳細については、Community Plugin Scanner を参照してください。


コードのレビュー/作成時

コードレビューと実装には、次のチェックリストを使用してください。

  1. メモリ管理:コンポーネントとビューは適切に管理されていますか?
  2. 型安全性:キャストではなく instanceof を使用していますか?
  3. UI テキスト:すべてセンテンスケースになっていますか?
  4. コマンドの命名:冗長な語が含まれていませんか?
  5. ファイル操作:推奨される API を使用していますか?
  6. モバイル互換性:iOS と互換性のない機能はありませんか?
  7. サンプルコード:ボイラープレートはすべて削除されていますか?
  8. マニフェスト:バージョンは正しく、構造は有効ですか?
  9. アクセシビリティ:キーボード操作、ARIA ラベル、フォーカスインジケーターに対応していますか?
  10. テスト:マウスを使わずにプラグインを操作できますか?
  11. タッチターゲット:すべてのインタラクティブ要素が 44×44px 以上ですか?
  12. フォーカススタイル::focus-visible と適切な CSS 変数を使用していますか?
  13. 設定:1.13 以降では宣言型の getSettingDefinitions() を使用していますか?保存されるデータはすべて plugin.settings にまとめられていますか?

よくあるパターン

適切なコマンド登録
// ✅ CORRECT
this.addCommand({
  id: 'insert-timestamp',
  name: 'Insert timestamp',
  editorCallback: (editor: Editor, view: MarkdownView) => {
    editor.replaceSelection(new Date().toISOString());
  }
});
安全な型の絞り込み
// ✅ CORRECT
const file = this.app.vault.getAbstractFileByPath(path);
if (file instanceof TFile) {
  // TypeScript now knows it's a TFile
  await this.app.vault.read(file);
}
キーボードで操作できるボタン
// ✅ CORRECT
const button = containerEl.createEl('button', {
  attr: {
    'aria-label': 'Open settings',
    'data-tooltip-position': 'top'
  }
});
button.setText('⚙️');

button.addEventListener('keydown', (e) => {
  if (e.key === 'Enter' || e.key === ' ') {
    e.preventDefault();
    performAction();
  }
});
宣言型の設定(1.13 以降)
// ✅ CORRECT — getSettingDefinitions() replaces display() on 1.13+
getSettingDefinitions() {
  return [
    {
      name: 'Mode',
      control: {
        type: 'dropdown',
        key: 'mode',
        defaultValue: 'fast',
        options: { fast: 'Fast', thorough: 'Thorough' },
      },
    },
  ];
}
テーマ対応 CSS
/* ✅ CORRECT */
.my-plugin-modal {
  background: var(--modal-background);
  color: var(--text-normal);
  padding: var(--size-4-4);
  border-radius: var(--radius-m);
  font-size: var(--font-ui-medium);
}

.my-plugin-button:focus-visible {
  outline: 2px solid var(--interactive-accent);
  outline-offset: 2px;
}

Obsidian プラグインの開発を支援する際は、これらのルールを積極的に適用し、ガイドラインに基づいて改善点を提案してください。各トピックの詳しい情報については、詳細なリファレンスファイルを参照してください。

コメント