Skip to content

Commit 93cfa6c

Browse files
fix: add css hash to custom element rendered with svelte:element (#12715)
* fix: add css hash to custom element rendered with `svelte:element` * simplify * skip arg where possible * drive-by improvements — remove some unnecessary arguments where possible --------- Co-authored-by: Rich Harris <rich.harris@vercel.com>
1 parent 8e04a91 commit 93cfa6c

File tree

6 files changed

+53
-23
lines changed

6 files changed

+53
-23
lines changed

.changeset/chilly-carpets-switch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: add css hash to custom element rendered with `svelte:element`

packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -470,10 +470,8 @@ function build_element_spread_attributes(
470470
attribute.type === 'SpreadAttribute' && attribute.metadata.expression.has_call;
471471
}
472472

473-
const lowercase_attributes =
474-
element.metadata.svg || element.metadata.mathml || is_custom_element_node(element)
475-
? b.false
476-
: b.true;
473+
const preserve_attribute_case =
474+
element.metadata.svg || element.metadata.mathml || is_custom_element_node(element);
477475
const id = context.state.scope.generate('attributes');
478476

479477
const update = b.stmt(
@@ -485,8 +483,8 @@ function build_element_spread_attributes(
485483
element_id,
486484
b.id(id),
487485
b.object(values),
488-
lowercase_attributes,
489-
b.literal(context.state.analysis.css.hash),
486+
context.state.analysis.css.hash !== '' && b.literal(context.state.analysis.css.hash),
487+
preserve_attribute_case && b.true,
490488
is_ignored(element, 'hydration_attribute_changed') && b.true
491489
)
492490
)

packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ function build_dynamic_element_attributes(attributes, context, element_id) {
200200
element_id,
201201
b.id(id),
202202
b.object(values),
203-
b.literal(context.state.analysis.css.hash)
203+
context.state.analysis.css.hash !== '' && b.literal(context.state.analysis.css.hash)
204204
)
205205
)
206206
);
@@ -221,7 +221,7 @@ function build_dynamic_element_attributes(attributes, context, element_id) {
221221
element_id,
222222
b.literal(null),
223223
b.object(values),
224-
b.literal(context.state.analysis.css.hash)
224+
context.state.analysis.css.hash !== '' && b.literal(context.state.analysis.css.hash)
225225
)
226226
)
227227
);

packages/svelte/src/internal/client/dom/elements/attributes.js

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,19 @@ export function set_custom_element_data(node, prop, value) {
147147
* @param {Element & ElementCSSInlineStyle} element
148148
* @param {Record<string, any> | undefined} prev
149149
* @param {Record<string, any>} next New attributes - this function mutates this object
150-
* @param {boolean} lowercase_attributes
151-
* @param {string} css_hash
150+
* @param {string} [css_hash]
151+
* @param {boolean} preserve_attribute_case
152152
* @param {boolean} [skip_warning]
153153
* @returns {Record<string, any>}
154154
*/
155-
export function set_attributes(element, prev, next, lowercase_attributes, css_hash, skip_warning) {
156-
var has_hash = css_hash.length !== 0;
155+
export function set_attributes(
156+
element,
157+
prev,
158+
next,
159+
css_hash,
160+
preserve_attribute_case = false,
161+
skip_warning
162+
) {
157163
var current = prev || {};
158164
var is_option_element = element.tagName === 'OPTION';
159165

@@ -163,8 +169,8 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha
163169
}
164170
}
165171

166-
if (has_hash && !next.class) {
167-
next.class = '';
172+
if (css_hash !== undefined) {
173+
next.class = next.class ? next.class + ' ' + css_hash : css_hash;
168174
}
169175

170176
var setters = setters_cache.get(element.nodeName);
@@ -267,7 +273,7 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha
267273
element.value = element[key] = element.__value = value;
268274
} else {
269275
var name = key;
270-
if (lowercase_attributes) {
276+
if (!preserve_attribute_case) {
271277
name = normalize_attribute(name);
272278
}
273279

@@ -279,11 +285,6 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha
279285
element[name] = value;
280286
}
281287
} else if (typeof value !== 'function') {
282-
if (has_hash && name === 'class') {
283-
if (value) value += ' ';
284-
value += css_hash;
285-
}
286-
287288
set_attribute(element, name, value);
288289
}
289290
}
@@ -309,7 +310,7 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha
309310
* @param {Element} node
310311
* @param {Record<string, any> | undefined} prev
311312
* @param {Record<string, any>} next The new attributes - this function mutates this object
312-
* @param {string} css_hash
313+
* @param {string} [css_hash]
313314
*/
314315
export function set_dynamic_element_attributes(node, prev, next, css_hash) {
315316
if (node.tagName.includes('-')) {
@@ -319,6 +320,10 @@ export function set_dynamic_element_attributes(node, prev, next, css_hash) {
319320
}
320321
}
321322

323+
if (css_hash !== undefined) {
324+
next.class = next.class ? next.class + ' ' + css_hash : css_hash;
325+
}
326+
322327
for (key in next) {
323328
set_custom_element_data(node, key, next[key]);
324329
}
@@ -330,8 +335,8 @@ export function set_dynamic_element_attributes(node, prev, next, css_hash) {
330335
/** @type {Element & ElementCSSInlineStyle} */ (node),
331336
prev,
332337
next,
333-
node.namespaceURI !== NAMESPACE_SVG,
334-
css_hash
338+
css_hash,
339+
node.namespaceURI !== NAMESPACE_SVG
335340
);
336341
}
337342

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ok, test } from '../../test';
2+
3+
export default test({
4+
html: `<custom-element class="red svelte-p153w3"></custom-element><custom-element class="red svelte-p153w3"></custom-element>`,
5+
6+
async test({ assert, target }) {
7+
const [el, el2] = target.querySelectorAll('custom-element');
8+
ok(el);
9+
ok(el2);
10+
11+
assert.deepEqual(el.className, 'red svelte-p153w3');
12+
assert.deepEqual(el2.className, 'red svelte-p153w3');
13+
}
14+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<svelte:element this={'custom-element'} class="red"></svelte:element>
2+
<custom-element class="red"></custom-element>
3+
4+
<style>
5+
.red {
6+
color: red;
7+
}
8+
</style>

0 commit comments

Comments
 (0)