-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgenGetTemplateMethod.ts
109 lines (98 loc) · 3.32 KB
/
genGetTemplateMethod.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import type { File } from '@babel/types';
import * as t from '@babel/types';
import babelTraverse from '@babel/traverse';
import { isBoolean } from '../utils';
import type { CompileTemplateResult } from '../compileTemplate';
interface objectExpression {
[key: string]: t.Expression;
}
function createObjectProperty(key: string, value: t.Expression) {
return t.objectProperty(t.identifier(key), value);
}
function createObjectExpression(obj: objectExpression) {
return t.objectExpression(Object.entries(obj).map(([key, value]) => {
return createObjectProperty(key, value);
}));
}
function createArrayExpression(elements) {
return t.arrayExpression(elements);
}
function createIdentifier(value) {
return value === '' ? t.stringLiteral('') : t.identifier(value);
}
/**
*
* get template() {
* return []
* }
*/
function cretateGetTemplateClassMethod(returnExpression) {
return t.classMethod(
'get',
t.identifier('template'),
[],
t.blockStatement(
[t.returnStatement(returnExpression)],
),
);
}
const templateFlag = t.booleanLiteral(true);
export default function genGetTemplateMethod(ast: File, templateResult: CompileTemplateResult): void {
babelTraverse(ast, {
ClassDeclaration(path) {
// export default class
if (t.isExportDefaultDeclaration(path.parent)) {
const { node } = path;
// class must extended from HTMLElement
if (t.isIdentifier(node.superClass) && node.superClass.name === 'HTMLElement') {
const { templateString, values } = templateResult;
const templateStringExpression = t.stringLiteral(templateString);
const templateValuesExpression = createArrayExpression(values.map(val => {
if (typeof val === 'string') {
// 1 variables
return createIdentifier(val);
} else {
// 2. events and props
/*
example:
[
{
name: 'onclick',
handler: 'onClick',
capture: true,
},
{
name: 'title',
value: '#title'
}
]
*/
return createArrayExpression(val.map(attr => {
const attributeEntries = Object.entries(attr).map(([key, val]) => {
let expression;
if (key === 'name') {
expression = t.stringLiteral(val);
} else if (key === 'value' || key === 'handler') {
expression = createIdentifier(val);
} else if (key === 'capture') {
expression = t.booleanLiteral(val);
}
return [key, expression];
});
const attributeObjectExpression = Object.fromEntries(attributeEntries);
return createObjectExpression(attributeObjectExpression);
},
));
}
}));
const returnExpression = createObjectExpression({
templateString: templateStringExpression,
templateData: templateValuesExpression,
template: templateFlag,
});
node.body.body.push(cretateGetTemplateClassMethod(returnExpression));
}
}
},
});
}