为什么想要在开发时做这样一个工具,是因为在没有这个工具之前的链路是这样的:
如果有这样一个VScode 插件可以做到:
这样就节省了切换vscode/chrome以及copy文案、在国际化页面里搜索文案的时间。 如果创建/编辑一个key能节省1分钟,创建100个key就能节省一个多小时的时间 🙃
每用一次mdsi18n插件就能延长1min的寿命。。。
这个插件主要利用了插件提供的一下能力:
根据上述插件能力 贴一下核心代码逻辑:
// 声明HoverProvider
const hoverDisposable = languages.registerHoverProvider(
['typescript', 'javascript', 'typescriptreact', 'javascriptreact', 'json'], // registerHoverProvider第一个参数为当前provider生效的文件类型: ts、js、tsx、jsx、json
{
async provideHover(document: TextDocument, position: Position, token: CancellationToken ) {
const line = document.lineAt(position).text; // 光标所在的行
const keyRegExp = new RegExp(`[\`|\'|\"]${KEY_PREFIX}[^\'|\'|\"]*[\`|\'|\"]`, 'g'); // 匹配符合前缀的内容
let positionMatch: RegExpMatchArray | null = line.match(keyRegExp);
if (positionMatch && positionMatch.length) {
let positionWord = document.getText(document.getWordRangeAtPosition(position, keyRegExp));
positionWord = positionWord.replace(REPLACE_SPACE_REG, '$1');
const mcm: MarkdownString = await getValueFromHoverText(positionWord); // 这里返回的MarkdownString就是Hover之后展示的内容
return new Hover(mcm);
}
}
}
);
// - 然后在 vscode extension的统一入口 extension.ts中挂载 HoverProvider
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
// This line of code will only be executed once when your extension is activated
// ...
context.subscriptions.push(hoverDisposable);
// ...
}
// 还是基于上面HoverProvider,因为创建/编辑的入口都在Hover上,只是getValueFromHoverText这里需要处理返回内容
// 如果当前Hover的Key没有找到文案
export async function getValueFromHoverText(mdsKey: string): Promise<MarkdownString> {
// ...
const webViewArgs = { webviewType: "Create", data: { mdsKey }}; // command 携带参数传递给webview,参数必须经过如下处理
const commandUri = Uri.parse(`command:${Command.showWebview}?${encodeURIComponent(JSON.stringify(webViewArgs))}`); // 你细品
let noKeyTip = `*没有找到对应文案* \n\n [创建Key](${commandUri} "创建key")`;
const markdown = new MarkdownString(noKeyTip, true);
markdown.isTrusted = true; // 如果想让Hover执行command 一定要设置 isTrusted,否则vscode将不识别命令
return markdown;
}
// 如果当前Hover的Key 已经存在国际化文案,提供编辑入口
export async function getValueFromHoverText(mdsKey: string): Promise<MarkdownString> {
const markdown: MarkdownString = new MarkdownString();
// ...
const webViewArgs = {
webviewType: "Edit",
data: {
mdsKey,
zhCn: valueMap.get('Simplified Chinese'),
enUs: valueMap.get('english'),
tagName: handleTagName(data[0].tagName || ""),
description: data[0].description || ""
}
};
const commandUri = Uri.parse(`command:${Command.showWebview}?${encodeURIComponent(JSON.stringify(webViewArgs))}`);
let noKeyTip = ` [编辑文案](${commandUri} "编辑文案")`;
markdown.appendMarkdown(noKeyTip);
markdown.isTrusted = true;
return markdown;
}
// 查找国际化Key 实际是一个Command,可以通过右键菜单,或者command + shift + p 唤起
export default class FindSelectionCommand {
public registerCommand(context: ExtensionContext) {
const editor: TextEditor | undefined = window.activeTextEditor; // 当前vscode激活的编辑窗口,即光标所在的编辑器窗口
context.subscriptions.push(commands.registerCommand(Command.findSelection, async (args: FindSelectionCommandArgument) => {
if (!args || !editor) { return; }
const text = editor.document.getText(editor.selection); // 可以通过 editor.selection 直接获取当前所在编辑器选中的内容
if (!text) {
return;
}
await getMdsKeyByValue(text); // 这里处理openApi请求, 然后通过quickPick的形式展示获取到文案的Key
}));
}
}
export default async function getMdsKeyByValue(value: string): Promise<void> {
const itemList: QuickPickItem[] = [];
// ...
// window.showQuickPick 返回的 promise中能获取到选中的option
const selectedItem: any = await window.showQuickPick(itemList, {canPickMany: false, placeHolder: "未找到匹配的国际化Key"});
const editor: TextEditor | undefined = window.activeTextEditor;
editor?.edit(editBuilder => {
editBuilder.replace(editor.selection, selectedItem.label);
});
}
// -最后别忘了在 vscode extension的统一入口 extension.ts中注册命令
export function activate(context: vscode.ExtensionContext) {
// ...
new FindSelectionCommand().registerCommand(context);
// ...
}