babel-plugin-vasille 3.1.5 → 4.0.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/lib/jsx.js CHANGED
@@ -35,24 +35,30 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.transformJsx = transformJsx;
37
37
  exports.transformJsxArray = transformJsxArray;
38
+ exports.processConditions = processConditions;
38
39
  const t = __importStar(require("@babel/types"));
40
+ const call_1 = require("./call");
39
41
  const internal_js_1 = require("./internal.js");
42
+ const jsx_detect_js_1 = require("./jsx-detect.js");
40
43
  const lib_js_1 = require("./lib.js");
41
44
  const mesh_js_1 = require("./mesh.js");
42
- const jsx_detect_js_1 = require("./jsx-detect.js");
43
- function transformJsx(path, internal) {
44
- if (t.isJSXElement(path.node)) {
45
- return [transformJsxElement(path, internal)];
45
+ function transformJsx(path, conditions, internal) {
46
+ if (path.isJSXElement()) {
47
+ return transformJsxElement(path, conditions, internal);
46
48
  }
47
49
  return transformJsxArray(path.get("children"), internal);
48
50
  }
49
51
  function transformJsxArray(paths, internal) {
50
52
  const result = [];
51
- for (const path of paths) {
52
- if (t.isJSXElement(path.node) || t.isJSXFragment(path.node)) {
53
- result.push(...transformJsx(path, internal));
53
+ const conditions = { cases: null };
54
+ paths.forEach(path => {
55
+ if (!path.isJSXElement() && !(path.isJSXText() && /^\s+$/.test(path.node.value))) {
56
+ result.push(...processConditions(conditions, internal));
57
+ }
58
+ if (path.isJSXElement() || path.isJSXFragment()) {
59
+ result.push(...transformJsx(path, conditions, internal));
54
60
  }
55
- else if (t.isJSXText(path.node)) {
61
+ else if (path.isJSXText()) {
56
62
  if (!/^\s+$/.test(path.node.value)) {
57
63
  const fixed = path.node.value
58
64
  .replace(/\n\s+$/m, "")
@@ -60,6 +66,7 @@ function transformJsxArray(paths, internal) {
60
66
  .replace(/\s*\n\s*/gm, "\n");
61
67
  const call = t.callExpression(t.memberExpression(internal_js_1.ctx, t.identifier("text")), [t.stringLiteral(fixed)]);
62
68
  call.loc = path.node.loc;
69
+ /* istanbul ignore else */
63
70
  if (call.loc) {
64
71
  for (const char of path.node.value) {
65
72
  if (!/\s/.test(char)) {
@@ -78,47 +85,95 @@ function transformJsxArray(paths, internal) {
78
85
  result.push(t.expressionStatement(call));
79
86
  }
80
87
  }
81
- else if (t.isJSXExpressionContainer(path.node)) {
82
- const value = transformJsxExpressionContainer(path, internal, false, false);
88
+ else if (path.isJSXExpressionContainer()) {
89
+ const value = transformJsxExpressionContainer(path, internal, false, false, true, true);
83
90
  const call = t.callExpression(t.memberExpression(internal_js_1.ctx, t.identifier("text")), [value]);
84
91
  call.loc = value.loc;
85
92
  result.push(t.expressionStatement(call));
86
93
  }
87
94
  else {
88
- throw path.buildCodeFrameError("Vasille: Spread child is not supported");
95
+ (0, lib_js_1.err)(lib_js_1.Errors.TokenNotSupported, path, "Spread child is not supported", internal);
89
96
  }
90
- }
97
+ });
98
+ result.push(...processConditions(conditions, internal));
91
99
  return result;
92
100
  }
93
- function transformJsxExpressionContainer(path, internal, acceptSlots, isInternalSlot) {
94
- const expression = path.node.expression;
95
- const loc = expression.loc;
101
+ function transformJsxExpressionContainer(path, internal, acceptSlots, isInternalSlot, acceptsReactive, acceptsRaw) {
102
+ const expression = path.get("expression");
103
+ const loc = expression.node.loc;
96
104
  if (acceptSlots &&
97
- (t.isFunctionExpression(expression) || t.isArrowFunctionExpression(expression)) &&
98
- (0, jsx_detect_js_1.bodyHasJsx)(expression.body)) {
99
- (0, mesh_js_1.compose)(path.get("expression"), internal, isInternalSlot);
105
+ (expression.isFunctionExpression() || expression.isArrowFunctionExpression()) &&
106
+ (0, jsx_detect_js_1.bodyHasJsx)(expression.node.body)) {
107
+ (0, mesh_js_1.compose)(expression, internal, isInternalSlot, true);
100
108
  if (!isInternalSlot) {
101
- if (expression.params.length < 1) {
102
- expression.params.push(t.identifier(`_${internal.prefix}`));
109
+ if (expression.node.params.length < 1) {
110
+ expression.node.params.push(t.identifier(`_${internal.prefix}`));
103
111
  }
104
- expression.params.push(internal_js_1.ctx);
112
+ expression.node.params.push(internal_js_1.ctx);
105
113
  }
106
114
  else {
107
- expression.params.unshift(internal_js_1.ctx);
115
+ expression.node.params.unshift(internal_js_1.ctx);
108
116
  }
109
- expression.loc = loc;
110
- return expression;
117
+ expression.node.loc = loc;
118
+ return expression.node;
111
119
  }
112
- else if (isInternalSlot && (t.isFunctionExpression(expression) || t.isArrowFunctionExpression(expression))) {
113
- expression.params.unshift(internal_js_1.ctx);
120
+ else if (isInternalSlot && (expression.isFunctionExpression() || expression.isArrowFunctionExpression())) {
121
+ expression.node.params.unshift(internal_js_1.ctx);
114
122
  }
115
- let call = (0, lib_js_1.exprCall)(path.get("expression"), expression, internal);
116
- if (!call && t.isIdentifier(expression) && internal.stack.get(expression.name) === 3 /* VariableState.ReactiveObject */) {
117
- call = t.callExpression(t.memberExpression(internal.id, t.identifier("rop")), [expression]);
123
+ /* istanbul ignore else */
124
+ if (expression.isExpression()) {
125
+ if (acceptsReactive) {
126
+ // cals backward
127
+ if ((0, call_1.calls)(expression, ["backward"], internal)) {
128
+ const argPath = expression.get("arguments")[0];
129
+ if (argPath && argPath.isExpression()) {
130
+ const argValue = argPath.node;
131
+ if ((0, lib_js_1.exprCall)(argPath, argPath.node, internal, { strong: true })) {
132
+ if (!argPath.isMemberExpression() && !argPath.isIdentifier()) {
133
+ argPath.node = argValue;
134
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, argPath, "A reactive variable or object field expected, reactive expression are forward only", internal);
135
+ }
136
+ }
137
+ else {
138
+ argPath.node = argValue;
139
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, argPath, "The backward argument is not reactive", internal);
140
+ }
141
+ }
142
+ else {
143
+ (0, lib_js_1.err)(lib_js_1.Errors.IncorrectArguments, expression, "The argument is missing", internal);
144
+ }
145
+ }
146
+ // calls forward
147
+ else if ((0, call_1.calls)(expression, ["forward"], internal)) {
148
+ const argPath = expression.get("arguments")[0];
149
+ if (argPath && argPath.isExpression()) {
150
+ const argValue = argPath.node;
151
+ if (!(0, lib_js_1.exprCall)(argPath, argPath.node, internal, { strong: true })) {
152
+ argPath.node = argValue;
153
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, argPath, "A reactive expression expected, argument value is constant", internal);
154
+ }
155
+ else {
156
+ expression.node.arguments.unshift(internal_js_1.ctx);
157
+ }
158
+ }
159
+ else {
160
+ (0, lib_js_1.err)(lib_js_1.Errors.IncorrectArguments, expression, "The argument is missing", internal);
161
+ }
162
+ }
163
+ // two-side binding
164
+ else {
165
+ const isReactive = (0, lib_js_1.exprCall)(expression, expression.node, internal, { strong: !acceptsRaw });
166
+ if (!isReactive && !acceptsRaw) {
167
+ expression.replaceWith(internal.ref(expression.node));
168
+ }
169
+ }
170
+ }
171
+ else {
172
+ (0, mesh_js_1.meshExpression)(expression, internal);
173
+ }
118
174
  }
119
- const result = call ?? expression;
120
- result.loc = loc;
121
- return result;
175
+ expression.node.loc = loc;
176
+ return expression.node;
122
177
  }
123
178
  function idToProp(id, value, from) {
124
179
  let str = t.isIdentifier(id) || t.isJSXIdentifier(id) ? id.name : id.value;
@@ -135,7 +190,23 @@ function idToProp(id, value, from) {
135
190
  expr.loc = id.loc;
136
191
  return t.objectProperty(expr, value);
137
192
  }
138
- function transformJsxElement(path, internal) {
193
+ function processConditions(conditions, internal, _default) {
194
+ if (!conditions.cases) {
195
+ return [];
196
+ }
197
+ const ret = [
198
+ t.expressionStatement(internal.Switch(t.objectExpression([
199
+ t.objectProperty(t.identifier("cases"), t.arrayExpression(conditions.cases.map(item => t.objectExpression([
200
+ t.objectProperty(t.identifier("$case"), item.condition),
201
+ t.objectProperty(t.identifier("slot"), item.slot),
202
+ ])))),
203
+ ...(_default ? [t.objectProperty(t.identifier("default"), _default)] : []),
204
+ ]))),
205
+ ];
206
+ conditions.cases = null;
207
+ return ret;
208
+ }
209
+ function transformJsxElement(path, conditions, internal) {
139
210
  const name = path.node.openingElement.name;
140
211
  if (t.isJSXIdentifier(name) && name.name[0].toLowerCase() === name.name[0]) {
141
212
  const opening = path.get("openingElement");
@@ -151,64 +222,70 @@ function transformJsxElement(path, internal) {
151
222
  const attr = attrPath.node;
152
223
  if (t.isJSXAttribute(attr)) {
153
224
  const name = attr.name;
225
+ const valuePath = attrPath.get("value");
226
+ const expressionPath = valuePath.isJSXExpressionContainer() && valuePath.get("expression");
227
+ /* istanbul ignore else */
154
228
  if (t.isJSXIdentifier(name)) {
155
229
  if (name.name.startsWith("on")) {
156
- if (t.isJSXExpressionContainer(attr.value) && t.isExpression(attr.value.expression)) {
157
- const path = attrPath.get("value");
158
- if (t.isExpression(path.node.expression)) {
159
- (0, mesh_js_1.meshExpression)(path.get("expression"), internal);
230
+ if (expressionPath) {
231
+ /* istanbul ignore else */
232
+ if (expressionPath.isExpression()) {
233
+ (0, mesh_js_1.meshExpression)(expressionPath, internal);
234
+ events.push(idToProp(name, expressionPath.node, 2));
160
235
  }
161
- events.push(idToProp(name, path.node.expression, 2));
162
236
  }
163
237
  else {
164
- throw attrPath
165
- .get("value")
166
- .buildCodeFrameError("Vasille: Expected event handler.");
238
+ (0, lib_js_1.err)(lib_js_1.Errors.TokenNotSupported, valuePath, "Expected event handler", internal);
167
239
  }
168
240
  }
169
241
  else if (name.name === "class") {
170
242
  // class={[..]}
171
- if (t.isJSXExpressionContainer(attr.value) && t.isArrayExpression(attr.value.expression)) {
172
- const valuePath = attrPath.get("value");
243
+ /* istanbul ignore else */
244
+ if (valuePath.isJSXExpressionContainer() && t.isArrayExpression(valuePath.node.expression)) {
173
245
  const arrayExprPath = valuePath.get("expression");
174
246
  for (const elementPath of arrayExprPath.get("elements")) {
175
- const item = elementPath.node;
176
- if (t.isExpression(item)) {
247
+ if (elementPath.isExpression()) {
177
248
  // class={[cond && "string"]}
178
- if (t.isLogicalExpression(item) && item.operator === "&&" && t.isStringLiteral(item.right)) {
179
- const call = (0, lib_js_1.exprCall)(elementPath.get("left"), item.left, internal);
180
- classObject.push(idToProp(item.right, call ?? item.left));
249
+ if (elementPath.isLogicalExpression() &&
250
+ elementPath.node.operator === "&&" &&
251
+ t.isStringLiteral(elementPath.node.right)) {
252
+ (0, lib_js_1.exprCall)(elementPath.get("left"), elementPath.node.left, internal, {});
253
+ classObject.push(idToProp(elementPath.node.right, elementPath.node.left));
181
254
  }
182
255
  // class={[{..}]}
183
- else if (t.isObjectExpression(item)) {
256
+ else if (elementPath.isObjectExpression()) {
184
257
  for (const propPath of elementPath.get("properties")) {
185
258
  // class={[{a: b}]}
186
- if (t.isObjectProperty(propPath.node)) {
187
- const prop = propPath;
188
- const value = (0, lib_js_1.exprCall)(prop.get("value"), prop.node.value, internal) ?? prop.node.value;
189
- if (t.isExpression(prop.node.key) && !t.isIdentifier(prop.node.key)) {
190
- (0, mesh_js_1.meshExpression)(prop.get("key"), internal);
259
+ if (propPath.isObjectProperty()) {
260
+ const keyPath = propPath.get("key");
261
+ const valuePath = propPath.get("value");
262
+ /* istanbul ignore else */
263
+ if (valuePath.isExpression()) {
264
+ (0, lib_js_1.exprCall)(valuePath, valuePath.node, internal, {});
191
265
  }
192
- classObject.push(t.objectProperty(prop.node.key, value));
266
+ if (keyPath.isExpression() && !keyPath.isIdentifier()) {
267
+ (0, mesh_js_1.meshExpression)(keyPath, internal);
268
+ }
269
+ classObject.push(t.objectProperty(keyPath.node, valuePath.node));
193
270
  }
194
271
  // class={[{...a}]}
195
- else if (t.isSpreadElement(propPath.node)) {
272
+ else if (propPath.isSpreadElement()) {
196
273
  classObject.push(propPath.node);
197
274
  }
198
275
  // class={[{a(){}}]}
199
276
  else {
200
- throw propPath.buildCodeFrameError("Vasille: Methods are not allowed here");
277
+ (0, lib_js_1.err)(lib_js_1.Errors.TokenNotSupported, propPath, "Methods are not allowed here", internal);
201
278
  }
202
279
  }
203
280
  }
204
281
  // class={[".."]}
205
- else if (t.isStringLiteral(elementPath.node)) {
282
+ else if (elementPath.isStringLiteral()) {
206
283
  classStatic.push(elementPath.node);
207
284
  }
208
285
  // class={[..]}
209
286
  else {
210
- const call = (0, lib_js_1.exprCall)(elementPath, item, internal);
211
- classElements.push(call ?? item);
287
+ (0, lib_js_1.exprCall)(elementPath, elementPath.node, internal, { strong: true });
288
+ classElements.push(elementPath.node);
212
289
  }
213
290
  }
214
291
  // class={[...array]}
@@ -218,56 +295,59 @@ function transformJsxElement(path, internal) {
218
295
  }
219
296
  }
220
297
  // class={"a b"}
221
- else if (t.isJSXExpressionContainer(attr.value) && t.isStringLiteral(attr.value.expression)) {
222
- attrs.push(t.objectProperty(t.identifier("class"), attr.value.expression));
298
+ else if (expressionPath && expressionPath.isStringLiteral()) {
299
+ attrs.push(t.objectProperty(t.identifier("class"), expressionPath.node));
223
300
  }
224
301
  // class={`a ${b}`}
225
- else if (t.isJSXExpressionContainer(attr.value) && t.isTemplateLiteral(attr.value.expression)) {
226
- const jsxAttrPath = attrPath;
227
- const jsxContainerPath = jsxAttrPath.get("value");
228
- const value = (0, lib_js_1.exprCall)(jsxContainerPath.get("expression"), attr.value.expression, internal);
229
- attrs.push(t.objectProperty(t.identifier("class"), value ?? attr.value.expression));
230
- if (value) {
302
+ else if (expressionPath && expressionPath.isExpression()) {
303
+ if ((0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, { strong: true })) {
231
304
  console.warn(attrPath.buildCodeFrameError("Vasille: This will slow down your application"));
232
305
  }
306
+ attrs.push(t.objectProperty(t.identifier("class"), expressionPath.node));
233
307
  }
234
308
  // class={name}
235
- else if (t.isJSXExpressionContainer(attr.value) && t.isIdentifier(attr.value.expression)) {
236
- attrs.push(t.objectProperty(t.identifier("class"), attr.value.expression));
309
+ else if (expressionPath && expressionPath.isExpression()) {
310
+ (0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, {});
311
+ attrs.push(t.objectProperty(t.identifier("class"), expressionPath.node));
237
312
  }
238
313
  // class="a b"
239
- else if (t.isStringLiteral(attr.value)) {
240
- classStatic.push(attr.value);
314
+ else if (valuePath.isStringLiteral()) {
315
+ classStatic.push(valuePath.node);
241
316
  }
242
317
  }
243
318
  else if (name.name === "style") {
244
319
  // style={{..}}
245
- if (t.isJSXExpressionContainer(attr.value) && t.isObjectExpression(attr.value.expression)) {
246
- const valuePath = attrPath.get("value");
247
- const objectPath = valuePath.get("expression");
248
- for (const propPath of objectPath.get("properties")) {
320
+ /* istanbul ignore else */
321
+ if (expressionPath && expressionPath.isObjectExpression()) {
322
+ for (const propPath of expressionPath.get("properties")) {
249
323
  // style={{a: b}}
250
- if (t.isObjectProperty(propPath.node)) {
324
+ if (propPath.isObjectProperty()) {
251
325
  const prop = propPath;
252
- const value = (0, lib_js_1.exprCall)(prop.get("value"), prop.node.value, internal) ?? prop.node.value;
253
- if (t.isExpression(prop.node.key) && !t.isIdentifier(prop.node.key)) {
254
- (0, mesh_js_1.meshExpression)(prop.get("key"), internal);
326
+ const valuePath = prop.get("value");
327
+ /* istanbul ignore else */
328
+ if (valuePath.isExpression()) {
329
+ (0, lib_js_1.exprCall)(valuePath, valuePath.node, internal, { strong: true });
330
+ }
331
+ const value = valuePath.node;
332
+ const keyPath = propPath.get("key");
333
+ if (keyPath.isExpression() && !keyPath.isIdentifier()) {
334
+ (0, mesh_js_1.meshExpression)(keyPath, internal);
255
335
  }
256
336
  // style={{a: "b"}} -> static in compile time
257
- if (t.isIdentifier(prop.node.key) && t.isStringLiteral(prop.node.value)) {
258
- styleStatic.push([prop.node.key, prop.node.value]);
337
+ if (keyPath.isIdentifier() && valuePath.isStringLiteral()) {
338
+ styleStatic.push([keyPath.node, valuePath.node]);
259
339
  }
260
340
  // style={{a: 23}} -> static in compile time
261
- else if (t.isIdentifier(prop.node.key) && t.isNumericLiteral(prop.node.value)) {
262
- styleStatic.push([prop.node.key, t.stringLiteral(`${prop.node.value.value}px`)]);
341
+ else if (keyPath.isIdentifier() && valuePath.isNumericLiteral()) {
342
+ styleStatic.push([keyPath.node, t.stringLiteral(`${valuePath.node.value}px`)]);
263
343
  }
264
344
  // style={{a: [1, 2, 3]}} -> static in compile time
265
- else if (t.isIdentifier(prop.node.key) &&
266
- t.isArrayExpression(prop.node.value) &&
267
- prop.node.value.elements.every(item => t.isNumericLiteral(item))) {
345
+ else if (keyPath.isIdentifier() &&
346
+ valuePath.isArrayExpression() &&
347
+ valuePath.node.elements.every(item => t.isNumericLiteral(item))) {
268
348
  styleStatic.push([
269
- prop.node.key,
270
- t.stringLiteral(prop.node.value.elements
349
+ keyPath.node,
350
+ t.stringLiteral(valuePath.node.elements
271
351
  .map(item => {
272
352
  return `${item.value}px`;
273
353
  })
@@ -285,58 +365,66 @@ function transformJsxElement(path, internal) {
285
365
  }
286
366
  // style={{a(){}}}
287
367
  else {
288
- throw propPath.buildCodeFrameError("Vasille: Methods are not allowed here");
368
+ (0, lib_js_1.err)(lib_js_1.Errors.TokenNotSupported, propPath, "Methods are not allowed here", internal);
289
369
  }
290
370
  }
291
371
  }
292
372
  // style=".."
293
- else if (t.isStringLiteral(attr.value)) {
294
- attrs.push(t.objectProperty(t.identifier("style"), attr.value));
373
+ else if (valuePath.isStringLiteral()) {
374
+ attrs.push(t.objectProperty(t.identifier("style"), valuePath.node));
295
375
  }
296
376
  // style={".."}
297
- else if (t.isJSXExpressionContainer(attr.value) && t.isStringLiteral(attr.value.expression)) {
298
- attrs.push(t.objectProperty(t.identifier("style"), attr.value.expression));
377
+ else if (expressionPath && expressionPath.isStringLiteral()) {
378
+ attrs.push(t.objectProperty(t.identifier("style"), expressionPath.node));
299
379
  }
300
380
  // style={`a: ${b}px`}
301
- else if (t.isJSXExpressionContainer(attr.value) && t.isTemplateLiteral(attr.value.expression)) {
302
- const jsxAttrPath = attrPath;
303
- const jsxContainerPath = jsxAttrPath.get("value");
304
- const literalPath = jsxContainerPath.get("expression");
305
- const value = (0, lib_js_1.exprCall)(literalPath, attr.value.expression, internal);
306
- attrs.push(t.objectProperty(t.identifier("style"), value ?? attr.value.expression));
307
- if (value) {
381
+ else if (expressionPath && expressionPath.isExpression()) {
382
+ if ((0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, { strong: true })) {
308
383
  console.warn(attrPath.buildCodeFrameError("Vasille: This will slow down your application"));
309
384
  }
385
+ attrs.push(t.objectProperty(t.identifier("style"), expressionPath.node));
310
386
  }
311
387
  }
312
388
  else {
313
- if (!attr.value || t.isJSXExpressionContainer(attr.value)) {
314
- attrs.push(idToProp(name, t.isExpression(attr.value?.expression) ? attr.value.expression : t.booleanLiteral(true)));
389
+ /* istanbul ignore else */
390
+ if (expressionPath && expressionPath.isExpression()) {
391
+ attrs.push(idToProp(name, expressionPath.node));
315
392
  }
316
393
  else if (t.isStringLiteral(attr.value)) {
317
394
  attrs.push(idToProp(name, attr.value));
318
395
  }
396
+ else {
397
+ attrs.push(idToProp(name, t.booleanLiteral(true)));
398
+ }
319
399
  }
320
400
  }
321
401
  if (t.isJSXNamespacedName(name)) {
322
402
  if (name.namespace.name === "bind") {
323
- if (t.isJSXExpressionContainer(attr.value) || !attr.value) {
324
- const value = t.isExpression(attr.value?.expression)
325
- ? (0, lib_js_1.exprCall)(attrPath.get("value").get("expression"), attr.value.expression, internal)
326
- : undefined;
327
- bind.push(idToProp(name.name, value ?? (t.isExpression(attr.value?.expression) ? attr.value.expression : t.booleanLiteral(true))));
403
+ let pushed = false;
404
+ /* istanbul ignore else */
405
+ if (expressionPath) {
406
+ /* istanbul ignore else */
407
+ if (expressionPath.isExpression()) {
408
+ (0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, { strong: true });
409
+ bind.push(idToProp(name.name, expressionPath.node));
410
+ pushed = true;
411
+ }
328
412
  }
329
413
  else if (t.isStringLiteral(attr.value)) {
330
414
  bind.push(idToProp(name.name, attr.value));
415
+ pushed = true;
416
+ }
417
+ if (!pushed) {
418
+ bind.push(idToProp(name.name, t.booleanLiteral(true)));
331
419
  }
332
420
  }
333
421
  else {
334
- throw attrPath.buildCodeFrameError("Vasille: only bind namespace is supported");
422
+ (0, lib_js_1.err)(lib_js_1.Errors.ParserError, attrPath, "Only bind namespace is supported", internal);
335
423
  }
336
424
  }
337
425
  }
338
426
  else {
339
- throw attrPath.buildCodeFrameError("Vasille: Spread attribute is not allowed on HTML tags.");
427
+ (0, lib_js_1.err)(lib_js_1.Errors.ParserError, attrPath, "Spread attribute is not allowed on HTML tags", internal);
340
428
  }
341
429
  }
342
430
  if (classStatic.length > 0) {
@@ -368,7 +456,7 @@ function transformJsxElement(path, internal) {
368
456
  ...(statements.length > 0 ? [t.arrowFunctionExpression([internal_js_1.ctx], t.blockStatement(statements))] : []),
369
457
  ]);
370
458
  call.loc = path.node.loc;
371
- return t.expressionStatement(call);
459
+ return [...processConditions(conditions, internal), t.expressionStatement(call)];
372
460
  }
373
461
  if (t.isJSXIdentifier(name)) {
374
462
  const element = path.node;
@@ -377,33 +465,41 @@ function transformJsxElement(path, internal) {
377
465
  let run;
378
466
  const mapped = internal.mapping.get(name.name);
379
467
  if (mapped === "Debug" && internal.stack.get(name.name) === undefined && !internal.devMode) {
380
- return t.emptyStatement();
468
+ return processConditions(conditions, internal);
381
469
  }
382
470
  for (const attrPath of opening.get("attributes")) {
383
471
  const attr = attrPath.node;
384
472
  // <A prop=../>
385
473
  if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
474
+ const valuePath = attrPath.isJSXAttribute() && attrPath.get("value");
475
+ const needReactive = attr.name.name.startsWith("$");
386
476
  // <A prop=".."/>
477
+ /* istanbul ignore else */
387
478
  if (t.isStringLiteral(attr.value)) {
388
- props.push(idToProp(attr.name, attr.value));
479
+ props.push(idToProp(attr.name, needReactive ? internal.ref(attr.value) : attr.value));
389
480
  }
390
481
  // <A prop={..}/>
391
- else if (t.isJSXExpressionContainer(attr.value)) {
482
+ else if (valuePath && valuePath.isJSXExpressionContainer()) {
392
483
  const isSystem = internal.mapping.has(name.name);
393
- const value = transformJsxExpressionContainer(attrPath.get("value"), internal, !isSystem || attr.name.name === "slot", isSystem && attr.name.name === "slot");
484
+ const requiresReactive = attr.name.name.startsWith("$");
485
+ const value = transformJsxExpressionContainer(valuePath, internal, !isSystem || attr.name.name === "slot", isSystem && attr.name.name === "slot", requiresReactive, !requiresReactive);
394
486
  props.push(idToProp(attr.name, value));
395
487
  }
396
488
  else if (!attr.value) {
397
- props.push(idToProp(attr.name, t.booleanLiteral(true)));
489
+ props.push(idToProp(attr.name, needReactive ? internal.ref(t.booleanLiteral(true)) : t.booleanLiteral(true)));
398
490
  }
399
491
  }
400
492
  // <A {...arg}/>
401
- else if (t.isJSXSpreadAttribute(attr)) {
402
- props.push(t.spreadElement(attr.argument));
493
+ else if (attrPath.isJSXSpreadAttribute()) {
494
+ (0, mesh_js_1.meshExpression)(attrPath.get("argument"), internal);
495
+ props.push(t.spreadElement(attrPath.node.argument));
496
+ if (mapped === "If" || mapped === "ElseIf" || mapped === "Else") {
497
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, attrPath, "If, Else and ElseIf are syntax sugar, use Switch if you need more runtime elasticity", internal);
498
+ }
403
499
  }
404
500
  // <A space:name=../>
405
501
  else {
406
- throw attrPath.buildCodeFrameError("Vasille: Namespaced attributes names are not supported");
502
+ (0, lib_js_1.err)(lib_js_1.Errors.ParserError, attrPath, "Namespaced attributes names are not supported", internal);
407
503
  }
408
504
  }
409
505
  const filteredChildren = element.children.filter(item => {
@@ -413,11 +509,12 @@ function transformJsxElement(path, internal) {
413
509
  return !!item.value.trim();
414
510
  });
415
511
  const isInternal = internal.mapping.has(name.name);
512
+ // The child is a slot value
416
513
  if (filteredChildren.length === 1 &&
417
514
  t.isJSXExpressionContainer(filteredChildren[0]) &&
418
515
  (t.isFunctionExpression(filteredChildren[0].expression) ||
419
516
  t.isArrowFunctionExpression(filteredChildren[0].expression))) {
420
- transformJsxExpressionContainer(path.get("children")[element.children.indexOf(filteredChildren[0])], internal, true, isInternal);
517
+ transformJsxExpressionContainer(path.get("children")[element.children.indexOf(filteredChildren[0])], internal, true, isInternal, false, true);
421
518
  run = filteredChildren[0].expression;
422
519
  }
423
520
  else {
@@ -430,9 +527,42 @@ function transformJsxElement(path, internal) {
430
527
  run = t.arrowFunctionExpression(params, t.blockStatement(statements));
431
528
  }
432
529
  }
433
- const call = t.callExpression(t.identifier(name.name), [internal_js_1.ctx, t.objectExpression(props), ...(run ? [run] : [])]);
530
+ const ret = [];
531
+ const filter = (v) => {
532
+ return t.isObjectProperty(v);
533
+ };
534
+ if (mapped === "If" || mapped === "ElseIf" || mapped === "Else") {
535
+ const condition = props.filter(filter).find(prop => {
536
+ return t.isStringLiteral(prop.key) && prop.key.value === "$condition";
537
+ })?.value;
538
+ const slot = run ??
539
+ props.filter(filter).find(prop => {
540
+ return t.isIdentifier(prop.key) && prop.key.name === "slot";
541
+ })?.value;
542
+ if (mapped === "If") {
543
+ ret.push(...processConditions(conditions, internal));
544
+ }
545
+ if ((mapped === "ElseIf" || mapped === "Else") && !conditions.cases) {
546
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, path, "Malformed JSX If tag is missing", internal);
547
+ }
548
+ if (mapped === "If" || mapped === "ElseIf") {
549
+ if (t.isExpression(condition) && (t.isFunctionExpression(slot) || t.isArrowFunctionExpression(slot))) {
550
+ if (!conditions.cases) {
551
+ conditions.cases = [{ condition, slot }];
552
+ }
553
+ else {
554
+ conditions.cases.push({ condition, slot });
555
+ }
556
+ }
557
+ }
558
+ if (mapped === "Else") {
559
+ ret.push(...processConditions(conditions, internal, t.isFunctionExpression(slot) || t.isArrowFunctionExpression(slot) ? slot : undefined));
560
+ }
561
+ return ret;
562
+ }
563
+ const call = t.callExpression(t.identifier(name.name), [t.objectExpression(props), internal_js_1.ctx, ...(run ? [run] : [])]);
434
564
  call.loc = path.node.loc;
435
- return t.expressionStatement(call);
565
+ return [...ret, t.expressionStatement(call)];
436
566
  }
437
- throw path.buildCodeFrameError("Vasille: Unsupported tag detected, html lowercase tag names and components are accepted");
567
+ return (0, lib_js_1.err)(lib_js_1.Errors.ParserError, path, "Unsupported tag detected, html lowercase tag names and components are accepted", internal, []);
438
568
  }