@@ -6,7 +6,7 @@ import type { ObjectDictionary } from "@opticss/util";
6
6
7
7
/// @ts -ignore
8
8
import { data as _data } from "./-css-blocks-data" ;
9
- import type { AggregateRewriteData , StyleExpression } from "./AggregateRewriteData" ;
9
+ import type { AggregateRewriteData , StyleExpression , ImpliedStyles , ConditionalStyle } from "./AggregateRewriteData" ;
10
10
11
11
const data : AggregateRewriteData = _data ;
12
12
@@ -99,10 +99,9 @@ const enum FalsySwitchBehavior {
99
99
export default class CSSBlocksService extends Service {
100
100
classNamesFor ( argv : Array < string | number | boolean | null > ) : string {
101
101
let args = argv . slice ( ) ;
102
- console . log ( args ) ;
103
102
args . reverse ( ) ; // pop() is faster than shift()
104
103
let rewriteVersion = num ( args ) ;
105
- if ( rewriteVersion > 1 ) throw new Error ( `The rewrite is newer than expected. Please upgrade @css-blocks/ember-app.` ) ;
104
+ if ( rewriteVersion > 0 ) throw new Error ( `The rewrite schema is newer than expected. Please upgrade @css-blocks/ember-app.` ) ;
106
105
107
106
let numBlocks = num ( args ) ;
108
107
// the values in blockStyleIndices map style strings to an index into the array
@@ -119,6 +118,7 @@ export default class CSSBlocksService extends Service {
119
118
let sourceGuid = str ( args ) ;
120
119
let runtimeGuid = str ( args , true ) ; // this won't be non-null until we implement block passing.
121
120
let blockIndex = data . blockIds [ sourceGuid ] ;
121
+ assert ( blockIndex , `unknown block ${ sourceGuid } ` ) ;
122
122
let runtimeBlockIndex = runtimeGuid === null ? blockIndex : data . blockIds [ runtimeGuid ] ;
123
123
let blockInfo = data . blocks [ blockIndex ] ;
124
124
blockStyleIndices . push ( blockInfo . blockInterfaceStyles ) ;
@@ -182,7 +182,7 @@ export default class CSSBlocksService extends Service {
182
182
let currentValue = str ( args , true , true ) ;
183
183
let numValues = num ( args ) ;
184
184
let found = false ;
185
- let legal = new Array < string > ( ) ;
185
+ let legal : Array < String > = [ ] ;
186
186
while ( numValues -- ) {
187
187
let v = str ( args ) ;
188
188
legal . push ( v ) ;
@@ -214,38 +214,88 @@ export default class CSSBlocksService extends Service {
214
214
stylesApplied . add ( styles [ i ] ! ) ;
215
215
}
216
216
}
217
- // TODO: style inference
217
+
218
+ let aliasClassNames = applyImpliedStyles ( stylesApplied , data . impliedStyles ) ;
219
+
218
220
let classNameIndices = new Set < number > ( ) ;
221
+ // TODO: Only iterate over the subset of optimizations that might match this
222
+ // element's styles.
219
223
for ( let [ clsIdx , expr ] of data . optimizations ) {
220
224
if ( evaluateExpression ( expr , stylesApplied ) ) {
221
225
classNameIndices . add ( clsIdx ) ;
222
226
}
223
227
}
224
- let classNames = new Array < string > ( ) ;
228
+ let classNames = new Array < string > ( ... aliasClassNames ) ;
225
229
for ( let idx of classNameIndices ) {
226
230
classNames . push ( data . outputClassnames [ idx ] ) ;
227
231
}
228
232
let result = classNames . join ( " " ) ;
229
- console . log ( result ) ;
230
233
return result ;
231
234
}
232
235
}
233
236
234
- function evaluateExpression ( expr : StyleExpression , stylesApplied : Set < number > ) : boolean {
235
- if ( typeof expr === "number" ) return stylesApplied . has ( expr ) ;
237
+ function evaluateExpression ( expr : StyleExpression , stylesApplied : Set < number > , stylesApplied2 ?: Set < number > ) : boolean {
238
+ if ( typeof expr === "number" ) return ( stylesApplied . has ( expr ) || ( ! ! stylesApplied2 && stylesApplied2 . has ( expr ) ) ) ;
236
239
if ( expr [ 0 ] === Operator . AND ) {
237
240
for ( let i = 1 ; i < expr . length ; i ++ ) {
238
- if ( ! evaluateExpression ( expr [ i ] , stylesApplied ) ) return false ;
241
+ if ( ! evaluateExpression ( expr [ i ] , stylesApplied , stylesApplied2 ) ) return false ;
239
242
}
240
243
return true ;
241
244
} else if ( expr [ 0 ] === Operator . OR ) {
242
245
for ( let i = 1 ; i < expr . length ; i ++ ) {
243
- if ( evaluateExpression ( expr [ i ] , stylesApplied ) ) return true ;
246
+ if ( evaluateExpression ( expr [ i ] , stylesApplied , stylesApplied2 ) ) return true ;
244
247
}
245
248
return false ;
246
249
} else if ( expr [ 0 ] === Operator . NOT ) {
247
- return ! evaluateExpression ( expr [ 1 ] , stylesApplied ) ;
250
+ return ! evaluateExpression ( expr [ 1 ] , stylesApplied , stylesApplied2 ) ;
248
251
} else {
249
252
return false ;
250
253
}
251
254
}
255
+
256
+ function applyImpliedStyles ( stylesApplied : Set < number > , impliedStyles : ImpliedStyles ) : Set < string > {
257
+ console . log ( { impliedStyles} ) ;
258
+ let aliases = new Set < string > ( ) ;
259
+ let newStyles = new Set ( stylesApplied ) ;
260
+ let failedConditions = new Set < ConditionalStyle > ( ) ;
261
+ // for each new style we get the directly implied styles by each of them and
262
+ // add them to the next iteration of new styles. if a conditionally applied
263
+ // style doesn't match, it might be due to an implied style that isn't applied
264
+ // yet, so we keep the failures around and try adding them during each
265
+ // iteration once new styles are taken into account.
266
+ while ( newStyles . size > 0 ) {
267
+ let nextStyles = new Set < number > ( ) ;
268
+ let newFailedConditions = new Set < ConditionalStyle > ( ) ;
269
+ for ( let style of newStyles ) {
270
+ let implied = impliedStyles [ style ] ;
271
+ if ( ! implied ) continue ;
272
+ for ( let i of implied ) {
273
+ if ( typeof i === "number" ) {
274
+ nextStyles . add ( i ) ;
275
+ } else if ( typeof i === "string" ) {
276
+ aliases . add ( i ) ;
277
+ } else {
278
+ if ( evaluateExpression ( i . conditions , stylesApplied , newStyles ) ) {
279
+ nextStyles . add ( i . style ) ;
280
+ } else {
281
+ newFailedConditions . add ( i ) ;
282
+ }
283
+ }
284
+ }
285
+ }
286
+ for ( let s of newStyles ) {
287
+ stylesApplied . add ( s ) ;
288
+ }
289
+ newStyles = nextStyles ;
290
+ for ( let c of failedConditions ) {
291
+ if ( evaluateExpression ( c . conditions , stylesApplied , newStyles ) ) {
292
+ newStyles . add ( c . style ) ;
293
+ failedConditions . delete ( c ) ;
294
+ }
295
+ }
296
+ for ( let c of newFailedConditions ) {
297
+ failedConditions . add ( c ) ;
298
+ }
299
+ }
300
+ return aliases ;
301
+ }
0 commit comments