fix(css/prefixer): Handle supports (#5503)

This commit is contained in:
Alexander Akait 2022-08-17 10:09:44 +03:00 committed by GitHub
parent 916af18b8f
commit dc98234fab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 354 additions and 32 deletions

View File

@ -3,6 +3,7 @@ use std::mem::take;
use once_cell::sync::Lazy;
use preset_env_base::{query::targets_to_versions, version::Version, BrowserData, Versions};
use swc_atoms::js_word;
use swc_common::{
collections::{AHashMap, AHashSet},
EqIgnoreSpan, DUMMY_SP,
@ -548,6 +549,7 @@ pub enum Prefix {
struct Prefixer {
env: Versions,
in_keyframe_block: bool,
supports_condition: Option<SupportsCondition>,
simple_block: Option<SimpleBlock>,
rule_prefix: Option<Prefix>,
added_top_rules: Vec<(Prefix, Rule)>,
@ -601,7 +603,8 @@ impl VisitMut for Prefixer {
stylesheet.rules = new_rules;
}
// TODO handle declarations in `@media`/`@support`
// TODO `@import` test
// TODO `selector()` supports
fn visit_mut_at_rule(&mut self, at_rule: &mut AtRule) {
let original_simple_block = at_rule.block.clone();
@ -698,6 +701,67 @@ impl VisitMut for Prefixer {
}
}
fn visit_mut_supports_condition(&mut self, supports_condition: &mut SupportsCondition) {
let old_supports_condition = self.supports_condition.take();
self.supports_condition = Some(supports_condition.clone());
supports_condition.visit_mut_children_with(self);
self.supports_condition = old_supports_condition;
}
fn visit_mut_supports_in_parens(&mut self, supports_in_parens: &mut SupportsInParens) {
supports_in_parens.visit_mut_children_with(self);
if let Some(supports_condition) = &self.supports_condition {
match supports_in_parens {
SupportsInParens::Feature(_) if !self.added_declarations.is_empty() => {
let mut conditions = Vec::with_capacity(1 + self.added_declarations.len());
conditions.push(swc_css_ast::SupportsConditionType::SupportsInParens(
supports_in_parens.clone(),
));
for n in take(&mut self.added_declarations) {
let supports_condition_type = SupportsConditionType::Or(SupportsOr {
span: DUMMY_SP,
keyword: Ident {
span: DUMMY_SP,
value: js_word!("or"),
raw: None,
},
condition: SupportsInParens::Feature(SupportsFeature::Declaration(n)),
});
let need_skip =
supports_condition
.conditions
.iter()
.any(|existing_condition_type| {
supports_condition_type.eq_ignore_span(existing_condition_type)
});
if need_skip {
continue;
}
conditions.push(supports_condition_type);
}
if conditions.len() > 1 {
*supports_in_parens =
SupportsInParens::SupportsCondition(SupportsCondition {
span: DUMMY_SP,
conditions,
});
}
}
_ => {}
}
}
}
fn visit_mut_media_query_list(&mut self, media_query_list: &mut MediaQueryList) {
media_query_list.visit_mut_children_with(self);
@ -1020,7 +1084,7 @@ impl VisitMut for Prefixer {
self.simple_block = Some(simple_block.clone());
let mut new = vec![];
let mut new = Vec::with_capacity(simple_block.value.len());
for mut n in take(&mut simple_block.value) {
n.visit_mut_children_with(self);
@ -1117,10 +1181,6 @@ impl VisitMut for Prefixer {
fn visit_mut_declaration(&mut self, n: &mut Declaration) {
n.visit_mut_children_with(self);
if self.simple_block.is_none() {
return;
}
if n.value.is_empty() {
return;
}
@ -1285,22 +1345,27 @@ impl VisitMut for Prefixer {
let mut ms_value = n.value.clone();
let declarations = Lazy::new(|| {
let simple_block = self.simple_block.as_ref().unwrap();
let mut declarations = Vec::with_capacity(simple_block.value.len());
if let Some(simple_block) = &self.simple_block {
let mut declarations = Vec::with_capacity(simple_block.value.len());
for n in simple_block.value.iter() {
match n {
ComponentValue::DeclarationOrAtRule(DeclarationOrAtRule::Declaration(
declaration,
)) => declarations.push(declaration),
ComponentValue::StyleBlock(StyleBlock::Declaration(declaration)) => {
declarations.push(declaration)
for n in simple_block.value.iter() {
match n {
ComponentValue::DeclarationOrAtRule(DeclarationOrAtRule::Declaration(
declaration,
)) => {
declarations.push(declaration);
}
ComponentValue::StyleBlock(StyleBlock::Declaration(declaration)) => {
declarations.push(declaration);
}
_ => {}
}
_ => {}
}
}
declarations
declarations
} else {
vec![]
}
});
let properties = Lazy::new(|| {

View File

@ -244,7 +244,7 @@ a {
-ms-flex-direction: inherit;
flex-direction: inherit;
}
@supports (display: flex) {
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
.foo {
display: -webkit-box;
display: -webkit-flex;
@ -253,7 +253,7 @@ a {
display: flex;
}
}
@supports (flex: auto) {
@supports ((flex: auto) or (-webkit-box-flex: 1) or (-webkit-flex: auto) or (-moz-box-flex: 1) or (-ms-flex: auto)) {
.foo {
-webkit-box-flex: 1;
-webkit-flex: auto;

View File

@ -103,7 +103,7 @@ a {
order: inherit;
flex-direction: inherit;
}
@supports (display: flex) {
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
.foo {
display: -webkit-box;
display: -webkit-flex;

View File

@ -18,7 +18,7 @@
color: red;
}
}
@supports (flex-wrap: wrap) {
@supports ((flex-wrap: wrap) or (-webkit-flex-wrap: wrap) or (-ms-flex-wrap: wrap)) {
@-webkit-keyframes test {
0% {
color: red;
@ -40,8 +40,8 @@
}
}
}
@supports (flex-wrap: wrap) {
@supports (flex-wrap: wrap) {
@supports ((flex-wrap: wrap) or (-webkit-flex-wrap: wrap) or (-ms-flex-wrap: wrap)) {
@supports ((flex-wrap: wrap) or (-webkit-flex-wrap: wrap) or (-ms-flex-wrap: wrap)) {
@-webkit-keyframes test {
0% {
color: red;
@ -59,8 +59,6 @@
}
@keyframes test {
0% {
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
color: red;
}
}

View File

@ -19,10 +19,8 @@
-ms-appearance: auto;
appearance: auto;
}
@supports (flex-wrap: wrap) {
@supports ((flex-wrap: wrap) or (-webkit-flex-wrap: wrap) or (-ms-flex-wrap: wrap)) {
.foo {
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
-webkit-appearance: auto;
-moz-appearance: auto;
-ms-appearance: auto;
@ -30,7 +28,7 @@
}
}
}
@supports (flex-wrap: wrap) {
@supports ((flex-wrap: wrap) or (-webkit-flex-wrap: wrap) or (-ms-flex-wrap: wrap)) {
.foo {
-webkit-appearance: auto;
-moz-appearance: auto;

View File

@ -0,0 +1,73 @@
@supports (display: flex) {
div {
display: flex;
}
}
@supports not (display: flex) {
a {
color: #000;
}
}
@supports not (not (display: flex)) {
a {
color: #000;
}
}
@supports (display: flex) or (cursor: grab) {
div {
display: flex;
}
}
@supports (display: flex) and (cursor: grab) {
div {
display: flex;
}
}
@supports ((display: flex) and (cursor: grab)) {
div {
display: flex;
}
}
@supports ((display: flex)) and ((cursor: grab)) {
div {
display: flex;
}
}
@supports ((perspective: 1px) and (not (-webkit-overflow-scrolling: touch))) {
a {
color: #000;
}
}
@supports (cursor: grab) or (color: black) {
a {
color: black;
}
}
@supports (display: flex) {
@media screen and (min-width: 900px) {
article {
display: flex;
}
}
}
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
div {
display: flex;
}
}
@supports (display: flex) or (display: -webkit-box) {
div {
display: flex;
}
}

View File

@ -0,0 +1,94 @@
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports not ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
a {
color: #000;
}
}
@supports not ( not ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox))) {
a {
color: #000;
}
}
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) or ((cursor: grab) or (cursor: -webkit-grab) or (cursor: -moz-grab)) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) and ((cursor: grab) or (cursor: -webkit-grab) or (cursor: -moz-grab)) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports (((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) and ((cursor: grab) or (cursor: -webkit-grab) or (cursor: -moz-grab))) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports (((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox))) and (((cursor: grab) or (cursor: -webkit-grab) or (cursor: -moz-grab))) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports (((perspective: 1px) or (-webkit-perspective: 1px) or (-moz-perspective: 1px)) and ( not (-webkit-overflow-scrolling: touch))) {
a {
color: #000;
}
}
@supports ((cursor: grab) or (cursor: -webkit-grab) or (cursor: -moz-grab)) or (color: black) {
a {
color: black;
}
}
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
@media screen and (min-width: 900px) {
article {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
}
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports ((display: flex) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) or (display: -webkit-box) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}

View File

@ -0,0 +1,94 @@
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports not ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
a {
color: #000;
}
}
@supports not ( not ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox))) {
a {
color: #000;
}
}
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) or ((cursor: grab) or (cursor: -webkit-grab) or (cursor: -moz-grab)) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) and ((cursor: grab) or (cursor: -webkit-grab) or (cursor: -moz-grab)) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports (((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) and ((cursor: grab) or (cursor: -webkit-grab) or (cursor: -moz-grab))) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports (((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox))) and (((cursor: grab) or (cursor: -webkit-grab) or (cursor: -moz-grab))) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports ((perspective: 1px) and ( not (-webkit-overflow-scrolling: touch))) {
a {
color: #000;
}
}
@supports ((cursor: grab) or (cursor: -webkit-grab) or (cursor: -moz-grab)) or (color: black) {
a {
color: black;
}
}
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
@media screen and (min-width: 900px) {
article {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
}
@supports ((display: flex) or (display: -webkit-box) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}
@supports ((display: flex) or (display: -webkit-flex) or (display: -moz-box) or (display: -ms-flexbox)) or (display: -webkit-box) {
div {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
}

View File

@ -100,7 +100,7 @@ button::-moz-submit-invalid {
transition: opacity 0.5s 2s, -o-transform 0.5s 0.5s;
transition: opacity 0.5s 2s, transform 0.5s 0.5s;
}
@supports (transition: opacity 0.5s 2s, transform 0.5s 0.5s) {
@supports ((transition: opacity 0.5s 2s, transform 0.5s 0.5s) or (-webkit-transition: opacity 0.5s 2s, -webkit-transform 0.5s 0.5s) or (-moz-transition: opacity 0.5s 2s, -moz-transform 0.5s 0.5s) or (-o-transition: opacity 0.5s 2s, -o-transform 0.5s 0.5s) or (transition: opacity 0.5s 2s, -webkit-transform 0.5s 0.5s) or (transition: opacity 0.5s 2s, -moz-transform 0.5s 0.5s) or (transition: opacity 0.5s 2s, -o-transform 0.5s 0.5s)) {
button::-moz-submit-invalid {
opacity: 1;
-webkit-transform: translateX(45px);

View File

@ -46,7 +46,7 @@ button::-moz-submit-invalid {
transition: opacity 0.5s 2s, -o-transform 0.5s 0.5s;
transition: opacity 0.5s 2s, transform 0.5s 0.5s;
}
@supports (transition: opacity 0.5s 2s, transform 0.5s 0.5s) {
@supports ((transition: opacity 0.5s 2s, transform 0.5s 0.5s) or (transition: opacity 0.5s 2s, -webkit-transform 0.5s 0.5s) or (transition: opacity 0.5s 2s, -moz-transform 0.5s 0.5s) or (transition: opacity 0.5s 2s, -o-transform 0.5s 0.5s)) {
button::-moz-submit-invalid {
opacity: 1;
transform: translateX(45px);