@promptui-lib/figma-parser 0.1.16 → 0.1.18
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
|
@@ -180,6 +180,37 @@ export FIGMA_FILE_ID=ABC123xyz
|
|
|
180
180
|
**File ID:**
|
|
181
181
|
Da URL do Figma: `https://www.figma.com/file/ABC123xyz/MeuProjeto` → `ABC123xyz`
|
|
182
182
|
|
|
183
|
+
### Entendendo o fileId vs node-id
|
|
184
|
+
|
|
185
|
+
> ⚠️ **Importante**: O `fileId` é do **arquivo Figma inteiro**, não de uma tela específica!
|
|
186
|
+
|
|
187
|
+
Na URL do Figma:
|
|
188
|
+
```
|
|
189
|
+
https://www.figma.com/design/5gCjy5F30XJySmOPpgDKLM/Tela-de-Login?node-id=13-2&m=dev
|
|
190
|
+
└──────────────────────┘ └──────┘
|
|
191
|
+
fileId node-id (NÃO usar)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
| Conceito | O que é | Precisa na config? |
|
|
195
|
+
|----------|---------|-------------------|
|
|
196
|
+
| `fileId` | Identifica o **arquivo Figma inteiro** | ✅ Sim |
|
|
197
|
+
| `node-id` | Identifica um frame específico | ❌ Não |
|
|
198
|
+
|
|
199
|
+
**Regra:**
|
|
200
|
+
- **Mesmo arquivo Figma, telas diferentes** → Use o **mesmo fileId**
|
|
201
|
+
- **Arquivo Figma diferente** → Precisa de um **novo fileId**
|
|
202
|
+
|
|
203
|
+
**Exemplo:**
|
|
204
|
+
```
|
|
205
|
+
📁 Meu Projeto (fileId: ABC123xyz)
|
|
206
|
+
├── #LoginScreen ← mesmo fileId
|
|
207
|
+
├── #HomeScreen ← mesmo fileId
|
|
208
|
+
├── #ProfileScreen ← mesmo fileId
|
|
209
|
+
└── #SettingsScreen ← mesmo fileId
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
O CLI busca automaticamente **todos os frames** que começam com `#` dentro do arquivo.
|
|
213
|
+
|
|
183
214
|
---
|
|
184
215
|
|
|
185
216
|
## Guia para Designers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-parser.d.ts","sourceRoot":"","sources":["../../src/parser/node-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EAMb,cAAc,EACd,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAiB5B,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAwB7D;
|
|
1
|
+
{"version":3,"file":"node-parser.d.ts","sourceRoot":"","sources":["../../src/parser/node-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EAMb,cAAc,EACd,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAiB5B,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAwB7D;AAuND;;GAEG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,aAAkB,GAC1B,aAAa,CA6Cf;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE,aAAkB,GAC1B,aAAa,EAAE,CAEjB"}
|
|
@@ -35,17 +35,20 @@ export function parseFrameName(name) {
|
|
|
35
35
|
/**
|
|
36
36
|
* Converte um node em elemento JSX
|
|
37
37
|
* Se o filho for um componente (marcado com #), retorna IJSXComponent em vez de JSX inline
|
|
38
|
+
* @param usedTags - Set para rastrear tags únicas já usadas (ex: <main>)
|
|
38
39
|
*/
|
|
39
|
-
function nodeToJSX(node, blockName, depth = 0, parentNode) {
|
|
40
|
+
function nodeToJSX(node, blockName, depth = 0, parentNode, usedTags) {
|
|
40
41
|
const isRoot = depth === 0;
|
|
42
|
+
// Inicializa usedTags no root para rastrear tags únicas na hierarquia
|
|
43
|
+
const tagsSet = usedTags ?? new Set();
|
|
41
44
|
// Normaliza o nome (traduz PT->EN)
|
|
42
45
|
const normalizedName = normalizeName(node.name);
|
|
43
46
|
const elementName = isRoot ? '' : normalizedName.replace(/\s+/g, '-');
|
|
44
47
|
const className = isRoot
|
|
45
48
|
? blockName
|
|
46
49
|
: generateBEMElement(blockName, elementName);
|
|
47
|
-
// Detecta a tag HTML semântica apropriada
|
|
48
|
-
const tag = detectSemanticTag(node, parentNode, depth);
|
|
50
|
+
// Detecta a tag HTML semântica apropriada (passa usedTags para evitar duplicação de <main>)
|
|
51
|
+
const tag = detectSemanticTag(node, parentNode, depth, tagsSet);
|
|
49
52
|
// Obtém atributos semânticos (href, type, etc.)
|
|
50
53
|
const semanticAttrs = getSemanticAttributes(node, tag, normalizedName);
|
|
51
54
|
// Processa filhos
|
|
@@ -72,7 +75,7 @@ function nodeToJSX(node, blockName, depth = 0, parentNode) {
|
|
|
72
75
|
});
|
|
73
76
|
}
|
|
74
77
|
else {
|
|
75
|
-
children.push(nodeToJSX(child, blockName, depth + 1, node));
|
|
78
|
+
children.push(nodeToJSX(child, blockName, depth + 1, node, tagsSet));
|
|
76
79
|
}
|
|
77
80
|
}
|
|
78
81
|
}
|
|
@@ -10,8 +10,9 @@ import type { IFigmaNode } from '@promptui-lib/core';
|
|
|
10
10
|
export declare function normalizeName(name: string): string;
|
|
11
11
|
/**
|
|
12
12
|
* Detecta a tag HTML semântica apropriada
|
|
13
|
+
* @param usedTags - Set de tags já usadas na hierarquia (para evitar duplicação de <main>)
|
|
13
14
|
*/
|
|
14
|
-
export declare function detectSemanticTag(node: IFigmaNode, parentNode?: IFigmaNode,
|
|
15
|
+
export declare function detectSemanticTag(node: IFigmaNode, parentNode?: IFigmaNode, _depth?: number, usedTags?: Set<string>): string;
|
|
15
16
|
/**
|
|
16
17
|
* Gera atributos adicionais baseado no contexto
|
|
17
18
|
* Segue boas práticas de SEO e acessibilidade
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semantic-detector.d.ts","sourceRoot":"","sources":["../../src/parser/semantic-detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAmQrD;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAalD;AAED
|
|
1
|
+
{"version":3,"file":"semantic-detector.d.ts","sourceRoot":"","sources":["../../src/parser/semantic-detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAmQrD;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAalD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,UAAU,CAAC,EAAE,UAAU,EACvB,MAAM,GAAE,MAAU,EAClB,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACrB,MAAM,CAoLR;AA+ID;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,MAAM,GACrB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgLxB"}
|
|
@@ -251,8 +251,9 @@ export function normalizeName(name) {
|
|
|
251
251
|
}
|
|
252
252
|
/**
|
|
253
253
|
* Detecta a tag HTML semântica apropriada
|
|
254
|
+
* @param usedTags - Set de tags já usadas na hierarquia (para evitar duplicação de <main>)
|
|
254
255
|
*/
|
|
255
|
-
export function detectSemanticTag(node, parentNode,
|
|
256
|
+
export function detectSemanticTag(node, parentNode, _depth = 0, usedTags) {
|
|
256
257
|
const name = node.name.toLowerCase();
|
|
257
258
|
const normalizedName = normalizeName(name);
|
|
258
259
|
// Texto sempre usa tag apropriada baseada no contexto
|
|
@@ -296,14 +297,29 @@ export function detectSemanticTag(node, parentNode, depth = 0) {
|
|
|
296
297
|
if (SEMANTIC_PATTERNS.nav.test(normalizedName)) {
|
|
297
298
|
return 'nav';
|
|
298
299
|
}
|
|
299
|
-
// Seções estruturais
|
|
300
|
+
// Seções estruturais (tags que só devem aparecer uma vez por página)
|
|
300
301
|
if (SEMANTIC_PATTERNS.header.test(normalizedName)) {
|
|
301
|
-
|
|
302
|
+
// Evita duplicação de <header> no nível de página
|
|
303
|
+
if (usedTags?.has('header')) {
|
|
304
|
+
return 'div'; // Fallback para div se header já existe
|
|
305
|
+
}
|
|
306
|
+
usedTags?.add('header');
|
|
307
|
+
return 'header';
|
|
302
308
|
}
|
|
303
309
|
if (SEMANTIC_PATTERNS.footer.test(normalizedName)) {
|
|
310
|
+
// Evita duplicação de <footer> no nível de página
|
|
311
|
+
if (usedTags?.has('footer')) {
|
|
312
|
+
return 'div'; // Fallback para div se footer já existe
|
|
313
|
+
}
|
|
314
|
+
usedTags?.add('footer');
|
|
304
315
|
return 'footer';
|
|
305
316
|
}
|
|
306
317
|
if (SEMANTIC_PATTERNS.main.test(normalizedName)) {
|
|
318
|
+
// Evita duplicação de <main> - só pode ter um por página
|
|
319
|
+
if (usedTags?.has('main')) {
|
|
320
|
+
return 'section'; // Fallback para section se main já existe
|
|
321
|
+
}
|
|
322
|
+
usedTags?.add('main');
|
|
307
323
|
return 'main';
|
|
308
324
|
}
|
|
309
325
|
if (SEMANTIC_PATTERNS.section.test(normalizedName)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promptui-lib/figma-parser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Figma API client and parser for PromptUI",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@promptui-lib/core": "0.1.
|
|
33
|
+
"@promptui-lib/core": "0.1.18"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^20.0.0",
|