带你开发一个提示颜色代码的VS Code插件

1. 前言

在开发中,经常会需要使用到颜色代码,特别是在前端开发中,如CSS样式、JS代码、HTML等,但有时候在输入颜色代码时会因输入错误而造成浪费时间,因此本文将介绍如何开发一个提示颜色代码的VS Code插件,来提高开发效率。

2. 确定需求和目标

本插件的目标是提供一个简单而快捷的提示颜色代码的功能,能够减少输入错误带来的影响,提高代码质量和效率。因此,在我们开始之前,需要明确以下需求和目标:

2.1 需求

- 在输入颜色代码时,快速提示正确的颜色代码。

- 可以输入不同格式的颜色代码,如#fff、RGB等。

- 当输入错误的颜色代码时,能够进行提示和修复。

2.2 目标

- 开发一个简单实用的VS Code插件。

- 能够准确地提示和自动修复颜色代码。

- 使用简单的正则表达式或算法实现准确的匹配和提示。

3. 开始开发

3.1 首先,初始化插件工程

我们需要创建一个VS Code插件工程,命令行输入:

yo code

按照提示,输入插件的名称、描述等信息。

然后,在package.json中添加以下代码:

{

"devDependencies": {

"@types/node": "^14.14.33",

"@types/vscode": "^1.60.0",

"tslint": "^5.20.1",

"typescript": "^4.4.4",

"vscode-test": "^1.6.0"

},

"scripts": {

"watch": "tsc -w",

"test": "npm run compile && node ./node_modules/vscode/bin/test"

}

}

3.2 添加功能

接下来,我们需要添加功能。

首先,我们需要在插件中添加一个command,代码如下:

// package.json

{

...

"contributes": {

"commands": [{

"command": "extension.colorPicker",

"title": "Color Picker"

}]

},

...

}

// extension.ts

const colorPickerCommand = 'extension.colorPicker';

let disposable = vscode.commands.registerCommand(colorPickerCommand, () => {

// TODO: 添加Command的具体实现

});

context.subscriptions.push(disposable);

然后,我们需要为command添加UI界面,代码如下:

// package.json

{

...

"contributes": {

"commands": [{

"command": "extension.colorPicker",

"title": "Color Picker"

}],

"menus": {

"editor/context": [{

"command": "extension.colorPicker",

"when": "editorTextFocus"

}]

},

"viewsContainers": {

"explorer": [{

"id": "extension.colorPickerPickColorView",

"title": "Color Picker",

"icon": "resources/icon.png"

}]

},

"views": {

"extension.colorPickerPickColorView": [{

"id": "extension.colorPickerPickColor",

"name": "Pick Color"

}]

},

"webviewViews": [{

"id": "extension.colorPickerPickColor",

"name": "Pick Color",

"icon": "resources/icon.png",

"container": "extension.colorPickerPickColorView",

"location": "sidebar"

}]

},

...

}

接下来,我们需要在webview中添加一个颜色选择器,代码如下:

import * as vscode from 'vscode';

let panel: vscode.WebviewPanel;

function createPanel() {

panel = vscode.window.createWebviewPanel(

'colorPicker',

'Color Picker',

vscode.ViewColumn.One,

{

enableScripts: true,

localResourceRoots: [vscode.Uri.file(path.join(context.extensionPath, 'resources'))]

}

);

panel.onDidDispose(() => {

panel = undefined;

});

return panel;

}

const colorPickerCommand = 'extension.colorPicker';

let disposable = vscode.commands.registerCommand(colorPickerCommand, () => {

if (!panel) {

panel = createPanel();

}

panel.webview.html = getWebviewContent();

});

function getWebviewContent() {

const styleResetUri = vscode.Uri.file(path.join(context.extensionPath, 'resources', 'reset.css')).with({ scheme: 'vscode-resource' });

const scriptUri = vscode.Uri.file(path.join(context.extensionPath, 'resources', 'main.js')).with({ scheme: 'vscode-resource' });

const styleMainUri = vscode.Uri.file(path.join(context.extensionPath, 'resources', 'vscode.css')).with({ scheme: 'vscode-resource' });

const bootstrapUri = vscode.Uri.file(path.join(context.extensionPath, 'resources', 'css', 'bootstrap.min.css')).with({ scheme: 'vscode-resource' });

const styleReset = ``;

const styleMain = ``;

const htmlContent = `

${styleReset} ${styleMain}

Select Color:

`;

return htmlContent;

}

context.subscriptions.push(disposable);

我们使用了Bootstrap框架和jQuery库来实现选择器。

3.3 匹配颜色代码

接下来,我们需要添加匹配颜色代码的功能。我们使用正则表达式来匹配颜色代码。

代码如下:

// extension.ts

...

const colorRegex = /^#([0-9a-f]{3}){1,2}$/i;

const rgbaColorRegex = /^rgba?\(\s*(\d{1,3}%?)\s*,\s*(\d{1,3}%?)\s*,\s*(\d{1,3}%?)\s*(,\s*(\d+(\.\d+)?%?))?\)$/i;

// 判断是否是颜色代码

function isColorCode(text: string) {

return colorRegex.test(text) || rgbaColorRegex.test(text);

}

// 判断输入的颜色是否合法

function isColorValid(input: string) {

return isColorCode(input.trim());

}

...

3.4 提示颜色代码

最后,我们需要为输入颜色代码时进行提示。我们使用了自动完成API来实现。

代码如下:

// package.json

...

"contributes": {

...

"languages": [{

"id": "javascript",

"aliases": ["JavaScript", "javascript"],

"extensions": [".js"]

}],

"completions": [{

"language": "javascript",

"path": "./colorCompletions.json"

}]

},

...

// colorCompletions.json

{

"colors": [{

"label": "#ffffff",

"detail": "white"

}, {

"label": "#000000",

"detail": "black"

}, {

"label": "#ff0000",

"detail": "red"

}, {

"label": "#00ff00",

"detail": "green"

}, {

"label": "#0000ff",

"detail": "blue"

}, {

"label": "rgba(255, 255, 255, 1.0)",

"detail": "white"

}, {

"label": "rgba(0, 0, 0, 1.0)",

"detail": "black"

}, {

"label": "rgba(255, 0, 0, 1.0)",

"detail": "red"

}, {

"label": "rgba(0, 255, 0, 1.0)",

"detail": "green"

}, {

"label": "rgba(0, 0, 255, 1.0)",

"detail": "blue"

}]

}

// extension.ts

...

let disposable2 = vscode.languages.registerCompletionItemProvider(

'javascript',

{

provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {

const linePrefix = document.lineAt(position).text.substr(0, position.character);

// 判断当前单词

if (!isColorValid(linePrefix)) {

// 不是颜色输入,返回空

return undefined;

}

// 是颜色输入,返回对应的颜色提示

return new vscode.CompletionList([

...colors.map(color => {

const item = new vscode.CompletionItem(color.label);

item.documentation = color.detail;

item.kind = vscode.CompletionItemKind.Color;

return item;

})

], false);

}

},

'#'

);

...

4. 算法测试

为了验证算法的准确性,我们需要编写一些测试用例。在这里,我们使用Jest来编写测试代码。

代码如下:

// extension.test.ts

...

test('Color Regex: Match', () => {

expect(colorRegex.test('#FFF')).toBeTruthy();

expect(colorRegex.test('#fFF')).toBeTruthy();

expect(colorRegex.test('#ffffff')).toBeTruthy();

expect(colorRegex.test('#FFFFFF')).toBeTruthy();

expect(colorRegex.test('#000000')).toBeTruthy();

expect(colorRegex.test('#FF0000')).toBeTruthy();

expect(colorRegex.test('#00FF00')).toBeTruthy();

expect(colorRegex.test('#0000FF')).toBeTruthy();

expect(colorRegex.test('#a1b2c3')).toBeTruthy();

expect(rgbaColorRegex.test('rgba(255, 255, 255, 1.0)')).toBeTruthy();

expect(rgbaColorRegex.test('rgba(0, 0, 0, 1.0)')).toBeTruthy();

expect(rgbaColorRegex.test('rgba(255, 0, 0, 1.0)')).toBeTruthy();

expect(rgbaColorRegex.test('rgba(0, 255, 0, 1.0)')).toBeTruthy();

expect(rgbaColorRegex.test('rgba(0, 0, 255, 1.0)')).toBeTruthy();

});

test('Color Regex: Not Match', () => {

expect(colorRegex.test('color')).toBeFalsy();

expect(colorRegex.test('123')).toBeFalsy();

expect(colorRegex.test('#XXX')).toBeFalsy();

expect(rgbaColorRegex.test('rgba()')).toBeFalsy();

expect(rgbaColorRegex.test('rgba(, , , )')).toBeFalsy();

expect(rgbaColorRegex.test('rgba(256, 0, 0)')).toBeFalsy();

expect(rgbaColorRegex.test('rgba(255, 256, 0)')).toBeFalsy();

expect(rgbaColorRegex.test('rgba(255, 255, 256)')).toBeFalsy();

});

...

5. 总结

通过开发这个颜色代码提示插件,我们实现了快速匹配和提示颜色代码的功能,在开发中可以大大提高效率和代码质量。

在开发插件的过程中,我们学习了VS Code插件的基本开发流程、Webview、自动完成API和正则表达式的使用等技术,并且掌握了如何使用Jest编写测试用例对代码进行测试。

最后,希望本篇文章对您有所帮助,同时也能够激发您对于VS Code插件开发的兴趣和热情。