@promptui-lib/codegen 0.1.18 → 0.1.20

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.
@@ -1 +1 @@
1
- {"version":3,"file":"antd.template.d.ts","sourceRoot":"","sources":["../../src/frameworks/antd.template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAkE,MAAM,oBAAoB,CAAC;AAuMxH;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAiChE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAoB9E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAwC7D"}
1
+ {"version":3,"file":"antd.template.d.ts","sourceRoot":"","sources":["../../src/frameworks/antd.template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAA6E,MAAM,oBAAoB,CAAC;AAqNnI;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAiChE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAoB9E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAwC7D"}
@@ -96,6 +96,12 @@ function isComponentNode(child) {
96
96
  function isJSXNode(child) {
97
97
  return 'tag' in child;
98
98
  }
99
+ /**
100
+ * Check if a child is an asset node
101
+ */
102
+ function isAssetNode(child) {
103
+ return 'type' in child && child.type === 'asset';
104
+ }
99
105
  /**
100
106
  * Collect all imports needed for the component
101
107
  */
@@ -162,6 +168,13 @@ function generateJSX(node, indent = 2) {
162
168
  // Render child component as <ComponentName />
163
169
  return `${spaces} <${child.componentName} />`;
164
170
  }
171
+ if (isAssetNode(child)) {
172
+ // Render asset as <img /> with placeholder src
173
+ const classAttrAsset = child.className ? ` className="${child.className}"` : '';
174
+ const widthAttr = child.width ? ` width={${Math.round(child.width)}}` : '';
175
+ const heightAttr = child.height ? ` height={${Math.round(child.height)}}` : '';
176
+ return `${spaces} <img src="${child.fileName}.${child.format}" alt="${child.alt ?? ''}"${widthAttr}${heightAttr}${classAttrAsset} />`;
177
+ }
165
178
  if (isJSXNode(child)) {
166
179
  return generateJSX(child, indent + 2);
167
180
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.template.d.ts","sourceRoot":"","sources":["../../src/frameworks/bootstrap.template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAA4B,MAAM,oBAAoB,CAAC;AA2RlF;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAkDrE"}
1
+ {"version":3,"file":"bootstrap.template.d.ts","sourceRoot":"","sources":["../../src/frameworks/bootstrap.template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAgE,MAAM,oBAAoB,CAAC;AA6TtH;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAkDrE"}
@@ -213,6 +213,30 @@ function generateBootstrapClasses(styles) {
213
213
  }
214
214
  return classes;
215
215
  }
216
+ /**
217
+ * Check if a child is a text node
218
+ */
219
+ function isTextNode(child) {
220
+ return typeof child === 'object' && child !== null && 'type' in child && child.type === 'text';
221
+ }
222
+ /**
223
+ * Check if a child is a component node
224
+ */
225
+ function isComponentNode(child) {
226
+ return typeof child === 'object' && child !== null && 'type' in child && child.type === 'component';
227
+ }
228
+ /**
229
+ * Check if a child is an asset node
230
+ */
231
+ function isAssetNode(child) {
232
+ return typeof child === 'object' && child !== null && 'type' in child && child.type === 'asset';
233
+ }
234
+ /**
235
+ * Check if a child is a JSX node
236
+ */
237
+ function isJSXNode(child) {
238
+ return typeof child === 'object' && child !== null && 'tag' in child;
239
+ }
216
240
  /**
217
241
  * Gera JSX com classes Bootstrap
218
242
  */
@@ -238,11 +262,19 @@ function generateBootstrapJSX(node, styles, indent = 2) {
238
262
  }
239
263
  const childrenContent = [];
240
264
  for (const child of node.children) {
241
- if (typeof child === 'string' || (typeof child === 'object' && 'type' in child && child.type === 'text')) {
242
- const text = typeof child === 'string' ? child : child.value;
243
- childrenContent.push(`${spaces} {children ?? '${text}'}`);
265
+ if (isTextNode(child)) {
266
+ childrenContent.push(`${spaces} {children ?? '${child.value}'}`);
267
+ }
268
+ else if (isComponentNode(child)) {
269
+ childrenContent.push(`${spaces} <${child.componentName} />`);
270
+ }
271
+ else if (isAssetNode(child)) {
272
+ const classAttrAsset = child.className ? ` className="${child.className}"` : '';
273
+ const widthAttr = child.width ? ` width={${Math.round(child.width)}}` : '';
274
+ const heightAttr = child.height ? ` height={${Math.round(child.height)}}` : '';
275
+ childrenContent.push(`${spaces} <img src="${child.fileName}.${child.format}" alt="${child.alt ?? ''}"${widthAttr}${heightAttr}${classAttrAsset} />`);
244
276
  }
245
- else {
277
+ else if (isJSXNode(child)) {
246
278
  childrenContent.push(generateBootstrapJSX(child, styles, indent + 2));
247
279
  }
248
280
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mui.template.d.ts","sourceRoot":"","sources":["../../src/frameworks/mui.template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAA4B,MAAM,oBAAoB,CAAC;AA2RlF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAgE/D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAwB5D"}
1
+ {"version":3,"file":"mui.template.d.ts","sourceRoot":"","sources":["../../src/frameworks/mui.template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAgE,MAAM,oBAAoB,CAAC;AA6TtH;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAgE/D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAwB5D"}
@@ -189,6 +189,30 @@ function getMuiProps(node, componentType) {
189
189
  }
190
190
  return props;
191
191
  }
192
+ /**
193
+ * Check if a child is a text node
194
+ */
195
+ function isTextNode(child) {
196
+ return typeof child === 'object' && child !== null && 'type' in child && child.type === 'text';
197
+ }
198
+ /**
199
+ * Check if a child is a component node
200
+ */
201
+ function isComponentNode(child) {
202
+ return typeof child === 'object' && child !== null && 'type' in child && child.type === 'component';
203
+ }
204
+ /**
205
+ * Check if a child is an asset node
206
+ */
207
+ function isAssetNode(child) {
208
+ return typeof child === 'object' && child !== null && 'type' in child && child.type === 'asset';
209
+ }
210
+ /**
211
+ * Check if a child is a JSX node
212
+ */
213
+ function isJSXNode(child) {
214
+ return typeof child === 'object' && child !== null && 'tag' in child;
215
+ }
192
216
  /**
193
217
  * Gera JSX com componentes MUI
194
218
  */
@@ -215,11 +239,19 @@ function generateMuiJSX(node, styles, indent = 2) {
215
239
  }
216
240
  const childrenContent = [];
217
241
  for (const child of node.children) {
218
- if (typeof child === 'string' || (typeof child === 'object' && 'type' in child && child.type === 'text')) {
219
- const text = typeof child === 'string' ? child : child.value;
220
- childrenContent.push(`${spaces} {children ?? '${text}'}`);
242
+ if (isTextNode(child)) {
243
+ childrenContent.push(`${spaces} {children ?? '${child.value}'}`);
221
244
  }
222
- else {
245
+ else if (isComponentNode(child)) {
246
+ childrenContent.push(`${spaces} <${child.componentName} />`);
247
+ }
248
+ else if (isAssetNode(child)) {
249
+ const classAttrAsset = child.className ? ` className="${child.className}"` : '';
250
+ const widthAttr = child.width ? ` width={${Math.round(child.width)}}` : '';
251
+ const heightAttr = child.height ? ` height={${Math.round(child.height)}}` : '';
252
+ childrenContent.push(`${spaces} <img src="${child.fileName}.${child.format}" alt="${child.alt ?? ''}"${widthAttr}${heightAttr}${classAttrAsset} />`);
253
+ }
254
+ else if (isJSXNode(child)) {
223
255
  childrenContent.push(generateMuiJSX(child, styles, indent + 2));
224
256
  }
225
257
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tailwind.template.d.ts","sourceRoot":"","sources":["../../src/frameworks/tailwind.template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAY,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAuMlF;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE,CAY1E;AAuDD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAsCpE"}
1
+ {"version":3,"file":"tailwind.template.d.ts","sourceRoot":"","sources":["../../src/frameworks/tailwind.template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAY,cAAc,EAAsC,MAAM,oBAAoB,CAAC;AAuMtH;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE,CAY1E;AAyFD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAsCpE"}
@@ -204,6 +204,30 @@ export function generateTailwindClasses(styles) {
204
204
  }
205
205
  return classes;
206
206
  }
207
+ /**
208
+ * Check if a child is a text node
209
+ */
210
+ function isTextNode(child) {
211
+ return typeof child === 'object' && child !== null && 'type' in child && child.type === 'text';
212
+ }
213
+ /**
214
+ * Check if a child is a component node
215
+ */
216
+ function isComponentNode(child) {
217
+ return typeof child === 'object' && child !== null && 'type' in child && child.type === 'component';
218
+ }
219
+ /**
220
+ * Check if a child is an asset node
221
+ */
222
+ function isAssetNode(child) {
223
+ return typeof child === 'object' && child !== null && 'type' in child && child.type === 'asset';
224
+ }
225
+ /**
226
+ * Check if a child is a JSX node
227
+ */
228
+ function isJSXNode(child) {
229
+ return typeof child === 'object' && child !== null && 'tag' in child;
230
+ }
207
231
  /**
208
232
  * Gera JSX com classes Tailwind
209
233
  */
@@ -229,11 +253,19 @@ function generateTailwindJSX(node, styles, indent = 2) {
229
253
  }
230
254
  const childrenContent = [];
231
255
  for (const child of node.children) {
232
- if (typeof child === 'string' || (typeof child === 'object' && 'type' in child && child.type === 'text')) {
233
- const text = typeof child === 'string' ? child : child.value;
234
- childrenContent.push(`${spaces} {children ?? '${text}'}`);
256
+ if (isTextNode(child)) {
257
+ childrenContent.push(`${spaces} {children ?? '${child.value}'}`);
258
+ }
259
+ else if (isComponentNode(child)) {
260
+ childrenContent.push(`${spaces} <${child.componentName} />`);
261
+ }
262
+ else if (isAssetNode(child)) {
263
+ const classAttrAsset = child.className ? ` className="${child.className}"` : '';
264
+ const widthAttr = child.width ? ` width={${Math.round(child.width)}}` : '';
265
+ const heightAttr = child.height ? ` height={${Math.round(child.height)}}` : '';
266
+ childrenContent.push(`${spaces} <img src="${child.fileName}.${child.format}" alt="${child.alt ?? ''}"${widthAttr}${heightAttr}${classAttrAsset} />`);
235
267
  }
236
- else {
268
+ else if (isJSXNode(child)) {
237
269
  childrenContent.push(generateTailwindJSX(child, styles, indent + 2));
238
270
  }
239
271
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tsx-generator.d.ts","sourceRoot":"","sources":["../../src/generators/tsx-generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,aAAa,EAQd,MAAM,oBAAoB,CAAC;AA0O5B;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAmCtD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAUxD"}
1
+ {"version":3,"file":"tsx-generator.d.ts","sourceRoot":"","sources":["../../src/generators/tsx-generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,aAAa,EASd,MAAM,oBAAoB,CAAC;AA4T5B;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAuCtD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAUxD"}
@@ -18,6 +18,71 @@ function collectChildComponents(node) {
18
18
  }
19
19
  return components;
20
20
  }
21
+ /**
22
+ * Coleta todos os assets de uma árvore JSX recursivamente
23
+ */
24
+ function collectAssets(node) {
25
+ const assets = [];
26
+ for (const child of node.children) {
27
+ if ('type' in child && child.type === 'asset') {
28
+ assets.push(child);
29
+ }
30
+ else if ('tag' in child) {
31
+ // Recursivamente busca em nós JSX
32
+ assets.push(...collectAssets(child));
33
+ }
34
+ }
35
+ return assets;
36
+ }
37
+ /**
38
+ * Gera imports de assets (SVGs)
39
+ */
40
+ function generateAssetImports(assets) {
41
+ const imports = [];
42
+ const seen = new Set();
43
+ for (const asset of assets) {
44
+ // Evita duplicatas
45
+ if (seen.has(asset.fileName)) {
46
+ continue;
47
+ }
48
+ seen.add(asset.fileName);
49
+ // Gera nome de variável para o import (PascalCase + Icon)
50
+ const importName = asset.fileName
51
+ .split('-')
52
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
53
+ .join('') + 'Svg';
54
+ imports.push({
55
+ from: `./assets/${asset.fileName}.svg`,
56
+ default: importName,
57
+ });
58
+ }
59
+ return imports;
60
+ }
61
+ /**
62
+ * Gera JSX de um asset (SVG como img)
63
+ */
64
+ function generateAssetJSX(asset, indent) {
65
+ const spaces = ' '.repeat(indent);
66
+ // Gera nome de variável para o import
67
+ const importName = asset.fileName
68
+ .split('-')
69
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
70
+ .join('') + 'Svg';
71
+ let jsx = `${spaces}<img`;
72
+ jsx += ` src={${importName}}`;
73
+ jsx += ` alt="${asset.alt ?? ''}"`;
74
+ if (asset.className) {
75
+ jsx += ` className="${asset.className}"`;
76
+ }
77
+ if (asset.width) {
78
+ jsx += ` width={${Math.round(asset.width)}}`;
79
+ }
80
+ if (asset.height) {
81
+ jsx += ` height={${Math.round(asset.height)}}`;
82
+ }
83
+ jsx += ' />';
84
+ return jsx;
85
+ }
21
86
  /**
22
87
  * Calcula o caminho relativo de import entre duas camadas do Atomic Design
23
88
  */
@@ -188,6 +253,10 @@ function generateJSX(node, indent = 2) {
188
253
  // Renderiza componente filho como <ComponentName />
189
254
  childrenJSX.push(generateComponentJSX(child, indent + 2));
190
255
  }
256
+ else if ('type' in child && child.type === 'asset') {
257
+ // Renderiza asset como <img src={importedSvg} />
258
+ childrenJSX.push(generateAssetJSX(child, indent + 2));
259
+ }
191
260
  else {
192
261
  childrenJSX.push(generateJSX(child, indent + 2));
193
262
  }
@@ -205,8 +274,11 @@ export function generateTSX(ast) {
205
274
  // Coleta componentes filhos para gerar imports
206
275
  const childComponents = collectChildComponents(ast.jsx);
207
276
  const componentImports = generateComponentImports(childComponents, ast.layer);
208
- // Combina imports existentes com imports de componentes
209
- const allImports = [...(ast.imports ?? []), ...componentImports];
277
+ // Coleta assets para gerar imports de SVGs
278
+ const assets = collectAssets(ast.jsx);
279
+ const assetImports = generateAssetImports(assets);
280
+ // Combina imports existentes com imports de componentes e assets
281
+ const allImports = [...(ast.imports ?? []), ...componentImports, ...assetImports];
210
282
  // Imports
211
283
  const importsCode = generateImports(allImports);
212
284
  if (importsCode) {
@@ -11,7 +11,7 @@ export function generateDefaultVariables() {
11
11
  // Run 'promptui sync tokens' to update from Figma
12
12
 
13
13
  // Import fonts (if _fonts.scss exists)
14
- @import 'fonts';
14
+ @use 'fonts';
15
15
 
16
16
  // =============================================================================
17
17
  // COLORS
@@ -57,9 +57,9 @@ async function ensureVariablesFile(basePath) {
57
57
  // Verifica se tem o import de fonts
58
58
  try {
59
59
  const content = await readFile(variablesPath, 'utf-8');
60
- if (!content.includes("@import 'fonts'") && !content.includes('@import "fonts"')) {
60
+ if (!content.includes("@use 'fonts'") && !content.includes('@use "fonts"')) {
61
61
  // Adiciona o import de fonts no início
62
- const updatedContent = content.replace(/(\/\/ PromptUI - Design Tokens.*?\n)/s, "$1\n// Import fonts\n@import 'fonts';\n");
62
+ const updatedContent = content.replace(/(\/\/ PromptUI - Design Tokens.*?\n)/s, "$1\n// Import fonts\n@use 'fonts';\n");
63
63
  if (updatedContent !== content) {
64
64
  await writeFile(variablesPath, updatedContent, 'utf-8');
65
65
  return variablesPath; // Foi atualizado
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptui-lib/codegen",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "private": false,
5
5
  "description": "Code generator for PromptUI - generates React TSX and SCSS",
6
6
  "license": "UNLICENSED",
@@ -30,7 +30,7 @@
30
30
  "dist"
31
31
  ],
32
32
  "dependencies": {
33
- "@promptui-lib/core": "0.1.18"
33
+ "@promptui-lib/core": "0.1.20"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^20.0.0",