babel-plugin-vasille 3.2.1 → 4.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/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, "")
@@ -79,48 +85,95 @@ function transformJsxArray(paths, internal) {
79
85
  result.push(t.expressionStatement(call));
80
86
  }
81
87
  }
82
- else if (t.isJSXExpressionContainer(path.node)) {
83
- const value = transformJsxExpressionContainer(path, internal, false, false);
88
+ else if (path.isJSXExpressionContainer()) {
89
+ const value = transformJsxExpressionContainer(path, internal, false, false, true, true);
84
90
  const call = t.callExpression(t.memberExpression(internal_js_1.ctx, t.identifier("text")), [value]);
85
91
  call.loc = value.loc;
86
92
  result.push(t.expressionStatement(call));
87
93
  }
88
94
  else {
89
- 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);
90
96
  }
91
- }
97
+ });
98
+ result.push(...processConditions(conditions, internal));
92
99
  return result;
93
100
  }
94
- function transformJsxExpressionContainer(path, internal, acceptSlots, isInternalSlot) {
95
- const expression = path.node.expression;
96
- 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;
97
104
  if (acceptSlots &&
98
- (t.isFunctionExpression(expression) || t.isArrowFunctionExpression(expression)) &&
99
- (0, jsx_detect_js_1.bodyHasJsx)(expression.body)) {
100
- (0, mesh_js_1.compose)(path.get("expression"), internal, isInternalSlot, "slot");
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);
101
108
  if (!isInternalSlot) {
102
- if (expression.params.length < 1) {
103
- expression.params.push(t.identifier(`_${internal.prefix}`));
109
+ if (expression.node.params.length < 1) {
110
+ expression.node.params.push(t.identifier(`_${internal.prefix}`));
104
111
  }
105
- expression.params.push(internal_js_1.ctx);
112
+ expression.node.params.push(internal_js_1.ctx);
106
113
  }
107
114
  else {
108
- expression.params.unshift(internal_js_1.ctx);
115
+ expression.node.params.unshift(internal_js_1.ctx);
109
116
  }
110
- expression.loc = loc;
111
- return expression;
117
+ expression.node.loc = loc;
118
+ return expression.node;
112
119
  }
113
- else if (isInternalSlot && (t.isFunctionExpression(expression) || t.isArrowFunctionExpression(expression))) {
114
- expression.params.unshift(internal_js_1.ctx);
120
+ else if (isInternalSlot && (expression.isFunctionExpression() || expression.isArrowFunctionExpression())) {
121
+ expression.node.params.unshift(internal_js_1.ctx);
115
122
  }
116
- const exprPath = path.get("expression");
117
- let call = (0, lib_js_1.exprCall)(exprPath, expression, internal);
118
- if (!call && t.isIdentifier(expression) && internal.stack.get(expression.name) === 3 /* VariableState.ReactiveObject */) {
119
- 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
+ }
120
174
  }
121
- const result = call ?? exprPath.node;
122
- result.loc = loc;
123
- return result;
175
+ expression.node.loc = loc;
176
+ return expression.node;
124
177
  }
125
178
  function idToProp(id, value, from) {
126
179
  let str = t.isIdentifier(id) || t.isJSXIdentifier(id) ? id.name : id.value;
@@ -137,9 +190,28 @@ function idToProp(id, value, from) {
137
190
  expr.loc = id.loc;
138
191
  return t.objectProperty(expr, value);
139
192
  }
140
- 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) {
141
210
  const name = path.node.openingElement.name;
142
211
  if (t.isJSXIdentifier(name) && name.name[0].toLowerCase() === name.name[0]) {
212
+ if ((name.name === "head" && !internal.headTag) || (name.name === "body" && !internal.bodyTag)) {
213
+ return [];
214
+ }
143
215
  const opening = path.get("openingElement");
144
216
  const attrs = [];
145
217
  const events = [];
@@ -153,67 +225,70 @@ function transformJsxElement(path, internal) {
153
225
  const attr = attrPath.node;
154
226
  if (t.isJSXAttribute(attr)) {
155
227
  const name = attr.name;
228
+ const valuePath = attrPath.get("value");
229
+ const expressionPath = valuePath.isJSXExpressionContainer() && valuePath.get("expression");
156
230
  /* istanbul ignore else */
157
231
  if (t.isJSXIdentifier(name)) {
158
232
  if (name.name.startsWith("on")) {
159
- if (t.isJSXExpressionContainer(attr.value) && t.isExpression(attr.value.expression)) {
160
- const path = attrPath.get("value");
233
+ if (expressionPath) {
161
234
  /* istanbul ignore else */
162
- if (t.isExpression(path.node.expression)) {
163
- (0, mesh_js_1.meshExpression)(path.get("expression"), internal);
235
+ if (expressionPath.isExpression()) {
236
+ (0, mesh_js_1.meshExpression)(expressionPath, internal);
237
+ events.push(idToProp(name, expressionPath.node, 2));
164
238
  }
165
- events.push(idToProp(name, path.node.expression, 2));
166
239
  }
167
240
  else {
168
- throw attrPath
169
- .get("value")
170
- .buildCodeFrameError("Vasille: Expected event handler.");
241
+ (0, lib_js_1.err)(lib_js_1.Errors.TokenNotSupported, valuePath, "Expected event handler", internal);
171
242
  }
172
243
  }
173
244
  else if (name.name === "class") {
174
245
  // class={[..]}
175
246
  /* istanbul ignore else */
176
- if (t.isJSXExpressionContainer(attr.value) && t.isArrayExpression(attr.value.expression)) {
177
- const valuePath = attrPath.get("value");
247
+ if (valuePath.isJSXExpressionContainer() && t.isArrayExpression(valuePath.node.expression)) {
178
248
  const arrayExprPath = valuePath.get("expression");
179
249
  for (const elementPath of arrayExprPath.get("elements")) {
180
- const item = elementPath.node;
181
- if (t.isExpression(item)) {
250
+ if (elementPath.isExpression()) {
182
251
  // class={[cond && "string"]}
183
- if (t.isLogicalExpression(item) && item.operator === "&&" && t.isStringLiteral(item.right)) {
184
- const call = (0, lib_js_1.exprCall)(elementPath.get("left"), item.left, internal);
185
- classObject.push(idToProp(item.right, call ?? item.left));
252
+ if (elementPath.isLogicalExpression() &&
253
+ elementPath.node.operator === "&&" &&
254
+ t.isStringLiteral(elementPath.node.right)) {
255
+ (0, lib_js_1.exprCall)(elementPath.get("left"), elementPath.node.left, internal, {});
256
+ classObject.push(idToProp(elementPath.node.right, elementPath.node.left));
186
257
  }
187
258
  // class={[{..}]}
188
- else if (t.isObjectExpression(item)) {
259
+ else if (elementPath.isObjectExpression()) {
189
260
  for (const propPath of elementPath.get("properties")) {
190
261
  // class={[{a: b}]}
191
- if (t.isObjectProperty(propPath.node)) {
192
- const prop = propPath;
193
- const value = (0, lib_js_1.exprCall)(prop.get("value"), prop.node.value, internal) ?? prop.node.value;
194
- if (t.isExpression(prop.node.key) && !t.isIdentifier(prop.node.key)) {
195
- (0, mesh_js_1.meshExpression)(prop.get("key"), internal);
262
+ if (propPath.isObjectProperty()) {
263
+ const keyPath = propPath.get("key");
264
+ const valuePath = propPath.get("value");
265
+ /* istanbul ignore else */
266
+ if (valuePath.isExpression()) {
267
+ (0, lib_js_1.exprCall)(valuePath, valuePath.node, internal, {});
196
268
  }
197
- classObject.push(t.objectProperty(prop.node.key, value));
269
+ if (keyPath.isExpression() && !keyPath.isIdentifier()) {
270
+ (0, mesh_js_1.meshExpression)(keyPath, internal);
271
+ }
272
+ classObject.push(t.objectProperty(keyPath.node, valuePath.node));
198
273
  }
199
274
  // class={[{...a}]}
200
- else if (t.isSpreadElement(propPath.node)) {
275
+ else if (propPath.isSpreadElement()) {
201
276
  classObject.push(propPath.node);
202
277
  }
203
278
  // class={[{a(){}}]}
204
279
  else {
205
- throw propPath.buildCodeFrameError("Vasille: Methods are not allowed here");
280
+ (0, lib_js_1.err)(lib_js_1.Errors.TokenNotSupported, propPath, "Methods are not allowed here", internal);
206
281
  }
207
282
  }
208
283
  }
209
284
  // class={[".."]}
210
- else if (t.isStringLiteral(elementPath.node)) {
285
+ else if (elementPath.isStringLiteral()) {
211
286
  classStatic.push(elementPath.node);
212
287
  }
213
288
  // class={[..]}
214
289
  else {
215
- const call = (0, lib_js_1.exprCall)(elementPath, item, internal);
216
- classElements.push(call ?? item);
290
+ (0, lib_js_1.exprCall)(elementPath, elementPath.node, internal, { strong: true });
291
+ classElements.push(elementPath.node);
217
292
  }
218
293
  }
219
294
  // class={[...array]}
@@ -223,58 +298,59 @@ function transformJsxElement(path, internal) {
223
298
  }
224
299
  }
225
300
  // class={"a b"}
226
- else if (t.isJSXExpressionContainer(attr.value) && t.isStringLiteral(attr.value.expression)) {
227
- attrs.push(t.objectProperty(t.identifier("class"), attr.value.expression));
301
+ else if (expressionPath && expressionPath.isStringLiteral()) {
302
+ attrs.push(t.objectProperty(t.identifier("class"), expressionPath.node));
228
303
  }
229
304
  // class={`a ${b}`}
230
- else if (t.isJSXExpressionContainer(attr.value) && t.isTemplateLiteral(attr.value.expression)) {
231
- const jsxAttrPath = attrPath;
232
- const jsxContainerPath = jsxAttrPath.get("value");
233
- const value = (0, lib_js_1.exprCall)(jsxContainerPath.get("expression"), attr.value.expression, internal);
234
- attrs.push(t.objectProperty(t.identifier("class"), value ?? attr.value.expression));
235
- if (value) {
305
+ else if (expressionPath && expressionPath.isExpression()) {
306
+ if ((0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, { strong: true })) {
236
307
  console.warn(attrPath.buildCodeFrameError("Vasille: This will slow down your application"));
237
308
  }
309
+ attrs.push(t.objectProperty(t.identifier("class"), expressionPath.node));
238
310
  }
239
311
  // class={name}
240
- else if (t.isJSXExpressionContainer(attr.value) && t.isExpression(attr.value.expression)) {
241
- const expr = (0, lib_js_1.exprCall)(attrPath.get("value"), attr.value.expression, internal) ?? attr.value.expression;
242
- attrs.push(t.objectProperty(t.identifier("class"), expr));
312
+ else if (expressionPath && expressionPath.isExpression()) {
313
+ (0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, {});
314
+ attrs.push(t.objectProperty(t.identifier("class"), expressionPath.node));
243
315
  }
244
316
  // class="a b"
245
- else if (t.isStringLiteral(attr.value)) {
246
- classStatic.push(attr.value);
317
+ else if (valuePath.isStringLiteral()) {
318
+ classStatic.push(valuePath.node);
247
319
  }
248
320
  }
249
321
  else if (name.name === "style") {
250
322
  // style={{..}}
251
323
  /* istanbul ignore else */
252
- if (t.isJSXExpressionContainer(attr.value) && t.isObjectExpression(attr.value.expression)) {
253
- const valuePath = attrPath.get("value");
254
- const objectPath = valuePath.get("expression");
255
- for (const propPath of objectPath.get("properties")) {
324
+ if (expressionPath && expressionPath.isObjectExpression()) {
325
+ for (const propPath of expressionPath.get("properties")) {
256
326
  // style={{a: b}}
257
- if (t.isObjectProperty(propPath.node)) {
327
+ if (propPath.isObjectProperty()) {
258
328
  const prop = propPath;
259
- const value = (0, lib_js_1.exprCall)(prop.get("value"), prop.node.value, internal) ?? prop.node.value;
260
- if (t.isExpression(prop.node.key) && !t.isIdentifier(prop.node.key)) {
261
- (0, mesh_js_1.meshExpression)(prop.get("key"), internal);
329
+ const valuePath = prop.get("value");
330
+ /* istanbul ignore else */
331
+ if (valuePath.isExpression()) {
332
+ (0, lib_js_1.exprCall)(valuePath, valuePath.node, internal, { strong: true });
333
+ }
334
+ const value = valuePath.node;
335
+ const keyPath = propPath.get("key");
336
+ if (keyPath.isExpression() && !keyPath.isIdentifier()) {
337
+ (0, mesh_js_1.meshExpression)(keyPath, internal);
262
338
  }
263
339
  // style={{a: "b"}} -> static in compile time
264
- if (t.isIdentifier(prop.node.key) && t.isStringLiteral(prop.node.value)) {
265
- styleStatic.push([prop.node.key, prop.node.value]);
340
+ if (keyPath.isIdentifier() && valuePath.isStringLiteral()) {
341
+ styleStatic.push([keyPath.node, valuePath.node]);
266
342
  }
267
343
  // style={{a: 23}} -> static in compile time
268
- else if (t.isIdentifier(prop.node.key) && t.isNumericLiteral(prop.node.value)) {
269
- styleStatic.push([prop.node.key, t.stringLiteral(`${prop.node.value.value}px`)]);
344
+ else if (keyPath.isIdentifier() && valuePath.isNumericLiteral()) {
345
+ styleStatic.push([keyPath.node, t.stringLiteral(`${valuePath.node.value}px`)]);
270
346
  }
271
347
  // style={{a: [1, 2, 3]}} -> static in compile time
272
- else if (t.isIdentifier(prop.node.key) &&
273
- t.isArrayExpression(prop.node.value) &&
274
- prop.node.value.elements.every(item => t.isNumericLiteral(item))) {
348
+ else if (keyPath.isIdentifier() &&
349
+ valuePath.isArrayExpression() &&
350
+ valuePath.node.elements.every(item => t.isNumericLiteral(item))) {
275
351
  styleStatic.push([
276
- prop.node.key,
277
- t.stringLiteral(prop.node.value.elements
352
+ keyPath.node,
353
+ t.stringLiteral(valuePath.node.elements
278
354
  .map(item => {
279
355
  return `${item.value}px`;
280
356
  })
@@ -292,64 +368,66 @@ function transformJsxElement(path, internal) {
292
368
  }
293
369
  // style={{a(){}}}
294
370
  else {
295
- throw propPath.buildCodeFrameError("Vasille: Methods are not allowed here");
371
+ (0, lib_js_1.err)(lib_js_1.Errors.TokenNotSupported, propPath, "Methods are not allowed here", internal);
296
372
  }
297
373
  }
298
374
  }
299
375
  // style=".."
300
- else if (t.isStringLiteral(attr.value)) {
301
- attrs.push(t.objectProperty(t.identifier("style"), attr.value));
376
+ else if (valuePath.isStringLiteral()) {
377
+ attrs.push(t.objectProperty(t.identifier("style"), valuePath.node));
302
378
  }
303
379
  // style={".."}
304
- else if (t.isJSXExpressionContainer(attr.value) && t.isStringLiteral(attr.value.expression)) {
305
- attrs.push(t.objectProperty(t.identifier("style"), attr.value.expression));
380
+ else if (expressionPath && expressionPath.isStringLiteral()) {
381
+ attrs.push(t.objectProperty(t.identifier("style"), expressionPath.node));
306
382
  }
307
383
  // style={`a: ${b}px`}
308
- else if (t.isJSXExpressionContainer(attr.value) && t.isTemplateLiteral(attr.value.expression)) {
309
- const jsxAttrPath = attrPath;
310
- const jsxContainerPath = jsxAttrPath.get("value");
311
- const literalPath = jsxContainerPath.get("expression");
312
- const value = (0, lib_js_1.exprCall)(literalPath, attr.value.expression, internal);
313
- attrs.push(t.objectProperty(t.identifier("style"), value ?? attr.value.expression));
314
- if (value) {
384
+ else if (expressionPath && expressionPath.isExpression()) {
385
+ if ((0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, { strong: true })) {
315
386
  console.warn(attrPath.buildCodeFrameError("Vasille: This will slow down your application"));
316
387
  }
317
- }
318
- else if (t.isJSXExpressionContainer(attr.value) && t.isExpression(attr.value.expression)) {
319
- const expr = (0, lib_js_1.exprCall)(attrPath.get("value"), attr.value.expression, internal) ?? attr.value.expression;
320
- attrs.push(t.objectProperty(t.identifier("style"), expr));
388
+ attrs.push(t.objectProperty(t.identifier("style"), expressionPath.node));
321
389
  }
322
390
  }
323
391
  else {
324
392
  /* istanbul ignore else */
325
- if (!attr.value || t.isJSXExpressionContainer(attr.value)) {
326
- attrs.push(idToProp(name, t.isExpression(attr.value?.expression) ? attr.value.expression : t.booleanLiteral(true)));
393
+ if (expressionPath && expressionPath.isExpression()) {
394
+ attrs.push(idToProp(name, expressionPath.node));
327
395
  }
328
396
  else if (t.isStringLiteral(attr.value)) {
329
397
  attrs.push(idToProp(name, attr.value));
330
398
  }
399
+ else {
400
+ attrs.push(idToProp(name, t.booleanLiteral(true)));
401
+ }
331
402
  }
332
403
  }
333
404
  if (t.isJSXNamespacedName(name)) {
334
405
  if (name.namespace.name === "bind") {
406
+ let pushed = false;
335
407
  /* istanbul ignore else */
336
- if (t.isJSXExpressionContainer(attr.value) || !attr.value) {
337
- const value = t.isExpression(attr.value?.expression)
338
- ? (0, lib_js_1.exprCall)(attrPath.get("value").get("expression"), attr.value.expression, internal)
339
- : undefined;
340
- bind.push(idToProp(name.name, value ?? (t.isExpression(attr.value?.expression) ? attr.value.expression : t.booleanLiteral(true))));
408
+ if (expressionPath) {
409
+ /* istanbul ignore else */
410
+ if (expressionPath.isExpression()) {
411
+ (0, lib_js_1.exprCall)(expressionPath, expressionPath.node, internal, { strong: true });
412
+ bind.push(idToProp(name.name, expressionPath.node));
413
+ pushed = true;
414
+ }
341
415
  }
342
416
  else if (t.isStringLiteral(attr.value)) {
343
417
  bind.push(idToProp(name.name, attr.value));
418
+ pushed = true;
419
+ }
420
+ if (!pushed) {
421
+ bind.push(idToProp(name.name, t.booleanLiteral(true)));
344
422
  }
345
423
  }
346
424
  else {
347
- throw attrPath.buildCodeFrameError("Vasille: only bind namespace is supported");
425
+ (0, lib_js_1.err)(lib_js_1.Errors.ParserError, attrPath, "Only bind namespace is supported", internal);
348
426
  }
349
427
  }
350
428
  }
351
429
  else {
352
- throw attrPath.buildCodeFrameError("Vasille: Spread attribute is not allowed on HTML tags.");
430
+ (0, lib_js_1.err)(lib_js_1.Errors.ParserError, attrPath, "Spread attribute is not allowed on HTML tags", internal);
353
431
  }
354
432
  }
355
433
  if (classStatic.length > 0) {
@@ -381,7 +459,7 @@ function transformJsxElement(path, internal) {
381
459
  ...(statements.length > 0 ? [t.arrowFunctionExpression([internal_js_1.ctx], t.blockStatement(statements))] : []),
382
460
  ]);
383
461
  call.loc = path.node.loc;
384
- return t.expressionStatement(call);
462
+ return [...processConditions(conditions, internal), t.expressionStatement(call)];
385
463
  }
386
464
  if (t.isJSXIdentifier(name)) {
387
465
  const element = path.node;
@@ -390,34 +468,41 @@ function transformJsxElement(path, internal) {
390
468
  let run;
391
469
  const mapped = internal.mapping.get(name.name);
392
470
  if (mapped === "Debug" && internal.stack.get(name.name) === undefined && !internal.devMode) {
393
- return t.emptyStatement();
471
+ return processConditions(conditions, internal);
394
472
  }
395
473
  for (const attrPath of opening.get("attributes")) {
396
474
  const attr = attrPath.node;
397
475
  // <A prop=../>
398
476
  if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
477
+ const valuePath = attrPath.isJSXAttribute() && attrPath.get("value");
478
+ const needReactive = attr.name.name.startsWith("$");
399
479
  // <A prop=".."/>
400
480
  /* istanbul ignore else */
401
481
  if (t.isStringLiteral(attr.value)) {
402
- props.push(idToProp(attr.name, attr.value));
482
+ props.push(idToProp(attr.name, needReactive ? internal.ref(attr.value) : attr.value));
403
483
  }
404
484
  // <A prop={..}/>
405
- else if (t.isJSXExpressionContainer(attr.value)) {
485
+ else if (valuePath && valuePath.isJSXExpressionContainer()) {
406
486
  const isSystem = internal.mapping.has(name.name);
407
- const value = transformJsxExpressionContainer(attrPath.get("value"), internal, !isSystem || attr.name.name === "slot", isSystem && attr.name.name === "slot");
487
+ const requiresReactive = attr.name.name.startsWith("$");
488
+ const value = transformJsxExpressionContainer(valuePath, internal, !isSystem || attr.name.name === "slot", isSystem && attr.name.name === "slot", requiresReactive, !requiresReactive);
408
489
  props.push(idToProp(attr.name, value));
409
490
  }
410
491
  else if (!attr.value) {
411
- props.push(idToProp(attr.name, t.booleanLiteral(true)));
492
+ props.push(idToProp(attr.name, needReactive ? internal.ref(t.booleanLiteral(true)) : t.booleanLiteral(true)));
412
493
  }
413
494
  }
414
495
  // <A {...arg}/>
415
- else if (t.isJSXSpreadAttribute(attr)) {
416
- props.push(t.spreadElement(attr.argument));
496
+ else if (attrPath.isJSXSpreadAttribute()) {
497
+ (0, mesh_js_1.meshExpression)(attrPath.get("argument"), internal);
498
+ props.push(t.spreadElement(attrPath.node.argument));
499
+ if (mapped === "If" || mapped === "ElseIf" || mapped === "Else") {
500
+ (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);
501
+ }
417
502
  }
418
503
  // <A space:name=../>
419
504
  else {
420
- throw attrPath.buildCodeFrameError("Vasille: Namespaced attributes names are not supported");
505
+ (0, lib_js_1.err)(lib_js_1.Errors.ParserError, attrPath, "Namespaced attributes names are not supported", internal);
421
506
  }
422
507
  }
423
508
  const filteredChildren = element.children.filter(item => {
@@ -427,11 +512,12 @@ function transformJsxElement(path, internal) {
427
512
  return !!item.value.trim();
428
513
  });
429
514
  const isInternal = internal.mapping.has(name.name);
515
+ // The child is a slot value
430
516
  if (filteredChildren.length === 1 &&
431
517
  t.isJSXExpressionContainer(filteredChildren[0]) &&
432
518
  (t.isFunctionExpression(filteredChildren[0].expression) ||
433
519
  t.isArrowFunctionExpression(filteredChildren[0].expression))) {
434
- transformJsxExpressionContainer(path.get("children")[element.children.indexOf(filteredChildren[0])], internal, true, isInternal);
520
+ transformJsxExpressionContainer(path.get("children")[element.children.indexOf(filteredChildren[0])], internal, true, isInternal, false, true);
435
521
  run = filteredChildren[0].expression;
436
522
  }
437
523
  else {
@@ -444,9 +530,42 @@ function transformJsxElement(path, internal) {
444
530
  run = t.arrowFunctionExpression(params, t.blockStatement(statements));
445
531
  }
446
532
  }
533
+ const ret = [];
534
+ const filter = (v) => {
535
+ return t.isObjectProperty(v);
536
+ };
537
+ if (mapped === "If" || mapped === "ElseIf" || mapped === "Else") {
538
+ const condition = props.filter(filter).find(prop => {
539
+ return t.isStringLiteral(prop.key) && prop.key.value === "$condition";
540
+ })?.value;
541
+ const slot = run ??
542
+ props.filter(filter).find(prop => {
543
+ return t.isIdentifier(prop.key) && prop.key.name === "slot";
544
+ })?.value;
545
+ if (mapped === "If") {
546
+ ret.push(...processConditions(conditions, internal));
547
+ }
548
+ if ((mapped === "ElseIf" || mapped === "Else") && !conditions.cases) {
549
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, path, "Malformed JSX If tag is missing", internal);
550
+ }
551
+ if (mapped === "If" || mapped === "ElseIf") {
552
+ if (t.isExpression(condition) && (t.isFunctionExpression(slot) || t.isArrowFunctionExpression(slot))) {
553
+ if (!conditions.cases) {
554
+ conditions.cases = [{ condition, slot }];
555
+ }
556
+ else {
557
+ conditions.cases.push({ condition, slot });
558
+ }
559
+ }
560
+ }
561
+ if (mapped === "Else") {
562
+ ret.push(...processConditions(conditions, internal, t.isFunctionExpression(slot) || t.isArrowFunctionExpression(slot) ? slot : undefined));
563
+ }
564
+ return ret;
565
+ }
447
566
  const call = t.callExpression(t.identifier(name.name), [t.objectExpression(props), internal_js_1.ctx, ...(run ? [run] : [])]);
448
567
  call.loc = path.node.loc;
449
- return t.expressionStatement(call);
568
+ return [...ret, t.expressionStatement(call)];
450
569
  }
451
- throw path.buildCodeFrameError("Vasille: Unsupported tag detected, html lowercase tag names and components are accepted");
570
+ return (0, lib_js_1.err)(lib_js_1.Errors.ParserError, path, "Unsupported tag detected, html lowercase tag names and components are accepted", internal, []);
452
571
  }