From f68e916942d3f5dca837979956cd9262f3052859 Mon Sep 17 00:00:00 2001 From: pqcqaq <905739777@qq.com> Date: Fri, 1 Nov 2024 13:39:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BE=9B=E8=BD=AC=E6=8D=A2=E4=B8=BAmo?= =?UTF-8?q?dule=20less=E7=9A=84=E5=86=99=E6=B3=95=E7=9A=84=E5=BF=AB?= =?UTF-8?q?=E9=80=9F=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/extension.ts | 3 ++ src/plugins/styleConvert.ts | 62 +++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 src/plugins/styleConvert.ts diff --git a/src/extension.ts b/src/extension.ts index 0b44698..c1781e9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -38,6 +38,7 @@ import { activateTriggerPlugin, deactivateTriggerPlugin, } from './plugins/oakTriggers'; +import { activateStyleConvert, deactivateStyleConvert } from './plugins/StyleConvert'; // 初始化配置 // 查找工作区的根目录中的oak.config.json文件,排除src和node_modules目录 @@ -189,6 +190,7 @@ export async function activate(context: vscode.ExtensionContext) { ...oakPathHighlighter ); createFileWatcher(context); + activateStyleConvert(context); } catch (error) { console.error('激活插件时出错:', error); } @@ -273,4 +275,5 @@ export function deactivate() { deactivateOakLocale(); deactivateOakComponentPropsLinkProvider(); stopWorker(); + deactivateStyleConvert(); } diff --git a/src/plugins/styleConvert.ts b/src/plugins/styleConvert.ts new file mode 100644 index 0000000..9a33590 --- /dev/null +++ b/src/plugins/styleConvert.ts @@ -0,0 +1,62 @@ +import * as vscode from 'vscode'; + +class ClassNameConversionProvider implements vscode.CodeActionProvider { + public provideCodeActions( + document: vscode.TextDocument, + range: vscode.Range, + context: vscode.CodeActionContext, + token: vscode.CancellationToken + ): vscode.CodeAction[] | undefined { + const classNameAttr = this.getClassNameAttr(document, range); + if (!classNameAttr) { + return; + } + + const fix = new vscode.CodeAction('转换为ModuleLess写法', vscode.CodeActionKind.QuickFix); + fix.edit = new vscode.WorkspaceEdit(); + fix.edit.replace( + document.uri, + classNameAttr.range, + this.convertToModuleStyle(classNameAttr.text) + ); + + return [fix]; + } + + private getClassNameAttr(document: vscode.TextDocument, range: vscode.Range): { text: string, range: vscode.Range } | undefined { + const line = document.lineAt(range.start.line); + const classNameMatch = line.text.match(/className\s*=\s*(['"])([^'"]+)(['"])/); + if (classNameMatch) { + const start = line.text.indexOf(classNameMatch[0]); + const end = start + classNameMatch[0].length; + return { + text: classNameMatch[0], + range: new vscode.Range(range.start.line, start, range.start.line, end) + }; + } + } + + private convertToModuleStyle(classNameAttr: string): string { + const classes = classNameAttr.match(/(['"])([^'"]+)(['"])/)?.[2]; + const convertedClasses = classes?.split(' ') + .map(cls => `\${Styles.${cls}}`) + .join(' '); + return `className={\`${convertedClasses}\`}`; + } +} + +const provider = vscode.languages.registerCodeActionsProvider( + { scheme: 'file', language: 'typescriptreact' }, + new ClassNameConversionProvider(), + { + providedCodeActionKinds: [vscode.CodeActionKind.QuickFix] + } +); + +export function activateStyleConvert(context: vscode.ExtensionContext) { + context.subscriptions.push(provider); +} + +export function deactivateStyleConvert() { + provider.dispose(); +}