ripple 0.2.208 → 0.2.210
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 +43 -0
- package/README.md +2 -1
- package/package.json +2 -6
- package/shims/rollup-estree-types.d.ts +1 -1
- package/src/compiler/index.d.ts +1 -0
- package/src/compiler/index.js +7 -1
- package/src/compiler/phases/1-parse/index.js +15 -6
- package/src/compiler/phases/2-analyze/css-analyze.js +100 -104
- package/src/compiler/phases/2-analyze/index.js +215 -2
- package/src/compiler/phases/3-transform/client/index.js +388 -50
- package/src/compiler/phases/3-transform/segments.js +123 -39
- package/src/compiler/phases/3-transform/server/index.js +266 -13
- package/src/compiler/types/index.d.ts +16 -3
- package/src/compiler/utils.js +1 -15
- package/src/constants.js +0 -2
- package/src/helpers.d.ts +4 -0
- package/src/html-tree-validation.js +211 -0
- package/src/jsx-runtime.d.ts +260 -259
- package/src/jsx-runtime.js +12 -12
- package/src/runtime/array.js +17 -17
- package/src/runtime/create-subscriber.js +1 -1
- package/src/runtime/index-client.js +1 -5
- package/src/runtime/index-server.js +15 -0
- package/src/runtime/internal/client/compat.js +3 -3
- package/src/runtime/internal/client/composite.js +6 -1
- package/src/runtime/internal/client/head.js +50 -4
- package/src/runtime/internal/client/html.js +73 -12
- package/src/runtime/internal/client/hydration.js +12 -0
- package/src/runtime/internal/client/index.js +1 -1
- package/src/runtime/internal/client/portal.js +54 -29
- package/src/runtime/internal/client/rpc.js +3 -1
- package/src/runtime/internal/client/switch.js +5 -0
- package/src/runtime/internal/client/template.js +117 -11
- package/src/runtime/internal/client/try.js +1 -0
- package/src/runtime/internal/server/index.js +113 -1
- package/src/runtime/internal/server/rpc.js +4 -4
- package/src/runtime/map.js +2 -2
- package/src/runtime/object.js +6 -6
- package/src/runtime/proxy.js +12 -11
- package/src/runtime/reactive-value.js +9 -1
- package/src/runtime/set.js +12 -7
- package/src/runtime/url-search-params.js +0 -1
- package/src/server/index.js +4 -0
- package/src/utils/hashing.js +15 -0
- package/src/utils/normalize_css_property_name.js +1 -1
- package/tests/client/array/array.mutations.test.ripple +8 -8
- package/tests/client/basic/basic.errors.test.ripple +28 -0
- package/tests/client/basic/basic.events.test.ripple +6 -3
- package/tests/client/basic/basic.utilities.test.ripple +1 -1
- package/tests/client/compiler/compiler.regex.test.ripple +10 -8
- package/tests/client/composite/composite.generics.test.ripple +5 -2
- package/tests/client/dynamic-elements.test.ripple +30 -1
- package/tests/client/function-overload-import.ripple +6 -7
- package/tests/client/html.test.ripple +0 -1
- package/tests/client/object.test.ripple +2 -2
- package/tests/client/portal.test.ripple +3 -3
- package/tests/client/return.test.ripple +2500 -0
- package/tests/client/try.test.ripple +69 -0
- package/tests/client/typescript-generics.test.ripple +1 -1
- package/tests/client/url/url.derived.test.ripple +1 -1
- package/tests/client/url/url.parsing.test.ripple +3 -3
- package/tests/client/url/url.partial-removal.test.ripple +7 -7
- package/tests/client/url/url.reactivity.test.ripple +15 -15
- package/tests/client/url/url.serialization.test.ripple +2 -2
- package/tests/hydration/basic.test.js +23 -0
- package/tests/hydration/build-components.js +10 -4
- package/tests/hydration/compiled/client/basic.js +165 -3
- package/tests/hydration/compiled/client/for.js +1140 -23
- package/tests/hydration/compiled/client/head.js +234 -0
- package/tests/hydration/compiled/client/html.js +135 -0
- package/tests/hydration/compiled/client/portal.js +172 -0
- package/tests/hydration/compiled/client/reactivity.js +3 -1
- package/tests/hydration/compiled/client/return.js +1976 -0
- package/tests/hydration/compiled/client/switch.js +162 -0
- package/tests/hydration/compiled/server/basic.js +249 -0
- package/tests/hydration/compiled/server/events.js +1 -1
- package/tests/hydration/compiled/server/for.js +891 -1
- package/tests/hydration/compiled/server/head.js +291 -0
- package/tests/hydration/compiled/server/html.js +133 -0
- package/tests/hydration/compiled/server/if.js +1 -1
- package/tests/hydration/compiled/server/portal.js +250 -0
- package/tests/hydration/compiled/server/reactivity.js +1 -1
- package/tests/hydration/compiled/server/return.js +1969 -0
- package/tests/hydration/compiled/server/switch.js +130 -0
- package/tests/hydration/components/basic.ripple +55 -0
- package/tests/hydration/components/for.ripple +403 -0
- package/tests/hydration/components/head.ripple +111 -0
- package/tests/hydration/components/html.ripple +38 -0
- package/tests/hydration/components/portal.ripple +49 -0
- package/tests/hydration/components/return.ripple +564 -0
- package/tests/hydration/components/switch.ripple +51 -0
- package/tests/hydration/for.test.js +363 -0
- package/tests/hydration/head.test.js +105 -0
- package/tests/hydration/html.test.js +46 -0
- package/tests/hydration/portal.test.js +71 -0
- package/tests/hydration/return.test.js +544 -0
- package/tests/hydration/switch.test.js +42 -0
- package/tests/server/basic.attributes.test.ripple +1 -1
- package/tests/server/compiler.test.ripple +22 -0
- package/tests/server/composite.test.ripple +5 -2
- package/tests/server/html-nesting-validation.test.ripple +237 -0
- package/tests/server/return.test.ripple +1379 -0
- package/tests/setup-hydration.js +6 -1
- package/tests/utils/escaping.test.js +3 -1
- package/tests/utils/normalize_css_property_name.test.js +0 -1
- package/tests/utils/patterns.test.js +6 -2
- package/tests/utils/sanitize_template_string.test.js +3 -2
- package/types/server.d.ts +16 -0
package/src/helpers.d.ts
CHANGED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map of elements that have certain elements that are not allowed inside them, in the sense that they will auto-close the parent/ancestor element.
|
|
3
|
+
* Theoretically one could take advantage of it but most of the time it will just result in confusing behavior and break when SSR'd.
|
|
4
|
+
* There are more elements that are invalid inside other elements, but they're not auto-closed and so don't break SSR and are therefore not listed here.
|
|
5
|
+
* Based on Svelte's html-tree-validation.js (https://github.com/sveltejs/svelte/blob/main/packages/svelte/src/html-tree-validation.js)
|
|
6
|
+
* @type {Record<string, { direct: string[]} | { descendant: string[]; reset_by?: string[] }>}
|
|
7
|
+
*/
|
|
8
|
+
const autoclosing_children = {
|
|
9
|
+
// based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
|
|
10
|
+
li: { direct: ['li'] },
|
|
11
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt#technical_summary
|
|
12
|
+
dt: { descendant: ['dt', 'dd'], reset_by: ['dl'] },
|
|
13
|
+
dd: { descendant: ['dt', 'dd'], reset_by: ['dl'] },
|
|
14
|
+
p: {
|
|
15
|
+
descendant: [
|
|
16
|
+
'address',
|
|
17
|
+
'article',
|
|
18
|
+
'aside',
|
|
19
|
+
'blockquote',
|
|
20
|
+
'div',
|
|
21
|
+
'dl',
|
|
22
|
+
'fieldset',
|
|
23
|
+
'footer',
|
|
24
|
+
'form',
|
|
25
|
+
'h1',
|
|
26
|
+
'h2',
|
|
27
|
+
'h3',
|
|
28
|
+
'h4',
|
|
29
|
+
'h5',
|
|
30
|
+
'h6',
|
|
31
|
+
'header',
|
|
32
|
+
'hgroup',
|
|
33
|
+
'hr',
|
|
34
|
+
'main',
|
|
35
|
+
'menu',
|
|
36
|
+
'nav',
|
|
37
|
+
'ol',
|
|
38
|
+
'p',
|
|
39
|
+
'pre',
|
|
40
|
+
'section',
|
|
41
|
+
'table',
|
|
42
|
+
'ul',
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
rt: { descendant: ['rt', 'rp'] },
|
|
46
|
+
rp: { descendant: ['rt', 'rp'] },
|
|
47
|
+
optgroup: { descendant: ['optgroup'] },
|
|
48
|
+
option: { descendant: ['option', 'optgroup'] },
|
|
49
|
+
thead: { direct: ['tbody', 'tfoot'] },
|
|
50
|
+
tbody: { direct: ['tbody', 'tfoot'] },
|
|
51
|
+
tfoot: { direct: ['tbody'] },
|
|
52
|
+
tr: { direct: ['tr', 'tbody'] },
|
|
53
|
+
td: { direct: ['td', 'th', 'tr'] },
|
|
54
|
+
th: { direct: ['td', 'th', 'tr'] },
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Map of elements that have certain elements that are not allowed inside them, in the sense that the browser will somehow repair the HTML.
|
|
59
|
+
* There are more elements that are invalid inside other elements, but they're not repaired and so don't break SSR and are therefore not listed here.
|
|
60
|
+
* @type {Record<string, { direct: string[]} | { descendant: string[]; reset_by?: string[]; only?: string[] } | { only: string[] }>}
|
|
61
|
+
*/
|
|
62
|
+
const disallowed_children = {
|
|
63
|
+
...autoclosing_children,
|
|
64
|
+
form: { descendant: ['form'] },
|
|
65
|
+
a: { descendant: ['a'] },
|
|
66
|
+
button: { descendant: ['button'] },
|
|
67
|
+
h1: { descendant: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] },
|
|
68
|
+
h2: { descendant: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] },
|
|
69
|
+
h3: { descendant: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] },
|
|
70
|
+
h4: { descendant: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] },
|
|
71
|
+
h5: { descendant: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] },
|
|
72
|
+
h6: { descendant: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] },
|
|
73
|
+
|
|
74
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
|
|
75
|
+
tr: { only: ['th', 'td', 'style', 'script', 'template'] },
|
|
76
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
|
|
77
|
+
tbody: { only: ['tr', 'style', 'script', 'template'] },
|
|
78
|
+
thead: { only: ['tr', 'style', 'script', 'template'] },
|
|
79
|
+
tfoot: { only: ['tr', 'style', 'script', 'template'] },
|
|
80
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
|
|
81
|
+
colgroup: { only: ['col', 'template'] },
|
|
82
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
|
|
83
|
+
table: {
|
|
84
|
+
only: ['caption', 'colgroup', 'tbody', 'thead', 'tfoot', 'style', 'script', 'template'],
|
|
85
|
+
},
|
|
86
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
|
|
87
|
+
head: {
|
|
88
|
+
only: [
|
|
89
|
+
'base',
|
|
90
|
+
'basefont',
|
|
91
|
+
'bgsound',
|
|
92
|
+
'link',
|
|
93
|
+
'meta',
|
|
94
|
+
'title',
|
|
95
|
+
'noscript',
|
|
96
|
+
'noframes',
|
|
97
|
+
'style',
|
|
98
|
+
'script',
|
|
99
|
+
'template',
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
// https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
|
|
103
|
+
html: { only: ['head', 'body', 'frameset'] },
|
|
104
|
+
frameset: { only: ['frame'] },
|
|
105
|
+
'#document': { only: ['html'] },
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Returns an error message if the tag is not allowed inside the ancestor tag (which is grandparent and above) such that it will result
|
|
110
|
+
* in the browser repairing the HTML, which will likely result in an error during hydration.
|
|
111
|
+
* @param {string} child_tag
|
|
112
|
+
* @param {string[]} ancestors All nodes starting with the parent, up until the ancestor, which means two entries minimum
|
|
113
|
+
* @param {string} [child_loc]
|
|
114
|
+
* @param {string} [ancestor_loc]
|
|
115
|
+
* @returns {string | null}
|
|
116
|
+
*/
|
|
117
|
+
export function is_tag_valid_with_ancestor(child_tag, ancestors, child_loc, ancestor_loc) {
|
|
118
|
+
if (child_tag.includes('-')) return null; // custom elements can be anything
|
|
119
|
+
|
|
120
|
+
const ancestor_tag = ancestors[ancestors.length - 1];
|
|
121
|
+
const disallowed = disallowed_children[ancestor_tag];
|
|
122
|
+
if (!disallowed) return null;
|
|
123
|
+
|
|
124
|
+
if ('reset_by' in disallowed && disallowed.reset_by) {
|
|
125
|
+
for (let i = ancestors.length - 2; i >= 0; i--) {
|
|
126
|
+
const ancestor = ancestors[i];
|
|
127
|
+
if (ancestor.includes('-')) return null; // custom elements can be anything
|
|
128
|
+
|
|
129
|
+
// A reset means that forbidden descendants are allowed again
|
|
130
|
+
if (disallowed.reset_by.includes(ancestors[i])) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if ('descendant' in disallowed && disallowed.descendant.includes(child_tag)) {
|
|
137
|
+
const child = child_loc ? `\`<${child_tag}>\` (${child_loc})` : `\`<${child_tag}>\``;
|
|
138
|
+
const ancestor = ancestor_loc
|
|
139
|
+
? `\`<${ancestor_tag}>\` (${ancestor_loc})`
|
|
140
|
+
: `\`<${ancestor_tag}>\``;
|
|
141
|
+
|
|
142
|
+
return `${child} cannot be a descendant of ${ancestor}`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Returns an error message if the tag is not allowed inside the parent tag such that it will result
|
|
150
|
+
* in the browser repairing the HTML, which will likely result in an error during hydration.
|
|
151
|
+
* @param {string} child_tag
|
|
152
|
+
* @param {string} parent_tag
|
|
153
|
+
* @param {string} [child_loc]
|
|
154
|
+
* @param {string} [parent_loc]
|
|
155
|
+
* @returns {string | null}
|
|
156
|
+
*/
|
|
157
|
+
export function is_tag_valid_with_parent(child_tag, parent_tag, child_loc, parent_loc) {
|
|
158
|
+
if (child_tag.includes('-') || parent_tag?.includes('-')) return null; // custom elements can be anything
|
|
159
|
+
|
|
160
|
+
if (parent_tag === 'template') return null; // no errors or warning should be thrown in immediate children of template tags
|
|
161
|
+
|
|
162
|
+
const disallowed = disallowed_children[parent_tag];
|
|
163
|
+
|
|
164
|
+
const child = child_loc ? `\`<${child_tag}>\` (${child_loc})` : `\`<${child_tag}>\``;
|
|
165
|
+
const parent = parent_loc ? `\`<${parent_tag}>\` (${parent_loc})` : `\`<${parent_tag}>\``;
|
|
166
|
+
|
|
167
|
+
if (disallowed) {
|
|
168
|
+
if ('direct' in disallowed && disallowed.direct.includes(child_tag)) {
|
|
169
|
+
return `${child} cannot be a direct child of ${parent}`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if ('descendant' in disallowed && disallowed.descendant.includes(child_tag)) {
|
|
173
|
+
return `${child} cannot be a child of ${parent}`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if ('only' in disallowed && disallowed.only) {
|
|
177
|
+
if (disallowed.only.includes(child_tag)) {
|
|
178
|
+
return null;
|
|
179
|
+
} else {
|
|
180
|
+
return `${child} cannot be a child of ${parent}. \`<${parent_tag}>\` only allows these children: ${disallowed.only.map((d) => `\`<${d}>\``).join(', ')}`;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// These tags are only valid with a few parents that have special child
|
|
186
|
+
// parsing rules - if we're down here, then none of those matched and
|
|
187
|
+
// so we allow it only if we don't know what the parent is, as all other
|
|
188
|
+
// cases are invalid (and we only get into this function if we know the parent).
|
|
189
|
+
switch (child_tag) {
|
|
190
|
+
case 'body':
|
|
191
|
+
case 'caption':
|
|
192
|
+
case 'col':
|
|
193
|
+
case 'colgroup':
|
|
194
|
+
case 'frameset':
|
|
195
|
+
case 'frame':
|
|
196
|
+
case 'head':
|
|
197
|
+
case 'html':
|
|
198
|
+
return `${child} cannot be a child of ${parent}`;
|
|
199
|
+
case 'thead':
|
|
200
|
+
case 'tbody':
|
|
201
|
+
case 'tfoot':
|
|
202
|
+
return `${child} must be the child of a \`<table>\`, not a ${parent}`;
|
|
203
|
+
case 'td':
|
|
204
|
+
case 'th':
|
|
205
|
+
return `${child} must be the child of a \`<tr>\`, not a ${parent}`;
|
|
206
|
+
case 'tr':
|
|
207
|
+
return `${child} must be the child of a \`<thead>\`, \`<tbody>\`, or \`<tfoot>\`, not a ${parent}`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return null;
|
|
211
|
+
}
|