@@ -12,13 +12,14 @@ import type {
1212 SvelteTransitionDirective ,
1313 SvelteStartTag ,
1414 SvelteName ,
15+ SvelteStyleDirective ,
1516} from "../../ast"
1617import type ESTree from "estree"
1718import type { Context } from "../../context"
1819import type * as SvAST from "../svelte-ast-types"
1920import { getWithLoc , indexOf } from "./common"
2021import { convertMustacheTag } from "./mustache"
21- import { convertTextToLiteral } from "./text"
22+ import { convertTemplateLiteralToLiteral , convertTextToLiteral } from "./text"
2223import { ParseError } from "../../errors"
2324import type { ScriptLetCallback } from "../../context/script-let"
2425
@@ -54,6 +55,10 @@ export function* convertAttributes(
5455 yield convertClassDirective ( attr , parent , ctx )
5556 continue
5657 }
58+ if ( attr . type === "Style" ) {
59+ yield convertStyleDirective ( attr , parent , ctx )
60+ continue
61+ }
5762 if ( attr . type === "Transition" ) {
5863 yield convertTransitionDirective ( attr , parent , ctx )
5964 continue
@@ -284,6 +289,79 @@ function convertClassDirective(
284289 return directive
285290}
286291
292+ /** Convert for Style Directive */
293+ function convertStyleDirective (
294+ node : SvAST . DirectiveForExpression ,
295+ parent : SvelteDirective [ "parent" ] ,
296+ ctx : Context ,
297+ ) : SvelteStyleDirective {
298+ const directive : SvelteStyleDirective = {
299+ type : "SvelteDirective" ,
300+ kind : "Style" ,
301+ key : null as any ,
302+ expression : null ,
303+ parent,
304+ ...ctx . getConvertLocation ( node ) ,
305+ }
306+ if ( processStyleDirectiveValue ( node , ctx ) ) {
307+ processDirective ( node , directive , ctx , ( expression ) => {
308+ directive . expression = convertTemplateLiteralToLiteral (
309+ expression ,
310+ directive ,
311+ ctx ,
312+ )
313+ return [ ]
314+ } )
315+ } else {
316+ processDirective ( node , directive , ctx , ( expression ) => {
317+ return ctx . scriptLet . addExpression ( expression , directive )
318+ } )
319+ }
320+
321+ return directive
322+ }
323+
324+ /** Process plain value */
325+ function processStyleDirectiveValue (
326+ node : SvAST . DirectiveForExpression ,
327+ ctx : Context ,
328+ ) : node is SvAST . DirectiveForExpression & {
329+ expression : ESTree . TemplateLiteral
330+ } {
331+ const { expression } = node
332+ if (
333+ ! expression ||
334+ expression . type !== "TemplateLiteral" ||
335+ expression . expressions . length !== 0
336+ ) {
337+ return false
338+ }
339+ const quasi = expression . quasis [ 0 ]
340+ if ( quasi . value . cooked != null ) {
341+ return false
342+ }
343+ const eqIndex = ctx . code . indexOf ( "=" , node . start )
344+ if ( eqIndex < 0 || eqIndex >= node . end ) {
345+ return false
346+ }
347+ const valueIndex = ctx . code . indexOf ( quasi . value . raw , eqIndex + 1 )
348+ if ( valueIndex < 0 || valueIndex >= node . end ) {
349+ return false
350+ }
351+ const maybeEnd = valueIndex + quasi . value . raw . length
352+ const maybeOpenQuote = ctx . code . slice ( eqIndex + 1 , valueIndex ) . trimStart ( )
353+ if ( maybeOpenQuote && maybeOpenQuote !== '"' && maybeOpenQuote !== "'" ) {
354+ return false
355+ }
356+ const maybeCloseQuote = ctx . code . slice ( maybeEnd , node . end ) . trimEnd ( )
357+ if ( maybeCloseQuote !== maybeOpenQuote ) {
358+ return false
359+ }
360+ getWithLoc ( expression ) . start = valueIndex
361+ getWithLoc ( expression ) . end = maybeEnd
362+ return true
363+ }
364+
287365/** Convert for Transition Directive */
288366function convertTransitionDirective (
289367 node : SvAST . TransitionDirective ,
0 commit comments