nexa-compiler 0.7.11 → 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.
package/dist/codegen/render.js
CHANGED
|
@@ -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'
|
|
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(`
|
|
179
|
+
lines.push(` const { ${allRenderBindings.join(', ')} } = ctx`);
|
|
185
180
|
}
|
|
186
181
|
lines.push(generateRenderCode(sfc.template, scopeId || undefined));
|
|
187
182
|
lines.push('}');
|
package/dist/codegen/template.js
CHANGED
|
@@ -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
|
|
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
|
|
136
|
+
function genChildrenSimple(children) {
|
|
82
137
|
if (!children || children.length === 0)
|
|
83
138
|
return '';
|
|
84
139
|
return children.map(child => genNode(child)).join(',\n ');
|
package/dist/parse/template.js
CHANGED
|
@@ -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;
|
|
@@ -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
|
|
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
|
|
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
|
-
|
|
161
|
-
|
|
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',
|