10
10
* CssProcessor.
11
11
*/
12
12
13
- import { SourceLocation } from '@babel/types' ;
13
+ import { SourceLocation , TemplateElement } from '@babel/types' ;
14
14
import {
15
15
type TransformedInternalConfig ,
16
16
type StyleObjectReturn ,
@@ -21,7 +21,7 @@ import {
21
21
serializeStyles ,
22
22
valueToLiteral ,
23
23
evaluateClassNameArg ,
24
- getCSSVar ,
24
+ transformProbableCssVar ,
25
25
} from '@pigment-css/utils' ;
26
26
import {
27
27
CallParam ,
@@ -119,6 +119,99 @@ export type CssTailProcessorParams = BaseCssProcessorConstructorParams extends [
119
119
? T
120
120
: never ;
121
121
122
+ function handleTemplateElementOrSimilar (
123
+ templateParams : ( TemplateElement | ExpressionValue ) [ ] ,
124
+ values : ValueCache ,
125
+ processor : BaseCssProcessor ,
126
+ ) {
127
+ const { themeArgs = { } , pigmentFeatures : { useLayer = true } = { } } =
128
+ processor . options as TransformedInternalConfig ;
129
+ // @ts -ignore @TODO - Fix this. No idea how to initialize a Tagged String array.
130
+ const templateStrs : string [ ] = [ ] ;
131
+ // @ts -ignore @TODO - Fix this. No idea how to initialize a Tagged String array.
132
+ templateStrs . raw = [ ] ;
133
+ const templateExpressions : Primitive [ ] = [ ] ;
134
+ let paramsToIterate = templateParams ;
135
+ const [ firstArg , ...restArgs ] = templateParams ;
136
+ if ( 'kind' in firstArg && firstArg . kind === ValueType . LAZY ) {
137
+ const value = values . get ( firstArg . ex . name ) as string [ ] ;
138
+ templateStrs . push ( ...value ) ;
139
+ // @ts -ignore @TODO - Fix this. No idea how to initialize a Tagged String array.
140
+ templateStrs . raw . push ( ...value ) ;
141
+ paramsToIterate = restArgs ;
142
+ }
143
+ paramsToIterate . forEach ( ( param ) => {
144
+ if ( 'kind' in param ) {
145
+ switch ( param . kind ) {
146
+ case ValueType . FUNCTION : {
147
+ const value = values . get ( param . ex . name ) as TemplateCallback ;
148
+ templateExpressions . push ( value ( themeArgs ) ) ;
149
+ break ;
150
+ }
151
+ case ValueType . CONST : {
152
+ if ( typeof param . value === 'string' ) {
153
+ templateExpressions . push ( transformProbableCssVar ( param . value ) ) ;
154
+ } else {
155
+ templateExpressions . push ( param . value ) ;
156
+ }
157
+ break ;
158
+ }
159
+ case ValueType . LAZY : {
160
+ const evaluatedValue = values . get ( param . ex . name ) ;
161
+ if ( typeof evaluatedValue === 'function' ) {
162
+ templateExpressions . push ( evaluatedValue ( themeArgs ) ) ;
163
+ } else if ( typeof evaluatedValue === 'string' ) {
164
+ templateExpressions . push ( transformProbableCssVar ( evaluatedValue ) ) ;
165
+ } else {
166
+ templateExpressions . push ( evaluatedValue as Primitive ) ;
167
+ }
168
+ break ;
169
+ }
170
+ default :
171
+ break ;
172
+ }
173
+ } else if ( 'type' in param && param . type === 'TemplateElement' ) {
174
+ templateStrs . push ( param . value . cooked as string ) ;
175
+ // @ts -ignore
176
+ templateStrs . raw . push ( param . value . raw ) ;
177
+ }
178
+ } ) ;
179
+ const { styles } = serializeStyles (
180
+ templateExpressions . length > 0 ? [ templateStrs , ...templateExpressions ] : [ templateStrs ] ,
181
+ ) ;
182
+
183
+ const cssText = useLayer
184
+ ? `@layer pigment.base{${ processor . wrapStyle ( styles , '' ) } }`
185
+ : processor . wrapStyle ( styles , '' ) ;
186
+ const className = processor . getClassName ( ) ;
187
+ const rules : Rules = {
188
+ [ `.${ className } ` ] : {
189
+ className,
190
+ cssText,
191
+ displayName : processor . displayName ,
192
+ start : processor . location ?. start ?? null ,
193
+ } ,
194
+ } ;
195
+ const location = processor . location ;
196
+ const sourceMapReplacements : Replacements = [
197
+ {
198
+ length : cssText . length ,
199
+ original : {
200
+ start : {
201
+ column : location ?. start . column ?? 0 ,
202
+ line : location ?. start . line ?? 0 ,
203
+ } ,
204
+ end : {
205
+ column : location ?. end . column ?? 0 ,
206
+ line : location ?. end . line ?? 0 ,
207
+ } ,
208
+ } ,
209
+ } ,
210
+ ] ;
211
+ processor . classNames . push ( className ) ;
212
+ processor . artifacts . push ( [ 'css' , [ rules , sourceMapReplacements ] ] ) ;
213
+ }
214
+
122
215
/**
123
216
* Only deals with css`` or css(metadata)`` calls.
124
217
*/
@@ -138,84 +231,8 @@ export class CssTaggedTemplateProcessor extends BaseCssProcessor {
138
231
}
139
232
140
233
build ( values : ValueCache ) : void {
141
- const { themeArgs, pigmentFeatures : { useLayer = true } = { } } = this
142
- . options as TransformedInternalConfig ;
143
234
const [ , templateParams ] = this . templateParam ;
144
- // @ts -ignore @TODO - Fix this. No idea how to initialize a Tagged String array.
145
- const templateStrs : string [ ] = [ ] ;
146
- // @ts -ignore @TODO - Fix this. No idea how to initialize a Tagged String array.
147
- templateStrs . raw = [ ] ;
148
- const templateExpressions : Primitive [ ] = [ ] ;
149
- templateParams . forEach ( ( param ) => {
150
- if ( 'kind' in param ) {
151
- switch ( param . kind ) {
152
- case ValueType . FUNCTION : {
153
- const value = values . get ( param . ex . name ) as TemplateCallback ;
154
- templateExpressions . push ( value ( themeArgs ) ) ;
155
- break ;
156
- }
157
- case ValueType . CONST : {
158
- templateExpressions . push ( param . value ) ;
159
- break ;
160
- }
161
- case ValueType . LAZY : {
162
- const evaluatedValue = values . get ( param . ex . name ) ;
163
- if ( typeof evaluatedValue === 'function' ) {
164
- templateExpressions . push ( evaluatedValue ( themeArgs ) ) ;
165
- } else if (
166
- typeof evaluatedValue === 'object' &&
167
- evaluatedValue &&
168
- ( evaluatedValue as unknown as Record < string , boolean > ) . isThemeVar
169
- ) {
170
- templateExpressions . push ( getCSSVar ( evaluatedValue . toString ( ) , true ) ) ;
171
- } else {
172
- templateExpressions . push ( evaluatedValue as Primitive ) ;
173
- }
174
- break ;
175
- }
176
- default :
177
- break ;
178
- }
179
- } else if ( 'type' in param && param . type === 'TemplateElement' ) {
180
- templateStrs . push ( param . value . cooked as string ) ;
181
- // @ts -ignore
182
- templateStrs . raw . push ( param . value . raw ) ;
183
- }
184
- } ) ;
185
- const { styles } = serializeStyles (
186
- templateExpressions . length > 0 ? [ templateStrs , ...templateExpressions ] : [ templateStrs ] ,
187
- ) ;
188
-
189
- const cssText = useLayer
190
- ? `@layer pigment.base{${ this . wrapStyle ( styles , '' ) } }`
191
- : this . wrapStyle ( styles , '' ) ;
192
- const className = this . getClassName ( ) ;
193
- const rules : Rules = {
194
- [ `.${ className } ` ] : {
195
- className,
196
- cssText,
197
- displayName : this . displayName ,
198
- start : this . location ?. start ?? null ,
199
- } ,
200
- } ;
201
- const location = this . location ;
202
- const sourceMapReplacements : Replacements = [
203
- {
204
- length : cssText . length ,
205
- original : {
206
- start : {
207
- column : location ?. start . column ?? 0 ,
208
- line : location ?. start . line ?? 0 ,
209
- } ,
210
- end : {
211
- column : location ?. end . column ?? 0 ,
212
- line : location ?. end . line ?? 0 ,
213
- } ,
214
- } ,
215
- } ,
216
- ] ;
217
- this . classNames . push ( className ) ;
218
- this . artifacts . push ( [ 'css' , [ rules , sourceMapReplacements ] ] ) ;
235
+ handleTemplateElementOrSimilar ( templateParams , values , this ) ;
219
236
}
220
237
}
221
238
@@ -235,7 +252,28 @@ export class CssObjectProcessor extends BaseCssProcessor {
235
252
return params . flat ( ) . filter ( ( param ) => 'kind' in param ) ;
236
253
}
237
254
255
+ isMaybeTransformedTemplateLiteral ( values : ValueCache ) : boolean {
256
+ const [ , firstArg , ...restArgs ] = this . callParam ;
257
+ if ( ! ( 'kind' in firstArg ) || firstArg . kind === ValueType . CONST ) {
258
+ return false ;
259
+ }
260
+ const firstArgVal = values . get ( firstArg . ex . name ) ;
261
+ if ( Array . isArray ( firstArgVal ) && restArgs . length === firstArgVal . length - 1 ) {
262
+ return true ;
263
+ }
264
+ return false ;
265
+ }
266
+
267
+ private buildForTransformedTemplateTag ( values : ValueCache ) {
268
+ const [ , ...templateParams ] = this . callParam ;
269
+ handleTemplateElementOrSimilar ( templateParams , values , this ) ;
270
+ }
271
+
238
272
build ( values : ValueCache ) : void {
273
+ if ( this . isMaybeTransformedTemplateLiteral ( values ) ) {
274
+ this . buildForTransformedTemplateTag ( values ) ;
275
+ return ;
276
+ }
239
277
const [ , ...callParams ] = this . callParam ;
240
278
const { themeArgs, pigmentFeatures : { useLayer = true } = { } } = this
241
279
. options as TransformedInternalConfig ;
0 commit comments