mirror of
https://github.com/sass/sass.git
synced 2024-09-21 10:37:22 +00:00
Merge remote-tracking branch 'origin/main' into merge-main
This commit is contained in:
commit
290c02f1f3
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -72,7 +72,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: bufbuild/buf-setup-action@v1.30.0
|
||||
- uses: bufbuild/buf-setup-action@v1.32.1
|
||||
with: {github_token: "${{ github.token }}"}
|
||||
- name: Generate protobuf code
|
||||
run: buf generate
|
||||
@ -138,7 +138,7 @@ jobs:
|
||||
|
||||
- name: Find changed files in js-api-doc
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@2d756ea4c53f7f6b397767d8723b3a10a9f35bf2
|
||||
uses: tj-actions/changed-files@03334d095e2739fa9ac4034ec16f66d5d01e9eba
|
||||
with: {files: js-api-doc}
|
||||
|
||||
- name: Deploy
|
||||
|
@ -4,6 +4,11 @@
|
||||
|
||||
* Remove `RgbColor`, `HslColor` and `HwbColor` SassScript values.
|
||||
|
||||
## 2.7.0
|
||||
|
||||
* Add `containing_url_unused` field to `CanonicalizeResponse` and
|
||||
`FileImportResponse`.
|
||||
|
||||
## 2.6.0
|
||||
|
||||
* Add `fatal_deprecation`, `silence_deprecation`, and `future_deprecation`
|
||||
|
67
accepted/css-function-mixin-preparation.md
Normal file
67
accepted/css-function-mixin-preparation.md
Normal file
@ -0,0 +1,67 @@
|
||||
# Preparing for Plain CSS Functions and Mixins: Draft 1
|
||||
|
||||
*([Issue](https://github.com/sass/sass/issues/3787))*
|
||||
|
||||
This proposal adds errors for existing Sass syntax which is likely to conflict
|
||||
with upcoming plain CSS support for functions and mixins.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Background](#background)
|
||||
* [Summary](#summary)
|
||||
* [Semantics](#semantics)
|
||||
* [`@mixin`](#mixin)
|
||||
* [`@function`](#function)
|
||||
* [Deprecation Process](#deprecation-process)
|
||||
|
||||
## Background
|
||||
|
||||
> This section is non-normative.
|
||||
|
||||
In [this informal proposal] and [this issue], the CSS working group have begun
|
||||
seriously discussing the possibility of introducing functions and mixins to CSS
|
||||
itself. Although many specific details are still in flux, all syntaxes that have
|
||||
been floated have two things in common:
|
||||
|
||||
[this informal proposal]: https://css.oddbird.net/sasslike/mixins-functions/
|
||||
[this issue]: https://github.com/w3c/csswg-drafts/issues/9350
|
||||
|
||||
* They use at-rules named `@mixin` and `@function`, just as Sass does today.
|
||||
* They require custom identifiers beginning with `--` after these at-rules.
|
||||
|
||||
Sass currently allows functions and mixins whose names begin with `--`, but this
|
||||
is a relatively painless thing to deprecate and would allow us full CSS
|
||||
compatibility with whatever version of the proposal ends up getting implemented.
|
||||
|
||||
## Summary
|
||||
|
||||
> This section is non-normative.
|
||||
|
||||
This proposal makes any mixin or function whose name begins with `--` an error.
|
||||
This will be preceded by a deprecation period in which those mixins and
|
||||
functions will just produce warnings.
|
||||
|
||||
## Semantics
|
||||
|
||||
### `@mixin`
|
||||
|
||||
Update [the `@mixin` semantics] to add after the first line:
|
||||
|
||||
[the `@mixin` semantics]: ../spec/at-rules/mixin.md
|
||||
|
||||
* If `name` begins with `--`, throw an error.
|
||||
|
||||
### `@function`
|
||||
|
||||
Update [the `@function` semantics] to add after the first line:
|
||||
|
||||
[the `@function` semantics]: ../spec/at-rules/function.md
|
||||
|
||||
* If `name` begins with `--`, throw an error.
|
||||
|
||||
## Deprecation Process
|
||||
|
||||
During the deprecation period, instead of throwing errors as described in [the
|
||||
semantics section] above, emit a deprecation warning named `css-function-mixin`.
|
||||
|
||||
[the semantics section]: #semantics
|
50
js-api-doc/deprecations.d.ts
vendored
50
js-api-doc/deprecations.d.ts
vendored
@ -5,22 +5,25 @@
|
||||
* `fatalDeprecations`, `futureDeprecations`, or `silenceDeprecations`.
|
||||
*/
|
||||
export interface Deprecations {
|
||||
// START AUTOGENERATED LIST
|
||||
// Checksum: eb5e3889156f5ed12e119f11786f06f91a5f05c2
|
||||
|
||||
/**
|
||||
* Deprecation for passing a string to `call` instead of using `get-function`.
|
||||
* Deprecation for passing a string directly to meta.call().
|
||||
*
|
||||
* This deprecation has been active in all versions of Dart Sass.
|
||||
* This deprecation was active in the first version of Dart Sass.
|
||||
*/
|
||||
'call-string': Deprecation<'call-string'>;
|
||||
|
||||
/**
|
||||
* Deprecation for `@elseif`.
|
||||
* Deprecation for @elseif.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.3.2.
|
||||
*/
|
||||
elseif: Deprecation<'elseif'>;
|
||||
|
||||
/**
|
||||
* Deprecation for parsing `@-moz-document`.
|
||||
* Deprecation for @-moz-document.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.7.2.
|
||||
*/
|
||||
@ -29,27 +32,26 @@ export interface Deprecations {
|
||||
/**
|
||||
* Deprecation for imports using relative canonical URLs.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.17.2.
|
||||
* This deprecation became active in Dart Sass 1.14.2.
|
||||
*/
|
||||
'relative-canonical': Deprecation<'relative-canonical'>;
|
||||
|
||||
/**
|
||||
* Deprecation for declaring new variables with `!global`.
|
||||
* Deprecation for declaring new variables with !global.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.17.2.
|
||||
*/
|
||||
'new-global': Deprecation<'new-global'>;
|
||||
|
||||
/**
|
||||
* Deprecation for using color module functions in place of plain CSS
|
||||
* functions.
|
||||
* Deprecation for using color module functions in place of plain CSS functions.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.23.0.
|
||||
*/
|
||||
'color-module-compat': Deprecation<'color-module-compat'>;
|
||||
|
||||
/**
|
||||
* Deprecation for treating `/` as division.
|
||||
* Deprecation for / operator for division.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.33.0.
|
||||
*/
|
||||
@ -63,22 +65,21 @@ export interface Deprecations {
|
||||
'bogus-combinators': Deprecation<'bogus-combinators'>;
|
||||
|
||||
/**
|
||||
* Deprecation for ambiguous `+` and `-` operators.
|
||||
* Deprecation for ambiguous + and - operators.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.55.0.
|
||||
*/
|
||||
'strict-unary': Deprecation<'strict-unary'>;
|
||||
|
||||
/**
|
||||
* Deprecation for passing invalid units to certain built-in functions.
|
||||
* Deprecation for passing invalid units to built-in functions.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.56.0.
|
||||
*/
|
||||
'function-units': Deprecation<'function-units'>;
|
||||
|
||||
/**
|
||||
* Deprecation for using `!default` or `!global` multiple times for one
|
||||
* variable.
|
||||
* Deprecation for using !default or !global multiple times for one variable.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.62.0.
|
||||
*/
|
||||
@ -92,42 +93,49 @@ export interface Deprecations {
|
||||
'null-alpha': Deprecation<'null-alpha'>;
|
||||
|
||||
/**
|
||||
* Deprecation for passing percentages to the Sass `abs()` function.
|
||||
* Deprecation for passing percentages to the Sass abs() function.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.65.0.
|
||||
*/
|
||||
'abs-percent': Deprecation<'abs-percent'>;
|
||||
|
||||
/**
|
||||
* Deprecation for using the current working directory as an implicit load
|
||||
* path.
|
||||
* Deprecation for using the current working directory as an implicit load path.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.73.0.
|
||||
*/
|
||||
'fs-importer-cwd': Deprecation<'fs-importer-cwd'>;
|
||||
|
||||
/**
|
||||
* Deprecation for certain uses of built-in `sass:color` functions.
|
||||
* Deprecation for function and mixin names beginning with --.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.76.0.
|
||||
*/
|
||||
'css-function-mixin': Deprecation<'css-function-mixin'>;
|
||||
|
||||
/**
|
||||
* Deprecation for certain uses of built-in sass:color functions.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.78.0.
|
||||
*/
|
||||
'color-4-api': Deprecation<'color-4-api'>;
|
||||
|
||||
/**
|
||||
* Deprecation for using global color functions instead of loading them from
|
||||
* `sass:color`.
|
||||
* Deprecation for using global color functions instead of sass:color.
|
||||
*
|
||||
* This deprecation became active in Dart Sass 1.76.0.
|
||||
* This deprecation became active in Dart Sass 1.78.0.
|
||||
*/
|
||||
'color-functions': Deprecation<'color-functions'>;
|
||||
|
||||
/**
|
||||
* Deprecation for `@import` rules.
|
||||
* Deprecation for @import rules.
|
||||
*
|
||||
* This deprecation is not yet active, but will be soon.
|
||||
*/
|
||||
import: Deprecation<'import'>;
|
||||
|
||||
// END AUTOGENERATED LIST
|
||||
|
||||
/**
|
||||
* Used for any user-emitted deprecation warnings.
|
||||
*/
|
||||
|
107
package-lock.json
generated
107
package-lock.json
generated
@ -8,6 +8,7 @@
|
||||
"dependencies": {
|
||||
"@types/diff": "^5.0.1",
|
||||
"@types/glob": "^7.1.4",
|
||||
"@types/js-yaml": "^4.0.3",
|
||||
"@types/marked": "^4.0.8",
|
||||
"@types/node": "^14.11.2",
|
||||
"@types/prettier": "^2.4.1",
|
||||
@ -17,6 +18,7 @@
|
||||
"gts": "^3.1.0",
|
||||
"immutable": "^4.0.0",
|
||||
"indent-string": "^4.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"markdown-link-check": "3.11.1",
|
||||
"markdown-toc": "^1.2.0",
|
||||
"markdownlint-cli2": "^0.8.1",
|
||||
@ -171,6 +173,18 @@
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
|
||||
@ -326,6 +340,11 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/js-yaml": {
|
||||
"version": "4.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
|
||||
"integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg=="
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
|
||||
@ -1388,6 +1407,18 @@
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
|
||||
@ -1814,6 +1845,18 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/gray-matter/node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/gts": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/gts/-/gts-3.1.1.tgz",
|
||||
@ -2210,17 +2253,21 @@
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/js-yaml/node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||
},
|
||||
"node_modules/json-parse-even-better-errors": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
||||
@ -4311,6 +4358,15 @@
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4435,6 +4491,11 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/js-yaml": {
|
||||
"version": "4.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
|
||||
"integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg=="
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
|
||||
@ -5065,6 +5126,15 @@
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -5473,6 +5543,17 @@
|
||||
"extend-shallow": "^2.0.1",
|
||||
"js-yaml": "^3.8.1",
|
||||
"toml": "^2.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"gts": {
|
||||
@ -5761,12 +5842,18 @@
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"json-parse-even-better-errors": {
|
||||
|
@ -13,12 +13,14 @@
|
||||
"toc-check": "npx ts-node test/toc-check.ts",
|
||||
"update-toc": "npx ts-node tool/update-toc.ts",
|
||||
"js-api-doc-check": "npm run tangle && npx ts-node test/js-api-doc-check.ts",
|
||||
"deprecations-check": "npx ts-node test/deprecations-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",
|
||||
"sync-deprecations": "npx ts-node tool/sync-deprecations.ts",
|
||||
"markdownlint": "npx markdownlint-cli2 '**/*.md' '*.md' --ignore 'node_modules/**'",
|
||||
"fix": "npm run update-toc && npm run markdownlint -- --fix && 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"
|
||||
"fix": "npm run sync-deprecations && npm run update-toc && npm run markdownlint -- --fix && npm run tangle && gts fix && npm run untangle",
|
||||
"test": "npm run deprecations-check && 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",
|
||||
@ -41,6 +43,7 @@
|
||||
"ts-dedent": "^2.2.0",
|
||||
"ts-node": "^10.2.1",
|
||||
"typedoc": "^0.24.7",
|
||||
"typescript": "^5.0.4"
|
||||
"typescript": "^5.0.4",
|
||||
"yaml": "^2.2.1"
|
||||
}
|
||||
}
|
||||
|
146
proposal/interleaved-declarations.md
Normal file
146
proposal/interleaved-declarations.md
Normal file
@ -0,0 +1,146 @@
|
||||
# Interleaved Declarations: Draft 1
|
||||
|
||||
*([Issue](https://github.com/sass/sass/issues/3846))*
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Background](#background)
|
||||
* [Summary](#summary)
|
||||
* [Definitions](#definitions)
|
||||
* [Current Style Rule](#current-style-rule)
|
||||
* [Current Keyframe Block](#current-keyframe-block)
|
||||
* [Declarations](#declarations)
|
||||
* [Semantics](#semantics)
|
||||
* [Unknown At-Rules](#unknown-at-rules)
|
||||
* [Semantics](#semantics-1)
|
||||
* [Deprecation Process](#deprecation-process)
|
||||
|
||||
## Background
|
||||
|
||||
> This section is non-normative.
|
||||
|
||||
Historically, Sass has hoisted declarations that appear after nested rules into
|
||||
the original style rule. Although this doesn't match the logical ordering of the
|
||||
source document, it *does* avoid duplicating the style rule (and any other
|
||||
nested rules) for each set of interleaved properties.
|
||||
|
||||
Many years after this decision was made, the [CSS Nesting Module] was published
|
||||
by the W3C, adding native support for nesting rules within style rules using
|
||||
essentially the same syntax as Sass. Although initially its semantics for
|
||||
interleaved declarations were the same as Sass's, [a later update] (four days
|
||||
ago at time of writing) changed it to preserve the logical ordering of
|
||||
interleaved declarations.
|
||||
|
||||
[CSS Nesting Module]: https://drafts.csswg.org/css-nesting/
|
||||
[a later update]: https://github.com/w3c/csswg-drafts/commit/e5547b96f5de6fb5a68d050f42d562c448b99d0b
|
||||
|
||||
## Summary
|
||||
|
||||
> This section is non-normative.
|
||||
|
||||
This proposal changes the behavior of declarations that appear after nested
|
||||
rules. Instead of being hoisted to the beginning of the parent rule, they will
|
||||
now be placed in their original logical order, duplicating the parent selector.
|
||||
|
||||
That is, the following Sass:
|
||||
|
||||
```scss
|
||||
.a {
|
||||
color: red;
|
||||
@media screen {color: blue}
|
||||
color: green;
|
||||
}
|
||||
```
|
||||
|
||||
will now compile to this CSS:
|
||||
|
||||
```scss
|
||||
.a {
|
||||
color: red;
|
||||
}
|
||||
|
||||
@media screen {
|
||||
.a {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
|
||||
.a {
|
||||
color: green;
|
||||
}
|
||||
```
|
||||
|
||||
## Definitions
|
||||
|
||||
### Current Style Rule
|
||||
|
||||
Change the definition of the [current style rule][old] to:
|
||||
|
||||
[old]: ../spec/style-rules.md#current-style-rule
|
||||
|
||||
> Differences are highlighted in bold.
|
||||
|
||||
The *current style rule* is the CSS style rule that was created by the innermost
|
||||
[execution of a style rule], `@media` rule, `@supports` rule, unknown at-rule.
|
||||
**This may be overridden by the [execution of a declaration].**
|
||||
|
||||
[execution of a style rule]: ../spec/style-rules.md#semantics
|
||||
[execution of a declaration]: #semantics
|
||||
|
||||
### Current Keyframe Block
|
||||
|
||||
Change the definition of the [current keyframe block][old keyframe] to:
|
||||
|
||||
[old keyframe]: ../spec/style-rules.md#current-keyframe-block
|
||||
|
||||
> Differences are highlighted in bold.
|
||||
|
||||
The *current keyframe block* is the CSS keyframe block that was created by the
|
||||
innermost [execution of a style rule]. **This may be overridden by the
|
||||
[execution of a declaration].**
|
||||
|
||||
## Declarations
|
||||
|
||||
### Semantics
|
||||
|
||||
Add the following to the semantics for [executing a declaration] `declaration`
|
||||
before "Append `css` to `parent`":
|
||||
|
||||
[executing a declaration]: ../spec/declarations.md#semantics
|
||||
|
||||
* If `parent` isn't the last statement in its parent:
|
||||
|
||||
* Let `copy` by a copy of `parent` without any children.
|
||||
|
||||
* Append `copy` to `parent`'s parent.
|
||||
|
||||
* Set the [current style rule], [keyframe block], or at-rule (according to
|
||||
`copy`'s type) to `copy`, for the remaining duration of its previous value.
|
||||
|
||||
* Set `parent` to `copy`.
|
||||
|
||||
[current style rule]: #current-style-rule
|
||||
[keyframe block]: #current-keyframe-block
|
||||
|
||||
## Unknown At-Rules
|
||||
|
||||
### Semantics
|
||||
|
||||
Add the following to the semantics for executing an unknown at-rule `rule` after
|
||||
"If `rule`'s name is 'font-face', or if its unprefixed name is 'keyframes',
|
||||
append `css` to the current module's CSS":
|
||||
|
||||
* If `rule`'s name is case-insensitively equal to "nest", append `css` to
|
||||
`parent`.
|
||||
|
||||
## Deprecation Process
|
||||
|
||||
This proposal's change to the semantics of interleaved declarations is
|
||||
backwards-incompatible. Before changing to the new semantics, an implementation
|
||||
should have a period of deprecation in which it emits a deprecation warning for
|
||||
a declaration whose `parent` is not the last statement in [the current module]'s
|
||||
CSS without changing the existing behavior.
|
||||
|
||||
> Authors can move interleaved declarations before any nested rules to preserve
|
||||
> existing behavior, or nest them in `& { ... }` style rules to anticipate the
|
||||
> new behavior.
|
@ -160,7 +160,13 @@ that includes CSS for *all* modules transitively used or forwarded by
|
||||
|
||||
* Let `selector` be `extend(rule's selector, domestic's extensions)`.
|
||||
|
||||
* Let `selector-lists` be an empty set of selector lists.
|
||||
* Remove from `selector` any [complex selectors] containing a placeholder
|
||||
selector that begins with `-` or `_` from `css`'s selector.
|
||||
|
||||
* If `selector` is empty, move on to the next `rule`.
|
||||
|
||||
* Let `selector-lists` be a set of selector lists containing only
|
||||
`selector`.
|
||||
|
||||
* For each module `foreign` in `downstream`:
|
||||
|
||||
@ -171,7 +177,7 @@ that includes CSS for *all* modules transitively used or forwarded by
|
||||
> means that `foreign`'s own extensions will already have been resolved
|
||||
> by the time we start working on modules upstream of it.
|
||||
|
||||
* Add `selector` to `selector-lists`.
|
||||
* Add `extended-selector` to `selector-lists`.
|
||||
|
||||
* Set `new-selectors[rule]` to a selector that matches the union of all
|
||||
elements matched by selectors in `selector-lists`. This selector must obey
|
||||
@ -188,6 +194,12 @@ that includes CSS for *all* modules transitively used or forwarded by
|
||||
> `domestic`'s extensions don't count as "original", and may be optimized
|
||||
> away.
|
||||
|
||||
If none of the selectors in `selector-lists` match any elements, add
|
||||
nothing to `new-selectors`.
|
||||
|
||||
> This may occur if `selector-lists` contains placeholder selectors that
|
||||
> haven't been extended.
|
||||
|
||||
* For every extension `extension` whose extender appears in `rule`'s
|
||||
selector:
|
||||
|
||||
@ -203,7 +215,13 @@ that includes CSS for *all* modules transitively used or forwarded by
|
||||
|
||||
* If `domestic` has already been traversed, do nothing.
|
||||
|
||||
* Otherwise, traverse every module in `domestic`'s dependencies.
|
||||
* For each module `upstream` in `domestic`'s dependencies:
|
||||
|
||||
* For each unmarked comment in `domestic`'s CSS, if that comment originally
|
||||
appeared before the `@use` or `@forward` rule that loaded `upstream`, add
|
||||
a copy of that comment to `css` and then mark it.
|
||||
|
||||
* Traverse `upstream`.
|
||||
|
||||
> Because this traverses modules depth-first, it emits CSS in reverse
|
||||
> topological order.
|
||||
@ -212,22 +230,30 @@ that includes CSS for *all* modules transitively used or forwarded by
|
||||
statements in `domestic`'s CSS tree that contains only comments and
|
||||
`@import` rules *and* that ends with an `@import` rule.
|
||||
|
||||
* Insert a copy of `initial-imports` in `css` after the last `@import` rule, or
|
||||
at the beginning of `css` if it doesn't contain any `@import` rules.
|
||||
* Insert a copy of `initial-imports` in `css` after the longest initial
|
||||
subsequence of comments and `@import` rules in `css`.
|
||||
|
||||
> If there are no comments or `@import` rules in `css`, this initial
|
||||
> subsequence is empty and `initial-imports` is inserted at the beginning of
|
||||
> `css`.
|
||||
|
||||
* For each top-level statement `statement` in `domestic`'s CSS tree after
|
||||
`initial-imports`:
|
||||
|
||||
* If `statement` is an `@import` rule, insert a copy of `statement` in `css`
|
||||
after the last `@import` rule, or at the beginning of `css` if it doesn't
|
||||
contain any `@import` rules.
|
||||
* If `statement` is a marked comment, ignore it.
|
||||
|
||||
* Otherwise, add a copy of `statement` to the end of `css`, with any style
|
||||
rules' selectors replaced with the corresponding selectors in
|
||||
`new-selectors`.
|
||||
`new-selectors`. Omit any style rules that don't have corresponding
|
||||
selectors in `new-selectors`.
|
||||
|
||||
> This will omit style rules that contain un-extended placeholder
|
||||
> selectors.
|
||||
|
||||
* Return `css`.
|
||||
|
||||
[complex selectors]: https://drafts.csswg.org/selectors-4/#complex
|
||||
|
||||
### Extending a Selector
|
||||
|
||||
This algorithm takes a selector list `extendee`, a simple selector `target`, and
|
||||
|
@ -22,6 +22,8 @@ To execute a `@function` rule `rule`:
|
||||
|
||||
* Let `name` be the value of `rule`'s `Identifier`.
|
||||
|
||||
* If `name` begins with `--`, throw an error.
|
||||
|
||||
* If `name` is `calc`, `element`, `expression`, `url`, `and`, `or`, or `not`, or
|
||||
if `name` has a [vendor prefix] and the unprefixed identifier is one of those
|
||||
strings, throw an error.
|
||||
|
@ -109,8 +109,8 @@ To execute an `@import` rule `rule`:
|
||||
> `ImportMedia` is a subset of the valid syntax of `MediaQueryList`, so
|
||||
> this will always work.
|
||||
|
||||
* Add an `@import` with the evaluated modifiers to [the current module]'s
|
||||
CSS AST.
|
||||
* Add an `@import` with the evaluated modifiers to [the current module]'s CSS
|
||||
AST after the longest initial subsequence of comments and `@import` rules.
|
||||
|
||||
* Otherwise, let `file` be the result of [loading the file][] with
|
||||
`argument`'s URL string. If this returns null, throw an error.
|
||||
|
@ -31,6 +31,8 @@ To execute a `@mixin` rule `rule`:
|
||||
|
||||
* Let `name` be the value of `rule`'s `Identifier`.
|
||||
|
||||
* If `name` begins with `--`, throw an error.
|
||||
|
||||
* Let `parent` be the [current scope].
|
||||
|
||||
[current scope]: ../spec.md#scope
|
||||
|
@ -1,11 +1,13 @@
|
||||
# Unknown At-Rules
|
||||
|
||||
In order to be flexible in its compatibility with future additions to CSS, Sass
|
||||
supports *all* at-rule names with a default syntax that's highly liberal in the
|
||||
structures it allows. It uses the following grammar:
|
||||
## Syntax
|
||||
|
||||
> In order to be flexible in its compatibility with future additions to CSS, Sass
|
||||
> supports *all* at-rule names with a default syntax that's highly liberal in the
|
||||
> structures it allows.
|
||||
|
||||
<x><pre>
|
||||
**UnknownAtRule** ::= '@' [InterpolatedIdentifier][] InterpolatedValue?
|
||||
**UnknownAtRule** ::= '@' [InterpolatedIdentifier] InterpolatedValue?
|
||||
  ('{' Statements '}')?
|
||||
</pre></x>
|
||||
|
||||
@ -14,11 +16,50 @@ structures it allows. It uses the following grammar:
|
||||
No whitespace is allowed after `@`. As with all statements, an `UnknownAtRule`
|
||||
without a block must be separated from other statements with a semicolon.
|
||||
|
||||
When an at-rule is executed, its name is evaluated to produce an unquoted string
|
||||
which is used as the name of the generated at-rule. Then that generated name is
|
||||
checked to see if it's an at-rule that has special runtime handling.
|
||||
## Semantics
|
||||
|
||||
> Note that only `@keyframes` has special runtime handling that's triggered
|
||||
> here. Other CSS at-rules that Sass handles specially, like `@media` or
|
||||
> `@supports`, are detected at parse-time. This means that `@m#{ed}ia` will be
|
||||
> treated as an unknown at-rule rather than a media rule.
|
||||
To execute an unknown at-rule `rule`:
|
||||
|
||||
* Let `name` be the result of evaluating `rule`'s `InterpolatedIdentifier`.
|
||||
|
||||
* Let `value` be the result of evaluating `rule`'s `InterpolatedValue`, if it
|
||||
exists.
|
||||
|
||||
* Let `css` be a CSS unknown at-rule with name `name`, value `value`, and with
|
||||
an empty list of children if `rule` has `Statements`.
|
||||
|
||||
* Let `parent` be the [current style rule], [keyframe block], or at-rule if one
|
||||
exists; or the innermost if multiple exist.
|
||||
|
||||
[current style rule]: ../style-rules.md#current-style-rule
|
||||
[keyframe block]: ../style-rules.md#current-style-rule
|
||||
|
||||
* If `rule` has `Statements`:
|
||||
|
||||
* If `parent` isn't set, append `css` to [the current module]'s CSS.
|
||||
|
||||
* Otherwise, if `parent` is a style rule:
|
||||
|
||||
* If `rule`'s name is "font-face", or if its [unprefixed] name is
|
||||
"keyframes", append `css` to [the current module]'s CSS.
|
||||
|
||||
* Otherwise:
|
||||
|
||||
* Append `css` to `parent`'s parent.
|
||||
|
||||
* Append a copy of `parent` without any children to `css`.
|
||||
|
||||
> This copy is now the [current style rule] until `rule` is done being
|
||||
> executed.
|
||||
|
||||
* Otherwise, append `css` to `parent`.
|
||||
|
||||
* Evaluate each child in `rule`'s `Statement`s.
|
||||
|
||||
* Otherwise:
|
||||
|
||||
* Append `css` to `parent` if it's set, or to [the current module]'s CSS
|
||||
otherwise.
|
||||
|
||||
[the current module]: ../spec.md#current-module
|
||||
[unprefixed]: ../syntax.md#vendor-prefix
|
||||
|
79
spec/declarations.md
Normal file
79
spec/declarations.md
Normal file
@ -0,0 +1,79 @@
|
||||
## Declarations
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Syntax](#syntax)
|
||||
* [Definitions](#definitions)
|
||||
* [Current Declaration Name](#current-declaration-name)
|
||||
* [Semantics](#semantics)
|
||||
|
||||
## Syntax
|
||||
|
||||
<x><pre>
|
||||
**Declaration** ::= StandardDeclaration | CustomDeclaration
|
||||
**StandardDeclaration** ::= [InterpolatedIdentifier]¹ ':' (Value | Value? '{' Statements '}')
|
||||
**CustomDeclaration** ::= [InterpolatedIdentifier]² ':' InterpolatedDeclarationValue
|
||||
</pre></x>
|
||||
|
||||
1. This may not begin with "--".
|
||||
2. This *must* begin with "--".
|
||||
|
||||
[InterpolatedIdentifier]: syntax.md#interpolatedidentifier
|
||||
|
||||
## Definitions
|
||||
|
||||
### Current Declaration Name
|
||||
|
||||
The *current declaration name* is the innermost value declared as such when
|
||||
[executing a declaration].
|
||||
|
||||
[executing a declaration]: #semantics
|
||||
|
||||
### Semantics
|
||||
|
||||
To execute a declaration `declaration`:
|
||||
|
||||
* Let `parent-name` be the [current declaration name], if one exists.
|
||||
|
||||
[current declaration name]: #current-declaration-name
|
||||
|
||||
* If `name` is set and `declaration` is a [`CustomDeclaration`], throw an error.
|
||||
|
||||
[`CustomDeclaration`]: #syntax
|
||||
|
||||
* Let `name` be the result of evaluating the all interpolation in
|
||||
`declaration`'s name.
|
||||
|
||||
* If `parent-name` exists, set `name` to `parent-name + "-" + name`.
|
||||
|
||||
* Declare `name` as the [current declaration name] for the duration of executing
|
||||
`declaration`.
|
||||
|
||||
* If `declaration` has a `Value`:
|
||||
|
||||
* Let `value` be the result of evaluating that `Value`.
|
||||
|
||||
* Otherwise, if `declaration` is a `CustomDeclaration`:
|
||||
|
||||
* Let `value` be an unquoted string whose value is the result of evaluating
|
||||
`declaration`'s `InterpolatedDeclarationValue`.
|
||||
|
||||
* If `value` is empty, throw an error.
|
||||
|
||||
> Note that `value` being only whitespace is allowed, including `--foo: ;`.
|
||||
|
||||
* Let `parent` be the [current style rule], [keyframe block], or at-rule; or
|
||||
the innermost if multiple exist.
|
||||
|
||||
[current style rule]: style-rules.md#current-style-rule
|
||||
[keyframe block]: style-rules.md#current-style-rule
|
||||
|
||||
> Parsing guarantees that a declaration will have at least one parent.
|
||||
|
||||
* If `value` is set, and it's neither null nor an empty unquoted string:
|
||||
|
||||
* Let `css` be a CSS declaration with name `name` and value `value`.
|
||||
|
||||
* Append `css` to `parent`.
|
||||
|
||||
* Evaluate each child in `declaration`'s `Statements` if it exists.
|
124
spec/deprecations.yaml
Normal file
124
spec/deprecations.yaml
Normal file
@ -0,0 +1,124 @@
|
||||
# This file specifies the status of all of Sass's deprecations in a
|
||||
# machine-readable way. After updating this file, run
|
||||
# `npm run sync-deprecations` to update the JS API spec and docs in this repo.
|
||||
#
|
||||
# The Dart Sass compiler and the Node embedded host use this file to generate
|
||||
# their lists of deprecations. Other embedded hosts should do the same if they
|
||||
# expose the list of deprecations in their APIs.
|
||||
#
|
||||
# example-id:
|
||||
# description: One-line description of this deprecation.
|
||||
# dart-sass:
|
||||
# # Status of this deprecation in Dart Sass
|
||||
# status: future | active | obsolete
|
||||
# # Dart Sass version that deprecated this feature.
|
||||
# deprecated: 1.0.0
|
||||
# # Dart Sass version that obsoleted this deprecation.
|
||||
# obsolete: 2.0.0
|
||||
|
||||
call-string:
|
||||
description: Passing a string directly to meta.call().
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 0.0.0
|
||||
|
||||
elseif:
|
||||
description: "@elseif."
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.3.2
|
||||
|
||||
moz-document:
|
||||
description: "@-moz-document."
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.7.2
|
||||
|
||||
relative-canonical:
|
||||
description: Imports using relative canonical URLs.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.14.2
|
||||
|
||||
new-global:
|
||||
description: Declaring new variables with !global.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.17.2
|
||||
|
||||
color-module-compat:
|
||||
description: Using color module functions in place of plain CSS functions.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.23.0
|
||||
|
||||
slash-div:
|
||||
description: / operator for division.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.33.0
|
||||
|
||||
bogus-combinators:
|
||||
description: Leading, trailing, and repeated combinators.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.54.0
|
||||
|
||||
strict-unary:
|
||||
description: Ambiguous + and - operators.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.55.0
|
||||
|
||||
function-units:
|
||||
description: Passing invalid units to built-in functions.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.56.0
|
||||
|
||||
duplicate-var-flags:
|
||||
description: Using !default or !global multiple times for one variable.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.62.0
|
||||
|
||||
null-alpha:
|
||||
description: Passing null as alpha in the $PLATFORM API.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.62.3
|
||||
|
||||
abs-percent:
|
||||
description: Passing percentages to the Sass abs() function.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.65.0
|
||||
|
||||
fs-importer-cwd:
|
||||
description: Using the current working directory as an implicit load path.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.73.0
|
||||
|
||||
css-function-mixin:
|
||||
description: Function and mixin names beginning with --.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.76.0
|
||||
|
||||
color-4-api:
|
||||
description: Certain uses of built-in sass:color functions.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.78.0
|
||||
|
||||
color-functions:
|
||||
description: Using global color functions instead of sass:color.
|
||||
dart-sass:
|
||||
status: active
|
||||
deprecated: 1.78.0
|
||||
|
||||
import:
|
||||
description: "@import rules."
|
||||
dart-sass:
|
||||
status: future
|
@ -192,6 +192,15 @@ message InboundMessage {
|
||||
// `null` instead.
|
||||
string error = 3;
|
||||
}
|
||||
|
||||
// Whether `containing_url` in `CanonicalizeRequest` is unused.
|
||||
//
|
||||
// The compiler can cache the `CanonicalizeResponse` if the `containing_url`
|
||||
// is unused.
|
||||
//
|
||||
// The default value is `false`, thus when the value is not set by the host,
|
||||
// the `CanonicalizeResponse` will not be cached by the compiler.
|
||||
bool containing_url_unused = 4;
|
||||
}
|
||||
|
||||
// A response indicating the result of importing a canonical URL.
|
||||
@ -257,6 +266,15 @@ message InboundMessage {
|
||||
// An error message explaining why the URL could not be loaded.
|
||||
string error = 3;
|
||||
}
|
||||
|
||||
// Whether `containing_url` in `FileImportRequest` is unused.
|
||||
//
|
||||
// The compiler can cache the `FileImportResponse` if the `containing_url`
|
||||
// is unused.
|
||||
//
|
||||
// The default value is `false`, thus when the value is not set by the host,
|
||||
// the `FileImportResponse` will not be cached by the compiler.
|
||||
bool containing_url_unused = 4;
|
||||
}
|
||||
|
||||
// A response indicating the result of calling a custom Sass function defined
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
### `Deprecations`
|
||||
|
||||
<!-- START AUTOGENERATED LIST -->
|
||||
<!-- Checksum: eb5e3889156f5ed12e119f11786f06f91a5f05c2 -->
|
||||
```ts
|
||||
export interface Deprecations {
|
||||
'call-string': Deprecation<'call-string'>;
|
||||
@ -44,12 +46,14 @@ export interface Deprecations {
|
||||
'null-alpha': Deprecation<'null-alpha'>;
|
||||
'abs-percent': Deprecation<'abs-percent'>;
|
||||
'fs-importer-cwd': Deprecation<'fs-importer-cwd'>;
|
||||
'css-function-mixin': Deprecation<'css-function-mixin'>;
|
||||
'color-4-api': Deprecation<'color-4-api'>;
|
||||
'color-functions': Deprecation<'color-functions'>;
|
||||
import: Deprecation<'import'>;
|
||||
'user-authored': Deprecation<'user-authored', 'user'>;
|
||||
}
|
||||
```
|
||||
<!-- END AUTOGENERATED LIST -->
|
||||
|
||||
### `DeprecationOrId`
|
||||
|
||||
|
@ -156,8 +156,9 @@ Before beginning compilation:
|
||||
|
||||
* 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.
|
||||
* 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:
|
||||
@ -182,6 +183,7 @@ Before beginning compilation:
|
||||
replaced with the result of [simplifying] those calculations.
|
||||
|
||||
[<ident-token>]: https://drafts.csswg.org/css-syntax-3/#ident-token-diagram
|
||||
[underscore-insensitively]: ../modules.md#underscore-insensitive
|
||||
[`SassFunction`]: value/function.d.ts.md
|
||||
[simplifying]: https://github.com/sass/sass/tree/main/spec/types/calculation.md#simplifying-a-calculation
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
* [Package Importers](#package-importers)
|
||||
* [Node Package Importer](#node-package-importer)
|
||||
* [Global Importer List](#global-importer-list)
|
||||
* [Underscore-Insensitive](#underscore-insensitive)
|
||||
* [Basename](#basename)
|
||||
* [Dirname](#dirname)
|
||||
* [Syntax](#syntax)
|
||||
@ -70,7 +71,10 @@ A new *configuration* ID is unique unless otherwise specified.
|
||||
A *module* is a collection of various properties:
|
||||
|
||||
* A set of [members](#member) that contains at most one member of any given type
|
||||
and name.
|
||||
and [underscore-insensitive] name. All lookups in this set are
|
||||
underscore-insensitive unless explicitly specified otherwise.
|
||||
|
||||
[underscore-insensitive]: #underscore-insensitive
|
||||
|
||||
> For example, a module may not have two variables named `$name`, although it
|
||||
> may contain a function and a mixin with the same name or two functions with
|
||||
@ -300,6 +304,16 @@ When the Node Package Importer is invoked with a string named `string`:
|
||||
The *global importer list* is a list of importers that's set for the entire
|
||||
duration of a Sass compilation.
|
||||
|
||||
### Underscore-Insensitive
|
||||
|
||||
If a name comparison is *underscore-insensitive*, it considers the characters
|
||||
U+002D HYPHEN-MINUS and U+005F LOW LINE to be equal to one another.
|
||||
|
||||
> Long ago, Sass only supported underscores as separators for Sass identifiers.
|
||||
> When support for hyphens was added to match CSS, they were made equivalent to
|
||||
> underscores for backwards-compatibility. This insensitivity is generally only
|
||||
> used for Sass member names, not any other identifiers.
|
||||
|
||||
### Basename
|
||||
|
||||
The *basename* of a URL is the final component of that URL's path.
|
||||
|
@ -10,6 +10,8 @@
|
||||
* [Bogus Selector](#bogus-selector)
|
||||
* [Syntax](#syntax)
|
||||
* [`ComplexSelector`](#complexselector)
|
||||
* [Serialization](#serialization)
|
||||
* [Parent Selector](#parent-selector)
|
||||
|
||||
## Definitions
|
||||
|
||||
@ -67,3 +69,12 @@ A selector list is *bogus* if any of its complex selectors are bogus.
|
||||
</pre></x>
|
||||
|
||||
[\<combinator>]: https://drafts.csswg.org/selectors-4/#typedef-combinator
|
||||
|
||||
## Serialization
|
||||
|
||||
### Parent Selector
|
||||
|
||||
To serialize a parent selector, emit the character `&`.
|
||||
|
||||
> A parent selector can only appear in a serialized selector if it was parsed
|
||||
> from plain CSS, which doesn't allow it to have a suffix.
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
* [Definitions](#definitions)
|
||||
* [Current Style Rule](#current-style-rule)
|
||||
* [Current Keyframe Block](#current-keyframe-block)
|
||||
* [Semantics](#semantics)
|
||||
|
||||
## Definitions
|
||||
@ -11,42 +12,77 @@
|
||||
### Current Style Rule
|
||||
|
||||
The *current style rule* is the CSS style rule that was created by the innermost
|
||||
[execution of a style rule](#semantics).
|
||||
[execution of a style rule](#semantics), `@media` rule, `@supports` rule, or
|
||||
unknown at-rule.
|
||||
|
||||
### Current Keyframe Block
|
||||
|
||||
The *current keyframe block* is the CSS keyframe block that was created by the
|
||||
innermost [execution of a style rule](#semantics).
|
||||
|
||||
## Semantics
|
||||
|
||||
To execute a style rule `rule`:
|
||||
|
||||
* Let `selector` be the result of evaluating all interpolation in `rule`'s
|
||||
selector and parsing the result as a selector list.
|
||||
* Let `selector-text` be the result of evaluating all interpolation in `rule`'s
|
||||
selector.
|
||||
|
||||
* If there is a [current style rule](#current-style-rule):
|
||||
* Let `parent` be the [current style rule], at-rule, or keyframe block if one
|
||||
exists, or the innermost if multiple exist.
|
||||
|
||||
* If `selector` contains one or more parent selectors, replace them with the
|
||||
current style rule's selector and set `selector` to the result.
|
||||
[current style rule]: #current-style-rule
|
||||
|
||||
* If `parent` is a keyframe block, throw an error.
|
||||
|
||||
* Otherwise, if `parent` is an unknown at-rule whose name without vendor
|
||||
prefixes is "keyframes":
|
||||
|
||||
* Let `selector` be the result of parsing `selector-text` as a keyframe
|
||||
selector.
|
||||
|
||||
* Append a keyframe block with selector `selector` to `parent`.
|
||||
|
||||
* Evaluate each child of `rule`.
|
||||
|
||||
* Cease evaluating `rule`.
|
||||
|
||||
* Otherwise, if `parent` is a style rule whose stylesheet wasn't [parsed as
|
||||
CSS]:
|
||||
|
||||
[parsed as CSS]: syntax.md#parsing-text-as-css
|
||||
|
||||
> Checking whether `rule`'s stylesheet is CSS ensures that the plain CSS
|
||||
> behavior occurs even when plain CSS is evaluated in a Sass context, such as
|
||||
> through a nested `@import` or a `meta.load-css()` call.
|
||||
|
||||
* If `selector` contains one or more parent selectors and `rule`'s stylesheet
|
||||
wasn't [parsed as CSS], replace those parent selectors with the current
|
||||
style rule's selector and set `selector` to the result.
|
||||
|
||||
* Otherwise, nest `selector` within the current style rule's selector using
|
||||
the [descendant combinator][] and set `selector` to the result.
|
||||
the [descendant combinator] and set `selector` to the result.
|
||||
|
||||
[descendant combinator]: https://www.w3.org/TR/selectors-3/#descendant-combinators
|
||||
|
||||
* Otherwise, if `selector` contains one or more parent selectors, throw an
|
||||
error.
|
||||
* Otherwise, if `selector` contains one or more parent selectors and `rule`'s
|
||||
stylesheet wasn't [parsed as CSS], throw an error.
|
||||
|
||||
* Let `css` be a CSS style rule with selector `selector`.
|
||||
|
||||
* Execute each child `child` of `rule`.
|
||||
* If `parent` is set and its stylesheet was [parsed as CSS], append `css` to
|
||||
`parent`.
|
||||
|
||||
* Otherwise, if there is a current at-rule, append `css` to its children.
|
||||
|
||||
* Otherwise, append `css` to [the current module]'s CSS.
|
||||
|
||||
[the current module]: spec.md#current-module
|
||||
|
||||
* Execute each child of `rule`.
|
||||
|
||||
* If `css` contains any children and `selector` is [bogus], throw an error.
|
||||
|
||||
[bogus]: selectors.md#bogus-selector
|
||||
|
||||
* Remove any [complex selectors][] containing a placeholder selector that
|
||||
begins with `-` or `_` from `css`'s selector.
|
||||
|
||||
[complex selectors]: https://drafts.csswg.org/selectors-4/#complex
|
||||
|
||||
* Unless `css`'s selector is now empty, append `css` to [the current module][]'s
|
||||
* Otherwise, if `css` contains no children, remove it from the current module's
|
||||
CSS.
|
||||
|
||||
[the current module]: spec.md#current-module
|
||||
|
@ -210,9 +210,9 @@ modifications. The following productions should produce errors:
|
||||
|
||||
* A declaration followed by an open curly brace (that is, a nested declaration).
|
||||
|
||||
* A style rule appearing within another style rule.
|
||||
* The parent selector `&` in a declaration value.
|
||||
|
||||
* The parent selector `&`, either in a selector or a declaration value.
|
||||
* A style rule whose selector contains a trailing combinator.
|
||||
|
||||
* Placeholder selectors.
|
||||
|
||||
@ -275,6 +275,11 @@ SCSS:
|
||||
adjacent `/`s in a [`SlashListExpression`] may have no whitespace between
|
||||
them, so `//` is parsed as two slash separators in a slash-separated list.
|
||||
|
||||
* A `ParentSelector` may appear anywhere in a `CompoundSelector`, rather than
|
||||
just as the first `SimpleSelector`.
|
||||
|
||||
* A `ParentSelector` may not have a `suffix`.
|
||||
|
||||
### Consuming an Identifier
|
||||
|
||||
This algorithm consumes input from a stream of [code points][] and returns a
|
||||
|
22
test/deprecations-check.ts
Normal file
22
test/deprecations-check.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import * as crypto from 'crypto';
|
||||
import * as fs from 'fs';
|
||||
|
||||
const yamlFile = 'spec/deprecations.yaml';
|
||||
const specFile = 'spec/js-api/deprecations.d.ts.md';
|
||||
const docFile = 'js-api-doc/deprecations.d.ts';
|
||||
|
||||
(async () => {
|
||||
const yamlText = fs.readFileSync(yamlFile, 'utf8');
|
||||
const specText = fs.readFileSync(specFile, 'utf8');
|
||||
const docText = fs.readFileSync(docFile, 'utf8');
|
||||
|
||||
const checksum = crypto.createHash('sha1').update(yamlText).digest('hex');
|
||||
|
||||
if (
|
||||
!specText.includes(`<!-- Checksum: ${checksum} -->`) ||
|
||||
!docText.includes(`// Checksum: ${checksum}`)
|
||||
) {
|
||||
console.error('Deprecations out-of-sync. Run `npm run sync-deprecations`.');
|
||||
process.exitCode = 1;
|
||||
}
|
||||
})();
|
100
tool/sync-deprecations.ts
Normal file
100
tool/sync-deprecations.ts
Normal file
@ -0,0 +1,100 @@
|
||||
// Updates the JS API spec and docs with the list of deprecations specified
|
||||
// in spec/deprecations.yaml.
|
||||
|
||||
import * as colors from 'colors/safe';
|
||||
import * as crypto from 'crypto';
|
||||
import * as fs from 'fs';
|
||||
import {parse} from 'yaml';
|
||||
|
||||
interface YamlData {
|
||||
[key: string]: {
|
||||
description: string;
|
||||
'dart-sass': {
|
||||
status: 'active' | 'future' | 'obsolete';
|
||||
deprecated?: string;
|
||||
obsolete?: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const yamlFile = 'spec/deprecations.yaml';
|
||||
const specFile = 'spec/js-api/deprecations.d.ts.md';
|
||||
const docFile = 'js-api-doc/deprecations.d.ts';
|
||||
|
||||
const specRegex =
|
||||
/<!-- START AUTOGENERATED LIST -->[\s\S]*?<!-- END AUTOGENERATED LIST -->/m;
|
||||
const docRegex =
|
||||
/\/\/ START AUTOGENERATED LIST[\s\S]*?\/\/ END AUTOGENERATED LIST/m;
|
||||
|
||||
(async () => {
|
||||
const yamlText = fs.readFileSync(yamlFile, 'utf8');
|
||||
const oldSpecText = fs.readFileSync(specFile, 'utf8');
|
||||
const oldDocText = fs.readFileSync(docFile, 'utf8');
|
||||
|
||||
if (!specRegex.test(oldSpecText)) {
|
||||
console.error(
|
||||
`${colors.red(colors.bold('Error:'))} ` +
|
||||
`Cannot find AUTOGENERATED LIST block in ${specFile}`
|
||||
);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
if (!docRegex.test(oldDocText)) {
|
||||
console.error(
|
||||
`${colors.red(colors.bold('Error:'))} ` +
|
||||
`Cannot find AUTOGENERATED LIST block in ${docFile}`
|
||||
);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const deprecations = parse(yamlText) as YamlData;
|
||||
let specList = '';
|
||||
let docList = '';
|
||||
for (const [id, deprecation] of Object.entries(deprecations)) {
|
||||
const key = id.includes('-') ? `'${id}'` : id;
|
||||
specList += ` ${key}: Deprecation<'${id}'>;\n`;
|
||||
const lowercase =
|
||||
deprecation.description.substring(0, 1).toLowerCase() +
|
||||
deprecation.description.substring(1);
|
||||
const dartSass = deprecation['dart-sass'];
|
||||
const activeText = !dartSass.deprecated
|
||||
? 'This deprecation is not yet active, but will be soon.'
|
||||
: dartSass.deprecated === '0.0.0'
|
||||
? 'This deprecation was active in the first version of Dart Sass.'
|
||||
: `This deprecation became active in Dart Sass ${dartSass.deprecated}.`;
|
||||
const obsoleteText = dartSass.obsolete
|
||||
? `\nIt became obsolete in Dart Sass ${dartSass.obsolete}.`
|
||||
: '';
|
||||
docList += ` /**
|
||||
* Deprecation for ${lowercase.replace(/\$PLATFORM/g, 'JS')}
|
||||
*
|
||||
* ${activeText}${obsoleteText}
|
||||
*/
|
||||
${key}: Deprecation<'${id}'>;\n\n`;
|
||||
}
|
||||
const checksum = crypto.createHash('sha1').update(yamlText).digest('hex');
|
||||
|
||||
const newSpecText = oldSpecText.replace(
|
||||
/<!-- START AUTOGENERATED LIST -->[\s\S]*?<!-- END AUTOGENERATED LIST -->/m,
|
||||
`<!-- START AUTOGENERATED LIST -->
|
||||
<!-- Checksum: ${checksum} -->
|
||||
\`\`\`ts
|
||||
export interface Deprecations {
|
||||
${specList} 'user-authored': Deprecation<'user-authored', 'user'>;
|
||||
}
|
||||
\`\`\`
|
||||
<!-- END AUTOGENERATED LIST -->`
|
||||
);
|
||||
|
||||
const newDocText = oldDocText.replace(
|
||||
/\/\/ START AUTOGENERATED LIST[\s\S]*?\/\/ END AUTOGENERATED LIST/m,
|
||||
`// START AUTOGENERATED LIST
|
||||
// Checksum: ${checksum}
|
||||
|
||||
${docList} // END AUTOGENERATED LIST`
|
||||
);
|
||||
|
||||
fs.writeFileSync(specFile, newSpecText);
|
||||
fs.writeFileSync(docFile, newDocText);
|
||||
})();
|
Loading…
Reference in New Issue
Block a user