gonia 0.3.1 → 0.3.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/dist/client/hydrate.js +12 -8
- package/dist/server/render.js +62 -8
- package/package.json +1 -1
package/dist/client/hydrate.js
CHANGED
|
@@ -228,11 +228,15 @@ function processElement(el, registry) {
|
|
|
228
228
|
// Check if any directive needs a scope
|
|
229
229
|
let scope = findParentScope(el, true) ?? {};
|
|
230
230
|
let directiveCreatedScope = false;
|
|
231
|
-
// Collect
|
|
232
|
-
const
|
|
231
|
+
// Collect unique directive names for conflict detection
|
|
232
|
+
const directiveNameSet = new Set();
|
|
233
233
|
for (const { name } of directives) {
|
|
234
234
|
const fullName = `g-${name}`;
|
|
235
|
-
|
|
235
|
+
const isNew = !directiveNameSet.has(fullName);
|
|
236
|
+
directiveNameSet.add(fullName);
|
|
237
|
+
// Only process first occurrence
|
|
238
|
+
if (!isNew)
|
|
239
|
+
continue;
|
|
236
240
|
const registration = getDirective(fullName);
|
|
237
241
|
if (!directiveCreatedScope && directiveNeedsScope(fullName)) {
|
|
238
242
|
// Create a new scope that inherits from parent
|
|
@@ -246,7 +250,7 @@ function processElement(el, registry) {
|
|
|
246
250
|
}
|
|
247
251
|
// Apply assigns with conflict detection
|
|
248
252
|
if (directiveCreatedScope) {
|
|
249
|
-
applyAssigns(scope,
|
|
253
|
+
applyAssigns(scope, [...directiveNameSet]);
|
|
250
254
|
}
|
|
251
255
|
const ctx = createContext(Mode.CLIENT, scope);
|
|
252
256
|
contextCache.set(el, ctx);
|
|
@@ -433,16 +437,16 @@ async function processDirectiveElements() {
|
|
|
433
437
|
if (options.scope) {
|
|
434
438
|
const parentScope = findParentScope(el);
|
|
435
439
|
scope = createElementScope(el, parentScope);
|
|
436
|
-
// Collect
|
|
437
|
-
const
|
|
440
|
+
// Collect unique directive names on this element for conflict detection
|
|
441
|
+
const directiveNameSet = new Set([name]);
|
|
438
442
|
for (const attr of el.attributes) {
|
|
439
443
|
const attrReg = getDirective(attr.name);
|
|
440
444
|
if (attrReg) {
|
|
441
|
-
|
|
445
|
+
directiveNameSet.add(attr.name);
|
|
442
446
|
}
|
|
443
447
|
}
|
|
444
448
|
// Apply assigns with conflict detection
|
|
445
|
-
applyAssigns(scope,
|
|
449
|
+
applyAssigns(scope, [...directiveNameSet]);
|
|
446
450
|
}
|
|
447
451
|
else {
|
|
448
452
|
scope = findParentScope(el, true) ?? {};
|
package/dist/server/render.js
CHANGED
|
@@ -66,6 +66,22 @@ function getSelector(localRegistry) {
|
|
|
66
66
|
selectors.push('slot');
|
|
67
67
|
// Match g-scope for inline scope initialization (TODO: make prefix configurable)
|
|
68
68
|
selectors.push('[g-scope]');
|
|
69
|
+
// Match common g-bind:* attributes for dynamic binding
|
|
70
|
+
// These need to be indexed so their expressions can be evaluated with proper scope
|
|
71
|
+
selectors.push('[g-bind\\:class]');
|
|
72
|
+
selectors.push('[g-bind\\:style]');
|
|
73
|
+
selectors.push('[g-bind\\:href]');
|
|
74
|
+
selectors.push('[g-bind\\:src]');
|
|
75
|
+
selectors.push('[g-bind\\:id]');
|
|
76
|
+
selectors.push('[g-bind\\:value]');
|
|
77
|
+
selectors.push('[g-bind\\:disabled]');
|
|
78
|
+
selectors.push('[g-bind\\:checked]');
|
|
79
|
+
selectors.push('[g-bind\\:placeholder]');
|
|
80
|
+
selectors.push('[g-bind\\:title]');
|
|
81
|
+
selectors.push('[g-bind\\:alt]');
|
|
82
|
+
selectors.push('[g-bind\\:name]');
|
|
83
|
+
selectors.push('[g-bind\\:type]');
|
|
84
|
+
// Note: Can't do wildcard for data-* attributes in CSS, but hasBindAttributes handles them
|
|
69
85
|
return selectors.join(',');
|
|
70
86
|
}
|
|
71
87
|
/**
|
|
@@ -190,7 +206,23 @@ export async function render(html, state, registry) {
|
|
|
190
206
|
const window = new Window();
|
|
191
207
|
const document = window.document;
|
|
192
208
|
const index = [];
|
|
209
|
+
const indexedDirectives = new Map(); // Track indexed (element, directive) pairs
|
|
193
210
|
const selector = getSelector(registry);
|
|
211
|
+
// Helper to add to index only if not already indexed for this (element, directive) pair
|
|
212
|
+
const addToIndex = (item) => {
|
|
213
|
+
const existing = indexedDirectives.get(item.el);
|
|
214
|
+
if (existing?.has(item.name)) {
|
|
215
|
+
return false; // Already indexed
|
|
216
|
+
}
|
|
217
|
+
if (!existing) {
|
|
218
|
+
indexedDirectives.set(item.el, new Set([item.name]));
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
existing.add(item.name);
|
|
222
|
+
}
|
|
223
|
+
index.push(item);
|
|
224
|
+
return true;
|
|
225
|
+
};
|
|
194
226
|
const observer = new window.MutationObserver((mutations) => {
|
|
195
227
|
for (const mutation of mutations) {
|
|
196
228
|
for (const node of mutation.addedNodes) {
|
|
@@ -206,7 +238,7 @@ export async function render(html, state, registry) {
|
|
|
206
238
|
}
|
|
207
239
|
// Handle native <slot> elements
|
|
208
240
|
if (match.tagName === 'SLOT') {
|
|
209
|
-
|
|
241
|
+
addToIndex({
|
|
210
242
|
el: match,
|
|
211
243
|
name: 'slot',
|
|
212
244
|
directive: null,
|
|
@@ -227,7 +259,7 @@ export async function render(html, state, registry) {
|
|
|
227
259
|
}
|
|
228
260
|
}
|
|
229
261
|
if (!hasDirective) {
|
|
230
|
-
|
|
262
|
+
addToIndex({
|
|
231
263
|
el: match,
|
|
232
264
|
name: 'scope',
|
|
233
265
|
directive: null,
|
|
@@ -237,6 +269,27 @@ export async function render(html, state, registry) {
|
|
|
237
269
|
});
|
|
238
270
|
}
|
|
239
271
|
}
|
|
272
|
+
// Handle g-bind:* elements that don't have other directives
|
|
273
|
+
// Add a placeholder so they get processed for dynamic attribute binding
|
|
274
|
+
if (hasBindAttributes(match)) {
|
|
275
|
+
let hasDirective = false;
|
|
276
|
+
for (const name of getDirectiveNames()) {
|
|
277
|
+
if (match.hasAttribute(name)) {
|
|
278
|
+
hasDirective = true;
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (!hasDirective && !match.hasAttribute('g-scope')) {
|
|
283
|
+
addToIndex({
|
|
284
|
+
el: match,
|
|
285
|
+
name: 'bind',
|
|
286
|
+
directive: null,
|
|
287
|
+
expr: '',
|
|
288
|
+
priority: DirectivePriority.NORMAL,
|
|
289
|
+
isNativeSlot: false
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
240
293
|
// Check all registered directives from global registry
|
|
241
294
|
const tagName = match.tagName.toLowerCase();
|
|
242
295
|
for (const name of getDirectiveNames()) {
|
|
@@ -247,7 +300,7 @@ export async function render(html, state, registry) {
|
|
|
247
300
|
// Check if this is a custom element directive (tag name matches)
|
|
248
301
|
if (tagName === name) {
|
|
249
302
|
if (options.template || options.scope || options.provide || options.using) {
|
|
250
|
-
|
|
303
|
+
addToIndex({
|
|
251
304
|
el: match,
|
|
252
305
|
name,
|
|
253
306
|
directive: fn,
|
|
@@ -261,7 +314,7 @@ export async function render(html, state, registry) {
|
|
|
261
314
|
// Check if this is an attribute directive
|
|
262
315
|
const attr = match.getAttribute(name);
|
|
263
316
|
if (attr !== null) {
|
|
264
|
-
|
|
317
|
+
addToIndex({
|
|
265
318
|
el: match,
|
|
266
319
|
name,
|
|
267
320
|
directive: fn,
|
|
@@ -280,7 +333,7 @@ export async function render(html, state, registry) {
|
|
|
280
333
|
const fullName = `g-${name}`;
|
|
281
334
|
if (getDirective(fullName))
|
|
282
335
|
continue;
|
|
283
|
-
|
|
336
|
+
addToIndex({
|
|
284
337
|
el: match,
|
|
285
338
|
name,
|
|
286
339
|
directive,
|
|
@@ -370,13 +423,14 @@ export async function render(html, state, registry) {
|
|
|
370
423
|
}
|
|
371
424
|
}
|
|
372
425
|
}
|
|
373
|
-
// Collect
|
|
374
|
-
const
|
|
426
|
+
// Collect unique directive names for conflict detection
|
|
427
|
+
const directiveNameSet = new Set();
|
|
375
428
|
for (const item of directives) {
|
|
376
429
|
if (!item.isNativeSlot && item.directive !== null) {
|
|
377
|
-
|
|
430
|
+
directiveNameSet.add(item.name);
|
|
378
431
|
}
|
|
379
432
|
}
|
|
433
|
+
const directiveNames = [...directiveNameSet];
|
|
380
434
|
// Check if any directive needs scope - create once if so
|
|
381
435
|
let elementScope = null;
|
|
382
436
|
for (const name of directiveNames) {
|