babel-plugin-vasille 0.99.2 → 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.
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.findStyleInNode = findStyleInNode;
27
+ const t = __importStar(require("@babel/types"));
28
+ const call_1 = require("./call");
29
+ function tryProcessProp(path, pseudo, media, internal) {
30
+ if (t.isObjectMethod(path.node)) {
31
+ throw path.buildCodeFrameError("Object methods not supported here");
32
+ }
33
+ if (t.isSpreadElement(path.node)) {
34
+ throw path.buildCodeFrameError("Spread element not suppored here");
35
+ }
36
+ return processProp(path, pseudo, media, internal);
37
+ }
38
+ const mediaDefaults = ["mobile", "tablet", "laptop", "prefersDark", "prefersLight"];
39
+ function processValue(name, path, pseudo, theme, media, mediaDefault, allowFallback, internal) {
40
+ if ((0, call_1.calls)(path.node, ["theme"], internal)) {
41
+ const call = path.node;
42
+ if (theme) {
43
+ throw path.buildCodeFrameError("Vasille: Theme seem the be defined twince");
44
+ }
45
+ if (t.isStringLiteral(call.arguments[0])) {
46
+ return processValue(name, path.get("arguments")[1], pseudo, `body.${call.arguments[0].value}`, media, mediaDefault, false, internal);
47
+ }
48
+ else {
49
+ throw path
50
+ .get("arguments")[0]
51
+ .buildCodeFrameError("Vasille: Expected string literal");
52
+ }
53
+ }
54
+ if ((0, call_1.calls)(path.node, ["dark"], internal)) {
55
+ if (theme) {
56
+ throw path.buildCodeFrameError("Vasille: Theme seem the be defined twince");
57
+ }
58
+ return processValue(name, path.get("arguments")[0], pseudo, `.dark`, media, mediaDefault, false, internal);
59
+ }
60
+ let callee;
61
+ if ((callee = (0, call_1.calls)(path.node, mediaDefaults, internal))) {
62
+ const index = mediaDefaults.indexOf(callee) + 1;
63
+ if (mediaDefault.includes(index)) {
64
+ return processValue(name, path.get("arguments")[0], pseudo, theme, media, mediaDefault, false, internal);
65
+ }
66
+ return processValue(name, path.get("arguments")[0], pseudo, theme, media, [...mediaDefault, index], false, internal);
67
+ }
68
+ function composeRules(value) {
69
+ return mediaDefault.length
70
+ ? mediaDefault.map(index => {
71
+ return {
72
+ defaultMediaRule: index,
73
+ mediaRule: media,
74
+ pseudo: pseudo,
75
+ theme: theme,
76
+ rule: `${name}:${value}`,
77
+ };
78
+ })
79
+ : [
80
+ {
81
+ defaultMediaRule: 0,
82
+ mediaRule: media,
83
+ pseudo: pseudo,
84
+ theme: theme,
85
+ rule: `${name}:${value}`,
86
+ },
87
+ ];
88
+ }
89
+ if (t.isStringLiteral(path.node)) {
90
+ return composeRules(path.node.value);
91
+ }
92
+ if (t.isNumericLiteral(path.node)) {
93
+ return composeRules(`${path.node.value}px`);
94
+ }
95
+ if (t.isArrayExpression(path.node)) {
96
+ if (path.node.elements.every(item => t.isNumericLiteral(item))) {
97
+ return composeRules(path.node.elements.map(item => `${item.value}px`).join(" "));
98
+ }
99
+ else if (allowFallback) {
100
+ return [
101
+ ...path.get("elements").map(path => {
102
+ if (t.isExpression(path.node)) {
103
+ return processValue(name, path, pseudo, theme, media, mediaDefault, false, internal);
104
+ }
105
+ else {
106
+ throw path.buildCodeFrameError("Vasille: Exprected expression");
107
+ }
108
+ }).flat(1),
109
+ ];
110
+ }
111
+ else {
112
+ throw path.buildCodeFrameError("Vasille: Only numbers arrays are suppored here");
113
+ }
114
+ }
115
+ throw path.buildCodeFrameError("Vasille: Failed o parse value, it is not a string, number or array");
116
+ }
117
+ function processProp(path, pseudo, media, internal) {
118
+ let name;
119
+ if (t.isIdentifier(path.node.key)) {
120
+ name = path.node.key.name;
121
+ }
122
+ else if (t.isStringLiteral(path.node.key)) {
123
+ name = path.node.key.value;
124
+ }
125
+ else {
126
+ throw path.get("key").buildCodeFrameError("Vasille: Incompaible key, exprect idenifier or string literal");
127
+ }
128
+ if (name.startsWith("@")) {
129
+ if (media || pseudo) {
130
+ throw path.get("key").buildCodeFrameError("Vasille: Media queries allowed inly in the root of style");
131
+ }
132
+ if (t.isObjectExpression(path.node.value)) {
133
+ return path.get("value").get("properties").map(item => {
134
+ return tryProcessProp(item, "", name, internal);
135
+ }).flat(1);
136
+ }
137
+ else {
138
+ throw path.get("value").buildCodeFrameError("Vasille: Exprected object expression");
139
+ }
140
+ }
141
+ if (name.startsWith(":")) {
142
+ if (pseudo) {
143
+ throw path.get("key").buildCodeFrameError("Recursive pseudo classes are restriced");
144
+ }
145
+ if (t.isObjectExpression(path.node.value)) {
146
+ return path.get("value").get("properties").map(item => {
147
+ return tryProcessProp(item, name, media, internal);
148
+ }).flat(1);
149
+ }
150
+ else {
151
+ throw path.get("value").buildCodeFrameError("Vasille: Exprected object expression");
152
+ }
153
+ }
154
+ return processValue(name, path.get("value"), pseudo, "", media, [], true, internal);
155
+ }
156
+ function findStyleInNode(path, internal) {
157
+ if (t.isExpressionStatement(path.node)) {
158
+ return findStyleInNode(path.get("expression"), internal);
159
+ }
160
+ if (t.isExportNamedDeclaration(path.node)) {
161
+ return findStyleInNode(path.get("declaration"), internal);
162
+ }
163
+ if (t.isVariableDeclaration(path.node) &&
164
+ path.node.declarations.length === 1 &&
165
+ (0, call_1.calls)(path.node.declarations[0].init, ["webStyleSheet"], internal)) {
166
+ const call = path.node.declarations[0].init;
167
+ const callPath = path
168
+ .get("declarations")[0]
169
+ .get("init");
170
+ const objPath = callPath.get("arguments")[0];
171
+ if (call.arguments.length !== 1) {
172
+ throw callPath.buildCodeFrameError("Vasille: webStyleSheet function has 1 parameter");
173
+ }
174
+ if (!t.isObjectExpression(call.arguments[0])) {
175
+ throw objPath.buildCodeFrameError("Vasille: expected object expression");
176
+ }
177
+ for (const path of objPath.get("properties")) {
178
+ if (!t.isObjectProperty(path.node)) {
179
+ throw path.buildCodeFrameError("Vasille: Expected object property");
180
+ }
181
+ const prop = path;
182
+ if (!t.isObjectExpression(prop.node.value)) {
183
+ throw prop.get("value").buildCodeFrameError("Vasille: Exprected object expression");
184
+ }
185
+ if (!(t.isIdentifier(prop.node.key) || t.isStringLiteral(prop.node.key))) {
186
+ throw prop.get("key").buildCodeFrameError("Vasille: Expected identifier of string literal");
187
+ }
188
+ const unsorted = [];
189
+ const sorted = {};
190
+ for (const path of prop.get("value").get("properties")) {
191
+ unsorted.push(...tryProcessProp(path, "", "", internal));
192
+ }
193
+ for (const rule of unsorted) {
194
+ if (!sorted[rule.defaultMediaRule]) {
195
+ sorted[rule.defaultMediaRule] = {};
196
+ }
197
+ const defaultMediaRule = sorted[rule.defaultMediaRule];
198
+ if (!defaultMediaRule[rule.mediaRule]) {
199
+ defaultMediaRule[rule.mediaRule] = {};
200
+ }
201
+ const mediaRule = defaultMediaRule[rule.mediaRule];
202
+ if (!mediaRule[rule.theme]) {
203
+ mediaRule[rule.theme] = {};
204
+ }
205
+ const theme = mediaRule[rule.theme];
206
+ if (!theme[rule.pseudo]) {
207
+ theme[rule.pseudo] = [];
208
+ }
209
+ theme[rule.pseudo].push(rule.rule);
210
+ }
211
+ const expressions = [];
212
+ for (const defaultMediaRule in sorted) {
213
+ for (const mediaRule in sorted[defaultMediaRule]) {
214
+ for (const theme in sorted[defaultMediaRule][mediaRule]) {
215
+ for (const pseudo in sorted[defaultMediaRule][mediaRule][theme]) {
216
+ const rulePack = sorted[defaultMediaRule][mediaRule][theme][pseudo].join(";");
217
+ const pseudoPack = pseudo ? `{}${pseudo}{${rulePack}}` : `{}{${rulePack}}`;
218
+ const themePack = theme ? `${theme} ${pseudoPack}` : pseudoPack;
219
+ const mediaRulePack = t.stringLiteral(mediaRule ? `${mediaRule}{${themePack}}` : themePack);
220
+ expressions.push(defaultMediaRule !== '0'
221
+ ? t.arrayExpression([t.numericLiteral(parseInt(defaultMediaRule)), mediaRulePack])
222
+ : mediaRulePack);
223
+ }
224
+ }
225
+ }
226
+ }
227
+ prop.get("value").replaceWith(t.arrayExpression(expressions));
228
+ }
229
+ return true;
230
+ }
231
+ return false;
232
+ }
package/lib-node/mesh.js CHANGED
@@ -139,11 +139,20 @@ function meshExpression(nodePath, internal) {
139
139
  meshAllUnknown(path.get("elements"), internal);
140
140
  break;
141
141
  }
142
- case "CallExpression": {
142
+ case "CallExpression":
143
+ case "OptionalCallExpression": {
143
144
  const path = nodePath;
144
145
  const callsFn = (0, call_1.calls)(path.node, call_1.composeOnly, internal);
146
+ const callsStyleHint = (0, call_1.calls)(path.node, call_1.styleOnly, internal);
147
+ const callsStyleCreate = (0, call_1.calls)(path.node, ["webStyleSheet"], internal);
145
148
  if (callsFn) {
146
- throw path.buildCodeFrameError(`Vasille: Usage of function "${callsFn}" is restricted here`);
149
+ throw path.buildCodeFrameError(`Vasille: Usage of hint "${callsFn}" is restricted here`);
150
+ }
151
+ if (callsStyleHint) {
152
+ throw path.buildCodeFrameError(`Vasille: Usage of style hint "${callsStyleHint}" is restricted here`);
153
+ }
154
+ if (callsStyleCreate) {
155
+ throw path.buildCodeFrameError("Vasille: Styles can be created in moldule level code only");
147
156
  }
148
157
  meshOrIgnoreExpression(path.get("callee"), internal);
149
158
  meshAllUnknown(path.get("arguments"), internal);
@@ -155,12 +164,6 @@ function meshExpression(nodePath, internal) {
155
164
  }
156
165
  break;
157
166
  }
158
- case "OptionalCallExpression": {
159
- const path = nodePath;
160
- meshExpression(path.get("callee"), internal);
161
- meshAllUnknown(path.get("arguments"), internal);
162
- break;
163
- }
164
167
  case "AssignmentExpression": {
165
168
  const path = nodePath;
166
169
  const left = path.node.left;
@@ -27,6 +27,7 @@ exports.trProgram = trProgram;
27
27
  const t = __importStar(require("@babel/types"));
28
28
  const internal_1 = require("./internal");
29
29
  const mesh_1 = require("./mesh");
30
+ const css_transformer_1 = require("./css-transformer");
30
31
  const imports = new Map([
31
32
  ["vasille-dx", "VasilleDX"],
32
33
  ["vasille-web", "VasilleWeb"],
@@ -41,12 +42,20 @@ const ignoreMembers = new Set([
41
42
  "mapModel",
42
43
  "reactiveObject",
43
44
  "setModel",
45
+ "theme",
46
+ "dark",
47
+ "mobile",
48
+ "tablet",
49
+ "laptop",
50
+ "prefersDark",
51
+ "prefersLight",
44
52
  ]);
45
53
  function extractText(node) {
46
54
  return t.isIdentifier(node) ? node.name : node.value;
47
55
  }
48
56
  function trProgram(path, devMode) {
49
57
  let id;
58
+ let stylesConnected = false;
50
59
  const internal = {
51
60
  get id() {
52
61
  this.internalUsed = true;
@@ -58,6 +67,7 @@ function trProgram(path, devMode) {
58
67
  stack: new internal_1.StackedStates(),
59
68
  mapping: new Map(),
60
69
  global: "",
70
+ cssGlobal: "",
61
71
  prefix: "Vasille_",
62
72
  importStatement: null,
63
73
  internalUsed: false,
@@ -72,12 +82,19 @@ function trProgram(path, devMode) {
72
82
  for (const specifier of statement.specifiers) {
73
83
  if (t.isImportNamespaceSpecifier(specifier)) {
74
84
  internal.global = specifier.local.name;
85
+ if (statement.source.value === "vasille-web") {
86
+ internal.cssGlobal = internal.global;
87
+ stylesConnected = true;
88
+ }
75
89
  id = t.memberExpression(t.identifier(internal.global), t.identifier("$"));
76
90
  }
77
91
  else if (t.isImportSpecifier(specifier)) {
78
92
  const imported = extractText(specifier.imported);
79
93
  const local = specifier.local.name;
80
94
  internal.mapping.set(local, imported);
95
+ if (imported === "webStyleSheet") {
96
+ stylesConnected = true;
97
+ }
81
98
  if (!id) {
82
99
  id = t.identifier(name);
83
100
  }
@@ -93,12 +110,36 @@ function trProgram(path, devMode) {
93
110
  }
94
111
  });
95
112
  }
113
+ else if (statement.source.value === "vasille-css") {
114
+ for (const specifier of statement.specifiers) {
115
+ if (t.isImportSpecifier(specifier)) {
116
+ internal.mapping.set(specifier.local.name, extractText(specifier.imported));
117
+ }
118
+ else if (t.isImportNamespaceSpecifier(specifier)) {
119
+ internal.cssGlobal = specifier.local.name;
120
+ }
121
+ }
122
+ statement.specifiers = statement.specifiers.filter(spec => {
123
+ if (!t.isImportSpecifier(spec)) {
124
+ return true;
125
+ }
126
+ else {
127
+ return !ignoreMembers.has(extractText(spec.imported));
128
+ }
129
+ });
130
+ stylesConnected = true;
131
+ }
96
132
  }
97
133
  else {
98
134
  if (!id) {
135
+ if (stylesConnected) {
136
+ (0, css_transformer_1.findStyleInNode)(statementPath, internal);
137
+ }
99
138
  return;
100
139
  }
101
- (0, mesh_1.meshStatement)(statementPath, internal);
140
+ if (!stylesConnected || !(0, css_transformer_1.findStyleInNode)(statementPath, internal)) {
141
+ (0, mesh_1.meshStatement)(statementPath, internal);
142
+ }
102
143
  }
103
144
  }
104
145
  if (internal.internalUsed && !internal.global && internal.importStatement) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "babel-plugin-vasille",
3
- "version": "0.99.2",
4
- "description": "",
3
+ "version": "0.99.3",
4
+ "description": "Convert Vasille Meta Language code to pure JavaScript",
5
5
  "main": "lib-node/index.js",
6
6
  "type": "commonjs",
7
7
  "exports": {
@@ -21,7 +21,9 @@
21
21
  "keywords": [
22
22
  "front-end",
23
23
  "framework",
24
- "dx"
24
+ "web",
25
+ "compiler",
26
+ "babel"
25
27
  ],
26
28
  "author": "lixcode",
27
29
  "license": "MIT",
@@ -29,9 +31,6 @@
29
31
  "url": "https://github.com/vasille-js/vasille-js/issues"
30
32
  },
31
33
  "homepage": "https://github.com/vasille-js/vasille-js#readme",
32
- "dependencies": {
33
- "vasille-dx": "^3.0.3"
34
- },
35
34
  "devDependencies": {
36
35
  "@babel/parser": "^7.26.1",
37
36
  "@babel/plugin-syntax-jsx": "^7.25.9",
@@ -46,6 +45,8 @@
46
45
  "path": "^0.12.7",
47
46
  "prettier": "^3.3.3",
48
47
  "ts-jest": "^29.2.5",
49
- "typescript": "^5.6.3"
48
+ "typescript": "^5.6.3",
49
+ "vasille-css": "^3.0.3",
50
+ "vasille-dx": "^3.0.3"
50
51
  }
51
52
  }