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插件开发的兴趣和热情。