ステップ1実装

This commit is contained in:
ry.yamafuji 2025-06-07 19:59:28 +09:00
parent 97b9c2d2c3
commit c825fb3f74
4 changed files with 197 additions and 6 deletions

56
docs/pg_task.md Normal file
View File

@ -0,0 +1,56 @@
# ImageMarkPengent 実装タスク
## 0. チュートリアル:現状の拡張機能をビルド・実行する
1. 依存パッケージのインストール(初回のみ)
```sh
yarn install
```
2. ビルド
```sh
yarn compile
```
3. VSCodeでこのプロジェクトimagemarkpengentを開く
4. F5キーまたは「実行とデバッグ」→「拡張機能のデバッグ」で新しいVSCodeウィンドウが起動し、拡張機能が有効化される
5. コマンドパレットCtrl+Shift+P`Hello World` コマンドを実行できる
---
## 概要
VSCode拡張機能「ImageMarkPengent」の実装タスク一覧です。
---
## 実装ステップ
### 1. コマンド登録と右クリックメニュー対応
- [x] `package.json` にコマンドを登録する
- [x] `explorer/context` メニューに「Open in ImageMarkPengent」を追加
- [ ] 対象拡張子を `.png` / `.jpg` / `.jpeg` に限定
### 2. WebViewで画像表示
- [ ] コマンド実行時にWebViewパネルを開く
- [ ] 画像ファイルを `<img>` または `<canvas>` で表示
- [ ] 画像の上に描き込み可能な `canvas` を重ねる
### 3. 赤丸マーク描画機能
- [ ] WebView内でJavaScriptにより `<canvas>` へ赤丸を描画
- [ ] クリック座標を取得し、赤丸を描画・保持
- [ ] 複数マークの描画・再描画に対応
### 4. 加工画像の保存機能
- [ ] WebViewに「保存」ボタンを設置
- [ ] `canvas.toDataURL()` で画像データを取得
- [ ] `vscode.postMessage()` で拡張機能側に送信
- [ ] 拡張機能側でファイル保存(別名保存も対応)
---
## 今後の拡張案(任意)
- 番号付きマーカーや矢印の追加
- マークの色やサイズ変更
- Undo/Redo機能
- 他画像フォーマット対応

117
docs/tips.md Normal file
View File

@ -0,0 +1,117 @@
# VSCode拡張機能開発TIPSImageMarkPengent
## Vscodeの起動イメージ
```mermaid
flowchart TD
A["拡張機能の起動"] --> B["コマンドやイベントリスナーを登録"]
B --> C["Disposableをcontext.subscriptionsにpush"]
C --> D["拡張機能の終了"]
D --> E["VSCodeが自動でdispose()を呼び出し、リソース解放"]
```
## よく使うAPI・ポイント
- `vscode.window.showInformationMessage('メッセージ')`
- 右下に情報メッセージを表示できる。デバッグやユーザー通知に便利。
- `console.log('メッセージ')`
- 拡張機能のデバッグ用ログ。VSCodeの「出力」→「拡張機能のログ」で確認できる。
- `vscode.commands.registerCommand('コマンドID', () => { ... })`
- コマンドIDはpackage.jsonのcontributes.commandsで定義したものと一致させる必要がある。
- コマンドの実装はこのコールバック内に記述。
- `context.subscriptions.push(オブジェクト)`
- 登録したコマンドやイベントリスナーは、context.subscriptionsにpushしておくと拡張機能の終了時に自動でクリーンアップされる。
- もう少しかみ砕くと拡張機能が無効化・アンロードされたときに、イベントリスナーやコマンドなどのリソースを自動で解放してくれるという意味です。
- pushしない場合、拡張機能が終了してもコマンドやリスナーが残り続け、メモリリークや予期しない動作の原因になります。
- `activate(context: vscode.ExtensionContext)`
- 拡張機能が有効化されたときに一度だけ呼ばれる初期化関数。
- `deactivate()`
- 拡張機能が無効化されたときに呼ばれるクリーンアップ関数。
---
## その他
- コマンドの追加や変更を行った場合は、VSCodeの再起動や拡張機能の再読み込みReloadを行うと反映されやすい。
---
## コマンド登録と右クリックメニュー対応
### コマンドの登録
1. `package.json`にコマンドを登録する
2. contributes.commands に新しいコマンド(例: imagemarkpengent.openImageEditorを追加
3. activationEvents にコマンドのonCommandイベントを追加
* VSCode拡張機能が「いつ有効化起動」されるかを決めるトリガーを定義するものです。
* VSCodeの拡張機能は、「VSCodeの起動時」や「特定のファイルを開いたとき」など、必要なタイミングで初めてメモリにロードされ、activate関数が呼ばれます。
| 設定値 | 説明 |
| ----------------------- | ------------------------------------------------------------ |
| "onCommand:コマンドID" | 指定したコマンドが実行されたときに拡張機能を有効化 |
| "onLanguage:言語ID" | 指定した言語のファイルが開かれたとき |
| "onFileSystem:スキーム" | 指定したファイルシステムスキームのリソースにアクセスしたとき |
| "*" | VSCode起動時に必ず有効化非推奨重くなるため |
```json
"activationEvents": [
"onCommand:imagemarkpengent.openImageEditor"
],
"contributes": {
"commands": [
{
"command": "imagemarkpengent.openImageEditor",
"title": "Open in ImageMarkPengent"
}
],
}
```
### 右クリックメニューに対応する
1. `package.json`にコマンドを登録する
2. contributes.menus に`explorer/context`を追加する
* explorer/context は エクスプローラー(ファイルツリー)で右クリックしたときのコンテキストメニュー
3. menuの内容を追加する
* groupはメニュー内でのコマンドの表示位置を指定するためのグループ名です
* "navigation": ファイルやフォルダをナビゲーション・開く
```json
"contributes": {
"menus": {
"explorer/context": [
{
"command": "imagemarkpengent.openImageEditor",
"when": "resourceExtname =~ /\\.(png|jpg|jpeg)$/",
"group": "navigation"
}
]
}
}
```
### 対象拡張子を `.png` / `.jpg` / `.jpeg` に限定
基本的には、explorer/context メニューの when 句で拡張子を限定すれば十分ですが
「コマンドの実行自体を拡張子で制御したい」場合は、コマンド実装側でも拡張子チェックを行うのが安全です。
#### コマンド側の実装例
```js
vscode.commands.registerCommand('imagemarkpengent.openImageEditor', (uri: vscode.Uri) => {
if (!uri || !uri.fsPath.match(/\.(png|jpg|jpeg)$/i)) {
vscode.window.showWarningMessage('対応画像ファイル(.png, .jpg, .jpegを選択してください。');
return;
}
// ここに画像編集処理
});
```

View File

@ -9,15 +9,26 @@
"categories": [ "categories": [
"Other" "Other"
], ],
"activationEvents": [], "activationEvents": [
"onCommand:imagemarkpengent.openImageEditor"
],
"main": "./out/extension.js", "main": "./out/extension.js",
"contributes": { "contributes": {
"commands": [ "commands": [
{ {
"command": "imagemarkpengent.helloWorld", "command": "imagemarkpengent.openImageEditor",
"title": "Hello World" "title": "Open in ImageMarkPengent"
} }
] ],
"menus": {
"explorer/context": [
{
"command": "imagemarkpengent.openImageEditor",
"when": "resourceExtname =~ /\\.(png|jpg|jpeg)$/",
"group": "navigation"
}
]
}
}, },
"scripts": { "scripts": {
"vscode:prepublish": "yarn run compile", "vscode:prepublish": "yarn run compile",

View File

@ -14,12 +14,19 @@ export function activate(context: vscode.ExtensionContext) {
// Now provide the implementation of the command with registerCommand // Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json // The commandId parameter must match the command field in package.json
const disposable = vscode.commands.registerCommand('imagemarkpengent.helloWorld', () => { const disposable = vscode.commands.registerCommand('imagemarkpengent.helloWorld', () => {
// The code you place here will be executed every time your command is executed
// Display a message box to the user
vscode.window.showInformationMessage('Hello World from ImageMarkPengent!'); vscode.window.showInformationMessage('Hello World from ImageMarkPengent!');
}); });
const disposableOpenImageEditor = vscode.commands.registerCommand('imagemarkpengent.openImageEditor', (uri: vscode.Uri) => {
if (!uri || !uri.fsPath.match(/\.(png|jpg|jpeg)$/i)) {
vscode.window.showWarningMessage('対応画像ファイル(.png, .jpg, .jpegを選択してください。');
return;
}
vscode.window.showInformationMessage('画像編集コマンドが呼び出されました: ' + uri.fsPath);
});
context.subscriptions.push(disposable); context.subscriptions.push(disposable);
context.subscriptions.push(disposableOpenImageEditor);
} }
// This method is called when your extension is deactivated // This method is called when your extension is deactivated