Rewrite parsing to trait

This commit is contained in:
Adrian Wozniak 2020-04-29 23:27:16 +02:00
parent 899352dd9f
commit c036891396
5 changed files with 1499 additions and 1322 deletions

View File

@ -12,7 +12,6 @@ const INPUT: &str = "./jirs-client/js/styles.css";
type Css = Arc<RwLock<CssFile>>; type Css = Arc<RwLock<CssFile>>;
mod colors;
mod prop; mod prop;
#[derive(Debug)] #[derive(Debug)]

View File

@ -0,0 +1,496 @@
use crate::prop::{CssParser, ParseToken, Parser, PropertyValue, TimeProperty, Token, ValueResult};
#[derive(Debug, PartialEq)]
pub enum AnimationDirectionProperty {
Normal,
Reverse,
Alternate,
AlternateReverse,
Initial,
Inherit,
}
impl Token for AnimationDirectionProperty {}
impl ParseToken<AnimationDirectionProperty> for CssParser {
fn parse_token(&mut self) -> Result<PropertyValue<AnimationDirectionProperty>, String> {
let p = match self.expect_consume()?.as_str() {
"normal" => AnimationDirectionProperty::Normal,
"reverse" => AnimationDirectionProperty::Reverse,
"alternate" => AnimationDirectionProperty::Alternate,
"alternate-reverse" => AnimationDirectionProperty::AlternateReverse,
"initial" => AnimationDirectionProperty::Initial,
"inherit" => AnimationDirectionProperty::Inherit,
_ => return Err(format!("invalid animation direction {:?}", self.current)),
};
Ok(PropertyValue::Other(p))
}
}
#[derive(Debug, PartialEq)]
pub enum AnimationFillModeProperty {
None,
Forwards,
Backwards,
Both,
Initial,
Inherit,
}
impl Token for AnimationFillModeProperty {}
impl ParseToken<AnimationFillModeProperty> for CssParser {
fn parse_token(&mut self) -> ValueResult<AnimationFillModeProperty> {
let p = match self.expect_consume()?.as_str() {
"none" => AnimationFillModeProperty::None,
"forwards" => AnimationFillModeProperty::Forwards,
"backwards" => AnimationFillModeProperty::Backwards,
"both" => AnimationFillModeProperty::Both,
"initial" => AnimationFillModeProperty::Initial,
"inherit" => AnimationFillModeProperty::Inherit,
_ => return Err(format!("invalid animation fill mode {:?}", self.current)),
};
Ok(PropertyValue::Other(p))
}
}
#[derive(Debug, PartialEq)]
pub enum AnimationPlayStateProperty {
Paused,
Running,
Initial,
Inherit,
}
impl Token for AnimationPlayStateProperty {}
impl ParseToken<AnimationPlayStateProperty> for CssParser {
fn parse_token(&mut self) -> ValueResult<AnimationPlayStateProperty> {
self.skip_white();
let name = self.expect_consume()?;
let p = match name.as_str() {
"paused" => AnimationPlayStateProperty::Paused,
"running" => AnimationPlayStateProperty::Running,
"initial" => AnimationPlayStateProperty::Initial,
"inherit" => AnimationPlayStateProperty::Inherit,
_ => return Err(format!("invalid animation play state {:?}", name)),
};
Ok(PropertyValue::Other(p))
}
}
#[derive(Debug, PartialEq)]
pub enum AnimationTimingFunctionStepsProperty {
Start,
End,
}
impl Token for AnimationTimingFunctionStepsProperty {}
impl ParseToken<AnimationTimingFunctionStepsProperty> for CssParser {
fn parse_token(&mut self) -> ValueResult<AnimationTimingFunctionStepsProperty> {
let s = self.expect_consume()?;
let p = match s.to_lowercase().as_str() {
"start" => AnimationTimingFunctionStepsProperty::Start,
"end" => AnimationTimingFunctionStepsProperty::End,
_ => return Err(format!("invalid animation timing function step {:?}", s)),
};
Ok(PropertyValue::Other(p))
}
}
#[derive(Debug, PartialEq)]
pub enum AnimationTimingFunctionProperty {
Linear,
Ease,
EaseIn,
EaseOut,
EaseInOut,
StepStart,
StepEnd,
Steps(
PropertyValue<u32>,
PropertyValue<AnimationTimingFunctionStepsProperty>,
),
CubicBezier(
PropertyValue<f64>,
PropertyValue<f64>,
PropertyValue<f64>,
PropertyValue<f64>,
),
Initial,
Inherit,
}
impl Token for AnimationTimingFunctionProperty {}
impl ParseToken<AnimationTimingFunctionProperty> for CssParser {
fn parse_token(&mut self) -> ValueResult<AnimationTimingFunctionProperty> {
let current = self.expect_consume()?;
let p = match current.as_str() {
"linear" => AnimationTimingFunctionProperty::Linear,
"ease" => AnimationTimingFunctionProperty::Ease,
"ease-in" => AnimationTimingFunctionProperty::EaseIn,
"ease-out" => AnimationTimingFunctionProperty::EaseOut,
"ease-in-out" => AnimationTimingFunctionProperty::EaseInOut,
"step-start" => AnimationTimingFunctionProperty::StepStart,
"step-end" => AnimationTimingFunctionProperty::StepEnd,
"initial" => AnimationTimingFunctionProperty::Initial,
"inherit" => AnimationTimingFunctionProperty::Inherit,
"steps" => {
self.consume_expected("(")?;
self.skip_white();
let b = self.parse_token()?;
match b {
PropertyValue::Other(n) if n <= 0 => {
return Err(format!("invalid animation timing function, number of iterations must be greater than 0"));
}
_ => (),
}
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let c = self.parse_token()?;
self.skip_white();
self.consume_expected(")")?;
self.skip_white();
self.consume_semicolon()?;
AnimationTimingFunctionProperty::Steps(b, c)
}
"cubic-bezier" => {
self.consume_expected("(")?;
self.skip_white();
let a = self.parse_token()?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let b = self.parse_token()?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let c = self.parse_token()?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let d = self.parse_token()?;
self.skip_white();
self.consume_expected(")")?;
self.skip_white();
self.consume_semicolon()?;
AnimationTimingFunctionProperty::CubicBezier(a, b, c, d)
}
_ => return Err(format!("invalid animation timing function {:?}", current)),
};
Ok(PropertyValue::Other(p))
}
}
#[derive(Debug, PartialEq)]
pub enum AnimationDelayProperty {
Time(PropertyValue<TimeProperty>),
Initial,
Inherit,
}
impl Token for AnimationDelayProperty {}
impl ParseToken<AnimationDelayProperty> for CssParser {
fn parse_token(&mut self) -> Result<PropertyValue<AnimationDelayProperty>, String> {
let p = match self.peek().cloned().unwrap_or_default().as_str() {
"initial" => {
self.expect_consume()?;
AnimationDelayProperty::Initial
}
"inherit" => {
self.expect_consume()?;
AnimationDelayProperty::Inherit
}
_ => AnimationDelayProperty::Time(self.parse_token()?),
};
Ok(PropertyValue::Other(p))
}
}
#[derive(Debug, PartialEq)]
pub enum AnimationProperty {
Initial,
Inherit,
Custom(
String,
PropertyValue<TimeProperty>,
PropertyValue<AnimationTimingFunctionProperty>,
PropertyValue<AnimationDelayProperty>,
PropertyValue<usize>,
PropertyValue<AnimationDirectionProperty>,
PropertyValue<AnimationFillModeProperty>,
PropertyValue<AnimationPlayStateProperty>,
),
}
impl Token for AnimationProperty {}
impl ParseToken<AnimationProperty> for CssParser {
fn parse_token(&mut self) -> Result<PropertyValue<AnimationProperty>, String> {
eprintln!("only full animation is supported!");
if let Some(v) = self.try_parse_variable() {
return Ok(PropertyValue::Variable(v));
}
let def = self
.peek()
.cloned()
.ok_or_else(|| "expect to find token but EOF".to_string())?;
let p = match def.as_str() {
"initial" => {
self.expect_consume()?;
PropertyValue::Other(AnimationProperty::Initial)
}
"inherit" => {
self.expect_consume()?;
PropertyValue::Other(AnimationProperty::Inherit)
}
_ => {
let duration = if self.next_is_semicolon() {
PropertyValue::Other(TimeProperty::Seconds(0))
} else {
let v = self.parse_token()?;
self.skip_white();
v
};
let timing = if self.next_is_semicolon() {
PropertyValue::Other(AnimationTimingFunctionProperty::Ease)
} else {
let v = self.parse_token()?;
self.skip_white();
v
};
let delay = if self.next_is_semicolon() {
PropertyValue::Other(AnimationDelayProperty::Time(PropertyValue::Other(
TimeProperty::Seconds(0),
)))
} else {
let v = self.parse_token()?;
self.skip_white();
v
};
let iteration_count = if self.next_is_semicolon() {
PropertyValue::Other(1)
} else {
let v = self.expect_consume()?.parse::<usize>().map_err(|_| {
format!(
"invalid animation iteration count, expect number got {:?}",
self.current
)
})?;
self.skip_white();
PropertyValue::Other(v)
};
let direction = if self.next_is_semicolon() {
PropertyValue::Other(AnimationDirectionProperty::Normal)
} else {
let v = self.parse_token()?;
self.skip_white();
v
};
let fill_mode = if self.next_is_semicolon() {
PropertyValue::Other(AnimationFillModeProperty::None)
} else {
let v = self.parse_token()?;
self.skip_white();
v
};
let play_state = if self.next_is_semicolon() {
PropertyValue::Other(AnimationPlayStateProperty::Running)
} else {
let v = self.parse_token()?;
self.skip_white();
v
};
let name = self.expect_consume()?;
PropertyValue::Other(AnimationProperty::Custom(
name,
duration,
timing,
delay,
iteration_count,
direction,
fill_mode,
play_state,
))
}
};
Ok(p)
}
}
#[cfg(test)]
mod tests {
use crate::prop::CssTokenizer;
use super::*;
/// we assume currently we hit property name
/// display : block;
/// ^
/// so we need to add `:`
///
/// But we also we adding spaces around because they are allowed in css and needs to be skipped
fn parse_prop_value(s: &str) -> CssParser {
let full = format!(" : {} {}", s, if s.contains(";") { "" } else { ";" });
let tokens = CssTokenizer::new(full.as_str()).tokenize();
CssParser::new("", tokens)
}
#[test]
fn parse_animation_timing_function() {
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("linear").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::Linear,
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("ease").parse_token();
let expected = Ok(PropertyValue::Other(AnimationTimingFunctionProperty::Ease));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("ease-in").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::EaseIn,
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("ease-out").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::EaseOut,
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("ease-in-out").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::EaseInOut,
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("step-start").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::StepStart,
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("step-end").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::StepEnd,
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("steps(1,start)").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::Steps(
PropertyValue::Other(1),
PropertyValue::Other(AnimationTimingFunctionStepsProperty::Start),
),
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("steps(3,end)").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::Steps(
PropertyValue::Other(3),
PropertyValue::Other(AnimationTimingFunctionStepsProperty::End),
),
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("steps(0,start)").parse_token();
let expected = Err(
"invalid animation timing function, number of iterations must be greater than 0"
.to_string(),
);
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("steps(-2,start)").parse_token();
let expected =
Err("invalid token, expect number greater or equal 0 got \"-2\"".to_string());
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("steps(0,end)").parse_token();
let expected = Err(
"invalid animation timing function, number of iterations must be greater than 0"
.to_string(),
);
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("steps(-1,end)").parse_token();
let expected =
Err("invalid token, expect number greater or equal 0 got \"-1\"".to_string());
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("steps(end)").parse_token();
let expected =
Err("invalid token, expect number greater or equal 0 got \"end\"".to_string());
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("steps(start)").parse_token();
let expected =
Err("invalid token, expect number greater or equal 0 got \"start\"".to_string());
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("steps(0)").parse_token();
let expected = Err(
"invalid animation timing function, number of iterations must be greater than 0"
.to_string(),
);
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("steps(1)").parse_token();
let expected = Err("expect to find token \",\" but found \")\"".to_string());
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("cubic-bezier(0.1,0.2,0.3,0.4)").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::CubicBezier(
PropertyValue::Other(0.1),
PropertyValue::Other(0.2),
PropertyValue::Other(0.3),
PropertyValue::Other(0.4),
),
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("cubic-bezier(0.1, 0.2, 0.3, 0.4)").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::CubicBezier(
PropertyValue::Other(0.1),
PropertyValue::Other(0.2),
PropertyValue::Other(0.3),
PropertyValue::Other(0.4),
),
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("cubic-bezier(0.1,0.2,0.3)").parse_token();
let expected = Err("expect to find token \",\" but found \")\"".to_string());
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("cubic-bezier(0.1,0.2)").parse_token();
let expected = Err("expect to find token \",\" but found \")\"".to_string());
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("cubic-bezier(0.1)").parse_token();
let expected = Err("expect to find token \",\" but found \")\"".to_string());
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("initial").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::Initial,
));
assert_eq!(res, expected);
let res: ValueResult<AnimationTimingFunctionProperty> =
parse_prop_value("inherit").parse_token();
let expected = Ok(PropertyValue::Other(
AnimationTimingFunctionProperty::Inherit,
));
assert_eq!(res, expected);
}
}

View File

@ -1,47 +1,190 @@
use std::str::FromStr; use std::str::FromStr;
/// hsla(360, 100%, 100%, 1.0) use crate::prop::{CssParser, ParseToken, Parser, PropertyValue, Token, ValueResult};
/// 012345
/// hsl(360, 100%, 100%, 1.0) #[derive(Debug, PartialEq)]
/// 01234 pub enum ColorProperty {
pub fn parse_hsla(given: &str, parse_alpha: bool) -> Result<(u16, u8, u8, f64), String> { Name(String),
let start_idx = if parse_alpha { 5 } else { 4 }; Rgba(
let v: Vec<String> = given[start_idx..(given.len() - 1)] PropertyValue<u8>,
.split(',') PropertyValue<u8>,
.map(|s| s.to_string()) PropertyValue<u8>,
.collect(); PropertyValue<u8>,
let h = v ),
.get(0) Hsla(
.ok_or_else(|| format!("invalid color {:?}", given)) PropertyValue<u16>,
.and_then(|s| s.parse().map_err(|_| format!("invalid color {:?}", given)))?; PropertyValue<u8>,
let s = parse_percent(given, v.get(1))?; PropertyValue<u8>,
let l = parse_percent(given, v.get(2))?; PropertyValue<f64>,
let a = if parse_alpha { ),
v.get(3) Current,
.ok_or_else(|| format!("invalid color {:?}", given))
.and_then(|s| {
s.parse::<f64>()
.map_err(|_| format!("invalid color {:?}", given))
})?
} else {
1.0f64
};
Ok((h, s, l, a))
} }
fn parse_percent(s: &str, v: Option<&String>) -> Result<u8, String> { impl Token for ColorProperty {}
v.ok_or_else(|| format!("invalid color {:?}", s))
.and_then(|s| { impl ParseToken<ColorProperty> for CssParser {
if s.ends_with('%') { fn parse_token(&mut self) -> ValueResult<ColorProperty> {
Ok(s[0..(s.len() - 1)].to_string()) self.skip_white();
} else { let current = self.expect_consume()?;
Err(format!("invalid color {:?}", s)) let s = current.trim();
let p = match s {
"currentColor" => ColorProperty::Current,
_ if s.len() == 7 && s.starts_with('#') => {
let r = u8::from_str_radix(&s[1..=2], 16)
.map_err(|_| format!("invalid color {:?}", s))?;
let g = u8::from_str_radix(&s[3..=4], 16)
.map_err(|_| format!("invalid color {:?}", s))?;
let b = u8::from_str_radix(&s[5..=6], 16)
.map_err(|_| format!("invalid color {:?}", s))?;
ColorProperty::Rgba(
PropertyValue::Other(r),
PropertyValue::Other(g),
PropertyValue::Other(b),
PropertyValue::Other(255),
)
} }
}) _ if s.len() == 4 && s.starts_with('#') => {
.and_then(|s| { let _x = &s[1..=1];
s.parse::<u8>() let r = u8::from_str_radix(&s[1..=1].repeat(2), 16)
.map_err(|_| format!("invalid color {:?}", s)) .map_err(|_| format!("invalid color {:?}", s))?;
}) let g = u8::from_str_radix(&s[2..=2].repeat(2), 16)
.map_err(|_| format!("invalid color {:?}", s))?;
let b = u8::from_str_radix(&s[3..=3].repeat(2), 16)
.map_err(|_| format!("invalid color {:?}", s))?;
ColorProperty::Rgba(
PropertyValue::Other(r),
PropertyValue::Other(g),
PropertyValue::Other(b),
PropertyValue::Other(255),
)
}
_ if s.len() == 9 && s.starts_with('#') => {
let (r, g, b, a) = (
u8::from_str_radix(&s[1..=2], 16)
.map_err(|_| format!("invalid color {:?}", s))?,
u8::from_str_radix(&s[3..=4], 16)
.map_err(|_| format!("invalid color {:?}", s))?,
u8::from_str_radix(&s[5..=6], 16)
.map_err(|_| format!("invalid color {:?}", s))?,
u8::from_str_radix(&s[7..=8], 16)
.map_err(|_| format!("invalid color {:?}", s))?,
);
ColorProperty::Rgba(
PropertyValue::Other(r),
PropertyValue::Other(g),
PropertyValue::Other(b),
PropertyValue::Other(a),
)
}
"rgba" => {
self.skip_white();
self.consume_expected("(")?;
self.skip_white();
let r = self.parse_token()?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let g = self.parse_token()?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let b = self.parse_token()?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let a = self.parse_token()?.into_color_alpha();
self.skip_white();
self.consume_expected(")")?;
self.skip_white();
ColorProperty::Rgba(r, g, b, a)
}
"rgb" => {
self.skip_white();
self.consume_expected("(")?;
self.skip_white();
let r = self.parse_token()?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let g = self.parse_token()?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let b = self.parse_token()?;
self.skip_white();
let a = PropertyValue::Other(255);
self.skip_white();
self.consume_expected(")")?;
self.skip_white();
ColorProperty::Rgba(r, g, b, a)
}
"hsla" => {
self.skip_white();
self.consume_expected("(")?;
self.skip_white();
let h = self.parse_token()?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let s = self.parse_token()?;
self.consume_expected("%")?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let l = self.parse_token()?;
self.consume_expected("%")?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let a = self.parse_token()?;
match a {
PropertyValue::Other(f) if -0.001f64 > f || f > 1.001f64 => {
return Err(format!("out of range hsl alpha value {:?}", a))
}
_ => (),
};
self.skip_white();
self.consume_expected(")")?;
self.skip_white();
ColorProperty::Hsla(h, s, l, a)
}
"hsl" => {
self.skip_white();
self.consume_expected("(")?;
self.skip_white();
let h = self.parse_token()?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let s = self.parse_token()?;
self.consume_expected("%")?;
self.skip_white();
self.consume_expected(",")?;
self.skip_white();
let l = self.parse_token()?;
self.consume_expected("%")?;
let a = PropertyValue::Other(1f64);
self.skip_white();
self.consume_expected(")")?;
self.skip_white();
ColorProperty::Hsla(h, s, l, a)
}
_ => s
.parse::<Color>()
.map(|c| c.to_values())
.and_then(|(r, g, b)| {
Ok(ColorProperty::Rgba(
PropertyValue::Other(r),
PropertyValue::Other(g),
PropertyValue::Other(b),
PropertyValue::Other(255),
))
})?,
};
Ok(PropertyValue::Other(p))
}
} }
pub enum Color { pub enum Color {

File diff suppressed because it is too large Load Diff

55
jirs-css/tests/full.css Normal file
View File

@ -0,0 +1,55 @@
p > #foo + .bar {
align-content: space-between;
align-items: center;
align-self: auto;
all: inherit;
animation: 3s ease-in 1s 2 reverse both paused slidein;
animation-delay: 4ms;
animation-direction: alternate-reverse;
animation-duration: 5s;
animation-iteration-count: 9;
animation-name: my-animation;
animation-play-state: paused;
animation-timing-function: ease-in;
backface-visibility: visible;
background-attachment: local;
background-blend-mode: darken;
background-clip: content-box;
background-color: rgba(12, 34, 56, 0.6);
/* */
clear: left;
color: aqua;
display: block;
float: right;
justify-content: flex-end;
position: relative;
z-index: -2;
}
p > #foo ~ .bar {
align-content: var(--align-content);
align-items: var(--align-items);
align-self: var(--align-self);
all: var(--all);
animation: var(--animation);
animation-delay: var(--animation-delay);
animation-direction: var(--animation-direction);
animation-duration: var(--animation-duration);
animation-iteration-count: var(--animation-iteration-count);
animation-name: var(--animation-name);
animation-play-state: var(--animation-play-state);
animation-timing-function: var(--animation-timing-function);
backface-visibility: var(--backface-visibility);
background-attachment: var(--background-attachment);
background-blend-mode: var(--background-blend-mode);
background-clip: var(--background-clip);
background-color: var(--background-color);
/* */
clear: var(--clear);
color: var(--color);
display: var(--display);
float: var(--float);
justify-content: var(--justify-content);
position: var(--position);
z-index: var(--z-index);
}