Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SassCalculation #237

Merged
merged 14 commits into from
Jul 19, 2023
50 changes: 0 additions & 50 deletions lib/src/function-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ import * as proto from './vendor/embedded_sass_pb';
import {PromiseOr, catchOr, compilerError, thenOr} from './utils';
import {Protofier} from './protofier';
import {Value} from './value';
import {
CalculationOperation,
CalculationValue,
SassCalculation,
} from './value/calculations';
import {List} from 'immutable';

/**
* The next ID to use for a function. The embedded protocol requires that
Expand Down Expand Up @@ -72,7 +66,6 @@ export class FunctionRegistry<sync extends 'sync' | 'async'> {
)
),
result => {
result = simplify(result) as types.Value;
if (!(result instanceof Value)) {
const name =
request.identifier.case === 'name'
Expand Down Expand Up @@ -126,46 +119,3 @@ export class FunctionRegistry<sync extends 'sync' | 'async'> {
}
}
}

/**
* Implements the simplification algorithm for custom function return values.
* {@link https://github.com/sass/sass/blob/main/spec/types/calculation.md#simplifying-a-calculationvalue}
*/
function simplify(value: unknown): unknown {
if (value instanceof SassCalculation) {
const simplifiedArgs = value.arguments.map(
simplify
) as List<CalculationValue>;
if (value.name === 'calc') {
if (simplifiedArgs.size !== 1) {
throw new Error('calc() requires exactly 1 argument.');
}
return simplifiedArgs.get(0);
}
if (value.name === 'clamp') {
if (simplifiedArgs.size !== 3) {
throw new Error('clamp() requires exactly 3 arguments.');
}
return SassCalculation.clamp(
simplifiedArgs.get(0) as CalculationValue,
simplifiedArgs.get(1),
simplifiedArgs.get(2)
);
}
if (value.name === 'min') {
return SassCalculation.min(simplifiedArgs);
}
if (value.name === 'max') {
return SassCalculation.max(simplifiedArgs);
}
throw new Error(`Unknown calculation function: ${value.name}.`);
}
if (value instanceof CalculationOperation) {
return new CalculationOperation(
value.operator,
simplify(value.left) as CalculationValue,
simplify(value.right) as CalculationValue
);
}
return value;
}
34 changes: 20 additions & 14 deletions lib/src/protofier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ export class Protofier {
string.quoted = value.hasQuotes;
result.value = {case: 'string', value: string};
} else if (value instanceof SassNumber) {
const number = new proto.Value_Number();
number.value = value.value;
number.numerators = value.numeratorUnits.toArray();
number.denominators = value.denominatorUnits.toArray();
result.value = {case: 'number', value: number};
result.value = {case: 'number', value: this.protofyNumber(value)};
} else if (value instanceof SassColor) {
if (value.hasCalculatedHsl) {
const color = new proto.Value_HslColor();
Expand Down Expand Up @@ -140,6 +136,15 @@ export class Protofier {
return result;
}

/** Converts `number` to its protocol buffer representation. */
private protofyNumber(number: SassNumber): proto.Value_Number {
return new proto.Value_Number({
value: number.value,
numerators: number.numeratorUnits.toArray(),
denominators: number.denominatorUnits.toArray(),
});
}

/** Converts `separator` to its protocol buffer representation. */
private protofySeparator(separator: ListSeparator): proto.ListSeparator {
switch (separator) {
Expand Down Expand Up @@ -193,8 +198,7 @@ export class Protofier {
} else if (value instanceof SassString) {
result.value = {case: 'string', value: value.text};
} else if (value instanceof SassNumber) {
// @ts-ignore
result.value = this.protofy(value).value;
result.value = {case: 'number', value: this.protofyNumber(value)};
} else {
throw utils.compilerError(`Unknown CalculationValue ${value}`);
}
Expand Down Expand Up @@ -230,11 +234,7 @@ export class Protofier {
}

case 'number': {
const number = value.value.value;
return new SassNumber(number.value, {
numeratorUnits: number.numerators,
denominatorUnits: number.denominators,
});
return this.deprotofyNumber(value.value.value);
}

case 'rgbColor': {
Expand Down Expand Up @@ -341,6 +341,13 @@ export class Protofier {
}
}

private deprotofyNumber(number: proto.Value_Number): SassNumber {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a short doc comment for this.

return new SassNumber(number.value, {
numeratorUnits: number.numerators,
denominatorUnits: number.denominators,
});
}

/** Converts `separator` to its JS representation. */
private deprotofySeparator(separator: proto.ListSeparator): ListSeparator {
switch (separator) {
Expand Down Expand Up @@ -413,8 +420,7 @@ export class Protofier {
): CalculationValue {
switch (value.value.case) {
case 'number':
// @ts-ignore
return this.deprotofy(value) as SassNumber;
return this.deprotofyNumber(value.value.value);
case 'calculation':
return this.deprotofyCalculation(value.value.value);
case 'string':
Expand Down
Loading