From ee98d665cdc2a7a3f2fad03eaec7d4dda7f77e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cchenhuachun=E2=80=9D?= <“samchen08@163.com”> Date: Fri, 6 Feb 2026 17:49:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20parser=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/parser/src/vue/index.ts | 6 ++-- packages/parser/src/vue/scripts.ts | 23 +++++++++++++- packages/parser/src/vue/template.ts | 28 +++++++++++++++++ packages/parser/tests/sources/test_27.ts | 39 +++++++++++------------- packages/parser/vitest.config.ts | 2 +- 5 files changed, 73 insertions(+), 25 deletions(-) diff --git a/packages/parser/src/vue/index.ts b/packages/parser/src/vue/index.ts index c339bf556..a3819f630 100644 --- a/packages/parser/src/vue/index.ts +++ b/packages/parser/src/vue/index.ts @@ -58,14 +58,16 @@ export async function parseVue(options: IParseVueOptions) { inject, handlers, imports, - dataSources + dataSources, + directives } = parseScripts(sfc.script, project); const { nodes, slots, context } = parseTemplate(id, name, sfc.template, { platform, handlers, styles, - imports + imports, + directives }); const dsl: BlockSchema = { diff --git a/packages/parser/src/vue/scripts.ts b/packages/parser/src/vue/scripts.ts index 9ee381024..fe94311c6 100644 --- a/packages/parser/src/vue/scripts.ts +++ b/packages/parser/src/vue/scripts.ts @@ -18,7 +18,8 @@ import type { BlockEmit, BlockInject, DataSourceSchema, - ProjectSchema + ProjectSchema, + JSExpression } from '@vtj/core'; import { getJSExpression, @@ -47,6 +48,7 @@ export interface ParseScriptsResult { inject?: BlockInject[]; handlers?: Record; dataSources?: Record; + directives?: Record; errors: string[]; } @@ -109,6 +111,9 @@ export function parseScripts(content: string, project: ProjectSchema) { case 'expose': result.expose = processExpose(item.value as any); break; + case 'directives': + result.directives = processDirectives(item.value as any); + break; } } @@ -560,3 +565,19 @@ function processExpose(expression: ArrayExpression) { function findApi(project: ProjectSchema, id: string) { return (project.apis || []).find((n) => n.id === id); } + +function processDirectives(expression: ObjectExpression) { + if (!expression?.properties) return {}; + const map: Record = {}; + for (const item of expression.properties) { + const { key, value } = item as any; + if (key?.name && value?.name) { + map[key.name] = map[key.name.toLowerCase()] = { + type: 'JSExpression', + value: value.name + }; + } + } + + return map; +} diff --git a/packages/parser/src/vue/template.ts b/packages/parser/src/vue/template.ts index 5a8e44c5c..6a890f8df 100644 --- a/packages/parser/src/vue/template.ts +++ b/packages/parser/src/vue/template.ts @@ -37,6 +37,7 @@ import { type ImportStatement } from './scripts'; let __slots: BlockSlot[] = []; let __context: Record> = {}; let __handlers: Record = {}; +let __directives: Record = {}; let __styles: CSSRules = {}; let __platform: PlatformType = 'web'; let __imports: ImportStatement[] = []; @@ -46,6 +47,7 @@ export interface ParseTemplateOptions { imports?: ImportStatement[]; handlers?: Record; styles?: CSSRules; + directives?: Record; } export function parseTemplate( @@ -60,6 +62,7 @@ export function parseTemplate( __styles = options?.styles || {}; __platform = options?.platform || 'web'; __imports = options?.imports || []; + __directives = options?.directives || {}; const result = compileTemplate({ id, @@ -213,6 +216,8 @@ function getDirectives( branches?: any[] ) { const directives: NodeDirective[] = []; + const builtIns = ['if', 'for', 'model', 'show', 'bind', 'html']; + // v-if if ( branches && @@ -249,6 +254,7 @@ function getDirectives( } }); } + if (node.type === NodeTypes.ELEMENT) { const directivProps = node.props.filter( (prop) => prop.type === NodeTypes.DIRECTIVE @@ -291,6 +297,28 @@ function getDirectives( value: getJSExpression(vHtml.exp?.loc.source || '') }); } + + const others = directivProps.filter((n) => !builtIns.includes(n.name)); + + for (const item of others) { + const modifiers = (item.modifiers || []).reduce( + (result, cur) => { + result[cur.content] = true; + return result; + }, + {} as Record + ); + const arg: string = (item as any).arg?.content || undefined; + const directiveName = __directives[item.name]; + if (directiveName) { + directives.push({ + name: directiveName, + value: getJSExpression(item.exp?.loc.source || ''), + arg, + modifiers + }); + } + } } return directives; } diff --git a/packages/parser/tests/sources/test_27.ts b/packages/parser/tests/sources/test_27.ts index 26c1bf82d..e28becbb2 100644 --- a/packages/parser/tests/sources/test_27.ts +++ b/packages/parser/tests/sources/test_27.ts @@ -1,36 +1,33 @@ export const test_27 = ` - - + `; diff --git a/packages/parser/vitest.config.ts b/packages/parser/vitest.config.ts index 7437697c5..d0090dcf4 100644 --- a/packages/parser/vitest.config.ts +++ b/packages/parser/vitest.config.ts @@ -3,6 +3,6 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { environment: 'jsdom', - include: ['**/uni.test.ts'] + include: ['**/vue.test.ts'] } });