sass/accepted/calculation-api.d.ts.md
2023-08-22 21:10:27 +00:00

9.4 KiB

JavaScript Calculation API: Draft 3.1

(Issue, Changelog)

Table of Contents

Background

This section is non-normative.

This proposal simply exposes the calculation type to the JavaScript API.

Summary

This section is non-normative.

Design Decisions

Simplification

We considered eagerly simplifying calculations as they were constructed to match the behavior of values in Sass itself. However, this poses a problem for API implementations that don't have direct access to compiler logic, such as the Node.js embedded host: they would need to implement the simplification logic locally, which is relatively complex and opens a broad surface area for subtle cross-implementation incompatibilities.

This could potentially be solved by adding an explicit request to the embedded protocol, but this would pose its own problems given that JS is strict about separating asynchronous calls (like those across process boundaries) and synchronous calls (like this API).

Given that, we chose instead to handle simplification only at the custom function boundary rather than when a calculation is constructed.

API

import {List, ValueObject} from 'immutable';

import {Value, SassNumber, SassString} from '../spec/js-api/value';

Types

Value

declare module '../spec/js-api/value' {
  interface Value {

assertCalculation

Returns this if it's a SassCalculation and throws an error otherwise.

The name parameter may be used for error reporting.

assertCalculation(name?: string): SassCalculation;
  } // Value
} // module

Options

declare module '../spec/js-api/options' {
  interface Options<sync extends 'sync' | 'async'> {

functions

Replace this option's specification with:

Before beginning compilation:

  • For each key/value pair signature/function in this record:

    • If signature isn't an followed immediately by an ArgumentDeclaration, throw an error.

    • Let name be signature's .

    • If there's already a global function whose name is underscore-insensitively equal to name, continue to the next key/value pair.

    • Otherwise, add a global function whose signature is signature. When this function is called:

      • Let result be the result of calling the associated CustomFunction with the given arguments. If this call throws an error, treat it as a Sass error thrown by the Sass function.

        As in the rest of Sass, _s and -s are considered equivalent when determining which function signatures match.

      • Throw an error if result is or transitively contains:

        • An object that's not an instance of the Value class.

        • A SassFunction whose signature field isn't a valid Sass function signature that could appear after the @function directive in a Sass stylesheet.

      • Return a copy of result.internal with all calculations it transitively contains (including the return value itself if it's a calculation) replaced with the result of simplifying those calculations.

functions?: Record<string, CustomFunction<sync>>;
  } // Options
} // module

CalculationValue

The type of values that can be arguments to a SassCalculation.

export type CalculationValue =
  | SassNumber
  | SassCalculation
  | SassString
  | CalculationOperation
  | CalculationInterpolation;

SassCalculation

The JS API representation of a Sass calculation.

Note: in the JS API calculations are not simplified eagerly. This also means that unsimplified calculations are not equal to the numbers they would be simplified to.

export class SassCalculation extends Value {

internal

The private internal field refers to a Sass calculation.

calc

Creates a value that represents calc(argument).

  • If argument is a quoted SassString, throw an error.

  • Return a calculation with name "calc" and argument as its single argument.

static calc(argument: CalculationValue): SassCalculation;

min

Creates a value that represents min(...arguments).

  • If arguments contains a quoted SassString, throw an error.

  • Return a calculation with name "min" and arguments as its arguments.

static min(
  arguments: CalculationValue[] | List<CalculationValue>
): SassCalculation;

max

Creates a value that represents max(...arguments).

  • If arguments contains a quoted SassString, throw an error.

  • Return a calculation with name "max" and arguments as its arguments.

static max(
  arguments: CalculationValue[] | List<CalculationValue>
): SassCalculation;

clamp

Creates a value that represents calc(min, value, max) expression.

  • If min, max, or clamp is a quoted SassString, throw an error.

  • If value is undefined and max is not undefined, throw an error.

  • If either value or max is undefined and neither min nor value is a SassString or CalculationInterpolation, throw an error.

  • Return a calculation with name "clamp" and min, value, and max as its arguments, excluding any arguments that are undefined.

static clamp(
  min: CalculationValue,
  value?: CalculationValue,
  max?: CalculationValue
): SassCalculation;

name

Returns internal's name field.

get name(): string;

Returns a list of internal's arguments.

get arguments(): List<CalculationValue>;
} // SassCalculation

CalculationOperator

The set of possible operators in a Sass calculation.

export type CalculationOperator = '+' | '-' | '*' | '/';

CalculationOperation

The JS API representation of a Sass [CalculationOperation].

export class CalculationOperation implements ValueObject {

internal

A private property like Value.internal that refers to a Sass [CalculationOperation].

Constructor

Creates a Sass CalculationOperation:

  • Throw an error if left or right is a quoted SassString.
  • Set the fields to the arguments of the corresponding names.
  • Return the resulting CalculationOperation.
constructor(
  operator: CalculationOperator,
  left: CalculationValue,
  right: CalculationValue
);

operator

Returns internal's operator field.

get operator(): CalculationOperator;

left

Returns internal's left field.

get left(): CalculationValue;

right

Returns internal's right field.

get right(): CalculationValue;

equals

Whether internal is equal to other.internal in Sass.

equals(other: unknown): boolean;

hashCode

Returns the same number for any two CalculationOperations that are equal according to equals.

hashCode(): number;
} // CalculationOperation

CalculationInterpolation

The JS API representation of a Sass CalculationInterpolation.

export class CalculationInterpolation implements ValueObject {

internal

A private property like Value.internal that refers to a Sass CalculationInterpolation.

Constructor

Creates a Sass CalculationInterpolation by setting the value field to the value argument and returns it.

constructor(value: string);

value

Returns internal's value field.

get value(): string;

equals

Whether internal is equal to other.internal in Sass.

equals(other: unknown): boolean;

hashCode

Returns the same number for any two CalculationInterpolations that are equal according to equals.

hashCode(): number;
} // CalculationInterpolation