@promptui-lib/figma-parser 0.1.22 → 0.1.23
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/dist/parser/layout-parser.d.ts +5 -2
- package/dist/parser/layout-parser.d.ts.map +1 -1
- package/dist/parser/layout-parser.js +17 -3
- package/dist/parser/node-parser.d.ts.map +1 -1
- package/dist/parser/node-parser.js +36 -55
- package/dist/parser/position-parser.d.ts.map +1 -1
- package/dist/parser/position-parser.js +9 -1
- package/dist/parser/semantic-detector.d.ts.map +1 -1
- package/dist/parser/semantic-detector.js +14 -8
- package/package.json +2 -2
|
@@ -14,6 +14,7 @@ export interface ILayoutProperties {
|
|
|
14
14
|
height?: IStyleProperty;
|
|
15
15
|
flex?: IStyleProperty;
|
|
16
16
|
flexWrap?: IStyleProperty;
|
|
17
|
+
flexShrink?: IStyleProperty;
|
|
17
18
|
}
|
|
18
19
|
/**
|
|
19
20
|
* Parseia padding de um node (funciona com ou sem Auto Layout)
|
|
@@ -26,11 +27,13 @@ export declare function parseLayout(node: IFigmaNode): ILayoutProperties;
|
|
|
26
27
|
/**
|
|
27
28
|
* Parseia sizing de um node
|
|
28
29
|
* @param isRoot - indica se é o node raiz do componente
|
|
30
|
+
* @param parentHasAutoLayout - indica se o pai tem Auto Layout (para aplicar flex-shrink)
|
|
29
31
|
*/
|
|
30
|
-
export declare function parseSizing(node: IFigmaNode, isRoot?: boolean): ILayoutProperties;
|
|
32
|
+
export declare function parseSizing(node: IFigmaNode, isRoot?: boolean, parentHasAutoLayout?: boolean): ILayoutProperties;
|
|
31
33
|
/**
|
|
32
34
|
* Combina layout e sizing
|
|
33
35
|
* @param isRoot - indica se é o node raiz do componente
|
|
36
|
+
* @param parentHasAutoLayout - indica se o pai tem Auto Layout
|
|
34
37
|
*/
|
|
35
|
-
export declare function parseLayoutAndSizing(node: IFigmaNode, isRoot?: boolean): IStyleProperty[];
|
|
38
|
+
export declare function parseLayoutAndSizing(node: IFigmaNode, isRoot?: boolean, parentHasAutoLayout?: boolean): IStyleProperty[];
|
|
36
39
|
//# sourceMappingURL=layout-parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-parser.d.ts","sourceRoot":"","sources":["../../src/parser/layout-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA4BrE,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,aAAa,CAAC,EAAE,cAAc,CAAC;IAC/B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,QAAQ,CAAC,EAAE,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"layout-parser.d.ts","sourceRoot":"","sources":["../../src/parser/layout-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA4BrE,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,aAAa,CAAC,EAAE,cAAc,CAAC;IAC/B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,cAAc,GAAG,IAAI,CAuBpE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,iBAAiB,CA2F/D;AAwBD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,GAAE,OAAe,EAAE,mBAAmB,GAAE,OAAe,GAAG,iBAAiB,CA+F9H;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,GAAE,OAAe,EAAE,mBAAmB,GAAE,OAAe,GAAG,cAAc,EAAE,CAStI"}
|
|
@@ -141,11 +141,17 @@ function isScreenNode(node) {
|
|
|
141
141
|
/**
|
|
142
142
|
* Parseia sizing de um node
|
|
143
143
|
* @param isRoot - indica se é o node raiz do componente
|
|
144
|
+
* @param parentHasAutoLayout - indica se o pai tem Auto Layout (para aplicar flex-shrink)
|
|
144
145
|
*/
|
|
145
|
-
export function parseSizing(node, isRoot = false) {
|
|
146
|
+
export function parseSizing(node, isRoot = false, parentHasAutoLayout = false) {
|
|
146
147
|
const properties = {};
|
|
147
148
|
// Se é o node raiz e é uma tela, usa viewport units
|
|
148
149
|
const isScreen = isRoot && isScreenNode(node);
|
|
150
|
+
// Verifica se precisa de flex-shrink: 0 (quando tem sizing HUG ou FIXED dentro de flex)
|
|
151
|
+
const needsFlexShrink = parentHasAutoLayout && (node.layoutSizingHorizontal === 'HUG' ||
|
|
152
|
+
node.layoutSizingHorizontal === 'FIXED' ||
|
|
153
|
+
node.layoutSizingVertical === 'HUG' ||
|
|
154
|
+
node.layoutSizingVertical === 'FIXED');
|
|
149
155
|
// Width
|
|
150
156
|
if (node.layoutSizingHorizontal) {
|
|
151
157
|
switch (node.layoutSizingHorizontal) {
|
|
@@ -217,15 +223,23 @@ export function parseSizing(node, isRoot = false) {
|
|
|
217
223
|
value: 'hidden',
|
|
218
224
|
};
|
|
219
225
|
}
|
|
226
|
+
// Adiciona flex-shrink: 0 quando necessário
|
|
227
|
+
if (needsFlexShrink) {
|
|
228
|
+
properties.flexShrink = {
|
|
229
|
+
property: 'flex-shrink',
|
|
230
|
+
value: '0',
|
|
231
|
+
};
|
|
232
|
+
}
|
|
220
233
|
return properties;
|
|
221
234
|
}
|
|
222
235
|
/**
|
|
223
236
|
* Combina layout e sizing
|
|
224
237
|
* @param isRoot - indica se é o node raiz do componente
|
|
238
|
+
* @param parentHasAutoLayout - indica se o pai tem Auto Layout
|
|
225
239
|
*/
|
|
226
|
-
export function parseLayoutAndSizing(node, isRoot = false) {
|
|
240
|
+
export function parseLayoutAndSizing(node, isRoot = false, parentHasAutoLayout = false) {
|
|
227
241
|
const layout = parseLayout(node);
|
|
228
|
-
const sizing = parseSizing(node, isRoot);
|
|
242
|
+
const sizing = parseSizing(node, isRoot, parentHasAutoLayout);
|
|
229
243
|
const combined = { ...layout, ...sizing };
|
|
230
244
|
return Object.values(combined).filter((prop) => prop !== undefined);
|
|
231
245
|
}
|
|
@@ -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,EAOb,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,EAOb,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;AAulBD;;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"}
|
|
@@ -61,24 +61,10 @@ function isAssetNode(node) {
|
|
|
61
61
|
return false;
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
|
-
* Patterns para detectar elementos de formulário
|
|
64
|
+
* Patterns para detectar elementos de formulário com prefixo explícito $tipo:nome
|
|
65
|
+
* O usuário deve marcar explicitamente os elementos para conversão
|
|
65
66
|
*/
|
|
66
|
-
const
|
|
67
|
-
// Input de texto (uma linha)
|
|
68
|
-
input: /^(input|text-?input|entrada|campo-texto|field-input|input-field)$/i,
|
|
69
|
-
// Textarea (múltiplas linhas)
|
|
70
|
-
textarea: /^(textarea|text-?area|area-?texto|multiline|multi-line|mensagem-input|message-input)$/i,
|
|
71
|
-
// Select/Dropdown
|
|
72
|
-
select: /^(select|dropdown|combo-?box|picker|seletor|selecao|lista-selecao|select-input)$/i,
|
|
73
|
-
// Checkbox
|
|
74
|
-
checkbox: /^(checkbox|check-?box|caixa-?selecao|toggle|switch)$/i,
|
|
75
|
-
// Radio button
|
|
76
|
-
radio: /^(radio|radio-?button|opcao-?radio|radio-?input)$/i,
|
|
77
|
-
// Button
|
|
78
|
-
button: /^(button|btn|botao|submit|cancel|action|cta)$/i,
|
|
79
|
-
// Label
|
|
80
|
-
label: /^(label|rotulo|field-?label|input-?label)$/i,
|
|
81
|
-
};
|
|
67
|
+
const FORM_ELEMENT_PREFIX_PATTERN = /^\$(input|textarea|select|checkbox|radio|button|label):/i;
|
|
82
68
|
/**
|
|
83
69
|
* Verifica se um node é um frame válido (FRAME, INSTANCE ou COMPONENT)
|
|
84
70
|
*/
|
|
@@ -135,51 +121,44 @@ function extractAllTexts(node) {
|
|
|
135
121
|
}
|
|
136
122
|
/**
|
|
137
123
|
* Detecta qual tipo de elemento de formulário um node representa
|
|
124
|
+
*
|
|
125
|
+
* IMPORTANTE: A detecção só acontece quando o nome tem prefixo explícito:
|
|
126
|
+
* $input:nome, $textarea:nome, $select:nome, etc.
|
|
127
|
+
*
|
|
128
|
+
* Isso preserva a estrutura visual do Figma por padrão.
|
|
138
129
|
*/
|
|
139
130
|
function detectSimulatedFormElement(node) {
|
|
140
131
|
if (!isValidFrameNode(node)) {
|
|
141
132
|
return null;
|
|
142
133
|
}
|
|
143
|
-
const name = node.name.
|
|
144
|
-
// Verifica
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
return 'select';
|
|
150
|
-
}
|
|
151
|
-
if (FORM_ELEMENT_PATTERNS.checkbox.test(name)) {
|
|
152
|
-
return 'checkbox';
|
|
153
|
-
}
|
|
154
|
-
if (FORM_ELEMENT_PATTERNS.radio.test(name)) {
|
|
155
|
-
return 'radio';
|
|
156
|
-
}
|
|
157
|
-
if (FORM_ELEMENT_PATTERNS.button.test(name)) {
|
|
158
|
-
// Só é button se tiver texto dentro
|
|
159
|
-
if (hasTextChild(node)) {
|
|
160
|
-
return 'button';
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
if (FORM_ELEMENT_PATTERNS.label.test(name)) {
|
|
164
|
-
// Só é label se tiver texto direto como filho
|
|
165
|
-
if (node.children?.some(child => child.type === 'TEXT')) {
|
|
166
|
-
return 'label';
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
if (FORM_ELEMENT_PATTERNS.input.test(name)) {
|
|
170
|
-
// Só é input se tiver texto dentro (placeholder)
|
|
171
|
-
if (hasTextChild(node)) {
|
|
172
|
-
return 'input';
|
|
173
|
-
}
|
|
134
|
+
const name = node.name.trim();
|
|
135
|
+
// Verifica se tem prefixo explícito $tipo:nome
|
|
136
|
+
const match = name.match(FORM_ELEMENT_PREFIX_PATTERN);
|
|
137
|
+
if (!match) {
|
|
138
|
+
// Sem prefixo explícito = não é um form element
|
|
139
|
+
return null;
|
|
174
140
|
}
|
|
175
|
-
|
|
141
|
+
const elementType = match[1].toLowerCase();
|
|
142
|
+
return elementType;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Extrai o nome limpo do node (remove prefixos especiais como $input:, #, etc.)
|
|
146
|
+
*/
|
|
147
|
+
function extractCleanName(name) {
|
|
148
|
+
// Remove prefixo de form element $tipo:
|
|
149
|
+
let clean = name.replace(FORM_ELEMENT_PREFIX_PATTERN, '');
|
|
150
|
+
// Remove prefixo de exportação #
|
|
151
|
+
clean = clean.replace(/^#/, '');
|
|
152
|
+
// Remove prefixo interno _
|
|
153
|
+
clean = clean.replace(/^_/, '');
|
|
154
|
+
return clean.trim();
|
|
176
155
|
}
|
|
177
156
|
/**
|
|
178
157
|
* Detecta o tipo específico de input baseado no contexto
|
|
179
158
|
*/
|
|
180
159
|
function detectInputType(node, parentNode) {
|
|
181
|
-
const nodeName = node.name.toLowerCase();
|
|
182
|
-
const parentName = parentNode
|
|
160
|
+
const nodeName = extractCleanName(node.name).toLowerCase();
|
|
161
|
+
const parentName = parentNode ? extractCleanName(parentNode.name).toLowerCase() : '';
|
|
183
162
|
const combinedContext = `${parentName} ${nodeName}`;
|
|
184
163
|
// Detecta por palavras-chave no contexto
|
|
185
164
|
if (combinedContext.includes('senha') || combinedContext.includes('password')) {
|
|
@@ -209,7 +188,7 @@ function detectInputType(node, parentNode) {
|
|
|
209
188
|
* Detecta o tipo de button baseado no contexto
|
|
210
189
|
*/
|
|
211
190
|
function detectButtonType(node) {
|
|
212
|
-
const name = node.name.toLowerCase();
|
|
191
|
+
const name = extractCleanName(node.name).toLowerCase();
|
|
213
192
|
const text = extractFirstText(node).toLowerCase();
|
|
214
193
|
const context = `${name} ${text}`;
|
|
215
194
|
if (context.includes('submit') || context.includes('enviar') || context.includes('entrar') || context.includes('login') || context.includes('cadastrar')) {
|
|
@@ -430,12 +409,14 @@ function collectStyles(node, blockName, depth = 0, parentNode) {
|
|
|
430
409
|
: `.${generateBEMElement(blockName, elementName)}`;
|
|
431
410
|
// Coleta propriedades deste node
|
|
432
411
|
const properties = [];
|
|
412
|
+
// Verifica se o pai tem Auto Layout (para aplicar flex-shrink nos filhos)
|
|
413
|
+
const parentHasAutoLayoutMode = parentNode ? hasAutoLayout(parentNode) : false;
|
|
433
414
|
// Layout e sizing
|
|
434
415
|
// Para FRAME, COMPONENT, INSTANCE: extrai layout completo (flex, gap, etc)
|
|
435
416
|
// Para GROUP: extrai sizing e position: relative (container sem flex)
|
|
436
417
|
// Para outros tipos (RECTANGLE, etc): extrai apenas sizing (width, height)
|
|
437
418
|
if (node.type === 'FRAME' || node.type === 'COMPONENT' || node.type === 'INSTANCE') {
|
|
438
|
-
properties.push(...parseLayoutAndSizing(node, isRoot));
|
|
419
|
+
properties.push(...parseLayoutAndSizing(node, isRoot, parentHasAutoLayoutMode));
|
|
439
420
|
// Se é um container sem Auto Layout, adiciona position: relative
|
|
440
421
|
const containerPos = parseContainerPosition(node);
|
|
441
422
|
if (containerPos) {
|
|
@@ -452,7 +433,7 @@ function collectStyles(node, blockName, depth = 0, parentNode) {
|
|
|
452
433
|
}
|
|
453
434
|
else if (node.type === 'GROUP') {
|
|
454
435
|
// GROUPs são containers visuais - precisam de position: relative e sizing
|
|
455
|
-
const sizingProps = parseSizing(node);
|
|
436
|
+
const sizingProps = parseSizing(node, false, parentHasAutoLayoutMode);
|
|
456
437
|
const sizingArray = Object.values(sizingProps).filter((p) => p !== undefined);
|
|
457
438
|
properties.push(...sizingArray);
|
|
458
439
|
// GROUP sempre precisa de position: relative se tiver filhos
|
|
@@ -465,7 +446,7 @@ function collectStyles(node, blockName, depth = 0, parentNode) {
|
|
|
465
446
|
}
|
|
466
447
|
else if (node.type !== 'TEXT' && node.absoluteBoundingBox) {
|
|
467
448
|
// Para elementos não-texto com dimensões, extrai apenas sizing
|
|
468
|
-
const sizingProps = parseSizing(node);
|
|
449
|
+
const sizingProps = parseSizing(node, false, parentHasAutoLayoutMode);
|
|
469
450
|
const sizingArray = Object.values(sizingProps).filter((p) => p !== undefined);
|
|
470
451
|
properties.push(...sizingArray);
|
|
471
452
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"position-parser.d.ts","sourceRoot":"","sources":["../../src/parser/position-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAgB,MAAM,oBAAoB,CAAC;AAEnF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;
|
|
1
|
+
{"version":3,"file":"position-parser.d.ts","sourceRoot":"","sources":["../../src/parser/position-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAgB,MAAM,oBAAoB,CAAC;AAEnF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AA6BD;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAEvD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAEhE;AAwBD;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,UAAU,CAAC,EAAE,UAAU,GACtB,cAAc,EAAE,CA6IlB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAa/D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,cAAc,GAAG,IAAI,CAQ9E"}
|
|
@@ -13,12 +13,20 @@ function roundPixelValue(value) {
|
|
|
13
13
|
return Math.round(value * 10) / 10;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* Formata valor de pixel arredondado
|
|
16
|
+
* Formata valor de pixel arredondado (suporta valores negativos)
|
|
17
17
|
*/
|
|
18
18
|
function formatPixels(value) {
|
|
19
19
|
const rounded = roundPixelValue(value);
|
|
20
20
|
return `${rounded}px`;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Formata valor de pixel para CSS, incluindo valores negativos
|
|
24
|
+
* Valores negativos são importantes para elementos que "vazam" do container
|
|
25
|
+
*/
|
|
26
|
+
function formatPixelsWithNegative(value) {
|
|
27
|
+
const rounded = roundPixelValue(value);
|
|
28
|
+
return `${rounded}px`;
|
|
29
|
+
}
|
|
22
30
|
/**
|
|
23
31
|
* Verifica se um node pai tem Auto Layout
|
|
24
32
|
*/
|
|
@@ -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;
|
|
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;AAuRrD;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAalD;AA0DD;;;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,CA4MR;AAgJD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,MAAM,GACrB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgLxB"}
|
|
@@ -184,13 +184,18 @@ const SEMANTIC_PATTERNS = {
|
|
|
184
184
|
// Links
|
|
185
185
|
link: /(link|anchor|href|ancora|forgot|esqueci|saiba-mais|ver-mais|leia-mais)/i,
|
|
186
186
|
// Formulários
|
|
187
|
+
// NOTA: Patterns de form elements são desativados por padrão para preservar a estrutura visual.
|
|
188
|
+
// Use prefixo $input:, $label:, etc. no Figma para ativar a conversão.
|
|
189
|
+
// Os patterns abaixo são mantidos apenas para elementos claramente marcados.
|
|
187
190
|
form: /^(form|formulario|login-form|signup-form|contact-form|search-form)/i,
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
// input/label/select/etc NÃO são mais detectados automaticamente
|
|
192
|
+
// para evitar converter estruturas visuais em elementos HTML
|
|
193
|
+
input: /^(\$input:|never-match-automatically)/i, // Desativado - use $input:nome
|
|
194
|
+
label: /^(\$label:|never-match-automatically)/i, // Desativado - use $label:nome
|
|
195
|
+
select: /^(\$select:|never-match-automatically)/i, // Desativado - use $select:nome
|
|
196
|
+
textarea: /^(\$textarea:|never-match-automatically)/i, // Desativado - use $textarea:nome
|
|
197
|
+
checkbox: /^(\$checkbox:|never-match-automatically)/i, // Desativado - use $checkbox:nome
|
|
198
|
+
radio: /^(\$radio:|never-match-automatically)/i, // Desativado - use $radio:nome
|
|
194
199
|
fieldset: /^(fieldset|field-group|grupo-campos)/i,
|
|
195
200
|
// Navegação - expandido para mais variações
|
|
196
201
|
nav: /^(nav|navigation|navbar|menu|navegacao|breadcrumb|tabs|pagination|nav-bar|top-nav|main-nav|side-nav)/i,
|
|
@@ -486,8 +491,9 @@ function detectTextTag(node, parentNode, normalizedName) {
|
|
|
486
491
|
if (fontSize >= 24 && fontWeight >= 600) {
|
|
487
492
|
return getHeadingLevel(fontSize);
|
|
488
493
|
}
|
|
489
|
-
// Labels
|
|
490
|
-
|
|
494
|
+
// Labels - só detecta com prefixo explícito $label:
|
|
495
|
+
// NÃO detecta automaticamente para preservar estrutura visual
|
|
496
|
+
if (name.startsWith('$label:')) {
|
|
491
497
|
return 'label';
|
|
492
498
|
}
|
|
493
499
|
// Links - mas não se o pai já é um link (evita <a> aninhado)
|
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.23",
|
|
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.23"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^20.0.0",
|