Beginnings of at-rule parsing

This commit is contained in:
Tyler Hallada 2020-03-19 18:40:28 -04:00
parent 6a4c68a833
commit de742425d0
2 changed files with 103 additions and 18 deletions

View File

@ -1,25 +1,44 @@
use cssparser::{ use cssparser::{
AtRuleParser, CowRcStr, DeclarationListParser, DeclarationParser, ParseError, Parser, AtRuleParser, AtRuleType, CowRcStr, DeclarationListParser, DeclarationParser, ParseError, Parser,
ParserInput, QualifiedRuleParser, RuleListParser, SourceLocation, ParserInput, QualifiedRuleParser, RuleListParser, SourceLocation,
}; };
use std::fmt; use std::fmt;
use std::convert::Into; use std::convert::Into;
use std::error::Error; use std::error::Error;
#[derive(Debug)]
pub enum CssRule {
AtRule(CssAtRule),
StyleRule(CssStyleRule),
}
// TODO: try to use CowRcStr instead of Strings in these structs. // TODO: try to use CowRcStr instead of Strings in these structs.
// I tried to do it earlier but I ended up in lifetime hell in parse_block(). // I tried to do it earlier but I ended up in lifetime hell in parse_block().
#[derive(Debug)] #[derive(Debug)]
pub struct CssRule { pub struct CssStyleRule {
pub selectors: String, pub selectors: String,
pub declarations: Vec<CssDeclaration>, pub declarations: Vec<CssDeclaration>,
} }
#[derive(Debug)]
pub struct CssAtRule {
// TODO: put name into the string cache
pub name: String,
pub prelude: String,
pub block: Option<String>,
}
#[derive(Debug)] #[derive(Debug)]
pub struct CssDeclaration { pub struct CssDeclaration {
pub property: String, pub property: String,
pub value: String, pub value: String,
} }
struct CssAtRulePrelude {
name: String,
prelude: String,
}
#[derive(Debug)] #[derive(Debug)]
pub enum CssError {} pub enum CssError {}
@ -28,10 +47,60 @@ pub type CssParseError<'i> = ParseError<'i, CssError>;
struct CssParser; struct CssParser;
impl<'i> AtRuleParser<'i> for CssParser { impl<'i> AtRuleParser<'i> for CssParser {
type PreludeBlock = (); type PreludeBlock = CssAtRulePrelude;
type PreludeNoBlock = (); type PreludeNoBlock = CssAtRulePrelude;
type AtRule = CssRule; type AtRule = CssRule;
type Error = CssError; type Error = CssError;
fn parse_prelude<'t>(
&mut self,
name: CowRcStr<'i>,
input: &mut Parser<'i, 't>,
) -> Result<AtRuleType<Self::PreludeNoBlock, Self::PreludeBlock>, CssParseError<'i>> {
let position = input.position();
while input.next().is_ok() {}
match_ignore_ascii_case! { &*name,
"import" | "namespace" | "charset" => {
Ok(AtRuleType::WithoutBlock(CssAtRulePrelude {
name: name.to_string(),
prelude: input.slice_from(position).to_string(),
}))
},
_ => {
Ok(AtRuleType::WithBlock(CssAtRulePrelude {
name: name.to_string(),
prelude: input.slice_from(position).to_string(),
}))
}
}
}
fn parse_block<'t>(
&mut self,
prelude: Self::PreludeBlock,
_location: SourceLocation,
input: &mut Parser<'i, 't>
) -> Result<Self::AtRule, CssParseError<'i>> {
let position = input.position();
while input.next().is_ok() {}
Ok(CssRule::AtRule(CssAtRule {
name: prelude.name,
prelude: prelude.prelude,
block: Some(input.slice_from(position).to_string()),
}))
}
fn rule_without_block(
&mut self,
prelude: Self::PreludeNoBlock,
_location: SourceLocation
) -> Self::AtRule {
CssRule::AtRule(CssAtRule {
name: prelude.name,
prelude: prelude.prelude,
block: None,
})
}
} }
impl<'i> QualifiedRuleParser<'i> for CssParser { impl<'i> QualifiedRuleParser<'i> for CssParser {
@ -54,10 +123,10 @@ impl<'i> QualifiedRuleParser<'i> for CssParser {
_location: SourceLocation, _location: SourceLocation,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
) -> Result<CssRule, CssParseError<'i>> { ) -> Result<CssRule, CssParseError<'i>> {
Ok(CssRule { Ok(CssRule::StyleRule(CssStyleRule {
selectors, selectors,
declarations: parse_declarations(input).unwrap(), declarations: parse_declarations(input).unwrap(),
}) }))
} }
} }

View File

@ -5,6 +5,7 @@ extern crate lazy_static;
extern crate html5ever; extern crate html5ever;
#[macro_use] #[macro_use]
extern crate maplit; extern crate maplit;
#[macro_use]
extern crate cssparser; extern crate cssparser;
extern crate string_cache; extern crate string_cache;
extern crate typed_arena; extern crate typed_arena;
@ -30,7 +31,7 @@ mod css_parser;
use arena_dom::{create_element, html5ever_parse_slice_into_arena, Arena, NodeData, Ref}; use arena_dom::{create_element, html5ever_parse_slice_into_arena, Arena, NodeData, Ref};
use config::permissive::{ADD_ATTRIBUTES, ALL_ATTRIBUTES, ATTRIBUTES, ELEMENTS, PROTOCOLS}; use config::permissive::{ADD_ATTRIBUTES, ALL_ATTRIBUTES, ATTRIBUTES, ELEMENTS, PROTOCOLS};
use config::relaxed::CSS_PROPERTIES; use config::relaxed::CSS_PROPERTIES;
use css_parser::{parse_css_style_attribute, parse_css_stylesheet}; use css_parser::{CssRule, parse_css_style_attribute, parse_css_stylesheet};
use css_property::CssProperty; use css_property::CssProperty;
fn main() { fn main() {
@ -91,19 +92,34 @@ fn transform_node<'arena>(node: Ref<'arena>, arena: Arena<'arena>) {
dbg!(&rules); dbg!(&rules);
let mut sanitized_css = String::new(); let mut sanitized_css = String::new();
for rule in rules { for rule in rules {
sanitized_css += &rule.selectors.trim(); match rule {
sanitized_css += " {\n"; CssRule::StyleRule(style_rule) => {
for declaration in rule.declarations.into_iter() { sanitized_css += &style_rule.selectors.trim();
let declaration_string = &declaration.to_string(); sanitized_css += " {\n";
if CSS_PROPERTIES for declaration in style_rule.declarations.into_iter() {
.contains(&CssProperty::from(declaration.property)) let declaration_string = &declaration.to_string();
{ if CSS_PROPERTIES
sanitized_css += " "; .contains(&CssProperty::from(declaration.property))
sanitized_css += declaration_string; {
sanitized_css += " "; sanitized_css += " ";
sanitized_css += declaration_string;
sanitized_css += " ";
}
}
sanitized_css += "\n}";
},
CssRule::AtRule(at_rule) => {
dbg!(&at_rule);
sanitized_css += &format!("@{} ", at_rule.name);
sanitized_css += &at_rule.prelude.trim();
if let Some(block) = at_rule.block {
sanitized_css += " {\n";
sanitized_css += &block.trim();
sanitized_css += "\n}";
}
} }
} }
sanitized_css += "\n}"; sanitized_css += "\n";
} }
let sanitized_css = sanitized_css.trim(); let sanitized_css = sanitized_css.trim();
dbg!(&sanitized_css); dbg!(&sanitized_css);