@base44/vite-plugin 0.2.27 → 0.2.29

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.
Files changed (77) hide show
  1. package/dist/capabilities/inline-edit/controller.d.ts.map +1 -1
  2. package/dist/capabilities/inline-edit/controller.js +9 -3
  3. package/dist/capabilities/inline-edit/controller.js.map +1 -1
  4. package/dist/capabilities/inline-edit/dom-utils.d.ts +1 -0
  5. package/dist/capabilities/inline-edit/dom-utils.d.ts.map +1 -1
  6. package/dist/capabilities/inline-edit/dom-utils.js +17 -7
  7. package/dist/capabilities/inline-edit/dom-utils.js.map +1 -1
  8. package/dist/capabilities/inline-edit/index.d.ts +1 -1
  9. package/dist/capabilities/inline-edit/index.d.ts.map +1 -1
  10. package/dist/capabilities/inline-edit/types.d.ts +4 -0
  11. package/dist/capabilities/inline-edit/types.d.ts.map +1 -1
  12. package/dist/consts.d.ts +11 -0
  13. package/dist/consts.d.ts.map +1 -0
  14. package/dist/consts.js +11 -0
  15. package/dist/consts.js.map +1 -0
  16. package/dist/injections/visual-edit-agent.d.ts.map +1 -1
  17. package/dist/injections/visual-edit-agent.js +26 -4
  18. package/dist/injections/visual-edit-agent.js.map +1 -1
  19. package/dist/jsx-processor.d.ts +3 -1
  20. package/dist/jsx-processor.d.ts.map +1 -1
  21. package/dist/jsx-processor.js +29 -6
  22. package/dist/jsx-processor.js.map +1 -1
  23. package/dist/jsx-utils.d.ts +9 -0
  24. package/dist/jsx-utils.d.ts.map +1 -1
  25. package/dist/jsx-utils.js +86 -0
  26. package/dist/jsx-utils.js.map +1 -1
  27. package/dist/processors/collection-id-processor.d.ts +20 -0
  28. package/dist/processors/collection-id-processor.d.ts.map +1 -0
  29. package/dist/processors/collection-id-processor.js +182 -0
  30. package/dist/processors/collection-id-processor.js.map +1 -0
  31. package/dist/processors/collection-item-field-processor.d.ts +39 -0
  32. package/dist/processors/collection-item-field-processor.d.ts.map +1 -0
  33. package/dist/processors/collection-item-field-processor.js +281 -0
  34. package/dist/processors/collection-item-field-processor.js.map +1 -0
  35. package/dist/processors/collection-item-id-processor.d.ts +12 -0
  36. package/dist/processors/collection-item-id-processor.d.ts.map +1 -0
  37. package/dist/processors/collection-item-id-processor.js +50 -0
  38. package/dist/processors/collection-item-id-processor.js.map +1 -0
  39. package/dist/processors/static-array-processor.d.ts +0 -3
  40. package/dist/processors/static-array-processor.d.ts.map +1 -1
  41. package/dist/processors/static-array-processor.js +2 -4
  42. package/dist/processors/static-array-processor.js.map +1 -1
  43. package/dist/processors/utils/collection-tracing-utils.d.ts +36 -0
  44. package/dist/processors/utils/collection-tracing-utils.d.ts.map +1 -0
  45. package/dist/processors/utils/collection-tracing-utils.js +390 -0
  46. package/dist/processors/utils/collection-tracing-utils.js.map +1 -0
  47. package/dist/processors/utils/shared-utils.d.ts +96 -0
  48. package/dist/processors/utils/shared-utils.d.ts.map +1 -0
  49. package/dist/processors/utils/shared-utils.js +600 -0
  50. package/dist/processors/utils/shared-utils.js.map +1 -0
  51. package/dist/statics/index.mjs +2 -2
  52. package/dist/statics/index.mjs.map +1 -1
  53. package/dist/visual-edit-plugin.d.ts +0 -1
  54. package/dist/visual-edit-plugin.d.ts.map +1 -1
  55. package/dist/visual-edit-plugin.js +29 -178
  56. package/dist/visual-edit-plugin.js.map +1 -1
  57. package/package.json +1 -1
  58. package/src/capabilities/inline-edit/controller.ts +35 -29
  59. package/src/capabilities/inline-edit/dom-utils.ts +14 -4
  60. package/src/capabilities/inline-edit/index.ts +1 -1
  61. package/src/capabilities/inline-edit/types.ts +5 -0
  62. package/src/consts.ts +11 -0
  63. package/src/injections/visual-edit-agent.ts +33 -4
  64. package/src/jsx-processor.ts +36 -14
  65. package/src/jsx-utils.ts +116 -0
  66. package/src/processors/collection-id-processor.ts +261 -0
  67. package/src/processors/collection-item-field-processor.ts +433 -0
  68. package/src/processors/collection-item-id-processor.ts +69 -0
  69. package/src/processors/static-array-processor.ts +7 -4
  70. package/src/processors/utils/collection-tracing-utils.ts +507 -0
  71. package/src/processors/utils/shared-utils.ts +785 -0
  72. package/src/visual-edit-plugin.ts +34 -215
  73. package/dist/processors/shared-utils.d.ts +0 -19
  74. package/dist/processors/shared-utils.d.ts.map +0 -1
  75. package/dist/processors/shared-utils.js +0 -77
  76. package/dist/processors/shared-utils.js.map +0 -1
  77. package/src/processors/shared-utils.ts +0 -116
@@ -3,196 +3,31 @@ import { default as traverse } from "@babel/traverse";
3
3
  import { default as generate } from "@babel/generator";
4
4
  import * as t from "@babel/types";
5
5
  import type { Plugin } from "vite";
6
- import { StaticArrayProcessor } from "./processors/static-array-processor.js";
6
+ import { JSXProcessor } from "./jsx-processor.js";
7
7
  import { JSXUtils } from "./jsx-utils.js";
8
8
 
9
- // Helper function to check if JSX element contains dynamic content
10
- export function checkIfElementHasDynamicContent(jsxElement: any) {
11
- let hasDynamicContent = false;
12
-
13
- // Helper function to check if any node contains dynamic patterns
14
- function checkNodeForDynamicContent(node: any) {
15
- // JSX expressions like {variable}, {func()}, {obj.prop}
16
- if (t.isJSXExpressionContainer(node)) {
17
- const expression = node.expression;
18
-
19
- // Skip empty expressions {}
20
- if (t.isJSXEmptyExpression(expression)) {
21
- return false;
22
- }
23
-
24
- // Any non-literal expression is considered dynamic
25
- if (!t.isLiteral(expression)) {
26
- return true;
27
- }
28
- }
29
-
30
- // Template literals with expressions `Hello ${name}`
31
- if (t.isTemplateLiteral(node) && node.expressions.length > 0) {
32
- return true;
33
- }
34
-
35
- // Member expressions like props.title, state.value
36
- if (t.isMemberExpression(node)) {
37
- return true;
38
- }
39
-
40
- // Function calls like getData(), format()
41
- if (t.isCallExpression(node)) {
42
- return true;
43
- }
44
-
45
- // Conditional expressions like condition ? "yes" : "no"
46
- if (t.isConditionalExpression(node)) {
47
- return true;
48
- }
49
-
50
- // Identifier references (could be props, state, variables)
51
- if (t.isIdentifier(node)) {
52
- // Common dynamic identifiers
53
- const dynamicNames = [
54
- "props",
55
- "state",
56
- "data",
57
- "item",
58
- "value",
59
- "text",
60
- "content",
61
- ];
62
- if (dynamicNames.some((name) => node.name.includes(name))) {
63
- return true;
64
- }
65
- }
66
-
67
- return false;
68
- }
69
-
70
- // Recursively traverse all child nodes
71
- function traverseNode(node: any) {
72
- if (checkNodeForDynamicContent(node)) {
73
- hasDynamicContent = true;
74
- return;
75
- }
76
-
77
- // Recursively check child nodes
78
- Object.keys(node).forEach((key) => {
79
- const value = node[key];
80
-
81
- if (Array.isArray(value)) {
82
- value.forEach((child) => {
83
- if (child && typeof child === "object" && child.type) {
84
- traverseNode(child);
85
- }
86
- });
87
- } else if (value && typeof value === "object" && value.type) {
88
- traverseNode(value);
89
- }
90
- });
91
- }
92
-
93
- // Check the element's own attributes for dynamic content
94
- const attributes = jsxElement.openingElement?.attributes || [];
95
- attributes.forEach((attr: any) => {
96
- if (hasDynamicContent) return; // Early exit if already found dynamic content
97
-
98
- // Spread attributes like {...props} are always dynamic
99
- if (t.isJSXSpreadAttribute(attr)) {
100
- hasDynamicContent = true;
101
- return;
102
- }
103
-
104
- // Check attribute values for dynamic expressions
105
- if (t.isJSXAttribute(attr) && attr.value) {
106
- traverseNode(attr.value);
107
- }
108
- });
109
-
110
- // Check all children of the JSX element
111
- jsxElement.children.forEach((child: any) => {
112
- if (hasDynamicContent) return; // Early exit if already found dynamic content
113
- traverseNode(child);
114
- });
115
-
116
- return hasDynamicContent;
117
- }
118
-
119
9
  export function visualEditPlugin() {
120
10
  return {
121
11
  name: "visual-edit-transform",
122
12
  apply: (config) => config.mode === "development",
123
13
  enforce: "pre",
124
14
  order: "pre",
125
- // Inject Tailwind CDN for visual editing capabilities
126
15
  transformIndexHtml(html: any) {
127
- // Inject the Tailwind CSS CDN script right before the closing </head> tag
128
16
  const tailwindScript = ` <!-- Tailwind CSS CDN for visual editing -->\n <script src="https://cdn.tailwindcss.com"></script>\n `;
129
17
  return html.replace("</head>", tailwindScript + "</head>");
130
18
  },
131
19
  transform(code: any, id: any) {
132
- // Skip node_modules and visual-edit-agent itself
133
20
  if (id.includes("node_modules") || id.includes("visual-edit-agent")) {
134
21
  return null;
135
22
  }
136
23
 
137
- // Process JS/JSX/TS/TSX files
138
24
  if (!id.match(/\.(jsx?|tsx?)$/)) {
139
25
  return null;
140
26
  }
141
27
 
142
- // Extract filename from path, preserving pages/ or components/ structure
143
- const pathParts = id.split("/");
144
- let filename;
145
-
146
- // Check if this is a pages or components file
147
- if (id.includes("/pages/")) {
148
- const pagesIndex = pathParts.findIndex((part: any) => part === "pages");
149
- if (pagesIndex >= 0 && pagesIndex < pathParts.length - 1) {
150
- // Get all parts from 'pages' to the file, preserving nested structure
151
- const relevantParts = pathParts.slice(pagesIndex, pathParts.length);
152
- const lastPart = relevantParts[relevantParts.length - 1];
153
- // Remove file extension from the last part
154
- relevantParts[relevantParts.length - 1] = lastPart.includes(".")
155
- ? lastPart.split(".")[0]
156
- : lastPart;
157
- filename = relevantParts.join("/");
158
- } else {
159
- filename = pathParts[pathParts.length - 1];
160
- if (filename.includes(".")) {
161
- filename = filename.split(".")[0];
162
- }
163
- }
164
- } else if (id.includes("/components/")) {
165
- const componentsIndex = pathParts.findIndex(
166
- (part: any) => part === "components"
167
- );
168
- if (componentsIndex >= 0 && componentsIndex < pathParts.length - 1) {
169
- // Get all parts from 'components' to the file, preserving nested structure
170
- const relevantParts = pathParts.slice(
171
- componentsIndex,
172
- pathParts.length
173
- );
174
- const lastPart = relevantParts[relevantParts.length - 1];
175
- // Remove file extension from the last part
176
- relevantParts[relevantParts.length - 1] = lastPart.includes(".")
177
- ? lastPart.split(".")[0]
178
- : lastPart;
179
- filename = relevantParts.join("/");
180
- } else {
181
- filename = pathParts[pathParts.length - 1];
182
- if (filename.includes(".")) {
183
- filename = filename.split(".")[0];
184
- }
185
- }
186
- } else {
187
- // For other files (like layout), just use the filename
188
- filename = pathParts[pathParts.length - 1];
189
- if (filename.includes(".")) {
190
- filename = filename.split(".")[0];
191
- }
192
- }
28
+ const filename = extractFilename(id);
193
29
 
194
30
  try {
195
- // Parse the code into an AST
196
31
  const ast = parse(code, {
197
32
  sourceType: "module",
198
33
  plugins: [
@@ -214,61 +49,17 @@ export function visualEditPlugin() {
214
49
  ],
215
50
  });
216
51
 
217
- // Traverse the AST and add source location and dynamic content attributes to JSX elements
218
52
  JSXUtils.init(t);
219
- const staticArrayProcessor = new StaticArrayProcessor(t);
220
- let elementsProcessed = 0;
53
+ const processor = new JSXProcessor(t, filename);
54
+
221
55
  traverse.default(ast, {
222
56
  JSXElement(path) {
223
57
  const jsxElement = path.node;
224
- const openingElement = jsxElement.openingElement;
225
-
226
- // Skip fragments
227
58
  if (t.isJSXFragment(jsxElement)) return;
228
-
229
- // Skip if already has source location attribute
230
- const hasSourceLocation = openingElement.attributes.some(
231
- (attr) =>
232
- t.isJSXAttribute(attr) &&
233
- t.isJSXIdentifier(attr.name) &&
234
- attr.name.name === "data-source-location"
235
- );
236
-
237
- if (hasSourceLocation) return;
238
-
239
- // Get line and column from AST node location
240
- const { line, column } = openingElement.loc?.start || {
241
- line: 1,
242
- column: 0,
243
- };
244
-
245
- // Create the source location attribute
246
- const sourceLocationAttr = t.jsxAttribute(
247
- t.jsxIdentifier("data-source-location"),
248
- t.stringLiteral(`${filename}:${line}:${column}`)
249
- );
250
-
251
- // Check if element has dynamic content
252
- const isDynamic = checkIfElementHasDynamicContent(jsxElement);
253
-
254
- // Create the dynamic content attribute
255
- const dynamicContentAttr = t.jsxAttribute(
256
- t.jsxIdentifier("data-dynamic-content"),
257
- t.stringLiteral(isDynamic ? "true" : "false")
258
- );
259
-
260
- // Add both attributes to the beginning of the attributes array
261
- openingElement.attributes.unshift(
262
- sourceLocationAttr,
263
- dynamicContentAttr
264
- );
265
-
266
- staticArrayProcessor.process(path.get("openingElement"));
267
- elementsProcessed++;
59
+ processor.processJSXElement(path.get("openingElement"));
268
60
  },
269
61
  });
270
62
 
271
- // Generate the code back from the AST
272
63
  const result = generate.default(ast, {
273
64
  compact: false,
274
65
  concise: false,
@@ -282,10 +73,38 @@ export function visualEditPlugin() {
282
73
  } catch (error) {
283
74
  console.error("Failed to add source location to JSX:", error);
284
75
  return {
285
- code: code, // Return original code on failure
76
+ code: code,
286
77
  map: null,
287
78
  };
288
79
  }
289
80
  },
290
81
  } as Plugin;
291
82
  }
83
+
84
+ function extractFilename(id: string): string {
85
+ const pathParts = id.split("/");
86
+
87
+ const segmentIndex = findSegmentIndex(pathParts, ["pages", "components"]);
88
+ if (segmentIndex >= 0 && segmentIndex < pathParts.length - 1) {
89
+ const relevantParts = pathParts.slice(segmentIndex);
90
+ const last = relevantParts[relevantParts.length - 1];
91
+ relevantParts[relevantParts.length - 1] = stripExtension(last ?? "");
92
+ return relevantParts.join("/");
93
+ }
94
+
95
+ const lastPart = pathParts[pathParts.length - 1] ?? "";
96
+ return stripExtension(lastPart);
97
+ }
98
+
99
+ function findSegmentIndex(parts: string[], segments: string[]): number {
100
+ for (const segment of segments) {
101
+ const idx = parts.findIndex((part) => part === segment);
102
+ if (idx >= 0) return idx;
103
+ }
104
+ return -1;
105
+ }
106
+
107
+ function stripExtension(filename: string): string {
108
+ const dotIndex = filename.indexOf(".");
109
+ return dotIndex >= 0 ? filename.substring(0, dotIndex) : filename;
110
+ }
@@ -1,19 +0,0 @@
1
- import type { NodePath } from "@babel/traverse";
2
- import type * as t from "@babel/types";
3
- export declare class JSXAttributeUtils {
4
- private types;
5
- constructor(types: typeof t);
6
- hasAttribute(path: NodePath<t.JSXOpeningElement>, attributeName: string): boolean;
7
- addStringAttribute(path: NodePath<t.JSXOpeningElement>, attributeName: string, value: string): void;
8
- addExpressionAttribute(path: NodePath<t.JSXOpeningElement>, attributeName: string, expression: t.Expression): void;
9
- }
10
- export declare class StaticValueUtils {
11
- private types;
12
- constructor(types: typeof t);
13
- isPrimitiveLiteral(path: NodePath<t.Node>): boolean;
14
- isStaticValue(path: NodePath<t.Node>, visited?: Set<string>): boolean;
15
- isStaticIdentifier(path: NodePath<t.Identifier>, visited?: Set<string>): boolean;
16
- isStaticObject(path: NodePath<t.ObjectExpression>, visited?: Set<string>): boolean;
17
- isStaticArrayExpression(arrayExpression: NodePath<t.ArrayExpression>, visited?: Set<string>): boolean;
18
- }
19
- //# sourceMappingURL=shared-utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shared-utils.d.ts","sourceRoot":"","sources":["../../src/processors/shared-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,KAAK,CAAC,MAAM,cAAc,CAAC;AAGvC,qBAAa,iBAAiB;IAChB,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,OAAO,CAAC;IAEnC,YAAY,CACV,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,EACnC,aAAa,EAAE,MAAM,GACpB,OAAO;IAQV,kBAAkB,CAChB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,EACnC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,GACZ,IAAI;IAWP,sBAAsB,CACpB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,EACnC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,CAAC,CAAC,UAAU,GACvB,IAAI;CAUR;AAED,qBAAa,gBAAgB;IACf,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,OAAO,CAAC;IAEnC,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO;IASnD,aAAa,CACX,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EACtB,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAC/B,OAAO;IASV,kBAAkB,CAChB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,EAC5B,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAC/B,OAAO;IAoBV,cAAc,CACZ,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAClC,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAC/B,OAAO;IAOV,uBAAuB,CACrB,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,EAC5C,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAC/B,OAAO;CAMX"}
@@ -1,77 +0,0 @@
1
- import { JSXUtils } from "../jsx-utils.js";
2
- export class JSXAttributeUtils {
3
- types;
4
- constructor(types) {
5
- this.types = types;
6
- }
7
- hasAttribute(path, attributeName) {
8
- return path.node.attributes.some((attr) => this.types.isJSXAttribute(attr) &&
9
- JSXUtils.getAttributeName(attr) === attributeName);
10
- }
11
- addStringAttribute(path, attributeName, value) {
12
- if (!this.hasAttribute(path, attributeName)) {
13
- path.node.attributes.push(this.types.jsxAttribute(this.types.jsxIdentifier(attributeName), this.types.stringLiteral(value)));
14
- }
15
- }
16
- addExpressionAttribute(path, attributeName, expression) {
17
- if (!this.hasAttribute(path, attributeName)) {
18
- path.node.attributes.push(this.types.jsxAttribute(this.types.jsxIdentifier(attributeName), this.types.jsxExpressionContainer(expression)));
19
- }
20
- }
21
- }
22
- export class StaticValueUtils {
23
- types;
24
- constructor(types) {
25
- this.types = types;
26
- }
27
- isPrimitiveLiteral(path) {
28
- return (path.isStringLiteral() ||
29
- path.isNumericLiteral() ||
30
- path.isBooleanLiteral() ||
31
- path.isNullLiteral());
32
- }
33
- isStaticValue(path, visited = new Set()) {
34
- if (this.isPrimitiveLiteral(path))
35
- return true;
36
- if (path.isIdentifier())
37
- return this.isStaticIdentifier(path, visited);
38
- if (path.isObjectExpression())
39
- return this.isStaticObject(path, visited);
40
- if (path.isArrayExpression())
41
- return this.isStaticArrayExpression(path, visited);
42
- return false;
43
- }
44
- isStaticIdentifier(path, visited = new Set()) {
45
- const binding = path.scope.getBinding(path.node.name);
46
- if (!binding)
47
- return false;
48
- if (binding.kind === "module")
49
- return true;
50
- if (binding.kind === "const" && binding.path.isVariableDeclarator()) {
51
- const name = path.node.name;
52
- if (visited.has(name))
53
- return false;
54
- visited.add(name);
55
- const init = binding.path.get("init");
56
- if (init.hasNode()) {
57
- return this.isStaticValue(init, visited);
58
- }
59
- }
60
- return false;
61
- }
62
- isStaticObject(path, visited = new Set()) {
63
- return path.get("properties").every((prop) => {
64
- if (!prop.isObjectProperty())
65
- return false;
66
- return this.isStaticValue(prop.get("value"), visited);
67
- });
68
- }
69
- isStaticArrayExpression(arrayExpression, visited = new Set()) {
70
- return arrayExpression.get("elements").every((element) => {
71
- if (!element.node || element.isSpreadElement())
72
- return true;
73
- return this.isStaticValue(element, visited);
74
- });
75
- }
76
- }
77
- //# sourceMappingURL=shared-utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shared-utils.js","sourceRoot":"","sources":["../../src/processors/shared-utils.ts"],"names":[],"mappings":"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"}
@@ -1,116 +0,0 @@
1
- import type { NodePath } from "@babel/traverse";
2
- import type * as t from "@babel/types";
3
- import { JSXUtils } from "../jsx-utils.js";
4
-
5
- export class JSXAttributeUtils {
6
- constructor(private types: typeof t) {}
7
-
8
- hasAttribute(
9
- path: NodePath<t.JSXOpeningElement>,
10
- attributeName: string
11
- ): boolean {
12
- return path.node.attributes.some(
13
- (attr: t.JSXAttribute | t.JSXSpreadAttribute) =>
14
- this.types.isJSXAttribute(attr) &&
15
- JSXUtils.getAttributeName(attr) === attributeName
16
- );
17
- }
18
-
19
- addStringAttribute(
20
- path: NodePath<t.JSXOpeningElement>,
21
- attributeName: string,
22
- value: string
23
- ): void {
24
- if (!this.hasAttribute(path, attributeName)) {
25
- path.node.attributes.push(
26
- this.types.jsxAttribute(
27
- this.types.jsxIdentifier(attributeName),
28
- this.types.stringLiteral(value)
29
- )
30
- );
31
- }
32
- }
33
-
34
- addExpressionAttribute(
35
- path: NodePath<t.JSXOpeningElement>,
36
- attributeName: string,
37
- expression: t.Expression
38
- ): void {
39
- if (!this.hasAttribute(path, attributeName)) {
40
- path.node.attributes.push(
41
- this.types.jsxAttribute(
42
- this.types.jsxIdentifier(attributeName),
43
- this.types.jsxExpressionContainer(expression)
44
- )
45
- );
46
- }
47
- }
48
- }
49
-
50
- export class StaticValueUtils {
51
- constructor(private types: typeof t) {}
52
-
53
- isPrimitiveLiteral(path: NodePath<t.Node>): boolean {
54
- return (
55
- path.isStringLiteral() ||
56
- path.isNumericLiteral() ||
57
- path.isBooleanLiteral() ||
58
- path.isNullLiteral()
59
- );
60
- }
61
-
62
- isStaticValue(
63
- path: NodePath<t.Node>,
64
- visited: Set<string> = new Set()
65
- ): boolean {
66
- if (this.isPrimitiveLiteral(path)) return true;
67
- if (path.isIdentifier()) return this.isStaticIdentifier(path, visited);
68
- if (path.isObjectExpression()) return this.isStaticObject(path, visited);
69
- if (path.isArrayExpression())
70
- return this.isStaticArrayExpression(path, visited);
71
- return false;
72
- }
73
-
74
- isStaticIdentifier(
75
- path: NodePath<t.Identifier>,
76
- visited: Set<string> = new Set()
77
- ): boolean {
78
- const binding = path.scope.getBinding(path.node.name);
79
- if (!binding) return false;
80
-
81
- if (binding.kind === "module") return true;
82
-
83
- if (binding.kind === "const" && binding.path.isVariableDeclarator()) {
84
- const name = path.node.name;
85
- if (visited.has(name)) return false;
86
- visited.add(name);
87
-
88
- const init = binding.path.get("init");
89
- if (init.hasNode()) {
90
- return this.isStaticValue(init as NodePath<t.Node>, visited);
91
- }
92
- }
93
-
94
- return false;
95
- }
96
-
97
- isStaticObject(
98
- path: NodePath<t.ObjectExpression>,
99
- visited: Set<string> = new Set()
100
- ): boolean {
101
- return path.get("properties").every((prop: NodePath) => {
102
- if (!prop.isObjectProperty()) return false;
103
- return this.isStaticValue(prop.get("value") as NodePath<t.Node>, visited);
104
- });
105
- }
106
-
107
- isStaticArrayExpression(
108
- arrayExpression: NodePath<t.ArrayExpression>,
109
- visited: Set<string> = new Set()
110
- ): boolean {
111
- return arrayExpression.get("elements").every((element) => {
112
- if (!element.node || element.isSpreadElement()) return true;
113
- return this.isStaticValue(element as unknown as NodePath<t.Node>, visited);
114
- });
115
- }
116
- }