nexa-compiler 0.7.10 → 0.8.0

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.
@@ -24,13 +24,10 @@ export function generateComponentCode(sfc, filename) {
24
24
  // Only add Teleport/Transition if they are used in template (keeping it simple for tests)
25
25
  const hasTeleport = sfc.template?.includes('<Teleport');
26
26
  const hasTransition = sfc.template?.includes('<Transition');
27
- const hasVCurrency = sfc.template?.includes('v-currency');
28
27
  if (hasTeleport && !existing.includes('Teleport'))
29
28
  needed.push('Teleport');
30
29
  if (hasTransition && !existing.includes('Transition'))
31
30
  needed.push('Transition');
32
- if (hasVCurrency && !existing.includes('vCurrency'))
33
- needed.push('vCurrency');
34
31
  if (needed.length > 0) {
35
32
  const merged = [...existing, ...needed].join(', ');
36
33
  lines.push(imp.replace(/\{[^}]+\}/s, `{ ${merged} }`));
@@ -54,8 +51,6 @@ export function generateComponentCode(sfc, filename) {
54
51
  defaultImports.push('Teleport');
55
52
  if (sfc.template?.includes('<Transition'))
56
53
  defaultImports.push('Transition');
57
- if (sfc.template?.includes('v-currency'))
58
- defaultImports.push('vCurrency');
59
54
  lines.push(`import { ${defaultImports.join(', ')} } from 'nexa-framework'`);
60
55
  }
61
56
  const { scopeId, styleCode } = transformStyle(sfc.style, sfc.scoped, sfc.template);
@@ -70,7 +65,7 @@ export function generateComponentCode(sfc, filename) {
70
65
  const emitsDef = parseDefineEmits(fullScript);
71
66
  const cleanSetup = stripMacroLines(fullScript);
72
67
  const scriptBindings = extractBindings(cleanSetup);
73
- const importBindings = extractImportBindings(importLines).filter(b => !['h', 'hText', 'effect', 'defineComponent', 'registerComponent', 'reloadComponent', 'injectStyle', 'signal', 'computed', 'watch', 'onMounted', 'onUnmounted', 'Teleport', 'Transition', 'vCurrency'].includes(b));
68
+ const importBindings = extractImportBindings(importLines).filter(b => !['h', 'hText', 'effect', 'defineComponent', 'registerComponent', 'reloadComponent', 'injectStyle', 'signal', 'computed', 'watch', 'onMounted', 'onUnmounted', 'Teleport', 'Transition'].includes(b));
74
69
  if (propsDef) {
75
70
  if (!propsDef._isJS) {
76
71
  propsKeys = Object.keys(propsDef);
@@ -181,7 +176,7 @@ export function generateComponentCode(sfc, filename) {
181
176
  const componentBindings = renderBindings.map(b => /^[A-Z]/.test(b) ? `${b}: _ntc_${b}` : b);
182
177
  const allRenderBindings = [...componentBindings, ...usedBuiltIns.map(b => `${b}: _ntc_${b}`)];
183
178
  if (allRenderBindings.length > 0) {
184
- lines.push(` let { ${allRenderBindings.join(', ')} } = ctx`);
179
+ lines.push(` const { ${allRenderBindings.join(', ')} } = ctx`);
185
180
  }
186
181
  lines.push(generateRenderCode(sfc.template, scopeId || undefined));
187
182
  lines.push('}');
@@ -50,7 +50,14 @@ function genForIterate(list, item, index, body) {
50
50
  }
51
51
  function genElement(node) {
52
52
  const { tag, props, children } = node;
53
- const childStr = genChildren(children);
53
+ const isComponent = /^[A-Z]/.test(tag) || ['Teleport', 'Transition', 'Fragment'].includes(tag);
54
+ if (isComponent && children && children.length > 0) {
55
+ const slotChildren = children.filter(c => c.type === 'element' && c.slotName);
56
+ if (slotChildren.length > 0) {
57
+ return genElementWithSlots(node);
58
+ }
59
+ }
60
+ const childStr = genChildrenSimple(children);
54
61
  const elementCode = buildElementCode(tag, props, childStr, node.scopeId);
55
62
  if (node.vFor) {
56
63
  const { item, index, list } = node.vFor;
@@ -59,6 +66,54 @@ function genElement(node) {
59
66
  // Note: v-if is handled by transformChildren and genIf
60
67
  return elementCode;
61
68
  }
69
+ function genElementWithSlots(node) {
70
+ const { tag, props, children } = node;
71
+ const isComponent = /^[A-Z]/.test(tag) || ['Teleport', 'Transition', 'Fragment'].includes(tag);
72
+ const tagCode = isComponent ? `_ntc_${tag}` : `'${tag}'`;
73
+ let finalProps = props;
74
+ if (node.scopeId) {
75
+ const scopeProp = `"${node.scopeId}": ""`;
76
+ finalProps = props ? `${props}, ${scopeProp}` : scopeProp;
77
+ }
78
+ const slotObj = genSlotObject(children);
79
+ let elementCode;
80
+ if (finalProps) {
81
+ elementCode = `h(${tagCode}, { ${finalProps} }, {\n ${slotObj}\n })`;
82
+ }
83
+ else {
84
+ elementCode = `h(${tagCode}, null, {\n ${slotObj}\n })`;
85
+ }
86
+ if (node.vFor) {
87
+ const { item, index, list } = node.vFor;
88
+ return genForIterate(list, item, index, elementCode);
89
+ }
90
+ return elementCode;
91
+ }
92
+ function genSlotObject(children) {
93
+ const entries = [];
94
+ const regularChildren = [];
95
+ for (const child of children) {
96
+ if (child.type === 'element' && child.slotName) {
97
+ const el = child;
98
+ const name = el.slotName;
99
+ const key = /^[\w$]+$/.test(name) ? name : JSON.stringify(name);
100
+ const args = el.slotProps ? `(${el.slotProps})` : '()';
101
+ const childCode = el.children && el.children.length > 0
102
+ ? el.children.map(c => genNode(c)).join(',\n ')
103
+ : '';
104
+ const body = childCode ? `[\n ${childCode}\n ]` : 'null';
105
+ entries.push(`${key}: ${args} => ${body}`);
106
+ }
107
+ else {
108
+ regularChildren.push(child);
109
+ }
110
+ }
111
+ if (regularChildren.length > 0) {
112
+ const defaultCode = regularChildren.map(c => genNode(c)).join(',\n ');
113
+ entries.push(`default: () => [\n ${defaultCode}\n ]`);
114
+ }
115
+ return entries.join(',\n ');
116
+ }
62
117
  function buildElementCode(tag, propStr, childStr, scopeId) {
63
118
  const isComponent = /^[A-Z]/.test(tag) || ['Teleport', 'Transition', 'Fragment'].includes(tag);
64
119
  const tagCode = isComponent ? `_ntc_${tag}` : `'${tag}'`;
@@ -78,7 +133,7 @@ function buildElementCode(tag, propStr, childStr, scopeId) {
78
133
  }
79
134
  return `h(${tagCode})`;
80
135
  }
81
- function genChildren(children) {
136
+ function genChildrenSimple(children) {
82
137
  if (!children || children.length === 0)
83
138
  return '';
84
139
  return children.map(child => genNode(child)).join(',\n ');
@@ -150,7 +150,11 @@ function parseAttrs(attrsStr, template, tagStart) {
150
150
  }
151
151
  else if (rawName.startsWith('#')) {
152
152
  name = 'slot';
153
+ const slotPropsValue = quotedValue;
153
154
  quotedValue = rawName.slice(1);
155
+ if (slotPropsValue !== undefined && slotPropsValue !== quotedValue) {
156
+ attrs.push({ name: 'slotProps', value: slotPropsValue, dynamic: true });
157
+ }
154
158
  }
155
159
  else {
156
160
  name = rawName;
@@ -15,6 +15,8 @@ export type TransformedNode = {
15
15
  list: string;
16
16
  };
17
17
  scopeId?: string;
18
+ slotName?: string;
19
+ slotProps?: string;
18
20
  } | {
19
21
  type: 'text';
20
22
  content: string;
@@ -12,11 +12,11 @@ function transformNode(node, scopeId) {
12
12
  const slotProps = dynamicAttrs.length > 0
13
13
  ? dynamicAttrs.map(a => `${a.name}: ${a.value}`).join(', ')
14
14
  : undefined;
15
- return { type: 'slot', name: node.attrs.find(a => a.name === 'name')?.value || 'default', slotProps, children: node.children?.map(c => transformNode(c, scopeId)) };
15
+ return { type: 'slot', name: node.attrs.find(a => a.name === 'name')?.value || 'default', slotProps, children: node.children?.map(c => transformNode(c)) };
16
16
  }
17
17
  const vForAttr = node.attrs.find(a => a.name === 'v-for');
18
18
  const vIfAttr = node.attrs.find(a => a.name === 'v-if');
19
- const filteredAttrs = node.attrs.filter(a => a.name !== 'v-if' && a.name !== 'v-for');
19
+ const filteredAttrs = node.attrs.filter(a => a.name !== 'v-if' && a.name !== 'v-for' && a.name !== 'slot' && a.name !== 'slotProps');
20
20
  const props = genProps(filteredAttrs, node.tag);
21
21
  const result = {
22
22
  type: 'element',
@@ -27,6 +27,14 @@ function transformNode(node, scopeId) {
27
27
  if (scopeId) {
28
28
  result.scopeId = scopeId;
29
29
  }
30
+ const slotAttr = node.attrs.find(a => a.name === 'slot');
31
+ if (slotAttr && typeof slotAttr.value === 'string') {
32
+ result.slotName = slotAttr.value;
33
+ }
34
+ const slotPropsAttr = node.attrs.find(a => a.name === 'slotProps');
35
+ if (slotPropsAttr && typeof slotPropsAttr.value === 'string') {
36
+ result.slotProps = slotPropsAttr.value;
37
+ }
30
38
  if (vIfAttr && typeof vIfAttr.value === 'string') {
31
39
  result.vIf = vIfAttr.value;
32
40
  }
@@ -43,7 +51,7 @@ function transformNode(node, scopeId) {
43
51
  const slotProps = dynamicAttrs.length > 0
44
52
  ? dynamicAttrs.map(a => `${a.name}: ${a.value}`).join(', ')
45
53
  : undefined;
46
- return { type: 'slot', name: node.name, slotProps, children: node.children?.map(c => transformNode(c, scopeId)) };
54
+ return { type: 'slot', name: node.name, slotProps, children: node.children?.map(c => transformNode(c)) };
47
55
  }
48
56
  case 'if': {
49
57
  const then = transformChildren(node.then, scopeId);
@@ -138,9 +146,6 @@ function genProps(attrs, tag) {
138
146
  if (propName === 'vShow' && typeof attr.value === 'string') {
139
147
  parts.push(`${propName}: ${attr.value}`);
140
148
  }
141
- else if (propName === 'vCurrency' && typeof attr.value === 'string') {
142
- parts.push(`${propName}: ${attr.value}`);
143
- }
144
149
  else if (propName === 'vModel' && typeof attr.value === 'string') {
145
150
  const isComponent = /^[A-Z]/.test(tag) || tag.includes('-');
146
151
  if (isComponent) {
@@ -156,29 +161,9 @@ function genProps(attrs, tag) {
156
161
  const parts_name = propName.split('.');
157
162
  const realName = parts_name[0];
158
163
  const modifiers = parts_name.slice(1);
159
- let handler;
160
- if (typeof attr.value === 'string' && /^\w+$/.test(attr.value)) {
161
- handler = attr.value;
162
- }
163
- else if (typeof attr.value === 'string') {
164
- const eqIdx = attr.value.indexOf('=');
165
- if (eqIdx > 0) {
166
- const lhs = attr.value.slice(0, eqIdx).trim();
167
- const rhs = attr.value.slice(eqIdx + 1).trim();
168
- if (/^[a-zA-Z_$]\w*$/.test(lhs)) {
169
- handler = `($event) => { ${lhs}.value = ${rhs} }`;
170
- }
171
- else {
172
- handler = `($event) => { ${attr.value} }`;
173
- }
174
- }
175
- else {
176
- handler = `($event) => { ${attr.value} }`;
177
- }
178
- }
179
- else {
180
- handler = `($event) => { ${attr.value} }`;
181
- }
164
+ let handler = typeof attr.value === 'string' && /^\w+$/.test(attr.value)
165
+ ? attr.value
166
+ : `($event) => { ${attr.value} }`;
182
167
  const keyMap = {
183
168
  enter: 'Enter', esc: 'Escape', tab: 'Tab',
184
169
  space: ' ', up: 'ArrowUp', down: 'ArrowDown',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexa-compiler",
3
- "version": "0.7.10",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",