mirror of
https://github.com/sass/sass.git
synced 2024-09-21 10:37:22 +00:00
Use literate programming for JS API specs (#3552)
This commit is contained in:
parent
8dd2d5e020
commit
7abda4e2f4
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with: {node-version: '${{ env.NODE_VERSION }}'}
|
||||
- run: npm ci
|
||||
- run: npx gts lint && npx tsc --noEmit
|
||||
- run: npm run tangle && npx gts lint && npx tsc --noEmit
|
||||
|
||||
toc:
|
||||
name: Tables of contents
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,3 +1,9 @@
|
||||
# Ignore the tangled output of literate TypeScript specs.
|
||||
/proposal/*.d.ts
|
||||
/accepted/*.d.ts
|
||||
/spec/**/*.d.ts
|
||||
!/spec/util/**/*.d.ts
|
||||
|
||||
# Created by https://www.gitignore.io/api/node
|
||||
# Edit at https://www.gitignore.io/?templates=node
|
||||
|
||||
|
251
accepted/calculation-api.d.ts
vendored
251
accepted/calculation-api.d.ts
vendored
@ -1,251 +0,0 @@
|
||||
/**
|
||||
* # JavaScript Calculation API: Draft 2
|
||||
*
|
||||
* *([Issue](https://github.com/sass/sass/issues/818),
|
||||
* [Changelog](calculation-api.changes.md))*
|
||||
*
|
||||
* ## Background
|
||||
*
|
||||
* > This section is non-normative.
|
||||
*
|
||||
* This proposal simply exposes the [calculation type] to the JavaScript API.
|
||||
*
|
||||
* [calculation type]: ../accepted/first-class-calc.md
|
||||
*
|
||||
* ## 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';
|
||||
|
||||
declare module '../spec/js-api/value' {
|
||||
interface Value {
|
||||
/**
|
||||
* Asserts that `this` is a `SassCalculation`:
|
||||
*
|
||||
* - If `internal` is a Sass calculation, return `this`.
|
||||
* - Otherwise, throw an error.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertCalculation(name?: string): SassCalculation;
|
||||
}
|
||||
}
|
||||
|
||||
declare module '../spec/js-api/options' {
|
||||
interface Options<sync extends 'sync' | 'async'> {
|
||||
/**
|
||||
* Replace this option's specification with:
|
||||
*
|
||||
* Before beginning compilation:
|
||||
*
|
||||
* - For each key/value pair `signature`/`function` in this record:
|
||||
*
|
||||
* - If `signature` isn't an [<ident-token>] followed immediately by an
|
||||
* `ArgumentDeclaration`, throw an error.
|
||||
*
|
||||
* [<ident-token>]: https://drafts.csswg.org/css-syntax-3/#ident-token-diagram
|
||||
*
|
||||
* - Let `name` be `signature`'s <ident-token>.
|
||||
*
|
||||
* - 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.
|
||||
*
|
||||
* [simplifying]: ../spec/types/calculation.md#simplifying-a-calculation
|
||||
*/
|
||||
functions?: Record<string, CustomFunction<sync>>;
|
||||
}
|
||||
}
|
||||
|
||||
/** The type of values that can be arguments to a `SassCalculation`. */
|
||||
type CalculationValue =
|
||||
| SassNumber
|
||||
| SassCalculation
|
||||
| SassString
|
||||
| CalculationOperation
|
||||
| CalculationInterpolation;
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass [calculation].
|
||||
*
|
||||
* [calculation]: ../spec/types/calculation.md#types
|
||||
*
|
||||
* `internal` refers to 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 {
|
||||
/**
|
||||
* Creates a value that represents `calc(argument)` expression.
|
||||
*
|
||||
* - If `argument` is or transitively contains a quoted `SassString`, throw an
|
||||
* error.
|
||||
*
|
||||
* - Return a calculation with name `"calc"` and a `argument` as its single
|
||||
* argument.
|
||||
*/
|
||||
static calc(argument: CalculationValue): SassCalculation;
|
||||
|
||||
/**
|
||||
* Creates a value that represents `min(...arguments)`.
|
||||
*
|
||||
* - If `argument` is or transitively 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;
|
||||
|
||||
/**
|
||||
* Creates a value that represents `min(...arguments)`.
|
||||
*
|
||||
* - If `arguments` transitively 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;
|
||||
|
||||
/**
|
||||
* Creates a value that represents `calc(min, value, max)` expression.
|
||||
*
|
||||
* - If `min`, `max`, or `clamp` is or transitively contains a quoted
|
||||
* `SassString`, throw an error.
|
||||
*
|
||||
* - If `value` is undefined and `max` is not undefined, throw an error.
|
||||
*
|
||||
* - If `value` or `max` is undefined and neither `min` nor `value` is a
|
||||
* `SassString` that begins with `"var("`, 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;
|
||||
|
||||
/** `internal`'s `name` field. */
|
||||
get name(): string;
|
||||
|
||||
/** A list of `internal`'s arguments. */
|
||||
get arguments(): List<CalculationValue>;
|
||||
}
|
||||
|
||||
/** The set of possible operators in a Sass calculation. */
|
||||
type CalculationOperator = '+' | '-' | '*' | '/';
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass [CalculationOperation].
|
||||
*
|
||||
* [CalculationOperation]: ../spec/types/calculation.md#types
|
||||
*
|
||||
* `internal` refers to a Sass CalculationOperation.
|
||||
*/
|
||||
export abstract class CalculationOperation implements ValueObject {
|
||||
/**
|
||||
* Creates a Sass CalculationOperation by setting the fields to the arguments
|
||||
* of the corresponding names, and returns it.
|
||||
*/
|
||||
constructor(
|
||||
operator: CalculationOperator,
|
||||
left: CalculationValue,
|
||||
right: CalculationValue
|
||||
);
|
||||
|
||||
/** `internal`'s `operator` field. */
|
||||
get operator(): CalculationOperator;
|
||||
|
||||
/** `internal`'s `left` field. */
|
||||
get left(): CalculationValue;
|
||||
|
||||
/** `internal`'s `right` field. */
|
||||
get right(): CalculationValue;
|
||||
|
||||
/** Whether `internal` is equal to `other.internal` in Sass. */
|
||||
equals(other: CalculationOperation): boolean;
|
||||
|
||||
/** Must be the same for two equal values. */
|
||||
hashCode(): number;
|
||||
}
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass [CalculationInterpolation].
|
||||
*
|
||||
* [CalculationInterpolation]: ../spec/types/calculation.md#types
|
||||
*
|
||||
* `internal` refers to a Sass CalculationInterpolation.
|
||||
*
|
||||
* Two `CalculationInterpolation`s are equal if their `value` fields are equal.
|
||||
*/
|
||||
export abstract class CalculationInterpolation implements ValueObject {
|
||||
/**
|
||||
* Creates a Sass CalculationInterpolation by setting the `value` field to the
|
||||
* argument of the corresponding name, and returns it.
|
||||
*/
|
||||
constructor(value: string);
|
||||
|
||||
/** `internal`'s `value` field. */
|
||||
get value(): string;
|
||||
|
||||
/** Whether `internal` is equal to `other.internal` in Sass. */
|
||||
equals(other: CalculationOperation): boolean;
|
||||
|
||||
/** Must be the same for two equal values. */
|
||||
hashCode(): number;
|
||||
}
|
423
accepted/calculation-api.d.ts.md
Normal file
423
accepted/calculation-api.d.ts.md
Normal file
@ -0,0 +1,423 @@
|
||||
# JavaScript Calculation API: Draft 2
|
||||
|
||||
*([Issue](https://github.com/sass/sass/issues/818),
|
||||
[Changelog](calculation-api.changes.md))*
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Background](#background)
|
||||
* [Summary](#summary)
|
||||
* [Design Decisions](#design-decisions)
|
||||
* [Simplification](#simplification)
|
||||
* [API](#api)
|
||||
* [Types](#types)
|
||||
* [`Value`](#value)
|
||||
* [`assertCalculation`](#assertcalculation)
|
||||
* [`Options`](#options)
|
||||
* [`functions`](#functions)
|
||||
* [`CalculationValue`](#calculationvalue)
|
||||
* [`SassCalculation`](#sasscalculation)
|
||||
* [`internal`](#internal)
|
||||
* [`calc`](#calc)
|
||||
* [`min`](#min)
|
||||
* [`max`](#max)
|
||||
* [`clamp`](#clamp)
|
||||
* [`name`](#name)
|
||||
* [`CalculationOperator`](#calculationoperator)
|
||||
* [`CalculationOperation`](#calculationoperation)
|
||||
* [`internal`](#internal-1)
|
||||
* [Constructor](#constructor)
|
||||
* [`operator`](#operator)
|
||||
* [`left`](#left)
|
||||
* [`right`](#right)
|
||||
* [`equals`](#equals)
|
||||
* [`hashCode`](#hashcode)
|
||||
* [`CalculationInterpolation`](#calculationinterpolation)
|
||||
* [`internal`](#internal-2)
|
||||
* [Constructor](#constructor-1)
|
||||
* [`value`](#value)
|
||||
* [`equals`](#equals-1)
|
||||
* [`hashCode`](#hashcode-1)
|
||||
|
||||
## Background
|
||||
|
||||
> This section is non-normative.
|
||||
|
||||
This proposal simply exposes the [calculation type] to the JavaScript API.
|
||||
|
||||
[calculation type]: ../accepted/first-class-calc.md
|
||||
|
||||
## 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
|
||||
|
||||
```ts
|
||||
import {List, ValueObject} from 'immutable';
|
||||
|
||||
import {Value, SassNumber, SassString} from '../spec/js-api/value';
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
### `Value`
|
||||
|
||||
```ts
|
||||
declare module '../spec/js-api/value' {
|
||||
interface Value {
|
||||
```
|
||||
|
||||
#### `assertCalculation`
|
||||
|
||||
Returns `this` if it's a [`SassCalculation`] and throws an error otherwise.
|
||||
|
||||
[`SassCalculation`]: #sasscalculation
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertCalculation(name?: string): SassCalculation;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // Value
|
||||
} // module
|
||||
```
|
||||
|
||||
### `Options`
|
||||
|
||||
```ts
|
||||
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 [<ident-token>] followed immediately by an
|
||||
`ArgumentDeclaration`, throw an error.
|
||||
|
||||
* Let `name` be `signature`'s <ident-token>.
|
||||
|
||||
* 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.
|
||||
|
||||
[<ident-token>]: https://drafts.csswg.org/css-syntax-3/#ident-token-diagram
|
||||
[`SassFunction`]: ../spec/js-api/value/function.d.ts.md
|
||||
[simplifying]: ../spec/types/calculation.md#simplifying-a-calculation
|
||||
|
||||
```ts
|
||||
functions?: Record<string, CustomFunction<sync>>;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // Options
|
||||
} // module
|
||||
```
|
||||
|
||||
### `CalculationValue`
|
||||
|
||||
The type of values that can be arguments to a [`SassCalculation`].
|
||||
|
||||
```ts
|
||||
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.
|
||||
|
||||
```ts
|
||||
export class SassCalculation extends Value {
|
||||
```
|
||||
|
||||
#### `internal`
|
||||
|
||||
The [private `internal` field] refers to a Sass [calculation].
|
||||
|
||||
[private `internal` field]: ../spec/js-api/value/index.d.ts.md#internal
|
||||
[calculation]: ../spec/types/calculation.md
|
||||
|
||||
#### `calc`
|
||||
|
||||
Creates a value that represents `calc(argument)`.
|
||||
|
||||
* If `argument` is or transitively contains a quoted `SassString`, throw an
|
||||
error.
|
||||
|
||||
* Return a calculation with name `"calc"` and `argument` as its single argument.
|
||||
|
||||
```ts
|
||||
static calc(argument: CalculationValue): SassCalculation;
|
||||
```
|
||||
|
||||
#### `min`
|
||||
|
||||
Creates a value that represents `min(...arguments)`.
|
||||
|
||||
* If `argument` is or transitively contains a quoted `SassString`, throw an
|
||||
error.
|
||||
|
||||
* Return a calculation with name `"min"` and `arguments` as its arguments.
|
||||
|
||||
```ts
|
||||
static min(
|
||||
arguments: CalculationValue[] | List<CalculationValue>
|
||||
): SassCalculation;
|
||||
```
|
||||
|
||||
#### `max`
|
||||
|
||||
Creates a value that represents `max(...arguments)`.
|
||||
|
||||
* If `arguments` transitively contains a quoted `SassString`, throw an error.
|
||||
|
||||
* Return a calculation with name `"max"` and `arguments` as its arguments.
|
||||
|
||||
```ts
|
||||
static max(
|
||||
arguments: CalculationValue[] | List<CalculationValue>
|
||||
): SassCalculation;
|
||||
```
|
||||
|
||||
#### `clamp`
|
||||
|
||||
Creates a value that represents `calc(min, value, max)` expression.
|
||||
|
||||
* If `min`, `max`, or `clamp` is or transitively contains a quoted `SassString`,
|
||||
throw an error.
|
||||
|
||||
* If `value` is undefined and `max` is not undefined, throw an error.
|
||||
|
||||
* If `value` or `max` is undefined and neither `min` nor `value` is a
|
||||
`SassString` that begins with `"var("`, throw an error.
|
||||
|
||||
* Return a calculation with name `"clamp"` and `min`, `value`, and `max` as its
|
||||
arguments, excluding any arguments that are undefined.
|
||||
|
||||
```ts
|
||||
static clamp(
|
||||
min: CalculationValue,
|
||||
value?: CalculationValue,
|
||||
max?: CalculationValue
|
||||
): SassCalculation;
|
||||
```
|
||||
|
||||
#### `name`
|
||||
|
||||
Returns [`internal`]'s `name` field.
|
||||
|
||||
[`internal`]: #internal
|
||||
|
||||
```ts
|
||||
get name(): string;
|
||||
```
|
||||
|
||||
Returns a list of [`internal`]'s arguments.
|
||||
|
||||
```ts
|
||||
get arguments(): List<CalculationValue>;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SassCalculation
|
||||
```
|
||||
|
||||
### `CalculationOperator`
|
||||
|
||||
The set of possible operators in a Sass calculation.
|
||||
|
||||
```ts
|
||||
type CalculationOperator = '+' | '-' | '*' | '/';
|
||||
```
|
||||
|
||||
### `CalculationOperation`
|
||||
|
||||
The JS API representation of a Sass [`CalculationOperation`].
|
||||
|
||||
[CalculationOperation]: ../spec/types/calculation.md#types
|
||||
|
||||
```ts
|
||||
export abstract class CalculationOperation implements ValueObject {
|
||||
```
|
||||
|
||||
#### `internal`
|
||||
|
||||
A private property like [`Value.internal`] that refers to a Sass
|
||||
[`CalculationOperation`].
|
||||
|
||||
[`Value.internal`]: ../spec/js-api/value/index.d.ts.md
|
||||
|
||||
#### Constructor
|
||||
|
||||
Creates a Sass CalculationOperation by setting the fields to the arguments of
|
||||
the corresponding names, and returns it.
|
||||
|
||||
|
||||
```ts
|
||||
constructor(
|
||||
operator: CalculationOperator,
|
||||
left: CalculationValue,
|
||||
right: CalculationValue
|
||||
);
|
||||
```
|
||||
|
||||
#### `operator`
|
||||
|
||||
Returns [`internal`][co-internal]'s `operator` field.
|
||||
|
||||
[co-internal]: #internal-1
|
||||
|
||||
```ts
|
||||
get operator(): CalculationOperator;
|
||||
```
|
||||
|
||||
#### `left`
|
||||
|
||||
Returns [`internal`][co-internal]'s `left` field.
|
||||
|
||||
```ts
|
||||
get left(): CalculationValue;
|
||||
```
|
||||
|
||||
#### `right`
|
||||
|
||||
Returns [`internal`][co-internal]'s `right` field.
|
||||
|
||||
```ts
|
||||
get right(): CalculationValue;
|
||||
```
|
||||
|
||||
#### `equals`
|
||||
|
||||
Whether [`internal`][co-internal] is equal to `other.internal` in Sass
|
||||
|
||||
```ts
|
||||
equals(other: CalculationOperation): boolean;
|
||||
```
|
||||
|
||||
#### `hashCode`
|
||||
|
||||
Returns the same number for any two `CalculationOperation`s that are equal
|
||||
according to [`equals`](#equals).
|
||||
|
||||
```ts
|
||||
hashCode(): number;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // CalculationOperation
|
||||
```
|
||||
|
||||
### `CalculationInterpolation`
|
||||
|
||||
The JS API representation of a Sass [`CalculationInterpolation`].
|
||||
|
||||
[`CalculationInterpolation`]: ../spec/types/calculation.md#types
|
||||
|
||||
```ts
|
||||
export abstract 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.
|
||||
|
||||
```ts
|
||||
constructor(value: string);
|
||||
```
|
||||
|
||||
#### `value`
|
||||
|
||||
Returns [`internal`][ci-internal]'s `value` field.
|
||||
|
||||
[ci-internal]: #internal-2
|
||||
|
||||
```ts
|
||||
get value(): string;
|
||||
```
|
||||
|
||||
#### `equals`
|
||||
|
||||
Whether [`internal`][ci-internal] is equal to `other.internal` in Sass.
|
||||
|
||||
```ts
|
||||
equals(other: CalculationOperation): boolean;
|
||||
```
|
||||
|
||||
#### `hashCode`
|
||||
|
||||
Returns the same number for any two `CalculationInterpolation`s that are equal
|
||||
according to [`equals`](#equals-1).
|
||||
|
||||
```ts
|
||||
hashCode(): number;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // CalculationInterpolation
|
||||
```
|
26
package-lock.json
generated
26
package-lock.json
generated
@ -8,6 +8,7 @@
|
||||
"dependencies": {
|
||||
"@types/diff": "^5.0.1",
|
||||
"@types/glob": "^7.1.4",
|
||||
"@types/marked": "^4.0.8",
|
||||
"@types/prettier": "^2.4.1",
|
||||
"colors": "^1.3.3",
|
||||
"diff": "^5.0.0",
|
||||
@ -16,8 +17,10 @@
|
||||
"indent-string": "^4.0.0",
|
||||
"markdown-link-check": "3.11.1",
|
||||
"markdown-toc": "^1.2.0",
|
||||
"marked": "^4.3.0",
|
||||
"prettier": "^2.4.1",
|
||||
"source-map-js": "^0.6.2",
|
||||
"ts-dedent": "^2.2.0",
|
||||
"ts-node": "^10.2.1",
|
||||
"typedoc": "^0.22.4"
|
||||
},
|
||||
@ -276,6 +279,11 @@
|
||||
"integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/marked": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.0.8.tgz",
|
||||
"integrity": "sha512-HVNzMT5QlWCOdeuBsgXP8EZzKUf0+AXzN+sLmjvaB3ZlLqO+e4u0uXrdw9ub69wBKFs+c6/pA4r9sy6cCDvImw=="
|
||||
},
|
||||
"node_modules/@types/minimatch": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
|
||||
@ -3742,6 +3750,14 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-dedent": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz",
|
||||
"integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==",
|
||||
"engines": {
|
||||
"node": ">=6.10"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.3.1.tgz",
|
||||
@ -4249,6 +4265,11 @@
|
||||
"integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/marked": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.0.8.tgz",
|
||||
"integrity": "sha512-HVNzMT5QlWCOdeuBsgXP8EZzKUf0+AXzN+sLmjvaB3ZlLqO+e4u0uXrdw9ub69wBKFs+c6/pA4r9sy6cCDvImw=="
|
||||
},
|
||||
"@types/minimatch": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
|
||||
@ -6804,6 +6825,11 @@
|
||||
"integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
|
||||
"dev": true
|
||||
},
|
||||
"ts-dedent": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz",
|
||||
"integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="
|
||||
},
|
||||
"ts-node": {
|
||||
"version": "10.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.3.1.tgz",
|
||||
|
13
package.json
13
package.json
@ -12,14 +12,17 @@
|
||||
"link-check": "npx ts-node test/link-check.ts",
|
||||
"toc-check": "npx ts-node test/toc-check.ts",
|
||||
"update-toc": "npx ts-node tool/update-toc.ts",
|
||||
"js-api-doc-check": "npx ts-node test/js-api-doc-check.ts",
|
||||
"typedoc": "npx typedoc --treatWarningsAsErrors js-api-doc/index.d.ts",
|
||||
"fix": "gts fix",
|
||||
"test": "gts lint && tsc --noEmit && npm run toc-check && npm run link-check && npm run js-api-doc-check && npm run typedoc"
|
||||
"js-api-doc-check": "npm run tangle && npx ts-node test/js-api-doc-check.ts",
|
||||
"typedoc": "npm run tangle && npx typedoc --treatWarningsAsErrors js-api-doc/index.d.ts",
|
||||
"tangle": "npx ts-node tool/tangle.ts",
|
||||
"untangle": "npx ts-node tool/untangle.ts",
|
||||
"fix": "npm run update-toc && npm run tangle && gts fix && npm run untangle",
|
||||
"test": "npm run tangle && gts lint && tsc --noEmit && npm run toc-check && npm run link-check && npm run js-api-doc-check && npm run typedoc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/diff": "^5.0.1",
|
||||
"@types/glob": "^7.1.4",
|
||||
"@types/marked": "^4.0.8",
|
||||
"@types/prettier": "^2.4.1",
|
||||
"colors": "^1.3.3",
|
||||
"diff": "^5.0.0",
|
||||
@ -28,8 +31,10 @@
|
||||
"indent-string": "^4.0.0",
|
||||
"markdown-link-check": "3.11.1",
|
||||
"markdown-toc": "^1.2.0",
|
||||
"marked": "^4.3.0",
|
||||
"prettier": "^2.4.1",
|
||||
"source-map-js": "^0.6.2",
|
||||
"ts-dedent": "^2.2.0",
|
||||
"ts-node": "^10.2.1",
|
||||
"typedoc": "^0.22.4"
|
||||
},
|
||||
|
356
proposal/js-deprecations.d.ts
vendored
356
proposal/js-deprecations.d.ts
vendored
@ -1,356 +0,0 @@
|
||||
/**
|
||||
* # JavaScript Deprecations API: Draft 1.1
|
||||
*
|
||||
* *([Issue](https://github.com/sass/sass/issues/3520),
|
||||
* [Changelog](js-deprecations.changes.md))*
|
||||
*
|
||||
* ## Background
|
||||
*
|
||||
* > This section is non-normative.
|
||||
*
|
||||
* We recently added support to Dart Sass that allowed users to opt in to
|
||||
* treating deprecation warnings as errors (on a per-deprecation basis), as
|
||||
* well as opting in early to certain future deprecations. This is currently
|
||||
* supported on the command line and via the Dart API, but we'd like to extend
|
||||
* this support to the JS API as well.
|
||||
*
|
||||
* We would also like to add support for silencing a particular deprecation's
|
||||
* warnings, primarily to enable a gentler process for deprecating `@import`.
|
||||
*
|
||||
* ## Summary
|
||||
*
|
||||
* > This section is non-normative.
|
||||
*
|
||||
* This proposal adds a new `Deprecation` interface and `Version` class to the
|
||||
* JS API, three new optional properties on `Options` (`fatalDeprecations`,
|
||||
* `silenceDeprecations`, and `futureDeprecations`), a new parameter on
|
||||
* `Logger.warn` (`options.deprecationType`) two type aliases (`DeprecationOrId`
|
||||
* and `DeprecationStatus`) and a new object `deprecations` that contains the
|
||||
* various `Deprecation` objects.
|
||||
*
|
||||
* All deprecations are specified in `deprecations`, and any new deprecations
|
||||
* added in the future (even those specific to a particular implementation)
|
||||
* should update the specification accordingly. Deprecations should never be
|
||||
* removed from the specification; when the behavior being deprecated is removed
|
||||
* (i.e. there's a major version release), the deprecation status should be
|
||||
* changed to obsolete, but remain in the specification.
|
||||
*
|
||||
* Every `Deprecation` has a unique `id`, one of four `status` values, and
|
||||
* (optionally) a human-readable `description`. Depending on the status, each
|
||||
* deprecation may also have a `deprecatedIn` version and an `obsoleteIn`
|
||||
* version that specify the compiler versions the deprecation became active
|
||||
* and became obsolete in, respectively.
|
||||
*
|
||||
* ### Design Decisions
|
||||
*
|
||||
* #### Exposing the Full `Deprecation` Interface
|
||||
*
|
||||
* One alternative to specifying a full `Deprecation` interface is to just have
|
||||
* the relevant APIs take in string IDs. We considered this, but concluded that
|
||||
* each deprecation has additional metadata that users of the API may wish to
|
||||
* access (for example, a bundler may wish to surface the `description` and
|
||||
* `deprecatedIn` version to its users).
|
||||
*
|
||||
* #### Formally Specifying the Deprecations
|
||||
*
|
||||
* We chose to make the list of deprecations part of the specification itself,
|
||||
* as this ensures that the language-wide deprecations are consistent across
|
||||
* implementations. However, if an implementation wishes to add a deprecation
|
||||
* that applies only to itself, it may still do so.
|
||||
*
|
||||
* Additionally, we chose to leave the `status`, `deprecatedIn` version, and
|
||||
* `obsoleteIn` version of each deprecation out of the specification. As the
|
||||
* two current implementers of this API are both based on Dart Sass, these
|
||||
* fields are _currently_ consistent across implementations in practice, but
|
||||
* the status of each deprecation in other potential future implementers would
|
||||
* not always match Dart Sass, and the relevent versions would almost certainly
|
||||
* not match.
|
||||
*
|
||||
* #### Warnings for Invalid Deprecations and Precedence of Options
|
||||
*
|
||||
* Whenever potentially invalid sets of deprecations are passed to any of the
|
||||
* options, we choose to emit warnings rather than errors, as the status of
|
||||
* each deprecation can change over time, and users may share a configuration
|
||||
* when compiling across multiple implementations/versions whose dependency
|
||||
* statuses may not be in sync.
|
||||
*
|
||||
* The situations we chose to warn for are:
|
||||
*
|
||||
* - an invalid string ID.
|
||||
*
|
||||
* This is disallowed by the API's types, but may still occur at runtime,
|
||||
* and should be warned for accordingly.
|
||||
*
|
||||
* - a future deprecation is passed to `fatalDeprecations` but not
|
||||
* `futureDeprecations`.
|
||||
*
|
||||
* In this scenario, the future deprecation will still be treated as fatal,
|
||||
* but we want to warn users to prevent situtations where a user tries to
|
||||
* make every deprecation fatal and ends up including future ones too.
|
||||
*
|
||||
* - an obsolete deprecation is passed to `fatalDeprecations`.
|
||||
*
|
||||
* If a deprecation is obsolete, that means the breaking change has already
|
||||
* happened, so making it fatal is a no-op.
|
||||
*
|
||||
* - passing anything other than an active deprecation to `silenceDeprecations`.
|
||||
*
|
||||
* This is particularly important for obsolete deprecations, since otherwise
|
||||
* users may not be aware of a subtle breaking change for which they were
|
||||
* previously silencing warnings. We also warn for passing
|
||||
* `Deprecation.userAuthored`, since there's no way to distinguish between
|
||||
* different deprecations from user-authored code, so silencing them as a
|
||||
* group is inadvisable. Passing a future deprecation here is either a no-op,
|
||||
* or cancels out passing it to `futureDeprecations`, so we warn for that as
|
||||
* well.
|
||||
*
|
||||
* - passing a non-future deprecation to `futureDeprecations`.
|
||||
*
|
||||
* This is a no-op, so we should warn users so they can clean up their
|
||||
* configuration.
|
||||
*/
|
||||
|
||||
/* ## API */
|
||||
|
||||
import {SourceSpan} from '../spec/js-api';
|
||||
|
||||
declare module '../spec/js-api' {
|
||||
interface Options<sync extends 'sync' | 'async'> {
|
||||
/**
|
||||
* A set of deprecations to treat as fatal.
|
||||
*
|
||||
* If a deprecation warning of any provided type is encountered during
|
||||
* compilation, the compiler must error instead.
|
||||
*
|
||||
* The compiler should convert any string passed here to a `Deprecation`
|
||||
* by indexing `deprecations`. *
|
||||
* If a version is passed here, it should be treated equivalently to passing
|
||||
* all active deprecations whose `deprecatedIn` version is less than or
|
||||
* equal to it.
|
||||
*
|
||||
* The compiler must error if a future deprecation is included here, unless
|
||||
* that future deprecation is also passed to `futureDeprecations`. It must
|
||||
* emit a warning if an obsolete deprecation is included here.
|
||||
*
|
||||
* If a deprecation is passed both here and to `silenceDeprecations`, a
|
||||
* warning must be emitted, but making the deprecation fatal must take
|
||||
* precedence.
|
||||
*/
|
||||
fatalDeprecations?: (DeprecationOrId | Version)[];
|
||||
|
||||
/**
|
||||
* A set of active deprecations to ignore.
|
||||
*
|
||||
* If a deprecation warning of any provided type is encountered during
|
||||
* compilation, the compiler must ignore it.
|
||||
*
|
||||
* The compiler should convert any string passed here to a `Deprecation`
|
||||
* by indexing `Deprecations`.
|
||||
*
|
||||
* The compiler must error if an obsolete deprecation or
|
||||
* `deprecations['user-authored']` is included here. It must emit a warning
|
||||
* if a future deprecation is included here, but silencing it takes
|
||||
* precedence over `futureDeprecations` enabling it.
|
||||
*/
|
||||
silenceDeprecations?: DeprecationOrId[];
|
||||
|
||||
/**
|
||||
* A set of future deprecations to opt into early.
|
||||
*
|
||||
* For each future deprecation provided here, the compiler must treat that
|
||||
* deprecation as if it is active, emitting warnings as necessary (subject
|
||||
* to `fatalDeprecations` and `silenceDeprecations`).
|
||||
*
|
||||
* The compiler should convert any string passed here to a `Deprecation`
|
||||
* by indexing `Deprecations`.
|
||||
*
|
||||
* The compiler must emit a warning if a non-future deprecation is included
|
||||
* here.
|
||||
*/
|
||||
futureDeprecations?: DeprecationOrId[];
|
||||
}
|
||||
|
||||
interface Logger {
|
||||
/**
|
||||
* Update the third sub-bullet of bullet two to read:
|
||||
*
|
||||
* If this warning is caused by behavior that used to be allowed but will
|
||||
* be disallowed in the future, set `options.deprecation` to `true` and
|
||||
* set `options.deprecationType` to the relevant `Deprecation`. Otherwise,
|
||||
* set `options.deprecation` to `false` and leave `options.deprecationType`
|
||||
* undefined.
|
||||
*/
|
||||
warn?(
|
||||
message: string,
|
||||
options: {
|
||||
deprecation: boolean;
|
||||
deprecationType?: Deprecation;
|
||||
span?: SourceSpan;
|
||||
stack?: string;
|
||||
}
|
||||
): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An object containing all of the deprecations.
|
||||
*/
|
||||
export const deprecations: Deprecations;
|
||||
}
|
||||
|
||||
interface Deprecations {
|
||||
/** Deprecation for passing a string to `call` instead of `get-function`. */
|
||||
'call-string': Deprecation<'call-string'>;
|
||||
|
||||
/** Deprecation for `@elseif`. */
|
||||
elseif: Deprecation<'elseif'>;
|
||||
|
||||
/** Deprecation for parsing `@-moz-document`. */
|
||||
'moz-document': Deprecation<'moz-document'>;
|
||||
|
||||
/** Deprecation for importers using relative canonical URLs. */
|
||||
'relative-canonical': Deprecation<'relative-canonical'>;
|
||||
|
||||
/** Deprecation for declaring new variables with `!global`. */
|
||||
'new-global': Deprecation<'new-global'>;
|
||||
|
||||
/**
|
||||
* Deprecation for certain functions in the color module matching the
|
||||
* behavior of their global counterparts for compatibility reasons.
|
||||
*/
|
||||
'color-module-compat': Deprecation<'color-module-compat'>;
|
||||
|
||||
/**
|
||||
* Deprecation for treaing `/` as division.
|
||||
*
|
||||
* Update the proposal for forward slash as a separator to say that it emits
|
||||
* deprecation warnings with ID 'slash-div'.
|
||||
*/
|
||||
'slash-div': Deprecation<'slash-div'>;
|
||||
|
||||
/**
|
||||
* Deprecation for leading, trailing, and repeated combinators.
|
||||
*
|
||||
* Update the proposal for bogus combinators to say that it emits deprecation
|
||||
* warnings with ID 'bogus-combinators'.
|
||||
*/
|
||||
'bogus-combinators': Deprecation<'bogus-combinators'>;
|
||||
|
||||
/**
|
||||
* Deprecation for ambiguous `+` and `-` operators.
|
||||
*
|
||||
* Update the proposal for strict unary operators to say that it emits
|
||||
* deprecation warnings with ID 'strict-unary'.
|
||||
*/
|
||||
'strict-unary': Deprecation<'strict-unary'>;
|
||||
|
||||
/**
|
||||
* Deprecation for passing invalid units to certain built-in functions.
|
||||
*
|
||||
* Update the proposals for function units, random with units, and angle units
|
||||
* to say that they emit deprecation warnings with ID 'function-units'.
|
||||
*/
|
||||
'function-units': Deprecation<'function-units'>;
|
||||
|
||||
/**
|
||||
* Deprecation for using multiple `!global` or `!default` flags on a single
|
||||
* variable.
|
||||
*
|
||||
* > This deprecation was never explicitly listed in a proposal.
|
||||
*/
|
||||
'duplicate-var-flags': Deprecation<'duplicate-var-flags'>;
|
||||
|
||||
/**
|
||||
* Deprecation for `@import` rules.
|
||||
*
|
||||
* Update the proposal for the module system to say that, when `@import` is
|
||||
* deprecated, Sass will emit deprecation warnings with ID 'import' when
|
||||
* `@import` rules are encountered.
|
||||
*/
|
||||
import: Deprecation<'import'>;
|
||||
|
||||
/** Used for deprecations coming from user-authored code. */
|
||||
'user-authored': Deprecation<'user-authored', 'user'>;
|
||||
}
|
||||
|
||||
/** A deprecation, or the ID of one. */
|
||||
export type DeprecationOrId = Deprecation | keyof Deprecations;
|
||||
|
||||
/** A deprecation's status. */
|
||||
export type DeprecationStatus = 'active' | 'user' | 'future' | 'obsolete';
|
||||
|
||||
/** A deprecated feature in the language. */
|
||||
export interface Deprecation<
|
||||
id extends keyof Deprecations = keyof Deprecations,
|
||||
status extends DeprecationStatus = DeprecationStatus
|
||||
> {
|
||||
/**
|
||||
* A kebab-case ID for this deprecation.
|
||||
*/
|
||||
id: id;
|
||||
|
||||
/**
|
||||
* The status of this deprecation.
|
||||
*
|
||||
* - 'active' means this deprecation is currently enabled. `deprecatedIn` is
|
||||
* non-null and `obsoleteIn` is null.
|
||||
* - 'user' means this deprecation is from user-authored code. Both
|
||||
* `deprecatedIn` and `obsoleteIn` are null.
|
||||
* - 'future' means this deprecation is not yet enabled. Both `deprecatedIn`
|
||||
* and `obsoleteIn` are null.
|
||||
* - 'obsolete' means this deprecation is now obsolete, as the feature it was
|
||||
* for has been fully removed. Both `deprecatedIn` and `obsoleteIn` are
|
||||
* non-null.
|
||||
*/
|
||||
status: status;
|
||||
|
||||
/** A brief user-readable description of this deprecation. */
|
||||
description?: string;
|
||||
|
||||
/**
|
||||
* The compiler version this feature was first deprecated in.
|
||||
*
|
||||
* This is implementation-dependent, so versions are not guaranteed to be
|
||||
* consistent between different compilers. For future deprecations, or those
|
||||
* originating from user-authored code, this is null.
|
||||
*/
|
||||
deprecatedIn: status extends 'future' | 'user' ? null : Version;
|
||||
|
||||
/**
|
||||
* The compiler version this feature was fully removed in, making the
|
||||
* deprecation obsolete.
|
||||
*
|
||||
* This is null for active and future deprecations.
|
||||
*/
|
||||
obsoleteIn: status extends 'obsolete' ? Version : null;
|
||||
}
|
||||
|
||||
/** A semantic version of the compiler. */
|
||||
export class Version {
|
||||
/**
|
||||
* The major version.
|
||||
*
|
||||
* This must be a non-negative integer.
|
||||
*/
|
||||
readonly major: number;
|
||||
|
||||
/**
|
||||
* The minor version.
|
||||
*
|
||||
* This must be a non-negative integer.
|
||||
*/
|
||||
readonly minor: number;
|
||||
|
||||
/**
|
||||
* The patch version.
|
||||
*
|
||||
* This must be a non-negative integer.
|
||||
*/
|
||||
readonly patch: number;
|
||||
|
||||
constructor(major: number, minor: number, patch: number);
|
||||
|
||||
/**
|
||||
* Parses a string in the form "major.minor.patch" into a `Version`.
|
||||
*/
|
||||
static parse(version: string): Version;
|
||||
}
|
516
proposal/js-deprecations.d.ts.md
Normal file
516
proposal/js-deprecations.d.ts.md
Normal file
@ -0,0 +1,516 @@
|
||||
# JavaScript Deprecations API: Draft 1.1
|
||||
|
||||
*([Issue](https://github.com/sass/sass/issues/3520),
|
||||
[Changelog](js-deprecations.changes.md))*
|
||||
|
||||
## Background
|
||||
|
||||
> This section is non-normative.
|
||||
|
||||
We recently added support to Dart Sass that allowed users to opt in to
|
||||
treating deprecation warnings as errors (on a per-deprecation basis), as
|
||||
well as opting in early to certain future deprecations. This is currently
|
||||
supported on the command line and via the Dart API, but we'd like to extend
|
||||
this support to the JS API as well.
|
||||
|
||||
We would also like to add support for silencing a particular deprecation's
|
||||
warnings, primarily to enable a gentler process for deprecating `@import`.
|
||||
|
||||
## Summary
|
||||
|
||||
> This section is non-normative.
|
||||
|
||||
This proposal adds a new `Deprecation` interface and `Version` class to the
|
||||
JS API, three new optional properties on `Options` (`fatalDeprecations`,
|
||||
`silenceDeprecations`, and `futureDeprecations`), a new parameter on
|
||||
`Logger.warn` (`options.deprecationType`) two type aliases (`DeprecationOrId`
|
||||
and `DeprecationStatus`) and a new object `deprecations` that contains the
|
||||
various `Deprecation` objects.
|
||||
|
||||
All deprecations are specified in `deprecations`, and any new deprecations
|
||||
added in the future (even those specific to a particular implementation)
|
||||
should update the specification accordingly. Deprecations should never be
|
||||
removed from the specification; when the behavior being deprecated is removed
|
||||
(i.e. there's a major version release), the deprecation status should be
|
||||
changed to obsolete, but remain in the specification.
|
||||
|
||||
Every `Deprecation` has a unique `id`, one of four `status` values, and
|
||||
(optionally) a human-readable `description`. Depending on the status, each
|
||||
deprecation may also have a `deprecatedIn` version and an `obsoleteIn`
|
||||
version that specify the compiler versions the deprecation became active
|
||||
and became obsolete in, respectively.
|
||||
|
||||
### Design Decisions
|
||||
|
||||
#### Exposing the Full `Deprecation` Interface
|
||||
|
||||
One alternative to specifying a full `Deprecation` interface is to just have
|
||||
the relevant APIs take in string IDs. We considered this, but concluded that
|
||||
each deprecation has additional metadata that users of the API may wish to
|
||||
access (for example, a bundler may wish to surface the `description` and
|
||||
`deprecatedIn` version to its users).
|
||||
|
||||
#### Formally Specifying the Deprecations
|
||||
|
||||
We chose to make the list of deprecations part of the specification itself,
|
||||
as this ensures that the language-wide deprecations are consistent across
|
||||
implementations. However, if an implementation wishes to add a deprecation
|
||||
that applies only to itself, it may still do so.
|
||||
|
||||
Additionally, while a deprecation's status is part of the specification, we
|
||||
chose to leave the `deprecatedIn` and `obsoleteIn` versions of each
|
||||
deprecation out of the specification. As the two current implementers of this
|
||||
API are both based on Dart Sass, these versions are _currently_ consistent
|
||||
across implementations in practice, potential future implementers should not
|
||||
need to be tied to Dart Sass's versioning.
|
||||
|
||||
#### Warnings for Invalid Deprecations and Precedence of Options
|
||||
|
||||
Whenever potentially invalid sets of deprecations are passed to any of the
|
||||
options, we choose to emit warnings rather than errors, as the status of
|
||||
each deprecation can change over time, and users may share a configuration
|
||||
when compiling across multiple implementations/versions whose dependency
|
||||
statuses may not be in sync.
|
||||
|
||||
The situations we chose to warn for are:
|
||||
|
||||
* an invalid string ID.
|
||||
|
||||
This is disallowed by the API's types, but may still occur at runtime,
|
||||
and should be warned for accordingly.
|
||||
|
||||
* a future deprecation is passed to `fatalDeprecations` but not
|
||||
`futureDeprecations`.
|
||||
|
||||
In this scenario, the future deprecation will still be treated as fatal,
|
||||
but we want to warn users to prevent situtations where a user tries to
|
||||
make every deprecation fatal and ends up including future ones too.
|
||||
|
||||
* an obsolete deprecation is passed to `fatalDeprecations`.
|
||||
|
||||
If a deprecation is obsolete, that means the breaking change has already
|
||||
happened, so making it fatal is a no-op.
|
||||
|
||||
* passing anything other than an active deprecation to `silenceDeprecations`.
|
||||
|
||||
This is particularly important for obsolete deprecations, since otherwise
|
||||
users may not be aware of a subtle breaking change for which they were
|
||||
previously silencing warnings. We also warn for passing
|
||||
`Deprecation.userAuthored`, since there's no way to distinguish between
|
||||
different deprecations from user-authored code, so silencing them as a
|
||||
group is inadvisable. Passing a future deprecation here is either a no-op,
|
||||
or cancels out passing it to `futureDeprecations`, so we warn for that as
|
||||
well.
|
||||
|
||||
* passing a non-future deprecation to `futureDeprecations`.
|
||||
|
||||
This is a no-op, so we should warn users so they can clean up their
|
||||
configuration.
|
||||
|
||||
## API
|
||||
|
||||
```ts
|
||||
import {SourceSpan} from '../spec/js-api';
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
### `Options`
|
||||
|
||||
```ts
|
||||
declare module '../spec/js-api' {
|
||||
interface Options<sync extends 'sync' | 'async'> {
|
||||
```
|
||||
|
||||
#### `fatalDeprecations`
|
||||
|
||||
A set of deprecations to treat as fatal.
|
||||
|
||||
If a deprecation warning of any provided type is encountered during compilation,
|
||||
the compiler must error instead.
|
||||
|
||||
The compiler should convert any string passed here to a `Deprecation` by
|
||||
indexing `deprecations`. If a version is passed here, it should be treated
|
||||
equivalently to passing all active deprecations whose `deprecatedIn` version is
|
||||
less than or equal to it.
|
||||
|
||||
The compiler must error if a future deprecation is included here, unless that
|
||||
future deprecation is also passed to `futureDeprecations`. It must emit a
|
||||
warning if an obsolete deprecation is included here.
|
||||
|
||||
If a deprecation is passed both here and to `silenceDeprecations`, a warning
|
||||
must be emitted, but making the deprecation fatal must take precedence.
|
||||
|
||||
```ts
|
||||
fatalDeprecations?: (DeprecationOrId | Version)[];
|
||||
```
|
||||
|
||||
#### `silenceDeprecations`
|
||||
|
||||
A set of active deprecations to ignore.
|
||||
|
||||
If a deprecation warning of any provided type is encountered during compilation,
|
||||
the compiler must ignore it.
|
||||
|
||||
The compiler should convert any string passed here to a `Deprecation` by
|
||||
indexing `Deprecations`.
|
||||
|
||||
The compiler must error if an obsolete deprecation or
|
||||
`deprecations['user-authored']` is included here. It must emit a warning if a
|
||||
future deprecation is included here, but silencing it takes precedence over
|
||||
`futureDeprecations` enabling it.
|
||||
|
||||
```ts
|
||||
silenceDeprecations?: DeprecationOrId[];
|
||||
```
|
||||
|
||||
#### `futureDeprecations`
|
||||
|
||||
A set of future deprecations to opt into early.
|
||||
|
||||
For each future deprecation provided here, the compiler must treat that
|
||||
deprecation as if it is active, emitting warnings as necessary (subject to
|
||||
`fatalDeprecations` and `silenceDeprecations`).
|
||||
|
||||
The compiler should convert any string passed here to a `Deprecation` by
|
||||
indexing `Deprecations`.
|
||||
|
||||
The compiler must emit a warning if a non-future deprecation is included here.
|
||||
|
||||
```ts
|
||||
futureDeprecations?: DeprecationOrId[];
|
||||
```
|
||||
|
||||
```ts
|
||||
} // Options
|
||||
```
|
||||
|
||||
### `Logger`
|
||||
|
||||
```ts
|
||||
interface Logger {
|
||||
```
|
||||
|
||||
#### `warn`
|
||||
|
||||
Update the third sub-bullet of bullet two to read:
|
||||
|
||||
If this warning is caused by behavior that used to be allowed but will be
|
||||
disallowed in the future, set `options.deprecation` to `true` and set
|
||||
`options.deprecationType` to the relevant `Deprecation`. Otherwise, set
|
||||
`options.deprecation` to `false` and leave `options.deprecationType` undefined.
|
||||
|
||||
```ts
|
||||
warn?(
|
||||
message: string,
|
||||
options: {
|
||||
deprecation: boolean;
|
||||
deprecationType?: Deprecation;
|
||||
span?: SourceSpan;
|
||||
stack?: string;
|
||||
}
|
||||
): void;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // Logger
|
||||
} // module
|
||||
```
|
||||
|
||||
### `Deprecations`
|
||||
|
||||
```ts
|
||||
interface Deprecations {
|
||||
```
|
||||
|
||||
#### `call-string`
|
||||
|
||||
Deprecation for passing a string to `call` instead of `get-function`.
|
||||
|
||||
```ts
|
||||
'call-string': Deprecation<'call-string'>;
|
||||
```
|
||||
|
||||
#### `elseif`
|
||||
|
||||
Deprecation for `@elseif`.
|
||||
|
||||
```ts
|
||||
elseif: Deprecation<'elseif'>;
|
||||
```
|
||||
|
||||
#### `moz-document`
|
||||
|
||||
Deprecation for parsing `@-moz-document`.
|
||||
|
||||
```ts
|
||||
'moz-document': Deprecation<'moz-document'>;
|
||||
```
|
||||
|
||||
#### `relative-canonical`
|
||||
|
||||
Deprecation for importers using relative canonical URLs.
|
||||
|
||||
```ts
|
||||
'relative-canonical': Deprecation<'relative-canonical'>;
|
||||
```
|
||||
|
||||
#### `new-global`
|
||||
|
||||
Deprecation for declaring new variables with `!global`.
|
||||
|
||||
```ts
|
||||
'new-global': Deprecation<'new-global'>;
|
||||
```
|
||||
|
||||
#### `color-module-compat`
|
||||
|
||||
Deprecation for certain functions in the color module matching the
|
||||
behavior of their global counterparts for compatibility reasons.
|
||||
|
||||
```ts
|
||||
'color-module-compat': Deprecation<'color-module-compat'>;
|
||||
```
|
||||
|
||||
#### `slash-div`
|
||||
|
||||
Deprecation for treaing `/` as division.
|
||||
|
||||
Update the proposal for forward slash as a separator to say that it emits
|
||||
deprecation warnings with ID 'slash-div'.
|
||||
|
||||
```ts
|
||||
'slash-div': Deprecation<'slash-div'>;
|
||||
```
|
||||
|
||||
#### `bogus-combinators`
|
||||
|
||||
Deprecation for leading, trailing, and repeated combinators.
|
||||
|
||||
Update the proposal for bogus combinators to say that it emits deprecation
|
||||
warnings with ID 'bogus-combinators'.
|
||||
|
||||
```ts
|
||||
'bogus-combinators': Deprecation<'bogus-combinators'>;
|
||||
```
|
||||
|
||||
#### `strict-unary`
|
||||
|
||||
Deprecation for ambiguous `+` and `-` operators.
|
||||
|
||||
Update the proposal for strict unary operators to say that it emits deprecation
|
||||
warnings with ID 'strict-unary'.
|
||||
|
||||
```ts
|
||||
'strict-unary': Deprecation<'strict-unary'>;
|
||||
```
|
||||
|
||||
#### `function-units`
|
||||
|
||||
Deprecation for passing invalid units to certain built-in functions.
|
||||
|
||||
Update the proposals for function units, random with units, and angle units to
|
||||
say that they emit deprecation warnings with ID 'function-units'.
|
||||
|
||||
```ts
|
||||
'function-units': Deprecation<'function-units'>;
|
||||
```
|
||||
|
||||
#### `duplicate-var-flags`
|
||||
|
||||
Deprecation for using multiple `!global` or `!default` flags on a single
|
||||
variable.
|
||||
|
||||
> This deprecation was never explicitly listed in a proposal.
|
||||
|
||||
```ts
|
||||
'duplicate-var-flags': Deprecation<'duplicate-var-flags'>;
|
||||
```
|
||||
|
||||
#### `import`
|
||||
|
||||
Deprecation for `@import` rules.
|
||||
|
||||
Update the proposal for the module system to say that, when `@import` is
|
||||
deprecated, Sass will emit deprecation warnings with ID 'import' when `@import`
|
||||
rules are encountered.
|
||||
|
||||
```ts
|
||||
import: Deprecation<'import'>;
|
||||
```
|
||||
|
||||
#### `user-authored`
|
||||
|
||||
Used for deprecations coming from user-authored code.
|
||||
|
||||
```ts
|
||||
'user-authored': Deprecation<'user-authored', 'user'>;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // Deprecations
|
||||
```
|
||||
|
||||
### `DeprecationOrId`
|
||||
|
||||
A deprecation, or the ID of one.
|
||||
|
||||
```ts
|
||||
export type DeprecationOrId = Deprecation | keyof Deprecations;
|
||||
```
|
||||
|
||||
### `DeprecationStatus`
|
||||
|
||||
A deprecation's status.
|
||||
|
||||
```ts
|
||||
export type DeprecationStatus = 'active' | 'user' | 'future' | 'obsolete';
|
||||
```
|
||||
|
||||
### `Deprecation`
|
||||
|
||||
A deprecated feature in the language.
|
||||
|
||||
```ts
|
||||
export interface Deprecation<
|
||||
id extends keyof Deprecations = keyof Deprecations,
|
||||
status extends DeprecationStatus = DeprecationStatus
|
||||
> {
|
||||
```
|
||||
|
||||
#### `id`
|
||||
|
||||
A kebab-case ID for this deprecation.
|
||||
|
||||
```ts
|
||||
id: id;
|
||||
```
|
||||
|
||||
The status of this deprecation.
|
||||
|
||||
* 'active' means this deprecation is currently enabled. `deprecatedIn` is
|
||||
non-null and `obsoleteIn` is null.
|
||||
* 'user' means this deprecation is from user-authored code. Both `deprecatedIn`
|
||||
and `obsoleteIn` are null.
|
||||
* 'future' means this deprecation is not yet enabled. Both `deprecatedIn` and
|
||||
`obsoleteIn` are null.
|
||||
* 'obsolete' means this deprecation is now obsolete, as the feature it was for
|
||||
has been fully removed. Both `deprecatedIn` and `obsoleteIn` are non-null.
|
||||
|
||||
```ts
|
||||
status: status;
|
||||
```
|
||||
|
||||
#### `description`
|
||||
|
||||
A brief user-readable description of this deprecation.
|
||||
|
||||
```ts
|
||||
description?: string;
|
||||
```
|
||||
|
||||
#### `deprecatedIn`
|
||||
|
||||
The compiler version this feature was first deprecated in.
|
||||
|
||||
This is implementation-dependent, so versions are not guaranteed to be
|
||||
consistent between different compilers. For future deprecations, or those
|
||||
originating from user-authored code, this is null.
|
||||
|
||||
```ts
|
||||
deprecatedIn: status extends 'future' | 'user' ? null : Version;
|
||||
```
|
||||
|
||||
#### `obsoleteIn`
|
||||
|
||||
The compiler version this feature was fully removed in, making the deprecation
|
||||
obsolete.
|
||||
|
||||
This is null for active and future deprecations.
|
||||
|
||||
```ts
|
||||
obsoleteIn: status extends 'obsolete' ? Version : null;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // Deprecation
|
||||
```
|
||||
|
||||
### `Version`
|
||||
|
||||
A [semantic version] of the compiler.
|
||||
|
||||
[semantic version]: https://semver.org/
|
||||
|
||||
```ts
|
||||
export class Version {
|
||||
```
|
||||
|
||||
#### Constructor
|
||||
|
||||
Creates a new `Version` with its `major`, `minor`, and `patch` fields set to the
|
||||
corresponding arguments.
|
||||
|
||||
```ts
|
||||
constructor(major: number, minor: number, patch: number);
|
||||
```
|
||||
|
||||
#### `major`
|
||||
|
||||
The major version.
|
||||
|
||||
This must be a non-negative integer.
|
||||
|
||||
```ts
|
||||
readonly major: number;
|
||||
```
|
||||
|
||||
#### `minor`
|
||||
|
||||
The minor version.
|
||||
|
||||
This must be a non-negative integer.
|
||||
|
||||
```ts
|
||||
readonly minor: number;
|
||||
```
|
||||
|
||||
#### `patch`
|
||||
|
||||
The patch version.
|
||||
|
||||
This must be a non-negative integer.
|
||||
|
||||
```ts
|
||||
readonly patch: number;
|
||||
```
|
||||
|
||||
#### `parse`
|
||||
|
||||
Parses a string in the form "major.minor.patch" into a `Version`.
|
||||
|
||||
```ts
|
||||
static parse(version: string): Version;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // Version
|
||||
```
|
||||
|
||||
## Top-Level Members
|
||||
|
||||
```ts
|
||||
declare module '../spec/js-api' {
|
||||
```
|
||||
|
||||
### `deprecations`
|
||||
|
||||
An object containing all of the deprecations.
|
||||
|
||||
```ts
|
||||
export const deprecations: Deprecations;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // module
|
||||
```
|
185
proposal/prev-url.d.ts
vendored
185
proposal/prev-url.d.ts
vendored
@ -1,185 +0,0 @@
|
||||
/**
|
||||
* # Containing URL: Draft 1.0
|
||||
*
|
||||
* *([Issue](https://github.com/sass/sass/issues/3247))*
|
||||
*
|
||||
* ## Background
|
||||
*
|
||||
* > This section is non-normative.
|
||||
*
|
||||
* Among many other changes, the [new importer API] dropped an importer's
|
||||
* ability to access the URL of the stylesheet that contained the load, known in
|
||||
* the legacy API as the "previous URL". This was an intentional design choice
|
||||
* which enforced the invariant that the same canonical URL always refers to the
|
||||
* same file.
|
||||
*
|
||||
* [new import API]: ../accepted/new-js-importer.d.ts
|
||||
*
|
||||
* However, this restriction makes it difficult for importers to work as
|
||||
* expected in certain contexts. For example, in the Node.js ecosystem JS loads
|
||||
* depend on the structure of the `node_modules` directory closest to the
|
||||
* containing file. The new import API can't match this behavior.
|
||||
*
|
||||
* This is particularly problematic for the widely-used Webpack importer, which
|
||||
* expands on the concept of directory-specific load contexts to allow users to
|
||||
* do fine-grained customization of how differnt files will load their
|
||||
* dependencies. In order to ease migration to the new API for this plugin and
|
||||
* its users, and to better match external ecosystems' load semantics, a
|
||||
* solution is needed.
|
||||
*
|
||||
* ## Summary
|
||||
*
|
||||
* > This section is non-normative.
|
||||
*
|
||||
* This proposal adds an additional option to the `Importer.canonicalize()` API
|
||||
* that provides the canonical URL of the containing file (the "containing
|
||||
* URL"). However, in order to preserve the desired invariants, this option is
|
||||
* only provided when either:
|
||||
*
|
||||
* - `Importer.canonicalize()` is being passed a relative URL (which means the
|
||||
* URL has already been tried as a load relative to the current canonical
|
||||
* URL), or
|
||||
*
|
||||
* - `Importer.canonicalize()` is passed an absolute URL whose scheme the
|
||||
* importer has declared as non-canonical.
|
||||
*
|
||||
* A "non-canonical" scheme is a new concept introduced by this proposals.
|
||||
* Importers will optionally be able to provide a `nonCanonicalScheme` field
|
||||
* which will declare one or more URL schemes that they'll never return from
|
||||
* `canonicalize()`. (If they do, Sass will throw an error.)
|
||||
*
|
||||
* ### Design Decisions
|
||||
*
|
||||
* #### Invariants
|
||||
*
|
||||
* The specific restrictions for this API were put in place to preserve the
|
||||
* following invariants:
|
||||
*
|
||||
* 1. There must be a one-to-one mapping between canonical URLs and stylesheets.
|
||||
* This means that even when a user loads a stylesheet using a relative URL,
|
||||
* that stylesheet must have an absolute canonical URL associated with it
|
||||
* *and* loading that canonical URL must return the same stylesheet. This
|
||||
* means that any stylesheet can *always* be unambiguously loaded using its
|
||||
* canonical URL.
|
||||
*
|
||||
* 2. Relative URLs are resolved like paths and HTTP URLs. For example, within
|
||||
* `scheme:a/b/c.scss`, the URL `../d` should be resolved to `scheme:a/d`.
|
||||
*
|
||||
* 3. Loads relative to the current stylesheet always take precedence over loads
|
||||
* from importers, so if `scheme:a/b/x.scss` exists then `@use "x"` within
|
||||
* `scheme:a/b/c.scss` will always load it.
|
||||
*
|
||||
* #### Risks
|
||||
*
|
||||
* Providing access to the containing URL puts these invariants at risk in two ways:
|
||||
*
|
||||
* 1. Access to the containing URL in addition to a canonical URL makes it
|
||||
* possible for importer authors to handle the same canonical URL differently
|
||||
* depending in different contexts, violating invariant (1).
|
||||
*
|
||||
* 2. It's likely that importer authors familiar with the legacy API will
|
||||
* incorrectly assume that any containing URL that exists is the best way to
|
||||
* handle relative loads, since the only way to do so in the legacy API was
|
||||
* to manually resolve them relative to the `prev` parameter. Doing so will
|
||||
* almost certainly lead to violations of invariant (3) and possibly (2).
|
||||
*
|
||||
* #### Alternatives Considered
|
||||
*
|
||||
* To mitigate these risks, we need to have _some_ restriction on when the
|
||||
* containing URL is available to importers. We considered the following
|
||||
* alternative restrictions before settling on the current one:
|
||||
*
|
||||
* ##### Unavailable for Pre-Resolved Loads
|
||||
*
|
||||
* **Don't provide the containing URL when the `canonicalize()` function is
|
||||
* called for pre-resolved relative loads.** When the user loads a relative URL,
|
||||
* the Sass compiler first resolves that URL against the current canonical URL
|
||||
* and passes the resulting absolute URL to the current importer's
|
||||
* `canonicalize()` function. This invocation would not have access to the
|
||||
* containing URL; all other invocations would, including when Sass passes the
|
||||
* relative URL as-is to `canonicalize()`.
|
||||
*
|
||||
* This mitigates risk (2) by ensuring that all relative URL resolution is
|
||||
* handled by the compiler by default. The importer will be invoked with an
|
||||
* absolute URL and no containing URL first for each relative load, which will
|
||||
* break for any importers that naïvely try to use the containing URL in all
|
||||
* cases.
|
||||
*
|
||||
* This has several drawbacks. First, a badly-behaved importer could work around
|
||||
* this by returning `null` for all relative loads and then manually resolving
|
||||
* relative URLs as part of its load path resolution, thus continuing to violate
|
||||
* invariant (3). Second, this provides no protection against risk (1) since the
|
||||
* stylesheet author may still directly load a canonical URL.
|
||||
*
|
||||
* ##### Unavailable for Absolute Loads
|
||||
*
|
||||
* **Don't provide the containing URL when the `canonicalize()` function is
|
||||
* being called for any absolute URL.** Since relative loads always pass
|
||||
* absolute URLs to their importers first, this is a superset of "Unavailable
|
||||
* for Pre-Resolved Loads". In addition, it protects against risk (1) by
|
||||
* ensuring that all absolute URLs (which are a superset of canonical URLs) are
|
||||
* canonicalized without regard to context.
|
||||
*
|
||||
* However, this limits the functionality of importers that use a custom URL
|
||||
* scheme for *non-canonical* URLs. For example, if we choose to support
|
||||
* [package imports] by claiming the `pkg:` scheme as a "built-in package
|
||||
* importer", implementations of this scheme wouldn't be able to do
|
||||
* context-sensitive resolution. This would make the scheme useless for
|
||||
* supporting Node-style resolution, a core use-case. Given that we want to
|
||||
* encourage users to use URL schemes rather than relative URLs, this is a
|
||||
* blocking limitation.
|
||||
*
|
||||
* [package imports]: https://github.com/sass/sass/issues/2739
|
||||
*
|
||||
* Thus we arrive at the actual behavior, which makes the containing URL
|
||||
* unavailable for absolute loads _unless_ they have a URL scheme declared
|
||||
* explicitly non-canonical. This supports the `pkg:` use-case while still
|
||||
* protecting against risk (1), since the containing URL is never available for
|
||||
* canonical resolutions.
|
||||
*/
|
||||
|
||||
import {PromiseOr} from '../spec/js-api/util/promise_or';
|
||||
|
||||
declare module '../spec/js-api/importer' {
|
||||
/**
|
||||
* Replace the first two bullet points for [invoking an importer with a
|
||||
* string] with:
|
||||
*
|
||||
* [invoking an importer with a string]: ../spec/js-api/importer.d.ts
|
||||
*
|
||||
* - Let `fromImport` be `true` if the importer is being run for an `@import`
|
||||
* and `false` otherwise.
|
||||
*
|
||||
* - If `string` is a relative URL, or if it's an absolute URL whose scheme is
|
||||
* non-canonical for this importer, let `containingUrl` be the canonical URL
|
||||
* of the [current source file]. Otherwise, or if the current source file
|
||||
* has no canonical URL, let `containingUrl` be undefined.
|
||||
*
|
||||
* [current source file]: ../spec/spec.md#current-source-file
|
||||
*
|
||||
* - Let `url` be the result of calling `canonicalize` with `string`,
|
||||
* `fromImport`, and `containingUrl`. If it returns a promise, wait for it
|
||||
* to complete and use its value instead, or rethrow its error if it
|
||||
* rejects.
|
||||
*/
|
||||
interface Importer<sync extends 'sync' | 'async' = 'sync' | 'async'> {
|
||||
/**
|
||||
* The set of URL schemes that are considered *non-canonical* for this
|
||||
* importer. If this is a single string, treat it as a list containing that
|
||||
* string.
|
||||
*
|
||||
* Before beginning compilation, throw an error if any element of this
|
||||
* contains a character other than a lowercase ASCII letter, an ASCII
|
||||
* numeral, U+002B (`+`), U+002D (`-`), or U+002E (`.`).
|
||||
*
|
||||
* > Uppercase letters are normalized to lowercase in the `URL` constructor,
|
||||
* > so for simplicity and efficiency we only allow lowercase here.
|
||||
*/
|
||||
nonCanonicalScheme?: string | string[];
|
||||
|
||||
canonicalize(
|
||||
url: string,
|
||||
options: {fromImport: boolean; containingUrl?: URL}
|
||||
): PromiseOr<URL | null, sync>;
|
||||
}
|
||||
}
|
211
proposal/prev-url.d.ts.md
Normal file
211
proposal/prev-url.d.ts.md
Normal file
@ -0,0 +1,211 @@
|
||||
# Containing URL: Draft 1.0
|
||||
|
||||
*([Issue](https://github.com/sass/sass/issues/3247))*
|
||||
|
||||
```ts
|
||||
import {PromiseOr} from '../spec/js-api/util/promise_or';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Background](#background)
|
||||
* [Summary](#summary)
|
||||
* [Design Decisions](#design-decisions)
|
||||
* [Invariants](#invariants)
|
||||
* [Risks](#risks)
|
||||
* [Alternatives Considered](#alternatives-considered)
|
||||
* [Unavailable for Pre-Resolved Loads](#unavailable-for-pre-resolved-loads)
|
||||
* [Unavailable for Absolute Loads](#unavailable-for-absolute-loads)
|
||||
* [Types](#types)
|
||||
* [`Importer`](#importer)
|
||||
* [`nonCanonicalScheme`](#noncanonicalscheme)
|
||||
* [`canonicalize`](#canonicalize)
|
||||
|
||||
## Background
|
||||
|
||||
> This section is non-normative.
|
||||
|
||||
Among many other changes, the [new importer API] dropped an importer's ability
|
||||
to access the URL of the stylesheet that contained the load, known in the legacy
|
||||
API as the "previous URL". This was an intentional design choice which enforced
|
||||
the invariant that the same canonical URL always refers to the same file.
|
||||
|
||||
[new import API]: ../accepted/new-js-importer.d.ts
|
||||
|
||||
However, this restriction makes it difficult for importers to work as expected
|
||||
in certain contexts. For example, in the Node.js ecosystem JS loads depend on
|
||||
the structure of the `node_modules` directory closest to the containing file.
|
||||
The new import API can't match this behavior.
|
||||
|
||||
This is particularly problematic for the widely-used Webpack importer, which
|
||||
expands on the concept of directory-specific load contexts to allow users to do
|
||||
fine-grained customization of how differnt files will load their dependencies.
|
||||
In order to ease migration to the new API for this plugin and its users, and to
|
||||
better match external ecosystems' load semantics, a solution is needed.
|
||||
|
||||
## Summary
|
||||
|
||||
> This section is non-normative.
|
||||
|
||||
This proposal adds an additional option to the `Importer.canonicalize()` API
|
||||
that provides the canonical URL of the containing file (the "containing URL").
|
||||
However, in order to preserve the desired invariants, this option is only
|
||||
provided when either:
|
||||
|
||||
- `Importer.canonicalize()` is being passed a relative URL (which means the URL
|
||||
has already been tried as a load relative to the current canonical URL), or
|
||||
|
||||
- `Importer.canonicalize()` is passed an absolute URL whose scheme the importer
|
||||
has declared as non-canonical.
|
||||
|
||||
A "non-canonical" scheme is a new concept introduced by this proposals.
|
||||
Importers will optionally be able to provide a `nonCanonicalScheme` field which
|
||||
will declare one or more URL schemes that they'll never return from
|
||||
`canonicalize()`. (If they do, Sass will throw an error.)
|
||||
|
||||
### Design Decisions
|
||||
|
||||
#### Invariants
|
||||
|
||||
The specific restrictions for this API were put in place to preserve the
|
||||
following invariants:
|
||||
|
||||
1. There must be a one-to-one mapping between canonical URLs and stylesheets.
|
||||
This means that even when a user loads a stylesheet using a relative URL,
|
||||
that stylesheet must have an absolute canonical URL associated with it *and*
|
||||
loading that canonical URL must return the same stylesheet. This means that
|
||||
any stylesheet can *always* be unambiguously loaded using its canonical URL.
|
||||
|
||||
2. Relative URLs are resolved like paths and HTTP URLs. For example, within
|
||||
`scheme:a/b/c.scss`, the URL `../d` should be resolved to `scheme:a/d`.
|
||||
|
||||
3. Loads relative to the current stylesheet always take precedence over loads
|
||||
from importers, so if `scheme:a/b/x.scss` exists then `@use "x"` within
|
||||
`scheme:a/b/c.scss` will always load it.
|
||||
|
||||
#### Risks
|
||||
|
||||
Providing access to the containing URL puts these invariants at risk in two ways:
|
||||
|
||||
1. Access to the containing URL in addition to a canonical URL makes it possible
|
||||
for importer authors to handle the same canonical URL differently depending
|
||||
in different contexts, violating invariant (1).
|
||||
|
||||
2. It's likely that importer authors familiar with the legacy API will
|
||||
incorrectly assume that any containing URL that exists is the best way to
|
||||
handle relative loads, since the only way to do so in the legacy API was to
|
||||
manually resolve them relative to the `prev` parameter. Doing so will almost
|
||||
certainly lead to violations of invariant (3) and possibly (2).
|
||||
|
||||
#### Alternatives Considered
|
||||
|
||||
To mitigate these risks, we need to have _some_ restriction on when the
|
||||
containing URL is available to importers. We considered the following
|
||||
alternative restrictions before settling on the current one:
|
||||
|
||||
##### Unavailable for Pre-Resolved Loads
|
||||
|
||||
**Don't provide the containing URL when the `canonicalize()` function is called
|
||||
for pre-resolved relative loads.** When the user loads a relative URL, the Sass
|
||||
compiler first resolves that URL against the current canonical URL and passes
|
||||
the resulting absolute URL to the current importer's `canonicalize()` function.
|
||||
This invocation would not have access to the containing URL; all other
|
||||
invocations would, including when Sass passes the relative URL as-is to
|
||||
`canonicalize()`.
|
||||
|
||||
This mitigates risk (2) by ensuring that all relative URL resolution is handled
|
||||
by the compiler by default. The importer will be invoked with an absolute URL
|
||||
and no containing URL first for each relative load, which will break for any
|
||||
importers that naïvely try to use the containing URL in all cases.
|
||||
|
||||
This has several drawbacks. First, a badly-behaved importer could work around
|
||||
this by returning `null` for all relative loads and then manually resolving
|
||||
relative URLs as part of its load path resolution, thus continuing to violate
|
||||
invariant (3). Second, this provides no protection against risk (1) since the
|
||||
stylesheet author may still directly load a canonical URL.
|
||||
|
||||
##### Unavailable for Absolute Loads
|
||||
|
||||
**Don't provide the containing URL when the `canonicalize()` function is being
|
||||
called for any absolute URL.** Since relative loads always pass absolute URLs to
|
||||
their importers first, this is a superset of "Unavailable for Pre-Resolved
|
||||
Loads". In addition, it protects against risk (1) by ensuring that all absolute
|
||||
URLs (which are a superset of canonical URLs) are canonicalized without regard
|
||||
to context.
|
||||
|
||||
However, this limits the functionality of importers that use a custom URL scheme
|
||||
for *non-canonical* URLs. For example, if we choose to support [package imports]
|
||||
by claiming the `pkg:` scheme as a "built-in package importer", implementations
|
||||
of this scheme wouldn't be able to do context-sensitive resolution. This would
|
||||
make the scheme useless for supporting Node-style resolution, a core use-case.
|
||||
Given that we want to encourage users to use URL schemes rather than relative
|
||||
URLs, this is a blocking limitation.
|
||||
|
||||
[package imports]: https://github.com/sass/sass/issues/2739
|
||||
|
||||
Thus we arrive at the actual behavior, which makes the containing URL
|
||||
unavailable for absolute loads _unless_ they have a URL scheme declared
|
||||
explicitly non-canonical. This supports the `pkg:` use-case while still
|
||||
protecting against risk (1), since the containing URL is never available for
|
||||
canonical resolutions.
|
||||
|
||||
## Types
|
||||
|
||||
```ts
|
||||
declare module '../spec/js-api/importer' {
|
||||
```
|
||||
|
||||
### `Importer`
|
||||
|
||||
Replace the first two bullet points for [invoking an importer with a string]
|
||||
with:
|
||||
|
||||
[invoking an importer with a string]: ../spec/js-api/importer.d.ts.md
|
||||
|
||||
* Let `fromImport` be `true` if the importer is being run for an `@import` and
|
||||
`false` otherwise.
|
||||
|
||||
* If `string` is a relative URL, or if it's an absolute URL whose scheme is
|
||||
non-canonical for this importer, let `containingUrl` be the canonical URL of
|
||||
the [current source file]. Otherwise, or if the current source file has no
|
||||
canonical URL, let `containingUrl` be undefined.
|
||||
|
||||
[current source file]: ../spec/spec.md#current-source-file
|
||||
|
||||
* Let `url` be the result of calling `canonicalize` with `string`, `fromImport`,
|
||||
and `containingUrl`. If it returns a promise, wait for it to complete and use
|
||||
its value instead, or rethrow its error if it rejects.
|
||||
|
||||
```ts
|
||||
interface Importer<sync extends 'sync' | 'async' = 'sync' | 'async'> {
|
||||
```
|
||||
|
||||
#### `nonCanonicalScheme`
|
||||
|
||||
The set of URL schemes that are considered *non-canonical* for this importer. If
|
||||
this is a single string, treat it as a list containing that string.
|
||||
|
||||
Before beginning compilation, throw an error if any element of this contains a
|
||||
character other than a lowercase ASCII letter, an ASCII numeral, U+002B (`+`),
|
||||
U+002D (`-`), or U+002E (`.`).
|
||||
|
||||
> Uppercase letters are normalized to lowercase in the `URL` constructor, so for
|
||||
> simplicity and efficiency we only allow lowercase here.
|
||||
|
||||
```ts
|
||||
nonCanonicalScheme?: string | string[];
|
||||
```
|
||||
|
||||
#### `canonicalize`
|
||||
|
||||
```ts
|
||||
canonicalize(
|
||||
url: string,
|
||||
options: {fromImport: boolean; containingUrl?: URL}
|
||||
): PromiseOr<URL | null, sync>;
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
} // module
|
||||
```
|
111
spec/js-api/compile.d.ts
vendored
111
spec/js-api/compile.d.ts
vendored
@ -1,111 +0,0 @@
|
||||
import {RawSourceMap} from 'source-map-js'; // https://www.npmjs.com/package/source-map-js
|
||||
|
||||
import {Options, StringOptions} from './options';
|
||||
|
||||
/** The object returned by the compiler when a Sass compilation succeeds. */
|
||||
export interface CompileResult {
|
||||
css: string;
|
||||
|
||||
loadedUrls: URL[];
|
||||
|
||||
sourceMap?: RawSourceMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the Sass file at `path`:
|
||||
*
|
||||
* - If any object in `options.importers` has both `findFileUrl` and
|
||||
* `canonicalize` fields, throw an error.
|
||||
*
|
||||
* - Let `css` be the result of [compiling `path`] with `options.importers` as
|
||||
* `importers` and `options.loadPaths` as `load-paths`. The compiler must
|
||||
* respect the configuration specified by the `options` object.
|
||||
*
|
||||
* [compiling `path`]: ../spec/spec.md#compiling-a-path
|
||||
*
|
||||
* - If the compilation succeeds, return a `CompileResult` object composed as
|
||||
* follows:
|
||||
*
|
||||
* - Set `CompileResult.css` to `css`.
|
||||
*
|
||||
* - Set `CompileResult.loadedUrls` to a list of unique canonical URLs of
|
||||
* source files [loaded] during the compilation. The order of URLs is not
|
||||
* guaranteed.
|
||||
*
|
||||
* [loaded]: ../spec/modules.md#loading-a-source-file
|
||||
*
|
||||
* - If `options.sourceMap` is `true`, set `CompileResult.sourceMap` to a
|
||||
* sourceMap object describing how sections of the Sass input correspond to
|
||||
* sections of the CSS output.
|
||||
*
|
||||
* > The structure of the sourceMap can vary from implementation to
|
||||
* > implementation.
|
||||
*
|
||||
* - Otherwise, throw an `Exception`.
|
||||
*/
|
||||
export function compile(path: string, options?: Options<'sync'>): CompileResult;
|
||||
|
||||
/**
|
||||
* Like `compile`, but runs asynchronously.
|
||||
*
|
||||
* The compiler must support asynchronous plugins when running in this mode.
|
||||
*/
|
||||
export function compileAsync(
|
||||
path: string,
|
||||
options?: Options<'async'>
|
||||
): Promise<CompileResult>;
|
||||
|
||||
/**
|
||||
* Compiles the Sass `source`:
|
||||
*
|
||||
* - If `options.importer` or any object in `options.importers` has both
|
||||
* `findFileUrl` and `canonicalize` fields, throw an error.
|
||||
*
|
||||
* - Let `css` be the result of [compiling a string] with:
|
||||
* - `options.source` as `string`;
|
||||
* - `options.syntax` as `syntax`, or "scss" if `options.syntax` is not set;
|
||||
* - `options.url` as `url`;
|
||||
* - `options.importer` as `importer`;
|
||||
* - `options.importers` as `importers`;
|
||||
* - `options.loadPaths` as `load-paths`.
|
||||
* The compiler must respect the configuration specified by the `options`
|
||||
* object.
|
||||
*
|
||||
* [compiling a string]: ../spec/spec.md#compiling-a-string
|
||||
*
|
||||
* - If the compilation succeeds, return a `CompileResult` object composed as
|
||||
* follows:
|
||||
*
|
||||
* - Set `CompileResult.css` to `css`.
|
||||
*
|
||||
* - Set `CompileResult.loadedUrls` to a list of unique canonical URLs of
|
||||
* source files [loaded] during the compilation. The order of URLs is not
|
||||
* guaranteed.
|
||||
* - If `options.url` is set, include it in the list.
|
||||
* - Otherwise, do not include a URL for `source`.
|
||||
*
|
||||
* [loaded]: ../spec/modules.md#loading-a-source-file
|
||||
*
|
||||
* - If `options.sourceMap` is `true`, set `CompileResult.sourceMap` to a
|
||||
* sourceMap object describing how sections of the Sass input correspond to
|
||||
* sections of the CSS output.
|
||||
*
|
||||
* > The structure of the sourceMap can vary from implementation to
|
||||
* > implementation.
|
||||
*
|
||||
* - If the compilation fails, throw an `Exception`.
|
||||
*/
|
||||
export function compileString(
|
||||
source: string,
|
||||
options?: StringOptions<'sync'>
|
||||
): CompileResult;
|
||||
|
||||
/**
|
||||
* Like `compileString`, but runs asynchronously.
|
||||
*
|
||||
* The compiler must support asynchronous plugins when running in this mode.
|
||||
*/
|
||||
export function compileStringAsync(
|
||||
source: string,
|
||||
options?: StringOptions<'async'>
|
||||
): Promise<CompileResult>;
|
150
spec/js-api/compile.d.ts.md
Normal file
150
spec/js-api/compile.d.ts.md
Normal file
@ -0,0 +1,150 @@
|
||||
# Compile API
|
||||
|
||||
> These APIs are the entrypoints for compiling Sass to CSS.
|
||||
|
||||
```ts
|
||||
import {RawSourceMap} from 'source-map-js'; // https://www.npmjs.com/package/source-map-js
|
||||
|
||||
import {Options, StringOptions} from './options';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`CompileResult`](#compileresult)
|
||||
* [Functions](#functions)
|
||||
* [`compile`](#compile)
|
||||
* [`compileAsync`](#compileasync)
|
||||
* [`compileString`](#compilestring)
|
||||
* [`compileStringAsync`](#compilestringasync)
|
||||
|
||||
## Types
|
||||
|
||||
### `CompileResult`
|
||||
|
||||
The object returned by the compiler when a Sass compilation succeeds.
|
||||
|
||||
```ts
|
||||
export interface CompileResult {
|
||||
css: string;
|
||||
|
||||
loadedUrls: URL[];
|
||||
|
||||
sourceMap?: RawSourceMap;
|
||||
}
|
||||
```
|
||||
|
||||
## Functions
|
||||
|
||||
### `compile`
|
||||
|
||||
Compiles the Sass file at `path`:
|
||||
|
||||
* If any object in `options.importers` has both `findFileUrl` and `canonicalize`
|
||||
fields, throw an error.
|
||||
|
||||
* Let `css` be the result of [compiling `path`] with `options.importers` as
|
||||
`importers` and `options.loadPaths` as `load-paths`. The compiler must respect
|
||||
the configuration specified by the `options` object.
|
||||
|
||||
[compiling `path`]: ../spec.md#compiling-a-path
|
||||
|
||||
* If the compilation succeeds, return a `CompileResult` object composed as
|
||||
follows:
|
||||
|
||||
* Set `CompileResult.css` to `css`.
|
||||
|
||||
* Set `CompileResult.loadedUrls` to a list of unique canonical URLs of source
|
||||
files [loaded] during the compilation. The order of URLs is not guaranteed.
|
||||
|
||||
[loaded]: ../modules.md#loading-a-source-file
|
||||
|
||||
* If `options.sourceMap` is `true`, set `CompileResult.sourceMap` to a
|
||||
sourceMap object describing how sections of the Sass input correspond to
|
||||
sections of the CSS output.
|
||||
|
||||
> The structure of the sourceMap can vary from implementation to
|
||||
> implementation.
|
||||
|
||||
* Otherwise, throw an `Exception`.
|
||||
|
||||
```ts
|
||||
export function compile(path: string, options?: Options<'sync'>): CompileResult;
|
||||
```
|
||||
|
||||
### `compileAsync`
|
||||
|
||||
Like [`compile`], but runs asynchronously.
|
||||
|
||||
[`compile`]: #compile
|
||||
|
||||
The compiler must support asynchronous plugins when running in this mode.
|
||||
|
||||
```ts
|
||||
export function compileAsync(
|
||||
path: string,
|
||||
options?: Options<'async'>
|
||||
): Promise<CompileResult>;
|
||||
```
|
||||
|
||||
### `compileString`
|
||||
|
||||
Compiles the Sass `source`:
|
||||
|
||||
* If `options.importer` or any object in `options.importers` has both
|
||||
`findFileUrl` and `canonicalize` fields, throw an error.
|
||||
|
||||
* Let `css` be the result of [compiling a string] with:
|
||||
|
||||
* `options.source` as `string`;
|
||||
* `options.syntax` as `syntax`, or "scss" if `options.syntax` is not set;
|
||||
* `options.url` as `url`;
|
||||
* `options.importer` as `importer`;
|
||||
* `options.importers` as `importers`;
|
||||
* `options.loadPaths` as `load-paths`.
|
||||
|
||||
The compiler must respect the configuration specified by the `options` object.
|
||||
|
||||
[compiling a string]: ../spec.md#compiling-a-string
|
||||
|
||||
* If the compilation succeeds, return a `CompileResult` object composed as
|
||||
follows:
|
||||
|
||||
* Set `CompileResult.css` to `css`.
|
||||
|
||||
* Set `CompileResult.loadedUrls` to a list of unique canonical URLs of source
|
||||
files [loaded] during the compilation. The order of URLs is not guaranteed.
|
||||
|
||||
* If `options.url` is set, include it in the list.
|
||||
* Otherwise, do not include a URL for `source`.
|
||||
|
||||
* If `options.sourceMap` is `true`, set `CompileResult.sourceMap` to a
|
||||
sourceMap object describing how sections of the Sass input correspond to
|
||||
sections of the CSS output.
|
||||
|
||||
> The structure of the sourceMap can vary from implementation to
|
||||
> implementation.
|
||||
|
||||
[loaded]: ../modules.md#loading-a-source-file
|
||||
|
||||
* If the compilation fails, throw an `Exception`.
|
||||
|
||||
```ts
|
||||
export function compileString(
|
||||
source: string,
|
||||
options?: StringOptions<'sync'>
|
||||
): CompileResult;
|
||||
```
|
||||
|
||||
### `compileStringAsync`
|
||||
|
||||
Like `compileString`, but runs asynchronously.
|
||||
|
||||
The compiler must support asynchronous plugins when running in this mode.
|
||||
|
||||
```ts
|
||||
export function compileStringAsync(
|
||||
source: string,
|
||||
options?: StringOptions<'async'>
|
||||
): Promise<CompileResult>;
|
||||
```
|
57
spec/js-api/exception.d.ts
vendored
57
spec/js-api/exception.d.ts
vendored
@ -1,57 +0,0 @@
|
||||
import {SourceSpan} from './logger';
|
||||
|
||||
/**
|
||||
* The error thrown by the compiler when a Sass compilation fails. This should
|
||||
* *not* be thrown for errors that occur outside of Sass compilation, such as
|
||||
* argument verification errors.
|
||||
*/
|
||||
export class Exception extends Error {
|
||||
private constructor();
|
||||
|
||||
/**
|
||||
* The compiler supplies this error message to the JS runtime. This should
|
||||
* contain the description of the Sass exception as well as human-friendly
|
||||
* representations of `span` and `sassStack` (if they're set).
|
||||
*
|
||||
* This message must be passed directly to the super constructor.
|
||||
*
|
||||
* > The format can vary from implementation to implementation.
|
||||
*/
|
||||
message: string;
|
||||
|
||||
/**
|
||||
* The Sass error message, excluding the human-friendly representation of
|
||||
* `span` and `sassStack`.
|
||||
*
|
||||
* > The format can vary from implementation to implementation.
|
||||
*/
|
||||
readonly sassMessage: string;
|
||||
|
||||
/**
|
||||
* A human-friendly representation of the loads, function calls, and mixin
|
||||
* includes that were active when this error was thrown.
|
||||
*
|
||||
* > The format can vary from implementation to implementation.
|
||||
*/
|
||||
readonly sassStack: string;
|
||||
|
||||
/**
|
||||
* A span whose `url` is the canonical URL of the stylesheet being parsed or
|
||||
* evaluated, and whose `start` points to the line in that stylesheet on which
|
||||
* the error occurred.
|
||||
*
|
||||
* > The other details of this span can vary from implementation to
|
||||
* > implementation, but implementations are strongly encouraged to ensure
|
||||
* > that this covers a span of text that clearly indicates the location of
|
||||
* > the error.
|
||||
*/
|
||||
readonly span: SourceSpan;
|
||||
|
||||
/**
|
||||
* Provides a formatted string with useful information about the error.
|
||||
*
|
||||
* > This likely includes the Sass error message, span, and stack. The format
|
||||
* > can vary from implementation to implementation.
|
||||
*/
|
||||
toString(): string; // TODO(awjin): Mark this as `override` once TS 4.3 is released.
|
||||
}
|
93
spec/js-api/exception.d.ts.md
Normal file
93
spec/js-api/exception.d.ts.md
Normal file
@ -0,0 +1,93 @@
|
||||
# Exception API
|
||||
|
||||
The error thrown by the compiler when a Sass compilation fails. This should
|
||||
*not* be thrown for errors that occur outside of Sass compilation, such as
|
||||
argument verification errors.
|
||||
|
||||
```ts
|
||||
import {SourceSpan} from './logger';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`Exception`](#exception)
|
||||
* [`message`](#message)
|
||||
* [`sassMessage`](#sassmessage)
|
||||
* [`sassStack`](#sassstack)
|
||||
* [`span`](#span)
|
||||
* [`toString()`](#tostring)
|
||||
|
||||
## Types
|
||||
|
||||
### `Exception`
|
||||
|
||||
```ts
|
||||
export class Exception extends Error {
|
||||
private constructor();
|
||||
```
|
||||
|
||||
#### `message`
|
||||
|
||||
The compiler supplies this error message to the JS runtime. This should contain
|
||||
the description of the Sass exception as well as human-friendly representations
|
||||
of `span` and `sassStack` (if they're set).
|
||||
|
||||
This message must be passed directly to the super constructor.
|
||||
|
||||
> The format can vary from implementation to implementation.
|
||||
|
||||
```ts
|
||||
message: string;
|
||||
```
|
||||
|
||||
#### `sassMessage`
|
||||
|
||||
The Sass error message, excluding the human-friendly representation of `span`
|
||||
and `sassStack`.
|
||||
|
||||
> The format can vary from implementation to implementation.
|
||||
|
||||
```ts
|
||||
readonly sassMessage: string;
|
||||
```
|
||||
|
||||
#### `sassStack`
|
||||
|
||||
A human-friendly representation of the loads, function calls, and mixin includes
|
||||
that were active when this error was thrown.
|
||||
|
||||
> The format can vary from implementation to implementation.
|
||||
|
||||
```ts
|
||||
readonly sassStack: string;
|
||||
```
|
||||
|
||||
#### `span`
|
||||
|
||||
A span whose `url` is the canonical URL of the stylesheet being parsed or
|
||||
evaluated, and whose `start` points to the line in that stylesheet on which the
|
||||
error occurred.
|
||||
|
||||
> The other details of this span can vary from implementation to implementation,
|
||||
> but implementations are strongly encouraged to ensure that this covers a span
|
||||
> of text that clearly indicates the location of the error.
|
||||
|
||||
```ts
|
||||
readonly span: SourceSpan;
|
||||
```
|
||||
|
||||
#### `toString()`
|
||||
|
||||
Provides a formatted string with useful information about the error.
|
||||
|
||||
> This likely includes the Sass error message, span, and stack. The format can
|
||||
> vary from implementation to implementation.
|
||||
|
||||
```ts
|
||||
toString(): string; // TODO(awjin): Mark this as `override` once TS 4.3 is released.
|
||||
```
|
||||
|
||||
```ts
|
||||
} // Exception
|
||||
```
|
113
spec/js-api/importer.d.ts
vendored
113
spec/js-api/importer.d.ts
vendored
@ -1,113 +0,0 @@
|
||||
import {Syntax} from './options';
|
||||
import {PromiseOr} from './util/promise_or';
|
||||
|
||||
/**
|
||||
* This interface represents an [importer]. When the importer is invoked with a
|
||||
* string `string`:
|
||||
*
|
||||
* [importer]: ../spec/modules.md#importer
|
||||
*
|
||||
* - If `string` is an absolute URL whose scheme is `file`:
|
||||
*
|
||||
* - Let `url` be string.
|
||||
*
|
||||
* - Otherwise:
|
||||
*
|
||||
* - Let `fromImport` be `true` if the importer is being run for an `@import`
|
||||
* and `false` otherwise.
|
||||
*
|
||||
* - Let `url` be the result of calling `findFileUrl` with `string` and
|
||||
* `fromImport`. If it returns a promise, wait for it to complete and use
|
||||
* its value instead, or rethrow its error if it rejects.
|
||||
*
|
||||
* - If `url` is null, return null.
|
||||
*
|
||||
* - If `url`'s scheme is not `file`, throw an error.
|
||||
*
|
||||
* - Let `resolved` be the result of [resolving `url`].
|
||||
*
|
||||
* - If `resolved` is null, return null.
|
||||
*
|
||||
* - Let `text` be the contents of the file at `resolved`.
|
||||
*
|
||||
* - Let `syntax` be:
|
||||
* - "scss" if `url` ends in `.scss`.
|
||||
* - "indented" if `url` ends in `.sass`.
|
||||
* - "css" if `url` ends in `.css`.
|
||||
*
|
||||
* > The algorithm for resolving a `file:` URL guarantees that `url` will have
|
||||
* > one of these extensions.
|
||||
*
|
||||
* - Return `text`, `syntax`, and `resolved`.
|
||||
*
|
||||
* [resolving `url`]: ../spec/modules.md#resolving-a-file-url
|
||||
*/
|
||||
export interface FileImporter<
|
||||
sync extends 'sync' | 'async' = 'sync' | 'async'
|
||||
> {
|
||||
findFileUrl(
|
||||
url: string,
|
||||
options: {fromImport: boolean}
|
||||
): PromiseOr<URL | null, sync>;
|
||||
|
||||
canonicalize?: never;
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface represents an [importer]. When the importer is invoked with a
|
||||
* string `string`:
|
||||
*
|
||||
* [importer]: ../spec/modules.md#importer
|
||||
*
|
||||
* - Let `fromImport` be `true` if the importer is being run for an `@import`
|
||||
* and `false` otherwise.
|
||||
*
|
||||
* - Let `url` be the result of calling `canonicalize` with `url` and
|
||||
* `fromImport`. If it returns a promise, wait for it to complete and use its
|
||||
* value instead, or rethrow its error if it rejects.
|
||||
*
|
||||
* - If `url` is null, return null.
|
||||
*
|
||||
* - Let `result` be the result of calling `load` with `url`. If it returns a
|
||||
* promise, wait for it to complete and use its value instead, or rethrow its
|
||||
* error if it rejects.
|
||||
*
|
||||
* - If `result` is null, return null.
|
||||
*
|
||||
* - Let `syntax` be `result.syntax`.
|
||||
*
|
||||
* - Throw an error if `syntax` is not "scss", "indented", or "css".
|
||||
*
|
||||
* - Otherwise, throw an error.
|
||||
*
|
||||
* - Return `result.contents`, `syntax`, and `url`.
|
||||
*
|
||||
* [resolving `url`]: ../spec/modules.md#resolving-a-file-url
|
||||
*/
|
||||
export interface Importer<sync extends 'sync' | 'async' = 'sync' | 'async'> {
|
||||
canonicalize(
|
||||
url: string,
|
||||
options: {fromImport: boolean}
|
||||
): PromiseOr<URL | null, sync>;
|
||||
|
||||
load(canonicalUrl: URL): PromiseOr<ImporterResult | null, sync>;
|
||||
|
||||
findFileUrl?: never;
|
||||
}
|
||||
|
||||
export interface ImporterResult {
|
||||
/** The contents of stylesheet loaded by an importer. */
|
||||
contents: string;
|
||||
|
||||
/** The syntax to use to parse `css`. */
|
||||
syntax: Syntax;
|
||||
|
||||
/**
|
||||
* A browser-accessible URL indicating the resolved location of the imported
|
||||
* stylesheet.
|
||||
*
|
||||
* The implementation must use this URL in source maps to refer to source
|
||||
* spans in `css`.
|
||||
*/
|
||||
sourceMapUrl?: URL;
|
||||
}
|
126
spec/js-api/importer.d.ts.md
Normal file
126
spec/js-api/importer.d.ts.md
Normal file
@ -0,0 +1,126 @@
|
||||
# Importer API
|
||||
|
||||
> Interfaces for user-declared importers that customize how Sass loads
|
||||
> stylesheet dependencies.
|
||||
|
||||
```ts
|
||||
import {Syntax} from './options';
|
||||
import {PromiseOr} from './util/promise_or';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`FileImporter`](#fileimporter)
|
||||
* [`Importer`](#importer)
|
||||
* [`ImporterResult`](#importerresult)
|
||||
|
||||
## Types
|
||||
|
||||
### `FileImporter`
|
||||
|
||||
This interface represents an [importer]. When the importer is invoked with a
|
||||
string `string`:
|
||||
|
||||
[importer]: ../modules.md#importer
|
||||
|
||||
* If `string` is an absolute URL whose scheme is `file`:
|
||||
|
||||
* Let `url` be string.
|
||||
|
||||
* Otherwise:
|
||||
|
||||
* Let `fromImport` be `true` if the importer is being run for an `@import` and
|
||||
`false` otherwise.
|
||||
|
||||
* Let `url` be the result of calling `findFileUrl` with `string` and
|
||||
`fromImport`. If it returns a promise, wait for it to complete and use its
|
||||
value instead, or rethrow its error if it rejects.
|
||||
|
||||
* If `url` is null, return null.
|
||||
|
||||
* If `url`'s scheme is not `file`, throw an error.
|
||||
|
||||
* Let `resolved` be the result of [resolving `url`].
|
||||
|
||||
[resolving `url`]: ../modules.md#resolving-a-file-url
|
||||
|
||||
* If `resolved` is null, return null.
|
||||
|
||||
* Let `text` be the contents of the file at `resolved`.
|
||||
|
||||
* Let `syntax` be:
|
||||
* "scss" if `url` ends in `.scss`.
|
||||
* "indented" if `url` ends in `.sass`.
|
||||
* "css" if `url` ends in `.css`.
|
||||
|
||||
> The algorithm for resolving a `file:` URL guarantees that `url` will have
|
||||
> one of these extensions.
|
||||
|
||||
* Return `text`, `syntax`, and `resolved`.
|
||||
|
||||
```ts
|
||||
export interface FileImporter<
|
||||
sync extends 'sync' | 'async' = 'sync' | 'async'
|
||||
> {
|
||||
findFileUrl(
|
||||
url: string,
|
||||
options: {fromImport: boolean}
|
||||
): PromiseOr<URL | null, sync>;
|
||||
|
||||
canonicalize?: never;
|
||||
}
|
||||
```
|
||||
|
||||
### `Importer`
|
||||
|
||||
This interface represents an [importer]. When the importer is invoked with a
|
||||
string `string`:
|
||||
|
||||
* Let `fromImport` be `true` if the importer is being run for an `@import` and
|
||||
`false` otherwise.
|
||||
|
||||
* Let `url` be the result of calling `canonicalize` with `url` and `fromImport`.
|
||||
If it returns a promise, wait for it to complete and use its value instead, or
|
||||
rethrow its error if it rejects.
|
||||
|
||||
* If `url` is null, return null.
|
||||
|
||||
* Let `result` be the result of calling `load` with `url`. If it returns a
|
||||
promise, wait for it to complete and use its value instead, or rethrow its
|
||||
error if it rejects.
|
||||
|
||||
* If `result` is null, return null.
|
||||
|
||||
* Throw an error if `result.syntax` is not "scss", "indented", or "css".
|
||||
|
||||
* If `result.sourceMapUrl` is defined and the implementation generates a source
|
||||
map, the implementation must use this URL in the source map to refer to source
|
||||
spans in `result.contents`.
|
||||
|
||||
* Return `result.contents`, `result.syntax`, and `url`.
|
||||
|
||||
```ts
|
||||
export interface Importer<sync extends 'sync' | 'async' = 'sync' | 'async'> {
|
||||
canonicalize(
|
||||
url: string,
|
||||
options: {fromImport: boolean}
|
||||
): PromiseOr<URL | null, sync>;
|
||||
|
||||
load(canonicalUrl: URL): PromiseOr<ImporterResult | null, sync>;
|
||||
|
||||
findFileUrl?: never;
|
||||
}
|
||||
```
|
||||
|
||||
### `ImporterResult`
|
||||
|
||||
```ts
|
||||
export interface ImporterResult {
|
||||
contents: string;
|
||||
|
||||
syntax: Syntax;
|
||||
|
||||
sourceMapUrl?: URL;
|
||||
}
|
||||
```
|
105
spec/js-api/index.d.ts
vendored
105
spec/js-api/index.d.ts
vendored
@ -1,105 +0,0 @@
|
||||
/**
|
||||
* # JavaScript API
|
||||
*
|
||||
* Sass implementations that are available for use via JavaScript must expose
|
||||
* the following JavaScript API. As with the rest of this specification, they
|
||||
* must not add custom extensions that aren't shared across all implementations.
|
||||
*
|
||||
* > Having a shared, consistent API makes it easy for users to move between
|
||||
* > Sass implementations with minimal disruption, and for build system plugins
|
||||
* > to seamlessly work with multiple implementations.
|
||||
*
|
||||
* The JS API is specified as a TypeScript type declaration. Implementations
|
||||
* must adhere to this declaration and to the behavioral specifications written
|
||||
* in JSDoc comments on the declarations. Implementations may throw errors when
|
||||
* user code passes in values that don't adhere to the type declaration, but
|
||||
* unless otherwise indicated they may also handle these values in undefined
|
||||
* ways in accordance with the common JavaScript pattern of avoiding explicit
|
||||
* type checks. This must not be used as a way of adding custom extensions that
|
||||
* aren't shared across all implementations.
|
||||
*
|
||||
* Certain interfaces in the JS API are defined within the `legacy` directory,
|
||||
* indicating that they're part of the legacy Node Sass API. This API is
|
||||
* deprecated and implementations are not required to support it. However, at
|
||||
* least partial support is recommended for compatibility with older
|
||||
* applications and particularly build system plugins.
|
||||
*
|
||||
* As with other sections of this specification, the specification of the legacy
|
||||
* JS API is incomplete, and is added to *lazily*. This means that portions of
|
||||
* the spec—particularly the documentation comments that serve as a behavioral
|
||||
* specification—are only written when they're necessary as background for new
|
||||
* API proposals. */
|
||||
|
||||
export {
|
||||
CompileResult,
|
||||
compile,
|
||||
compileAsync,
|
||||
compileString,
|
||||
compileStringAsync,
|
||||
} from './compile';
|
||||
export {Exception} from './exception';
|
||||
export {FileImporter, Importer, ImporterResult} from './importer';
|
||||
export {Logger, SourceSpan, SourceLocation} from './logger';
|
||||
export {
|
||||
CustomFunction,
|
||||
Options,
|
||||
OutputStyle,
|
||||
StringOptions,
|
||||
StringOptionsWithImporter,
|
||||
StringOptionsWithoutImporter,
|
||||
Syntax,
|
||||
} from './options';
|
||||
export {PromiseOr} from './util/promise_or';
|
||||
export {
|
||||
ListSeparator,
|
||||
SassArgumentList,
|
||||
SassBoolean,
|
||||
SassColor,
|
||||
SassFunction,
|
||||
SassList,
|
||||
SassMap,
|
||||
SassNumber,
|
||||
SassString,
|
||||
Value,
|
||||
sassFalse,
|
||||
sassNull,
|
||||
sassTrue,
|
||||
} from './value';
|
||||
|
||||
// Legacy APIs
|
||||
export {LegacyException} from './legacy/exception';
|
||||
export {
|
||||
FALSE,
|
||||
LegacyAsyncFunction,
|
||||
LegacyAsyncFunctionDone,
|
||||
LegacyFunction,
|
||||
LegacySyncFunction,
|
||||
LegacyValue,
|
||||
NULL,
|
||||
TRUE,
|
||||
types,
|
||||
} from './legacy/function';
|
||||
export {
|
||||
LegacyAsyncImporter,
|
||||
LegacyImporter,
|
||||
LegacyImporterResult,
|
||||
LegacyImporterThis,
|
||||
LegacySyncImporter,
|
||||
} from './legacy/importer';
|
||||
export {
|
||||
LegacySharedOptions,
|
||||
LegacyFileOptions,
|
||||
LegacyStringOptions,
|
||||
LegacyOptions,
|
||||
} from './legacy/options';
|
||||
export {LegacyPluginThis} from './legacy/plugin_this';
|
||||
export {LegacyResult, render, renderSync} from './legacy/render';
|
||||
|
||||
/**
|
||||
* Information about the Sass implementation. This must begin with a unique
|
||||
* identifier for this package (typically but not necessarily the npm package
|
||||
* name), followed by U+0009 TAB, followed by its npm package version. It may
|
||||
* contain another tab character followed by additional information, but this is
|
||||
* not required.
|
||||
*/
|
||||
export const info: string;
|
123
spec/js-api/index.d.ts.md
Normal file
123
spec/js-api/index.d.ts.md
Normal file
@ -0,0 +1,123 @@
|
||||
# JavaScript API
|
||||
|
||||
Sass implementations that are available for use via JavaScript must expose the
|
||||
following JavaScript API. As with the rest of this specification, they must not
|
||||
add custom extensions that aren't shared across all implementations.
|
||||
|
||||
> Having a shared, consistent API makes it easy for users to move between Sass
|
||||
> implementations with minimal disruption, and for build system plugins to
|
||||
> seamlessly work with multiple implementations.
|
||||
|
||||
The JS API is specified as a TypeScript type declaration. Implementations must
|
||||
adhere to this declaration and to the behavioral specifications written in JSDoc
|
||||
comments on the declarations. Implementations may throw errors when user code
|
||||
passes in values that don't adhere to the type declaration, but unless otherwise
|
||||
indicated they may also handle these values in undefined ways in accordance with
|
||||
the common JavaScript pattern of avoiding explicit type checks. This must not be
|
||||
used as a way of adding custom extensions that aren't shared across all
|
||||
implementations.
|
||||
|
||||
Certain interfaces in the JS API are defined within the `legacy` directory,
|
||||
indicating that they're part of the legacy Node Sass API. This API is deprecated
|
||||
and implementations are not required to support it. However, at least partial
|
||||
support is recommended for compatibility with older applications and
|
||||
particularly build system plugins.
|
||||
|
||||
As with other sections of this specification, the specification of the legacy JS
|
||||
API is incomplete, and is added to *lazily*. This means that portions of the
|
||||
spec—particularly the documentation comments that serve as a behavioral
|
||||
specification—are only written when they're necessary as background for new API
|
||||
proposals.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Modern APIs](#modern-apis)
|
||||
* [Legacy APIs](#legacy-apis)
|
||||
* [Top-Level Members](#top-level-members)
|
||||
* [`info`](#info)
|
||||
|
||||
## Modern APIs
|
||||
|
||||
```ts
|
||||
export {
|
||||
CompileResult,
|
||||
compile,
|
||||
compileAsync,
|
||||
compileString,
|
||||
compileStringAsync,
|
||||
} from './compile';
|
||||
export {Exception} from './exception';
|
||||
export {FileImporter, Importer, ImporterResult} from './importer';
|
||||
export {Logger, SourceSpan, SourceLocation} from './logger';
|
||||
export {
|
||||
CustomFunction,
|
||||
Options,
|
||||
OutputStyle,
|
||||
StringOptions,
|
||||
StringOptionsWithImporter,
|
||||
StringOptionsWithoutImporter,
|
||||
Syntax,
|
||||
} from './options';
|
||||
export {PromiseOr} from './util/promise_or';
|
||||
export {
|
||||
ListSeparator,
|
||||
SassArgumentList,
|
||||
SassBoolean,
|
||||
SassColor,
|
||||
SassFunction,
|
||||
SassList,
|
||||
SassMap,
|
||||
SassNumber,
|
||||
SassString,
|
||||
Value,
|
||||
sassFalse,
|
||||
sassNull,
|
||||
sassTrue,
|
||||
} from './value';
|
||||
```
|
||||
|
||||
## Legacy APIs
|
||||
|
||||
```ts
|
||||
export {LegacyException} from './legacy/exception';
|
||||
export {
|
||||
FALSE,
|
||||
LegacyAsyncFunction,
|
||||
LegacyAsyncFunctionDone,
|
||||
LegacyFunction,
|
||||
LegacySyncFunction,
|
||||
LegacyValue,
|
||||
NULL,
|
||||
TRUE,
|
||||
types,
|
||||
} from './legacy/function';
|
||||
export {
|
||||
LegacyAsyncImporter,
|
||||
LegacyImporter,
|
||||
LegacyImporterResult,
|
||||
LegacyImporterThis,
|
||||
LegacySyncImporter,
|
||||
} from './legacy/importer';
|
||||
export {
|
||||
LegacySharedOptions,
|
||||
LegacyFileOptions,
|
||||
LegacyStringOptions,
|
||||
LegacyOptions,
|
||||
} from './legacy/options';
|
||||
export {LegacyPluginThis} from './legacy/plugin_this';
|
||||
export {LegacyResult, render, renderSync} from './legacy/render';
|
||||
```
|
||||
|
||||
## Top-Level Members
|
||||
|
||||
### `info`
|
||||
|
||||
Information about the Sass implementation. This must begin with a unique
|
||||
identifier for this package (typically but not necessarily the npm package
|
||||
name), followed by U+0009 TAB, followed by its npm package version. It may
|
||||
contain another tab character followed by additional information, but this is
|
||||
not required.
|
||||
|
||||
```ts
|
||||
export const info: string;
|
||||
```
|
39
spec/js-api/legacy/importer.d.ts
vendored
39
spec/js-api/legacy/importer.d.ts
vendored
@ -1,39 +0,0 @@
|
||||
import {LegacyPluginThis} from './plugin_this';
|
||||
|
||||
/**
|
||||
* The interface for the `this` keyword for custom importers. The implementation
|
||||
* must invoke importers with an appropriate `this`.
|
||||
*/
|
||||
interface LegacyImporterThis extends LegacyPluginThis {
|
||||
/**
|
||||
* `true` if this importer invocation was caused by an `@import` statement and
|
||||
* `false` otherwise.
|
||||
*
|
||||
* > This allows importers to look for `.import.scss` stylesheets if and only
|
||||
* > if an `@import` is being resolved.
|
||||
*/
|
||||
fromImport: boolean;
|
||||
}
|
||||
|
||||
export type LegacyImporterResult =
|
||||
| {file: string}
|
||||
| {contents: string}
|
||||
| Error
|
||||
| null;
|
||||
|
||||
type LegacySyncImporter = (
|
||||
this: LegacyImporterThis,
|
||||
url: string,
|
||||
prev: string
|
||||
) => LegacyImporterResult;
|
||||
|
||||
type LegacyAsyncImporter = (
|
||||
this: LegacyImporterThis,
|
||||
url: string,
|
||||
prev: string,
|
||||
done: (result: LegacyImporterResult) => void
|
||||
) => void;
|
||||
|
||||
export type LegacyImporter<sync = 'sync' | 'async'> = sync extends 'async'
|
||||
? LegacySyncImporter | LegacyAsyncImporter
|
||||
: LegacySyncImporter;
|
81
spec/js-api/legacy/importer.d.ts.md
Normal file
81
spec/js-api/legacy/importer.d.ts.md
Normal file
@ -0,0 +1,81 @@
|
||||
# Legacy Importer API
|
||||
|
||||
```ts
|
||||
import {LegacyPluginThis} from './plugin_this';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`LegacyImporterThis`](#legacyimporterthis)
|
||||
* [`fromImport`](#fromimport)
|
||||
* [`LegacyImporterResult`](#legacyimporterresult)
|
||||
* [`LegacySyncImporter`](#legacysyncimporter)
|
||||
* [`LegacyAsyncImporter`](#legacyasyncimporter)
|
||||
* [`LegacyImporter`](#legacyimporter)
|
||||
|
||||
## Types
|
||||
|
||||
### `LegacyImporterThis`
|
||||
|
||||
The interface for the `this` keyword for custom importers. The implementation
|
||||
must invoke importers with an appropriate `this`.
|
||||
|
||||
```ts
|
||||
interface LegacyImporterThis extends LegacyPluginThis {
|
||||
```
|
||||
|
||||
#### `fromImport`
|
||||
|
||||
The implementation must set this field to true if this importer invocation was
|
||||
caused by an `@import` statement and `false` otherwise.
|
||||
|
||||
> This allows importers to look for `.import.scss` stylesheets if and only if an
|
||||
> `@import` is being resolved.
|
||||
|
||||
```ts
|
||||
fromImport: boolean;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // LegacyImporterThis
|
||||
```
|
||||
|
||||
### `LegacyImporterResult`
|
||||
|
||||
```ts
|
||||
export type LegacyImporterResult =
|
||||
| {file: string}
|
||||
| {contents: string}
|
||||
| Error
|
||||
| null;
|
||||
```
|
||||
|
||||
### `LegacySyncImporter`
|
||||
|
||||
```ts
|
||||
type LegacySyncImporter = (
|
||||
this: LegacyImporterThis,
|
||||
url: string,
|
||||
prev: string
|
||||
) => LegacyImporterResult;
|
||||
```
|
||||
|
||||
### `LegacyAsyncImporter`
|
||||
|
||||
```ts
|
||||
type LegacyAsyncImporter = (
|
||||
this: LegacyImporterThis,
|
||||
url: string,
|
||||
prev: string,
|
||||
done: (result: LegacyImporterResult) => void
|
||||
) => void;
|
||||
```
|
||||
|
||||
### `LegacyImporter`
|
||||
|
||||
```ts
|
||||
export type LegacyImporter<sync = 'sync' | 'async'> = sync extends 'async'
|
||||
? LegacySyncImporter | LegacyAsyncImporter
|
||||
: LegacySyncImporter;
|
||||
```
|
95
spec/js-api/legacy/options.d.ts
vendored
95
spec/js-api/legacy/options.d.ts
vendored
@ -1,95 +0,0 @@
|
||||
import {Logger} from '../logger';
|
||||
import {LegacyImporter} from './importer';
|
||||
import {LegacyFunction} from './function';
|
||||
|
||||
/**
|
||||
* All the options for a Sass compilation except those that specify the specific
|
||||
* input format.
|
||||
*/
|
||||
export interface LegacySharedOptions<sync extends 'sync' | 'async'> {
|
||||
includePaths?: string[];
|
||||
|
||||
indentType?: 'space' | 'tab';
|
||||
|
||||
indentWidth?: number;
|
||||
|
||||
linefeed?: 'cr' | 'crlf' | 'lf' | 'lfcr';
|
||||
|
||||
omitSourceMapUrl?: boolean;
|
||||
|
||||
outFile?: string;
|
||||
|
||||
outputStyle?: 'compressed' | 'expanded' | 'nested' | 'compact';
|
||||
|
||||
sourceMap?: boolean | string;
|
||||
|
||||
sourceMapContents?: boolean;
|
||||
|
||||
sourceMapEmbed?: boolean;
|
||||
|
||||
sourceMapRoot?: string;
|
||||
|
||||
importer?: LegacyImporter<sync> | LegacyImporter<sync>[];
|
||||
|
||||
functions?: {[key: string]: LegacyFunction<sync>};
|
||||
|
||||
/**
|
||||
* If `true`, the compiler may prepend `@charset "UTF-8";` or U+FEFF
|
||||
* (byte-order marker) if it outputs non-ASCII CSS.
|
||||
*
|
||||
* If `false`, the compiler never emits these byte sequences. This is ideal
|
||||
* when concatenating or embedding in HTML `<style>` tags. (The output will
|
||||
* still be UTF-8.)
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
charset?: boolean;
|
||||
|
||||
/**
|
||||
* If true, the compiler must not print deprecation warnings for stylesheets
|
||||
* that are transitively loaded through an import path or importer.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
quietDeps?: boolean;
|
||||
|
||||
/**
|
||||
* If `true`, the compiler must print every single deprecation warning it
|
||||
* encounters.
|
||||
*
|
||||
* If `false`, the compiler may choose not to print repeated deprecation
|
||||
* warnings.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
verbose?: boolean;
|
||||
|
||||
/**
|
||||
* An object that provides callbacks for the compiler to use in lieu of its
|
||||
* default messaging behavior.
|
||||
*
|
||||
* The compiler must treat an `undefined` logger identically to an object that
|
||||
* doesn't have `warn` or `debug` fields.
|
||||
*/
|
||||
logger?: Logger;
|
||||
}
|
||||
|
||||
export interface LegacyFileOptions<sync extends 'sync' | 'async'>
|
||||
extends LegacySharedOptions<sync> {
|
||||
file: string;
|
||||
|
||||
data?: never;
|
||||
}
|
||||
|
||||
export interface LegacyStringOptions<sync extends 'sync' | 'async'>
|
||||
extends LegacySharedOptions<sync> {
|
||||
data: string;
|
||||
|
||||
file?: string;
|
||||
|
||||
indentedSyntax?: boolean;
|
||||
}
|
||||
|
||||
export type LegacyOptions<sync extends 'sync' | 'async'> =
|
||||
| LegacyFileOptions<sync>
|
||||
| LegacyStringOptions<sync>;
|
212
spec/js-api/legacy/options.d.ts.md
Normal file
212
spec/js-api/legacy/options.d.ts.md
Normal file
@ -0,0 +1,212 @@
|
||||
# Legacy API Options
|
||||
|
||||
```ts
|
||||
import {Logger} from '../logger';
|
||||
import {LegacyImporter} from './importer';
|
||||
import {LegacyFunction} from './function';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`LegacySharedOptions`](#legacysharedoptions)
|
||||
* [`includePaths`](#includepaths)
|
||||
* [`indentType`](#indenttype)
|
||||
* [`indentWidth`](#indentwidth)
|
||||
* [`linefeed`](#linefeed)
|
||||
* [`omitSourceMapUrl`](#omitsourcemapurl)
|
||||
* [`outFile`](#outfile)
|
||||
* [`outputStyle`](#outputstyle)
|
||||
* [`sourceMap`](#sourcemap)
|
||||
* [`sourceMapContents`](#sourcemapcontents)
|
||||
* [`sourceMapEmbed`](#sourcemapembed)
|
||||
* [`sourceMapRoot`](#sourcemaproot)
|
||||
* [`importer`](#importer)
|
||||
* [`functions`](#functions)
|
||||
* [`charset`](#charset)
|
||||
* [`quietDeps`](#quietdeps)
|
||||
* [`verbose`](#verbose)
|
||||
* [`logger`](#logger)
|
||||
* [`LegacyFileOptions`](#legacyfileoptions)
|
||||
* [`LegacyStringOptions`](#legacystringoptions)
|
||||
* [`LegacyOptions`](#legacyoptions)
|
||||
|
||||
## Types
|
||||
|
||||
### `LegacySharedOptions`
|
||||
|
||||
All the options for a legacy Sass compilation except those that specify the
|
||||
specific input format.
|
||||
|
||||
```ts
|
||||
export interface LegacySharedOptions<sync extends 'sync' | 'async'> {
|
||||
```
|
||||
|
||||
#### `includePaths`
|
||||
|
||||
```ts
|
||||
includePaths?: string[];
|
||||
```
|
||||
|
||||
#### `indentType`
|
||||
|
||||
```ts
|
||||
indentType?: 'space' | 'tab';
|
||||
```
|
||||
|
||||
#### `indentWidth`
|
||||
|
||||
```ts
|
||||
indentWidth?: number;
|
||||
```
|
||||
|
||||
#### `linefeed`
|
||||
|
||||
```ts
|
||||
linefeed?: 'cr' | 'crlf' | 'lf' | 'lfcr';
|
||||
```
|
||||
|
||||
#### `omitSourceMapUrl`
|
||||
|
||||
```ts
|
||||
omitSourceMapUrl?: boolean;
|
||||
```
|
||||
|
||||
#### `outFile`
|
||||
|
||||
```ts
|
||||
outFile?: string;
|
||||
```
|
||||
|
||||
#### `outputStyle`
|
||||
|
||||
```ts
|
||||
outputStyle?: 'compressed' | 'expanded' | 'nested' | 'compact';
|
||||
```
|
||||
|
||||
#### `sourceMap`
|
||||
|
||||
```ts
|
||||
sourceMap?: boolean | string;
|
||||
```
|
||||
|
||||
#### `sourceMapContents`
|
||||
|
||||
```ts
|
||||
sourceMapContents?: boolean;
|
||||
```
|
||||
|
||||
#### `sourceMapEmbed`
|
||||
|
||||
```ts
|
||||
sourceMapEmbed?: boolean;
|
||||
```
|
||||
|
||||
#### `sourceMapRoot`
|
||||
|
||||
```ts
|
||||
sourceMapRoot?: string;
|
||||
```
|
||||
|
||||
#### `importer`
|
||||
|
||||
```ts
|
||||
importer?: LegacyImporter<sync> | LegacyImporter<sync>[];
|
||||
```
|
||||
|
||||
#### `functions`
|
||||
|
||||
```ts
|
||||
functions?: {[key: string]: LegacyFunction<sync>};
|
||||
```
|
||||
|
||||
#### `charset`
|
||||
|
||||
If true, the compiler must prepend `@charset "UTF-8";` or U+FEFF (byte-order
|
||||
marker) if it emits non-ASCII CSS.
|
||||
|
||||
If false, the compiler must not prepend these byte sequences.
|
||||
|
||||
Defaults to true.
|
||||
|
||||
```ts
|
||||
charset?: boolean;
|
||||
```
|
||||
|
||||
#### `quietDeps`
|
||||
|
||||
|
||||
If true, the compiler must not print deprecation warnings for stylesheets that
|
||||
are transitively loaded through an import path.
|
||||
|
||||
Defaults to false.
|
||||
|
||||
```ts
|
||||
quietDeps?: boolean;
|
||||
```
|
||||
|
||||
#### `verbose`
|
||||
|
||||
If true, the compiler must print every single deprecation warning it encounters
|
||||
(except for those silenced by [`quietDeps`]).
|
||||
|
||||
[`quietDeps`]: #quietdeps
|
||||
|
||||
If false, the compiler may choose not to print repeated deprecation warnings.
|
||||
|
||||
Defaults to false.
|
||||
|
||||
```ts
|
||||
verbose?: boolean;
|
||||
```
|
||||
|
||||
#### `logger`
|
||||
|
||||
|
||||
A [custom logger] that provides callbacks for the compiler to use in lieu of its
|
||||
default messaging behavior.
|
||||
|
||||
[custom logger]: ../logger/index.d.ts.md
|
||||
|
||||
The compiler must treat an `undefined` logger identically to an object that
|
||||
doesn't have `warn` or `debug` fields.
|
||||
|
||||
```ts
|
||||
logger?: Logger;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // LegacySharedOptions
|
||||
```
|
||||
|
||||
### `LegacyFileOptions`
|
||||
|
||||
```ts
|
||||
export interface LegacyFileOptions<sync extends 'sync' | 'async'>
|
||||
extends LegacySharedOptions<sync> {
|
||||
file: string;
|
||||
|
||||
data?: never;
|
||||
}
|
||||
```
|
||||
|
||||
### `LegacyStringOptions`
|
||||
|
||||
```ts
|
||||
export interface LegacyStringOptions<sync extends 'sync' | 'async'>
|
||||
extends LegacySharedOptions<sync> {
|
||||
data: string;
|
||||
|
||||
file?: string;
|
||||
|
||||
indentedSyntax?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### `LegacyOptions`
|
||||
|
||||
```ts
|
||||
export type LegacyOptions<sync extends 'sync' | 'async'> =
|
||||
| LegacyFileOptions<sync>
|
||||
| LegacyStringOptions<sync>;
|
||||
```
|
72
spec/js-api/legacy/plugin_this.d.ts
vendored
72
spec/js-api/legacy/plugin_this.d.ts
vendored
@ -1,72 +0,0 @@
|
||||
/**
|
||||
* The shared interface for the `this` keyword for custom importers and custom
|
||||
* functions. The implementation must invoke importers and custom functions with
|
||||
* an appropriate `this`.
|
||||
*/
|
||||
export interface LegacyPluginThis {
|
||||
options: {
|
||||
/** The same `LegacyPluginThis` instance that contains this object. */
|
||||
context: LegacyPluginThis;
|
||||
|
||||
/** The `file` option passed to the `render()` or `renderSync()` call. */
|
||||
file?: string;
|
||||
|
||||
/** The `data` option passed to the `render()` or `renderSync()` call. */
|
||||
data?: string;
|
||||
|
||||
/**
|
||||
* A string that contains the current working directory followed by strings
|
||||
* passed in the `includePaths` option, separated by `";"` on Windows and
|
||||
* `":"` elsewhere.
|
||||
*/
|
||||
includePaths: string;
|
||||
|
||||
precision: 10;
|
||||
|
||||
/**
|
||||
* An integer. The specific semantics of this are left up to the
|
||||
* implementation. (The reference implementation always returns 1.)
|
||||
*/
|
||||
style: 1;
|
||||
|
||||
/**
|
||||
* The number 1 if the `indentType` option was `tab`. The number 0
|
||||
* otherwise.
|
||||
*/
|
||||
indentType: 1 | 0;
|
||||
|
||||
/**
|
||||
* An integer indicating the number of spaces or tabs emitted by the
|
||||
* compiler for each level of indentation.
|
||||
*/
|
||||
indentWidth: number;
|
||||
|
||||
/**
|
||||
* A value based on the `linefeed` option passed to the `render()` or
|
||||
* `renderSync()`:
|
||||
*
|
||||
* * If `linefeed` is `"cr"`, this must be `"\r"`.
|
||||
* * If `linefeed` is `"crlf"`, this must be `"\r\n"`.
|
||||
* * If `linefeed` is `"lf"` or `undefined`, this must be `"\n"`.
|
||||
* * If `linefeed` is `"lfcr"`, this must be `"\n\r"`.
|
||||
*/
|
||||
linefeed: '\r' | '\r\n' | '\n' | '\n\r';
|
||||
|
||||
result: {
|
||||
stats: {
|
||||
/**
|
||||
* The number of milliseconds since the Unix epoch (1 January 1970
|
||||
* 00:00:00 UT) at the point at which the user called `render()` or
|
||||
* `renderSync()`.
|
||||
*/
|
||||
start: number;
|
||||
|
||||
/**
|
||||
* The `file` option passed to the `render()` call, or the string
|
||||
* `"data"` if no file was passed.
|
||||
*/
|
||||
entry: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
156
spec/js-api/legacy/plugin_this.d.ts.md
Normal file
156
spec/js-api/legacy/plugin_this.d.ts.md
Normal file
@ -0,0 +1,156 @@
|
||||
# Legacy Plugin Context
|
||||
|
||||
The shared interface for the `this` keyword for custom importers and custom
|
||||
functions. The implementation must invoke importers and custom functions with an
|
||||
appropriate `this`.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`LegacyPluginThis`](#legacypluginthis)
|
||||
* [`context`](#context)
|
||||
* [`file`](#file)
|
||||
* [`data`](#data)
|
||||
* [`includePaths`](#includepaths)
|
||||
* [`precision`](#precision)
|
||||
* [`style`](#style)
|
||||
* [`indentType`](#indenttype)
|
||||
* [`indentWidth`](#indentwidth)
|
||||
* [`linefeed`](#linefeed)
|
||||
* [`result`](#result)
|
||||
* [`result.stats.start`](#resultstatsstart)
|
||||
* [`result.stats.entry`](#resultstatsentry)
|
||||
|
||||
## Types
|
||||
|
||||
### `LegacyPluginThis`
|
||||
|
||||
This class contains a single field, `options`, which contains all its metadata.
|
||||
|
||||
```ts
|
||||
export interface LegacyPluginThis {
|
||||
options: {
|
||||
```
|
||||
|
||||
#### `context`
|
||||
|
||||
The same `LegacyPluginThis` instance that contains the `options` object.
|
||||
|
||||
```ts
|
||||
context: LegacyPluginThis;
|
||||
```
|
||||
|
||||
#### `file`
|
||||
|
||||
The [`file` option] passed to the `render()` or `renderSync()` call.
|
||||
|
||||
[`file` option]: options.d.ts.md#legacyfileoptions
|
||||
|
||||
```ts
|
||||
file?: string;
|
||||
```
|
||||
|
||||
#### `data`
|
||||
|
||||
The [`data` option] passed to the `render()` or `renderSync()` call.
|
||||
|
||||
[`data` option]: options.d.ts.md#legacystringoptions
|
||||
|
||||
```ts
|
||||
data?: string;
|
||||
```
|
||||
|
||||
#### `includePaths`
|
||||
|
||||
A string that contains the current working directory followed by strings passed
|
||||
in the `includePaths` option, separated by `";"` on Windows and `":"` elsewhere.
|
||||
|
||||
```ts
|
||||
includePaths: string;
|
||||
```
|
||||
|
||||
#### `precision`
|
||||
|
||||
```ts
|
||||
precision: 10;
|
||||
```
|
||||
|
||||
#### `style`
|
||||
|
||||
The integer 1.
|
||||
|
||||
> Older implementations returned other values for this, but that behavior is
|
||||
> deprecated and should not be reproduced by new implementations.
|
||||
|
||||
```ts
|
||||
style: 1;
|
||||
```
|
||||
|
||||
#### `indentType`
|
||||
|
||||
The number 1 if the [`indentType` option] was `'tab'`. The number 0 otherwise.
|
||||
|
||||
[`indentType` option]: options.d.ts.md#indenttype
|
||||
|
||||
```ts
|
||||
indentType: 1 | 0;
|
||||
```
|
||||
|
||||
#### `indentWidth`
|
||||
|
||||
An integer indicating the number of spaces or tabs emitted by the compiler for
|
||||
each level of indentation.
|
||||
|
||||
```ts
|
||||
indentWidth: number;
|
||||
```
|
||||
|
||||
#### `linefeed`
|
||||
|
||||
A value based on the [`linefeed` option] passed to the `render()` or
|
||||
`renderSync()`:
|
||||
|
||||
[`linefeed` option]: options.d.ts.md#linefeed
|
||||
|
||||
* If `linefeed` is `"cr"`, this must be `"\r"`.
|
||||
* If `linefeed` is `"crlf"`, this must be `"\r\n"`.
|
||||
* If `linefeed` is `"lf"` or `undefined`, this must be `"\n"`.
|
||||
* If `linefeed` is `"lfcr"`, this must be `"\n\r"`.
|
||||
|
||||
```ts
|
||||
linefeed: '\r' | '\r\n' | '\n' | '\n\r';
|
||||
```
|
||||
|
||||
#### `result`
|
||||
|
||||
An object with a single field, `stats`, which contains several subfields.
|
||||
|
||||
```ts
|
||||
result: {
|
||||
stats: {
|
||||
```
|
||||
|
||||
##### `result.stats.start`
|
||||
|
||||
The number of milliseconds since the Unix epoch (1 January 1970 00:00:00 UT) at
|
||||
the point at which the user called `render()` or `renderSync()`.
|
||||
|
||||
```ts
|
||||
start: number;
|
||||
```
|
||||
|
||||
##### `result.stats.entry`
|
||||
|
||||
The [`file` option] passed to the `render()` call, or the string `"data"` if no
|
||||
file was passed.
|
||||
|
||||
```ts
|
||||
entry: string;
|
||||
```
|
||||
|
||||
```ts
|
||||
}; // options.result.stats
|
||||
}; // options.result
|
||||
}; // options
|
||||
} // LegacyPluginThis
|
||||
```
|
75
spec/js-api/logger/index.d.ts
vendored
75
spec/js-api/logger/index.d.ts
vendored
@ -1,75 +0,0 @@
|
||||
import {SourceSpan} from './source_span';
|
||||
|
||||
export {SourceLocation} from './source_location';
|
||||
export {SourceSpan} from './source_span';
|
||||
|
||||
/**
|
||||
* An object that provides callbacks for handling messages from the
|
||||
* compiler.
|
||||
*/
|
||||
export interface Logger {
|
||||
/**
|
||||
* If this field is defined, the compiler must invoke it under the following
|
||||
* circumstances:
|
||||
*
|
||||
* * When it encounters a `@warn` rule:
|
||||
* * Let `value` be the result of evaluating the rule's expression.
|
||||
* * Let `message` be `value`'s text if it's a string, or the result of
|
||||
* serializing `value` if it's not.
|
||||
* * Invoke `warn` with `message` and an object with `deprecation` set to
|
||||
* `false` and `stack` set to a string representation of the current Sass
|
||||
* stack trace.
|
||||
*
|
||||
* > The specific format of the stack trace may vary from implementation
|
||||
* > to implementation.
|
||||
*
|
||||
* * When it encounters anything else that the user needs to be warned about:
|
||||
*
|
||||
* > This is intentionally vague about what counts as a warning.
|
||||
* > Implementations have a considerable degree of flexibility in defining
|
||||
* > this for themselves, although in some cases warnings are mandated by
|
||||
* > the specification (such as in preparation for a breaking change).
|
||||
*
|
||||
* * Let `options` be an empty object.
|
||||
* * If this warning is caused by behavior that used to be allowed but will
|
||||
* be disallowed in the future, set `options.deprecation` to `true`.
|
||||
* Otherwise, set `options.deprecation` to `false`.
|
||||
* * If this warning is associated with a specific span of a Sass
|
||||
* stylesheet, set `options.span` to a `SourceSpan` that covers that span.
|
||||
* * If this warning occurred during execution of a stylesheet, set
|
||||
* `options.stack` to a string representation of the current Sass stack
|
||||
* trace.
|
||||
* * Invoke `warn` with a string describing the warning and `options`.
|
||||
*
|
||||
* If this field is defined, the compiler must not surface warnings in any way
|
||||
* other than inkoving `warn`.
|
||||
*/
|
||||
warn?(
|
||||
message: string,
|
||||
options: {
|
||||
deprecation: boolean;
|
||||
span?: SourceSpan;
|
||||
stack?: string;
|
||||
}
|
||||
): void;
|
||||
|
||||
/**
|
||||
* If this field is defined, the compiler must invoke it when it encounters a
|
||||
* `@debug` rule using the following procedure:
|
||||
*
|
||||
* * Let `value` be the result of evaluating the rule's expression.
|
||||
* * Let `message` be `value`'s text if it's a string, or the result of
|
||||
* serializing `value` if it's not.
|
||||
* * Invoke `debug` with `message` and an object with `span` set to the span
|
||||
* covering the `@debug` rule and its expression.
|
||||
*
|
||||
* If this field is defined, the compiler must not surface debug messages in
|
||||
* any way other than invoking `debug`.
|
||||
*/
|
||||
debug?(message: string, options: {span: SourceSpan}): void;
|
||||
}
|
||||
|
||||
export namespace Logger {
|
||||
/** A Logger that does nothing when it warn or debug methods are called. */
|
||||
export const silent: Logger;
|
||||
}
|
122
spec/js-api/logger/index.d.ts.md
Normal file
122
spec/js-api/logger/index.d.ts.md
Normal file
@ -0,0 +1,122 @@
|
||||
# Logger API
|
||||
|
||||
```ts
|
||||
import {SourceSpan} from './source_span';
|
||||
|
||||
export {SourceLocation} from './source_location';
|
||||
export {SourceSpan} from './source_span';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`Logger`](#logger)
|
||||
* [`warn`](#warn)
|
||||
* [`debug`](#debug)
|
||||
* [Fields](#fields)
|
||||
* [`Logger`](#logger-1)
|
||||
* [`silent`](#silent)
|
||||
|
||||
|
||||
## Types
|
||||
|
||||
### `Logger`
|
||||
|
||||
An object that provides callbacks for handling messages from the compiler.
|
||||
|
||||
```ts
|
||||
export interface Logger {
|
||||
```
|
||||
|
||||
#### `warn`
|
||||
|
||||
If this field is defined, the compiler must invoke it under the following
|
||||
circumstances:
|
||||
|
||||
* When it encounters a `@warn` rule:
|
||||
|
||||
* Let `value` be the result of evaluating the rule's expression.
|
||||
* Let `message` be `value`'s text if it's a string, or the result of
|
||||
serializing `value` if it's not.
|
||||
* Invoke `warn` with `message` and an object with `deprecation` set to `false`
|
||||
and `stack` set to a string representation of the current Sass stack trace.
|
||||
|
||||
> The specific format of the stack trace may vary from implementation to
|
||||
> implementation.
|
||||
|
||||
* When it encounters anything else that the user needs to be warned about:
|
||||
|
||||
> This is intentionally vague about what counts as a warning. Implementations
|
||||
> have a considerable degree of flexibility in defining this for themselves,
|
||||
> although in some cases warnings are mandated by the specification (such as
|
||||
> in preparation for a breaking change).
|
||||
|
||||
* Let `options` be an empty object.
|
||||
* If this warning is caused by behavior that used to be allowed but will be
|
||||
disallowed in the future, set `options.deprecation` to `true`. Otherwise,
|
||||
set `options.deprecation` to `false`.
|
||||
* If this warning is associated with a specific span of a Sass stylesheet, set
|
||||
`options.span` to a `SourceSpan` that covers that span.
|
||||
* If this warning occurred during execution of a stylesheet, set
|
||||
`options.stack` to a string representation of the current Sass stack trace.
|
||||
* Invoke `warn` with a string describing the warning and `options`.
|
||||
|
||||
If this field is defined, the compiler must not surface warnings in any way
|
||||
other than inkoving `warn`.
|
||||
|
||||
```ts
|
||||
warn?(
|
||||
message: string,
|
||||
options: {
|
||||
deprecation: boolean;
|
||||
span?: SourceSpan;
|
||||
stack?: string;
|
||||
}
|
||||
): void;
|
||||
```
|
||||
|
||||
#### `debug`
|
||||
|
||||
If this field is defined, the compiler must invoke it when it encounters a
|
||||
`@debug` rule using the following procedure:
|
||||
|
||||
* Let `value` be the result of evaluating the rule's expression.
|
||||
* Let `message` be `value`'s text if it's a string, or the result of serializing
|
||||
`value` if it's not.
|
||||
* Invoke `debug` with `message` and an object with `span` set to the span
|
||||
covering the `@debug` rule and its expression.
|
||||
|
||||
If this field is defined, the compiler must not surface debug messages in any
|
||||
way other than invoking `debug`.
|
||||
|
||||
```ts
|
||||
debug?(message: string, options: {span: SourceSpan}): void;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // interface Logger
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
### `Logger`
|
||||
|
||||
A namespace for built-in logger implementations.
|
||||
|
||||
```ts
|
||||
export namespace Logger {
|
||||
```
|
||||
|
||||
#### `silent`
|
||||
|
||||
A [`Logger`] that does nothing when it warn or debug methods are called.
|
||||
|
||||
[`Logger`]: #logger
|
||||
|
||||
```ts
|
||||
export const silent: Logger;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // namespace Logger
|
||||
```
|
24
spec/js-api/logger/source_location.d.ts
vendored
24
spec/js-api/logger/source_location.d.ts
vendored
@ -1,24 +0,0 @@
|
||||
/** An interface that represents a location in a text file. */
|
||||
export interface SourceLocation {
|
||||
/**
|
||||
* The 0-based offset of this location within the file it refers to, in terms
|
||||
* of UTF-16 code units.
|
||||
*/
|
||||
offset: number;
|
||||
|
||||
/**
|
||||
* The number of U+000A LINE FEED characters between the beginning of the file
|
||||
* and `offset`, exclusive.
|
||||
*
|
||||
* > In other words, this location's 0-based line.
|
||||
*/
|
||||
line: number;
|
||||
|
||||
/**
|
||||
* The number of UTF-16 code points between the last U+000A LINE FEED
|
||||
* character before `offset` and `offset`, exclusive.
|
||||
*
|
||||
* > In other words, this location's 0-based column.
|
||||
*/
|
||||
column: number;
|
||||
}
|
54
spec/js-api/logger/source_location.d.ts.md
Normal file
54
spec/js-api/logger/source_location.d.ts.md
Normal file
@ -0,0 +1,54 @@
|
||||
# Source Location
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`SourceLocation`](#sourcelocation)
|
||||
* [`offset`](#offset)
|
||||
* [`line`](#line)
|
||||
* [`column`](#column)
|
||||
|
||||
## Types
|
||||
|
||||
### `SourceLocation`
|
||||
|
||||
An interface that represents a location in a text file.
|
||||
|
||||
```ts
|
||||
export interface SourceLocation {
|
||||
```
|
||||
|
||||
#### `offset`
|
||||
|
||||
The 0-based offset of this location within the file it refers to, in terms of
|
||||
UTF-16 code units.
|
||||
|
||||
```ts
|
||||
offset: number;
|
||||
```
|
||||
|
||||
#### `line`
|
||||
|
||||
The number of U+000A LINE FEED characters between the beginning of the file and
|
||||
`offset`, exclusive.
|
||||
|
||||
> In other words, this location's 0-based line.
|
||||
|
||||
```ts
|
||||
line: number;
|
||||
```
|
||||
|
||||
#### `column`
|
||||
|
||||
The number of UTF-16 code points between the last U+000A LINE FEED character
|
||||
before `offset` and `offset`, exclusive.
|
||||
|
||||
> In other words, this location's 0-based column.
|
||||
|
||||
```ts
|
||||
column: number;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SourceLocation
|
||||
```
|
50
spec/js-api/logger/source_span.d.ts
vendored
50
spec/js-api/logger/source_span.d.ts
vendored
@ -1,50 +0,0 @@
|
||||
import {SourceLocation} from './source_location';
|
||||
|
||||
/**
|
||||
* An interface that represents a contiguous section ("span") of a text file.
|
||||
* This section may be empty if the `start` and `end` are the same location,
|
||||
* in which case it indicates a single position in the file.
|
||||
*/
|
||||
export interface SourceSpan {
|
||||
/**
|
||||
* The location of the first character of this span, unless `end` points to
|
||||
* the same character, in which case the span is empty and refers to the point
|
||||
* between this character and the one before it.
|
||||
*/
|
||||
start: SourceLocation;
|
||||
|
||||
/**
|
||||
* The location of the first character after this span. This must point to a
|
||||
* location after `start`.
|
||||
*/
|
||||
end: SourceLocation;
|
||||
|
||||
/**
|
||||
* The canonical URL of the file that this span refers to. For files on disk,
|
||||
* this must be a `file://` URL.
|
||||
*
|
||||
* This must be `undefined` for files that are passed to the compiler without
|
||||
* a URL. It must not be `undefined` for any files that are importable.
|
||||
*/
|
||||
url?: URL;
|
||||
|
||||
/**
|
||||
* The text covered by the span. This must be the text between `start.offset`
|
||||
* (inclusive) and `end.offset` (exclusive) of the file referred by this
|
||||
* span. Its length must be `end.offset - start.offset`.
|
||||
*/
|
||||
text: string;
|
||||
|
||||
/**
|
||||
* Additional source text surrounding this span.
|
||||
*
|
||||
* The compiler may choose to omit this. If it's not `undefined`, it must
|
||||
* contain `text`. Furthermore, `text` must begin at column `start.column` of
|
||||
* a line in `context`.
|
||||
*
|
||||
* > This usually contains the full lines the span begins and ends on if the
|
||||
* > span itself doesn't cover the full lines, but the specific scope is up to
|
||||
* > the compiler.
|
||||
*/
|
||||
context?: string;
|
||||
}
|
88
spec/js-api/logger/source_span.d.ts.md
Normal file
88
spec/js-api/logger/source_span.d.ts.md
Normal file
@ -0,0 +1,88 @@
|
||||
# Source Span
|
||||
|
||||
```ts
|
||||
import {SourceLocation} from './source_location';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`SourceSpan`](#sourcespan)
|
||||
* [`start`](#start)
|
||||
* [`end`](#end)
|
||||
* [`url`](#url)
|
||||
* [`text`](#text)
|
||||
* [`context`](#context)
|
||||
|
||||
## Types
|
||||
|
||||
### `SourceSpan`
|
||||
|
||||
An interface that represents a contiguous section ("span") of a text file. This
|
||||
section may be empty if the `start` and `end` are the same location, in which
|
||||
case it indicates a single position in the file.
|
||||
|
||||
```ts
|
||||
export interface SourceSpan {
|
||||
```
|
||||
|
||||
#### `start`
|
||||
|
||||
The location of the first character of this span, unless `end` points to the
|
||||
same character, in which case the span is empty and refers to the point between
|
||||
this character and the one before it.
|
||||
|
||||
```ts
|
||||
start: SourceLocation;
|
||||
```
|
||||
|
||||
#### `end`
|
||||
|
||||
The location of the first character after this span. This must point to a
|
||||
location after `start`.
|
||||
|
||||
```ts
|
||||
end: SourceLocation;
|
||||
```
|
||||
|
||||
#### `url`
|
||||
|
||||
The canonical URL of the file that this span refers to. For files on disk, this
|
||||
must be a `file://` URL.
|
||||
|
||||
This must be `undefined` for files that are passed to the compiler without a
|
||||
URL. It must not be `undefined` for any files that are importable.
|
||||
|
||||
```ts
|
||||
url?: URL;
|
||||
```
|
||||
|
||||
#### `text`
|
||||
|
||||
The text covered by the span. This must be the text between `start.offset`
|
||||
(inclusive) and `end.offset` (exclusive) of the file referred by this span. Its
|
||||
length must be `end.offset - start.offset`.
|
||||
|
||||
```ts
|
||||
text: string;
|
||||
```
|
||||
|
||||
#### `context`
|
||||
|
||||
Additional source text surrounding this span.
|
||||
|
||||
The compiler may choose to omit this. If it's not `undefined`, it must contain
|
||||
`text`. Furthermore, `text` must begin at column `start.column` of a line in
|
||||
`context`.
|
||||
|
||||
> This usually contains the full lines the span begins and ends on if the span
|
||||
> itself doesn't cover the full lines, but the specific scope is up to the
|
||||
> compiler.
|
||||
|
||||
```ts
|
||||
context?: string;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SourceSpan
|
||||
```
|
174
spec/js-api/options.d.ts
vendored
174
spec/js-api/options.d.ts
vendored
@ -1,174 +0,0 @@
|
||||
import {FileImporter, Importer} from './importer';
|
||||
import {Logger} from './logger';
|
||||
import {Value} from './value';
|
||||
import {PromiseOr} from './util/promise_or';
|
||||
|
||||
/** The types of input syntax that the compiler can parse. */
|
||||
export type Syntax = 'scss' | 'indented' | 'css';
|
||||
|
||||
/**
|
||||
* The ways in which the compiler can format the emitted CSS.
|
||||
*
|
||||
* > The specifics of each format can vary from implementation to
|
||||
* > implementation. If an implementation wants to add a new OutputStyle, they
|
||||
* > should expand this type.
|
||||
*/
|
||||
export type OutputStyle = 'expanded' | 'compressed';
|
||||
|
||||
/** A custom function that can be called from Sass stylesheets. */
|
||||
export type CustomFunction<sync extends 'sync' | 'async'> = (
|
||||
args: Value[]
|
||||
) => PromiseOr<Value, sync>;
|
||||
|
||||
/**
|
||||
* All of the options for a Sass compilation that are shared by compiling from a
|
||||
* path and by compiling from a string.
|
||||
*/
|
||||
export interface Options<sync extends 'sync' | 'async'> {
|
||||
/**
|
||||
* If true, the compiler must use only ASCII characters in the formatted
|
||||
* message of errors and logs that aren't handled by a `logger`.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
alertAscii?: boolean;
|
||||
|
||||
/**
|
||||
* If true, the compiler may use terminal colors in the formatted message of
|
||||
* errors and logs that aren't handled by a `logger`. Implementations may
|
||||
* choose the default value for this based on their own heuristics of whether
|
||||
* colored output would be useful or render appropriately. Implementations are
|
||||
* not obligated to use colors even if this is `true`.
|
||||
*
|
||||
* > The specific format can vary from implementation to implementation.
|
||||
*/
|
||||
alertColor?: boolean;
|
||||
|
||||
/**
|
||||
* If `true`, the compiler may prepend `@charset "UTF-8";` or U+FEFF
|
||||
* (byte-order marker) if it outputs non-ASCII CSS.
|
||||
*
|
||||
* If `false`, the compiler never emits these byte sequences. This is ideal
|
||||
* when concatenating or embedding in HTML `<style>` tags. (The output will
|
||||
* still be UTF-8.)
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
charset?: boolean;
|
||||
|
||||
/**
|
||||
* When the compiler encounters a global function call with a signature that
|
||||
* does not match that of a built-in function, but matches a key in this
|
||||
* record, it must call the associated `CustomFunction` and return its result.
|
||||
* If the function throws an error or returns anything other than a `Value`,
|
||||
* the compiler should treat it as the Sass function throwing an error.
|
||||
*
|
||||
* > As in the rest of Sass, `_`s and `-`s are considered equivalent when
|
||||
* > determining which function signatures match.
|
||||
*
|
||||
* Before beginning compilation, if any key in this record is not an
|
||||
* [<ident-token>] followed immediately by an `ArgumentDeclaration`, the
|
||||
* compiler must throw an error.
|
||||
*
|
||||
* [<ident-token>]: https://drafts.csswg.org/css-syntax-3/#ident-token-diagram
|
||||
*
|
||||
* If the `CustomFunction` returns an invalid value, or a value that
|
||||
* transitively contains an invalid value, the compiler must treat that as the
|
||||
* Sass function throwing an error. The following values are considered
|
||||
* invalid:
|
||||
*
|
||||
* - 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.
|
||||
*/
|
||||
functions?: Record<string, CustomFunction<sync>>;
|
||||
|
||||
/** The list of of custom importers to use to resolve file loads. */
|
||||
importers?: (Importer<sync> | FileImporter<sync>)[];
|
||||
|
||||
/** If set, the compiler must use these paths to resolve imports. */
|
||||
loadPaths?: string[];
|
||||
|
||||
/**
|
||||
* An object that provides callbacks for the compiler to use in lieu of its
|
||||
* default messaging behavior.
|
||||
*
|
||||
* The compiler must treat an `undefined` logger identically to an object
|
||||
* that doesn't have `warn` or `debug` fields.
|
||||
*/
|
||||
logger?: Logger;
|
||||
|
||||
/**
|
||||
* If true, the compiler must not print deprecation warnings for stylesheets
|
||||
* that are transitively loaded through an import path.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
quietDeps?: boolean;
|
||||
|
||||
/**
|
||||
* If true, the compiler must set the sourceMap field of the `CompileResult`
|
||||
* to a sourceMap object.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
sourceMap?: boolean;
|
||||
|
||||
/**
|
||||
* If true, the compiler must include the sources in the sourceMap of the
|
||||
* `CompileResult`.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
sourceMapIncludeSources?: boolean;
|
||||
|
||||
/**
|
||||
* If present, the compiler must format the emitted CSS in this style.
|
||||
*
|
||||
* Implementations may support any amount of options, provided that:
|
||||
* - They support the 'expanded' option.
|
||||
* - They produce CSS that is semantically equivalent regardless of style.
|
||||
* - They throw an error if they receive a value for this option that they
|
||||
* do not support.
|
||||
*/
|
||||
style?: OutputStyle;
|
||||
|
||||
/**
|
||||
* If `true`, the compiler must print every single deprecation warning it
|
||||
* encounters.
|
||||
*
|
||||
* If `false`, the compiler may choose not to print repeated deprecation
|
||||
* warnings.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
verbose?: boolean;
|
||||
}
|
||||
|
||||
export interface StringOptionsWithoutImporter<sync extends 'sync' | 'async'>
|
||||
extends Options<sync> {
|
||||
/**
|
||||
* The compiler must parse `source` using this syntax.
|
||||
*
|
||||
* @default 'scss'
|
||||
*/
|
||||
syntax?: Syntax;
|
||||
|
||||
/** When `importer` isn't passed, this is purely advisory. */
|
||||
url?: URL;
|
||||
}
|
||||
|
||||
export interface StringOptionsWithImporter<sync extends 'sync' | 'async'>
|
||||
extends StringOptionsWithoutImporter<sync> {
|
||||
/** The importer to use to resolve relative imports in the entrypoint. */
|
||||
importer: Importer<sync> | FileImporter<sync>;
|
||||
|
||||
/** The canonical URL of the entrypoint. */
|
||||
url: URL;
|
||||
}
|
||||
|
||||
export type StringOptions<sync extends 'sync' | 'async'> =
|
||||
| StringOptionsWithImporter<sync>
|
||||
| StringOptionsWithoutImporter<sync>;
|
340
spec/js-api/options.d.ts.md
Normal file
340
spec/js-api/options.d.ts.md
Normal file
@ -0,0 +1,340 @@
|
||||
## API Options
|
||||
|
||||
> The options object that's passed to the [compile API] to control various
|
||||
> aspects of Sass compilation.
|
||||
>
|
||||
> [compile API]: compile.d.ts.md
|
||||
|
||||
```ts
|
||||
import {FileImporter, Importer} from './importer';
|
||||
import {Logger} from './logger';
|
||||
import {Value} from './value';
|
||||
import {PromiseOr} from './util/promise_or';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`Syntax`](#syntax)
|
||||
* [`OutputStyle`](#outputstyle)
|
||||
* [`CustomFunction`](#customfunction)
|
||||
* [`Options`](#options)
|
||||
* [`alertAscii`](#alertascii)
|
||||
* [`alertColor`](#alertcolor)
|
||||
* [`charset`](#charset)
|
||||
* [`functions`](#functions)
|
||||
* [`importers`](#importers)
|
||||
* [`loadPaths`](#loadpaths)
|
||||
* [`logger`](#logger)
|
||||
* [`quietDeps`](#quietdeps)
|
||||
* [`sourceMap`](#sourcemap)
|
||||
* [`sourceMapIncludeSources`](#sourcemapincludesources)
|
||||
* [`style`](#style)
|
||||
* [`verbose`](#verbose)
|
||||
* [`StringOptionsWithoutImporter`](#stringoptionswithoutimporter)
|
||||
* [`syntax`](#syntax)
|
||||
* [`url`](#url)
|
||||
* [`StringOptionsWithImporter`](#stringoptionswithimporter)
|
||||
* [`importer`](#importer)
|
||||
* [`url`](#url-1)
|
||||
* [`StringOptions`](#stringoptions)
|
||||
|
||||
## Types
|
||||
|
||||
### `Syntax`
|
||||
|
||||
The types of input syntax that the compiler can parse.
|
||||
|
||||
```ts
|
||||
export type Syntax = 'scss' | 'indented' | 'css';
|
||||
```
|
||||
|
||||
### `OutputStyle`
|
||||
|
||||
The ways in which the compiler can format the emitted CSS. See [`Options.style`]
|
||||
for details.
|
||||
|
||||
[`Options.style`]: #style
|
||||
|
||||
```ts
|
||||
export type OutputStyle = 'expanded' | 'compressed';
|
||||
```
|
||||
|
||||
### `CustomFunction`
|
||||
|
||||
A custom function that can be called from Sass stylesheets.
|
||||
|
||||
```ts
|
||||
export type CustomFunction<sync extends 'sync' | 'async'> = (
|
||||
args: Value[]
|
||||
) => PromiseOr<Value, sync>;
|
||||
```
|
||||
|
||||
### `Options`
|
||||
|
||||
All of the options for a Sass compilation that are shared between compiling from
|
||||
a path and by compiling from a string.
|
||||
|
||||
```ts
|
||||
export interface Options<sync extends 'sync' | 'async'> {
|
||||
```
|
||||
|
||||
#### `alertAscii`
|
||||
|
||||
If true, the compiler must use only ASCII characters in the formatted message of
|
||||
errors and logs that aren't handled by a `logger`. Defaults to false.
|
||||
|
||||
```ts
|
||||
alertAscii?: boolean;
|
||||
```
|
||||
|
||||
#### `alertColor`
|
||||
|
||||
If true, the compiler may use terminal colors in the formatted message of errors
|
||||
and logs that aren't handled by a `logger`. Implementations may choose the
|
||||
default value for this based on their own heuristics of whether colored output
|
||||
would be useful or render appropriately. Implementations are not obligated to
|
||||
use colors even if this is `true`.
|
||||
|
||||
> The specific format of colored output can vary from implementation to
|
||||
> implementation.
|
||||
|
||||
```ts
|
||||
alertColor?: boolean;
|
||||
```
|
||||
|
||||
#### `charset`
|
||||
|
||||
If true, the compiler must prepend `@charset "UTF-8";` or U+FEFF (byte-order
|
||||
marker) if it emits non-ASCII CSS.
|
||||
|
||||
If false, the compiler must not prepend these byte sequences.
|
||||
|
||||
Defaults to true.
|
||||
|
||||
> This is ideal when concatenating CSS or embedding it in HTML `<style>` tags.
|
||||
> Note that the output will still be UTF-8 regardless of this option.
|
||||
|
||||
```ts
|
||||
charset?: boolean;
|
||||
```
|
||||
|
||||
#### `functions`
|
||||
|
||||
When the compiler encounters a global function call with a signature that does
|
||||
not match that of a built-in function, but matches a key in this record, it must
|
||||
call the associated `CustomFunction` and return its result. If the function
|
||||
throws an error or returns anything other than a `Value`, the compiler should
|
||||
treat it as the Sass function throwing an error.
|
||||
|
||||
> As in the rest of Sass, `_`s and `-`s are considered equivalent when
|
||||
> determining which function signatures match.
|
||||
|
||||
Before beginning compilation, if any key in this record is not an
|
||||
[<ident-token>] followed immediately by an `ArgumentDeclaration`, the compiler
|
||||
must throw an error.
|
||||
|
||||
[<ident-token>]: https://drafts.csswg.org/css-syntax-3/#ident-token-diagram
|
||||
|
||||
If the `CustomFunction` returns an invalid value, or a value that transitively
|
||||
contains an invalid value, the compiler must treat that as the Sass function
|
||||
throwing an error. The following values are considered invalid:
|
||||
|
||||
* 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.
|
||||
|
||||
```ts
|
||||
functions?: Record<string, CustomFunction<sync>>;
|
||||
```
|
||||
|
||||
#### `importers`
|
||||
|
||||
The list of [custom importers] to use to resolve file loads.
|
||||
|
||||
[custom importers]: importer.d.ts.md
|
||||
|
||||
```ts
|
||||
importers?: (Importer<sync> | FileImporter<sync>)[];
|
||||
```
|
||||
|
||||
#### `loadPaths`
|
||||
|
||||
If set, the compiler must use these paths to resolve imports.
|
||||
|
||||
```ts
|
||||
loadPaths?: string[];
|
||||
```
|
||||
|
||||
#### `logger`
|
||||
|
||||
A [custom logger] that provides callbacks for the compiler to use in lieu of its
|
||||
default messaging behavior.
|
||||
|
||||
[custom logger]: logger/index.d.ts.md
|
||||
|
||||
The compiler must treat an `undefined` logger identically to an object that
|
||||
doesn't have `warn` or `debug` fields.
|
||||
|
||||
```ts
|
||||
logger?: Logger;
|
||||
```
|
||||
|
||||
#### `quietDeps`
|
||||
|
||||
If true, the compiler must not print deprecation warnings for stylesheets that
|
||||
are transitively loaded through an import path.
|
||||
|
||||
Defaults to false.
|
||||
|
||||
```ts
|
||||
quietDeps?: boolean;
|
||||
```
|
||||
|
||||
#### `sourceMap`
|
||||
|
||||
If true, the compiler must set [`CompileResult.sourceMap`] to a sourceMap object
|
||||
that represents the mapping between the generated CSS and the source files.
|
||||
|
||||
[`CompileResult.sourceMap`]: compile.d.ts.md#compileresult
|
||||
|
||||
Defaults to false.
|
||||
|
||||
> Except as otherwise specified, the exact structure of this file and how it
|
||||
> maps between CSS and Sass is left up to the implementation.
|
||||
|
||||
```ts
|
||||
sourceMap?: boolean;
|
||||
```
|
||||
|
||||
#### `sourceMapIncludeSources`
|
||||
|
||||
If true, the compiler must include the full Sass source text in
|
||||
[`CompileResult.sourceMap`].
|
||||
|
||||
Defaults to false.
|
||||
|
||||
```ts
|
||||
sourceMapIncludeSources?: boolean;
|
||||
```
|
||||
|
||||
#### `style`
|
||||
|
||||
If present, the compiler must format the emitted CSS in this style.
|
||||
|
||||
Implementations may support any subset of `OutputStyle`s, provided that:
|
||||
|
||||
* They support the `'expanded'` style.
|
||||
* They produce CSS that is semantically equivalent regardless of style.
|
||||
* They throw an error if they receive a value for this option that they do not
|
||||
support.
|
||||
|
||||
> The specifics of each format can vary from implementation to implementation.
|
||||
> If an implementation wants to add a new `OutputStyle`, the `OutputStyle` type
|
||||
> should be expanded in this spec first to ensure that style names and
|
||||
> TypeScript types remain consistent across implementations.
|
||||
|
||||
```ts
|
||||
style?: OutputStyle;
|
||||
```
|
||||
|
||||
#### `verbose`
|
||||
|
||||
If true, the compiler must print every single deprecation warning it encounters
|
||||
(except for those silenced by [`quietDeps`]).
|
||||
|
||||
[`quietDeps`]: #quietdeps
|
||||
|
||||
If false, the compiler may choose not to print repeated deprecation warnings.
|
||||
|
||||
Defaults to false.
|
||||
|
||||
```ts
|
||||
verbose?: boolean;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // Options
|
||||
```
|
||||
|
||||
### `StringOptionsWithoutImporter`
|
||||
|
||||
> This interface is used for calls to [`compileString()`] and
|
||||
> [`compileStringAsync()`] that don't pass the `importer` parameter, and so
|
||||
> don't support relative imports.
|
||||
>
|
||||
> [`compileString()`]: compile.d.ts.md#compilestring
|
||||
> [`compileStringAsync()`]: compile.d.ts.md#compilestringasync
|
||||
|
||||
```ts
|
||||
export interface StringOptionsWithoutImporter<sync extends 'sync' | 'async'>
|
||||
extends Options<sync> {
|
||||
```
|
||||
|
||||
#### `syntax`
|
||||
|
||||
The compiler must parse `source` using this syntax. Defaults to `'scss'`.
|
||||
|
||||
```ts
|
||||
syntax?: Syntax;
|
||||
```
|
||||
|
||||
#### `url`
|
||||
|
||||
The URL of the stylesheet being parsed.
|
||||
|
||||
> When `importer` isn't passed, this is purely advisory and only used for error
|
||||
> reporting.
|
||||
|
||||
```ts
|
||||
url?: URL;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // StringOptionsWithoutImporter
|
||||
```
|
||||
|
||||
### `StringOptionsWithImporter`
|
||||
|
||||
> This interface is used for calls to [`compileString()`] and
|
||||
> [`compileStringAsync()`] that _do_ pass the `importer` parameter, and so _do_
|
||||
> support relative imports.
|
||||
|
||||
```ts
|
||||
export interface StringOptionsWithImporter<sync extends 'sync' | 'async'>
|
||||
extends StringOptionsWithoutImporter<sync> {
|
||||
```
|
||||
|
||||
#### `importer`
|
||||
|
||||
The [importer] to use to resolve relative imports in the entrypoint.
|
||||
|
||||
[importer]: importer.d.ts.md
|
||||
|
||||
```ts
|
||||
importer: Importer<sync> | FileImporter<sync>;
|
||||
```
|
||||
|
||||
#### `url`
|
||||
|
||||
The canonical URL of the entrypoint.
|
||||
|
||||
> This _must_ be passed when `importer` is passed, since otherwise there's
|
||||
> nothing to resolve relative URLs relative to.
|
||||
|
||||
```ts
|
||||
url: URL;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // StringOptionsWithImporter
|
||||
```
|
||||
|
||||
### `StringOptions`
|
||||
|
||||
```ts
|
||||
export type StringOptions<sync extends 'sync' | 'async'> =
|
||||
| StringOptionsWithImporter<sync>
|
||||
| StringOptionsWithoutImporter<sync>;
|
||||
```
|
28
spec/js-api/value/argument_list.d.ts
vendored
28
spec/js-api/value/argument_list.d.ts
vendored
@ -1,28 +0,0 @@
|
||||
import {List, OrderedMap} from 'immutable';
|
||||
|
||||
import {Value} from './index';
|
||||
import {SassList, ListSeparator} from './list';
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass argument list.
|
||||
*
|
||||
* `internal` refers to a Sass argument list.
|
||||
*/
|
||||
export class SassArgumentList extends SassList {
|
||||
/**
|
||||
* Creates a Sass argument list:
|
||||
*
|
||||
* - Set `internal` to a Sass argument list with contents set to `contents`,
|
||||
* keywords set to `keywords`, and list separator set to `separator`.
|
||||
* - Return `this`.
|
||||
*/
|
||||
constructor(
|
||||
contents: Value[] | List<Value>,
|
||||
keywords: Record<string, Value> | OrderedMap<string, Value>,
|
||||
/** @default ',' */
|
||||
separator?: ListSeparator
|
||||
);
|
||||
|
||||
/** `internal`'s keywords. */
|
||||
get keywords(): OrderedMap<string, Value>;
|
||||
}
|
62
spec/js-api/value/argument_list.d.ts.md
Normal file
62
spec/js-api/value/argument_list.d.ts.md
Normal file
@ -0,0 +1,62 @@
|
||||
# Argument List API
|
||||
|
||||
```ts
|
||||
import {List, OrderedMap} from 'immutable';
|
||||
|
||||
import {Value} from './index';
|
||||
import {SassList, ListSeparator} from './list';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`SassArgumentList`](#sassargumentlist)
|
||||
* [`internal`](#internal)
|
||||
* [Constructor](#constructor)
|
||||
* [`keywords`](#keywords)
|
||||
|
||||
## Types
|
||||
|
||||
### `SassArgumentList`
|
||||
|
||||
The JS API representation of a Sass argument list.
|
||||
|
||||
```ts
|
||||
export class SassArgumentList extends SassList {
|
||||
```
|
||||
|
||||
#### `internal`
|
||||
|
||||
The [private `internal` field] refers to a Sass argument list.
|
||||
|
||||
[private `internal` field]: index.d.ts.md#internal
|
||||
|
||||
#### Constructor
|
||||
|
||||
Creates a Sass argument list:
|
||||
|
||||
* Set `internal` to a Sass argument list with contents set to `contents`,
|
||||
keywords set to `keywords`, and list separator set to `separator`.
|
||||
|
||||
* Return `this`.
|
||||
|
||||
```ts
|
||||
constructor(
|
||||
contents: Value[] | List<Value>,
|
||||
keywords: Record<string, Value> | OrderedMap<string, Value>,
|
||||
/** @default ',' */
|
||||
separator?: ListSeparator
|
||||
);
|
||||
```
|
||||
|
||||
#### `keywords`
|
||||
|
||||
`internal`'s keywords.
|
||||
|
||||
```ts
|
||||
get keywords(): OrderedMap<string, Value>;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SassArgumentList
|
||||
```
|
14
spec/js-api/value/boolean.d.ts
vendored
14
spec/js-api/value/boolean.d.ts
vendored
@ -1,14 +0,0 @@
|
||||
import {Value} from './index';
|
||||
|
||||
/** The JS API representation of the SassScript true singleton. */
|
||||
export const sassTrue: SassBoolean;
|
||||
|
||||
/** The JS API representation of the SassScript false singleton. */
|
||||
export const sassFalse: SassBoolean;
|
||||
|
||||
/** The JS API representation of a Sass boolean. */
|
||||
export class SassBoolean extends Value {
|
||||
private constructor();
|
||||
|
||||
get value(): boolean;
|
||||
}
|
55
spec/js-api/value/boolean.d.ts.md
Normal file
55
spec/js-api/value/boolean.d.ts.md
Normal file
@ -0,0 +1,55 @@
|
||||
# Boolean API
|
||||
|
||||
```ts
|
||||
import {Value} from './index';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Fields](#fields)
|
||||
* [`sassTrue`](#sasstrue)
|
||||
* [`sassFalse`](#sassfalse)
|
||||
* [Types](#types)
|
||||
* [`SassBoolean`](#sassboolean)
|
||||
* [`value`](#value)
|
||||
|
||||
## Fields
|
||||
|
||||
### `sassTrue`
|
||||
|
||||
A `Value` whose [`internal`] is the SassScript true value.
|
||||
|
||||
[`internal`]: index.d.ts.md#internal
|
||||
|
||||
```ts
|
||||
export const sassTrue: SassBoolean;
|
||||
```
|
||||
|
||||
### `sassFalse`
|
||||
|
||||
A `Value` whose [`internal`] is the SassScript false value.
|
||||
|
||||
```ts
|
||||
export const sassFalse: SassBoolean;
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
### `SassBoolean`
|
||||
|
||||
The JS API representation of a Sass boolean.
|
||||
|
||||
```ts
|
||||
export class SassBoolean extends Value {
|
||||
private constructor();
|
||||
```
|
||||
|
||||
#### `value`
|
||||
|
||||
```ts
|
||||
get value(): boolean;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SassBoolean
|
||||
```
|
205
spec/js-api/value/color.d.ts
vendored
205
spec/js-api/value/color.d.ts
vendored
@ -1,205 +0,0 @@
|
||||
import {Value} from './index';
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass color.
|
||||
*
|
||||
* `internal` refers to a Sass color.
|
||||
*/
|
||||
export class SassColor extends Value {
|
||||
/**
|
||||
* - If `options.red` is set:
|
||||
*
|
||||
* - Let `red` be a Sass number with a value of `options.red` `fuzzyRound`ed
|
||||
* to the nearest integer.
|
||||
*
|
||||
* - Let `green` be a Sass number with a value of `options.green`
|
||||
* `fuzzyRound`ed to the nearest integer.
|
||||
*
|
||||
* - Let `blue` be a Sass number with a value of `options.blue`
|
||||
* `fuzzyRound`ed to the nearest integer.
|
||||
*
|
||||
* - If `options.alpha` is set, let `alpha` be a Sass number with a value of
|
||||
* `options.alpha`. Otherwise, let `alpha` be `null`.
|
||||
*
|
||||
* - Set `internal` to the result of running [`rgb()`] with `$red`, `$green`,
|
||||
* `$blue`, and `$alpha`.
|
||||
*
|
||||
* [`rgb()`]: ../../functions.md#rgb-and-rgba
|
||||
*
|
||||
* - Otherwise, if `options.saturation` is set:
|
||||
*
|
||||
* - Let `hue` be a Sass number with a value of `options.hue`.
|
||||
*
|
||||
* - Let `saturation` be a Sass number with a value of `options.saturation`.
|
||||
*
|
||||
* - Let `lightness` be a Sass number with a value of `options.lightness`.
|
||||
*
|
||||
* - If `options.alpha` is set, let `alpha` be a Sass number with a value of
|
||||
* `options.alpha`. Otherwise, let `alpha` be `null`.
|
||||
*
|
||||
* - Set `internal` to the result of running [`hsl()`] with `$hue`, `$saturation`,
|
||||
* `$lightness`, and `$alpha`.
|
||||
*
|
||||
* [`hsl()`]: ../../functions.md#hsl-and-hsla
|
||||
*
|
||||
* - Otherwise, if `options.whiteness` is set:
|
||||
*
|
||||
* - Let `hue` be a Sass number with a value of `options.hue`.
|
||||
*
|
||||
* - Let `whiteness` be a Sass number with a value of `options.whiteness`.
|
||||
*
|
||||
* - Let `blackness` be a Sass number with a value of `options.blackness`.
|
||||
*
|
||||
* - If `options.alpha` is set, let `alpha` be a Sass number with a value of
|
||||
* `options.alpha`. Otherwise, let `alpha` be `null`.
|
||||
*
|
||||
* - Set `internal` to the result of running [`hwb()`] with `$hue`, `$whiteness`,
|
||||
* `$blackness`, and `$alpha`.
|
||||
*
|
||||
* [`hwb()`]: ../../built-in-modules/color.md#hwb
|
||||
*
|
||||
* - Return `this`.
|
||||
*/
|
||||
constructor(options: {
|
||||
red: number;
|
||||
green: number;
|
||||
blue: number;
|
||||
alpha?: number;
|
||||
});
|
||||
|
||||
constructor(options: {
|
||||
hue: number;
|
||||
saturation: number;
|
||||
lightness: number;
|
||||
alpha?: number;
|
||||
});
|
||||
|
||||
constructor(options: {
|
||||
hue: number;
|
||||
whiteness: number;
|
||||
blackness: number;
|
||||
alpha?: number;
|
||||
});
|
||||
|
||||
/** `internal`'s red channel. */
|
||||
get red(): number;
|
||||
|
||||
/** `internal`'s green channel. */
|
||||
get green(): number;
|
||||
|
||||
/** `internal`'s blue channel. */
|
||||
get blue(): number;
|
||||
|
||||
/**
|
||||
* Returns the value of the result of [`hue(internal)`][hue].
|
||||
*
|
||||
* [hue]: ../spec/built-in-modules/color.md#hue
|
||||
*/
|
||||
get hue(): number;
|
||||
|
||||
/**
|
||||
* Returns the value of the result of [`saturation(internal)`][saturation].
|
||||
*
|
||||
* [saturation]: ../spec/built-in-modules/color.md#saturation
|
||||
*/
|
||||
get saturation(): number;
|
||||
|
||||
/**
|
||||
* Returns the value of the result of [`lightness(internal)`][lightness].
|
||||
*
|
||||
* [lightness]: ../spec/built-in-modules/color.md#lightness
|
||||
*/
|
||||
get lightness(): number;
|
||||
|
||||
/**
|
||||
* Returns the value of the result of [`whiteness(internal)`][whiteness].
|
||||
*
|
||||
* [whiteness]: ../spec/built-in-modules/color.md#whiteness
|
||||
*/
|
||||
get whiteness(): number;
|
||||
|
||||
/**
|
||||
* Returns the value of the result of [`blackness(internal)`][blackness].
|
||||
*
|
||||
* [blackness]: ../spec/built-in-modules/color.md#blackness
|
||||
*/
|
||||
get blackness(): number;
|
||||
|
||||
/**
|
||||
* Returns the value of the result of [`alpha(internal)`][alpha].
|
||||
*
|
||||
* [alpha]: ../spec/built-in-modules/color.md#alpha
|
||||
*/
|
||||
get alpha(): number;
|
||||
|
||||
/**
|
||||
* Returns a new copy of `this` with one or more changes made to the RGB
|
||||
* channels:
|
||||
*
|
||||
* - If `options.whiteness` or `options.blackness` is set:
|
||||
*
|
||||
* - Let `hue` be `options.hue` if it was passed, or `this.hue` otherwise.
|
||||
*
|
||||
* - Let `whiteness` be `options.whiteness` if it was passed, or
|
||||
* `this.whiteness` otherwise.
|
||||
*
|
||||
* - Let `blackness` be `options.blackness` if it was passed, or
|
||||
* `this.blackness` otherwise.
|
||||
*
|
||||
* - Let `alpha` be `options.alpha` if it was passed, or `this.alpha`
|
||||
* otherwise.
|
||||
*
|
||||
* - Return the result of `SassColor({hue, whiteness, blackness, alpha})`.
|
||||
*
|
||||
* - Otherwise, if `options.hue`, `options.saturation`, or `options.lightness`
|
||||
* is set:
|
||||
*
|
||||
* - Let `hue` be `options.hue` if it was passed, or `this.hue` otherwise.
|
||||
*
|
||||
* - Let `saturation` be `options.saturation` if it was passed, or
|
||||
* `this.saturation` otherwise.
|
||||
*
|
||||
* - Let `lightness` be `options.lightness` if it was passed, or
|
||||
* `this.lightness` otherwise.
|
||||
*
|
||||
* - Let `alpha` be `options.alpha` if it was passed, or `this.alpha`
|
||||
* otherwise.
|
||||
*
|
||||
* - Return the result of `SassColor({hue, saturation, lightness, alpha})`.
|
||||
*
|
||||
* - Otherwise:
|
||||
*
|
||||
* - Let `red` be `options.red` if it was passed, or `this.red` otherwise.
|
||||
*
|
||||
* - Let `green` be `options.green` if it was passed, or `this.green`
|
||||
* otherwise.
|
||||
*
|
||||
* - Let `blue` be `options.blue` if it was passed, or `this.blue`
|
||||
* otherwise.
|
||||
*
|
||||
* - Let `alpha` be `options.alpha` if it was passed, or `this.alpha`
|
||||
* otherwise.
|
||||
*
|
||||
* - Return the result of `SassColor({red, green, blue, alpha})`.
|
||||
*/
|
||||
change(options: {
|
||||
red?: number;
|
||||
green?: number;
|
||||
blue?: number;
|
||||
alpha?: number;
|
||||
}): SassColor;
|
||||
|
||||
change(options: {
|
||||
hue?: number;
|
||||
saturation?: number;
|
||||
lightness?: number;
|
||||
alpha?: number;
|
||||
}): SassColor;
|
||||
|
||||
change(options: {
|
||||
hue?: number;
|
||||
whiteness?: number;
|
||||
blackness?: number;
|
||||
alpha?: number;
|
||||
}): SassColor;
|
||||
}
|
264
spec/js-api/value/color.d.ts.md
Normal file
264
spec/js-api/value/color.d.ts.md
Normal file
@ -0,0 +1,264 @@
|
||||
# Color API
|
||||
|
||||
```ts
|
||||
import {Value} from './index';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`SassColor`](#sasscolor)
|
||||
* [`internal`](#internal)
|
||||
* [Constructor](#constructor)
|
||||
* [`red`](#red)
|
||||
* [`green`](#green)
|
||||
* [`blue`](#blue)
|
||||
* [`hue`](#hue)
|
||||
* [`saturation`](#saturation)
|
||||
* [`lightness`](#lightness)
|
||||
* [`whiteness`](#whiteness)
|
||||
* [`blackness`](#blackness)
|
||||
* [`alpha`](#alpha)
|
||||
* [`change`](#change)
|
||||
|
||||
## Types
|
||||
|
||||
### `SassColor`
|
||||
|
||||
The JS API representation of a Sass color.
|
||||
|
||||
```ts
|
||||
export class SassColor extends Value {
|
||||
```
|
||||
|
||||
#### `internal`
|
||||
|
||||
The [private `internal` field] refers to a Sass color.
|
||||
|
||||
[private `internal` field]: index.d.ts.md#internal
|
||||
|
||||
#### Constructor
|
||||
|
||||
* If `options.red` is set:
|
||||
|
||||
* Let `red` be a Sass number with a value of `options.red` `fuzzyRound`ed
|
||||
to the nearest integer.
|
||||
|
||||
* Let `green` be a Sass number with a value of `options.green`
|
||||
`fuzzyRound`ed to the nearest integer.
|
||||
|
||||
* Let `blue` be a Sass number with a value of `options.blue`
|
||||
`fuzzyRound`ed to the nearest integer.
|
||||
|
||||
* If `options.alpha` is set, let `alpha` be a Sass number with a value of
|
||||
`options.alpha`. Otherwise, let `alpha` be `null`.
|
||||
|
||||
* Set [`internal`] to the result of [`rgb(red, green, blue, alpha)`].
|
||||
|
||||
[`internal`]: #internal
|
||||
[`rgb(red, green, blue, alpha)`]: ../../functions.md#rgb-and-rgba
|
||||
|
||||
* Otherwise, if `options.saturation` is set:
|
||||
|
||||
* Let `hue` be a Sass number with a value of `options.hue`.
|
||||
|
||||
* Let `saturation` be a Sass number with a value of `options.saturation`.
|
||||
|
||||
* Let `lightness` be a Sass number with a value of `options.lightness`.
|
||||
|
||||
* If `options.alpha` is set, let `alpha` be a Sass number with a value of
|
||||
`options.alpha`. Otherwise, let `alpha` be `null`.
|
||||
|
||||
* Set [`internal`] to the result of [`hsl(hue, saturation, lightness,
|
||||
alpha)`].
|
||||
|
||||
[`hsl(hue, saturation, lightness, alpha)`]: ../../functions.md#hsl-and-hsla
|
||||
|
||||
* Otherwise, if `options.whiteness` is set:
|
||||
|
||||
* Let `hue` be a Sass number with a value of `options.hue`.
|
||||
|
||||
* Let `whiteness` be a Sass number with a value of `options.whiteness`.
|
||||
|
||||
* Let `blackness` be a Sass number with a value of `options.blackness`.
|
||||
|
||||
* If `options.alpha` is set, let `alpha` be a Sass number with a value of
|
||||
`options.alpha`. Otherwise, let `alpha` be `null`.
|
||||
|
||||
* Set [`internal`] to the result of [`hwb(hue, whiteness, blackness, alpha)`].
|
||||
|
||||
[`hwb(hue, whiteness, blackness, alpha)`]: ../../built-in-modules/color.md#hwb
|
||||
|
||||
* Return `this`.
|
||||
|
||||
```ts
|
||||
constructor(options: {
|
||||
red: number;
|
||||
green: number;
|
||||
blue: number;
|
||||
alpha?: number;
|
||||
});
|
||||
|
||||
constructor(options: {
|
||||
hue: number;
|
||||
saturation: number;
|
||||
lightness: number;
|
||||
alpha?: number;
|
||||
});
|
||||
|
||||
constructor(options: {
|
||||
hue: number;
|
||||
whiteness: number;
|
||||
blackness: number;
|
||||
alpha?: number;
|
||||
});
|
||||
```
|
||||
|
||||
#### `red`
|
||||
|
||||
Returns [`internal`]'s red channel.
|
||||
|
||||
```ts
|
||||
get red(): number;
|
||||
```
|
||||
|
||||
#### `green`
|
||||
|
||||
Returns [`internal`]'s green channel.
|
||||
|
||||
```ts
|
||||
get green(): number;
|
||||
```
|
||||
|
||||
#### `blue`
|
||||
|
||||
Returns [`internal`]'s blue channel.
|
||||
|
||||
```ts
|
||||
get blue(): number;
|
||||
```
|
||||
|
||||
#### `hue`
|
||||
|
||||
Returns the value of the result of [`hue(internal)`].
|
||||
|
||||
[`hue(internal)`]: ../../built-in-modules/color.md#hue
|
||||
|
||||
```ts
|
||||
get hue(): number;
|
||||
```
|
||||
|
||||
#### `saturation`
|
||||
|
||||
Returns the value of the result of [`saturation(internal)`].
|
||||
|
||||
[`saturation(internal)`]: ../../built-in-modules/color.md#saturation
|
||||
|
||||
```ts
|
||||
get saturation(): number;
|
||||
```
|
||||
|
||||
#### `lightness`
|
||||
|
||||
Returns the value of the result of [`lightness(internal)`].
|
||||
|
||||
[`lightness(internal)`]: ../../built-in-modules/color.md#lightness
|
||||
|
||||
```ts
|
||||
get lightness(): number;
|
||||
```
|
||||
|
||||
#### `whiteness`
|
||||
|
||||
Returns the value of the result of [`whiteness(internal)`].
|
||||
|
||||
[`whiteness(internal)`]: ../../built-in-modules/color.md#whiteness
|
||||
|
||||
```ts
|
||||
get whiteness(): number;
|
||||
```
|
||||
|
||||
#### `blackness`
|
||||
|
||||
Returns the value of the result of [`blackness(internal)`].
|
||||
|
||||
[`blackness(internal)`]: ../../built-in-modules/color.md#blackness
|
||||
|
||||
```ts
|
||||
get blackness(): number;
|
||||
```
|
||||
|
||||
#### `alpha`
|
||||
|
||||
Returns the value of the result of [`alpha(internal)`].
|
||||
|
||||
[`alpha(internal)`]: ../../built-in-modules/color.md#alpha
|
||||
|
||||
```ts
|
||||
get alpha(): number;
|
||||
```
|
||||
|
||||
#### `change`
|
||||
|
||||
Returns a new color created by changing some of this color's channels:
|
||||
|
||||
* If `options.whiteness` or `options.blackness` is set, return the result of:
|
||||
|
||||
```js
|
||||
SassColor({
|
||||
hue: options.hue ?? this.hue,
|
||||
whiteness: options.whiteness ?? this.whiteness,
|
||||
blackness: options.blackness ?? this.blackness,
|
||||
alpha: options.alpha ?? this.alpha
|
||||
})
|
||||
```
|
||||
|
||||
* Otherwise, if `options.hue`, `options.saturation`, or `options.lightness`
|
||||
is set, return the result of:
|
||||
|
||||
```js
|
||||
SassColor({
|
||||
hue: options.hue ?? this.hue,
|
||||
saturation: options.saturation ?? this.saturation,
|
||||
lightness: options.lightness ?? this.lightness,
|
||||
alpha: options.alpha ?? this.alpha
|
||||
})
|
||||
```
|
||||
|
||||
* Otherwise, return the result of:
|
||||
|
||||
```js
|
||||
SassColor({
|
||||
red: options.red ?? this.red,
|
||||
green: options.green ?? this.gren,
|
||||
blue: options.blue ?? this.blue,
|
||||
alpha: options.alpha ?? this.alpha
|
||||
})
|
||||
```
|
||||
|
||||
```ts
|
||||
change(options: {
|
||||
red?: number;
|
||||
green?: number;
|
||||
blue?: number;
|
||||
alpha?: number;
|
||||
}): SassColor;
|
||||
|
||||
change(options: {
|
||||
hue?: number;
|
||||
saturation?: number;
|
||||
lightness?: number;
|
||||
alpha?: number;
|
||||
}): SassColor;
|
||||
|
||||
change(options: {
|
||||
hue?: number;
|
||||
whiteness?: number;
|
||||
blackness?: number;
|
||||
alpha?: number;
|
||||
}): SassColor;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SassColor
|
||||
```
|
36
spec/js-api/value/function.d.ts
vendored
36
spec/js-api/value/function.d.ts
vendored
@ -1,36 +0,0 @@
|
||||
import {Value} from './index';
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass function.
|
||||
*
|
||||
* `internal` refers to a Sass function.
|
||||
*/
|
||||
export class SassFunction extends Value {
|
||||
/**
|
||||
* Creates a Sass function:
|
||||
*
|
||||
* - If `signature` isn't a valid Sass function signature that could appear
|
||||
* after the `@function` directive in a Sass stylesheet (such as
|
||||
* `mix($color1, $color2, $weight: 50%)`), the implementation *may* throw an
|
||||
* error.
|
||||
*
|
||||
* > This is optional to allow for implementations of the value API that
|
||||
* > don't have easy access to a Sass parser, such as the embedded host.
|
||||
* > These implementations must instead throw an error when the invalid
|
||||
* > function is returned from the custom function.
|
||||
*
|
||||
* - Set `internal` to a Sass function with signature set to `signature` that,
|
||||
* upon execution, runs `callback` and returns the result.
|
||||
*
|
||||
* - Return `this`.
|
||||
*/
|
||||
constructor(
|
||||
/**
|
||||
* Must be a valid Sass function signature that could appear after the
|
||||
* `@function` directive in a Sass stylesheet, such as
|
||||
* `mix($color1, $color2, $weight: 50%)`.
|
||||
*/
|
||||
signature: string,
|
||||
callback: (args: Value[]) => Value
|
||||
);
|
||||
}
|
54
spec/js-api/value/function.d.ts.md
Normal file
54
spec/js-api/value/function.d.ts.md
Normal file
@ -0,0 +1,54 @@
|
||||
# Function Value API
|
||||
|
||||
```ts
|
||||
import {Value} from './index';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`SassFunction`](#sassfunction)
|
||||
* [`internal`](#internal)
|
||||
* [Constructor](#constructor)
|
||||
|
||||
## Types
|
||||
|
||||
### `SassFunction`
|
||||
|
||||
The JS API representation of a Sass function.
|
||||
|
||||
```ts
|
||||
export class SassFunction extends Value {
|
||||
```
|
||||
|
||||
#### `internal`
|
||||
|
||||
The [private `internal` field] refers to a Sass function.
|
||||
|
||||
[private `internal` field]: index.d.ts.md#internal
|
||||
|
||||
#### Constructor
|
||||
|
||||
Creates a Sass function:
|
||||
|
||||
* If `signature` isn't a valid Sass function signature that could appear after
|
||||
the `@function` directive in a Sass stylesheet (such as `mix($color1, $color2,
|
||||
$weight: 50%)`), the implementation *may* throw an error.
|
||||
|
||||
> This is optional to allow for implementations of the value API that don't
|
||||
> have easy access to a Sass parser, such as the embedded host. These
|
||||
> implementations must instead throw an error when the invalid function is
|
||||
> returned from the custom function.
|
||||
|
||||
* Set `internal` to a Sass function with signature set to `signature` that, upon
|
||||
execution, runs `callback` and returns the result.
|
||||
|
||||
* Return `this`.
|
||||
|
||||
```ts
|
||||
constructor(signature: string, callback: (args: Value[]) => Value);
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SassFunction
|
||||
```
|
187
spec/js-api/value/index.d.ts
vendored
187
spec/js-api/value/index.d.ts
vendored
@ -1,187 +0,0 @@
|
||||
import {List, ValueObject} from 'immutable';
|
||||
|
||||
import {SassBoolean} from './boolean';
|
||||
import {SassColor} from './color';
|
||||
import {SassFunction} from './function';
|
||||
import {ListSeparator} from './list';
|
||||
import {SassMap} from './map';
|
||||
import {SassNumber} from './number';
|
||||
import {SassString} from './string';
|
||||
|
||||
export {SassArgumentList} from './argument_list';
|
||||
export {SassBoolean, sassTrue, sassFalse} from './boolean';
|
||||
export {SassColor} from './color';
|
||||
export {SassFunction} from './function';
|
||||
export {SassList, ListSeparator} from './list';
|
||||
export {SassMap} from './map';
|
||||
export {SassNumber} from './number';
|
||||
export {SassString} from './string';
|
||||
|
||||
/** The JS API representation of the SassScript null singleton. */
|
||||
export const sassNull: Value;
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass value.
|
||||
*
|
||||
* Sass values are immutable. Therefore, all subclasses of Value must have an
|
||||
* API that obeys immutability. Their APIs must not expose ways to modify
|
||||
* Sass values, including lists and maps. An API call that returns a new copy
|
||||
* of a Sass value must ensure that the copy preserves the metadata of the
|
||||
* original value (e.g. units).
|
||||
*
|
||||
* > To make the spec terser and easier to author, each subclass that extends
|
||||
* > `Value` has a virtual, private property named `internal` that refers to the
|
||||
* > Sass value it represents.
|
||||
*/
|
||||
export abstract class Value implements ValueObject {
|
||||
protected constructor();
|
||||
|
||||
/**
|
||||
* Returns `this` as an array:
|
||||
*
|
||||
* - If `internal` is a Sass list, return an array of its contents.
|
||||
* - If `internal` is a Sass map, return an array of its keys and values as
|
||||
* two-element `SassList`s.
|
||||
* - Otherwise, return an array containing `this`.
|
||||
*/
|
||||
get asList(): List<Value>;
|
||||
|
||||
/** Whether `internal` is a bracketed Sass list. */
|
||||
get hasBrackets(): boolean;
|
||||
|
||||
/** Whether `this` is truthy. */
|
||||
get isTruthy(): boolean;
|
||||
|
||||
/** Returns JS null if `internal` is Sass null. Otherwise, returns `this`. */
|
||||
get realNull(): null | Value;
|
||||
|
||||
/**
|
||||
* Returns `internal`'s list separator:
|
||||
*
|
||||
* - If `internal` is a Sass list, return its separator.
|
||||
* - Otherwise, return `null`.
|
||||
*/
|
||||
get separator(): ListSeparator;
|
||||
|
||||
/**
|
||||
* Converts the Sass index `sassIndex` to a JS index into the array returned
|
||||
* by `asList`:
|
||||
*
|
||||
* - If `sassIndex` is not a unitless Sass number, throw an error.
|
||||
*
|
||||
* - Let `value` be the value of `sassIndex`. Let `index` be the result of
|
||||
* `fuzzyAsInt(value)`. If `index === null`, throw an error.
|
||||
*
|
||||
* - If `index === 0`, or the absolute value of `index` is greater than
|
||||
* `asList.length`, throw an error.
|
||||
*
|
||||
* - If `index > 0`, return `index - 1`.
|
||||
* - Otherwise, if `index < 0`, return `asList.length + index`.
|
||||
*
|
||||
* > Sass indices start counting at 1, and may be negative in order to index
|
||||
* > from the end of the list.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
sassIndexToListIndex(sassIndex: Value, name?: string): number;
|
||||
|
||||
/**
|
||||
* - Return `this.asList.get(index)`.
|
||||
*
|
||||
* > Note that the `immutable` package uses zero-based indexing, with negative
|
||||
* > numbers indexing backwards from the end of the list. Non-integer indices
|
||||
* > are rounded down.
|
||||
*/
|
||||
get(index: number): Value | undefined;
|
||||
|
||||
/**
|
||||
* Asserts that `this` is a `SassBoolean`:
|
||||
*
|
||||
* - If `internal` is a Sass boolean, return `this`.
|
||||
* - Otherwise, throw an error.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertBoolean(name?: string): SassBoolean;
|
||||
|
||||
/**
|
||||
* Asserts that `this` is a `SassColor`:
|
||||
*
|
||||
* - If `internal` is a Sass color, return `this`.
|
||||
* - Otherwise, throw an error.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertColor(name?: string): SassColor;
|
||||
|
||||
/**
|
||||
* Asserts that `this` is a `SassFunction`:
|
||||
*
|
||||
* - If `internal` is a Sass function, return `this`.
|
||||
* - Otherwise, throw an error.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertFunction(name?: string): SassFunction;
|
||||
|
||||
/**
|
||||
* Asserts that `this` is a `SassMap`:
|
||||
*
|
||||
* - If `internal` is a Sass map, return `this`.
|
||||
* - If `internal` is an empty Sass list, return a `SassMap` with `internal`
|
||||
* set to an empty map.
|
||||
* - Otherwise, throw an error.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertMap(name?: string): SassMap;
|
||||
|
||||
/**
|
||||
* Asserts that `this` is a `SassNumber`:
|
||||
*
|
||||
* - If `internal` is a Sass number, return `this`.
|
||||
* - Otherwise, throw an error.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertNumber(name?: string): SassNumber;
|
||||
|
||||
/**
|
||||
* Asserts that `this` is a `SassString`:
|
||||
*
|
||||
* - If `internal` is a Sass string, return `this`.
|
||||
* - Otherwise, throw an error.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertString(name?: string): SassString;
|
||||
|
||||
/**
|
||||
* Returns `this` interpreted as a map.
|
||||
*
|
||||
* - If `this` is a `SassMap`, return `this`.
|
||||
*
|
||||
* - Otherwise, if `internal` is an empty Sass list, return a `SassMap` with
|
||||
* its `internal` set to an empty `OrderedMap`.
|
||||
*
|
||||
* - Otherwise, return `null`.
|
||||
*/
|
||||
tryMap(): SassMap | null;
|
||||
|
||||
/** Whether `this == other` in SassScript. */
|
||||
equals(other: Value): boolean;
|
||||
|
||||
/**
|
||||
* Must be the same for `Value`s that are equal to each other according to the
|
||||
* `==` SassScript operator.
|
||||
*/
|
||||
hashCode(): number;
|
||||
|
||||
/**
|
||||
* Returns a serialized representation of `this`.
|
||||
*
|
||||
* > The specific format can vary from implementation to implementation and is
|
||||
* > not guaranteed to be valid Sass source code.
|
||||
*/
|
||||
toString(): string;
|
||||
}
|
287
spec/js-api/value/index.d.ts.md
Normal file
287
spec/js-api/value/index.d.ts.md
Normal file
@ -0,0 +1,287 @@
|
||||
# Value API
|
||||
|
||||
```ts
|
||||
import {List, ValueObject} from 'immutable';
|
||||
|
||||
import {SassBoolean} from './boolean';
|
||||
import {SassColor} from './color';
|
||||
import {SassFunction} from './function';
|
||||
import {ListSeparator} from './list';
|
||||
import {SassMap} from './map';
|
||||
import {SassNumber} from './number';
|
||||
import {SassString} from './string';
|
||||
|
||||
export {SassArgumentList} from './argument_list';
|
||||
export {SassBoolean, sassTrue, sassFalse} from './boolean';
|
||||
export {SassColor} from './color';
|
||||
export {SassFunction} from './function';
|
||||
export {SassList, ListSeparator} from './list';
|
||||
export {SassMap} from './map';
|
||||
export {SassNumber} from './number';
|
||||
export {SassString} from './string';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Fields](#fields)
|
||||
* [`sassNull`](#sassnull)
|
||||
* [Types](#types)
|
||||
* [`Value`](#value)
|
||||
* [`internal`](#internal)
|
||||
* [`asList`](#aslist)
|
||||
* [`hasBrackets`](#hasbrackets)
|
||||
* [`isTruthy`](#istruthy)
|
||||
* [`realNull`](#realnull)
|
||||
* [`separator`](#separator)
|
||||
* [`sassIndexToListIndex`](#sassindextolistindex)
|
||||
* [`get`](#get)
|
||||
* [`assertBoolean`](#assertboolean)
|
||||
* [`assertColor`](#assertcolor)
|
||||
* [`assertFunction`](#assertfunction)
|
||||
* [`assertMap`](#assertmap)
|
||||
* [`assertNumber`](#assertnumber)
|
||||
* [`assertString`](#assertstring)
|
||||
* [`tryMap`](#trymap)
|
||||
* [`equals`](#equals)
|
||||
* [`hashCode`](#hashcode)
|
||||
* [`toString`](#tostring)
|
||||
|
||||
## Fields
|
||||
|
||||
### `sassNull`
|
||||
|
||||
A `Value` whose [`internal`] is the SassScript null value.
|
||||
|
||||
[`internal`]: #internal
|
||||
|
||||
```ts
|
||||
export const sassNull: Value;
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
### `Value`
|
||||
|
||||
The JS API representation of a Sass value.
|
||||
|
||||
Sass values are immutable. Therefore, all subclasses of Value must have an API
|
||||
that obeys immutability. Their APIs must not expose ways to modify Sass values,
|
||||
including lists and maps. An API call that returns a new copy of a Sass value
|
||||
must ensure that the copy preserves the metadata of the original value (e.g.
|
||||
units).
|
||||
|
||||
```ts
|
||||
export abstract class Value implements ValueObject {
|
||||
protected constructor();
|
||||
```
|
||||
|
||||
#### `internal`
|
||||
|
||||
To make the spec terser and easier to author, each `Value` instance has a
|
||||
private property named `internal` that refers to the Sass value it represents.
|
||||
This property is only used for spec purposes and is not visible in any sense to
|
||||
JavaScript.
|
||||
|
||||
#### `asList`
|
||||
|
||||
Returns `this` as an array:
|
||||
|
||||
* If [`internal`] is a Sass list, return an array of its contents.
|
||||
* If [`internal`] is a Sass map, return an array of its keys and values as
|
||||
two-element `SassList`s.
|
||||
* Otherwise, return a list containing `this`.
|
||||
|
||||
```ts
|
||||
get asList(): List<Value>;
|
||||
```
|
||||
|
||||
#### `hasBrackets`
|
||||
|
||||
Whether [`internal`] is a bracketed Sass list.
|
||||
|
||||
```ts
|
||||
get hasBrackets(): boolean;
|
||||
```
|
||||
|
||||
#### `isTruthy`
|
||||
|
||||
Whether `this` is truthy.
|
||||
|
||||
```ts
|
||||
get isTruthy(): boolean;
|
||||
```
|
||||
|
||||
#### `realNull`
|
||||
|
||||
Returns JS null if [`internal`] is Sass null. Otherwise, returns `this`.
|
||||
|
||||
```ts
|
||||
get realNull(): null | Value;
|
||||
```
|
||||
|
||||
#### `separator`
|
||||
|
||||
Return [`internal`]'s separator if it's a Sass list, and `null` otherwise.
|
||||
|
||||
```ts
|
||||
get separator(): ListSeparator;
|
||||
```
|
||||
|
||||
#### `sassIndexToListIndex`
|
||||
|
||||
Converts the Sass index `sassIndex` to a JS index into the array returned by
|
||||
`asList`:
|
||||
|
||||
- If `sassIndex` is not a unitless Sass number, throw an error.
|
||||
|
||||
- Let `value` be the value of `sassIndex`. Let `index` be the result of
|
||||
`fuzzyAsInt(value)`. If `index === null`, throw an error.
|
||||
|
||||
- If `index === 0`, or the absolute value of `index` is greater than
|
||||
`asList.length`, throw an error.
|
||||
|
||||
- If `index > 0`, return `index - 1`.
|
||||
- Otherwise, if `index < 0`, return `asList.length + index`.
|
||||
|
||||
> Sass indices start counting at 1, and may be negative in order to index from
|
||||
> the end of the list.
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
sassIndexToListIndex(sassIndex: Value, name?: string): number;
|
||||
```
|
||||
|
||||
#### `get`
|
||||
|
||||
Returns `this.asList.get(index)`.
|
||||
|
||||
> Note that the `immutable` package uses zero-based indexing, with negative
|
||||
> numbers indexing backwards from the end of the list. Non-integer indices are
|
||||
> rounded down.
|
||||
|
||||
```ts
|
||||
get(index: number): Value | undefined;
|
||||
```
|
||||
|
||||
#### `assertBoolean`
|
||||
|
||||
Returns `this` if it's a [`SassBoolean`] and throws an error otherwise.
|
||||
|
||||
[`SassBoolean`]: boolean.d.ts.md
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertBoolean(name?: string): SassBoolean;
|
||||
```
|
||||
|
||||
#### `assertColor`
|
||||
|
||||
Returns `this` if it's a [`SassColor`] and throws an error otherwise.
|
||||
|
||||
[`SassColor`]: color.d.ts.md
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertColor(name?: string): SassColor;
|
||||
```
|
||||
|
||||
#### `assertFunction`
|
||||
|
||||
Returns `this` if it's a [`SassFunction`] and throws an error otherwise.
|
||||
|
||||
[`SassFunction`]: function.d.ts.md
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertFunction(name?: string): SassFunction;
|
||||
```
|
||||
|
||||
#### `assertMap`
|
||||
|
||||
Return `this.tryMap()` if it's not null, and throw an error otherwise.
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertMap(name?: string): SassMap;
|
||||
```
|
||||
|
||||
#### `assertNumber`
|
||||
|
||||
Returns `this` if it's a [`SassNumber`] and throws an error otherwise.
|
||||
|
||||
[`SassNumber`]: number.d.ts.md
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertNumber(name?: string): SassNumber;
|
||||
```
|
||||
|
||||
#### `assertString`
|
||||
|
||||
Returns `this` if it's a [`SassString`] and throws an error otherwise.
|
||||
|
||||
[`SassString`]: string.d.ts.md
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertString(name?: string): SassString;
|
||||
```
|
||||
|
||||
#### `tryMap`
|
||||
|
||||
Returns `this` interpreted as a map.
|
||||
|
||||
* If `this` is a [`SassMap`], return `this`.
|
||||
|
||||
* Otherwise, if [`internal`] is an empty Sass list, return a `SassMap` with its
|
||||
`internal` set to an empty map.
|
||||
|
||||
* Otherwise, return `null`.
|
||||
|
||||
```ts
|
||||
tryMap(): SassMap | null;
|
||||
```
|
||||
|
||||
#### `equals`
|
||||
|
||||
Returns whether [`internal`] is `==` to `other`'s `internal` in SassScript.
|
||||
|
||||
```ts
|
||||
equals(other: Value): boolean;
|
||||
```
|
||||
|
||||
#### `hashCode`
|
||||
|
||||
Returns the same number for any two `Value`s that are equal according to
|
||||
[`equals`].
|
||||
|
||||
[`equals`]: #equals
|
||||
|
||||
> This is _not_ required to be different for different values, although having
|
||||
> overlap between common values is likely to cause performance issues.
|
||||
|
||||
```ts
|
||||
hashCode(): number;
|
||||
```
|
||||
|
||||
#### `toString`
|
||||
|
||||
Returns a string representation of `this`.
|
||||
|
||||
> The specific format can vary from implementation to implementation and is not
|
||||
> guaranteed to be valid Sass source code.
|
||||
|
||||
```ts
|
||||
toString(): string;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // Value
|
||||
```
|
50
spec/js-api/value/list.d.ts
vendored
50
spec/js-api/value/list.d.ts
vendored
@ -1,50 +0,0 @@
|
||||
import {List} from 'immutable';
|
||||
|
||||
import {Value} from './index';
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass list separator.
|
||||
*
|
||||
* > `null` represents the undecided separator type.
|
||||
*/
|
||||
export type ListSeparator = ',' | '/' | ' ' | null;
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass list.
|
||||
*
|
||||
* `internal` refers to a Sass list.
|
||||
*/
|
||||
export class SassList extends Value {
|
||||
/**
|
||||
* Creates a Sass list:
|
||||
*
|
||||
* - If the first argument is an `Array` or a `List`:
|
||||
* - Let `contents` be the first argument.
|
||||
* - Let `options` be the second argument, or `{}` if it's undefined.
|
||||
*
|
||||
* - Otherwise:
|
||||
* - Let `contents` be `[]`.
|
||||
* - Let `options` be the first argument, or `{}` if it's undefined.
|
||||
*
|
||||
* - Let `separator` be `options.separator`, or `','` if that's undefined.
|
||||
*
|
||||
* - Let `brackets` be `options.brackets`, or `false` if that's undefined.
|
||||
*
|
||||
* - Set `internal` to a Sass list with contents set to `contents`, separator
|
||||
* set to `separator`, and brackets set to `brackets`.
|
||||
*
|
||||
* - Return `this`.
|
||||
*/
|
||||
constructor(
|
||||
contents: Value[] | List<Value>,
|
||||
options?: {
|
||||
separator?: ListSeparator;
|
||||
brackets?: boolean;
|
||||
}
|
||||
);
|
||||
|
||||
constructor(options?: {separator?: ListSeparator; brackets?: boolean});
|
||||
|
||||
/** `internal`'s list separator. */
|
||||
get separator(): ListSeparator;
|
||||
}
|
89
spec/js-api/value/list.d.ts.md
Normal file
89
spec/js-api/value/list.d.ts.md
Normal file
@ -0,0 +1,89 @@
|
||||
# List API
|
||||
|
||||
```ts
|
||||
import {List} from 'immutable';
|
||||
|
||||
import {Value} from './index';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`ListSeparator`](#listseparator)
|
||||
* [`SassList`](#sasslist)
|
||||
* [`internal`](#internal)
|
||||
* [Constructor](#constructor)
|
||||
* [`separator`](#separator)
|
||||
|
||||
## Types
|
||||
|
||||
### `ListSeparator`
|
||||
|
||||
The JS API representation of a Sass list separator. null represents the
|
||||
undecided separator type.
|
||||
|
||||
```ts
|
||||
export type ListSeparator = ',' | '/' | ' ' | null;
|
||||
```
|
||||
|
||||
### `SassList`
|
||||
|
||||
The JS API representation of a Sass list.
|
||||
|
||||
```ts
|
||||
export class SassList extends Value {
|
||||
```
|
||||
|
||||
#### `internal`
|
||||
|
||||
The [private `internal` field] refers to [a Sass list].
|
||||
|
||||
[private `internal` field]: index.d.ts.md#internal
|
||||
[a Sass list]: ../../types/list.md
|
||||
|
||||
#### Constructor
|
||||
|
||||
Creates a Sass list:
|
||||
|
||||
* If the first argument is an `Array` or a `List`:
|
||||
* Let `contents` be the first argument.
|
||||
* Let `options` be the second argument, or `{}` if it's undefined.
|
||||
|
||||
* Otherwise:
|
||||
* Let `contents` be `[]`.
|
||||
* Let `options` be the first argument, or `{}` if it's undefined.
|
||||
|
||||
* Let `separator` be `options.separator`, or `','` if that's undefined.
|
||||
|
||||
* Let `brackets` be `options.brackets`, or `false` if that's undefined.
|
||||
|
||||
* Set `internal` to a Sass list with contents set to `contents`, separator set
|
||||
to `separator`, and brackets set to `brackets`.
|
||||
|
||||
* Return `this`.
|
||||
|
||||
```ts
|
||||
constructor(
|
||||
contents: Value[] | List<Value>,
|
||||
options?: {
|
||||
separator?: ListSeparator;
|
||||
brackets?: boolean;
|
||||
}
|
||||
);
|
||||
|
||||
constructor(options?: {separator?: ListSeparator; brackets?: boolean});
|
||||
```
|
||||
|
||||
#### `separator`
|
||||
|
||||
[`internal`]'s list separator.
|
||||
|
||||
[`internal`]: #internal
|
||||
|
||||
```ts
|
||||
get separator(): ListSeparator;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SassList
|
||||
```
|
41
spec/js-api/value/map.d.ts
vendored
41
spec/js-api/value/map.d.ts
vendored
@ -1,41 +0,0 @@
|
||||
import {OrderedMap} from 'immutable';
|
||||
|
||||
import {SassList} from './list';
|
||||
import {Value} from './index';
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass map.
|
||||
*
|
||||
* `internal` refers to a Sass map.
|
||||
*/
|
||||
export class SassMap extends Value {
|
||||
/**
|
||||
* Creates a Sass map:
|
||||
*
|
||||
* - If `contents` is undefined, set it to an empty `OrderedMap`.
|
||||
* - Set `internal` to a Sass map with contents set to `contents`.
|
||||
* - Return `this`.
|
||||
*/
|
||||
constructor(contents?: OrderedMap<Value, Value>);
|
||||
|
||||
/**
|
||||
* Returns a map containing `internal`'s contents:
|
||||
*
|
||||
* - Let `result` be an empty `OrderedMap`.
|
||||
* - Add each key and value from `internal`'s contents to `result`, in order.
|
||||
* - Return `result`.
|
||||
*/
|
||||
get contents(): OrderedMap<Value, Value>;
|
||||
|
||||
/**
|
||||
* - If the first argument is a JavaScript number, pass it to
|
||||
* `this.asList.get` and return the result.
|
||||
*
|
||||
* - Otherwise, pass it to `this.contents.get` and return the result.
|
||||
*/
|
||||
get(key: Value): Value | undefined;
|
||||
|
||||
get(index: number): SassList | undefined;
|
||||
|
||||
tryMap(): SassMap;
|
||||
}
|
82
spec/js-api/value/map.d.ts.md
Normal file
82
spec/js-api/value/map.d.ts.md
Normal file
@ -0,0 +1,82 @@
|
||||
# Map API
|
||||
|
||||
```ts
|
||||
import {OrderedMap} from 'immutable';
|
||||
|
||||
import {SassList} from './list';
|
||||
import {Value} from './index';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`SassMap`](#sassmap)
|
||||
* [`internal`](#internal)
|
||||
* [Constructor](#constructor)
|
||||
* [`contents`](#contents)
|
||||
* [`get`](#get)
|
||||
* [`tryMap`](#trymap)
|
||||
|
||||
## Types
|
||||
|
||||
### `SassMap`
|
||||
|
||||
The JS API representation of a Sass map.
|
||||
|
||||
```ts
|
||||
export class SassMap extends Value {
|
||||
```
|
||||
|
||||
#### `internal`
|
||||
|
||||
The [private `internal` field] refers to a Sass map.
|
||||
|
||||
[private `internal` field]: index.d.ts.md#internal
|
||||
|
||||
|
||||
#### Constructor
|
||||
|
||||
Creates a Sass map:
|
||||
|
||||
* If `contents` is undefined, set it to an empty `OrderedMap`.
|
||||
* Set `internal` to a Sass map with contents set to `contents`.
|
||||
* Return `this`.
|
||||
|
||||
```ts
|
||||
constructor(contents?: OrderedMap<Value, Value>);
|
||||
```
|
||||
|
||||
#### `contents`
|
||||
|
||||
Returns a map containing `internal`'s contents:
|
||||
|
||||
* Let `result` be an empty `OrderedMap`.
|
||||
* Add each key and value from `internal`'s contents to `result`, in order.
|
||||
* Return `result`.
|
||||
|
||||
```ts
|
||||
get contents(): OrderedMap<Value, Value>;
|
||||
```
|
||||
|
||||
#### `get`
|
||||
|
||||
* If the first argument is a JavaScript number, pass it to `this.asList.get` and
|
||||
return the result.
|
||||
|
||||
* Otherwise, pass it to `this.contents.get` and return the result.
|
||||
|
||||
```ts
|
||||
get(key: Value): Value | undefined;
|
||||
|
||||
get(index: number): SassList | undefined;
|
||||
```
|
||||
|
||||
#### `tryMap`
|
||||
|
||||
```ts
|
||||
tryMap(): SassMap;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SassMap
|
||||
```
|
258
spec/js-api/value/number.d.ts
vendored
258
spec/js-api/value/number.d.ts
vendored
@ -1,258 +0,0 @@
|
||||
import {List} from 'immutable';
|
||||
|
||||
import {Value} from './index';
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass number.
|
||||
*
|
||||
* `internal` refers to a Sass number.
|
||||
*/
|
||||
export class SassNumber extends Value {
|
||||
/**
|
||||
* Creates a Sass number:
|
||||
*
|
||||
* - If the second argument is undefined:
|
||||
*
|
||||
* - Set `internal` to a Sass number with a value of `value`.
|
||||
*
|
||||
* - Otherwise, if the second argument is a string:
|
||||
*
|
||||
* - Set `internal` to a Sass number with a value of `value` and that string
|
||||
* as its single numerator unit.
|
||||
*
|
||||
* - Otherwise,
|
||||
*
|
||||
* - Let `options` be the second argument.
|
||||
*
|
||||
* - Set `internal` to a Sass number with a value of `value`,
|
||||
* `options.numeratorUnits` as its numerator units (if passed), and
|
||||
* `options.denominatorUnits` as its denominator units (if passed).
|
||||
*
|
||||
* - Return `this`.
|
||||
*/
|
||||
constructor(
|
||||
value: number,
|
||||
unit?:
|
||||
| string
|
||||
| {
|
||||
numeratorUnits?: string[] | List<string>;
|
||||
denominatorUnits?: string[] | List<string>;
|
||||
}
|
||||
);
|
||||
|
||||
/** `internal`'s value. */
|
||||
get value(): number;
|
||||
|
||||
/** Whether `internal`'s value `fuzzyEquals` an integer. */
|
||||
get isInt(): boolean;
|
||||
|
||||
/**
|
||||
* Returns `internal`'s value as an integer:
|
||||
*
|
||||
* - If `internal`'s value `fuzzyEquals` an integer, return that integer.
|
||||
* - Otherwise, return `null`.
|
||||
*/
|
||||
get asInt(): number | null;
|
||||
|
||||
/** `internal`'s numerator units. */
|
||||
get numeratorUnits(): List<string>;
|
||||
|
||||
/** `internal`'s denominator units. */
|
||||
get denominatorUnits(): List<string>;
|
||||
|
||||
/** Whether `internal` has numerator or denominator units. */
|
||||
get hasUnits(): boolean;
|
||||
|
||||
/**
|
||||
* Asserts that `internal`'s value is an integer:
|
||||
*
|
||||
* - If `internal`'s value `fuzzyEquals` an integer, return that integer.
|
||||
* - Otherwise, throw an error.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertInt(name?: string): number;
|
||||
|
||||
/**
|
||||
* Asserts that `internal`'s value is within the specified range:
|
||||
*
|
||||
* - If `internal`'s value is `fuzzyGreaterThan` `min` and `fuzzyLessThan`
|
||||
* `max`, return it.
|
||||
* - Otherwise, if `internal`'s value `fuzzyEquals` `min`, return `min`.
|
||||
* - Otherwise, if `internal`'s value `fuzzyEquals` `max`, return `max`.
|
||||
* - Otherwise, throw an error.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertInRange(min: number, max: number, name?: string): number;
|
||||
|
||||
/**
|
||||
* Asserts that `internal` is unitless:
|
||||
*
|
||||
* - If `internal` has any numerator or denominator units, throw an error.
|
||||
* - Otherwise, return `this`.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertNoUnits(name?: string): SassNumber;
|
||||
|
||||
/**
|
||||
* Asserts the type of `internal`'s unit:
|
||||
*
|
||||
* - If `internal` has any denominator units, or if `unit` is not `internal`'s
|
||||
* only numerator unit, throw an error.
|
||||
* - Otherwise, return `this`.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
assertUnit(unit: string, name?: string): SassNumber;
|
||||
|
||||
/**
|
||||
* Whether `internal` has the specified unit:
|
||||
*
|
||||
* - If `internal` has any denominator units, return false.
|
||||
* - Otherwise, return whether `unit` is `internal`'s only numerator unit.
|
||||
*/
|
||||
hasUnit(unit: string): boolean;
|
||||
|
||||
/**
|
||||
* Whether `internal` is [compatible] with `unit`.
|
||||
*
|
||||
* [compatible]: ../../types/number.md#compatible-units
|
||||
*/
|
||||
compatibleWithUnit(unit: string): boolean;
|
||||
|
||||
/**
|
||||
* Creates a new copy of `this` with its units converted to those represented
|
||||
* by `newNumerators` and `newDenominators`:
|
||||
*
|
||||
* - Let `converter` be the result of
|
||||
*
|
||||
* ```
|
||||
* withUnits(0, {
|
||||
* numeratorUnits: newNumerators,
|
||||
* denominatorUnits: newDenominators,
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* - If `converter` is not [compatible] with `internal`, throw an error.
|
||||
*
|
||||
* - Set `converter` to the result of `simplify`ing `converter`.
|
||||
*
|
||||
* - Return a new `SassNumber` with `internal` set to the result of the
|
||||
* SassScript expression `converter + internal`.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
convert(
|
||||
newNumerators: string[] | List<string>,
|
||||
newDenominators: string[] | List<string>,
|
||||
name?: string
|
||||
): SassNumber;
|
||||
|
||||
/**
|
||||
* Creates a new copy of `this` with its units converted to the units of
|
||||
* `other`:
|
||||
*
|
||||
* - Let `newNumerators` be the numerator units of `other`.
|
||||
* - Let `newDenominators` be the denominator units of `other`.
|
||||
* - Return the result of `convert(newNumerators, newDenominators)`.
|
||||
*
|
||||
* > The `name` and `otherName` parameters may be used for error reporting.
|
||||
*/
|
||||
convertToMatch(
|
||||
other: SassNumber,
|
||||
name?: string,
|
||||
otherName?: string
|
||||
): SassNumber;
|
||||
|
||||
/**
|
||||
* Return the value of the result of `convert(newNumerators,
|
||||
* newDenominators)`.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
convertValue(
|
||||
newNumerators: string[] | List<string>,
|
||||
newDenominators: string[] | List<string>,
|
||||
name?: string
|
||||
): number;
|
||||
|
||||
/**
|
||||
* Returns the value of the result of `convertToMatch(other)`.
|
||||
*
|
||||
* > The `name` and `otherName` parameters may be used for error reporting.
|
||||
*/
|
||||
convertValueToMatch(
|
||||
other: SassNumber,
|
||||
name?: string,
|
||||
otherName?: string
|
||||
): number;
|
||||
|
||||
/**
|
||||
* Creates a new copy of `this` with its units converted to those represented
|
||||
* by `newNumerators` and `newDenominators`:
|
||||
*
|
||||
* - Support converting to/from unitless:
|
||||
*
|
||||
* - If `internal` is unitless:
|
||||
*
|
||||
* - If `newNumerators` and `newDenominators` are both empty, return
|
||||
* `this`.
|
||||
*
|
||||
* - Otherwise, for the duration of this procedure, let `internal` behave
|
||||
* as if its numerator units were equal to `newNumerators` and its
|
||||
* denominator units were equal to `newDenominators`.
|
||||
*
|
||||
* - Otherwise, if `newNumerators` and `newDenominators` are both empty, set
|
||||
* `newNumerators` to `internal`'s numerator units and `newDenominators`
|
||||
* to `internal`'s denominator units.
|
||||
*
|
||||
* - Return the result of `convert(newNumerators, newDenominators)`.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
coerce(
|
||||
newNumerators: string[] | List<string>,
|
||||
newDenominators: string[] | List<string>,
|
||||
name?: string
|
||||
): SassNumber;
|
||||
|
||||
/**
|
||||
* Creates a new copy of `this` with its units converted to the units of
|
||||
* `other`:
|
||||
*
|
||||
* - Let `newNumerators` be the numerator units of `other`.
|
||||
* - Let `newDenominators` be the denominator units of `other`.
|
||||
* - Return the result of `coerce(newNumerators, newDenominators)`.
|
||||
*
|
||||
* > The `name` and `otherName` parameters may be used for error reporting.
|
||||
*/
|
||||
coerceToMatch(
|
||||
other: SassNumber,
|
||||
name?: string,
|
||||
otherName?: string
|
||||
): SassNumber;
|
||||
|
||||
/**
|
||||
* Return the value of the result of `coerce(newNumerators, newDenominators)`.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
coerceValue(
|
||||
newNumerators: string[] | List<string>,
|
||||
newDenominators: string[] | List<string>,
|
||||
name?: string
|
||||
): number;
|
||||
|
||||
/**
|
||||
* Returns the value of the result of `coerceToMatch(other)`.
|
||||
*
|
||||
* > The `name` and `otherName` parameters may be used for error reporting.
|
||||
*/
|
||||
coerceValueToMatch(
|
||||
other: SassNumber,
|
||||
name?: string,
|
||||
otherName?: string
|
||||
): number;
|
||||
}
|
361
spec/js-api/value/number.d.ts.md
Normal file
361
spec/js-api/value/number.d.ts.md
Normal file
@ -0,0 +1,361 @@
|
||||
# Number API
|
||||
|
||||
```ts
|
||||
import {List} from 'immutable';
|
||||
|
||||
import {Value} from './index';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`SassNumber`](#sassnumber)
|
||||
* [`internal`](#internal)
|
||||
* [Constructor](#constructor)
|
||||
* [`value`](#value)
|
||||
* [`isInt`](#isint)
|
||||
* [`asInt`](#asint)
|
||||
* [`numeratorUnits`](#numeratorunits)
|
||||
* [`denominatorUnits`](#denominatorunits)
|
||||
* [`hasUnits`](#hasunits)
|
||||
* [`assertInt`](#assertint)
|
||||
* [`assertInRange`](#assertinrange)
|
||||
* [`assertUnitless`](#assertunitless)
|
||||
* [`assertUnit`](#assertunit)
|
||||
* [`hasUnit`](#hasunit)
|
||||
* [`compatibleWithUnit`](#compatiblewithunit)
|
||||
* [`convert`](#convert)
|
||||
* [`convertToMatch`](#converttomatch)
|
||||
* [`convertValue`](#convertvalue)
|
||||
* [`convertValueToMatch`](#convertvaluetomatch)
|
||||
* [`coerce`](#coerce)
|
||||
* [`coerceToMatch`](#coercetomatch)
|
||||
* [`coerce`](#coerce-1)
|
||||
* [`coerceValueToMatch`](#coercevaluetomatch)
|
||||
|
||||
## Types
|
||||
|
||||
### `SassNumber`
|
||||
|
||||
The JS API representation of a Sass number.
|
||||
|
||||
```ts
|
||||
export class SassNumber extends Value {
|
||||
```
|
||||
|
||||
#### `internal`
|
||||
|
||||
The [private `internal` field] refers to [a Sass number].
|
||||
|
||||
[private `internal` field]: index.d.ts.md#internal
|
||||
[a Sass number]: ../../types/number.md
|
||||
|
||||
#### Constructor
|
||||
|
||||
Creates a Sass number:
|
||||
|
||||
* If the second argument is undefined:
|
||||
|
||||
* Set `internal` to a Sass number with a value of `value`.
|
||||
|
||||
* Otherwise, if the second argument is a string:
|
||||
|
||||
* Set `internal` to a Sass number with a value of `value` and that string as
|
||||
its single numerator unit.
|
||||
|
||||
* Otherwise,
|
||||
|
||||
* Let `options` be the second argument.
|
||||
|
||||
* Set `internal` to a Sass number with a value of `value`,
|
||||
`options.numeratorUnits` as its numerator units (if passed), and
|
||||
`options.denominatorUnits` as its denominator units (if passed).
|
||||
|
||||
* Return `this`.
|
||||
|
||||
```ts
|
||||
constructor(
|
||||
value: number,
|
||||
unit?:
|
||||
| string
|
||||
| {
|
||||
numeratorUnits?: string[] | List<string>;
|
||||
denominatorUnits?: string[] | List<string>;
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
#### `value`
|
||||
|
||||
Returns [`internal`]'s value.
|
||||
|
||||
[`internal`]: #internal
|
||||
|
||||
```ts
|
||||
get value(): number;
|
||||
```
|
||||
|
||||
#### `isInt`
|
||||
|
||||
Whether [`internal`] is an [integer].
|
||||
|
||||
[integer]: ../../types/number.md#integer
|
||||
|
||||
```ts
|
||||
get isInt(): boolean;
|
||||
```
|
||||
|
||||
#### `asInt`
|
||||
|
||||
Returns [`internal`]'s [integer value] if it has one, or null if it doesn't.
|
||||
|
||||
[integer value]: ../../types/number.md#integer
|
||||
|
||||
```ts
|
||||
get asInt(): number | null;
|
||||
```
|
||||
|
||||
#### `numeratorUnits`
|
||||
|
||||
Returns [`internal`]'s numerator units.
|
||||
|
||||
```ts
|
||||
get numeratorUnits(): List<string>;
|
||||
```
|
||||
|
||||
#### `denominatorUnits`
|
||||
|
||||
Returns [`internal`]'s denominator units.
|
||||
|
||||
```ts
|
||||
get denominatorUnits(): List<string>;
|
||||
```
|
||||
|
||||
#### `hasUnits`
|
||||
|
||||
Whether [`internal`] has numerator or denominator units.
|
||||
|
||||
```ts
|
||||
get hasUnits(): boolean;
|
||||
```
|
||||
|
||||
#### `assertInt`
|
||||
|
||||
Returns [`internal`]'s [integer value] if it has one, and throws an error if it
|
||||
doesn't.
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertInt(name?: string): number;
|
||||
```
|
||||
|
||||
#### `assertInRange`
|
||||
|
||||
Asserts that [`internal`]'s value is within the specified range:
|
||||
|
||||
* If `internal`'s value is greater than `min` and less than `max`, return it.
|
||||
* Otherwise, if `internal`'s value [fuzzy equals] `min`, return `min`.
|
||||
* Otherwise, if `internal`'s value fuzzy equals `max`, return `max`.
|
||||
* Otherwise, throw an error.
|
||||
|
||||
[fuzzy equals]: ../../types/number.md#fuzzy-equality
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertInRange(min: number, max: number, name?: string): number;
|
||||
```
|
||||
|
||||
#### `assertUnitless`
|
||||
|
||||
Returns `this` if [`internal`] has no numerator or denominator units, and throws
|
||||
an error otherwise.
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertNoUnits(name?: string): SassNumber;
|
||||
```
|
||||
|
||||
#### `assertUnit`
|
||||
|
||||
Asserts the type of [`internal`]'s unit:
|
||||
|
||||
* If `internal` has any denominator units, or if `unit` is not `internal`'s
|
||||
only numerator unit, throw an error.
|
||||
* Otherwise, return `this`.
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
assertUnit(unit: string, name?: string): SassNumber;
|
||||
```
|
||||
|
||||
#### `hasUnit`
|
||||
|
||||
Returns whether `unit` is [`internal`]'s only numerator unit and `internal` has no
|
||||
denominator units.
|
||||
|
||||
```ts
|
||||
hasUnit(unit: string): boolean;
|
||||
```
|
||||
|
||||
#### `compatibleWithUnit`
|
||||
|
||||
Whether `internal` is [compatible] with `unit`.
|
||||
|
||||
[compatible]: ../../types/number.md#compatible-units
|
||||
|
||||
```ts
|
||||
compatibleWithUnit(unit: string): boolean;
|
||||
```
|
||||
|
||||
#### `convert`
|
||||
|
||||
* Let `converter` be the [`internal`] field of the result of
|
||||
|
||||
```js
|
||||
withUnits(0, {
|
||||
numeratorUnits: newNumerators,
|
||||
denominatorUnits: newDenominators,
|
||||
});
|
||||
```
|
||||
|
||||
* If `converter` is not [compatible] with `internal`, throw an error.
|
||||
|
||||
* Set `converter` to the result of [simplifying] `converter`.
|
||||
|
||||
[simplifying]: ../../types/number.md#simplifying-a-number
|
||||
|
||||
* Return a new `SassNumber` with `internal` set to the result of the
|
||||
SassScript expression `converter + internal`.
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
convert(
|
||||
newNumerators: string[] | List<string>,
|
||||
newDenominators: string[] | List<string>,
|
||||
name?: string
|
||||
): SassNumber;
|
||||
```
|
||||
|
||||
#### `convertToMatch`
|
||||
|
||||
Return the result of `convert(other.numeratorUnits, other.denominatorUnits)`.
|
||||
|
||||
> The `name` and `otherName` parameters may be used for error reporting.
|
||||
|
||||
```ts
|
||||
convertToMatch(
|
||||
other: SassNumber,
|
||||
name?: string,
|
||||
otherName?: string
|
||||
): SassNumber;
|
||||
```
|
||||
|
||||
#### `convertValue`
|
||||
|
||||
Return the result of `convert(newNumerators, newDenominators).value`.
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
convertValue(
|
||||
newNumerators: string[] | List<string>,
|
||||
newDenominators: string[] | List<string>,
|
||||
name?: string
|
||||
): number;
|
||||
```
|
||||
|
||||
#### `convertValueToMatch`
|
||||
|
||||
Returns the result of `convertToMatch(other).value`.
|
||||
|
||||
> The `name` and `otherName` parameters may be used for error reporting.
|
||||
|
||||
```ts
|
||||
convertValueToMatch(
|
||||
other: SassNumber,
|
||||
name?: string,
|
||||
otherName?: string
|
||||
): number;
|
||||
```
|
||||
|
||||
#### `coerce`
|
||||
|
||||
Creates a new copy of `this` with its units converted to those represented
|
||||
by `newNumerators` and `newDenominators`:
|
||||
|
||||
* If `newNumerators` and `newDenominators` are both empty, return the result of
|
||||
`new SassNumber(this.value)`.
|
||||
|
||||
* If `internal` is unitless, return the result of:
|
||||
|
||||
[unitless]: ../../types/number.md#
|
||||
|
||||
```js
|
||||
new SassNumber(this.value, {
|
||||
numeratorUnits: newNumerators,
|
||||
denominatorUnits: newDenominators
|
||||
});
|
||||
```
|
||||
|
||||
* Return the result of `convert(newNumerators, newDenominators)`.
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
coerce(
|
||||
newNumerators: string[] | List<string>,
|
||||
newDenominators: string[] | List<string>,
|
||||
name?: string
|
||||
): SassNumber;
|
||||
```
|
||||
|
||||
#### `coerceToMatch`
|
||||
|
||||
Return the result of `coerce(other.numeratorUnits, other.denominatorUnits)`.
|
||||
|
||||
> The `name` and `otherName` parameters may be used for error reporting.
|
||||
|
||||
```ts
|
||||
coerceToMatch(
|
||||
other: SassNumber,
|
||||
name?: string,
|
||||
otherName?: string
|
||||
): SassNumber;
|
||||
```
|
||||
|
||||
#### `coerce`
|
||||
|
||||
Return the result of `coerce(newNumerators, newDenominators).value`.
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
coerceValue(
|
||||
newNumerators: string[] | List<string>,
|
||||
newDenominators: string[] | List<string>,
|
||||
name?: string
|
||||
): number;
|
||||
```
|
||||
|
||||
#### `coerceValueToMatch`
|
||||
|
||||
Returns the value of the result of `coerceToMatch(other)`.
|
||||
|
||||
> The `name` and `otherName` parameters may be used for error reporting.
|
||||
|
||||
```ts
|
||||
coerceValueToMatch(
|
||||
other: SassNumber,
|
||||
name?: string,
|
||||
otherName?: string
|
||||
): number;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SassNumber
|
||||
```
|
78
spec/js-api/value/string.d.ts
vendored
78
spec/js-api/value/string.d.ts
vendored
@ -1,78 +0,0 @@
|
||||
import {Value} from './index';
|
||||
|
||||
/**
|
||||
* The JS API representation of a Sass string.
|
||||
*
|
||||
* `internal` refers to a Sass string.
|
||||
*/
|
||||
export class SassString extends Value {
|
||||
/**
|
||||
* Creates a Sass string:
|
||||
*
|
||||
* - If the first argument is a string:
|
||||
* - Let `text` be the first argument.
|
||||
* - Let `options` be the second argument, or `{}` if it's undefined.
|
||||
*
|
||||
* - Otherwise:
|
||||
* - Let `text` be `""`.
|
||||
* - Let `options` be the first argument, or `{}` if it's undefined.
|
||||
*
|
||||
* - Let `quotes` be `options.quotes`, or `true` if that's undefined.
|
||||
*
|
||||
* - Set `internal` to a Sass string with contents set to `text` and quoted
|
||||
* set to `quotes`.
|
||||
*
|
||||
* - Return `this`.
|
||||
*/
|
||||
constructor(
|
||||
text: string,
|
||||
options?: {
|
||||
quotes?: boolean;
|
||||
}
|
||||
);
|
||||
|
||||
constructor(options?: {/** @default true */ quotes?: boolean});
|
||||
|
||||
/**
|
||||
* Creates an empty Sass string:
|
||||
*
|
||||
* - Set `internal` to an empty Sass string with quoted value set to
|
||||
* `options.quotes`.
|
||||
* - Return `this`.
|
||||
*/
|
||||
|
||||
/** The contents of `internal` serialized as UTF-16 code units. */
|
||||
get text(): string;
|
||||
|
||||
/** Whether `internal` has quotes. */
|
||||
get hasQuotes(): boolean;
|
||||
|
||||
/** The number of Unicode code points in `text`. */
|
||||
get sassLength(): number;
|
||||
|
||||
/**
|
||||
* Converts the Sass index `sassIndex` to a JS index into `text`:
|
||||
*
|
||||
* - If `sassIndex` is not a unitless Sass number, throw an error.
|
||||
*
|
||||
* - Let `value` be the value of `sassIndex`. Let `index` be the result of
|
||||
* `fuzzyAsInt(value)`. If `index === null`, throw an error.
|
||||
*
|
||||
* - If `index === 0`, or the absolute value of `index` is greater than
|
||||
* the length of `sassLength`, throw an error.
|
||||
*
|
||||
* - If `index > 0`, let `normalizedIndex = index - 1`.
|
||||
* - Otherwise, if `index < 0`, let `normalizedIndex = sassLength + index`.
|
||||
*
|
||||
* - Let `jsIndex` be a JS index. Set `jsIndex` to the first code
|
||||
* unit of the Unicode code point that `normalizedIndex` points to.
|
||||
*
|
||||
* > Sass indices count Unicode code points, whereas JS indices count
|
||||
* > UTF-16 code units.
|
||||
*
|
||||
* - Return `jsIndex`.
|
||||
*
|
||||
* > The `name` parameter may be used for error reporting.
|
||||
*/
|
||||
sassIndexToStringIndex(sassIndex: Value, name?: string): number;
|
||||
}
|
117
spec/js-api/value/string.d.ts.md
Normal file
117
spec/js-api/value/string.d.ts.md
Normal file
@ -0,0 +1,117 @@
|
||||
# String API
|
||||
|
||||
```ts
|
||||
import {Value} from './index';
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Types](#types)
|
||||
* [`SassString`](#sassstring)
|
||||
* [`internal`](#internal)
|
||||
* [Constructor](#constructor)
|
||||
* [`text`](#text)
|
||||
* [`hasQuotes`](#hasquotes)
|
||||
* [`sassLength`](#sasslength)
|
||||
* [`sassIndexToStringIndex`](#sassindextostringindex)
|
||||
|
||||
## Types
|
||||
|
||||
### `SassString`
|
||||
|
||||
The JS API representation of a Sass string.
|
||||
|
||||
```ts
|
||||
export class SassString extends Value {
|
||||
```
|
||||
|
||||
#### `internal`
|
||||
|
||||
The [private `internal` field] refers to a Sass string.
|
||||
|
||||
[private `internal` field]: index.d.ts.md#internal
|
||||
|
||||
#### Constructor
|
||||
|
||||
Creates a Sass string:
|
||||
|
||||
* If the first argument is a string:
|
||||
* Let `text` be the first argument.
|
||||
* Let `options` be the second argument, or `{}` if it's undefined.
|
||||
|
||||
* Otherwise:
|
||||
* Let `text` be `""`.
|
||||
* Let `options` be the first argument, or `{}` if it's undefined.
|
||||
|
||||
* Let `quotes` be `options.quotes`, or `true` if that's undefined.
|
||||
|
||||
* Set [`internal`] to a Sass string with contents set to `text` and quoted set
|
||||
to `quotes`.
|
||||
|
||||
* Return `this`.
|
||||
|
||||
```ts
|
||||
constructor(
|
||||
text: string,
|
||||
options?: {
|
||||
quotes?: boolean;
|
||||
}
|
||||
);
|
||||
|
||||
constructor(options?: {/** @default true */ quotes?: boolean});
|
||||
```
|
||||
|
||||
#### `text`
|
||||
|
||||
The contents of [`internal`] serialized as UTF-16 code units.
|
||||
|
||||
```ts
|
||||
get text(): string;
|
||||
```
|
||||
|
||||
#### `hasQuotes`
|
||||
|
||||
Whether [`internal`] has quotes.
|
||||
|
||||
```ts
|
||||
get hasQuotes(): boolean;
|
||||
```
|
||||
|
||||
#### `sassLength`
|
||||
|
||||
The number of Unicode code points in [`internal`]'s contents.
|
||||
|
||||
```ts
|
||||
get sassLength(): number;
|
||||
```
|
||||
|
||||
#### `sassIndexToStringIndex`
|
||||
|
||||
Converts the Sass index `sassIndex` to a JS index into `text`:
|
||||
|
||||
* If `sassIndex` is not a unitless Sass number, throw an error.
|
||||
|
||||
* Let `value` be the value of `sassIndex`. Let `index` be the result of
|
||||
`fuzzyAsInt(value)`. If `index === null`, throw an error.
|
||||
|
||||
* If `index === 0`, or the absolute value of `index` is greater than the length
|
||||
of `sassLength`, throw an error.
|
||||
|
||||
* If `index > 0`, let `normalizedIndex = index * 1`.
|
||||
* Otherwise, if `index < 0`, let `normalizedIndex = sassLength + index`.
|
||||
|
||||
* Return the index in `text` of the first code unit of the Unicode code point
|
||||
that `normalizedIndex` points to.
|
||||
|
||||
> Sass indices count Unicode code points, whereas JS indices count UTF-16 code
|
||||
> units.
|
||||
|
||||
> The `name` parameter may be used for error reporting.
|
||||
|
||||
```ts
|
||||
sassIndexToStringIndex(sassIndex: Value, name?: string): number;
|
||||
```
|
||||
|
||||
```ts
|
||||
} // SassString
|
||||
```
|
@ -17,10 +17,12 @@ const parser: prettier.CustomParser = (text, parsers) => {
|
||||
};
|
||||
|
||||
for (const specPath of glob.sync('spec/js-api/**/*.d.ts')) {
|
||||
const specFile = prettier.format(fs.readFileSync(specPath, 'utf-8'), {
|
||||
const specFile = prettier
|
||||
.format(fs.readFileSync(specPath, 'utf-8'), {
|
||||
filepath: specPath,
|
||||
parser,
|
||||
});
|
||||
})
|
||||
.replace(/\n\n+/g, '\n');
|
||||
const docPath = p.join('js-api-doc', p.relative('spec/js-api', specPath));
|
||||
|
||||
if (!fs.existsSync(docPath)) {
|
||||
@ -31,10 +33,12 @@ for (const specPath of glob.sync('spec/js-api/**/*.d.ts')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const docFile = prettier.format(fs.readFileSync(docPath, 'utf-8'), {
|
||||
const docFile = prettier
|
||||
.format(fs.readFileSync(docPath, 'utf-8'), {
|
||||
filepath: specPath,
|
||||
parser,
|
||||
});
|
||||
})
|
||||
.replace(/\n\n+/g, '\n');
|
||||
if (specFile === docFile) continue;
|
||||
|
||||
const diffResult = diff.createTwoFilesPatch(
|
||||
|
62
tool/tangle.ts
Normal file
62
tool/tangle.ts
Normal file
@ -0,0 +1,62 @@
|
||||
// The literate programming "tangle" tool: takes literate programming files (in
|
||||
// this case, Markdown files with embedded TypeScript) and converts them to the
|
||||
// corresponding physical TypeScript files.
|
||||
|
||||
import * as colors from 'colors/safe';
|
||||
import * as crypto from 'crypto';
|
||||
import * as fs from 'fs';
|
||||
import * as glob from 'glob';
|
||||
import {marked} from 'marked';
|
||||
import * as p from 'path';
|
||||
import * as prettier from 'prettier';
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const files = glob.sync(args.length === 0 ? '**/*.d.ts.md' : args, {
|
||||
ignore: ['node_modules/**/*.d.ts.md'],
|
||||
});
|
||||
|
||||
(async () => {
|
||||
for (const file of files) {
|
||||
if (!file.endsWith('.md')) {
|
||||
console.error(
|
||||
`${colors.red(colors.bold('Error:'))} Can't tangle non-.md file ` +
|
||||
`"${file}".`
|
||||
);
|
||||
process.exitCode = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
const outputFile = file.substring(0, file.length - 3);
|
||||
const outputType = p.extname(outputFile).substring(1);
|
||||
if (outputType === '') {
|
||||
console.error(
|
||||
`${colors.yellow(colors.bold('Warning:'))} File "${file}" has no ` +
|
||||
"additional extension, so there's nothing to tangle it to."
|
||||
);
|
||||
}
|
||||
|
||||
const source = fs.readFileSync(file, 'utf8');
|
||||
const hash = crypto.createHash('sha256').update(source).digest('hex');
|
||||
const codeBlocks: string[] = [`// <[tangle hash]> ${hash}`];
|
||||
|
||||
marked.parse(source, {
|
||||
walkTokens: token => {
|
||||
if (token.type === 'code' && token.lang === outputType) {
|
||||
codeBlocks.push(token.text);
|
||||
codeBlocks.push('// ==<[tangle boundary]>==');
|
||||
}
|
||||
},
|
||||
});
|
||||
codeBlocks.push('');
|
||||
|
||||
const config = (await prettier.resolveConfig(outputFile)) ?? {};
|
||||
fs.writeFileSync(
|
||||
outputFile,
|
||||
prettier.format(codeBlocks.join('\n'), {
|
||||
filepath: outputFile,
|
||||
...config,
|
||||
})
|
||||
);
|
||||
console.log(colors.grey(`Tangled ${file} to ${outputFile}`));
|
||||
}
|
||||
})();
|
104
tool/untangle.ts
Normal file
104
tool/untangle.ts
Normal file
@ -0,0 +1,104 @@
|
||||
// The inverse of `tangle.ts`, which takes the generated TypeScript and injects
|
||||
// it back into the Markdown document. This allow us to format the TypeScript
|
||||
// files using standard tools while keeping their canonical sources in Markdown.
|
||||
|
||||
import * as colors from 'colors/safe';
|
||||
import * as crypto from 'crypto';
|
||||
import dedent from 'ts-dedent';
|
||||
import * as fs from 'fs';
|
||||
import * as glob from 'glob';
|
||||
import {marked} from 'marked';
|
||||
import * as p from 'path';
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const files = glob.sync(args.length === 0 ? '**/*.d.ts.md' : args, {
|
||||
ignore: ['node_modules/**/*.d.ts.md'],
|
||||
});
|
||||
|
||||
for (const file of files) {
|
||||
if (!file.endsWith('.md')) {
|
||||
console.error(
|
||||
`${colors.red(colors.bold('Error:'))} Can't untangle non-.md file ` +
|
||||
`"${file}".`
|
||||
);
|
||||
process.exitCode = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
const tangledFile = file.substring(0, file.length - 3);
|
||||
const tangledType = p.extname(tangledFile).substring(1);
|
||||
if (tangledType === '') {
|
||||
console.error(
|
||||
`${colors.yellow(colors.bold('Warning:'))} File "${file}" has no ` +
|
||||
"additional extension, so there's nothing to untangle it from."
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(tangledFile)) {
|
||||
console.error(
|
||||
`${colors.red(colors.bold('Error:'))} Can't untangle "${file}" ` +
|
||||
`because "${tangledFile}" doesn't exist.`
|
||||
);
|
||||
process.exitCode = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
const codeBlocks = fs
|
||||
.readFileSync(tangledFile, 'utf8')
|
||||
.split(/\n *\/\/ ==<\[tangle boundary\]>==\n/);
|
||||
|
||||
const match = /^\/\/ <\[tangle hash\]> (.*?)\n/.exec(codeBlocks[0]);
|
||||
if (!match) {
|
||||
console.error(
|
||||
`${colors.red(colors.bold('Error:'))} "${tangledFile}" is missing ` +
|
||||
'the initial hash.'
|
||||
);
|
||||
process.exitCode = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
const expectedHash = match[1];
|
||||
codeBlocks[0] = codeBlocks[0].split('\n').slice(1).join('\n');
|
||||
|
||||
let source = fs.readFileSync(file, 'utf8');
|
||||
const hash = crypto.createHash('sha256').update(source).digest('hex');
|
||||
if (hash !== expectedHash) {
|
||||
console.error(
|
||||
`${colors.red(colors.bold('Error:'))} "${file}" was modified after ` +
|
||||
`"${tangledFile}" was tangled.`
|
||||
);
|
||||
process.exitCode = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
let failed = false;
|
||||
marked.parse(source, {
|
||||
walkTokens: token => {
|
||||
if (failed) return;
|
||||
if (token.type === 'code' && token.lang === tangledType) {
|
||||
let codeBlock = codeBlocks.shift();
|
||||
if (codeBlock === undefined) {
|
||||
console.error(
|
||||
`${colors.red(colors.bold('Error:'))} "${tangledFile}" has fewer ` +
|
||||
`code blocks than "${file}".`
|
||||
);
|
||||
process.exitCode = 1;
|
||||
failed = true;
|
||||
codeBlock = '';
|
||||
}
|
||||
|
||||
source = source.replace(
|
||||
token.raw,
|
||||
// Add a leading newline to satisfy dedent().
|
||||
`\`\`\`${token.lang}\n${dedent('\n' + codeBlock)}\n\`\`\``
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
if (failed) continue;
|
||||
|
||||
if (!source.endsWith('\n')) source += '\n';
|
||||
fs.writeFileSync(file, source);
|
||||
console.log(colors.grey(`Untangled ${tangledFile} to ${file}`));
|
||||
}
|
Loading…
Reference in New Issue
Block a user