Skip to content

Commit 3c4fe63

Browse files
authored
(fix) better transform of custom css properties (#1024)
Transform instead of delete to ensure better DX (correct mappings) and to not break if the property value does contain for example a store which leads to a inner transform. #1023 #974
1 parent 81f61e5 commit 3c4fe63

File tree

8 files changed

+51
-14
lines changed

8 files changed

+51
-14
lines changed

packages/svelte2tsx/src/htmlxtojsx/nodes/attribute.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ export function handleAttribute(
8282
}
8383
}
8484

85-
// Custom property -> remove completely due to JSX incompatibility
86-
if (parent.type === 'InlineComponent' && attr.name.startsWith('--')) {
87-
str.overwrite(attr.start, attr.end, '', { contentOnly: true });
85+
// Custom CSS property
86+
if (parent.type === 'InlineComponent' && attr.name.startsWith('--') && attr.value !== true) {
87+
str.prependRight(attr.start, '{...__sveltets_cssProp({"');
88+
buildTemplateString(attr, str, htmlx, '": `', '`})}');
8889
return;
8990
}
9091

@@ -169,23 +170,30 @@ export function handleAttribute(
169170
return;
170171
}
171172

172-
// we have multiple attribute values, so we build a string out of them.
173-
// technically the user can do something funky like attr="text "{value} or even attr=text{value}
174-
// so instead of trying to maintain a nice sourcemap with prepends etc, we just overwrite the whole thing
173+
// We have multiple attribute values, so we build a template string out of them.
174+
buildTemplateString(attr, str, htmlx, '={`', '`}');
175+
}
175176

177+
function buildTemplateString(
178+
attr: Attribute,
179+
str: MagicString,
180+
htmlx: string,
181+
leadingOverride: string,
182+
trailingOverride: string
183+
) {
176184
const equals = htmlx.lastIndexOf('=', attr.value[0].start);
177-
str.overwrite(equals, attr.value[0].start, '={`');
185+
str.overwrite(equals, attr.value[0].start, leadingOverride);
178186

179-
for (const n of attr.value) {
187+
for (const n of attr.value as BaseNode[]) {
180188
if (n.type == 'MustacheTag') {
181189
str.appendRight(n.start, '$');
182190
}
183191
}
184192

185193
if (isQuote(htmlx[attr.end - 1])) {
186-
str.overwrite(attr.end - 1, attr.end, '`}');
194+
str.overwrite(attr.end - 1, attr.end, trailingOverride);
187195
} else {
188-
str.appendLeft(attr.end, '`}');
196+
str.appendLeft(attr.end, trailingOverride);
189197
}
190198
}
191199

packages/svelte2tsx/svelte-shims.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ declare function __sveltets_ensureAction(actionCall: SvelteActionReturnType): {}
105105
declare function __sveltets_ensureTransition(transitionCall: SvelteTransitionReturnType): {};
106106
declare function __sveltets_ensureFunction(expression: (e: Event & { detail?: any }) => unknown ): {};
107107
declare function __sveltets_ensureType<T>(type: AConstructorTypeOf<T>, el: T): {};
108+
declare function __sveltets_cssProp(prop: Record<string, any>): {};
108109
declare function __sveltets_ctorOf<T>(type: T): AConstructorTypeOf<T>;
109110
declare function __sveltets_instanceOf<T = any>(type: AConstructorTypeOf<T>): T;
110111
declare function __sveltets_allPropsType(): SvelteAllProps

packages/svelte2tsx/test/htmlx2jsx/samples/component-slot-infer-props/expected.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<><Parent bare shorthand={shorthand} text1="val1" text2="val2" text3={`a${a}b${b}`} textEmpty="" literal={true} strLiteral={'foo'} complex={{a}} a-dashed-complex={{a}} >{() => {/*Ωignore_startΩ*/const Ψcomplex={a},Ψa_dashed_complex={a};/*Ωignore_endΩ*/() => { let {foo} = /*Ωignore_startΩ*/new Parent({target: __sveltets_any(''), props: {'bare':true, 'shorthand':shorthand, 'text1':"", 'text2':"", 'text3':"", 'textEmpty':"", 'literal':true, 'strLiteral':"", 'complex':Ψcomplex, 'a-dashed-complex':Ψa_dashed_complex}})/*Ωignore_endΩ*/.$$slot_def['default'];<>
1+
<><Parent bare shorthand={shorthand} text1="val1" text2="val2" text3={`a${a}b${b}`} textEmpty="" literal={true} strLiteral={'foo'} complex={{a}} a-dashed-complex={{a}} {...__sveltets_cssProp({"--custom-cssprop": `foo`})} >{() => {/*Ωignore_startΩ*/const Ψcomplex={a},Ψa_dashed_complex={a};/*Ωignore_endΩ*/() => { let {foo} = /*Ωignore_startΩ*/new Parent({target: __sveltets_any(''), props: {'bare':true, 'shorthand':shorthand, 'text1':"", 'text2':"", 'text3':"", 'textEmpty':"", 'literal':true, 'strLiteral':"", 'complex':Ψcomplex, 'a-dashed-complex':Ψa_dashed_complex}})/*Ωignore_endΩ*/.$$slot_def['default'];<>
22
{() => { let {bar} = /*Ωignore_startΩ*/new Parent({target: __sveltets_any(''), props: {'bare':true, 'shorthand':shorthand, 'text1':"", 'text2':"", 'text3':"", 'textEmpty':"", 'literal':true, 'strLiteral':"", 'complex':Ψcomplex, 'a-dashed-complex':Ψa_dashed_complex}})/*Ωignore_endΩ*/.$$slot_def['named'];<><Component >
33
{foo} {bar}
44
</Component></>}}
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
<><Component betweenprop /></>
1+
<><Component
2+
{...__sveltets_cssProp({"--custom-css-property1": `${'hi'}`})}
3+
{...__sveltets_cssProp({"--custom-css-property2": `hi`})}
4+
betweenprop
5+
{...__sveltets_cssProp({"--custom-css-property3": `hi${jo}hi`})}
6+
{...__sveltets_cssProp({"--custom-css-property4": `hi${jo}hi`})}
7+
{...__sveltets_cssProp({"--custom-css-property5": `hi${jo}hi`})} /></>
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
<Component --custom-css-property1={'hi'} --custom-css-property2="hi" betweenprop --custom-css-property3="hi{jo}hi" />
1+
<Component
2+
--custom-css-property1={'hi'}
3+
--custom-css-property2="hi"
4+
betweenprop
5+
--custom-css-property3="hi{jo}hi"
6+
--custom-css-property4='hi{jo}hi'
7+
--custom-css-property5=hi{jo}hi />
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<><Component bare shorthand={shorthand} text1="val1" text2="val2" text3={`a${a}b${b}`} textEmpty="" literal={true} strLiteral={'foo'} complex={{a}} a-dashed-complex={{a}} />{/*Ωignore_startΩ*/new Component({target: __sveltets_any(''), props: {'bare':true, 'shorthand':shorthand, 'text1':"", 'text2':"", 'text3':"", 'textEmpty':"", 'literal':true, 'strLiteral':"", 'complex':{a}, 'a-dashed-complex':{a}}})/*Ωignore_endΩ*/.$on('click', e => e)}</>
1+
<><Component bare shorthand={shorthand} text1="val1" text2="val2" text3={`a${a}b${b}`} textEmpty="" literal={true} strLiteral={'foo'} complex={{a}} a-dashed-complex={{a}} {...__sveltets_cssProp({"--custom-cssprop": `foo`})} />{/*Ωignore_startΩ*/new Component({target: __sveltets_any(''), props: {'bare':true, 'shorthand':shorthand, 'text1':"", 'text2':"", 'text3':"", 'textEmpty':"", 'literal':true, 'strLiteral':"", 'complex':{a}, 'a-dashed-complex':{a}}})/*Ωignore_endΩ*/.$on('click', e => e)}</>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
///<reference types="svelte" />
2+
<></>;function render() {
3+
<><Component
4+
{...__sveltets_cssProp({"--custom-css-property1": `${(__sveltets_store_get(jo), $jo)}`})}
5+
{...__sveltets_cssProp({"--custom-css-property2": `hi${(__sveltets_store_get(jo), $jo)}hi`})}
6+
{...__sveltets_cssProp({"--custom-css-property3": `hi${(__sveltets_store_get(jo), $jo)}hi`})}
7+
{...__sveltets_cssProp({"--custom-css-property4": `hi${(__sveltets_store_get(jo), $jo)}hi`})} /></>
8+
return { props: {}, slots: {}, getters: {}, events: {} }}
9+
10+
export default class Input__SvelteComponent_ extends createSvelte2TsxComponent(__sveltets_partial(__sveltets_with_any_event(render))) {
11+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<Component
2+
--custom-css-property1={$jo}
3+
--custom-css-property2="hi{$jo}hi"
4+
--custom-css-property3='hi{$jo}hi'
5+
--custom-css-property4=hi{$jo}hi />

0 commit comments

Comments
 (0)