Skip to content

Commit

Permalink
fixup broken @page rule parse/write
Browse files Browse the repository at this point in the history
  • Loading branch information
keithamus committed Aug 5, 2023
1 parent 9d0e813 commit f9b216f
Show file tree
Hide file tree
Showing 7 changed files with 533 additions and 217 deletions.
2 changes: 1 addition & 1 deletion crates/hdx_ast/src/css/rules/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
pub struct PageRule<'a> {
#[cfg_attr(feature = "serde", serde(borrow))]
pub selectors: Box<'a, Option<Spanned<PageSelectorList<'a>>>>,
pub selectors: Box<'a, Spanned<PageSelectorList<'a>>>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub properties: Box<'a, Vec<'a, Spanned<Property<'a>>>>,
#[cfg_attr(feature = "serde", serde(borrow))]
Expand Down
2 changes: 1 addition & 1 deletion crates/hdx_parser/src/css/parser_extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ impl<'a> Parser<'a> {
return result;
}
Kind::LeftCurly => {
dbg!(self.cur());
return self.parse_block(
|parser: &mut Parser<'a>,
rules: Vec<'a, Spanned<Rule>>,
Expand All @@ -113,7 +114,6 @@ impl<'a> Parser<'a> {
}
_ => {
prelude = Some(Prelude::parse(self)?);
self.advance();
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions crates/hdx_parser/src/css/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
pub mod page;

use crate::{Kind, Parse, Parser, Result, Spanned};

pub struct NoPreludeAllowed;
impl<'a> Parse<'a> for NoPreludeAllowed {
fn parse(parser: &mut Parser<'a>) -> Result<Spanned<Self>> {
let span = parser.cur().span;
parser.expect_without_advance(Kind::LeftCurly)?;
Ok(Self {}.spanned(span.up_to(&parser.cur().span)))
}
}
109 changes: 96 additions & 13 deletions crates/hdx_parser/src/css/rules/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ use hdx_ast::css::{
};
use oxc_allocator::Vec;

use super::NoPreludeAllowed;
use crate::{atom, diagnostics, Atom, Atomizable, Kind, Parse, Parser, Result, Spanned};

impl<'a> Parse<'a> for PageRule<'a> {
fn parse(parser: &mut Parser<'a>) -> Result<Spanned<Self>> {
let span = parser.cur().span;
dbg!(parser.cur());
parser.parse_at_rule(
Some(atom!("page")),
|parser: &mut Parser<'a>,
Expand All @@ -19,7 +21,9 @@ impl<'a> Parse<'a> for PageRule<'a> {
rules: Vec<'a, Spanned<PageMarginRule<'a>>>,
properties: Vec<'a, Spanned<Property<'a>>>| {
Ok(Self {
selectors: parser.boxup(selectors),
selectors: parser.boxup(selectors.unwrap_or_else(|| {
Spanned::dummy(PageSelectorList { children: parser.new_vec() })
})),
properties: parser.boxup(properties),
rules: parser.boxup(rules),
}
Expand All @@ -32,8 +36,9 @@ impl<'a> Parse<'a> for PageRule<'a> {
impl<'a> Parse<'a> for PageSelectorList<'a> {
fn parse(parser: &mut Parser<'a>) -> Result<Spanned<Self>> {
let span = parser.cur().span;
Ok(Self { children: parser.parse_comma_list_of::<PageSelector>()? }
.spanned(span.up_to(&parser.cur().span)))
let ok = Ok(Self { children: parser.parse_comma_list_of::<PageSelector>()? }
.spanned(span.up_to(&parser.cur().span)));
ok
}
}

Expand All @@ -43,20 +48,19 @@ impl<'a> Parse<'a> for PageSelector<'a> {
let mut page_type = None;
let mut pseudos = parser.new_vec();
if parser.at(Kind::Ident) {
println!("PageSelector::page_type assigning to {:?}", parser.cur());
page_type = Some(parser.expect_ident()?);
} else {
parser.expect_without_advance(Kind::Colon)?;
}
if parser.at(Kind::Colon) {
loop {
dbg!(parser.cur());
pseudos.push(PagePseudoClass::parse(parser)?);
if !parser.at(Kind::Colon) {
break;
}
pseudos.push(PagePseudoClass::parse(parser)?);
}
}
println!("PageSelector::OK(self) {:?} {:?}", page_type, pseudos);
Ok(Self { page_type, pseudos }.spanned(span.up_to(&parser.cur().span)))
}
}
Expand All @@ -80,7 +84,7 @@ impl<'a> Parse<'a> for PageMarginRule<'a> {
None,
|parser: &mut Parser<'a>,
_name: Atom,
_prelude: Option<Spanned<IgnoreWhitespaceInPageMarginPrelude>>,
_prelude: Option<Spanned<NoPreludeAllowed>>,
_rules: Vec<'a, Spanned<PageMarginRule<'a>>>,
properties: Vec<'a, Spanned<Property<'a>>>| {
Ok(Self { margin_box: PageMarginBox::TopLeft, properties }
Expand All @@ -90,11 +94,90 @@ impl<'a> Parse<'a> for PageMarginRule<'a> {
}
}

struct IgnoreWhitespaceInPageMarginPrelude;
impl<'a> Parse<'a> for IgnoreWhitespaceInPageMarginPrelude {
fn parse(parser: &mut Parser<'a>) -> Result<Spanned<Self>> {
let span = parser.cur().span;
parser.expect_without_advance(Kind::LeftCurly)?;
Ok(Self {}.spanned(span.up_to(&parser.cur().span)))
#[cfg(test)]
mod test {
use hdx_ast::{
css::{
properties::{Background, Property},
rules::{PagePseudoClass, PageRule, PageSelector, PageSelectorList},
values::{ColorValue, NamedColor},
},
Spanned,
};
use oxc_allocator::Allocator;

use crate::{Atom, Parser, ParserOptions, Span, Vec};

#[test]
fn parses_toc_left_selector() {
let allocator = Allocator::default();
let parser = Parser::new(&allocator, "toc:left", ParserOptions::default());
let parser_return = parser.parse_with::<PageSelectorList>();
let ast = parser_return.output.unwrap();
if !parser_return.errors.is_empty() {
panic!("{:?}", parser_return.errors[0]);
}
if !parser_return.warnings.is_empty() {
panic!("{:?}", parser_return.warnings[0]);
}
let mut children = Vec::new_in(&allocator);
let mut pseudos = Vec::new_in(&allocator);
pseudos.push(Spanned { span: Span::new(3, 8), node: PagePseudoClass::Left });
children.push(Spanned {
span: Span::new(0, 8),
node: PageSelector { page_type: Some(Atom::from("toc")), pseudos },
});
assert_eq!(ast, Spanned { span: Span::new(0, 8), node: PageSelectorList { children } });
}

#[test]
fn parses_toc_left_page_rule_with_bakcground_black() {
let allocator = Allocator::default();
let parser = Parser::new(
&allocator,
"@page toc:left { background: black; }",
ParserOptions::default(),
);
let mut children = Vec::new_in(&allocator);
let mut pseudos = Vec::new_in(&allocator);
pseudos.push(Spanned { span: Span::new(9, 15), node: PagePseudoClass::Left });
children.push(Spanned {
span: Span::new(6, 15),
node: PageSelector { page_type: Some(Atom::from("toc")), pseudos },
});
let mut properties = Vec::new_in(&allocator);
properties.push(Spanned {
span: Span::new(17, 36),
node: Property::Background({
parser.boxup(Spanned {
span: Span::new(17, 36),
node: Background {
value: parser.boxup(Spanned {
span: Span::new(29, 34),
node: ColorValue::Named(NamedColor::Black),
}),
important: false,
},
})
}),
});
let expected = Spanned {
span: Span::new(0, 37),
node: PageRule {
selectors: parser
.boxup(Spanned { span: Span::new(6, 15), node: PageSelectorList { children } }),
properties: parser.boxup(properties),
rules: parser.boxup(Vec::new_in(&allocator)),
},
};
let parser_return = parser.parse_entirely_with::<PageRule>();
if !parser_return.errors.is_empty() {
panic!("{:?}", parser_return.errors[0]);
}
if !parser_return.warnings.is_empty() {
panic!("{:?}", parser_return.warnings[0]);
}
let ast = parser_return.output.unwrap();
assert_eq!(ast, expected);
}
}
9 changes: 5 additions & 4 deletions crates/hdx_writer/src/css/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ impl<'a> WriteCss<'a> for AtRule<'a> {
impl<'a> WriteCss<'a> for PageRule<'a> {
fn write_css<W: CssWriter>(&self, sink: &mut W) -> Result {
sink.write_str("@page")?;
sink.write_trivia_char(' ')?;
if let Some(selectors) = &*self.selectors {
selectors.write_css(sink)?;
if self.selectors.node.children.len() > 0 {
sink.write_char(' ')?;
}
self.selectors.write_css(sink)?;
if self.selectors.node.children.len() > 0 {
sink.write_trivia_char(' ')?;
}
sink.write_char('{')?;
Expand Down Expand Up @@ -127,7 +129,6 @@ impl<'a> WriteCss<'a> for PageSelector<'a> {
fn write_css<W: CssWriter>(&self, sink: &mut W) -> Result {
if let Some(page_type) = &self.page_type {
sink.write_str(page_type.as_ref())?;
sink.write_char(' ')?;
}
for pseudo in self.pseudos.iter() {
sink.write_char(':')?;
Expand Down
Loading

0 comments on commit f9b216f

Please sign in to comment.