mirror of
https://github.com/swc-project/swc.git
synced 2024-12-25 06:36:08 +03:00
feat(css/prefixer): Support more properties (#4055)
This commit is contained in:
parent
a9708a5a1f
commit
f2517a345b
@ -94,3 +94,41 @@ where
|
|||||||
{
|
{
|
||||||
node.visit_mut_with(&mut PseudoElementSelectorNameReplacer { from, to });
|
node.visit_mut_with(&mut PseudoElementSelectorNameReplacer { from, to });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PseudoElementOnPseudoClassReplacer<'a> {
|
||||||
|
from: &'a str,
|
||||||
|
to: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VisitMut for PseudoElementOnPseudoClassReplacer<'_> {
|
||||||
|
fn visit_mut_subclass_selector(&mut self, n: &mut SubclassSelector) {
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
match n {
|
||||||
|
SubclassSelector::PseudoElement(PseudoElementSelector { name, span, .. })
|
||||||
|
if &*name.value.to_lowercase() == self.from =>
|
||||||
|
{
|
||||||
|
*n = SubclassSelector::PseudoClass(PseudoClassSelector {
|
||||||
|
span: *span,
|
||||||
|
name: Ident {
|
||||||
|
span: name.span,
|
||||||
|
value: self.to.into(),
|
||||||
|
raw: self.to.into(),
|
||||||
|
},
|
||||||
|
children: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace_pseudo_class_selector_on_pseudo_element_selector<N>(
|
||||||
|
node: &mut N,
|
||||||
|
from: &str,
|
||||||
|
to: &str,
|
||||||
|
) where
|
||||||
|
N: for<'aa> VisitMutWith<PseudoElementOnPseudoClassReplacer<'aa>>,
|
||||||
|
{
|
||||||
|
node.visit_mut_with(&mut PseudoElementOnPseudoClassReplacer { from, to });
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@ use swc_common::DUMMY_SP;
|
|||||||
use swc_css_ast::*;
|
use swc_css_ast::*;
|
||||||
use swc_css_utils::{
|
use swc_css_utils::{
|
||||||
replace_function_name, replace_ident, replace_pseudo_class_selector_name,
|
replace_function_name, replace_ident, replace_pseudo_class_selector_name,
|
||||||
replace_pseudo_element_selector_name,
|
replace_pseudo_class_selector_on_pseudo_element_selector, replace_pseudo_element_selector_name,
|
||||||
};
|
};
|
||||||
use swc_css_visit::{VisitMut, VisitMutWith};
|
use swc_css_visit::{VisitMut, VisitMutWith};
|
||||||
|
|
||||||
@ -12,9 +12,184 @@ pub fn prefixer() -> impl VisitMut {
|
|||||||
Prefixer::default()
|
Prefixer::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CrossFadeFunctionReplacerOnLegacyVariant<'a> {
|
||||||
|
from: &'a str,
|
||||||
|
to: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VisitMut for CrossFadeFunctionReplacerOnLegacyVariant<'_> {
|
||||||
|
fn visit_mut_function(&mut self, n: &mut Function) {
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
if &*n.name.value.to_lowercase() == self.from {
|
||||||
|
let mut transparency_values = vec![];
|
||||||
|
|
||||||
|
for group in n.value.split_mut(|n| {
|
||||||
|
matches!(
|
||||||
|
n,
|
||||||
|
ComponentValue::Delimiter(Delimiter {
|
||||||
|
value: DelimiterValue::Comma,
|
||||||
|
..
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
if transparency_values.len() >= 2 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut transparency_value = None;
|
||||||
|
|
||||||
|
for n in group {
|
||||||
|
match n {
|
||||||
|
ComponentValue::Percentage(Percentage {
|
||||||
|
value: Number { value, .. },
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
if transparency_value.is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
transparency_value = Some(*value / 100.0);
|
||||||
|
}
|
||||||
|
ComponentValue::Number(Number { value, .. }) => {
|
||||||
|
if transparency_value.is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
transparency_value = Some(*value);
|
||||||
|
}
|
||||||
|
ComponentValue::Integer(Integer { value, .. }) => {
|
||||||
|
if transparency_value.is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
transparency_value = Some((*value) as f64);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transparency_values.push(transparency_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if transparency_values.len() != 2 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let transparency_value = match (transparency_values[0], transparency_values[1]) {
|
||||||
|
(None, None) => 0.5,
|
||||||
|
(Some(number), None) => number,
|
||||||
|
(None, Some(number)) => 1.0 - number,
|
||||||
|
(Some(first), Some(second)) if first + second == 1.0 => first,
|
||||||
|
_ => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut new_value: Vec<ComponentValue> = n
|
||||||
|
.value
|
||||||
|
.iter()
|
||||||
|
.filter(|n| {
|
||||||
|
!matches!(
|
||||||
|
n,
|
||||||
|
ComponentValue::Percentage(_)
|
||||||
|
| ComponentValue::Number(_)
|
||||||
|
| ComponentValue::Integer(_)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
new_value.extend(vec![
|
||||||
|
ComponentValue::Delimiter(Delimiter {
|
||||||
|
span: DUMMY_SP,
|
||||||
|
value: DelimiterValue::Comma,
|
||||||
|
}),
|
||||||
|
ComponentValue::Number(Number {
|
||||||
|
span: DUMMY_SP,
|
||||||
|
value: transparency_value,
|
||||||
|
raw: transparency_value.to_string().into(),
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
n.value = new_value;
|
||||||
|
|
||||||
|
n.name.value = self.to.into();
|
||||||
|
n.name.raw = self.to.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace_cross_fade_function_on_legacy_variant<N>(node: &mut N, from: &str, to: &str)
|
||||||
|
where
|
||||||
|
N: for<'aa> VisitMutWith<CrossFadeFunctionReplacerOnLegacyVariant<'aa>>,
|
||||||
|
{
|
||||||
|
node.visit_mut_with(&mut CrossFadeFunctionReplacerOnLegacyVariant { from, to });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ImageSetFunctionReplacerOnLegacyVariant<'a> {
|
||||||
|
from: &'a str,
|
||||||
|
to: &'a str,
|
||||||
|
in_function: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VisitMut for ImageSetFunctionReplacerOnLegacyVariant<'_> {
|
||||||
|
fn visit_mut_component_value(&mut self, n: &mut ComponentValue) {
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
if !self.in_function {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let ComponentValue::Str(Str { value, raw, span }) = n {
|
||||||
|
*n = ComponentValue::Url(Url {
|
||||||
|
span: *span,
|
||||||
|
name: Ident {
|
||||||
|
span: DUMMY_SP,
|
||||||
|
value: "url".into(),
|
||||||
|
raw: "url".into(),
|
||||||
|
},
|
||||||
|
value: Some(UrlValue::Str(Str {
|
||||||
|
span: DUMMY_SP,
|
||||||
|
value: value.as_ref().into(),
|
||||||
|
raw: raw.as_ref().into(),
|
||||||
|
})),
|
||||||
|
modifiers: Some(vec![]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_function(&mut self, n: &mut Function) {
|
||||||
|
let old_in_function = self.in_function;
|
||||||
|
|
||||||
|
self.in_function = true;
|
||||||
|
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
if &*n.name.value.to_lowercase() == self.from {
|
||||||
|
n.name.value = self.to.into();
|
||||||
|
n.name.raw = self.to.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.in_function = old_in_function;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace_image_set_function_on_legacy_variant<N>(node: &mut N, from: &str, to: &str)
|
||||||
|
where
|
||||||
|
N: for<'aa> VisitMutWith<ImageSetFunctionReplacerOnLegacyVariant<'aa>>,
|
||||||
|
{
|
||||||
|
node.visit_mut_with(&mut ImageSetFunctionReplacerOnLegacyVariant {
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
in_function: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Prefixer {
|
struct Prefixer {
|
||||||
in_stylesheet: bool,
|
in_stylesheet: bool,
|
||||||
|
in_keyframe_block: bool,
|
||||||
added_rules: Vec<Rule>,
|
added_rules: Vec<Rule>,
|
||||||
in_simple_block: bool,
|
in_simple_block: bool,
|
||||||
added_declarations: Vec<Declaration>,
|
added_declarations: Vec<Declaration>,
|
||||||
@ -28,12 +203,21 @@ pub enum Prefix {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VisitMut for Prefixer {
|
impl VisitMut for Prefixer {
|
||||||
|
fn visit_mut_keyframe_block(&mut self, n: &mut KeyframeBlock) {
|
||||||
|
let old_in_keyframe_block = self.in_keyframe_block;
|
||||||
|
|
||||||
|
self.in_keyframe_block = true;
|
||||||
|
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
self.in_keyframe_block = old_in_keyframe_block;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO handle `resolution` in media/supports at-rules
|
// TODO handle `resolution` in media/supports at-rules
|
||||||
// TODO handle declarations in `@media`/`@support`
|
// TODO handle declarations in `@media`/`@support`
|
||||||
// TODO handle `@viewport`
|
// TODO handle `@viewport`
|
||||||
// TODO handle `@keyframes`
|
// TODO handle `@keyframes`
|
||||||
|
|
||||||
// TODO improve legacy `::placeholder` pseudo
|
|
||||||
fn visit_mut_qualified_rule(&mut self, n: &mut QualifiedRule) {
|
fn visit_mut_qualified_rule(&mut self, n: &mut QualifiedRule) {
|
||||||
n.visit_mut_children_with(self);
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
@ -55,11 +239,11 @@ impl VisitMut for Prefixer {
|
|||||||
"file-selector-button",
|
"file-selector-button",
|
||||||
"-webkit-file-upload-button",
|
"-webkit-file-upload-button",
|
||||||
);
|
);
|
||||||
replace_pseudo_element_selector_name(&mut new_prelude, "backdrop", "-ms-backdrop");
|
replace_pseudo_element_selector_name(&mut new_prelude, "backdrop", "-webkit-backdrop");
|
||||||
replace_pseudo_element_selector_name(
|
replace_pseudo_element_selector_name(
|
||||||
&mut new_prelude,
|
&mut new_prelude,
|
||||||
"placeholder",
|
"placeholder",
|
||||||
"-ms-input-placeholder",
|
"-webkit-input-placeholder",
|
||||||
);
|
);
|
||||||
|
|
||||||
if n.prelude != new_prelude {
|
if n.prelude != new_prelude {
|
||||||
@ -82,6 +266,25 @@ impl VisitMut for Prefixer {
|
|||||||
"-moz-placeholder-shown",
|
"-moz-placeholder-shown",
|
||||||
);
|
);
|
||||||
replace_pseudo_element_selector_name(&mut new_prelude, "selection", "-moz-selection");
|
replace_pseudo_element_selector_name(&mut new_prelude, "selection", "-moz-selection");
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut new_prelude_with_previous = new_prelude.clone();
|
||||||
|
|
||||||
|
replace_pseudo_class_selector_on_pseudo_element_selector(
|
||||||
|
&mut new_prelude_with_previous,
|
||||||
|
"placeholder",
|
||||||
|
"-moz-placeholder",
|
||||||
|
);
|
||||||
|
|
||||||
|
if new_prelude_with_previous != new_prelude {
|
||||||
|
self.added_rules.push(Rule::QualifiedRule(QualifiedRule {
|
||||||
|
span: DUMMY_SP,
|
||||||
|
prelude: new_prelude_with_previous,
|
||||||
|
block: n.block.clone(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
replace_pseudo_element_selector_name(&mut new_prelude, "placeholder", "-moz-placeholder");
|
replace_pseudo_element_selector_name(&mut new_prelude, "placeholder", "-moz-placeholder");
|
||||||
|
|
||||||
if n.prelude != new_prelude {
|
if n.prelude != new_prelude {
|
||||||
@ -105,11 +308,30 @@ impl VisitMut for Prefixer {
|
|||||||
"file-selector-button",
|
"file-selector-button",
|
||||||
"-ms-browse",
|
"-ms-browse",
|
||||||
);
|
);
|
||||||
replace_pseudo_element_selector_name(&mut new_prelude, "backdrop", "-webkit-backdrop");
|
replace_pseudo_element_selector_name(&mut new_prelude, "backdrop", "-ms-backdrop");
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut new_prelude_with_previous = new_prelude.clone();
|
||||||
|
|
||||||
|
replace_pseudo_class_selector_on_pseudo_element_selector(
|
||||||
|
&mut new_prelude_with_previous,
|
||||||
|
"placeholder",
|
||||||
|
"-ms-input-placeholder",
|
||||||
|
);
|
||||||
|
|
||||||
|
if new_prelude_with_previous != new_prelude {
|
||||||
|
self.added_rules.push(Rule::QualifiedRule(QualifiedRule {
|
||||||
|
span: DUMMY_SP,
|
||||||
|
prelude: new_prelude_with_previous,
|
||||||
|
block: n.block.clone(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
replace_pseudo_element_selector_name(
|
replace_pseudo_element_selector_name(
|
||||||
&mut new_prelude,
|
&mut new_prelude,
|
||||||
"placeholder",
|
"placeholder",
|
||||||
"-webkit-input-placeholder",
|
"-ms-input-placeholder",
|
||||||
);
|
);
|
||||||
|
|
||||||
if n.prelude != new_prelude {
|
if n.prelude != new_prelude {
|
||||||
@ -171,8 +393,17 @@ impl VisitMut for Prefixer {
|
|||||||
let mut webkit_new_value = n.value.clone();
|
let mut webkit_new_value = n.value.clone();
|
||||||
|
|
||||||
replace_function_name(&mut webkit_new_value, "filter", "-webkit-filter");
|
replace_function_name(&mut webkit_new_value, "filter", "-webkit-filter");
|
||||||
replace_function_name(&mut webkit_new_value, "image-set", "-webkit-image-set");
|
replace_image_set_function_on_legacy_variant(
|
||||||
|
&mut webkit_new_value,
|
||||||
|
"image-set",
|
||||||
|
"-webkit-image-set",
|
||||||
|
);
|
||||||
replace_function_name(&mut webkit_new_value, "calc", "-webkit-calc");
|
replace_function_name(&mut webkit_new_value, "calc", "-webkit-calc");
|
||||||
|
replace_cross_fade_function_on_legacy_variant(
|
||||||
|
&mut webkit_new_value,
|
||||||
|
"cross-fade",
|
||||||
|
"-webkit-cross-fade",
|
||||||
|
);
|
||||||
|
|
||||||
let mut moz_new_value = n.value.clone();
|
let mut moz_new_value = n.value.clone();
|
||||||
|
|
||||||
@ -320,6 +551,7 @@ impl VisitMut for Prefixer {
|
|||||||
same_content!(Prefix::O, "-o-animation-timing-function");
|
same_content!(Prefix::O, "-o-animation-timing-function");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO improve me https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip
|
||||||
"background-clip" => {
|
"background-clip" => {
|
||||||
if let ComponentValue::Ident(Ident { value, .. }) = &n.value[0] {
|
if let ComponentValue::Ident(Ident { value, .. }) = &n.value[0] {
|
||||||
if &*value.to_lowercase() == "text" {
|
if &*value.to_lowercase() == "text" {
|
||||||
@ -516,6 +748,7 @@ impl VisitMut for Prefixer {
|
|||||||
same_content!(Prefix::Ms, "-ms-flex-line-pack");
|
same_content!(Prefix::Ms, "-ms-flex-line-pack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO fix me https://developer.mozilla.org/en-US/docs/Web/CSS/Image-Rendering
|
||||||
"image-rendering" => {
|
"image-rendering" => {
|
||||||
if let ComponentValue::Ident(Ident { value, .. }) = &n.value[0] {
|
if let ComponentValue::Ident(Ident { value, .. }) = &n.value[0] {
|
||||||
if &*value.to_lowercase() == "pixelated" {
|
if &*value.to_lowercase() == "pixelated" {
|
||||||
@ -712,7 +945,10 @@ impl VisitMut for Prefixer {
|
|||||||
same_content!(Prefix::Moz, "-moz-transform");
|
same_content!(Prefix::Moz, "-moz-transform");
|
||||||
|
|
||||||
if !has_3d_function {
|
if !has_3d_function {
|
||||||
|
if !self.in_keyframe_block {
|
||||||
same_content!(Prefix::Ms, "-ms-transform");
|
same_content!(Prefix::Ms, "-ms-transform");
|
||||||
|
}
|
||||||
|
|
||||||
same_content!(Prefix::O, "-o-transform");
|
same_content!(Prefix::O, "-o-transform");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -720,7 +956,11 @@ impl VisitMut for Prefixer {
|
|||||||
"transform-origin" => {
|
"transform-origin" => {
|
||||||
same_content!(Prefix::Webkit, "-webkit-transform-origin");
|
same_content!(Prefix::Webkit, "-webkit-transform-origin");
|
||||||
same_content!(Prefix::Moz, "-moz-transform-origin");
|
same_content!(Prefix::Moz, "-moz-transform-origin");
|
||||||
|
|
||||||
|
if !self.in_keyframe_block {
|
||||||
same_content!(Prefix::Ms, "-ms-transform-origin");
|
same_content!(Prefix::Ms, "-ms-transform-origin");
|
||||||
|
}
|
||||||
|
|
||||||
same_content!(Prefix::O, "-o-transform-origin");
|
same_content!(Prefix::O, "-o-transform-origin");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,8 +1049,10 @@ impl VisitMut for Prefixer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO improve me for `filter` values https://github.com/postcss/autoprefixer/blob/main/test/cases/transition.css#L6
|
// TODO improve me for `filter` values https://github.com/postcss/autoprefixer/blob/main/test/cases/transition.css#L6
|
||||||
|
// TODO https://github.com/postcss/autoprefixer/blob/main/lib/transition.js
|
||||||
"transition" => {
|
"transition" => {
|
||||||
replace_ident(&mut webkit_new_value, "transform", "-webkit-transform");
|
replace_ident(&mut webkit_new_value, "transform", "-webkit-transform");
|
||||||
|
replace_ident(&mut webkit_new_value, "filter", "-webkit-filter");
|
||||||
|
|
||||||
same_content!(Prefix::Webkit, "-webkit-transition");
|
same_content!(Prefix::Webkit, "-webkit-transition");
|
||||||
|
|
||||||
@ -910,7 +1152,6 @@ impl VisitMut for Prefixer {
|
|||||||
"stretch" => {
|
"stretch" => {
|
||||||
same_name!("-webkit-fill-available");
|
same_name!("-webkit-fill-available");
|
||||||
same_name!("-moz-available");
|
same_name!("-moz-available");
|
||||||
same_name!("fill-available");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -1094,11 +1335,13 @@ impl VisitMut for Prefixer {
|
|||||||
|
|
||||||
"background-origin" => {
|
"background-origin" => {
|
||||||
same_content!(Prefix::Webkit, "-webkit-background-origin");
|
same_content!(Prefix::Webkit, "-webkit-background-origin");
|
||||||
|
same_content!(Prefix::Moz, "-moz-background-origin");
|
||||||
same_content!(Prefix::O, "-o-background-origin");
|
same_content!(Prefix::O, "-o-background-origin");
|
||||||
}
|
}
|
||||||
|
|
||||||
"background-size" => {
|
"background-size" => {
|
||||||
same_content!(Prefix::Webkit, "-webkit-background-size");
|
same_content!(Prefix::Webkit, "-webkit-background-size");
|
||||||
|
same_content!(Prefix::Moz, "-moz-background-size");
|
||||||
same_content!(Prefix::O, "-o-background-size");
|
same_content!(Prefix::O, "-o-background-size");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1195,11 +1438,7 @@ impl VisitMut for Prefixer {
|
|||||||
|
|
||||||
// TODO add `grid` support https://github.com/postcss/autoprefixer/tree/main/lib/hacks (starting with grid) and https://github.com/postcss/autoprefixer/blob/main/data/prefixes.js#L559 and https://github.com/postcss/autoprefixer/blob/main/lib/hacks/intrinsic.js
|
// TODO add `grid` support https://github.com/postcss/autoprefixer/tree/main/lib/hacks (starting with grid) and https://github.com/postcss/autoprefixer/blob/main/data/prefixes.js#L559 and https://github.com/postcss/autoprefixer/blob/main/lib/hacks/intrinsic.js
|
||||||
// TODO handle https://github.com/postcss/autoprefixer/blob/main/data/prefixes.js#L938
|
// TODO handle https://github.com/postcss/autoprefixer/blob/main/data/prefixes.js#L938
|
||||||
// TODO handle `image-set()` https://github.com/postcss/autoprefixer/blob/main/lib/hacks/image-set.js
|
|
||||||
// TODO handle `linear-gradient()`/`repeating-linear-gradient()`/`radial-gradient()`/`repeating-radial-gradient()` in all properties https://github.com/postcss/autoprefixer/blob/main/data/prefixes.js#L168
|
// TODO handle `linear-gradient()`/`repeating-linear-gradient()`/`radial-gradient()`/`repeating-radial-gradient()` in all properties https://github.com/postcss/autoprefixer/blob/main/data/prefixes.js#L168
|
||||||
// TODO add https://github.com/postcss/autoprefixer/blob/main/lib/hacks/filter-value.js
|
|
||||||
// TODO add https://github.com/postcss/autoprefixer/blob/main/lib/hacks/cross-fade.js
|
|
||||||
// TODO handle transform functions https://github.com/postcss/autoprefixer/blob/main/lib/hacks/transform-decl.js
|
|
||||||
// TODO fix me https://github.com/postcss/autoprefixer/blob/main/test/cases/custom-prefix.out.css
|
// TODO fix me https://github.com/postcss/autoprefixer/blob/main/test/cases/custom-prefix.out.css
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
dialog::-ms-backdrop {
|
dialog::-webkit-backdrop {
|
||||||
background: rgba(255, 0, 0, .25);
|
background: rgba(255, 0, 0, .25);
|
||||||
}
|
}
|
||||||
dialog::-webkit-backdrop {
|
dialog::-ms-backdrop {
|
||||||
background: rgba(255, 0, 0, .25);
|
background: rgba(255, 0, 0, .25);
|
||||||
}
|
}
|
||||||
dialog::backdrop {
|
dialog::backdrop {
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
.class {
|
.class {
|
||||||
-webkit-background-origin: initial;
|
-webkit-background-origin: initial;
|
||||||
|
-moz-background-origin: initial;
|
||||||
-o-background-origin: initial;
|
-o-background-origin: initial;
|
||||||
background-origin: initial;
|
background-origin: initial;
|
||||||
}
|
}
|
||||||
.class {
|
.class {
|
||||||
-webkit-background-size: contain;
|
-webkit-background-size: contain;
|
||||||
|
-moz-background-size: contain;
|
||||||
-o-background-size: contain;
|
-o-background-size: contain;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
a {
|
a {
|
||||||
-webkit-background-size: 20px;
|
-webkit-background-size: 20px;
|
||||||
|
-moz-background-size: 20px;
|
||||||
-o-background-size: 20px;
|
-o-background-size: 20px;
|
||||||
background-size: 20px;
|
background-size: 20px;
|
||||||
}
|
}
|
||||||
b {
|
b {
|
||||||
-webkit-background-size: contain;
|
-webkit-background-size: contain;
|
||||||
|
-moz-background-size: contain;
|
||||||
-o-background-size: contain;
|
-o-background-size: contain;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
}
|
}
|
||||||
div {
|
div {
|
||||||
-webkit-background-size: -webkit-calc(20px);
|
-webkit-background-size: -webkit-calc(20px);
|
||||||
|
-moz-background-size: -moz-calc(20px);
|
||||||
-o-background-size: calc(20px);
|
-o-background-size: calc(20px);
|
||||||
background-size: -webkit-calc(20px);
|
background-size: -webkit-calc(20px);
|
||||||
background-size: -moz-calc(20px);
|
background-size: -moz-calc(20px);
|
||||||
|
@ -21,3 +21,18 @@ h3 {
|
|||||||
.foo {
|
.foo {
|
||||||
background-image: cross-fade(.59 linear-gradient(white, black), radial-gradient(circle closest-corner, white, black));
|
background-image: cross-fade(.59 linear-gradient(white, black), radial-gradient(circle closest-corner, white, black));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.class {
|
||||||
|
background-image: cross-fade( url(white.png) 0%, url(black.png) 100%); /* fully black */
|
||||||
|
background-image: cross-fade( url(white.png) 25%, url(black.png) 75%); /* 25% white, 75% black */
|
||||||
|
background-image: cross-fade( url(white.png) 50%, url(black.png) 50%); /* 50% white, 50% black */
|
||||||
|
background-image: cross-fade( url(white.png) 75%, url(black.png) 25%); /* 75% white, 25% black */
|
||||||
|
background-image: cross-fade( url(white.png) 100%, url(black.png) 0%); /* fully white */
|
||||||
|
background-image: cross-fade( url(green.png) 75%, url(red.png) 75%); /* both green and red at 75% */
|
||||||
|
background-image: cross-fade( url(white.png), url(black.png) 75%);
|
||||||
|
background-image: cross-fade( url(red.png) 33.33%, url(yellow.png) 33.33%, url(blue.png) 33.33%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.broken {
|
||||||
|
background-image: cross-fade(url(red.png) 33.33%);
|
||||||
|
}
|
||||||
|
@ -1,18 +1,43 @@
|
|||||||
a {
|
a {
|
||||||
|
background-image: -webkit-cross-fade(url(foo.png), url(bar.png), 0.2);
|
||||||
background-image: cross-fade(20% url(foo.png), url(bar.png));
|
background-image: cross-fade(20% url(foo.png), url(bar.png));
|
||||||
}
|
}
|
||||||
b {
|
b {
|
||||||
|
background-image: -webkit-cross-fade(url(foo.png), url(bar.png), 0.5);
|
||||||
background-image: cross-fade(url(foo.png), url(bar.png));
|
background-image: cross-fade(url(foo.png), url(bar.png));
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
|
background-image: -webkit-cross-fade(url(foo.png), url(bar.png), 0.10823);
|
||||||
background-image: cross-fade(10.823% url(foo.png), url(bar.png));
|
background-image: cross-fade(10.823% url(foo.png), url(bar.png));
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
|
background-image: -webkit-cross-fade(url(foo.png), url(bar.png), 0.59);
|
||||||
background-image: cross-fade(0.59 url(foo.png), url(bar.png));
|
background-image: cross-fade(0.59 url(foo.png), url(bar.png));
|
||||||
}
|
}
|
||||||
h3 {
|
h3 {
|
||||||
|
background-image: -webkit-cross-fade(url(foo.png), url(bar.png), 0.59);
|
||||||
background-image: cross-fade(.59 url(foo.png), url(bar.png));
|
background-image: cross-fade(.59 url(foo.png), url(bar.png));
|
||||||
}
|
}
|
||||||
.foo {
|
.foo {
|
||||||
|
background-image: -webkit-cross-fade(linear-gradient(white, black), radial-gradient(circle closest-corner, white, black), 0.59);
|
||||||
background-image: cross-fade(.59 linear-gradient(white, black), radial-gradient(circle closest-corner, white, black));
|
background-image: cross-fade(.59 linear-gradient(white, black), radial-gradient(circle closest-corner, white, black));
|
||||||
}
|
}
|
||||||
|
.class {
|
||||||
|
background-image: -webkit-cross-fade(url(white.png), url(black.png), 0);
|
||||||
|
background-image: cross-fade(url(white.png) 0%, url(black.png) 100%);
|
||||||
|
background-image: -webkit-cross-fade(url(white.png), url(black.png), 0.25);
|
||||||
|
background-image: cross-fade(url(white.png) 25%, url(black.png) 75%);
|
||||||
|
background-image: -webkit-cross-fade(url(white.png), url(black.png), 0.5);
|
||||||
|
background-image: cross-fade(url(white.png) 50%, url(black.png) 50%);
|
||||||
|
background-image: -webkit-cross-fade(url(white.png), url(black.png), 0.75);
|
||||||
|
background-image: cross-fade(url(white.png) 75%, url(black.png) 25%);
|
||||||
|
background-image: -webkit-cross-fade(url(white.png), url(black.png), 1);
|
||||||
|
background-image: cross-fade(url(white.png) 100%, url(black.png) 0%);
|
||||||
|
background-image: cross-fade(url(green.png) 75%, url(red.png) 75%);
|
||||||
|
background-image: -webkit-cross-fade(url(white.png), url(black.png), 0.25);
|
||||||
|
background-image: cross-fade(url(white.png), url(black.png) 75%);
|
||||||
|
background-image: cross-fade(url(red.png) 33.33%, url(yellow.png) 33.33%, url(blue.png) 33.33%);
|
||||||
|
}
|
||||||
|
.broken {
|
||||||
|
background-image: cross-fade(url(red.png) 33.33%);
|
||||||
|
}
|
||||||
|
@ -6,9 +6,10 @@
|
|||||||
a {
|
a {
|
||||||
-webkit-filter: blur(10px);
|
-webkit-filter: blur(10px);
|
||||||
filter: blur(10px);
|
filter: blur(10px);
|
||||||
-webkit-transition: filter 2s;
|
-webkit-transition: -webkit-filter 2s;
|
||||||
-moz-transition: filter 2s;
|
-moz-transition: filter 2s;
|
||||||
-o-transition: filter 2s;
|
-o-transition: filter 2s;
|
||||||
|
transition: -webkit-filter 2s;
|
||||||
transition: filter 2s;
|
transition: filter 2s;
|
||||||
}
|
}
|
||||||
div {
|
div {
|
||||||
|
@ -5,7 +5,14 @@
|
|||||||
.b,
|
.b,
|
||||||
.c::selection,
|
.c::selection,
|
||||||
.d:read-only,
|
.d:read-only,
|
||||||
.e::-ms-input-placeholder {
|
.e::-webkit-input-placeholder {
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
.a,
|
||||||
|
.b,
|
||||||
|
.c::-moz-selection,
|
||||||
|
.d:-moz-read-only,
|
||||||
|
.e:-moz-placeholder {
|
||||||
color: yellow;
|
color: yellow;
|
||||||
}
|
}
|
||||||
.a,
|
.a,
|
||||||
@ -19,7 +26,14 @@
|
|||||||
.b,
|
.b,
|
||||||
.c::selection,
|
.c::selection,
|
||||||
.d:read-only,
|
.d:read-only,
|
||||||
.e::-webkit-input-placeholder {
|
.e:-ms-input-placeholder {
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
.a,
|
||||||
|
.b,
|
||||||
|
.c::selection,
|
||||||
|
.d:read-only,
|
||||||
|
.e::-ms-input-placeholder {
|
||||||
color: yellow;
|
color: yellow;
|
||||||
}
|
}
|
||||||
.a,
|
.a,
|
||||||
|
@ -33,3 +33,7 @@ h1 {
|
|||||||
.class {
|
.class {
|
||||||
content: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
content: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.broken {
|
||||||
|
content: image-set('foo@1x.png' 1x, "foo@2x.png" 2x) "test";
|
||||||
|
}
|
@ -3,39 +3,43 @@ a {
|
|||||||
background-image: image-set(url(foo@1x.png) 1x, url(foo@2x.png) 2x);
|
background-image: image-set(url(foo@1x.png) 1x, url(foo@2x.png) 2x);
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
background-image: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
background-image: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
background-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
background-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
}
|
}
|
||||||
.class {
|
.class {
|
||||||
background-image: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
background-image: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
background-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
background-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
}
|
}
|
||||||
.class {
|
.class {
|
||||||
-webkit-border-image: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
-webkit-border-image: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
-moz-border-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
-moz-border-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
-o-border-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
-o-border-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
border-image: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
border-image: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
border-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
border-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
}
|
}
|
||||||
.class {
|
.class {
|
||||||
-webkit-mask: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
-webkit-mask: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
mask: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
mask: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
mask: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
mask: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
}
|
}
|
||||||
.class {
|
.class {
|
||||||
-webkit-mask-image: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
-webkit-mask-image: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
mask-image: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
mask-image: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
mask-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
mask-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
}
|
}
|
||||||
.class {
|
.class {
|
||||||
list-style: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
list-style: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
list-style: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
list-style: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
}
|
}
|
||||||
.class {
|
.class {
|
||||||
list-style-image: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
list-style-image: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
list-style-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
list-style-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
}
|
}
|
||||||
.class {
|
.class {
|
||||||
content: -webkit-image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
content: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x);
|
||||||
content: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
content: image-set('foo@1x.png' 1x, "foo@2x.png" 2x);
|
||||||
}
|
}
|
||||||
|
.broken {
|
||||||
|
content: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x) "test";
|
||||||
|
content: image-set('foo@1x.png' 1x, "foo@2x.png" 2x) "test";
|
||||||
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
top: calc(10% + 10px);
|
top: calc(10% + 10px);
|
||||||
-webkit-transform: rotate(10deg);
|
-webkit-transform: rotate(10deg);
|
||||||
-moz-transform: rotate(10deg);
|
-moz-transform: rotate(10deg);
|
||||||
-ms-transform: rotate(10deg);
|
|
||||||
-o-transform: rotate(10deg);
|
-o-transform: rotate(10deg);
|
||||||
transform: rotate(10deg);
|
transform: rotate(10deg);
|
||||||
}
|
}
|
||||||
@ -23,7 +22,6 @@
|
|||||||
top: calc(10%);
|
top: calc(10%);
|
||||||
-webkit-transform: rotate(0);
|
-webkit-transform: rotate(0);
|
||||||
-moz-transform: rotate(0);
|
-moz-transform: rotate(0);
|
||||||
-ms-transform: rotate(0);
|
|
||||||
-o-transform: rotate(0);
|
-o-transform: rotate(0);
|
||||||
transform: rotate(0);
|
transform: rotate(0);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
input::placeholder {
|
input::placeholder {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input::placeholder, #fs-toggle:fullscreen {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
@ -1,12 +1,42 @@
|
|||||||
input::-ms-input-placeholder {
|
input::-webkit-input-placeholder {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
input:-moz-placeholder {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
input::-moz-placeholder {
|
input::-moz-placeholder {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
input::-webkit-input-placeholder {
|
input:-ms-input-placeholder {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
input::-ms-input-placeholder {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
input::placeholder {
|
input::placeholder {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
input::-webkit-input-placeholder,
|
||||||
|
#fs-toggle:-webkit-full-screen {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
input:-moz-placeholder,
|
||||||
|
#fs-toggle:-moz-full-screen {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
input::-moz-placeholder,
|
||||||
|
#fs-toggle:-moz-full-screen {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
input:-ms-input-placeholder,
|
||||||
|
#fs-toggle:-ms-fullscreen {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
input::-ms-input-placeholder,
|
||||||
|
#fs-toggle:-ms-fullscreen {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
input::placeholder,
|
||||||
|
#fs-toggle:fullscreen {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
@ -38,7 +38,6 @@ em {
|
|||||||
from {
|
from {
|
||||||
-webkit-transform: rotate(90deg);
|
-webkit-transform: rotate(90deg);
|
||||||
-moz-transform: rotate(90deg);
|
-moz-transform: rotate(90deg);
|
||||||
-ms-transform: rotate(90deg);
|
|
||||||
-o-transform: rotate(90deg);
|
-o-transform: rotate(90deg);
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ div {
|
|||||||
width: fill-available;
|
width: fill-available;
|
||||||
width: -webkit-fill-available;
|
width: -webkit-fill-available;
|
||||||
width: -moz-available;
|
width: -moz-available;
|
||||||
width: fill-available;
|
|
||||||
width: stretch;
|
width: stretch;
|
||||||
min-width: -webkit-fit-content;
|
min-width: -webkit-fit-content;
|
||||||
min-width: -moz-fit-content;
|
min-width: -moz-fit-content;
|
||||||
@ -57,7 +56,6 @@ div {
|
|||||||
a {
|
a {
|
||||||
width: -webkit-fill-available;
|
width: -webkit-fill-available;
|
||||||
width: -moz-available;
|
width: -moz-available;
|
||||||
width: fill-available;
|
|
||||||
width: stretch;
|
width: stretch;
|
||||||
}
|
}
|
||||||
b {
|
b {
|
||||||
|
@ -59,13 +59,11 @@
|
|||||||
.class {
|
.class {
|
||||||
width: -webkit-fill-available;
|
width: -webkit-fill-available;
|
||||||
width: -moz-available;
|
width: -moz-available;
|
||||||
width: fill-available;
|
|
||||||
width: stretch;
|
width: stretch;
|
||||||
}
|
}
|
||||||
.class {
|
.class {
|
||||||
width: -webkit-fill-available !important;
|
width: -webkit-fill-available !important;
|
||||||
width: -moz-available !important;
|
width: -moz-available !important;
|
||||||
width: fill-available !important;
|
|
||||||
width: stretch !important;
|
width: stretch !important;
|
||||||
}
|
}
|
||||||
.class {
|
.class {
|
||||||
|
Loading…
Reference in New Issue
Block a user