@sprlab/wccompiler 0.11.0 → 0.11.2
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/integrations/vue.js +34 -5
- package/lib/tree-walker.js +22 -9
- package/package.json +1 -1
package/integrations/vue.js
CHANGED
|
@@ -76,12 +76,14 @@ export function wccVuePlugin(options = {}) {
|
|
|
76
76
|
|
|
77
77
|
// Transform v-model:propName="expr" on custom elements (tags with hyphens)
|
|
78
78
|
// Also handles modifiers: v-model:propName.trim.number="expr"
|
|
79
|
-
// → :propName="expr" @wcc:model
|
|
79
|
+
// → :propName="expr" + merged @wcc:model handler
|
|
80
80
|
// with modifiers applied to the extracted value:
|
|
81
81
|
// .trim → value.trim() (for string values)
|
|
82
82
|
// .number → Number(value)
|
|
83
83
|
// .lazy → no-op for custom elements
|
|
84
|
-
//
|
|
84
|
+
//
|
|
85
|
+
// Multiple v-model:prop on the same element are merged into a single
|
|
86
|
+
// @wcc:model handler with semicolons (avoids Vue "Duplicate attribute" error).
|
|
85
87
|
let prev = ''
|
|
86
88
|
while (prev !== result) {
|
|
87
89
|
prev = result
|
|
@@ -99,14 +101,23 @@ export function wccVuePlugin(options = {}) {
|
|
|
99
101
|
}
|
|
100
102
|
// .lazy is a no-op for custom elements (they already use change events)
|
|
101
103
|
}
|
|
102
|
-
|
|
104
|
+
const handler = `$event.detail.prop === '${prop}' && (${expr} = ${value})`
|
|
105
|
+
// Check if there's already a @wcc:model on this element — append to it
|
|
106
|
+
if (prefix.includes('@wcc:model="')) {
|
|
107
|
+
const merged = prefix.replace(
|
|
108
|
+
/@wcc:model="([^"]*)"/,
|
|
109
|
+
(_, existing) => `@wcc:model="${existing}; ${handler}"`
|
|
110
|
+
)
|
|
111
|
+
return `${merged}:${prop}="${expr}"`
|
|
112
|
+
}
|
|
113
|
+
return `${prefix}:${prop}="${expr}" @wcc:model="${handler}"`
|
|
103
114
|
}
|
|
104
115
|
)
|
|
105
116
|
}
|
|
106
117
|
|
|
107
118
|
// Transform v-model="expr" (without argument) on custom elements
|
|
108
119
|
// Also handles modifiers: v-model.trim.lazy="expr"
|
|
109
|
-
// → :model-value="expr" @wcc:model
|
|
120
|
+
// → :model-value="expr" + merged @wcc:model handler
|
|
110
121
|
prev = ''
|
|
111
122
|
while (prev !== result) {
|
|
112
123
|
prev = result
|
|
@@ -122,11 +133,29 @@ export function wccVuePlugin(options = {}) {
|
|
|
122
133
|
value = `Number(${value})`
|
|
123
134
|
}
|
|
124
135
|
}
|
|
125
|
-
|
|
136
|
+
const handler = `$event.detail.prop === 'modelValue' && (${expr} = ${value})`
|
|
137
|
+
// Check if there's already a @wcc:model on this element — append to it
|
|
138
|
+
if (prefix.includes('@wcc:model="')) {
|
|
139
|
+
const merged = prefix.replace(
|
|
140
|
+
/@wcc:model="([^"]*)"/,
|
|
141
|
+
(_, existing) => `@wcc:model="${existing}; ${handler}"`
|
|
142
|
+
)
|
|
143
|
+
return `${merged}:model-value="${expr}"`
|
|
144
|
+
}
|
|
145
|
+
return `${prefix}:model-value="${expr}" @wcc:model="${handler}"`
|
|
126
146
|
}
|
|
127
147
|
)
|
|
128
148
|
}
|
|
129
149
|
|
|
150
|
+
// Post-process: merge any duplicate @wcc:model attributes on the same element
|
|
151
|
+
// This handles the case where v-model (no arg) was before v-model:prop in source order
|
|
152
|
+
result = result.replace(
|
|
153
|
+
/<([\w]+-[\w-]*)((?:\s[^>]*?)?)@wcc:model="([^"]*)"((?:\s[^>]*?)?)@wcc:model="([^"]*)"([^>]*?)>/g,
|
|
154
|
+
(match, tag, before, handler1, middle, handler2, after) => {
|
|
155
|
+
return `<${tag}${before}@wcc:model="${handler1}; ${handler2}"${middle}${after}>`
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
|
|
130
159
|
// ── Slot transforms ──
|
|
131
160
|
// Transform <template #name>content</template> inside custom elements
|
|
132
161
|
// → <div slot="name">content</div>
|
package/lib/tree-walker.js
CHANGED
|
@@ -88,7 +88,9 @@ export function walkTree(rootEl, signalNames, computedNames, propNames = new Set
|
|
|
88
88
|
// Detect <slot> elements — replace with <span data-slot="..."> placeholder
|
|
89
89
|
if (el.tagName === 'SLOT') {
|
|
90
90
|
const slotName = el.getAttribute('name') || '';
|
|
91
|
-
const
|
|
91
|
+
const safeName = slotName ? slotName.replace(/[^a-zA-Z0-9_]/g, '_') : 'default';
|
|
92
|
+
const varName = `__slot_${safeName}_${slotIdx}`;
|
|
93
|
+
slotIdx++;
|
|
92
94
|
const defaultContent = el.innerHTML.trim();
|
|
93
95
|
|
|
94
96
|
// Collect :prop="expr" attributes (slot props for scoped slots)
|
|
@@ -155,10 +157,13 @@ export function walkTree(rootEl, signalNames, computedNames, propNames = new Set
|
|
|
155
157
|
const attrsToRemove = [];
|
|
156
158
|
for (const attr of Array.from(el.attributes)) {
|
|
157
159
|
if (attr.name.startsWith('@')) {
|
|
158
|
-
const
|
|
160
|
+
const eventName = attr.name.slice(1);
|
|
161
|
+
const handlerName = attr.value.replace(/[^a-zA-Z0-9_]/g, '_').slice(0, 20);
|
|
162
|
+
const varName = `__evt_${eventName.replace(/-/g, '_')}_${handlerName}`;
|
|
163
|
+
eventIdx++;
|
|
159
164
|
events.push({
|
|
160
165
|
varName,
|
|
161
|
-
event:
|
|
166
|
+
event: eventName,
|
|
162
167
|
handler: attr.value,
|
|
163
168
|
path: [...pathParts],
|
|
164
169
|
});
|
|
@@ -180,7 +185,8 @@ export function walkTree(rootEl, signalNames, computedNames, propNames = new Set
|
|
|
180
185
|
kind = 'attr';
|
|
181
186
|
}
|
|
182
187
|
|
|
183
|
-
const varName = `
|
|
188
|
+
const varName = `__attr_${attrName.replace(/-/g, '_')}_${attrIdx}`;
|
|
189
|
+
attrIdx++;
|
|
184
190
|
attrBindings.push({
|
|
185
191
|
varName,
|
|
186
192
|
attr: attrName,
|
|
@@ -195,7 +201,8 @@ export function walkTree(rootEl, signalNames, computedNames, propNames = new Set
|
|
|
195
201
|
|
|
196
202
|
// Detect show attribute
|
|
197
203
|
if (el.hasAttribute('show')) {
|
|
198
|
-
const varName = `
|
|
204
|
+
const varName = `__show_${showIdx}`;
|
|
205
|
+
showIdx++;
|
|
199
206
|
showBindings.push({
|
|
200
207
|
varName,
|
|
201
208
|
expression: el.getAttribute('show'),
|
|
@@ -244,7 +251,8 @@ export function walkTree(rootEl, signalNames, computedNames, propNames = new Set
|
|
|
244
251
|
prop = 'value'; event = 'input';
|
|
245
252
|
}
|
|
246
253
|
|
|
247
|
-
const varName = `
|
|
254
|
+
const varName = `__model_${signalName}`;
|
|
255
|
+
modelIdx++;
|
|
248
256
|
modelBindings.push({ varName, signal: signalName, prop, event, coerce, radioValue, path: [...pathParts] });
|
|
249
257
|
el.removeAttribute('model');
|
|
250
258
|
}
|
|
@@ -265,7 +273,8 @@ export function walkTree(rootEl, signalNames, computedNames, propNames = new Set
|
|
|
265
273
|
throw error;
|
|
266
274
|
}
|
|
267
275
|
|
|
268
|
-
const varName = `
|
|
276
|
+
const varName = `__modelProp_${propName}`;
|
|
277
|
+
modelPropIdx++;
|
|
269
278
|
modelPropBindings.push({ varName, propName, signal, path: [...pathParts] });
|
|
270
279
|
modelPropAttrsToRemove.push(attr.name);
|
|
271
280
|
}
|
|
@@ -287,8 +296,10 @@ export function walkTree(rootEl, signalNames, computedNames, propNames = new Set
|
|
|
287
296
|
|
|
288
297
|
// Case 1: {{var}} is the sole content of the parent element and parent has only one child text node
|
|
289
298
|
if (soleMatch && parent.childNodes.length === 1) {
|
|
290
|
-
const varName = `__b${bindIdx++}`;
|
|
291
299
|
const name = baseName(soleMatch[1]);
|
|
300
|
+
const safeName = name.replace(/[^a-zA-Z0-9_]/g, '_').slice(0, 30);
|
|
301
|
+
const varName = `__text_${safeName}`;
|
|
302
|
+
bindIdx++;
|
|
292
303
|
bindings.push({
|
|
293
304
|
varName,
|
|
294
305
|
name,
|
|
@@ -317,8 +328,10 @@ export function walkTree(rootEl, signalNames, computedNames, propNames = new Set
|
|
|
317
328
|
const bm = part.match(/^\{\{((?:[^}]|\}(?!\}))+)\}\}$/);
|
|
318
329
|
if (bm) {
|
|
319
330
|
fragment.appendChild(doc.createElement('span'));
|
|
320
|
-
const varName = `__b${bindIdx++}`;
|
|
321
331
|
const name = baseName(bm[1]);
|
|
332
|
+
const safeName = name.replace(/[^a-zA-Z0-9_]/g, '_').slice(0, 30);
|
|
333
|
+
const varName = `__text_${safeName}_${bindIdx}`;
|
|
334
|
+
bindIdx++;
|
|
322
335
|
bindings.push({
|
|
323
336
|
varName,
|
|
324
337
|
name,
|
package/package.json
CHANGED