babel-plugin-vasille 5.0.4 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  `SteelFrameKit` is a front-end development kit, which is developed to provide fault tolerant web applications.
6
6
 
7
- [![npm](https://img.shields.io/npm/v/steel-frame?style=flat-square)](https://www.npmjs.com/package/steel-frame)
7
+ [![npm](https://img.shields.io/npm/v/steel-frame?style=round-square)](https://www.npmjs.com/package/steel-frame)
8
8
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/vasille-js/steel-frame)
9
9
  [![Coverage Status](https://coveralls.io/repos/github/vasille-js/steel-frame/badge.svg?branch=v5)](https://coveralls.io/github/vasille-js/steel-frame?branch=v5)
10
10
 
@@ -21,6 +21,7 @@
21
21
  - [How POWERFUL is SteelFrameKit](#how-powerful-is-steelframekit)
22
22
  - [Road map](#road-map)
23
23
  - [Change log](#change-log)
24
+ - [5.1](#51)
24
25
  - [5.0](#50)
25
26
  - [4.0 - 4.3](#40---43)
26
27
  - [3.0 - 3.2](#30---32)
@@ -119,10 +120,15 @@ All of these are supported:
119
120
  ## Change log
120
121
 
121
122
  We respect semantic versioning:
122
- - Major version is increased when we make incompatible API changes.
123
- - Minor version is increased when we add functionality.
123
+ - A major version is increased when we make incompatible API changes.
124
+ - A minor version is increased when we add functionality.
124
125
  - Patch version is increased when we fix bugs.
125
126
 
127
+ ### 5.1
128
+
129
+ Add support for web components compile target `web build components`.
130
+ _Web components as custom tags are supported in any version._
131
+
126
132
  ### 5.0
127
133
 
128
134
  - Add support for context and dependencies injection.
@@ -142,7 +148,7 @@ We respect semantic versioning:
142
148
  ### 3.0 - 3.2
143
149
 
144
150
  - Switch to a babel plugin to compile components code. **[API change]**
145
- - 100% of code has been covered with unit tests.
151
+ - 100% of the code has been covered with unit tests.
146
152
  - New developement direction: `keep it simple`.
147
153
 
148
154
  ### 2.0 - 2.3
@@ -152,7 +158,7 @@ We respect semantic versioning:
152
158
 
153
159
  ### 1.0 - 1.2
154
160
 
155
- - Initial version of core library.
161
+ - Initial version of a core library.
156
162
  - Developemnt direction: `performance-first`.
157
163
 
158
164
  ## Questions
package/lib/index.js CHANGED
@@ -13,6 +13,7 @@ function default_1() {
13
13
  replaceWeb: typeof params.opts.replaceWeb === "string" ? params.opts.replaceWeb : undefined,
14
14
  headTag: !!params.opts.headTag,
15
15
  bodyTag: !!params.opts.bodyTag,
16
+ shadow: !!params.opts.shadow,
16
17
  });
17
18
  },
18
19
  },
package/lib/jsx.js CHANGED
@@ -615,12 +615,37 @@ function transformJsxElement(path, conditions, internal) {
615
615
  }
616
616
  return ret;
617
617
  }
618
- const call = t.callExpression(t.identifier(name.name), [
619
- t.objectExpression(props),
620
- internal_js_1.ctx,
621
- ...(run ? [run] : internal.devLayer ? [t.buildUndefinedNode()] : []),
622
- ...(internal.devLayer ? [(0, transformer_1.nodeToStaticPosition)(path.node)] : []),
623
- ]);
618
+ if (internal.shadow && mapped === "Slot") {
619
+ const model = props.find(item => t.isObjectProperty(item) && t.isIdentifier(item.key) && item.key.name === "model");
620
+ const modelName = t.isObjectProperty(model) &&
621
+ ((t.isIdentifier(model.value) && model.value.name) ||
622
+ ((t.isMemberExpression(model.value) || t.isOptionalMemberExpression(model.value)) &&
623
+ t.isIdentifier(model.value.property) &&
624
+ model.value.property.name));
625
+ const call = t.callExpression(t.memberExpression(internal_js_1.ctx, t.identifier("tag")), [
626
+ t.stringLiteral("slot"),
627
+ t.objectExpression(modelName && modelName !== "slot"
628
+ ? [
629
+ t.objectProperty(t.identifier("a"), t.objectExpression([t.objectProperty(t.identifier("name"), t.stringLiteral(modelName))])),
630
+ ]
631
+ : []),
632
+ ...(run ? [run] : []),
633
+ ]);
634
+ run = t.arrowFunctionExpression([internal_js_1.ctx], call);
635
+ }
636
+ const localComponentName = internal.shadow && internal.componentsImports.get(name.name);
637
+ const call = localComponentName
638
+ ? t.callExpression(t.memberExpression(internal_js_1.ctx, t.identifier("tag")), [
639
+ t.stringLiteral((0, lib_js_1.toKebabCase)(localComponentName)),
640
+ t.objectExpression([t.objectProperty(t.identifier("b"), t.objectExpression(props))]),
641
+ ...(run ? [run] : []),
642
+ ])
643
+ : t.callExpression(t.identifier(name.name), [
644
+ t.objectExpression(props),
645
+ internal_js_1.ctx,
646
+ ...(run ? [run] : internal.devLayer ? [t.buildUndefinedNode()] : []),
647
+ ...(internal.devLayer ? [(0, transformer_1.nodeToStaticPosition)(path.node)] : []),
648
+ ]);
624
649
  call.loc = path.node.loc;
625
650
  return [...ret, t.expressionStatement(call)];
626
651
  }
package/lib/lib.js CHANGED
@@ -46,6 +46,7 @@ exports.mapModel = mapModel;
46
46
  exports.processModelCall = processModelCall;
47
47
  exports.checkReactiveName = checkReactiveName;
48
48
  exports.checkNonReactiveName = checkNonReactiveName;
49
+ exports.toKebabCase = toKebabCase;
49
50
  const t = __importStar(require("@babel/types"));
50
51
  const expression_js_1 = require("./expression.js");
51
52
  const internal_js_1 = require("./internal.js");
@@ -189,3 +190,15 @@ function checkNonReactiveName(idPath, internal) {
189
190
  err(Errors.RulesOfVasille, idPath, "Non-reactive variable name must not start with $", internal);
190
191
  }
191
192
  }
193
+ function toKebabCase(name) {
194
+ let index = 0;
195
+ let fixed = name[index].toLowerCase();
196
+ for (index++; index < name.length; index++) {
197
+ const curr = name[index];
198
+ if (curr === curr.toUpperCase()) {
199
+ fixed += "-";
200
+ }
201
+ fixed += curr.toLowerCase();
202
+ }
203
+ return fixed;
204
+ }
package/lib/mesh.js CHANGED
@@ -60,6 +60,7 @@ const order_check_1 = require("./order-check");
60
60
  const router_1 = require("./router");
61
61
  const utils_1 = require("./utils");
62
62
  const transformer_1 = require("./transformer");
63
+ const process_types_1 = require("./process-types");
63
64
  function meshOrIgnoreAllExpressions(nodePaths, internal) {
64
65
  for (const path of nodePaths) {
65
66
  /* istanbul ignore else */
@@ -73,9 +74,19 @@ function meshAllExpressions(nodePaths, internal) {
73
74
  meshExpression(path, internal);
74
75
  }
75
76
  }
76
- function meshComposeCall(name, path, internal) {
77
+ const restrictedNames = [
78
+ "annotation-xml",
79
+ "color-profile",
80
+ "font-face",
81
+ "font-face-src",
82
+ "font-face-uri",
83
+ "font-face-format",
84
+ "font-face-name",
85
+ "missing-glyph",
86
+ ];
87
+ function meshComposeCall(name, path, internal, isExported = false) {
77
88
  const args = path.isCallExpression() && path.get("arguments");
78
- const arg = args && (args[0].isFunctionExpression() || args[0].isArrowFunctionExpression()) && args[0];
89
+ const arg = args && args[0] && (args[0].isFunctionExpression() || args[0].isArrowFunctionExpression()) && args[0];
79
90
  if (!args || !arg || args.length !== 1) {
80
91
  return (0, lib_js_1.err)(lib_js_1.Errors.IncorrectArguments, path, "Invalid arguments number", internal);
81
92
  }
@@ -84,6 +95,33 @@ function meshComposeCall(name, path, internal) {
84
95
  if (internal.devLayer && path.isCallExpression()) {
85
96
  path.node.arguments.push((0, transformer_1.nodeToStaticPosition)(path.node), t.stringLiteral(name ? name : "#"));
86
97
  }
98
+ if (internal.shadow && isExported && name && path.isCallExpression()) {
99
+ const call = path.node;
100
+ const generics = call.typeParameters?.params;
101
+ const args = call.arguments;
102
+ const params = (t.isFunctionExpression(args[0]) || t.isArrowFunctionExpression(args[0])) && args[0].params;
103
+ const annotation = (generics && generics[0]) ||
104
+ (params && params[1] && !t.isVoidPattern(params[1]) && params[1].typeAnnotation) ||
105
+ null;
106
+ const type = (t.isTSTypeAnnotation(annotation) && annotation.typeAnnotation) || (t.isTSType(annotation) && annotation) || null;
107
+ const kebabName = (0, lib_js_1.toKebabCase)(name);
108
+ let fields;
109
+ if (t.isTSTypeLiteral(type)) {
110
+ fields = (0, process_types_1.processTypeLiteral)(type);
111
+ }
112
+ if (t.isTSTypeReference(type)) {
113
+ fields = (0, process_types_1.processReference)(type, internal);
114
+ }
115
+ if (kebabName.indexOf("-") === -1 || restrictedNames.indexOf(kebabName) !== -1) {
116
+ (0, lib_js_1.err)(lib_js_1.Errors.ParserError, path, `The name '${kebabName}' is not allowed by WHATWG`, internal);
117
+ }
118
+ if (fields) {
119
+ path.node.arguments.push(t.stringLiteral(kebabName), fields);
120
+ }
121
+ else {
122
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, path, "Missing type for web component composition", internal);
123
+ }
124
+ }
87
125
  }
88
126
  function meshAllUnknown(paths, internal) {
89
127
  for (const path of paths) {
@@ -816,7 +854,7 @@ function meshStatement(path, internal) {
816
854
  report(`File name is not correct, expected ${name}.ts, ${name}.tsx, ${name}.js or ${name}.jsx`);
817
855
  }
818
856
  }
819
- meshComposeCall(id.name, initPath, internal);
857
+ meshComposeCall(id.name, initPath, internal, isExported);
820
858
  }
821
859
  // calculate call
822
860
  else if ((0, call_js_1.calls)(initPath, ["calculate"], internal) &&
@@ -892,6 +930,19 @@ function meshStatement(path, internal) {
892
930
  meshClassBody(declarationPath.get("body"), internal);
893
931
  }
894
932
  }
933
+ break;
934
+ }
935
+ case "TSInterfaceDeclaration": {
936
+ const declaration = path.node;
937
+ (0, process_types_1.registerInterface)(declaration.id.name, declaration.body.body, internal);
938
+ break;
939
+ }
940
+ case "TSTypeAliasDeclaration": {
941
+ const alias = path.node;
942
+ if (t.isTSTypeLiteral(alias.typeAnnotation)) {
943
+ (0, process_types_1.registerInterface)(alias.id.name, alias.typeAnnotation.members, internal);
944
+ }
945
+ break;
895
946
  }
896
947
  }
897
948
  }
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerInterface = registerInterface;
4
+ exports.processUnion = processUnion;
5
+ exports.processType = processType;
6
+ exports.processSignatures = processSignatures;
7
+ exports.processTypeLiteral = processTypeLiteral;
8
+ exports.processReference = processReference;
9
+ const types_1 = require("@babel/types");
10
+ const any = 0;
11
+ const string = 1;
12
+ const number = 2;
13
+ const boolean = 3;
14
+ function registerInterface(name, members, internal) {
15
+ internal.interfaces.set(name, members);
16
+ }
17
+ function processUnion(type) {
18
+ let isString = false;
19
+ let isNumber = false;
20
+ let isBoolean = false;
21
+ let isAny = false;
22
+ for (const keyword of type.types) {
23
+ if ((0, types_1.isTSStringKeyword)(keyword)) {
24
+ isString = true;
25
+ }
26
+ else if ((0, types_1.isTSNumberKeyword)(keyword)) {
27
+ isNumber = true;
28
+ }
29
+ else if ((0, types_1.isTSBooleanKeyword)(keyword)) {
30
+ isBoolean = true;
31
+ }
32
+ else if (!(0, types_1.isTSNullKeyword)(keyword) && !(0, types_1.isTSUndefinedKeyword)(keyword)) {
33
+ isAny = true;
34
+ }
35
+ }
36
+ if (isAny) {
37
+ return any;
38
+ }
39
+ if (isString) {
40
+ return string;
41
+ }
42
+ if (isNumber && !isBoolean) {
43
+ return number;
44
+ }
45
+ if (isBoolean && !isNumber) {
46
+ return boolean;
47
+ }
48
+ return any;
49
+ }
50
+ function processType(type) {
51
+ if ((0, types_1.isTSUnionType)(type)) {
52
+ return processUnion(type);
53
+ }
54
+ if ((0, types_1.isTSStringKeyword)(type)) {
55
+ return string;
56
+ }
57
+ if ((0, types_1.isTSNumberKeyword)(type)) {
58
+ return number;
59
+ }
60
+ if ((0, types_1.isTSBooleanKeyword)(type)) {
61
+ return boolean;
62
+ }
63
+ return any;
64
+ }
65
+ function processSignatures(members) {
66
+ const props = [];
67
+ for (const member of members) {
68
+ if ((0, types_1.isTSPropertySignature)(member)) {
69
+ props.push((0, types_1.objectProperty)(member.key, (0, types_1.numericLiteral)(member.typeAnnotation ? processType(member.typeAnnotation.typeAnnotation) : any)));
70
+ }
71
+ }
72
+ return (0, types_1.objectExpression)(props);
73
+ }
74
+ function processTypeLiteral(literal) {
75
+ return processSignatures(literal.members);
76
+ }
77
+ function processReference(id, internal) {
78
+ /* istanbul ignore else */
79
+ if ((0, types_1.isIdentifier)(id.typeName)) {
80
+ const members = internal.interfaces.get(id.typeName.name);
81
+ return members ? processSignatures(members) : undefined;
82
+ }
83
+ }
@@ -69,12 +69,44 @@ function extractText(node) {
69
69
  // no case found for string literal
70
70
  return node.name;
71
71
  }
72
+ function extractComponentImport(node, internal) {
73
+ const name = node.source.value;
74
+ const match = /^(@\/components|\.)\/([^\/.]+)\.[tj]sx?$/.exec(name);
75
+ if (!match) {
76
+ return;
77
+ }
78
+ const filename = match[2];
79
+ const toRemove = [];
80
+ for (const specifier of node.specifiers) {
81
+ if (t.isImportDefaultSpecifier(specifier)) {
82
+ toRemove.push(specifier);
83
+ internal.componentsImports.set(specifier.local.name, filename);
84
+ }
85
+ if (t.isImportSpecifier(specifier)) {
86
+ const imported = extractText(specifier.imported);
87
+ // the exported component name must match the file name
88
+ /* istanbul ignore else */
89
+ if (imported === filename) {
90
+ toRemove.push(specifier);
91
+ internal.componentsImports.set(specifier.local.name, filename);
92
+ }
93
+ }
94
+ }
95
+ /* istanbul ignore else */
96
+ if (toRemove.length) {
97
+ node.specifiers = node.specifiers.filter(item => !toRemove.includes(item));
98
+ }
99
+ }
72
100
  // Handles import declarations and updates internal state
73
101
  function handleImportDeclaration(statementPath, internal, ids) {
74
102
  const statement = statementPath.node;
75
103
  const name = imports.get(statement.source.value);
76
- if (!name)
104
+ if (!name) {
105
+ if (internal.shadow) {
106
+ extractComponentImport(statement, internal);
107
+ }
77
108
  return;
109
+ }
78
110
  statement.source.value = internal.replaceWeb;
79
111
  internal.prefix = name;
80
112
  for (const specifier of statement.specifiers) {
@@ -177,6 +209,8 @@ function transformProgram(path, filename, opts) {
177
209
  const internal = {
178
210
  stack: new internal_js_1.StackedStates(),
179
211
  mapping: new Map(),
212
+ interfaces: new Map(),
213
+ componentsImports: new Map(),
180
214
  global: "",
181
215
  prefix: "Vasille_",
182
216
  importStatement: null,
@@ -189,6 +223,7 @@ function transformProgram(path, filename, opts) {
189
223
  replaceWeb: opts.replaceWeb ?? (opts.devLayer ? "steel-frame" : "vasille-web"),
190
224
  headTag: opts.headTag,
191
225
  bodyTag: opts.bodyTag,
226
+ shadow: opts.shadow,
192
227
  ref(arg, area, name) {
193
228
  if (opts.devLayer) {
194
229
  return named(call("ref", [arg ? arg : t.buildUndefinedNode(), nodeToStaticPosition(area), getInspector()]), name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "babel-plugin-vasille",
3
- "version": "5.0.4",
3
+ "version": "5.1.0",
4
4
  "description": "Convert Vasille Meta Language code to pure JavaScript",
5
5
  "main": "lib/index.js",
6
6
  "type": "commonjs",