mirror of
https://github.com/swc-project/swc.git
synced 2024-12-21 12:41:54 +03:00
b206404d94
swc_css_ast: - Add `DeclBlockItem`. - Change `DeclBlock.properties` to `DeclBlock.items`. swc_css_parser: - Add a way to recovered errors.
610 lines
19 KiB
Rust
610 lines
19 KiB
Rust
use std::{iter::once, mem::take};
|
|
use swc_common::{Span, DUMMY_SP};
|
|
use swc_css_ast::*;
|
|
use swc_css_utils::replace_text;
|
|
use swc_css_visit::{VisitMut, VisitMutWith};
|
|
|
|
pub fn prefixer() -> impl VisitMut {
|
|
Prefixer::default()
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct Prefixer {
|
|
added: Vec<Property>,
|
|
}
|
|
|
|
impl Prefixer {
|
|
fn handle_cursor_image_set(
|
|
&mut self,
|
|
v: &mut Value,
|
|
second: Option<Value>,
|
|
important: Option<Span>,
|
|
) {
|
|
match v {
|
|
Value::Fn(f) => match &*f.name.value {
|
|
"image-set" => {
|
|
let val = Value::Fn(FnValue {
|
|
span: DUMMY_SP,
|
|
name: Text {
|
|
span: DUMMY_SP,
|
|
value: "-webkit-image-set".into(),
|
|
},
|
|
args: f.args.clone(),
|
|
});
|
|
|
|
let second = second.map(|v| match &v {
|
|
Value::Text(t) => {
|
|
if &*t.value == "grab" {
|
|
Value::Text(Text {
|
|
span: t.span,
|
|
value: "-webkit-grab".into(),
|
|
})
|
|
} else {
|
|
v
|
|
}
|
|
}
|
|
_ => v,
|
|
});
|
|
|
|
self.added.push(Property {
|
|
span: DUMMY_SP,
|
|
name: Text {
|
|
span: DUMMY_SP,
|
|
value: "cursor".into(),
|
|
},
|
|
values: {
|
|
let val = Value::Comma(CommaValues {
|
|
span: DUMMY_SP,
|
|
values: once(val).chain(second).collect(),
|
|
});
|
|
|
|
vec![val]
|
|
},
|
|
important,
|
|
});
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
|
|
Value::Comma(c) => {
|
|
if c.values.len() >= 1 {
|
|
let second = c.values.get(1).cloned();
|
|
self.handle_cursor_image_set(&mut c.values[0], second, important);
|
|
}
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl VisitMut for Prefixer {
|
|
fn visit_mut_decl_block_items(&mut self, props: &mut Vec<DeclBlockItem>) {
|
|
let mut new = vec![];
|
|
for mut n in take(props) {
|
|
n.visit_mut_with(self);
|
|
new.extend(self.added.drain(..).map(DeclBlockItem::Property));
|
|
new.push(n);
|
|
}
|
|
|
|
*props = new;
|
|
}
|
|
|
|
fn visit_mut_property(&mut self, n: &mut Property) {
|
|
n.visit_mut_children_with(self);
|
|
|
|
macro_rules! simple {
|
|
($name:expr,$val:expr) => {{
|
|
let val = Value::Text(Text {
|
|
span: DUMMY_SP,
|
|
value: $val.into(),
|
|
});
|
|
self.added.push(Property {
|
|
span: n.span,
|
|
name: Text {
|
|
span: n.name.span,
|
|
value: $name.into(),
|
|
},
|
|
values: vec![val],
|
|
important: n.important.clone(),
|
|
});
|
|
}};
|
|
}
|
|
|
|
macro_rules! same_content {
|
|
($name:expr) => {{
|
|
self.added.push(Property {
|
|
span: n.span,
|
|
name: Text {
|
|
span: n.name.span,
|
|
value: $name.into(),
|
|
},
|
|
values: n.values.clone(),
|
|
important: n.important.clone(),
|
|
});
|
|
}};
|
|
}
|
|
|
|
macro_rules! same_name {
|
|
($name:expr) => {{
|
|
let val = Text {
|
|
span: DUMMY_SP,
|
|
value: $name.into(),
|
|
};
|
|
|
|
self.added.push(Property {
|
|
span: n.span,
|
|
name: n.name.clone(),
|
|
values: vec![Value::Text(val)],
|
|
important: n.important.clone(),
|
|
});
|
|
}};
|
|
}
|
|
|
|
match &*n.name.value {
|
|
"appearance" => {
|
|
same_content!("-webkit-appearance");
|
|
same_content!("-moz-appearance");
|
|
same_content!("-ms-appearance");
|
|
}
|
|
|
|
"animation" => {
|
|
same_content!("-webkit-animation");
|
|
}
|
|
|
|
"animation-duration" => {
|
|
same_content!("-webkit-animation-duration");
|
|
}
|
|
|
|
"animation-name" => {
|
|
same_content!("-webkit-animation-name");
|
|
}
|
|
|
|
"animation-iteration-count" => {
|
|
same_content!("-webkit-animation-iteration-count");
|
|
}
|
|
|
|
"animation-timing-function" => {
|
|
same_content!("-webkit-animation-timing-function");
|
|
}
|
|
|
|
"background-clip" => {
|
|
same_content!("-webkit-background-clip");
|
|
}
|
|
|
|
"box-decoration-break" => {
|
|
same_content!("-webkit-box-decoration-break");
|
|
}
|
|
|
|
"color-adjust" => {
|
|
same_content!("-webkit-print-color-adjust");
|
|
}
|
|
|
|
"columns" => {
|
|
same_content!("-webkit-columns");
|
|
}
|
|
|
|
"column-count" => {
|
|
same_content!("-webkit-column-count");
|
|
}
|
|
|
|
"column-fill" => {
|
|
same_content!("-webkit-column-fill");
|
|
}
|
|
|
|
"column-gap" => {
|
|
same_content!("-webkit-column-gap");
|
|
}
|
|
|
|
"column-rule" => {
|
|
same_content!("-webkit-column-rule");
|
|
}
|
|
|
|
"column-rule-color" => {
|
|
same_content!("-webkit-column-rule-color");
|
|
}
|
|
|
|
"column-rule-style" => {
|
|
same_content!("-webkit-column-rule-style");
|
|
}
|
|
|
|
"column-span" => {
|
|
same_content!("-webkit-column-span");
|
|
}
|
|
|
|
"column-rule-width" => {
|
|
same_content!("-webkit-column-rule-width");
|
|
}
|
|
|
|
"column-width" => {
|
|
same_content!("-webkit-column-width");
|
|
}
|
|
|
|
"background" => {
|
|
if n.values.len() >= 1 {
|
|
match &n.values[0] {
|
|
Value::Fn(f) => match &*f.name.value {
|
|
"image-set" => {
|
|
let val = Value::Fn(FnValue {
|
|
span: DUMMY_SP,
|
|
name: Text {
|
|
span: DUMMY_SP,
|
|
value: "-webkit-image-set".into(),
|
|
},
|
|
args: f.args.clone(),
|
|
});
|
|
self.added.push(Property {
|
|
span: n.span,
|
|
name: n.name.clone(),
|
|
values: vec![val],
|
|
important: n.important.clone(),
|
|
});
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
"background-image" => {
|
|
if n.values.len() >= 1 {
|
|
match &n.values[0] {
|
|
Value::Fn(f) => match &*f.name.value {
|
|
"image-set" => {
|
|
let val = Value::Fn(FnValue {
|
|
span: DUMMY_SP,
|
|
name: Text {
|
|
span: DUMMY_SP,
|
|
value: "-webkit-image-set".into(),
|
|
},
|
|
args: f.args.clone(),
|
|
});
|
|
self.added.push(Property {
|
|
span: n.span,
|
|
name: n.name.clone(),
|
|
values: vec![val],
|
|
important: n.important.clone(),
|
|
});
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
"cursor" => {
|
|
if n.values.len() >= 1 {
|
|
match &n.values[0] {
|
|
Value::Text(Text { value, .. }) => match &**value {
|
|
"grab" => {
|
|
same_name!("-webkit-grab");
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
|
|
_ => {
|
|
let second = n.values.get(1).cloned();
|
|
self.handle_cursor_image_set(&mut n.values[0], second, n.important);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
"display" => {
|
|
if n.values.len() == 1 {
|
|
match &n.values[0] {
|
|
Value::Text(Text { value, .. }) => match &**value {
|
|
"flex" => {
|
|
same_name!("-webkit-box");
|
|
same_name!("-webkit-flex");
|
|
same_name!("-ms-flexbox");
|
|
}
|
|
|
|
"inline-flex" => {
|
|
same_name!("-webkit-inline-box");
|
|
same_name!("-webkit-inline-flex");
|
|
same_name!("-ms-inline-flexbox");
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
"flex" => {
|
|
same_content!("-webkit-flex");
|
|
same_content!("-ms-flex");
|
|
}
|
|
|
|
"flex-grow" => {
|
|
same_content!("-webkit-box-flex");
|
|
same_content!("-webkit-flex-grow");
|
|
same_content!("-ms-flex-positive");
|
|
}
|
|
|
|
"flex-shrink" => {
|
|
same_content!("-webkit-flex-shrink");
|
|
same_content!("-ms-flex-negative");
|
|
}
|
|
|
|
"flex-basis" => {
|
|
same_content!("-webkit-flex-basis");
|
|
same_content!("-ms-flex-preferred-size");
|
|
}
|
|
|
|
"align-self" => {
|
|
same_content!("-webkit-align-self");
|
|
same_content!("-ms-flex-item-align");
|
|
}
|
|
|
|
"align-content" => {
|
|
same_content!("-webkit-align-content");
|
|
same_content!("-ms-flex-line-pack");
|
|
}
|
|
|
|
"align-items" => {
|
|
same_content!("-webkit-align-items");
|
|
same_content!("-webkit-box-align");
|
|
same_content!("-ms-flex-align");
|
|
}
|
|
|
|
"justify-content" => {
|
|
if n.values.len() == 1 {
|
|
match &n.values[0] {
|
|
Value::Text(Text { value, .. }) => match &**value {
|
|
"flex-end" => {
|
|
simple!("-webkit-box-pack", "end");
|
|
simple!("-ms-flex-pack", "end");
|
|
}
|
|
|
|
"flex-start" => {
|
|
simple!("-webkit-box-pack", "start");
|
|
simple!("-ms-flex-pack", "start");
|
|
}
|
|
|
|
"justify" => {
|
|
same_content!("-webkit-box-pack");
|
|
same_content!("-ms-flex-pack");
|
|
}
|
|
|
|
"space-between" => {
|
|
simple!("-webkit-box-pack", "justify");
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
same_content!("-webkit-justify-content");
|
|
}
|
|
|
|
"order" => {
|
|
same_content!("-webkit-order");
|
|
same_content!("-ms-flex-order");
|
|
}
|
|
|
|
"flex-direction" => {
|
|
same_content!("-webkit-flex-direction");
|
|
same_content!("-ms-flex-direction");
|
|
}
|
|
|
|
"filter" => {
|
|
same_content!("-webkit-filter");
|
|
}
|
|
|
|
"mask" => {
|
|
same_content!("-webkit-mask");
|
|
}
|
|
|
|
"mask-image" => {
|
|
same_content!("-webkit-mask-image");
|
|
}
|
|
|
|
"mask-mode" => {
|
|
same_content!("-webkit-mask-mode");
|
|
}
|
|
|
|
"mask-clip" => {
|
|
same_content!("-webkit-mask-clip");
|
|
}
|
|
|
|
"mask-size" => {
|
|
same_content!("-webkit-mask-size");
|
|
}
|
|
|
|
"mask-repeat" => {
|
|
same_content!("-webkit-mask-repeat");
|
|
}
|
|
|
|
"mask-origin" => {
|
|
same_content!("-webkit-mask-origin");
|
|
}
|
|
|
|
"mask-position" => {
|
|
same_content!("-webkit-mask-position");
|
|
}
|
|
|
|
"mask-composite" => {
|
|
same_content!("-webkit-mask-composite");
|
|
}
|
|
|
|
"margin-inline-start" => {
|
|
same_content!("-webkit-margin-start");
|
|
}
|
|
|
|
"margin-inline-end" => {
|
|
same_content!("-webkit-margin-end");
|
|
}
|
|
|
|
"backface-visibility" => {
|
|
same_content!("-webkit-backface-visibility");
|
|
}
|
|
|
|
"clip-path" => {
|
|
same_content!("-webkit-clip-path");
|
|
}
|
|
|
|
"position" => {
|
|
if n.values.len() == 1 {
|
|
match &n.values[0] {
|
|
Value::Text(Text { value, .. }) => match &**value {
|
|
"sticky" => {
|
|
same_name!("-webkit-sticky");
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
"user-select" => {
|
|
same_content!("-webkit-user-select");
|
|
same_content!("-moz-user-select");
|
|
same_content!("-ms-user-select");
|
|
}
|
|
|
|
"transform" => {
|
|
same_content!("-webkit-transform");
|
|
same_content!("-moz-transform");
|
|
same_content!("-ms-transform");
|
|
}
|
|
|
|
"text-decoration" => {
|
|
if n.values.len() == 1 {
|
|
match &n.values[0] {
|
|
Value::Text(Text { value, .. }) => match &**value {
|
|
"none" => {
|
|
same_content!("-webkit-text-decoration");
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
"text-size-adjust" => {
|
|
if n.values.len() == 1 {
|
|
match &n.values[0] {
|
|
Value::Text(Text { value, .. }) => match &**value {
|
|
"none" => {
|
|
same_content!("-webkit-text-size-adjust");
|
|
same_content!("-moz-text-size-adjust");
|
|
same_content!("-ms-text-size-adjust");
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
"transition" => {
|
|
let mut values = n.values.clone();
|
|
replace_text(&mut values, "transform", "-webkit-transform");
|
|
self.added.push(Property {
|
|
span: n.span,
|
|
name: Text {
|
|
span: n.name.span,
|
|
value: "-webkit-transition".into(),
|
|
},
|
|
values,
|
|
important: n.important.clone(),
|
|
});
|
|
}
|
|
|
|
"writing-mode" => {
|
|
if n.values.len() == 1 {
|
|
match &n.values[0] {
|
|
Value::Text(Text { value, .. }) => match &**value {
|
|
"none" => {
|
|
same_content!("-webkit-writing-mode");
|
|
same_content!("-ms-writing-mode");
|
|
}
|
|
|
|
"vertical-lr" | "sideways-lr" => {
|
|
same_content!("-webkit-writing-mode");
|
|
simple!("-ms-writing-mode", "tb");
|
|
}
|
|
|
|
"vertical-rl" | "sideways-rl" => {
|
|
same_content!("-webkit-writing-mode");
|
|
simple!("-ms-writing-mode", "tb-rl");
|
|
}
|
|
|
|
"horizontal-tb" => {
|
|
same_content!("-webkit-writing-mode");
|
|
simple!("-ms-writing-mode", "lr");
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
"min-width" | "width" | "max-width" | "min-height" | "height" | "max-height"
|
|
| "min-block-size" | "min-inline-size" => {
|
|
if n.values.len() == 1 {
|
|
match &n.values[0] {
|
|
Value::Text(Text { value, .. }) => match &**value {
|
|
"fit-content" => {
|
|
same_name!("-webkit-fit-content");
|
|
same_name!("-moz-fit-content");
|
|
}
|
|
|
|
"max-content" => {
|
|
same_name!("-webkit-max-content");
|
|
same_name!("-moz-max-content");
|
|
}
|
|
|
|
"min-content" => {
|
|
same_name!("-webkit-min-content");
|
|
same_name!("-moz-min-content");
|
|
}
|
|
|
|
"fill-available" => {
|
|
same_name!("-webkit-fill-available");
|
|
same_name!("-moz-available");
|
|
}
|
|
|
|
"stretch" => {
|
|
same_name!("-webkit-fill-available");
|
|
same_name!("-moz-available");
|
|
same_name!("fill-available");
|
|
}
|
|
|
|
_ => {}
|
|
},
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|