babel-plugin-vasille 5.0.3 → 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 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
- [![npm](https://img.shields.io/npm/v/steel-frame?style=flat-square)](https://www.npmjs.com/package/steel-frame)
7
+ [![npm](https://img.shields.io/npm/v/steel-frame?style=round-square)](https://www.npmjs.com/package/steel-frame)
8
8
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/vasille-js/steel-frame)
9
9
  [![Coverage Status](https://coveralls.io/repos/github/vasille-js/steel-frame/badge.svg?branch=v5)](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
- - Major version is increased when we make incompatible API changes.
123
- - Minor version is increased when we add functionality.
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/call.js CHANGED
@@ -97,12 +97,14 @@ function calls(path, names, internal) {
97
97
  }
98
98
  let propName = null;
99
99
  if (t.isMemberExpression(callee)) {
100
- /* istanbul ignore else */
101
100
  if (t.isIdentifier(callee.property)) {
102
101
  propName = callee.property.name;
103
102
  }
104
- else if (t.isStringLiteral(callee.property)) {
105
- propName = callee.property.value;
103
+ else {
104
+ /* istanbul ignore else */
105
+ if (t.isStringLiteral(callee.property)) {
106
+ propName = callee.property.value;
107
+ }
106
108
  }
107
109
  }
108
110
  if (propName &&
package/lib/expression.js CHANGED
@@ -141,13 +141,13 @@ function meshMember(path) {
141
141
  }
142
142
  }
143
143
  function meshLValue(path, internal) {
144
- /* istanbul ignore else */
145
144
  if (path.isIdentifier()) {
146
145
  meshIdentifier(path);
147
146
  }
148
147
  else if (path.isMemberExpression() || path.isOptionalMemberExpression()) {
149
148
  const object = path.get("object");
150
149
  meshMember(path);
150
+ /* istanbul ignore else */
151
151
  if (object.isLVal()) {
152
152
  meshLValue(object, internal);
153
153
  }
@@ -160,8 +160,11 @@ function meshLValue(path, internal) {
160
160
  }
161
161
  }
162
162
  }
163
- else if (path.isRestElement()) {
164
- meshLValue(path.get("argument"), internal);
163
+ else {
164
+ /* istanbul ignore else */
165
+ if (path.isRestElement()) {
166
+ meshLValue(path.get("argument"), internal);
167
+ }
165
168
  }
166
169
  }
167
170
  function checkNode(path, internal, area, name) {
@@ -214,12 +217,14 @@ function checkAllExpressions(nodePaths, search) {
214
217
  }
215
218
  function checkAllUnknown(paths, internal) {
216
219
  for (const path of paths) {
217
- /* istanbul ignore else */
218
220
  if (path.isSpreadElement()) {
219
221
  checkExpression(path.get("argument"), internal);
220
222
  }
221
- else if (path.isExpression()) {
222
- checkExpression(path, internal);
223
+ else {
224
+ /* istanbul ignore else */
225
+ if (path.isExpression()) {
226
+ checkExpression(path, internal);
227
+ }
223
228
  }
224
229
  }
225
230
  }
package/lib/index.js CHANGED
@@ -13,6 +13,7 @@ function default_1() {
13
13
  replaceWeb: typeof params.opts.replaceWeb === "string" ? params.opts.replaceWeb : undefined,
14
14
  headTag: !!params.opts.headTag,
15
15
  bodyTag: !!params.opts.bodyTag,
16
+ shadow: !!params.opts.shadow,
16
17
  });
17
18
  },
18
19
  },
package/lib/jsx.js CHANGED
@@ -289,7 +289,6 @@ function transformJsxElement(path, conditions, internal) {
289
289
  }
290
290
  else if (name.name === "class") {
291
291
  // class={[..]}
292
- /* istanbul ignore else */
293
292
  if (valuePath.isJSXExpressionContainer() && t.isArrayExpression(valuePath.node.expression)) {
294
293
  const arrayExprPath = valuePath.get("expression");
295
294
  for (const elementPath of arrayExprPath.get("elements")) {
@@ -354,19 +353,16 @@ function transformJsxElement(path, conditions, internal) {
354
353
  }
355
354
  attrs.push(t.objectProperty(t.identifier("class"), expressionPath.node));
356
355
  }
357
- // class={name}
358
- else if (expressionPath && expressionPath.isExpression()) {
359
- (0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, {}, expressionPath.node);
360
- attrs.push(t.objectProperty(t.identifier("class"), expressionPath.node));
361
- }
362
356
  // class="a b"
363
- else if (valuePath.isStringLiteral()) {
364
- classStatic.push(valuePath.node);
357
+ else {
358
+ /* istanbul ignore else */
359
+ if (valuePath.isStringLiteral()) {
360
+ classStatic.push(valuePath.node);
361
+ }
365
362
  }
366
363
  }
367
364
  else if (name.name === "style") {
368
365
  // style={{..}}
369
- /* istanbul ignore else */
370
366
  if (expressionPath && expressionPath.isObjectExpression()) {
371
367
  for (const propPath of expressionPath.get("properties")) {
372
368
  // style={{a: b}}
@@ -427,11 +423,14 @@ function transformJsxElement(path, conditions, internal) {
427
423
  attrs.push(t.objectProperty(t.identifier("style"), expressionPath.node));
428
424
  }
429
425
  // style={`a: ${b}px`}
430
- else if (expressionPath && expressionPath.isExpression()) {
431
- if ((0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, { strong: true }, expressionPath.node)) {
432
- console.warn(attrPath.buildCodeFrameError("Vasille: This will slow down your application"));
426
+ else {
427
+ /* istanbul ignore else */
428
+ if (expressionPath && expressionPath.isExpression()) {
429
+ if ((0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, { strong: true }, expressionPath.node)) {
430
+ console.warn(attrPath.buildCodeFrameError("Vasille: This will slow down your application"));
431
+ }
432
+ attrs.push(t.objectProperty(t.identifier("style"), expressionPath.node));
433
433
  }
434
- attrs.push(t.objectProperty(t.identifier("style"), expressionPath.node));
435
434
  }
436
435
  }
437
436
  else if (name.name === "callback" && expressionPath && expressionPath.isExpression()) {
@@ -439,7 +438,6 @@ function transformJsxElement(path, conditions, internal) {
439
438
  callback = expressionPath.node;
440
439
  }
441
440
  else {
442
- /* istanbul ignore else */
443
441
  if (expressionPath && expressionPath.isExpression()) {
444
442
  (0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, {}, expressionPath.node);
445
443
  attrs.push(idToProp(name, expressionPath.node));
@@ -455,7 +453,6 @@ function transformJsxElement(path, conditions, internal) {
455
453
  if (t.isJSXNamespacedName(name)) {
456
454
  if (name.namespace.name === "bind") {
457
455
  let pushed = false;
458
- /* istanbul ignore else */
459
456
  if (expressionPath) {
460
457
  /* istanbul ignore else */
461
458
  if (expressionPath.isExpression()) {
@@ -464,9 +461,12 @@ function transformJsxElement(path, conditions, internal) {
464
461
  pushed = true;
465
462
  }
466
463
  }
467
- else if (t.isStringLiteral(attr.value)) {
468
- bind.push(idToProp(name.name, attr.value));
469
- pushed = true;
464
+ else {
465
+ /* istanbul ignore else */
466
+ if (t.isStringLiteral(attr.value)) {
467
+ bind.push(idToProp(name.name, attr.value));
468
+ pushed = true;
469
+ }
470
470
  }
471
471
  if (!pushed) {
472
472
  bind.push(idToProp(name.name, t.booleanLiteral(true)));
@@ -527,7 +527,6 @@ function transformJsxElement(path, conditions, internal) {
527
527
  const valuePath = attrPath.isJSXAttribute() && attrPath.get("value");
528
528
  const needReactive = attr.name.name.startsWith("$");
529
529
  // <A prop=".."/>
530
- /* istanbul ignore else */
531
530
  if (t.isStringLiteral(attr.value)) {
532
531
  props.push(idToProp(attr.name, needReactive ? internal.ref(attr.value, attr, undefined) : attr.value));
533
532
  }
@@ -538,8 +537,11 @@ function transformJsxElement(path, conditions, internal) {
538
537
  const value = transformJsxExpressionContainer(valuePath, internal, !isSystem || attr.name.name === "slot", isSystem && attr.name.name === "slot", requiresReactive, !requiresReactive);
539
538
  props.push(idToProp(attr.name, value));
540
539
  }
541
- else if (!attr.value) {
542
- props.push(idToProp(attr.name, needReactive ? internal.ref(t.booleanLiteral(true), attr, undefined) : t.booleanLiteral(true)));
540
+ else {
541
+ /* istanbul ignore else */
542
+ if (!attr.value) {
543
+ props.push(idToProp(attr.name, needReactive ? internal.ref(t.booleanLiteral(true), attr, undefined) : t.booleanLiteral(true)));
544
+ }
543
545
  }
544
546
  }
545
547
  // <A {...arg}/>
@@ -613,12 +615,37 @@ function transformJsxElement(path, conditions, internal) {
613
615
  }
614
616
  return ret;
615
617
  }
616
- const call = t.callExpression(t.identifier(name.name), [
617
- t.objectExpression(props),
618
- internal_js_1.ctx,
619
- ...(run ? [run] : internal.devLayer ? [t.buildUndefinedNode()] : []),
620
- ...(internal.devLayer ? [(0, transformer_1.nodeToStaticPosition)(path.node)] : []),
621
- ]);
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
+ ]);
622
649
  call.loc = path.node.loc;
623
650
  return [...ret, t.expressionStatement(call)];
624
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");
@@ -179,7 +180,8 @@ function processModelCall(path, usage, type, isConst, internal, name) {
179
180
  : arrayModel(args, usage, internal, name));
180
181
  }
181
182
  function checkReactiveName(idPath, internal) {
182
- if (!(idPath.isIdentifier() && idPath.node.name.startsWith("$"))) {
183
+ if (!(idPath.isIdentifier() && idPath.node.name.startsWith("$")) &&
184
+ !(idPath.isStringLiteral() && idPath.node.value.startsWith("$"))) {
183
185
  err(Errors.RulesOfVasille, idPath, "Reactive variable name must start with $", internal);
184
186
  }
185
187
  }
@@ -188,3 +190,15 @@ function checkNonReactiveName(idPath, internal) {
188
190
  err(Errors.RulesOfVasille, idPath, "Non-reactive variable name must not start with $", internal);
189
191
  }
190
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
- function meshComposeCall(name, path, internal) {
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,15 +95,44 @@ 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) {
90
- /* istanbul ignore else */
91
128
  if (path.isSpreadElement()) {
92
129
  meshExpression(path.get("argument"), internal);
93
130
  }
94
- else if (path.isExpression()) {
95
- meshExpression(path, internal);
131
+ else {
132
+ /* istanbul ignore else */
133
+ if (path.isExpression()) {
134
+ meshExpression(path, internal);
135
+ }
96
136
  }
97
137
  }
98
138
  }
@@ -168,15 +208,17 @@ function meshExpression(nodePath, internal) {
168
208
  meshAllUnknown([argPath], internal);
169
209
  }
170
210
  const loc = path.node.loc;
171
- /* istanbul ignore else */
172
211
  if ((0, call_js_1.calls)(path, ["arrayModel"], internal)) {
173
212
  path.replaceWith(internal.arrayModel(argPath?.node, path.node, undefined));
174
213
  }
175
214
  else if ((0, call_js_1.calls)(path, ["mapModel"], internal)) {
176
215
  path.replaceWith(internal.mapModel(argPath?.node, path.node, undefined));
177
216
  }
178
- else if ((0, call_js_1.calls)(path, ["setModel"], internal)) {
179
- path.replaceWith(internal.setModel(argPath?.node, path.node, undefined));
217
+ else {
218
+ /* istanbul ignore else */
219
+ if ((0, call_js_1.calls)(path, ["setModel"], internal)) {
220
+ path.replaceWith(internal.setModel(argPath?.node, path.node, undefined));
221
+ }
180
222
  }
181
223
  path.node.loc = loc;
182
224
  }
@@ -265,14 +307,19 @@ function meshExpression(nodePath, internal) {
265
307
  if (t.isExpression(property) && !t.isIdentifier(property)) {
266
308
  meshOrIgnoreExpression(path.get("property"), internal);
267
309
  }
268
- if ((0, expression_js_1.memberIsIValue)(node) && !(0, expression_js_1.nodeIsMeshed)(path)) {
269
- if ((0, expression_js_1.exprIsSure)(path, internal)) {
270
- path.replaceWith(t.memberExpression(path.node, internal_js_1.V));
271
- }
272
- else {
273
- path.replaceWith(t.optionalMemberExpression(path.node, internal_js_1.V, false, true));
310
+ if ((0, expression_js_1.memberIsIValue)(node)) {
311
+ if (!(0, expression_js_1.nodeIsMeshed)(path)) {
312
+ if ((0, expression_js_1.exprIsSure)(path, internal)) {
313
+ path.replaceWith(t.memberExpression(path.node, internal_js_1.V));
314
+ }
315
+ else {
316
+ path.replaceWith(t.optionalMemberExpression(path.node, internal_js_1.V, false, true));
317
+ }
274
318
  }
275
319
  }
320
+ else if (node.computed && t.isIdentifier(property)) {
321
+ path.replaceWith(internal.match(t.stringLiteral(""), node, node));
322
+ }
276
323
  break;
277
324
  }
278
325
  case "BinaryExpression": {
@@ -382,7 +429,6 @@ function meshStatements(paths, internal) {
382
429
  }
383
430
  }
384
431
  function ignoreParams(path, internal, allowReactiveId) {
385
- /* istanbul ignore else */
386
432
  // param with default value
387
433
  if (path.isAssignmentPattern()) {
388
434
  const left = path.get("left");
@@ -407,6 +453,7 @@ function ignoreParams(path, internal, allowReactiveId) {
407
453
  // param is array destruction
408
454
  else if (path.isArrayPattern()) {
409
455
  for (const element of path.get("elements")) {
456
+ /* istanbul ignore else */
410
457
  if (element) {
411
458
  ignoreParams(element, internal, allowReactiveId && allowReactiveId.includes("array") && ["id", "array"]);
412
459
  if ((!allowReactiveId || !allowReactiveId.includes("array")) && element.isIdentifier()) {
@@ -437,7 +484,6 @@ function ignoreObjectPattern(pattern, internal) {
437
484
  (originName.startsWith("$") ? `rename it to "$${newName}"` : `rename it to "${newName.substring(1)}"`), internal);
438
485
  }
439
486
  const valuePath = path.get("value");
440
- /* istanbul ignore else */
441
487
  if (valuePath.isObjectPattern()) {
442
488
  /* istanbul ignore else */
443
489
  if (originName && originName.startsWith("$")) {
@@ -449,23 +495,24 @@ function ignoreObjectPattern(pattern, internal) {
449
495
  const right = valuePath.get("right");
450
496
  ignoreParams(valuePath.get("left"), internal, ["id"]);
451
497
  meshExpression(right, internal);
452
- if (property.computed && t.isIdentifier(property.key)) {
453
- right.replaceWith(internal.match(t.stringLiteral(property.key.name), right.node, property));
454
- }
455
- else if ((t.isIdentifier(property.key) && property.key.name.startsWith("$")) ||
498
+ if ((t.isIdentifier(property.key) && property.key.name.startsWith("$")) ||
456
499
  (t.isStringLiteral(property.key) && property.key.value.startsWith("$"))) {
457
500
  right.replaceWith(internal.ref(right.node, property, undefined));
458
501
  }
459
- }
460
- else if (t.isIdentifier(property.value)) {
461
- internal.stack.set(property.value.name, {});
462
- if (property.computed) {
463
- path
464
- .get("value")
465
- .replaceWith(t.assignmentPattern(property.value, internal.match(t.stringLiteral(property.value.name), null, property)));
502
+ else {
503
+ /* istanbul ignore else */
504
+ if (property.computed && !t.isStringLiteral(property.key)) {
505
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, valuePath, "Computed property can not be used in destruction", internal);
506
+ }
466
507
  }
467
- else if (property.value.name.startsWith("$")) {
468
- path.get("value").replaceWith(t.assignmentPattern(property.value, internal.ref(null, property, undefined)));
508
+ }
509
+ else {
510
+ /* istanbul ignore else */
511
+ if (t.isIdentifier(property.value)) {
512
+ internal.stack.set(property.value.name, {});
513
+ if (property.value.name.startsWith("$")) {
514
+ path.get("value").replaceWith(t.assignmentPattern(property.value, internal.ref(null, property, undefined)));
515
+ }
469
516
  }
470
517
  }
471
518
  }
@@ -477,13 +524,15 @@ function ignoreObjectPattern(pattern, internal) {
477
524
  function reactiveArrayPattern(path, internal) {
478
525
  if (path.isArrayPattern()) {
479
526
  path.get("elements").forEach((element, index) => {
480
- /* istanbul ignore else */
481
527
  if (index < 2) {
482
528
  (0, lib_js_1.checkReactiveName)(element, internal);
483
529
  }
484
- else if (element.isIdentifier()) {
485
- (0, lib_js_1.checkNonReactiveName)(element, internal);
486
- internal.stack.set(element.node.name, {});
530
+ else {
531
+ /* istanbul ignore else */
532
+ if (element.isIdentifier()) {
533
+ (0, lib_js_1.checkNonReactiveName)(element, internal);
534
+ internal.stack.set(element.node.name, {});
535
+ }
487
536
  }
488
537
  });
489
538
  }
@@ -519,7 +568,6 @@ function meshForHeader(path, internal) {
519
568
  }
520
569
  function meshClassBody(path, internal) {
521
570
  for (const item of path.get("body")) {
522
- /* istanbul ignore else */
523
571
  if (item.isClassMethod() || item.isClassPrivateMethod()) {
524
572
  meshFunction(item, internal);
525
573
  }
@@ -541,11 +589,11 @@ function meshClassBody(path, internal) {
541
589
  meshExpression(item.get("value"), internal);
542
590
  }
543
591
  }
544
- else if (item.isClassAccessorProperty()) {
545
- meshExpression(item.get("value"), internal);
546
- }
547
- else if (item.isClassPrivateProperty()) {
548
- meshExpression(item.get("value"), internal);
592
+ else {
593
+ /* istanbul ignore else */
594
+ if (item.isClassPrivateProperty()) {
595
+ meshExpression(item.get("value"), internal);
596
+ }
549
597
  }
550
598
  }
551
599
  }
@@ -553,7 +601,6 @@ function procedureProcessObjectExpression(path, internal, state) {
553
601
  for (const prop of path.get("properties")) {
554
602
  const keyPath = prop.get("key");
555
603
  const valuePath = prop.get("value");
556
- /* istanbul ignore else */
557
604
  if (prop.isObjectProperty()) {
558
605
  // the property name is known in compile time
559
606
  if ((!prop.node.computed || keyPath.isStringLiteral()) && valuePath.isExpression()) {
@@ -609,13 +656,16 @@ function procedureProcessObjectExpression(path, internal, state) {
609
656
  meshStatement(prop.get("body"), internal);
610
657
  internal.wrapFunctionBody(prop.node);
611
658
  }
612
- else if (prop.isSpreadElement()) {
613
- const argumentPath = prop.get("argument");
614
- if (argumentPath.isObjectExpression()) {
615
- procedureProcessObjectExpression(argumentPath, internal, state);
616
- }
617
- else {
618
- meshExpression(argumentPath, internal);
659
+ else {
660
+ /* istanbul ignore else */
661
+ if (prop.isSpreadElement()) {
662
+ const argumentPath = prop.get("argument");
663
+ if (argumentPath.isObjectExpression()) {
664
+ procedureProcessObjectExpression(argumentPath, internal, state);
665
+ }
666
+ else {
667
+ meshExpression(argumentPath, internal);
668
+ }
619
669
  }
620
670
  }
621
671
  }
@@ -804,7 +854,7 @@ function meshStatement(path, internal) {
804
854
  report(`File name is not correct, expected ${name}.ts, ${name}.tsx, ${name}.js or ${name}.jsx`);
805
855
  }
806
856
  }
807
- meshComposeCall(id.name, initPath, internal);
857
+ meshComposeCall(id.name, initPath, internal, isExported);
808
858
  }
809
859
  // calculate call
810
860
  else if ((0, call_js_1.calls)(initPath, ["calculate"], internal) &&
@@ -865,7 +915,6 @@ function meshStatement(path, internal) {
865
915
  }
866
916
  case "ExportDefaultDeclaration": {
867
917
  const declarationPath = path.get("declaration");
868
- /* istanbul ignore else */
869
918
  // export default 23;
870
919
  if (declarationPath.isExpression()) {
871
920
  meshExpression(declarationPath, internal);
@@ -875,9 +924,25 @@ function meshStatement(path, internal) {
875
924
  meshFunction(declarationPath, internal);
876
925
  }
877
926
  // export default class ..
878
- else if (declarationPath.isClassDeclaration()) {
879
- meshClassBody(declarationPath.get("body"), internal);
927
+ else {
928
+ /* istanbul ignore else */
929
+ if (declarationPath.isClassDeclaration()) {
930
+ meshClassBody(declarationPath.get("body"), internal);
931
+ }
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);
880
944
  }
945
+ break;
881
946
  }
882
947
  }
883
948
  }
@@ -898,12 +963,14 @@ function meshFunction(path, internal) {
898
963
  ignoreParams(param, internal, false);
899
964
  }
900
965
  const bodyPath = path.get("body");
901
- /* istanbul ignore else */
902
966
  if (bodyPath.isExpression()) {
903
967
  meshExpression(bodyPath, internal);
904
968
  }
905
- else if (bodyPath.isBlockStatement()) {
906
- meshStatement(bodyPath, internal);
969
+ else {
970
+ /* istanbul ignore else */
971
+ if (bodyPath.isBlockStatement()) {
972
+ meshStatement(bodyPath, internal);
973
+ }
907
974
  }
908
975
  if (path.isFunctionExpression() || path.isArrowFunctionExpression()) {
909
976
  path.replaceWith(internal.wrapFunction(path.node));
@@ -918,7 +985,6 @@ function composeExpression(path, internal) {
918
985
  switch (expr && expr.type) {
919
986
  case "CallExpression":
920
987
  case "OptionalCallExpression": {
921
- /* istanbul ignore else */
922
988
  if ((0, call_js_1.calls)(path, ["watch"], internal)) {
923
989
  (0, lib_js_1.parseCalculateCall)(path, internal, path.node, undefined);
924
990
  const args = path.node.arguments;
@@ -945,11 +1011,14 @@ function composeExpression(path, internal) {
945
1011
  }
946
1012
  path.get("callee").replaceWith(t.memberExpression(internal_js_1.ctx, t.identifier("runOnDestroy")));
947
1013
  }
948
- else if ((0, call_js_1.calls)(path, ["share"], internal)) {
949
- if (internal.stateOnly) {
950
- (0, lib_js_1.err)(lib_js_1.Errors.IncompatibleContext, path, "Stores/Models in Vasille.JS cannot share dependecies", internal);
1014
+ else {
1015
+ /* istanbul ignore else */
1016
+ if ((0, call_js_1.calls)(path, ["share"], internal)) {
1017
+ if (internal.stateOnly) {
1018
+ (0, lib_js_1.err)(lib_js_1.Errors.IncompatibleContext, path, "Stores/Models in Vasille.JS cannot share dependencies", internal);
1019
+ }
1020
+ path.node.arguments.unshift(internal_js_1.ctx);
951
1021
  }
952
- path.node.arguments.unshift(internal_js_1.ctx);
953
1022
  }
954
1023
  break;
955
1024
  }
@@ -1016,7 +1085,6 @@ function composeStatement(path, internal) {
1016
1085
  };
1017
1086
  }
1018
1087
  ignoreParams(declaration.get("id"), internal, ["id", "array"]);
1019
- /* istanbul ignore else */
1020
1088
  if ((0, call_js_1.calls)(declaration.get("init"), ["awaited"], internal)) {
1021
1089
  const callPath = declaration.get("init");
1022
1090
  reactiveArrayPattern(declaration.get("id"), internal);
@@ -1082,13 +1150,13 @@ function composeStatement(path, internal) {
1082
1150
  (0, lib_js_1.checkNonReactiveName)(idPath, internal);
1083
1151
  }
1084
1152
  // const x = { .. }
1085
- else if (t.isObjectExpression(init)) {
1153
+ else if (t.isObjectExpression(init) && !(kind === "let" && id.name.startsWith("$"))) {
1086
1154
  internal.stack.set(id.name, processObjectExpression(initPath, internal));
1087
1155
  meshInit = false;
1088
1156
  (0, lib_js_1.checkNonReactiveName)(idPath, internal);
1089
1157
  }
1090
1158
  // const a = []
1091
- else if (initPath.isArrayExpression()) {
1159
+ else if (initPath.isArrayExpression() && !(kind === "let" && id.name.startsWith("$"))) {
1092
1160
  if (kind !== "const") {
1093
1161
  (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, declaration, "Arrays must be must be declared as constants", internal);
1094
1162
  }
@@ -1100,11 +1168,28 @@ function composeStatement(path, internal) {
1100
1168
  // const s = new Set(), const m = new Map()
1101
1169
  else if (initPath.isNewExpression() &&
1102
1170
  t.isIdentifier(initPath.node.callee) &&
1103
- ["Set", "Map"].includes(initPath.node.callee.name)) {
1171
+ ["Set", "Map"].includes(initPath.node.callee.name) &&
1172
+ !(kind === "let" && id.name.startsWith("$"))) {
1104
1173
  (0, lib_js_1.processModelCall)(initPath, declaration.node, initPath.node.callee.name, kind === "const", internal, idName());
1105
1174
  meshInit = false;
1106
1175
  (0, lib_js_1.checkNonReactiveName)(idPath, internal);
1107
1176
  }
1177
+ // const x = y[z]
1178
+ else if (kind === "const" &&
1179
+ (initPath.isOptionalMemberExpression() || initPath.isMemberExpression()) &&
1180
+ initPath.node.computed &&
1181
+ t.isIdentifier(initPath.node.property)) {
1182
+ const path = initPath;
1183
+ const property = path.get("property");
1184
+ meshExpression(path.get("object"), internal);
1185
+ /* istanbul ignore else */
1186
+ if (property.isExpression()) {
1187
+ meshExpression(property, internal);
1188
+ }
1189
+ meshInit = false;
1190
+ path.replaceWith(internal.match(t.stringLiteral(id.name.startsWith("$") ? "$" : ""), path.node, declaration.node));
1191
+ }
1192
+ // let x = ..
1108
1193
  else if (kind === "let") {
1109
1194
  meshExpression(declaration.get("init"), internal);
1110
1195
  if (idPath.isIdentifier() && idPath.node.name.startsWith("$")) {
@@ -1115,6 +1200,7 @@ function composeStatement(path, internal) {
1115
1200
  }
1116
1201
  meshInit = false;
1117
1202
  }
1203
+ // const x = ..
1118
1204
  else {
1119
1205
  const isReactive = (0, lib_js_1.exprCall)(declaration.get("init"), declaration.node.init, internal, {
1120
1206
  name: idName(),
@@ -1129,9 +1215,6 @@ function composeStatement(path, internal) {
1129
1215
  meshInit = !isReactive;
1130
1216
  }
1131
1217
  }
1132
- else if (t.isObjectPattern(id)) {
1133
- ignoreObjectPattern(declaration.get("id"), internal);
1134
- }
1135
1218
  if (meshInit) {
1136
1219
  meshExpression(declaration.get("init"), internal);
1137
1220
  }
@@ -1162,13 +1245,15 @@ function compose(path, internal, isInternalSlot, isSlot) {
1162
1245
  if (!isSlot) {
1163
1246
  internal.isComposing = true;
1164
1247
  }
1165
- /* istanbul ignore else */
1166
1248
  if (body.isExpression()) {
1167
1249
  composeExpression(body, internal);
1168
1250
  }
1169
- else if (body.isBlockStatement()) {
1170
- (0, order_check_1.checkOrder)(body.get("body"), internal);
1171
- composeStatement(body, internal);
1251
+ else {
1252
+ /* istanbul ignore else */
1253
+ if (body.isBlockStatement()) {
1254
+ (0, order_check_1.checkOrder)(body.get("body"), internal);
1255
+ composeStatement(body, internal);
1256
+ }
1172
1257
  }
1173
1258
  if (!isSlot) {
1174
1259
  internal.isComposing = false;
@@ -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
+ }
@@ -69,34 +69,68 @@ 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) {
81
- /* istanbul ignore else */
82
113
  if (t.isImportNamespaceSpecifier(specifier)) {
83
114
  internal.global = specifier.local.name;
84
115
  internal.stylesConnected = true;
85
116
  }
86
- else if (t.isImportSpecifier(specifier)) {
87
- const imported = extractText(specifier.imported);
88
- const local = specifier.local.name;
89
- if (imported === "bind" || imported === "calculate" || imported === "watch") {
90
- ids.expr = local;
91
- }
92
- if (imported in ids) {
93
- ids[imported] = local;
94
- }
95
- internal.mapping.set(local, imported);
96
- if (imported === "styleSheet") {
97
- internal.stylesConnected = true;
117
+ else {
118
+ /* istanbul ignore else */
119
+ if (t.isImportSpecifier(specifier)) {
120
+ const imported = extractText(specifier.imported);
121
+ const local = specifier.local.name;
122
+ if (imported === "bind" || imported === "calculate" || imported === "watch") {
123
+ ids.expr = local;
124
+ }
125
+ if (imported in ids) {
126
+ ids[imported] = local;
127
+ }
128
+ internal.mapping.set(local, imported);
129
+ if (imported === "styleSheet") {
130
+ internal.stylesConnected = true;
131
+ }
132
+ internal.importStatement = statementPath;
98
133
  }
99
- internal.importStatement = statementPath;
100
134
  }
101
135
  }
102
136
  statement.specifiers = statement.specifiers.filter(spec => {
@@ -175,6 +209,8 @@ function transformProgram(path, filename, opts) {
175
209
  const internal = {
176
210
  stack: new internal_js_1.StackedStates(),
177
211
  mapping: new Map(),
212
+ interfaces: new Map(),
213
+ componentsImports: new Map(),
178
214
  global: "",
179
215
  prefix: "Vasille_",
180
216
  importStatement: null,
@@ -187,6 +223,7 @@ function transformProgram(path, filename, opts) {
187
223
  replaceWeb: opts.replaceWeb ?? (opts.devLayer ? "steel-frame" : "vasille-web"),
188
224
  headTag: opts.headTag,
189
225
  bodyTag: opts.bodyTag,
226
+ shadow: opts.shadow,
190
227
  ref(arg, area, name) {
191
228
  if (opts.devLayer) {
192
229
  return named(call("ref", [arg ? arg : t.buildUndefinedNode(), nodeToStaticPosition(area), getInspector()]), name);
@@ -236,9 +273,9 @@ function transformProgram(path, filename, opts) {
236
273
  },
237
274
  match(name, arg, area) {
238
275
  if (opts.devLayer) {
239
- return call("match", [name, arg ?? t.buildUndefinedNode(), nodeToStaticPosition(area), getInspector()]);
276
+ return call("match", [name, arg, nodeToStaticPosition(area), getInspector()]);
240
277
  }
241
- return call("match", arg ? [name, arg] : [name]);
278
+ return call("match", [name, arg]);
242
279
  },
243
280
  set(obj, field, value, area) {
244
281
  if (opts.devLayer) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "babel-plugin-vasille",
3
- "version": "5.0.3",
3
+ "version": "5.1.0",
4
4
  "description": "Convert Vasille Meta Language code to pure JavaScript",
5
5
  "main": "lib/index.js",
6
6
  "type": "commonjs",