Skip to content

Commit

Permalink
Merge branch 'main' into color-4-formats
Browse files Browse the repository at this point in the history
* main: (41 commits)
  [Function Units] Add a proposal (#3375)
  Mark accepted: Random with Units Proposal (#3377)
  Note configurations are shared across all files in a module by instance given a uniquely-identifying opaque ID (#3357)
  Clarify that compile and compileString accept optional options (#3373)
  Proposal: Define random() behavior for numbers with units (#3361)
  [Media Logic] Apply changes to the spec (#3365)
  [Reconfigurable Modules] Apply the proposal to the spec (#3364)
  [Media Logic] Mark as accepted (#3360)
  [Bogus Combinators] Update the specification (#3362)
  Update documentation for charset option (#3358)
  Define "useless selectors" in Phase 1
  Support complex selectors composed of only a single combinator
  Throw an error for an @extend rule with a bogus extender or target
  Don't throw an error for bogus style rules with no children
  Only omit style rules if _all_ of their complex selectors are bogus
  Allow bogus selectors in `selector.append()`
  Support single leading combinators in Phase 1
  Clarify the definition of bogus selectors in Phase 2
  Update the timeline for the deprecation and removal of `@import` (#3354)
  Mark the bogus combinators proposal as accepted
  ...
  • Loading branch information
mirisuzanne committed Aug 26, 2022
2 parents e81c0fc + 8228f43 commit 0223a56
Show file tree
Hide file tree
Showing 35 changed files with 1,447 additions and 113 deletions.
20 changes: 20 additions & 0 deletions LICENSE
@@ -0,0 +1,20 @@
Copyright (c) 2022, Google Inc.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 changes: 34 additions & 0 deletions accepted/bogus-combinators.changes.md
@@ -0,0 +1,34 @@
## Draft 3

* In Phase 1:

* Clarify the definition of bogus selectors.

* Only omit style rules if _all_ of their complex selectors are bogus.

* Expand the set of selectors that are treated by the extend algorithm as
matching nothing to include bogus pseudo selectors, since these can never be
transformed into anything useful.

* In Phase 2:

* Don't throw an error for style rules that contain no children, since this
would break nesting.

* Throw an error for an `@extend` rule with a bogus extender.

* Support single leading combinators.

* Support complex selectors composed of only a single combinator.

* Allow bogus selectors in `selector.append()`.

## Draft 2

* Allow leading combinators in `:has()`.

* Replace our custom `Combinator` production with the CSS spec's `<combinator>`.

## Draft 1

* Initial draft.
257 changes: 257 additions & 0 deletions accepted/bogus-combinators.md
@@ -0,0 +1,257 @@
# Bogus Combinators: Draft 3

*([Issue](https://github.com/sass/sass/issues/3340), [Changelog](bogus-combinators.changes.md))*

This proposal increases the strictness with which Sass parses and resolves
non-standard ("bogus") uses of selector combinators. In particular, it forbids
the use of multiple combinators in a row (such as `div + ~ a`) and limits the
use of leading combinators (such as `> a`) and trailing combinators (such as `a
>`) to selector nesting.
## Table of Contents

* [Background](#background)
* [Summary](#summary)
* [Phase 1: Deprecation](#phase-1-deprecation)
* [Phase 2: Removal](#phase-2-removal)
* [Definitions](#definitions)
* [Visible Combinator](#visible-combinator)
* [Complex Selector](#complex-selector)
* [Complex Selector Component](#complex-selector-component)
* [Trailing Combinator](#trailing-combinator)
* [Bogus Selector](#bogus-selector)
* [Syntax](#syntax)
* [`ComplexSelector`](#complexselector)
* [Semantics](#semantics)
* [Evaluating a Style Rule](#evaluating-a-style-rule)
* [Executing an Extend Rule](#executing-an-extend-rule)
* [Functions](#functions)
* [Deprecation Process](#deprecation-process)
* [Phase 1](#phase-1)
* [Phase 2](#phase-2)

## Background

> This section is non-normative.
Currently, Sass is very liberal when it comes to where explicit selector
combinators can be written—much more so than CSS itself. It allows:

* Multiple combinators between compound selectors (`a > + b`).
* Combinators at the beginning of selectors (`> a`).
* Combinators at the end of selectors (`a >`).

The latter two are useful when nesting style rules, but the former has no known
use at all. Historically, we've said that we support these because they enable
some browser hacks, but this seems to be purely hypothetical: [browserhacks.com]
is the most comprehensive source of hacks I've found, and it doesn't list any
hacks that are enabled by this support, even among its "legacy hacks".

[browserhacks.com]: http://browserhacks.com

In addition, supporting these selectors imposes substantial complexity on Sass
implementations. They [cause bugs] and make the data model more complex than it
needs to be. This in turn makes bugs like [sass/sass#1807] that don't involve
non-standard combinators more difficult to resolve.

[cause bugs]: https://github.com/sass/dart-sass/issues/1053
[sass/sass#1807]: https://github.com/sass/sass/issues/1807

## Summary

> This section is non-normative.
We'll move towards forbidding these combinators in two phases.

### Phase 1: Deprecation

In the first phase, we'll issue deprecation messages for all forbidden cases,
but only change behavior in cases where Sass was already producing invalid CSS
anyway. In particular:

* Once nesting and extensions have been resolved, if any of a style rule's
selectors contains a leading, trailing, or multiple combinator after nesting
and extensions are resolved, omit that style rule from the generated CSS and
emit a deprecation warning.

* If a selector with a leading or trailing combinator is used with any
extend-related infrastructure, emit a deprecation warning but *don't* change
the behavior unless the resolved selector still has a bogus combinator, as
above.

* If a selector with a doubled combinator is used with any extend-related
infrastructure, emit a deprecation warning and treat that selector as though
it matches no elements.

This will be sufficient to substantially simplify the implementation without
affecting the in-browser behavior of any stylesheets.

### Phase 2: Removal

In the second phase, which for existing implementations will accompany a major
version release, we will emit errors everywhere Phase 1 produced deprecation
warnings. In particular:

* If a style rule's selectors contain leading, trailing, or multiple combinators
after nesting is resolved, emit an error.

* If a selector with a leading, trailing, or multiple combinator is used with
`@extend` (which, given the previous restriction, will only be possible using
extension functions from `sass:selector`), emit an error.

## Definitions

> Most existing definitions being modified here haven't been defined explicitly
> before this document. The old definitions are listed in strikethrough mode to
> clarify the change.
### Visible Combinator

A *visible combinator* is any selector [combinator] other than the [descendant
combinator].

[combinator]: https://drafts.csswg.org/selectors-4/#combinators
[descendant combinator]: https://drafts.csswg.org/selectors-4/#descendant-combinators

### Complex Selector

~~A *complex selector* is a sequence of [visible combinators] (its *leading
combinators*) as well as a sequence of [complex selector components]. Either,
but not both, of these sequences may be empty~~

[visible combinators]: #visible-combinator
[complex selector components]: #complex-selector-components

A *complex selector* is an optional [visible combinator] (its *leading
combinator*) as well as a sequence of [complex selector components]. The
component sequence may be empty only for complex selectors with leading
combinators.

[visible combinator]: #visible-combinator

### Complex Selector Component

~~A *complex selector component* is a compound selector as well as a sequence of
zero or more [visible combinators].~~

A *complex selector component* is a compound selector as well as a single
[combinator].

### Trailing Combinator

A [complex selector]'s *trailing combinator* is its final [complex selector
component]'s combinator if it's not a [descendant combinator]. If it *is* a
descendant combinator, the complex selector doesn't have a trailing combinator.

[complex selector]: #complex-selector
[complex selector component]: #complex-selector-component

### Bogus Selector

A [complex selector] is *bogus* if it has a leading or [trailing combinator], or
if any of the simple selectors it transitively contains is a selector pseudo
with a bogus selector, except that `:has()` may contain complex selectors with
leading combinators.

A selector list is *bogus* if any of its complex selectors are bogus.

[trailing combinator]: #trailing-combinator

## Syntax

### `ComplexSelector`

> Note that the existing productions being modified have not been defined
> explicitly before this document. The old productions are listed in
> strikethrough mode to clarify the change.
This proposal modifies the existing `ComplexSelector` and
`ComplexSelectorComponent` productions to drop support for multiple combinators:

<x><pre>
~~**ComplexSelector** ::= [\<combinator>]* ComplexSelectorComponent+~~
~~&#32; | [\<combinator>]+~~
~~**ComplexSelectorComponent** ::= CompoundSelector [\<combinator>]*~~
**ComplexSelector** ::= [\<combinator>]? ComplexSelectorComponent+
&#32; | [\<combinator>]
**ComplexSelectorComponent** ::= CompoundSelector [\<combinator>]?
</pre></x>

[\<combinator>]: https://drafts.csswg.org/selectors-4/#typedef-combinator

## Semantics

### Evaluating a Style Rule

This proposal adds the following to [Evaluating a Style Rule], after executing
each child of `rule`:

[Evaluating a Style Rule]: ../spec/style-rules.md#semantics

* If `css` contains any children and `selector` is [bogus], throw an error.

[bogus]: #bogus-selector

### Executing an Extend Rule

This proposal adds the following to [Executing an Extend Rule], after checking
for a current style rule:

[Executing an Extend Rule]: ../spec/at-rules/extend.md#executing-an-extend-rule

* If the current style rule is [bogus], throw an error.

## Functions

For the `selector.extend()`, `selector.is-superselector()`,
`selector.replace()`, and `selector.unify()` functions, after parsing their
selector arguments, throw an error if any of the parsed selectors are [bogus].

> `selector.append()`, `selector.nest()`, and `selector.parse()` are still
> allowed to take bogus selectors because these functions are syntactic rather
> than semantic. This means on one hand that there aren't ambiguities about how
> to handle bogus selector inputs, and on the other that it may be useful to
> emit bogus selectors for later use in nesting contexts.
>
> Note that `selector.append()` already forbids selectors with leading or
> trailing combinators from being passed in between selectors.
## Deprecation Process

The deprecation will be divided into two phases:

### Phase 1

This phase will only change behavior that doesn't affect in-browser rendering.
In particular:

* The parsing of `ComplexSelector` and `ComplexSelectorComponent` is unchanged.

* A complex selector is instead considered [bogus] if it would be bogus in Phase
2 _or_ if it can be parsed in Phase 1 but not in Phase 2.

* The newly-added errors produce deprecation warnings instead.

* In [Evaluating a Style Rule], remove any complex selectors from `css`'s
selectors that are [bogus], except those that have a single leading combinator
but are otherwise not bogus.

> Leading combinators are allowed in Phase 1 (but still emit deprecation
> warnings) because they may be used for nesting along with `meta.load-css()`.
* Define a "useless" selector as:

* A complex selector that has multiple combinators.

* A bogus pseudo selector.

* Any selector that contains a useless selector.

In [Extending a Selector], treat useless selectors as selectors that can match
no elements.

[Extending a Selector]: ../spec/at-rules/extend.md#extending-a-selector

### Phase 2

This phase will emit errors as described in the body of the proposal.
14 changes: 7 additions & 7 deletions accepted/color-4-hwb.md
Expand Up @@ -78,7 +78,7 @@ are left to a future proposal.

## Procedures

### Scaling a Number
### Scaling a Number

This algorithm takes a number `number`, a value `factor`, and a number `max`.
It's written "scale `<number>` by `<factor>` with a `max` of `<max>`". It
Expand Down Expand Up @@ -112,7 +112,7 @@ All new functions are part of the `sass:color` built-in module.
* If either of `$whiteness` or `$blackness` don't have unit `%` or aren't
between `0%` and `100%` (inclusive), throw an error.

* Let `hue` be `($hue % 360) / 60` without units.
* Let `hue` be `$hue` without units.

* Let `whiteness` be `$whiteness / 100%`.

Expand All @@ -131,7 +131,7 @@ All new functions are part of the `sass:color` built-in module.
and rounded to the nearest integers.

* Let `alpha` be the result of [percent-converting][] `$alpha` with a `max` of 1.

* Return a color with the given `red`, `green`, `blue`, and `alpha` channels.

[percent-converting]: ../spec/built-in-modules/color.md#percent-converting-a-number
Expand Down Expand Up @@ -260,7 +260,7 @@ This function's new definition is as follows:

* Let `hue`, `saturation`, and `lightness` be the result of calling
`hue($color)`, `saturation($color)`, and `lightness($color)` respectively.

* If `$hue` isn't null, set `hue` to `hue + $hue`.

* If `$saturation` isn't null, set `saturation` to `saturation + $saturation`
Expand All @@ -279,7 +279,7 @@ This function's new definition is as follows:

* Let `hue`, `whiteness`, and `blackness` be the result of calling
`hue($color)`, `whiteness($color)`, and `blackness($color)` respectively.

* If `$hue` isn't null, set `hue` to `hue + $hue`.

* If `$whiteness` isn't null, set `whiteness` to `whiteness + $whiteness`
Expand Down Expand Up @@ -334,7 +334,7 @@ This function's new definition is as follows:

* Let `green` be `$color`'s green channel if `$green` is null or `$green`
without units otherwise.

* Let `blue` be `$color`'s blue channel if `$blue` is null or `$blue` without
units otherwise.

Expand Down Expand Up @@ -401,7 +401,7 @@ This function's new definition is as follows:

* If `$alpha` isn't null, set `alpha` to the result of [scaling][] `alpha` by
`$alpha` with `max` 1.

[scaling]: #scaling-a-number

* If any of `$red`, `$green`, or `$blue` aren't null:
Expand Down

0 comments on commit 0223a56

Please sign in to comment.