babel-plugin-vasille 5.0.4 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -5
- package/lib/index.js +1 -0
- package/lib/jsx.js +31 -6
- package/lib/lib.js +13 -0
- package/lib/mesh.js +54 -3
- package/lib/process-types.js +83 -0
- package/lib/transformer.js +36 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
`SteelFrameKit` is a front-end development kit, which is developed to provide fault tolerant web applications.
|
|
6
6
|
|
|
7
|
-
[](https://www.npmjs.com/package/steel-frame)
|
|
8
8
|
[](https://deepwiki.com/vasille-js/steel-frame)
|
|
9
9
|
[](https://coveralls.io/github/vasille-js/steel-frame?branch=v5)
|
|
10
10
|
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
- [How POWERFUL is SteelFrameKit](#how-powerful-is-steelframekit)
|
|
22
22
|
- [Road map](#road-map)
|
|
23
23
|
- [Change log](#change-log)
|
|
24
|
+
- [5.1](#51)
|
|
24
25
|
- [5.0](#50)
|
|
25
26
|
- [4.0 - 4.3](#40---43)
|
|
26
27
|
- [3.0 - 3.2](#30---32)
|
|
@@ -119,10 +120,15 @@ All of these are supported:
|
|
|
119
120
|
## Change log
|
|
120
121
|
|
|
121
122
|
We respect semantic versioning:
|
|
122
|
-
-
|
|
123
|
-
-
|
|
123
|
+
- A major version is increased when we make incompatible API changes.
|
|
124
|
+
- A minor version is increased when we add functionality.
|
|
124
125
|
- Patch version is increased when we fix bugs.
|
|
125
126
|
|
|
127
|
+
### 5.1
|
|
128
|
+
|
|
129
|
+
Add support for web components compile target `web build components`.
|
|
130
|
+
_Web components as custom tags are supported in any version._
|
|
131
|
+
|
|
126
132
|
### 5.0
|
|
127
133
|
|
|
128
134
|
- Add support for context and dependencies injection.
|
|
@@ -142,7 +148,7 @@ We respect semantic versioning:
|
|
|
142
148
|
### 3.0 - 3.2
|
|
143
149
|
|
|
144
150
|
- Switch to a babel plugin to compile components code. **[API change]**
|
|
145
|
-
- 100% of code has been covered with unit tests.
|
|
151
|
+
- 100% of the code has been covered with unit tests.
|
|
146
152
|
- New developement direction: `keep it simple`.
|
|
147
153
|
|
|
148
154
|
### 2.0 - 2.3
|
|
@@ -152,7 +158,7 @@ We respect semantic versioning:
|
|
|
152
158
|
|
|
153
159
|
### 1.0 - 1.2
|
|
154
160
|
|
|
155
|
-
- Initial version of core library.
|
|
161
|
+
- Initial version of a core library.
|
|
156
162
|
- Developemnt direction: `performance-first`.
|
|
157
163
|
|
|
158
164
|
## Questions
|
package/lib/index.js
CHANGED
package/lib/jsx.js
CHANGED
|
@@ -615,12 +615,37 @@ function transformJsxElement(path, conditions, internal) {
|
|
|
615
615
|
}
|
|
616
616
|
return ret;
|
|
617
617
|
}
|
|
618
|
-
|
|
619
|
-
t.
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
618
|
+
if (internal.shadow && mapped === "Slot") {
|
|
619
|
+
const model = props.find(item => t.isObjectProperty(item) && t.isIdentifier(item.key) && item.key.name === "model");
|
|
620
|
+
const modelName = t.isObjectProperty(model) &&
|
|
621
|
+
((t.isIdentifier(model.value) && model.value.name) ||
|
|
622
|
+
((t.isMemberExpression(model.value) || t.isOptionalMemberExpression(model.value)) &&
|
|
623
|
+
t.isIdentifier(model.value.property) &&
|
|
624
|
+
model.value.property.name));
|
|
625
|
+
const call = t.callExpression(t.memberExpression(internal_js_1.ctx, t.identifier("tag")), [
|
|
626
|
+
t.stringLiteral("slot"),
|
|
627
|
+
t.objectExpression(modelName && modelName !== "slot"
|
|
628
|
+
? [
|
|
629
|
+
t.objectProperty(t.identifier("a"), t.objectExpression([t.objectProperty(t.identifier("name"), t.stringLiteral(modelName))])),
|
|
630
|
+
]
|
|
631
|
+
: []),
|
|
632
|
+
...(run ? [run] : []),
|
|
633
|
+
]);
|
|
634
|
+
run = t.arrowFunctionExpression([internal_js_1.ctx], call);
|
|
635
|
+
}
|
|
636
|
+
const localComponentName = internal.shadow && internal.componentsImports.get(name.name);
|
|
637
|
+
const call = localComponentName
|
|
638
|
+
? t.callExpression(t.memberExpression(internal_js_1.ctx, t.identifier("tag")), [
|
|
639
|
+
t.stringLiteral((0, lib_js_1.toKebabCase)(localComponentName)),
|
|
640
|
+
t.objectExpression([t.objectProperty(t.identifier("b"), t.objectExpression(props))]),
|
|
641
|
+
...(run ? [run] : []),
|
|
642
|
+
])
|
|
643
|
+
: t.callExpression(t.identifier(name.name), [
|
|
644
|
+
t.objectExpression(props),
|
|
645
|
+
internal_js_1.ctx,
|
|
646
|
+
...(run ? [run] : internal.devLayer ? [t.buildUndefinedNode()] : []),
|
|
647
|
+
...(internal.devLayer ? [(0, transformer_1.nodeToStaticPosition)(path.node)] : []),
|
|
648
|
+
]);
|
|
624
649
|
call.loc = path.node.loc;
|
|
625
650
|
return [...ret, t.expressionStatement(call)];
|
|
626
651
|
}
|
package/lib/lib.js
CHANGED
|
@@ -46,6 +46,7 @@ exports.mapModel = mapModel;
|
|
|
46
46
|
exports.processModelCall = processModelCall;
|
|
47
47
|
exports.checkReactiveName = checkReactiveName;
|
|
48
48
|
exports.checkNonReactiveName = checkNonReactiveName;
|
|
49
|
+
exports.toKebabCase = toKebabCase;
|
|
49
50
|
const t = __importStar(require("@babel/types"));
|
|
50
51
|
const expression_js_1 = require("./expression.js");
|
|
51
52
|
const internal_js_1 = require("./internal.js");
|
|
@@ -189,3 +190,15 @@ function checkNonReactiveName(idPath, internal) {
|
|
|
189
190
|
err(Errors.RulesOfVasille, idPath, "Non-reactive variable name must not start with $", internal);
|
|
190
191
|
}
|
|
191
192
|
}
|
|
193
|
+
function toKebabCase(name) {
|
|
194
|
+
let index = 0;
|
|
195
|
+
let fixed = name[index].toLowerCase();
|
|
196
|
+
for (index++; index < name.length; index++) {
|
|
197
|
+
const curr = name[index];
|
|
198
|
+
if (curr === curr.toUpperCase()) {
|
|
199
|
+
fixed += "-";
|
|
200
|
+
}
|
|
201
|
+
fixed += curr.toLowerCase();
|
|
202
|
+
}
|
|
203
|
+
return fixed;
|
|
204
|
+
}
|
package/lib/mesh.js
CHANGED
|
@@ -60,6 +60,7 @@ const order_check_1 = require("./order-check");
|
|
|
60
60
|
const router_1 = require("./router");
|
|
61
61
|
const utils_1 = require("./utils");
|
|
62
62
|
const transformer_1 = require("./transformer");
|
|
63
|
+
const process_types_1 = require("./process-types");
|
|
63
64
|
function meshOrIgnoreAllExpressions(nodePaths, internal) {
|
|
64
65
|
for (const path of nodePaths) {
|
|
65
66
|
/* istanbul ignore else */
|
|
@@ -73,9 +74,19 @@ function meshAllExpressions(nodePaths, internal) {
|
|
|
73
74
|
meshExpression(path, internal);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
|
-
|
|
77
|
+
const restrictedNames = [
|
|
78
|
+
"annotation-xml",
|
|
79
|
+
"color-profile",
|
|
80
|
+
"font-face",
|
|
81
|
+
"font-face-src",
|
|
82
|
+
"font-face-uri",
|
|
83
|
+
"font-face-format",
|
|
84
|
+
"font-face-name",
|
|
85
|
+
"missing-glyph",
|
|
86
|
+
];
|
|
87
|
+
function meshComposeCall(name, path, internal, isExported = false) {
|
|
77
88
|
const args = path.isCallExpression() && path.get("arguments");
|
|
78
|
-
const arg = args && (args[0].isFunctionExpression() || args[0].isArrowFunctionExpression()) && args[0];
|
|
89
|
+
const arg = args && args[0] && (args[0].isFunctionExpression() || args[0].isArrowFunctionExpression()) && args[0];
|
|
79
90
|
if (!args || !arg || args.length !== 1) {
|
|
80
91
|
return (0, lib_js_1.err)(lib_js_1.Errors.IncorrectArguments, path, "Invalid arguments number", internal);
|
|
81
92
|
}
|
|
@@ -84,6 +95,33 @@ function meshComposeCall(name, path, internal) {
|
|
|
84
95
|
if (internal.devLayer && path.isCallExpression()) {
|
|
85
96
|
path.node.arguments.push((0, transformer_1.nodeToStaticPosition)(path.node), t.stringLiteral(name ? name : "#"));
|
|
86
97
|
}
|
|
98
|
+
if (internal.shadow && isExported && name && path.isCallExpression()) {
|
|
99
|
+
const call = path.node;
|
|
100
|
+
const generics = call.typeParameters?.params;
|
|
101
|
+
const args = call.arguments;
|
|
102
|
+
const params = (t.isFunctionExpression(args[0]) || t.isArrowFunctionExpression(args[0])) && args[0].params;
|
|
103
|
+
const annotation = (generics && generics[0]) ||
|
|
104
|
+
(params && params[1] && !t.isVoidPattern(params[1]) && params[1].typeAnnotation) ||
|
|
105
|
+
null;
|
|
106
|
+
const type = (t.isTSTypeAnnotation(annotation) && annotation.typeAnnotation) || (t.isTSType(annotation) && annotation) || null;
|
|
107
|
+
const kebabName = (0, lib_js_1.toKebabCase)(name);
|
|
108
|
+
let fields;
|
|
109
|
+
if (t.isTSTypeLiteral(type)) {
|
|
110
|
+
fields = (0, process_types_1.processTypeLiteral)(type);
|
|
111
|
+
}
|
|
112
|
+
if (t.isTSTypeReference(type)) {
|
|
113
|
+
fields = (0, process_types_1.processReference)(type, internal);
|
|
114
|
+
}
|
|
115
|
+
if (kebabName.indexOf("-") === -1 || restrictedNames.indexOf(kebabName) !== -1) {
|
|
116
|
+
(0, lib_js_1.err)(lib_js_1.Errors.ParserError, path, `The name '${kebabName}' is not allowed by WHATWG`, internal);
|
|
117
|
+
}
|
|
118
|
+
if (fields) {
|
|
119
|
+
path.node.arguments.push(t.stringLiteral(kebabName), fields);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
(0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, path, "Missing type for web component composition", internal);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
87
125
|
}
|
|
88
126
|
function meshAllUnknown(paths, internal) {
|
|
89
127
|
for (const path of paths) {
|
|
@@ -816,7 +854,7 @@ function meshStatement(path, internal) {
|
|
|
816
854
|
report(`File name is not correct, expected ${name}.ts, ${name}.tsx, ${name}.js or ${name}.jsx`);
|
|
817
855
|
}
|
|
818
856
|
}
|
|
819
|
-
meshComposeCall(id.name, initPath, internal);
|
|
857
|
+
meshComposeCall(id.name, initPath, internal, isExported);
|
|
820
858
|
}
|
|
821
859
|
// calculate call
|
|
822
860
|
else if ((0, call_js_1.calls)(initPath, ["calculate"], internal) &&
|
|
@@ -892,6 +930,19 @@ function meshStatement(path, internal) {
|
|
|
892
930
|
meshClassBody(declarationPath.get("body"), internal);
|
|
893
931
|
}
|
|
894
932
|
}
|
|
933
|
+
break;
|
|
934
|
+
}
|
|
935
|
+
case "TSInterfaceDeclaration": {
|
|
936
|
+
const declaration = path.node;
|
|
937
|
+
(0, process_types_1.registerInterface)(declaration.id.name, declaration.body.body, internal);
|
|
938
|
+
break;
|
|
939
|
+
}
|
|
940
|
+
case "TSTypeAliasDeclaration": {
|
|
941
|
+
const alias = path.node;
|
|
942
|
+
if (t.isTSTypeLiteral(alias.typeAnnotation)) {
|
|
943
|
+
(0, process_types_1.registerInterface)(alias.id.name, alias.typeAnnotation.members, internal);
|
|
944
|
+
}
|
|
945
|
+
break;
|
|
895
946
|
}
|
|
896
947
|
}
|
|
897
948
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerInterface = registerInterface;
|
|
4
|
+
exports.processUnion = processUnion;
|
|
5
|
+
exports.processType = processType;
|
|
6
|
+
exports.processSignatures = processSignatures;
|
|
7
|
+
exports.processTypeLiteral = processTypeLiteral;
|
|
8
|
+
exports.processReference = processReference;
|
|
9
|
+
const types_1 = require("@babel/types");
|
|
10
|
+
const any = 0;
|
|
11
|
+
const string = 1;
|
|
12
|
+
const number = 2;
|
|
13
|
+
const boolean = 3;
|
|
14
|
+
function registerInterface(name, members, internal) {
|
|
15
|
+
internal.interfaces.set(name, members);
|
|
16
|
+
}
|
|
17
|
+
function processUnion(type) {
|
|
18
|
+
let isString = false;
|
|
19
|
+
let isNumber = false;
|
|
20
|
+
let isBoolean = false;
|
|
21
|
+
let isAny = false;
|
|
22
|
+
for (const keyword of type.types) {
|
|
23
|
+
if ((0, types_1.isTSStringKeyword)(keyword)) {
|
|
24
|
+
isString = true;
|
|
25
|
+
}
|
|
26
|
+
else if ((0, types_1.isTSNumberKeyword)(keyword)) {
|
|
27
|
+
isNumber = true;
|
|
28
|
+
}
|
|
29
|
+
else if ((0, types_1.isTSBooleanKeyword)(keyword)) {
|
|
30
|
+
isBoolean = true;
|
|
31
|
+
}
|
|
32
|
+
else if (!(0, types_1.isTSNullKeyword)(keyword) && !(0, types_1.isTSUndefinedKeyword)(keyword)) {
|
|
33
|
+
isAny = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (isAny) {
|
|
37
|
+
return any;
|
|
38
|
+
}
|
|
39
|
+
if (isString) {
|
|
40
|
+
return string;
|
|
41
|
+
}
|
|
42
|
+
if (isNumber && !isBoolean) {
|
|
43
|
+
return number;
|
|
44
|
+
}
|
|
45
|
+
if (isBoolean && !isNumber) {
|
|
46
|
+
return boolean;
|
|
47
|
+
}
|
|
48
|
+
return any;
|
|
49
|
+
}
|
|
50
|
+
function processType(type) {
|
|
51
|
+
if ((0, types_1.isTSUnionType)(type)) {
|
|
52
|
+
return processUnion(type);
|
|
53
|
+
}
|
|
54
|
+
if ((0, types_1.isTSStringKeyword)(type)) {
|
|
55
|
+
return string;
|
|
56
|
+
}
|
|
57
|
+
if ((0, types_1.isTSNumberKeyword)(type)) {
|
|
58
|
+
return number;
|
|
59
|
+
}
|
|
60
|
+
if ((0, types_1.isTSBooleanKeyword)(type)) {
|
|
61
|
+
return boolean;
|
|
62
|
+
}
|
|
63
|
+
return any;
|
|
64
|
+
}
|
|
65
|
+
function processSignatures(members) {
|
|
66
|
+
const props = [];
|
|
67
|
+
for (const member of members) {
|
|
68
|
+
if ((0, types_1.isTSPropertySignature)(member)) {
|
|
69
|
+
props.push((0, types_1.objectProperty)(member.key, (0, types_1.numericLiteral)(member.typeAnnotation ? processType(member.typeAnnotation.typeAnnotation) : any)));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return (0, types_1.objectExpression)(props);
|
|
73
|
+
}
|
|
74
|
+
function processTypeLiteral(literal) {
|
|
75
|
+
return processSignatures(literal.members);
|
|
76
|
+
}
|
|
77
|
+
function processReference(id, internal) {
|
|
78
|
+
/* istanbul ignore else */
|
|
79
|
+
if ((0, types_1.isIdentifier)(id.typeName)) {
|
|
80
|
+
const members = internal.interfaces.get(id.typeName.name);
|
|
81
|
+
return members ? processSignatures(members) : undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
package/lib/transformer.js
CHANGED
|
@@ -69,12 +69,44 @@ function extractText(node) {
|
|
|
69
69
|
// no case found for string literal
|
|
70
70
|
return node.name;
|
|
71
71
|
}
|
|
72
|
+
function extractComponentImport(node, internal) {
|
|
73
|
+
const name = node.source.value;
|
|
74
|
+
const match = /^(@\/components|\.)\/([^\/.]+)\.[tj]sx?$/.exec(name);
|
|
75
|
+
if (!match) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const filename = match[2];
|
|
79
|
+
const toRemove = [];
|
|
80
|
+
for (const specifier of node.specifiers) {
|
|
81
|
+
if (t.isImportDefaultSpecifier(specifier)) {
|
|
82
|
+
toRemove.push(specifier);
|
|
83
|
+
internal.componentsImports.set(specifier.local.name, filename);
|
|
84
|
+
}
|
|
85
|
+
if (t.isImportSpecifier(specifier)) {
|
|
86
|
+
const imported = extractText(specifier.imported);
|
|
87
|
+
// the exported component name must match the file name
|
|
88
|
+
/* istanbul ignore else */
|
|
89
|
+
if (imported === filename) {
|
|
90
|
+
toRemove.push(specifier);
|
|
91
|
+
internal.componentsImports.set(specifier.local.name, filename);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/* istanbul ignore else */
|
|
96
|
+
if (toRemove.length) {
|
|
97
|
+
node.specifiers = node.specifiers.filter(item => !toRemove.includes(item));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
72
100
|
// Handles import declarations and updates internal state
|
|
73
101
|
function handleImportDeclaration(statementPath, internal, ids) {
|
|
74
102
|
const statement = statementPath.node;
|
|
75
103
|
const name = imports.get(statement.source.value);
|
|
76
|
-
if (!name)
|
|
104
|
+
if (!name) {
|
|
105
|
+
if (internal.shadow) {
|
|
106
|
+
extractComponentImport(statement, internal);
|
|
107
|
+
}
|
|
77
108
|
return;
|
|
109
|
+
}
|
|
78
110
|
statement.source.value = internal.replaceWeb;
|
|
79
111
|
internal.prefix = name;
|
|
80
112
|
for (const specifier of statement.specifiers) {
|
|
@@ -177,6 +209,8 @@ function transformProgram(path, filename, opts) {
|
|
|
177
209
|
const internal = {
|
|
178
210
|
stack: new internal_js_1.StackedStates(),
|
|
179
211
|
mapping: new Map(),
|
|
212
|
+
interfaces: new Map(),
|
|
213
|
+
componentsImports: new Map(),
|
|
180
214
|
global: "",
|
|
181
215
|
prefix: "Vasille_",
|
|
182
216
|
importStatement: null,
|
|
@@ -189,6 +223,7 @@ function transformProgram(path, filename, opts) {
|
|
|
189
223
|
replaceWeb: opts.replaceWeb ?? (opts.devLayer ? "steel-frame" : "vasille-web"),
|
|
190
224
|
headTag: opts.headTag,
|
|
191
225
|
bodyTag: opts.bodyTag,
|
|
226
|
+
shadow: opts.shadow,
|
|
192
227
|
ref(arg, area, name) {
|
|
193
228
|
if (opts.devLayer) {
|
|
194
229
|
return named(call("ref", [arg ? arg : t.buildUndefinedNode(), nodeToStaticPosition(area), getInspector()]), name);
|