gonia 0.2.0 → 0.2.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/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/render.js +46 -6
- package/package.json +2 -2
package/dist/server/index.d.ts
CHANGED
package/dist/server/index.js
CHANGED
package/dist/server/render.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @packageDocumentation
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { Window } from 'happy-dom';
|
|
7
7
|
import { Mode, DirectivePriority, getDirective } from '../types.js';
|
|
8
8
|
import { createContext } from '../context.js';
|
|
9
9
|
import { processNativeSlot } from '../directives/slot.js';
|
|
@@ -12,6 +12,20 @@ import { FOR_PROCESSED_ATTR, FOR_TEMPLATE_ATTR } from '../directives/for.js';
|
|
|
12
12
|
import { IF_PROCESSED_ATTR } from '../directives/if.js';
|
|
13
13
|
import { resolveDependencies as resolveInjectables } from '../inject.js';
|
|
14
14
|
import { resolveContext } from '../context-registry.js';
|
|
15
|
+
/**
|
|
16
|
+
* Decode HTML entities that happy-dom doesn't decode.
|
|
17
|
+
*
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
function decodeHTMLEntities(str) {
|
|
21
|
+
return str
|
|
22
|
+
.replace(/&#(\d+);/g, (_, code) => String.fromCharCode(Number(code)))
|
|
23
|
+
.replace(/"/g, '"')
|
|
24
|
+
.replace(/'/g, "'")
|
|
25
|
+
.replace(/</g, '<')
|
|
26
|
+
.replace(/>/g, '>')
|
|
27
|
+
.replace(/&/g, '&');
|
|
28
|
+
}
|
|
15
29
|
/** Registered services */
|
|
16
30
|
let services = new Map();
|
|
17
31
|
const selectorCache = new WeakMap();
|
|
@@ -123,10 +137,11 @@ function createServerResolverConfig(el, rootState) {
|
|
|
123
137
|
* ```
|
|
124
138
|
*/
|
|
125
139
|
export async function render(html, state, registry) {
|
|
126
|
-
const
|
|
140
|
+
const window = new Window();
|
|
141
|
+
const document = window.document;
|
|
127
142
|
const index = [];
|
|
128
143
|
const selector = getSelector(registry);
|
|
129
|
-
const observer = new MutationObserver((mutations) => {
|
|
144
|
+
const observer = new window.MutationObserver((mutations) => {
|
|
130
145
|
for (const mutation of mutations) {
|
|
131
146
|
for (const node of mutation.addedNodes) {
|
|
132
147
|
if (node.nodeType !== 1)
|
|
@@ -151,6 +166,27 @@ export async function render(html, state, registry) {
|
|
|
151
166
|
});
|
|
152
167
|
continue;
|
|
153
168
|
}
|
|
169
|
+
// Handle g-scope elements that don't have other directives
|
|
170
|
+
// Add a placeholder entry so they get processed
|
|
171
|
+
if (match.hasAttribute('g-scope')) {
|
|
172
|
+
let hasDirective = false;
|
|
173
|
+
for (const [name] of registry) {
|
|
174
|
+
if (match.hasAttribute(`g-${name}`)) {
|
|
175
|
+
hasDirective = true;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (!hasDirective) {
|
|
180
|
+
index.push({
|
|
181
|
+
el: match,
|
|
182
|
+
name: 'scope',
|
|
183
|
+
directive: null,
|
|
184
|
+
expr: '',
|
|
185
|
+
priority: DirectivePriority.STRUCTURAL,
|
|
186
|
+
isNativeSlot: false
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
154
190
|
for (const [name, directive] of registry) {
|
|
155
191
|
const attr = match.getAttribute(`g-${name}`);
|
|
156
192
|
if (attr !== null) {
|
|
@@ -160,7 +196,7 @@ export async function render(html, state, registry) {
|
|
|
160
196
|
el: match,
|
|
161
197
|
name,
|
|
162
198
|
directive,
|
|
163
|
-
expr: attr,
|
|
199
|
+
expr: decodeHTMLEntities(attr),
|
|
164
200
|
priority: directive.priority ?? DirectivePriority.NORMAL,
|
|
165
201
|
using: registration?.options.using
|
|
166
202
|
});
|
|
@@ -226,7 +262,7 @@ export async function render(html, state, registry) {
|
|
|
226
262
|
// Process g-scope first (inline scope initialization)
|
|
227
263
|
const scopeAttr = el.getAttribute('g-scope');
|
|
228
264
|
if (scopeAttr) {
|
|
229
|
-
const scopeValues = ctx.eval(scopeAttr);
|
|
265
|
+
const scopeValues = ctx.eval(decodeHTMLEntities(scopeAttr));
|
|
230
266
|
if (scopeValues && typeof scopeValues === 'object') {
|
|
231
267
|
Object.assign(state, scopeValues);
|
|
232
268
|
}
|
|
@@ -235,7 +271,7 @@ export async function render(html, state, registry) {
|
|
|
235
271
|
for (const attr of [...el.attributes]) {
|
|
236
272
|
if (attr.name.startsWith('g-bind:')) {
|
|
237
273
|
const targetAttr = attr.name.slice('g-bind:'.length);
|
|
238
|
-
const value = ctx.eval(attr.value);
|
|
274
|
+
const value = ctx.eval(decodeHTMLEntities(attr.value));
|
|
239
275
|
if (value === null || value === undefined) {
|
|
240
276
|
el.removeAttribute(targetAttr);
|
|
241
277
|
}
|
|
@@ -252,6 +288,10 @@ export async function render(html, state, registry) {
|
|
|
252
288
|
if (item.isNativeSlot) {
|
|
253
289
|
processNativeSlot(item.el);
|
|
254
290
|
}
|
|
291
|
+
else if (item.directive === null) {
|
|
292
|
+
// Placeholder for g-scope - already processed above
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
255
295
|
else {
|
|
256
296
|
const config = createServerResolverConfig(item.el, state);
|
|
257
297
|
const args = resolveInjectables(item.directive, item.expr, item.el, ctx.eval.bind(ctx), config, item.using);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gonia",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "A lightweight, SSR-first reactive UI library with declarative directives",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"
|
|
49
|
+
"happy-dom": "^17.4.4",
|
|
50
50
|
"tinyglobby": "^0.2.15"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|