@@ -17,6 +17,13 @@ import {SassString} from './value/string';
17
17
import { Value } from './value' ;
18
18
import { sassNull } from './value/null' ;
19
19
import { sassTrue , sassFalse } from './value/boolean' ;
20
+ import {
21
+ CalculationValue ,
22
+ SassCalculation ,
23
+ CalculationInterpolation ,
24
+ CalculationOperation ,
25
+ CalculationOperator ,
26
+ } from './value/calculations' ;
20
27
21
28
/**
22
29
* A class that converts [Value] objects into protobufs.
@@ -56,11 +63,7 @@ export class Protofier {
56
63
string . quoted = value . hasQuotes ;
57
64
result . value = { case : 'string' , value : string } ;
58
65
} else if ( value instanceof SassNumber ) {
59
- const number = new proto . Value_Number ( ) ;
60
- number . value = value . value ;
61
- number . numerators = value . numeratorUnits . toArray ( ) ;
62
- number . denominators = value . denominatorUnits . toArray ( ) ;
63
- result . value = { case : 'number' , value : number } ;
66
+ result . value = { case : 'number' , value : this . protofyNumber ( value ) } ;
64
67
} else if ( value instanceof SassColor ) {
65
68
if ( value . hasCalculatedHsl ) {
66
69
const color = new proto . Value_HslColor ( ) ;
@@ -116,6 +119,11 @@ export class Protofier {
116
119
fn . signature = value . signature ! ;
117
120
result . value = { case : 'hostFunction' , value : fn } ;
118
121
}
122
+ } else if ( value instanceof SassCalculation ) {
123
+ result . value = {
124
+ case : 'calculation' ,
125
+ value : this . protofyCalculation ( value ) ,
126
+ } ;
119
127
} else if ( value === sassTrue ) {
120
128
result . value = { case : 'singleton' , value : proto . SingletonValue . TRUE } ;
121
129
} else if ( value === sassFalse ) {
@@ -128,6 +136,15 @@ export class Protofier {
128
136
return result ;
129
137
}
130
138
139
+ /** Converts `number` to its protocol buffer representation. */
140
+ private protofyNumber ( number : SassNumber ) : proto . Value_Number {
141
+ return new proto . Value_Number ( {
142
+ value : number . value ,
143
+ numerators : number . numeratorUnits . toArray ( ) ,
144
+ denominators : number . denominatorUnits . toArray ( ) ,
145
+ } ) ;
146
+ }
147
+
131
148
/** Converts `separator` to its protocol buffer representation. */
132
149
private protofySeparator ( separator : ListSeparator ) : proto . ListSeparator {
133
150
switch ( separator ) {
@@ -144,6 +161,68 @@ export class Protofier {
144
161
}
145
162
}
146
163
164
+ /** Converts `calculation` to its protocol buffer representation. */
165
+ private protofyCalculation (
166
+ calculation : SassCalculation
167
+ ) : proto . Value_Calculation {
168
+ return new proto . Value_Calculation ( {
169
+ name : calculation . name ,
170
+ arguments : calculation . arguments
171
+ . map ( this . protofyCalculationValue . bind ( this ) )
172
+ . toArray ( ) ,
173
+ } ) ;
174
+ }
175
+
176
+ /** Converts a CalculationValue that appears within a `SassCalculation` to
177
+ * its protocol buffer representation. */
178
+ private protofyCalculationValue (
179
+ value : Object
180
+ ) : proto . Value_Calculation_CalculationValue {
181
+ const result = new proto . Value_Calculation_CalculationValue ( ) ;
182
+ if ( value instanceof SassCalculation ) {
183
+ result . value = {
184
+ case : 'calculation' ,
185
+ value : this . protofyCalculation ( value ) ,
186
+ } ;
187
+ } else if ( value instanceof CalculationOperation ) {
188
+ result . value = {
189
+ case : 'operation' ,
190
+ value : new proto . Value_Calculation_CalculationOperation ( {
191
+ operator : this . protofyCalculationOperator ( value . operator ) ,
192
+ left : this . protofyCalculationValue ( value . left ) ,
193
+ right : this . protofyCalculationValue ( value . right ) ,
194
+ } ) ,
195
+ } ;
196
+ } else if ( value instanceof CalculationInterpolation ) {
197
+ result . value = { case : 'interpolation' , value : value . value } ;
198
+ } else if ( value instanceof SassString ) {
199
+ result . value = { case : 'string' , value : value . text } ;
200
+ } else if ( value instanceof SassNumber ) {
201
+ result . value = { case : 'number' , value : this . protofyNumber ( value ) } ;
202
+ } else {
203
+ throw utils . compilerError ( `Unknown CalculationValue ${ value } ` ) ;
204
+ }
205
+ return result ;
206
+ }
207
+
208
+ /** Converts `operator` to its protocol buffer representation. */
209
+ private protofyCalculationOperator (
210
+ operator : CalculationOperator
211
+ ) : proto . CalculationOperator {
212
+ switch ( operator ) {
213
+ case '+' :
214
+ return proto . CalculationOperator . PLUS ;
215
+ case '-' :
216
+ return proto . CalculationOperator . MINUS ;
217
+ case '*' :
218
+ return proto . CalculationOperator . TIMES ;
219
+ case '/' :
220
+ return proto . CalculationOperator . DIVIDE ;
221
+ default :
222
+ throw utils . compilerError ( `Unknown CalculationOperator ${ operator } ` ) ;
223
+ }
224
+ }
225
+
147
226
/** Converts `value` to its JS representation. */
148
227
deprotofy ( value : proto . Value ) : Value {
149
228
switch ( value . value . case ) {
@@ -155,11 +234,7 @@ export class Protofier {
155
234
}
156
235
157
236
case 'number' : {
158
- const number = value . value . value ;
159
- return new SassNumber ( number . value , {
160
- numeratorUnits : number . numerators ,
161
- denominatorUnits : number . denominators ,
162
- } ) ;
237
+ return this . deprotofyNumber ( value . value . value ) ;
163
238
}
164
239
165
240
case 'rgbColor' : {
@@ -247,6 +322,9 @@ export class Protofier {
247
322
'The compiler may not send Value.host_function.'
248
323
) ;
249
324
325
+ case 'calculation' :
326
+ return this . deprotofyCalculation ( value . value . value ) ;
327
+
250
328
case 'singleton' :
251
329
switch ( value . value . value ) {
252
330
case proto . SingletonValue . TRUE :
@@ -263,6 +341,14 @@ export class Protofier {
263
341
}
264
342
}
265
343
344
+ /** Converts `number` to its JS representation. */
345
+ private deprotofyNumber ( number : proto . Value_Number ) : SassNumber {
346
+ return new SassNumber ( number . value , {
347
+ numeratorUnits : number . numerators ,
348
+ denominatorUnits : number . denominators ,
349
+ } ) ;
350
+ }
351
+
266
352
/** Converts `separator` to its JS representation. */
267
353
private deprotofySeparator ( separator : proto . ListSeparator ) : ListSeparator {
268
354
switch ( separator ) {
@@ -278,4 +364,100 @@ export class Protofier {
278
364
throw utils . compilerError ( `Unknown separator ${ separator } ` ) ;
279
365
}
280
366
}
367
+
368
+ /** Converts `calculation` to its Sass representation. */
369
+ private deprotofyCalculation (
370
+ calculation : proto . Value_Calculation
371
+ ) : SassCalculation {
372
+ switch ( calculation . name ) {
373
+ case 'calc' :
374
+ if ( calculation . arguments . length !== 1 ) {
375
+ throw utils . compilerError (
376
+ 'Value.Calculation.arguments must have exactly one argument for calc().'
377
+ ) ;
378
+ }
379
+ return SassCalculation . calc (
380
+ this . deprotofyCalculationValue ( calculation . arguments [ 0 ] )
381
+ ) ;
382
+ case 'clamp' :
383
+ if ( calculation . arguments . length !== 3 ) {
384
+ throw utils . compilerError (
385
+ 'Value.Calculation.arguments must have exactly 3 arguments for clamp().'
386
+ ) ;
387
+ }
388
+ return SassCalculation . clamp (
389
+ this . deprotofyCalculationValue ( calculation . arguments [ 0 ] ) ,
390
+ this . deprotofyCalculationValue ( calculation . arguments [ 1 ] ) ,
391
+ this . deprotofyCalculationValue ( calculation . arguments [ 2 ] )
392
+ ) ;
393
+ case 'min' :
394
+ if ( calculation . arguments . length === 0 ) {
395
+ throw utils . compilerError (
396
+ 'Value.Calculation.arguments must have at least 1 argument for min().'
397
+ ) ;
398
+ }
399
+ return SassCalculation . min (
400
+ calculation . arguments . map ( this . deprotofyCalculationValue )
401
+ ) ;
402
+ case 'max' :
403
+ if ( calculation . arguments . length === 0 ) {
404
+ throw utils . compilerError (
405
+ 'Value.Calculation.arguments must have at least 1 argument for max().'
406
+ ) ;
407
+ }
408
+ return SassCalculation . max (
409
+ calculation . arguments . map ( this . deprotofyCalculationValue )
410
+ ) ;
411
+ default :
412
+ throw utils . compilerError (
413
+ `Value.Calculation.name "${ calculation . name } " is not a recognized calculation type.`
414
+ ) ;
415
+ }
416
+ }
417
+
418
+ /** Converts `value` to its Sass representation. */
419
+ private deprotofyCalculationValue (
420
+ value : proto . Value_Calculation_CalculationValue
421
+ ) : CalculationValue {
422
+ switch ( value . value . case ) {
423
+ case 'number' :
424
+ return this . deprotofyNumber ( value . value . value ) ;
425
+ case 'calculation' :
426
+ return this . deprotofyCalculation ( value . value . value ) ;
427
+ case 'string' :
428
+ return new SassString ( value . value . value , { quotes : false } ) ;
429
+ case 'operation' :
430
+ return new CalculationOperation (
431
+ this . deprotofyCalculationOperator ( value . value . value . operator ) ,
432
+ this . deprotofyCalculationValue (
433
+ value . value . value . left as proto . Value_Calculation_CalculationValue
434
+ ) ,
435
+ this . deprotofyCalculationValue (
436
+ value . value . value . right as proto . Value_Calculation_CalculationValue
437
+ )
438
+ ) ;
439
+ case 'interpolation' :
440
+ return new CalculationInterpolation ( value . value . value ) ;
441
+ default :
442
+ throw utils . mandatoryError ( 'Calculation.CalculationValue.value' ) ;
443
+ }
444
+ }
445
+
446
+ /** Converts `operator` to its Sass representation. */
447
+ private deprotofyCalculationOperator (
448
+ operator : proto . CalculationOperator
449
+ ) : CalculationOperator {
450
+ switch ( operator ) {
451
+ case proto . CalculationOperator . PLUS :
452
+ return '+' ;
453
+ case proto . CalculationOperator . MINUS :
454
+ return '-' ;
455
+ case proto . CalculationOperator . TIMES :
456
+ return '*' ;
457
+ case proto . CalculationOperator . DIVIDE :
458
+ return '/' ;
459
+ default :
460
+ throw utils . compilerError ( `Unknown CalculationOperator ${ operator } ` ) ;
461
+ }
462
+ }
281
463
}
0 commit comments