babel-plugin-vasille 0.99.1 → 0.99.3

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
@@ -47,7 +47,7 @@ $ npx degit vasille-js/example-javascript my-project
47
47
 
48
48
  ### Examples
49
49
  * [TypeScript Example](https://github.com/vasille-js/example-typescript)
50
- * [JavaScript Example](https://github.com/vas[README.md](..%2Ftest%2Fmy-app%2FREADME.md)ille-js/example-javascript)
50
+ * [JavaScript Example](https://github.com/vasille-js/example-javascript)
51
51
 
52
52
  <hr>
53
53
 
@@ -104,8 +104,8 @@ All of these are supported:
104
104
  * [x] `100%` Test Coverage for the JSX library.
105
105
  * [x] Develop the `Vasille Babel Plugin`.
106
106
  * [ ] `100%` Test Coverage fot babel plugin.
107
- * [ ] Add CSS support (define styles in components).
108
- * [ ] Add custom `<input/>` components with 2-way value binding.
107
+ * [x] Add CSS support (define styles in components).
108
+ * [ ] Add custom `input` components with 2-way value binding.
109
109
  * [ ] Add router.
110
110
  * [ ] Develop dev-tools extension for debugging.
111
111
  * [ ] Develop a lot of libraries for the framework.
package/lib/call.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as t from "@babel/types";
2
- import { ctx } from "./internal.js";
2
+ import { ctx } from "./internal";
3
3
  export const composeOnly = [
4
4
  "forward",
5
5
  "watch",
@@ -11,6 +11,16 @@ export const composeOnly = [
11
11
  "setModel",
12
12
  "reactiveObject",
13
13
  ];
14
+ export const styleOnly = [
15
+ "theme",
16
+ "dark",
17
+ "mobile",
18
+ "tablet",
19
+ "laptop",
20
+ "prefersDark",
21
+ "prefersLight",
22
+ "webStyleSheet",
23
+ ];
14
24
  export const requiresContext = ["awaited", "forward"];
15
25
  const requiresContextSet = new Set(requiresContext);
16
26
  export function calls(node, names, internal) {
@@ -27,9 +37,10 @@ export function calls(node, names, internal) {
27
37
  }
28
38
  return false;
29
39
  }
30
- // The global object is overrided
31
- if (internal.stack.get(internal.global) !== undefined) {
32
- return false;
40
+ const global = internal.stack.get(internal.global) === undefined;
41
+ const cssGlobal = internal.stack.get(internal.cssGlobal) === undefined;
42
+ if (!global && !cssGlobal) {
43
+ return;
33
44
  }
34
45
  const propName = t.isMemberExpression(callee)
35
46
  ? t.isIdentifier(callee.property)
@@ -39,12 +50,15 @@ export function calls(node, names, internal) {
39
50
  : null
40
51
  : null;
41
52
  if (t.isMemberExpression(callee) && t.isIdentifier(callee.object) && propName) {
42
- if (callee.object.name === internal.global && set.has(propName)) {
53
+ if (global && callee.object.name === internal.global && set.has(propName)) {
43
54
  if (requiresContextSet.has(callee.object.name) && t.isCallExpression(node)) {
44
55
  node.arguments.unshift(ctx);
45
56
  }
46
57
  return callee.object.name;
47
58
  }
59
+ if (cssGlobal && callee.object.name === internal.cssGlobal && set.has(propName)) {
60
+ return callee.object.name;
61
+ }
48
62
  }
49
63
  }
50
64
  return false;
@@ -0,0 +1,206 @@
1
+ import * as t from "@babel/types";
2
+ import { calls } from "./call";
3
+ function tryProcessProp(path, pseudo, media, internal) {
4
+ if (t.isObjectMethod(path.node)) {
5
+ throw path.buildCodeFrameError("Object methods not supported here");
6
+ }
7
+ if (t.isSpreadElement(path.node)) {
8
+ throw path.buildCodeFrameError("Spread element not suppored here");
9
+ }
10
+ return processProp(path, pseudo, media, internal);
11
+ }
12
+ const mediaDefaults = ["mobile", "tablet", "laptop", "prefersDark", "prefersLight"];
13
+ function processValue(name, path, pseudo, theme, media, mediaDefault, allowFallback, internal) {
14
+ if (calls(path.node, ["theme"], internal)) {
15
+ const call = path.node;
16
+ if (theme) {
17
+ throw path.buildCodeFrameError("Vasille: Theme seem the be defined twince");
18
+ }
19
+ if (t.isStringLiteral(call.arguments[0])) {
20
+ return processValue(name, path.get("arguments")[1], pseudo, `body.${call.arguments[0].value}`, media, mediaDefault, false, internal);
21
+ }
22
+ else {
23
+ throw path
24
+ .get("arguments")[0]
25
+ .buildCodeFrameError("Vasille: Expected string literal");
26
+ }
27
+ }
28
+ if (calls(path.node, ["dark"], internal)) {
29
+ if (theme) {
30
+ throw path.buildCodeFrameError("Vasille: Theme seem the be defined twince");
31
+ }
32
+ return processValue(name, path.get("arguments")[0], pseudo, `.dark`, media, mediaDefault, false, internal);
33
+ }
34
+ let callee;
35
+ if ((callee = calls(path.node, mediaDefaults, internal))) {
36
+ const index = mediaDefaults.indexOf(callee) + 1;
37
+ if (mediaDefault.includes(index)) {
38
+ return processValue(name, path.get("arguments")[0], pseudo, theme, media, mediaDefault, false, internal);
39
+ }
40
+ return processValue(name, path.get("arguments")[0], pseudo, theme, media, [...mediaDefault, index], false, internal);
41
+ }
42
+ function composeRules(value) {
43
+ return mediaDefault.length
44
+ ? mediaDefault.map(index => {
45
+ return {
46
+ defaultMediaRule: index,
47
+ mediaRule: media,
48
+ pseudo: pseudo,
49
+ theme: theme,
50
+ rule: `${name}:${value}`,
51
+ };
52
+ })
53
+ : [
54
+ {
55
+ defaultMediaRule: 0,
56
+ mediaRule: media,
57
+ pseudo: pseudo,
58
+ theme: theme,
59
+ rule: `${name}:${value}`,
60
+ },
61
+ ];
62
+ }
63
+ if (t.isStringLiteral(path.node)) {
64
+ return composeRules(path.node.value);
65
+ }
66
+ if (t.isNumericLiteral(path.node)) {
67
+ return composeRules(`${path.node.value}px`);
68
+ }
69
+ if (t.isArrayExpression(path.node)) {
70
+ if (path.node.elements.every(item => t.isNumericLiteral(item))) {
71
+ return composeRules(path.node.elements.map(item => `${item.value}px`).join(" "));
72
+ }
73
+ else if (allowFallback) {
74
+ return [
75
+ ...path.get("elements").map(path => {
76
+ if (t.isExpression(path.node)) {
77
+ return processValue(name, path, pseudo, theme, media, mediaDefault, false, internal);
78
+ }
79
+ else {
80
+ throw path.buildCodeFrameError("Vasille: Exprected expression");
81
+ }
82
+ }).flat(1),
83
+ ];
84
+ }
85
+ else {
86
+ throw path.buildCodeFrameError("Vasille: Only numbers arrays are suppored here");
87
+ }
88
+ }
89
+ throw path.buildCodeFrameError("Vasille: Failed o parse value, it is not a string, number or array");
90
+ }
91
+ function processProp(path, pseudo, media, internal) {
92
+ let name;
93
+ if (t.isIdentifier(path.node.key)) {
94
+ name = path.node.key.name;
95
+ }
96
+ else if (t.isStringLiteral(path.node.key)) {
97
+ name = path.node.key.value;
98
+ }
99
+ else {
100
+ throw path.get("key").buildCodeFrameError("Vasille: Incompaible key, exprect idenifier or string literal");
101
+ }
102
+ if (name.startsWith("@")) {
103
+ if (media || pseudo) {
104
+ throw path.get("key").buildCodeFrameError("Vasille: Media queries allowed inly in the root of style");
105
+ }
106
+ if (t.isObjectExpression(path.node.value)) {
107
+ return path.get("value").get("properties").map(item => {
108
+ return tryProcessProp(item, "", name, internal);
109
+ }).flat(1);
110
+ }
111
+ else {
112
+ throw path.get("value").buildCodeFrameError("Vasille: Exprected object expression");
113
+ }
114
+ }
115
+ if (name.startsWith(":")) {
116
+ if (pseudo) {
117
+ throw path.get("key").buildCodeFrameError("Recursive pseudo classes are restriced");
118
+ }
119
+ if (t.isObjectExpression(path.node.value)) {
120
+ return path.get("value").get("properties").map(item => {
121
+ return tryProcessProp(item, name, media, internal);
122
+ }).flat(1);
123
+ }
124
+ else {
125
+ throw path.get("value").buildCodeFrameError("Vasille: Exprected object expression");
126
+ }
127
+ }
128
+ return processValue(name, path.get("value"), pseudo, "", media, [], true, internal);
129
+ }
130
+ export function findStyleInNode(path, internal) {
131
+ if (t.isExpressionStatement(path.node)) {
132
+ return findStyleInNode(path.get("expression"), internal);
133
+ }
134
+ if (t.isExportNamedDeclaration(path.node)) {
135
+ return findStyleInNode(path.get("declaration"), internal);
136
+ }
137
+ if (t.isVariableDeclaration(path.node) &&
138
+ path.node.declarations.length === 1 &&
139
+ calls(path.node.declarations[0].init, ["webStyleSheet"], internal)) {
140
+ const call = path.node.declarations[0].init;
141
+ const callPath = path
142
+ .get("declarations")[0]
143
+ .get("init");
144
+ const objPath = callPath.get("arguments")[0];
145
+ if (call.arguments.length !== 1) {
146
+ throw callPath.buildCodeFrameError("Vasille: webStyleSheet function has 1 parameter");
147
+ }
148
+ if (!t.isObjectExpression(call.arguments[0])) {
149
+ throw objPath.buildCodeFrameError("Vasille: expected object expression");
150
+ }
151
+ for (const path of objPath.get("properties")) {
152
+ if (!t.isObjectProperty(path.node)) {
153
+ throw path.buildCodeFrameError("Vasille: Expected object property");
154
+ }
155
+ const prop = path;
156
+ if (!t.isObjectExpression(prop.node.value)) {
157
+ throw prop.get("value").buildCodeFrameError("Vasille: Exprected object expression");
158
+ }
159
+ if (!(t.isIdentifier(prop.node.key) || t.isStringLiteral(prop.node.key))) {
160
+ throw prop.get("key").buildCodeFrameError("Vasille: Expected identifier of string literal");
161
+ }
162
+ const unsorted = [];
163
+ const sorted = {};
164
+ for (const path of prop.get("value").get("properties")) {
165
+ unsorted.push(...tryProcessProp(path, "", "", internal));
166
+ }
167
+ for (const rule of unsorted) {
168
+ if (!sorted[rule.defaultMediaRule]) {
169
+ sorted[rule.defaultMediaRule] = {};
170
+ }
171
+ const defaultMediaRule = sorted[rule.defaultMediaRule];
172
+ if (!defaultMediaRule[rule.mediaRule]) {
173
+ defaultMediaRule[rule.mediaRule] = {};
174
+ }
175
+ const mediaRule = defaultMediaRule[rule.mediaRule];
176
+ if (!mediaRule[rule.theme]) {
177
+ mediaRule[rule.theme] = {};
178
+ }
179
+ const theme = mediaRule[rule.theme];
180
+ if (!theme[rule.pseudo]) {
181
+ theme[rule.pseudo] = [];
182
+ }
183
+ theme[rule.pseudo].push(rule.rule);
184
+ }
185
+ const expressions = [];
186
+ for (const defaultMediaRule in sorted) {
187
+ for (const mediaRule in sorted[defaultMediaRule]) {
188
+ for (const theme in sorted[defaultMediaRule][mediaRule]) {
189
+ for (const pseudo in sorted[defaultMediaRule][mediaRule][theme]) {
190
+ const rulePack = sorted[defaultMediaRule][mediaRule][theme][pseudo].join(";");
191
+ const pseudoPack = pseudo ? `{}${pseudo}{${rulePack}}` : `{}{${rulePack}}`;
192
+ const themePack = theme ? `${theme} ${pseudoPack}` : pseudoPack;
193
+ const mediaRulePack = t.stringLiteral(mediaRule ? `${mediaRule}{${themePack}}` : themePack);
194
+ expressions.push(defaultMediaRule !== '0'
195
+ ? t.arrayExpression([t.numericLiteral(parseInt(defaultMediaRule)), mediaRulePack])
196
+ : mediaRulePack);
197
+ }
198
+ }
199
+ }
200
+ }
201
+ prop.get("value").replaceWith(t.arrayExpression(expressions));
202
+ }
203
+ return true;
204
+ }
205
+ return false;
206
+ }
package/lib/expression.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as t from "@babel/types";
2
- import { StackedStates } from "./internal.js";
2
+ import { StackedStates } from "./internal";
3
3
  export function encodeName(name) {
4
4
  return t.identifier(`Vasille_${name}`);
5
5
  }
package/lib/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { trProgram } from "./transformer.js";
1
+ import { trProgram } from "./transformer";
2
2
  export default function () {
3
3
  return {
4
4
  name: "Vasille",
5
5
  visitor: {
6
6
  Program(path, params) {
7
- trProgram(path, params.devMode !== false);
7
+ trProgram(path, params.opts.devMode !== false);
8
8
  },
9
9
  },
10
10
  };
package/lib/jsx.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as t from "@babel/types";
2
- import { ctx } from "./internal.js";
3
- import { exprCall } from "./lib.js";
4
- import { compose, meshExpression } from "./mesh.js";
5
- import { bodyHasJsx } from "./jsx-detect.js";
2
+ import { ctx } from "./internal";
3
+ import { exprCall } from "./lib";
4
+ import { compose, meshExpression } from "./mesh";
5
+ import { bodyHasJsx } from "./jsx-detect";
6
6
  export function transformJsx(path, internal) {
7
7
  if (t.isJSXElement(path.node)) {
8
8
  return [transformJsxElement(path, internal)];
@@ -21,12 +21,31 @@ export function transformJsxArray(paths, internal) {
21
21
  .replace(/\n\s+$/m, "")
22
22
  .replace(/^\s*\n\s+/m, "")
23
23
  .replace(/\s*\n\s*/gm, "\n");
24
- result.push(t.expressionStatement(t.callExpression(t.memberExpression(ctx, t.identifier("text")), [t.stringLiteral(fixed)])));
24
+ const call = t.callExpression(t.memberExpression(ctx, t.identifier("text")), [t.stringLiteral(fixed)]);
25
+ call.loc = path.node.loc;
26
+ if (call.loc) {
27
+ for (const char of path.node.value) {
28
+ if (!/\s/.test(char)) {
29
+ break;
30
+ }
31
+ if (char === "\n") {
32
+ call.loc.start.column = 0;
33
+ call.loc.start.line++;
34
+ }
35
+ else {
36
+ call.loc.start.column++;
37
+ }
38
+ call.loc.start.index++;
39
+ }
40
+ }
41
+ result.push(t.expressionStatement(call));
25
42
  }
26
43
  }
27
44
  else if (t.isJSXExpressionContainer(path.node)) {
28
45
  const value = transformJsxExpressionContainer(path, internal, false, false);
29
- result.push(t.expressionStatement(t.callExpression(t.memberExpression(ctx, t.identifier("text")), [value])));
46
+ const call = t.callExpression(t.memberExpression(ctx, t.identifier("text")), [value]);
47
+ call.loc = value.loc;
48
+ result.push(t.expressionStatement(call));
30
49
  }
31
50
  else {
32
51
  throw path.buildCodeFrameError("Vasille: Spread child is not supported");
@@ -38,6 +57,7 @@ function transformJsxExpressionContainer(path, internal, acceptSlots, isInternal
38
57
  if (!t.isExpression(path.node.expression)) {
39
58
  return t.booleanLiteral(true);
40
59
  }
60
+ const loc = path.node.expression.loc;
41
61
  if (acceptSlots &&
42
62
  (t.isFunctionExpression(path.node.expression) || t.isArrowFunctionExpression(path.node.expression)) &&
43
63
  bodyHasJsx(path.node.expression.body)) {
@@ -51,6 +71,7 @@ function transformJsxExpressionContainer(path, internal, acceptSlots, isInternal
51
71
  else {
52
72
  path.node.expression.params.unshift(ctx);
53
73
  }
74
+ path.node.expression.loc = loc;
54
75
  return path.node.expression;
55
76
  }
56
77
  else if (isInternalSlot &&
@@ -63,15 +84,24 @@ function transformJsxExpressionContainer(path, internal, acceptSlots, isInternal
63
84
  internal.stack.get(path.node.expression.name) === 3 /* VariableState.ReactiveObject */) {
64
85
  call = t.callExpression(t.memberExpression(internal.id, t.identifier("rop")), [path.node.expression]);
65
86
  }
66
- return call !== null && call !== void 0 ? call : path.node.expression;
87
+ const result = call !== null && call !== void 0 ? call : path.node.expression;
88
+ result.loc = loc;
89
+ return result;
67
90
  }
68
- function id(str) {
91
+ function idToProp(id, value, from) {
92
+ let str = t.isIdentifier(id) || t.isJSXIdentifier(id) ? id.name : id.value;
93
+ let expr;
94
+ if (from) {
95
+ str = str.substring(from);
96
+ }
69
97
  if (/^[\w_]+$/.test(str)) {
70
- return t.identifier(str);
98
+ expr = t.identifier(str);
71
99
  }
72
100
  else {
73
- return t.stringLiteral(str);
101
+ expr = t.stringLiteral(str);
74
102
  }
103
+ expr.loc = id.loc;
104
+ return t.objectProperty(expr, value);
75
105
  }
76
106
  function transformJsxElement(path, internal) {
77
107
  var _a, _b;
@@ -97,7 +127,7 @@ function transformJsxElement(path, internal) {
97
127
  if (t.isExpression(path.node.expression)) {
98
128
  meshExpression(path.get("expression"), internal);
99
129
  }
100
- events.push(t.objectProperty(id(name.name.substring(2)), path.node.expression));
130
+ events.push(idToProp(name, path.node.expression, 2));
101
131
  }
102
132
  else {
103
133
  throw attrPath
@@ -116,7 +146,7 @@ function transformJsxElement(path, internal) {
116
146
  // class={[cond && "string"]}
117
147
  if (t.isLogicalExpression(item) && item.operator === "&&" && t.isStringLiteral(item.right)) {
118
148
  const call = exprCall(elementPath.get("left"), item.left, internal);
119
- classObject.push(t.objectProperty(id(item.right.value), call !== null && call !== void 0 ? call : item.left));
149
+ classObject.push(idToProp(item.right, call !== null && call !== void 0 ? call : item.left));
120
150
  }
121
151
  // class={[{..}]}
122
152
  else if (t.isObjectExpression(item)) {
@@ -142,7 +172,7 @@ function transformJsxElement(path, internal) {
142
172
  }
143
173
  // class={[".."]}
144
174
  else if (t.isStringLiteral(elementPath.node)) {
145
- classStatic.push(elementPath.node.value);
175
+ classStatic.push(elementPath.node);
146
176
  }
147
177
  // class={[..]}
148
178
  else {
@@ -172,10 +202,7 @@ function transformJsxElement(path, internal) {
172
202
  }
173
203
  // class="a b"
174
204
  else if (t.isStringLiteral(attr.value)) {
175
- const splitted = attr.value.value.split(" ");
176
- for (const item of splitted) {
177
- classStatic.push(item);
178
- }
205
+ classStatic.push(attr.value);
179
206
  }
180
207
  // class=<div/>
181
208
  else {
@@ -253,10 +280,10 @@ function transformJsxElement(path, internal) {
253
280
  }
254
281
  else {
255
282
  if (t.isJSXExpressionContainer(attr.value)) {
256
- attrs.push(t.objectProperty(id(name.name), t.isExpression(attr.value.expression) ? attr.value.expression : t.booleanLiteral(true)));
283
+ attrs.push(idToProp(name, t.isExpression(attr.value.expression) ? attr.value.expression : t.booleanLiteral(true)));
257
284
  }
258
285
  else if (t.isStringLiteral(attr.value)) {
259
- attrs.push(t.objectProperty(id(name.name), attr.value));
286
+ attrs.push(idToProp(name, attr.value));
260
287
  }
261
288
  else {
262
289
  throw attrPath.buildCodeFrameError("Vasille: Value of bind must be an expression or string");
@@ -269,10 +296,10 @@ function transformJsxElement(path, internal) {
269
296
  const value = t.isExpression(attr.value.expression)
270
297
  ? exprCall(attrPath.get("value"), attr.value.expression, internal)
271
298
  : undefined;
272
- bind.push(t.objectProperty(id(name.name.name), value !== null && value !== void 0 ? value : (t.isExpression(attr.value.expression) ? attr.value.expression : t.booleanLiteral(true))));
299
+ bind.push(idToProp(name.name, value !== null && value !== void 0 ? value : (t.isExpression(attr.value.expression) ? attr.value.expression : t.booleanLiteral(true))));
273
300
  }
274
301
  else if (t.isStringLiteral(attr.value)) {
275
- bind.push(t.objectProperty(id(name.name.name), attr.value));
302
+ bind.push(idToProp(name.name, attr.value));
276
303
  }
277
304
  else {
278
305
  throw attrPath.buildCodeFrameError("Vasille: Value of bind must be an expression or string");
@@ -288,13 +315,16 @@ function transformJsxElement(path, internal) {
288
315
  }
289
316
  }
290
317
  if (classStatic.length > 0) {
291
- attrs.push(t.objectProperty(t.identifier("class"), t.stringLiteral(classStatic.join(" "))));
318
+ const first = classStatic[0];
319
+ const value = classStatic.length === 1 ? classStatic[0] : t.stringLiteral(classStatic.map(item => item.value).join(" "));
320
+ value.loc = first.loc;
321
+ attrs.push(t.objectProperty(t.identifier("class"), value));
292
322
  }
293
323
  if (styleStatic.length > 0) {
294
324
  attrs.push(t.objectProperty(t.identifier("style"), t.stringLiteral(styleStatic.map(([id, value]) => `${id.name}:${value.value}`).join(";"))));
295
325
  }
296
326
  const statements = transformJsxArray(path.get("children"), internal);
297
- return t.expressionStatement(t.callExpression(t.memberExpression(ctx, t.identifier("tag")), [
327
+ const call = t.callExpression(t.memberExpression(ctx, t.identifier("tag")), [
298
328
  t.stringLiteral(name.name),
299
329
  t.objectExpression([
300
330
  ...(attrs.length > 0 ? [t.objectProperty(t.identifier("attr"), t.objectExpression(attrs))] : []),
@@ -311,26 +341,32 @@ function transformJsxElement(path, internal) {
311
341
  ...(styleObject.length > 0 ? [t.objectProperty(t.identifier("style"), t.objectExpression(styleObject))] : []),
312
342
  ]),
313
343
  ...(statements.length > 0 ? [t.arrowFunctionExpression([ctx], t.blockStatement(statements))] : []),
314
- ]));
344
+ ]);
345
+ call.loc = path.node.loc;
346
+ return t.expressionStatement(call);
315
347
  }
316
348
  if (t.isJSXIdentifier(name)) {
317
349
  const element = path.node;
318
350
  const opening = path.get("openingElement");
319
351
  const props = [];
320
352
  let run;
353
+ const mapped = internal.mapping.get(name.name);
354
+ if (mapped === "Debug" && internal.stack.get(name.name) === undefined && !internal.devMode) {
355
+ return t.emptyStatement();
356
+ }
321
357
  for (const attrPath of opening.get("attributes")) {
322
358
  const attr = attrPath.node;
323
359
  // <A prop=../>
324
360
  if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
325
361
  // <A prop=".."/>
326
362
  if (t.isStringLiteral(attr.value)) {
327
- props.push(t.objectProperty(id(attr.name.name), attr.value));
363
+ props.push(idToProp(attr.name, attr.value));
328
364
  }
329
365
  // <A prop={..}/>
330
366
  else if (t.isJSXExpressionContainer(attr.value)) {
331
367
  const isSystem = internal.mapping.has(name.name);
332
368
  const value = transformJsxExpressionContainer(attrPath.get("value"), internal, !isSystem || attr.name.name === "slot", isSystem && attr.name.name === "slot");
333
- props.push(t.objectProperty(id(attr.name.name), value));
369
+ props.push(idToProp(attr.name, value));
334
370
  }
335
371
  else {
336
372
  throw attrPath.buildCodeFrameError("Vasille: JSX Elements/Fragments are not supported here");
@@ -358,7 +394,9 @@ function transformJsxElement(path, internal) {
358
394
  run = t.arrowFunctionExpression([ctx], t.blockStatement(statements));
359
395
  }
360
396
  }
361
- return t.expressionStatement(t.callExpression(t.identifier(name.name), [ctx, t.objectExpression(props), ...(run ? [run] : [])]));
397
+ const call = t.callExpression(t.identifier(name.name), [ctx, t.objectExpression(props), ...(run ? [run] : [])]);
398
+ call.loc = path.node.loc;
399
+ return t.expressionStatement(call);
362
400
  }
363
401
  throw path.buildCodeFrameError("Vasille: Unsupported tag detected, html lowercase tagnames and components are accepted");
364
402
  }
package/lib/lib.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as t from "@babel/types";
2
- import { checkNode, encodeName } from "./expression.js";
3
- import { ctx } from "./internal.js";
4
- import { calls } from "./call.js";
2
+ import { checkNode, encodeName } from "./expression";
3
+ import { ctx } from "./internal";
4
+ import { calls } from "./call";
5
5
  export function parseCalculateCall(path, internal) {
6
6
  if (t.isCallExpression(path.node) && calls(path.node, ["calculate", "watch"], internal)) {
7
7
  if (path.node.arguments.length !== 1) {
package/lib/mesh.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as t from "@babel/types";
2
- import { calls, composeOnly } from "./call.js";
3
- import { ctx } from "./internal.js";
4
- import { bodyHasJsx } from "./jsx-detect.js";
5
- import { arrayModel, exprCall, forwardOnlyExpr, mapModel, own, parseCalculateCall, reactiveObject, ref, setModel, } from "./lib.js";
6
- import { transformJsx } from "./jsx.js";
2
+ import { calls, composeOnly, styleOnly } from "./call";
3
+ import { ctx } from "./internal";
4
+ import { bodyHasJsx } from "./jsx-detect";
5
+ import { arrayModel, exprCall, forwardOnlyExpr, mapModel, own, parseCalculateCall, reactiveObject, ref, setModel, } from "./lib";
6
+ import { transformJsx } from "./jsx";
7
7
  export function meshOrIgnoreAllExpressions(nodePaths, internal) {
8
8
  for (const path of nodePaths) {
9
9
  if (t.isExpression(path.node)) {
@@ -97,11 +97,20 @@ export function meshExpression(nodePath, internal) {
97
97
  meshAllUnknown(path.get("elements"), internal);
98
98
  break;
99
99
  }
100
- case "CallExpression": {
100
+ case "CallExpression":
101
+ case "OptionalCallExpression": {
101
102
  const path = nodePath;
102
103
  const callsFn = calls(path.node, composeOnly, internal);
104
+ const callsStyleHint = calls(path.node, styleOnly, internal);
105
+ const callsStyleCreate = calls(path.node, ["webStyleSheet"], internal);
103
106
  if (callsFn) {
104
- throw path.buildCodeFrameError(`Vasille: Usage of function "${callsFn}" is restricted here`);
107
+ throw path.buildCodeFrameError(`Vasille: Usage of hint "${callsFn}" is restricted here`);
108
+ }
109
+ if (callsStyleHint) {
110
+ throw path.buildCodeFrameError(`Vasille: Usage of style hint "${callsStyleHint}" is restricted here`);
111
+ }
112
+ if (callsStyleCreate) {
113
+ throw path.buildCodeFrameError("Vasille: Styles can be created in moldule level code only");
105
114
  }
106
115
  meshOrIgnoreExpression(path.get("callee"), internal);
107
116
  meshAllUnknown(path.get("arguments"), internal);
@@ -113,12 +122,6 @@ export function meshExpression(nodePath, internal) {
113
122
  }
114
123
  break;
115
124
  }
116
- case "OptionalCallExpression": {
117
- const path = nodePath;
118
- meshExpression(path.get("callee"), internal);
119
- meshAllUnknown(path.get("arguments"), internal);
120
- break;
121
- }
122
125
  case "AssignmentExpression": {
123
126
  const path = nodePath;
124
127
  const left = path.node.left;