ripple 0.3.27 → 0.3.29
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/CHANGELOG.md +19 -0
- package/package.json +4 -4
- package/src/runtime/proxy.js +182 -180
- package/tests/client/basic/basic.errors.test.tsrx +24 -0
- package/tests/client/compiler/compiler.basic.test.tsrx +1 -1
- package/tests/client/tsconfig.json +1 -7
- package/tests/client/tsx.test.tsrx +53 -3
- package/tests/hydration/tsconfig.json +1 -8
- package/tests/server/basic.attributes.test.tsrx +67 -7
- package/tests/server/tsconfig.json +1 -8
- package/tsconfig.json +1 -8
- package/tsconfig.typecheck.json +1 -2
- package/types/index.d.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# ripple
|
|
2
2
|
|
|
3
|
+
## 0.3.29
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
[[`4543794`](https://github.com/Ripple-TS/ripple/commit/45437944a99decfb4bc56f7171772614a7f5691a)]:
|
|
9
|
+
- @tsrx/ripple@0.0.11
|
|
10
|
+
- ripple@0.3.29
|
|
11
|
+
|
|
12
|
+
## 0.3.28
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Updated dependencies
|
|
17
|
+
[[`e4b5555`](https://github.com/Ripple-TS/ripple/commit/e4b5555fb5b1651a2bf1bf232565c7e0e40213b8),
|
|
18
|
+
[`e4b5555`](https://github.com/Ripple-TS/ripple/commit/e4b5555fb5b1651a2bf1bf232565c7e0e40213b8)]:
|
|
19
|
+
- @tsrx/ripple@0.0.10
|
|
20
|
+
- ripple@0.3.28
|
|
21
|
+
|
|
3
22
|
## 0.3.27
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Ripple is an elegant TypeScript UI framework",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.3.
|
|
6
|
+
"version": "0.3.29",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index-client.js",
|
|
9
9
|
"main": "src/runtime/index-client.js",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"esm-env": "^1.2.2",
|
|
77
77
|
"@types/estree": "^1.0.8",
|
|
78
78
|
"@types/estree-jsx": "^1.0.5",
|
|
79
|
-
"@tsrx/ripple": "0.0.
|
|
79
|
+
"@tsrx/ripple": "0.0.11"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@types/node": "^24.3.0",
|
|
@@ -84,9 +84,9 @@
|
|
|
84
84
|
"typescript": "^5.9.3",
|
|
85
85
|
"@volar/language-core": "~2.4.28",
|
|
86
86
|
"vscode-languageserver-types": "^3.17.5",
|
|
87
|
-
"@tsrx/core": "0.0.
|
|
87
|
+
"@tsrx/core": "0.0.9"
|
|
88
88
|
},
|
|
89
89
|
"peerDependencies": {
|
|
90
|
-
"ripple": "0.3.
|
|
90
|
+
"ripple": "0.3.29"
|
|
91
91
|
}
|
|
92
92
|
}
|
package/src/runtime/proxy.js
CHANGED
|
@@ -30,13 +30,13 @@ export function proxy(value, block) {
|
|
|
30
30
|
TRACKED_ARRAY in value ||
|
|
31
31
|
TRACKED_OBJECT in value
|
|
32
32
|
) {
|
|
33
|
-
return value;
|
|
33
|
+
return /** @type {RippleArray<T> | RippleObject<T>} */ (value);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
const prototype = get_prototype_of(value);
|
|
37
37
|
|
|
38
38
|
if (prototype !== object_prototype && prototype !== array_prototype) {
|
|
39
|
-
return value;
|
|
39
|
+
return /** @type {RippleArray<T> | RippleObject<T>} */ (value);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/** @type {Map<any,Tracked>} */
|
|
@@ -50,222 +50,224 @@ export function proxy(value, block) {
|
|
|
50
50
|
tracked_elements.set('length', tracked_len);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
return
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (t === undefined && (!exists || get_descriptor(target, prop)?.writable)) {
|
|
62
|
-
t = tracked(exists ? /** @type {any} */ (target)[prop] : UNINITIALIZED, block);
|
|
63
|
-
tracked_elements.set(prop, t);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (t !== undefined) {
|
|
67
|
-
var v = get(t);
|
|
68
|
-
return v === UNINITIALIZED ? undefined : v;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
var result = Reflect.get(target, prop, receiver);
|
|
72
|
-
|
|
73
|
-
if (typeof result === 'function') {
|
|
74
|
-
if (methods_returning_arrays.has(prop)) {
|
|
75
|
-
/** @type {(this: any, ...args: any[]) => any} */
|
|
76
|
-
return function (...args) {
|
|
77
|
-
var output = Reflect.apply(result, receiver, args);
|
|
78
|
-
|
|
79
|
-
if (Array.isArray(output) && output !== target) {
|
|
80
|
-
return array_proxy({ elements: output, block, use_array: true });
|
|
81
|
-
}
|
|
53
|
+
return /** @type {RippleArray<T> | RippleObject<T>} */ (
|
|
54
|
+
new Proxy(value, {
|
|
55
|
+
/**
|
|
56
|
+
* @param {PropertyKey} prop
|
|
57
|
+
*/
|
|
58
|
+
get(target, prop, receiver) {
|
|
59
|
+
var t = tracked_elements.get(prop);
|
|
60
|
+
var exists = prop in target;
|
|
82
61
|
|
|
83
|
-
|
|
84
|
-
};
|
|
62
|
+
if (t === undefined && (!exists || get_descriptor(target, prop)?.writable)) {
|
|
63
|
+
t = tracked(exists ? /** @type {any} */ (target)[prop] : UNINITIALIZED, block);
|
|
64
|
+
tracked_elements.set(prop, t);
|
|
85
65
|
}
|
|
86
66
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
67
|
+
if (t !== undefined) {
|
|
68
|
+
var v = get(t);
|
|
69
|
+
return v === UNINITIALIZED ? undefined : v;
|
|
90
70
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// If the item exists in the original, we need to create a uninitialized tracked,
|
|
107
|
-
// else a later read of the property would result in a tracked being created with
|
|
108
|
-
// the value of the original item at that index.
|
|
109
|
-
other_t = tracked(UNINITIALIZED, block);
|
|
110
|
-
tracked_elements.set(i + '', other_t);
|
|
71
|
+
|
|
72
|
+
var result = Reflect.get(target, prop, receiver);
|
|
73
|
+
|
|
74
|
+
if (typeof result === 'function') {
|
|
75
|
+
if (methods_returning_arrays.has(prop)) {
|
|
76
|
+
/** @type {(this: any, ...args: any[]) => any} */
|
|
77
|
+
return function (...args) {
|
|
78
|
+
var output = Reflect.apply(result, receiver, args);
|
|
79
|
+
|
|
80
|
+
if (Array.isArray(output) && output !== target) {
|
|
81
|
+
return array_proxy({ elements: output, block, use_array: true });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return output;
|
|
85
|
+
};
|
|
111
86
|
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// If we haven't yet created a tracked for this property, we need to ensure
|
|
116
|
-
// we do so otherwise if we read it later, then the write won't be tracked and
|
|
117
|
-
// the heuristics of effects will be different vs if we had read the proxied
|
|
118
|
-
// object property before writing to that property.
|
|
119
|
-
if (t === undefined) {
|
|
120
|
-
if (!exists || get_descriptor(target, prop)?.writable) {
|
|
121
|
-
t = tracked(undefined, block);
|
|
122
|
-
set(t, value);
|
|
123
87
|
|
|
124
|
-
|
|
88
|
+
// When generating an iterator, we need to ensure that length is tracked
|
|
89
|
+
if (is_proxied_array && (prop === 'entries' || prop === 'values' || prop === 'keys')) {
|
|
90
|
+
receiver.length;
|
|
91
|
+
}
|
|
125
92
|
}
|
|
126
|
-
} else {
|
|
127
|
-
exists = t.__v !== UNINITIALIZED;
|
|
128
93
|
|
|
129
|
-
|
|
130
|
-
}
|
|
94
|
+
return result;
|
|
95
|
+
},
|
|
131
96
|
|
|
132
|
-
|
|
97
|
+
set(target, prop, value, receiver) {
|
|
98
|
+
var t = tracked_elements.get(prop);
|
|
99
|
+
var exists = prop in target;
|
|
100
|
+
|
|
101
|
+
if (is_proxied_array && prop === 'length' && t !== undefined) {
|
|
102
|
+
for (var i = value; i < t.__v; i += 1) {
|
|
103
|
+
var other_t = tracked_elements.get(i + '');
|
|
104
|
+
if (other_t !== undefined) {
|
|
105
|
+
set(other_t, UNINITIALIZED);
|
|
106
|
+
} else if (i in target) {
|
|
107
|
+
// If the item exists in the original, we need to create a uninitialized tracked,
|
|
108
|
+
// else a later read of the property would result in a tracked being created with
|
|
109
|
+
// the value of the original item at that index.
|
|
110
|
+
other_t = tracked(UNINITIALIZED, block);
|
|
111
|
+
tracked_elements.set(i + '', other_t);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
133
115
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
116
|
+
// If we haven't yet created a tracked for this property, we need to ensure
|
|
117
|
+
// we do so otherwise if we read it later, then the write won't be tracked and
|
|
118
|
+
// the heuristics of effects will be different vs if we had read the proxied
|
|
119
|
+
// object property before writing to that property.
|
|
120
|
+
if (t === undefined) {
|
|
121
|
+
if (!exists || get_descriptor(target, prop)?.writable) {
|
|
122
|
+
t = tracked(undefined, block);
|
|
123
|
+
set(t, value);
|
|
138
124
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
// will not cause the length to be out of sync.
|
|
144
|
-
var n = Number(prop);
|
|
125
|
+
tracked_elements.set(prop, t);
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
exists = t.__v !== UNINITIALIZED;
|
|
145
129
|
|
|
146
|
-
|
|
147
|
-
set(tracked_len, n + 1);
|
|
130
|
+
set(t, value);
|
|
148
131
|
}
|
|
149
|
-
}
|
|
150
132
|
|
|
151
|
-
|
|
152
|
-
},
|
|
133
|
+
var descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
153
134
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
},
|
|
135
|
+
// Set the new value before updating any tracked's so that any listeners get the new value
|
|
136
|
+
if (descriptor?.set) {
|
|
137
|
+
descriptor.set.call(receiver, value);
|
|
138
|
+
}
|
|
159
139
|
|
|
160
|
-
|
|
161
|
-
|
|
140
|
+
if (!exists && is_proxied_array && typeof prop === 'string') {
|
|
141
|
+
// If we have mutated an array directly, we might need to
|
|
142
|
+
// signal that length has also changed. Do it before updating metadata
|
|
143
|
+
// to ensure that iterating over the array as a result of a metadata update
|
|
144
|
+
// will not cause the length to be out of sync.
|
|
145
|
+
var n = Number(prop);
|
|
162
146
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
tracked_elements.set(prop, t);
|
|
147
|
+
if (Number.isInteger(n) && n >= tracked_len.__v) {
|
|
148
|
+
set(tracked_len, n + 1);
|
|
149
|
+
}
|
|
167
150
|
}
|
|
168
|
-
} else {
|
|
169
|
-
set(t, UNINITIALIZED);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return Reflect.deleteProperty(target, prop);
|
|
173
|
-
},
|
|
174
151
|
|
|
175
|
-
has(target, prop) {
|
|
176
|
-
if (is_proxied_array && prop === TRACKED_ARRAY) {
|
|
177
152
|
return true;
|
|
178
|
-
}
|
|
153
|
+
},
|
|
179
154
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
155
|
+
setPrototypeOf() {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`Cannot set prototype of ${is_proxied_array ? '\`RippleArray\`' : '\`RippleObject\`'}`,
|
|
158
|
+
);
|
|
159
|
+
},
|
|
183
160
|
|
|
184
|
-
|
|
185
|
-
|
|
161
|
+
deleteProperty(target, prop) {
|
|
162
|
+
var t = tracked_elements.get(prop);
|
|
186
163
|
|
|
187
|
-
if (t !== undefined || !exists || get_descriptor(target, prop)?.writable) {
|
|
188
164
|
if (t === undefined) {
|
|
189
|
-
|
|
165
|
+
if (prop in target) {
|
|
166
|
+
const t = tracked(UNINITIALIZED, block);
|
|
167
|
+
tracked_elements.set(prop, t);
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
set(t, UNINITIALIZED);
|
|
171
|
+
}
|
|
190
172
|
|
|
191
|
-
|
|
173
|
+
return Reflect.deleteProperty(target, prop);
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
has(target, prop) {
|
|
177
|
+
if (is_proxied_array && prop === TRACKED_ARRAY) {
|
|
178
|
+
return true;
|
|
192
179
|
}
|
|
193
180
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return false;
|
|
181
|
+
if (prop === TRACKED_OBJECT) {
|
|
182
|
+
return true;
|
|
197
183
|
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return exists;
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
defineProperty(_, prop, descriptor) {
|
|
204
|
-
if (
|
|
205
|
-
!('value' in descriptor) ||
|
|
206
|
-
descriptor.configurable === false ||
|
|
207
|
-
descriptor.enumerable === false ||
|
|
208
|
-
descriptor.writable === false
|
|
209
|
-
) {
|
|
210
|
-
// we disallow non-basic descriptors, because unless they are applied to the
|
|
211
|
-
// target object — which we avoid, so that state can be forked — we will run
|
|
212
|
-
// afoul of the various invariants
|
|
213
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/getOwnPropertyDescriptor#invariants
|
|
214
|
-
throw new Error(
|
|
215
|
-
'Only basic property descriptors are supported with value and configurable, enumerable, and writable set to true',
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
184
|
|
|
219
|
-
|
|
185
|
+
var t = tracked_elements.get(prop);
|
|
186
|
+
var exists = (t !== undefined && t.__v !== UNINITIALIZED) || Reflect.has(target, prop);
|
|
220
187
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
} else {
|
|
225
|
-
set(t, descriptor.value);
|
|
226
|
-
}
|
|
188
|
+
if (t !== undefined || !exists || get_descriptor(target, prop)?.writable) {
|
|
189
|
+
if (t === undefined) {
|
|
190
|
+
t = tracked(exists ? /** @type {any} */ (target)[prop] : UNINITIALIZED, block);
|
|
227
191
|
|
|
228
|
-
|
|
229
|
-
|
|
192
|
+
tracked_elements.set(prop, t);
|
|
193
|
+
}
|
|
230
194
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
195
|
+
var value = get(t);
|
|
196
|
+
if (value === UNINITIALIZED) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
236
200
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
201
|
+
return exists;
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
defineProperty(_, prop, descriptor) {
|
|
205
|
+
if (
|
|
206
|
+
!('value' in descriptor) ||
|
|
207
|
+
descriptor.configurable === false ||
|
|
208
|
+
descriptor.enumerable === false ||
|
|
209
|
+
descriptor.writable === false
|
|
210
|
+
) {
|
|
211
|
+
// we disallow non-basic descriptors, because unless they are applied to the
|
|
212
|
+
// target object — which we avoid, so that state can be forked — we will run
|
|
213
|
+
// afoul of the various invariants
|
|
214
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/getOwnPropertyDescriptor#invariants
|
|
215
|
+
throw new Error(
|
|
216
|
+
'Only basic property descriptors are supported with value and configurable, enumerable, and writable set to true',
|
|
217
|
+
);
|
|
240
218
|
}
|
|
241
|
-
}
|
|
242
219
|
|
|
243
|
-
|
|
244
|
-
},
|
|
220
|
+
var t = tracked_elements.get(prop);
|
|
245
221
|
|
|
246
|
-
|
|
247
|
-
|
|
222
|
+
if (t === undefined) {
|
|
223
|
+
t = tracked(descriptor.value, block);
|
|
224
|
+
tracked_elements.set(prop, t);
|
|
225
|
+
} else {
|
|
226
|
+
set(t, descriptor.value);
|
|
227
|
+
}
|
|
248
228
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
var
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
229
|
+
return true;
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
ownKeys(target) {
|
|
233
|
+
var own_keys = Reflect.ownKeys(target).filter((key) => {
|
|
234
|
+
var t = tracked_elements.get(key);
|
|
235
|
+
return t === undefined || t.__v !== UNINITIALIZED;
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
for (var [key, t] of tracked_elements) {
|
|
239
|
+
if (t.__v !== UNINITIALIZED && !(key in target)) {
|
|
240
|
+
own_keys.push(key);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return own_keys;
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
248
|
+
var descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
249
|
+
|
|
250
|
+
if (descriptor && 'value' in descriptor) {
|
|
251
|
+
var t = tracked_elements.get(prop);
|
|
252
|
+
if (t) descriptor.value = get(t);
|
|
253
|
+
} else if (descriptor === undefined) {
|
|
254
|
+
var t = tracked_elements.get(prop);
|
|
255
|
+
var value = t?.__v;
|
|
256
|
+
|
|
257
|
+
if (t !== undefined && value !== UNINITIALIZED) {
|
|
258
|
+
return {
|
|
259
|
+
enumerable: true,
|
|
260
|
+
configurable: true,
|
|
261
|
+
value,
|
|
262
|
+
writable: true,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
263
265
|
}
|
|
264
|
-
}
|
|
265
266
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
267
|
+
return descriptor;
|
|
268
|
+
},
|
|
269
|
+
})
|
|
270
|
+
);
|
|
269
271
|
}
|
|
270
272
|
|
|
271
273
|
/**
|
|
@@ -304,7 +306,7 @@ export function array_proxy({ elements, block, from_static = false, use_array =
|
|
|
304
306
|
* @returns {RippleObject<T>}
|
|
305
307
|
*/
|
|
306
308
|
export function object_proxy(obj, block) {
|
|
307
|
-
return proxy(obj, block);
|
|
309
|
+
return /** @type {RippleObject<T>} */ (proxy(obj, block));
|
|
308
310
|
}
|
|
309
311
|
|
|
310
312
|
/** @type {Set<PropertyKey>} */
|
|
@@ -228,6 +228,30 @@ describe('basic client > errors', () => {
|
|
|
228
228
|
}).toThrow('Do...while loops are not supported in components.');
|
|
229
229
|
});
|
|
230
230
|
|
|
231
|
+
it('should allow JSX fragments in TSRX templates as <tsx> shorthand', () => {
|
|
232
|
+
const code = `
|
|
233
|
+
export default component SafeProfile() {
|
|
234
|
+
<b><>{111}</></b>
|
|
235
|
+
}
|
|
236
|
+
`;
|
|
237
|
+
|
|
238
|
+
expect(() => {
|
|
239
|
+
compile(code, 'test.tsrx');
|
|
240
|
+
}).not.toThrow();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should allow JSX fragments inside tsx blocks', () => {
|
|
244
|
+
const code = `
|
|
245
|
+
export default component SafeProfile() {
|
|
246
|
+
<tsx><>{111}</></tsx>
|
|
247
|
+
}
|
|
248
|
+
`;
|
|
249
|
+
|
|
250
|
+
expect(() => {
|
|
251
|
+
compile(code, 'test.tsrx');
|
|
252
|
+
}).not.toThrow();
|
|
253
|
+
});
|
|
254
|
+
|
|
231
255
|
it('should not throw error for while loop inside a function within a component', () => {
|
|
232
256
|
const code = `
|
|
233
257
|
export default component App() {
|
|
@@ -74,7 +74,7 @@ describe('compiler > basics', () => {
|
|
|
74
74
|
}`;
|
|
75
75
|
|
|
76
76
|
expect(() => parse(invalid_source)).toThrow(
|
|
77
|
-
'"text" is a
|
|
77
|
+
'"text" is a TSRX keyword and must be used in the form {text some_value}',
|
|
78
78
|
);
|
|
79
79
|
});
|
|
80
80
|
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "../../tsconfig.json",
|
|
3
3
|
"include": ["../../src/**/*", "../**/*"],
|
|
4
|
-
"exclude": [
|
|
5
|
-
"../server",
|
|
6
|
-
"../server.d.ts",
|
|
7
|
-
"../setup-server.js",
|
|
8
|
-
"../hydration",
|
|
9
|
-
"../setup-hydration.js"
|
|
10
|
-
]
|
|
4
|
+
"exclude": ["../server", "../setup-server.js", "../hydration", "../setup-hydration.js"]
|
|
11
5
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { flushSync, track } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('tsx expression', () => {
|
|
4
|
-
it('renders a basic
|
|
4
|
+
it('renders a basic fragment shorthand element', () => {
|
|
5
5
|
component App() {
|
|
6
6
|
const el = <tsx><div>hello world</div></tsx>;
|
|
7
7
|
{el}
|
|
@@ -11,6 +11,56 @@ describe('tsx expression', () => {
|
|
|
11
11
|
expect(container.querySelector('div')).toBeTruthy();
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
+
it('applies scoped classes inside tsx blocks and fragment shorthand', () => {
|
|
15
|
+
component App() {
|
|
16
|
+
<tsx>
|
|
17
|
+
<div class="card">
|
|
18
|
+
<h2>
|
|
19
|
+
{'tsx block'}
|
|
20
|
+
</h2>
|
|
21
|
+
</div>
|
|
22
|
+
</tsx>
|
|
23
|
+
|
|
24
|
+
<>
|
|
25
|
+
<div class="card">
|
|
26
|
+
<h2>
|
|
27
|
+
{'fragment shorthand'}
|
|
28
|
+
</h2>
|
|
29
|
+
</div>
|
|
30
|
+
</>
|
|
31
|
+
|
|
32
|
+
<style>
|
|
33
|
+
.card {
|
|
34
|
+
padding: 1rem;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
h2 {
|
|
38
|
+
color: red;
|
|
39
|
+
}
|
|
40
|
+
</style>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
render(App);
|
|
44
|
+
|
|
45
|
+
const cards = Array.from(container.querySelectorAll('.card'));
|
|
46
|
+
const headings = Array.from(container.querySelectorAll('h2'));
|
|
47
|
+
|
|
48
|
+
expect(cards).toHaveLength(2);
|
|
49
|
+
expect(headings).toHaveLength(2);
|
|
50
|
+
|
|
51
|
+
cards.forEach((card) => {
|
|
52
|
+
expect(
|
|
53
|
+
Array.from(card.classList).filter((className) => className.startsWith('tsrx-')),
|
|
54
|
+
).toHaveLength(1);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
headings.forEach((heading) => {
|
|
58
|
+
expect(
|
|
59
|
+
Array.from(heading.classList).filter((className) => className.startsWith('tsrx-')),
|
|
60
|
+
).toHaveLength(1);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
14
64
|
it('renders a tsx element assigned to a variable', () => {
|
|
15
65
|
component App() {
|
|
16
66
|
const el = <tsx><span class="test">content</span></tsx>;
|
|
@@ -242,7 +292,7 @@ describe('tsx expression', () => {
|
|
|
242
292
|
expect(div.title).toBe('Item 1');
|
|
243
293
|
});
|
|
244
294
|
|
|
245
|
-
it('renders
|
|
295
|
+
it('renders fragment shorthand passed directly as component prop', () => {
|
|
246
296
|
component Wrapper(&{ content }: { content: any }) {
|
|
247
297
|
<div class="wrapper">{content}</div>
|
|
248
298
|
}
|
|
@@ -257,7 +307,7 @@ describe('tsx expression', () => {
|
|
|
257
307
|
expect(wrapper.textContent).toBe('direct prop');
|
|
258
308
|
});
|
|
259
309
|
|
|
260
|
-
it('renders
|
|
310
|
+
it('renders fragment shorthand passed directly as children prop', () => {
|
|
261
311
|
component Card(&{ title, children }: { title: any; children: any }) {
|
|
262
312
|
<div class="card">
|
|
263
313
|
<h2 class="card-title">{title}</h2>
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "../../tsconfig.json",
|
|
3
3
|
"include": ["../../src/**/*", "../**/*"],
|
|
4
|
-
"exclude": [
|
|
5
|
-
"../client",
|
|
6
|
-
"../client.d.ts",
|
|
7
|
-
"../setup-client.js",
|
|
8
|
-
"../server",
|
|
9
|
-
"../server.d.ts",
|
|
10
|
-
"../setup-server.js"
|
|
11
|
-
]
|
|
4
|
+
"exclude": ["../client", "../setup-client.js", "../server", "../setup-server.js"]
|
|
12
5
|
}
|
|
@@ -35,7 +35,9 @@ describe('basic server > attribute rendering', () => {
|
|
|
35
35
|
|
|
36
36
|
const div = document.querySelector('div');
|
|
37
37
|
|
|
38
|
-
expect(
|
|
38
|
+
expect(
|
|
39
|
+
Array.from(div.classList).filter((className) => className.startsWith('tsrx-')),
|
|
40
|
+
).toHaveLength(1);
|
|
39
41
|
expect(div.classList.contains('inactive')).toBe(true);
|
|
40
42
|
});
|
|
41
43
|
|
|
@@ -70,7 +72,9 @@ describe('basic server > attribute rendering', () => {
|
|
|
70
72
|
|
|
71
73
|
const div = document.querySelector('div');
|
|
72
74
|
|
|
73
|
-
expect(
|
|
75
|
+
expect(
|
|
76
|
+
Array.from(div.classList).filter((className) => className.startsWith('tsrx-')),
|
|
77
|
+
).toHaveLength(1);
|
|
74
78
|
|
|
75
79
|
expect(div.classList.contains('foo')).toBe(true);
|
|
76
80
|
expect(div.classList.contains('bar')).toBe(true);
|
|
@@ -83,6 +87,57 @@ describe('basic server > attribute rendering', () => {
|
|
|
83
87
|
expect(div.classList.contains('fff')).toBe(false);
|
|
84
88
|
});
|
|
85
89
|
|
|
90
|
+
it('applies scoped classes inside tsx blocks and fragment shorthand', async () => {
|
|
91
|
+
component App() {
|
|
92
|
+
<tsx>
|
|
93
|
+
<div class="card">
|
|
94
|
+
<h2>
|
|
95
|
+
{'tsx block'}
|
|
96
|
+
</h2>
|
|
97
|
+
</div>
|
|
98
|
+
</tsx>
|
|
99
|
+
|
|
100
|
+
<>
|
|
101
|
+
<div class="card">
|
|
102
|
+
<h2>
|
|
103
|
+
{'fragment shorthand'}
|
|
104
|
+
</h2>
|
|
105
|
+
</div>
|
|
106
|
+
</>
|
|
107
|
+
|
|
108
|
+
<style>
|
|
109
|
+
.card {
|
|
110
|
+
padding: 1rem;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
h2 {
|
|
114
|
+
color: red;
|
|
115
|
+
}
|
|
116
|
+
</style>
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const { body } = await render(App);
|
|
120
|
+
const { document } = parseHtml(body);
|
|
121
|
+
|
|
122
|
+
const cards = Array.from(document.querySelectorAll('.card'));
|
|
123
|
+
const headings = Array.from(document.querySelectorAll('h2'));
|
|
124
|
+
|
|
125
|
+
expect(cards).toHaveLength(2);
|
|
126
|
+
expect(headings).toHaveLength(2);
|
|
127
|
+
|
|
128
|
+
cards.forEach((card) => {
|
|
129
|
+
expect(
|
|
130
|
+
Array.from(card.classList).filter((className) => className.startsWith('tsrx-')),
|
|
131
|
+
).toHaveLength(1);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
headings.forEach((heading) => {
|
|
135
|
+
expect(
|
|
136
|
+
Array.from(heading.classList).filter((className) => className.startsWith('tsrx-')),
|
|
137
|
+
).toHaveLength(1);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
86
141
|
it('render dynamic class object', async () => {
|
|
87
142
|
component Basic() {
|
|
88
143
|
let &[active] = track(false);
|
|
@@ -101,7 +156,9 @@ describe('basic server > attribute rendering', () => {
|
|
|
101
156
|
|
|
102
157
|
const div = document.querySelector('div');
|
|
103
158
|
|
|
104
|
-
expect(
|
|
159
|
+
expect(
|
|
160
|
+
Array.from(div.classList).filter((className) => className.startsWith('tsrx-')),
|
|
161
|
+
).toHaveLength(1);
|
|
105
162
|
expect(div.classList.contains('inactive')).toBe(true);
|
|
106
163
|
expect(div.classList.contains('active')).toBe(false);
|
|
107
164
|
});
|
|
@@ -132,9 +189,9 @@ describe('basic server > attribute rendering', () => {
|
|
|
132
189
|
const divs = document.querySelectorAll('div');
|
|
133
190
|
|
|
134
191
|
divs.forEach((div) => {
|
|
135
|
-
expect(
|
|
136
|
-
|
|
137
|
-
);
|
|
192
|
+
expect(
|
|
193
|
+
Array.from(div.classList).filter((className) => className.startsWith('tsrx-')),
|
|
194
|
+
).toHaveLength(1);
|
|
138
195
|
});
|
|
139
196
|
},
|
|
140
197
|
);
|
|
@@ -204,7 +261,10 @@ describe('basic server > attribute rendering', () => {
|
|
|
204
261
|
|
|
205
262
|
it('render tracked object as style attribute', async () => {
|
|
206
263
|
component Basic() {
|
|
207
|
-
let style = new RippleObject({
|
|
264
|
+
let style = new RippleObject({
|
|
265
|
+
color: 'red',
|
|
266
|
+
fontWeight: 'bold',
|
|
267
|
+
});
|
|
208
268
|
|
|
209
269
|
<div style={{ color: style.color, fontWeight: style.fontWeight }}>{'Dynamic Style'}</div>
|
|
210
270
|
}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "../../tsconfig.json",
|
|
3
3
|
"include": ["../../src/**/*", "../**/*"],
|
|
4
|
-
"exclude": [
|
|
5
|
-
"../client",
|
|
6
|
-
"../client.d.ts",
|
|
7
|
-
"../setup-client.js",
|
|
8
|
-
"../hydration",
|
|
9
|
-
"../hydration.d.ts",
|
|
10
|
-
"../setup-hydration.js"
|
|
11
|
-
]
|
|
4
|
+
"exclude": ["../client", "../setup-client.js", "../hydration", "../setup-hydration.js"]
|
|
12
5
|
}
|
package/tsconfig.json
CHANGED
|
@@ -22,13 +22,6 @@
|
|
|
22
22
|
"rollup/*": ["./shims/rollup-estree-types.d.ts"]
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
|
-
"include": [
|
|
26
|
-
"./*.js",
|
|
27
|
-
"./src/",
|
|
28
|
-
"./tests/**/*.test.tsrx",
|
|
29
|
-
"./tests/**/*.tsrx",
|
|
30
|
-
"./tests/**/*.d.ts",
|
|
31
|
-
"./tests/**/*.js"
|
|
32
|
-
],
|
|
25
|
+
"include": ["./*.js", "./src/"],
|
|
33
26
|
"exclude": ["node_modules", "dist"]
|
|
34
27
|
}
|
package/tsconfig.typecheck.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -285,7 +285,7 @@ export interface RippleObjectCallable {
|
|
|
285
285
|
export interface RippleObjectConstructor {
|
|
286
286
|
new <T extends Object>(obj: T): RippleObject<T>;
|
|
287
287
|
}
|
|
288
|
-
export
|
|
288
|
+
export type RippleObject<T> = { [K in keyof T]: T[K] };
|
|
289
289
|
export const RippleObject: RippleObjectConstructor;
|
|
290
290
|
|
|
291
291
|
export interface RippleDateCallable {
|