Skip to content

Commit 06eb5be

Browse files
committed
Add property parser
1 parent 983e90b commit 06eb5be

File tree

5 files changed

+119
-43
lines changed

5 files changed

+119
-43
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern crate selectors;
88

99
mod parser;
1010
mod media_query;
11+
mod properties;
1112

1213
use napi::{CallContext, JsObject, JsUndefined};
1314
use serde::{Deserialize, Serialize};

src/parser.rs

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use selectors::{SelectorList, parser::SelectorImpl};
33
use std::fmt;
44
use std::cell::RefCell;
55
use crate::media_query::*;
6+
use crate::properties::*;
67

78
#[derive(Debug, Clone)]
89
pub struct Selectors;
@@ -155,7 +156,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser {
155156
type PreludeNoBlock = AtRulePrelude;
156157
type PreludeBlock = AtRulePrelude;
157158
type AtRule = (SourcePosition, CssRule);
158-
type Error = selectors::parser::SelectorParseErrorKind<'i>;
159+
type Error = ();
159160

160161
fn parse_prelude<'t>(
161162
&mut self,
@@ -288,7 +289,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser {
288289
impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser {
289290
type Prelude = SelectorList<Selectors>;
290291
type QualifiedRule = (SourcePosition, CssRule);
291-
type Error = selectors::parser::SelectorParseErrorKind<'i>;
292+
type Error = ();
292293

293294
#[inline]
294295
fn parse_prelude<'t>(
@@ -358,20 +359,20 @@ impl ToCss for ImportRule {
358359
#[derive(Debug)]
359360
pub struct StyleRule {
360361
pub selectors: SelectorList<Selectors>,
361-
pub declarations: Vec<(String, Vec<Value>)>
362+
pub declarations: Vec<Property>
362363
}
363364

364365
impl ToCss for StyleRule {
365366
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
366367
// dest.write_str(&self.selectors)?;
367368
self.selectors.to_css(dest)?;
368369
dest.write_str(" { ")?;
369-
for (key, val) in self.declarations.iter() {
370-
dest.write_str("\n ")?;
371-
dest.write_str(key)?;
372-
dest.write_str(": ")?;
373-
// dest.write_str(val)?;
374-
}
370+
// for (key, val) in self.declarations.iter() {
371+
// dest.write_str("\n ")?;
372+
// dest.write_str(key)?;
373+
// dest.write_str(": ")?;
374+
// // dest.write_str(val)?;
375+
// }
375376
dest.write_str("\n}")
376377
}
377378
}
@@ -424,7 +425,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser {
424425
type PreludeNoBlock = AtRulePrelude;
425426
type PreludeBlock = AtRulePrelude;
426427
type AtRule = CssRule;
427-
type Error = selectors::parser::SelectorParseErrorKind<'i>;
428+
type Error = ();
428429

429430
fn parse_prelude<'t>(
430431
&mut self,
@@ -648,33 +649,33 @@ pub enum Value {
648649
Url(String)
649650
}
650651

651-
fn exhaust<'i>(input: &mut cssparser::Parser<'i, '_>) -> Vec<Value> {
652+
// fn exhaust<'i>(input: &mut cssparser::Parser<'i, '_>) -> Vec<Value> {
652653
// let start = input.position();
653654
// while input.next().is_ok() {}
654655
// input.slice_from(start)
655-
let mut val = vec![];
656-
loop {
657-
if let Ok(tok) = input.next() {
658-
println!("{:?}", tok);
659-
match tok {
660-
Token::UnquotedUrl(ref url) => val.push(Value::Url((&**url).into())),
661-
Token::Function(ref name) if name.eq_ignore_ascii_case("url") => {
662-
let url = input.parse_nested_block(|input| {
663-
input.expect_string().map_err(Into::into).map(|s| s.clone())
664-
})
665-
.map_err(ParseError::<()>::basic);
666-
if let Ok(url) = url {
667-
val.push(Value::Url((&*url).into()));
668-
}
669-
},
670-
_ => {}
671-
}
672-
} else {
673-
break
674-
}
675-
}
676-
val
677-
}
656+
// let mut val = vec![];
657+
// loop {
658+
// if let Ok(tok) = input.next() {
659+
// println!("{:?}", tok);
660+
// match tok {
661+
// Token::UnquotedUrl(ref url) => val.push(Value::Url((&**url).into())),
662+
// Token::Function(ref name) if name.eq_ignore_ascii_case("url") => {
663+
// let url = input.parse_nested_block(|input| {
664+
// input.expect_string().map_err(Into::into).map(|s| s.clone())
665+
// })
666+
// .map_err(ParseError::<()>::basic);
667+
// if let Ok(url) = url {
668+
// val.push(Value::Url((&*url).into()));
669+
// }
670+
// },
671+
// _ => {}
672+
// }
673+
// } else {
674+
// break
675+
// }
676+
// }
677+
// val
678+
// }
678679

679680
struct SelectorParser;
680681
impl<'i> selectors::parser::Parser<'i> for SelectorParser {
@@ -685,7 +686,7 @@ impl<'i> selectors::parser::Parser<'i> for SelectorParser {
685686
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser {
686687
type Prelude = SelectorList<Selectors>;
687688
type QualifiedRule = CssRule;
688-
type Error = selectors::parser::SelectorParseErrorKind<'i>;
689+
type Error = ();
689690

690691
fn parse_prelude<'t>(
691692
&mut self,
@@ -696,7 +697,10 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser {
696697
// namespaces: self.namespaces,
697698
// url_data: Some(self.context.url_data),
698699
};
699-
SelectorList::parse(&selector_parser, input)
700+
match SelectorList::parse(&selector_parser, input) {
701+
Ok(x) => Ok(x),
702+
Err(_) => Err(input.new_error(BasicParseErrorKind::QualifiedRuleInvalid))
703+
}
700704
// Ok(exhaust(input))
701705
}
702706

@@ -727,22 +731,22 @@ struct PropertyDeclarationParser;
727731

728732
/// Parse a declaration within {} block: `color: blue`
729733
impl<'i> cssparser::DeclarationParser<'i> for PropertyDeclarationParser {
730-
type Declaration = (String, Vec<Value>);
731-
type Error = selectors::parser::SelectorParseErrorKind<'i>;
734+
type Declaration = Property;
735+
type Error = ();
732736

733737
fn parse_value<'t>(
734738
&mut self,
735739
name: CowRcStr<'i>,
736740
input: &mut cssparser::Parser<'i, 't>,
737741
) -> Result<Self::Declaration, cssparser::ParseError<'i, Self::Error>> {
738-
Ok((name.as_ref().into(), exhaust(input).into()))
742+
Property::parse(name, input)
739743
}
740744
}
741745

742746
/// Default methods reject all at rules.
743747
impl<'i> AtRuleParser<'i> for PropertyDeclarationParser {
744748
type PreludeNoBlock = ();
745749
type PreludeBlock = ();
746-
type AtRule = (String, Vec<Value>);
747-
type Error = selectors::parser::SelectorParseErrorKind<'i>;
750+
type AtRule = Property;
751+
type Error = ();
748752
}

src/properties/custom.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use cssparser::*;
2+
3+
#[derive(Debug)]
4+
pub struct CustomProperty {
5+
pub name: String,
6+
pub value: String
7+
}
8+
9+
impl CustomProperty {
10+
pub fn parse<'i, 't>(
11+
name: CowRcStr<'i>,
12+
input: &mut Parser<'i, 't>,
13+
) -> Result<Self, ParseError<'i, ()>> {
14+
input.skip_whitespace();
15+
input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| {
16+
// Need at least one token
17+
let start = input.state();
18+
input.next_including_whitespace()?;
19+
input.reset(&start);
20+
21+
// parse_declaration_value_block(input, references, missing_closing_characters)
22+
let start = input.position();
23+
loop {
24+
match input.next_including_whitespace_and_comments() {
25+
Ok(_) => {},
26+
Err(..) => {
27+
return Ok(CustomProperty {
28+
name: name.as_ref().into(),
29+
value: input.slice_from(start).trim_end().into()
30+
})
31+
},
32+
};
33+
}
34+
})
35+
}
36+
}

src/properties/mod.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
mod custom;
2+
3+
use cssparser::*;
4+
use custom::*;
5+
6+
#[derive(Debug)]
7+
pub enum Property {
8+
BackgroundColor(Color),
9+
Color(Color),
10+
Custom(CustomProperty)
11+
}
12+
13+
impl Property {
14+
pub fn parse<'i, 't>(name: CowRcStr<'i>, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ()>> {
15+
macro_rules! property {
16+
($property: ident, $type: ident) => {
17+
if let Ok(c) = $type::parse(input) {
18+
return Ok(Property::$property(c))
19+
}
20+
};
21+
}
22+
23+
let state = input.state();
24+
match name.as_ref() {
25+
"background-color" => property!(BackgroundColor, Color),
26+
"color" => property!(Color, Color),
27+
_ => {}
28+
}
29+
30+
input.reset(&state);
31+
return Ok(Property::Custom(CustomProperty::parse(name, input)?))
32+
}
33+
}

test.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ css.transform({
77
@import "foo.css" print;
88
99
.foo + .bar:not(.baz) {
10-
background: url(img.png), url('test.jpg');
10+
background-color: blue;
11+
// background: url(img.png), url('test.jpg');
1112
color: blue;
1213
}
1314
1415
.hi {}
1516
1617
@media screen and (max-width: 250px) {
1718
.baz {
18-
background: url(img.png);
19+
// background: url(img.png) ;
20+
color: var(--test);
1921
}
2022
}
2123
`)})

0 commit comments

Comments
 (0)