@promptui-lib/figma-parser 0.1.17 → 0.1.19

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":"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;AAkND;;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"}
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, depth?: number): string;
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;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,UAAU,CAAC,EAAE,UAAU,EACvB,KAAK,GAAE,MAAU,GAChB,MAAM,CAqKR;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"}
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, depth = 0) {
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
- return depth === 0 ? 'header' : 'header';
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.17",
3
+ "version": "0.1.19",
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.17"
33
+ "@promptui-lib/core": "0.1.19"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^20.0.0",