feat: parser支持自定义指令

This commit is contained in:
“chenhuachun”
2026-02-06 17:49:27 +08:00
parent 000f5b614f
commit ee98d665cd
5 changed files with 73 additions and 25 deletions

View File

@@ -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 = {

View File

@@ -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<string, JSFunction>;
dataSources?: Record<string, DataSourceSchema>;
directives?: Record<string, JSExpression>;
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<string, JSExpression> = {};
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;
}

View File

@@ -37,6 +37,7 @@ import { type ImportStatement } from './scripts';
let __slots: BlockSlot[] = [];
let __context: Record<string, Set<string>> = {};
let __handlers: Record<string, JSFunction> = {};
let __directives: Record<string, JSExpression> = {};
let __styles: CSSRules = {};
let __platform: PlatformType = 'web';
let __imports: ImportStatement[] = [];
@@ -46,6 +47,7 @@ export interface ParseTemplateOptions {
imports?: ImportStatement[];
handlers?: Record<string, JSFunction>;
styles?: CSSRules;
directives?: Record<string, JSExpression>;
}
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<string, boolean>
);
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;
}