第一次開發VSCode Extension之流程與心得

前置作業

  • VSCode
  • Nodejs,可安裝nvm隨意切換與安裝不同版本
  • Git

初始化專案

使用Yeoman來初始化擴展專案

  1. npm install --global yo generator-code
  2. yo code

Yeoman導覽會帶你一步一步建立專案

設定好一些專案的詳細資訊後就可以開始寫code了!

一些基本文件介紹

  • F5可以進入debug模式,測試擴展
  • .vscode資料夾存放程式執行和debug的命令
  • vsc-extension-quickstart.md簡單介紹了擴展的入門知識
  • src就是放原始碼的地方
  • package.json是擴展設定的檔案

Package.json

  • main為擴展入口,也就是程式的root
  • contributes中的commands是設定命令的地方,該命令需與原始碼中的命令一致才能呼叫

實際開發

  • vscode.commands.registerCommand可以設定command
  • 使用context.subscriptions.push把命令註冊到context中,這樣擴展關閉的時候會自動釋出
import * as vscode from "vscode";

export function activate(context: vscode.ExtensionContext) {
  console.log('Congratulations, your extension "test" is now active!');

  let disposable = vscode.commands.registerCommand("test.helloWorld", () => {
    vscode.window.showInformationMessage("Hello World from test!");
  });

  context.subscriptions.push(disposable);
}

export function deactivate() {}

本次的目標是開發一個能夠透過commands自動貼入程式碼片段的擴展

原始碼結構

我把extension.ts當作程式入口,並且根據不同command呼叫對應的功能(放在util裡面)

// extension.ts
import * as vscode from 'vscode';
import { youtubeEmbedPaste } from './util/youtubeEmbed';
import { foldBlock } from './util/foldBlock';
import { note } from './util/note';
import { label } from './util/label';
import { checkBox } from './util/checkBox';
import { button } from './util/button';
import { groupImages } from './util/groupImages';
import { mermaid } from './util/mermaid';

export function activate(context: vscode.ExtensionContext) {

	// Register multiple commands
	let youtubeEmbedCommand = vscode.commands.registerCommand('hexo-snippet-paste-tool-for-fluid.pasteYoutubeEmbed', () => {
		youtubeEmbedPaste();
	});

	let foldBlockCommand = vscode.commands.registerCommand('hexo-snippet-paste-tool-for-fluid.pasteFoldBlock', () => {
		foldBlock();
	});

	let noteCommand = vscode.commands.registerCommand('hexo-snippet-paste-tool-for-fluid.pasteNote', () => {
		note();
	});

	let labelCommand = vscode.commands.registerCommand('hexo-snippet-paste-tool-for-fluid.pasteLabel', () => {
		label();
	});

	let checkBoxCommand = vscode.commands.registerCommand('hexo-snippet-paste-tool-for-fluid.pasteCheckBox', () => {
		checkBox();
	});

	let buttonCommand = vscode.commands.registerCommand('hexo-snippet-paste-tool-for-fluid.pasteButton', () => {
		button();
	});

	let groupImagesCommand = vscode.commands.registerCommand('hexo-snippet-paste-tool-for-fluid.pasteGroupImages', () => {
		groupImages();		
	});

	let mermaidCommand = vscode.commands.registerCommand('hexo-snippet-paste-tool-for-fluid.pasteMermaid', () => {
		mermaid();
	});


	// Add the commands to the context
	context.subscriptions.push(youtubeEmbedCommand);
	context.subscriptions.push(foldBlockCommand);
	context.subscriptions.push(noteCommand);
	context.subscriptions.push(labelCommand);
	context.subscriptions.push(checkBoxCommand);
	context.subscriptions.push(buttonCommand);
	context.subscriptions.push(groupImagesCommand);
	context.subscriptions.push(mermaidCommand);
}

// This method is called when your extension is deactivated
export function deactivate() { }

Note功能範例

import * as vscode from 'vscode';

export async function note() {
    // Obtain the active text editor
    const editor = vscode.window.activeTextEditor;
    if (!editor) {return;}

    // UI for Width and Height Input
    vscode.window.showInputBox({
        value: 'info',
        prompt: 'Type in the type of the note (e.g., primary, default, info, success, warning, danger)'
    }).then(input => {
        // When user provide any input
        if (input) {

            // Prepare the fold block content
            const content = prepareNote(input);

            // Inserting the content to the editor
            editor.edit(editBuilder => {
                editBuilder.insert(editor.selection.active, content);
            });
        }
    });
}

function prepareNote(type: string): string {
    // Modify the fold block content with the specified type and title
    return `{% note ${type} %}\n\n{% endnote %}`;
}

這個擴展功能很好開發,剩下的就是準備好各式文件,並上架marketplace

我主要動到的有以下

  • package.json: 整個擴展的詳細資訊與各種設定(官方手冊有說明文件)
  • pacakge-lock.json: 各種依賴的版本號
  • README.md: 擴展的說明與手冊
  • CHANGELOG.md: 版本的修改紀錄,撰寫手冊
  • LICENSE: MIT, GPL-3等,上架會需要用到

發布與上架

測試完成後就準備發布

安裝擴展封裝與發布工具npm install -g @vscode/vsce

vsce package命令可以把擴展封裝,並且在vscode本地安裝測試
vsce publish命令發布擴展

但是在發布前需要到azure註冊與建立用戶,請參閱

註冊好了之後就可以使用token進行發布了!過幾分鐘後會在marketplace看到

marketplace

一些參考網站


第一次開發VSCode Extension之流程與心得
https://f88083.github.io/2024/03/20/第一次開發VSCode-Extension之流程與心得/
作者
Simon Lai
發布於
2024年3月20日
許可協議