Skip to content

Commit

Permalink
implement charset rule
Browse files Browse the repository at this point in the history
  • Loading branch information
keithamus committed Aug 5, 2023
1 parent f9b216f commit 73a914e
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 28 deletions.
15 changes: 15 additions & 0 deletions crates/hdx_ast/src/css/rules/charset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#[cfg(feature = "serde")]
use serde::Serialize;

use crate::Atom;

#[derive(Debug, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
// TODO: maybe make this an enum? Can use:
// https://www.iana.org/assignments/character-sets/character-sets.xhtml
pub struct Charset {
// Common charsets
// atom!("UTF-8")
// atom!("utf-8")
pub encoding: Atom,
}
2 changes: 2 additions & 0 deletions crates/hdx_ast/src/css/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod charset;
pub mod page;

pub use charset::*;
pub use page::*;
20 changes: 6 additions & 14 deletions crates/hdx_ast/src/css/stylesheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use crate::{
atom,
css::{
properties::Property,
rules::page::PageRule,
rules::{page::PageRule, Charset},
selector::Selector,
unknown::{UnknownAtRule, UnknownRule},
},
Atom, Box, Spanned, Vec,
Atom, Atomizable, Box, Spanned, Vec,
};

#[derive(Debug, PartialEq, Hash)]
Expand All @@ -29,24 +29,16 @@ pub enum StylesheetRule<'a> {
#[derive(Debug, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))]
pub enum AtRule<'a> {
Charset(Box<'a, Spanned<Charset>>),
Page(Box<'a, Spanned<PageRule<'a>>>),
Unknown(Box<'a, Spanned<UnknownAtRule<'a>>>),
}

#[derive(Debug, PartialEq, Hash)]
#[derive(Atomizable, Debug, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))]
pub enum AtRuleId {
Page,
Unknown,
}

impl AtRuleId {
pub fn from_atom(s: Atom) -> Self {
match s {
atom!("page") => Self::Page,
_ => Self::Unknown,
}
}
Charset, // atom!("charset")
Page, // atom!("page")
}

#[derive(Debug, PartialEq, Hash)]
Expand Down
1 change: 0 additions & 1 deletion crates/hdx_parser/src/css/parser_extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ 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 Down
14 changes: 14 additions & 0 deletions crates/hdx_parser/src/css/rules/charset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use hdx_ast::css::rules::charset::Charset;
use oxc_allocator::Vec;

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

impl<'a> Parse<'a> for Charset {
fn parse(parser: &mut Parser<'a>) -> Result<Spanned<Self>> {
let span = parser.cur().span;
parser.expect_at_keyword_of(atom!("charset"))?;
let encoding = parser.expect_string()?;
parser.expect(Kind::Semicolon)?;
Ok(Self { encoding }.spanned(span.up_to(&parser.cur().span)))
}
}
1 change: 1 addition & 0 deletions crates/hdx_parser/src/css/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod charset;
pub mod page;

use crate::{Kind, Parse, Parser, Result, Spanned};
Expand Down
2 changes: 0 additions & 2 deletions crates/hdx_parser/src/css/rules/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use crate::{atom, diagnostics, Atom, Atomizable, Kind, Parse, Parser, Result, Sp
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 Down Expand Up @@ -54,7 +53,6 @@ impl<'a> Parse<'a> for PageSelector<'a> {
}
if parser.at(Kind::Colon) {
loop {
dbg!(parser.cur());
pseudos.push(PagePseudoClass::parse(parser)?);
if !parser.at(Kind::Colon) {
break;
Expand Down
47 changes: 38 additions & 9 deletions crates/hdx_parser/src/css/stylesheet.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use hdx_ast::css::{
rules::page::PageRule,
rules::{page::PageRule, Charset},
selector::Selector,
stylesheet::{AtRule, AtRuleId, SelectorSet, StyleRule, Stylesheet, StylesheetRule},
unknown::{UnknownAtRule, UnknownRule},
};
use hdx_lexer::Kind;

use crate::{Parse, Parser, Result, Span, Spanned};
use crate::{diagnostics, Atomizable, Parse, Parser, Result, Span, Spanned};

// https://drafts.csswg.org/css-syntax-3/#consume-stylesheet-contents
impl<'a> Parse<'a> for Stylesheet<'a> {
Expand Down Expand Up @@ -45,14 +45,20 @@ impl<'a> Parse<'a> for AtRule<'a> {
fn parse(parser: &mut Parser<'a>) -> Result<Spanned<Self>> {
let span = parser.cur().span;
parser.expect_without_advance(Kind::AtKeyword)?;
Ok(match AtRuleId::from_atom(parser.cur().as_atom_lower().unwrap()) {
AtRuleId::Page => {
Ok(match AtRuleId::from_atom(parser.cur_atom_lower().unwrap()) {
Some(AtRuleId::Charset) => {
let rule = Charset::parse(parser)?;
AtRule::Charset(parser.boxup(rule)).spanned(span.up_to(&parser.cur().span))
}
Some(AtRuleId::Page) => {
let rule = PageRule::parse(parser)?;
AtRule::Page(parser.boxup(rule)).spanned(span.up_to(&parser.cur().span))
}
_ => {
None => {
let rule = UnknownAtRule::parse(parser)?;
AtRule::Unknown(parser.boxup(rule)).spanned(span.up_to(&parser.cur().span))
let rule_span = span.up_to(&parser.cur().span);
parser.warnings.push(diagnostics::UnknownRule(rule_span).into());
AtRule::Unknown(parser.boxup(rule)).spanned(rule_span)
}
})
}
Expand All @@ -68,10 +74,11 @@ impl<'a> Parse<'a> for SelectorSet<'a> {

#[cfg(test)]
mod test {
use hdx_ast::css::rules::Charset;
use oxc_allocator::Allocator;

use super::Stylesheet;
use crate::{Parser, ParserOptions};
use super::{AtRule, Stylesheet};
use crate::{atom, Parser, ParserOptions, Span, Spanned};

#[test]
fn smoke_test() {
Expand All @@ -82,6 +89,28 @@ mod test {
assert_eq!(ast.node.rules.len(), 0);
}

#[test]
fn parses_charset() {
let allocator = Allocator::default();
let parser = Parser::new(&allocator, "@charset \"utf-8\";", ParserOptions::default());
let expected = Spanned {
span: Span::new(0, 17),
node: AtRule::Charset(parser.boxup(Spanned {
span: Span::new(0, 17),
node: Charset { encoding: atom!("utf-8") },
})),
};
let parser_return = parser.parse_with::<AtRule>();
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);
}

#[test]
fn parses_two_rules() {
let allocator = Allocator::default();
Expand All @@ -91,13 +120,13 @@ mod test {
ParserOptions::default(),
);
let parser_return = parser.parse_with::<Stylesheet>();
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 ast = parser_return.output.unwrap();
assert_eq!(ast.node.rules.len(), 2);
}
}
14 changes: 12 additions & 2 deletions crates/hdx_writer/src/css/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,28 @@ use hdx_ast::{
css::{
component_values::{ComponentValue, Function, SimpleBlock},
properties::Custom,
rules::{PageMarginRule, PageRule, PageSelector, PageSelectorList},
rules::{Charset, PageMarginRule, PageRule, PageSelector, PageSelectorList},
stylesheet::{AtRule, StyleRule, Stylesheet, StylesheetRule},
unknown::{UnknownAtRule, UnknownDeclaration, UnknownPrelude, UnknownRule},
values::ValueLike,
},
Spanned,
};
use hdx_atom::Atomizable;
use hdx_atom::{atom, Atomizable};
use hdx_lexer::{Kind, PairWise, Token};
use oxc_allocator::Box;

use crate::{CssWriter, WriteCss};

impl<'a> WriteCss<'a> for Charset {
fn write_css<W: CssWriter>(&self, sink: &mut W) -> Result {
sink.write_str("@charset \"")?;
sink.write_str(self.encoding.as_ref())?;
sink.write_str("\";")?;
Ok(())
}
}

impl<'a> WriteCss<'a> for Stylesheet<'a> {
fn write_css<W: CssWriter>(&self, sink: &mut W) -> Result {
for rule in &self.rules {
Expand Down Expand Up @@ -69,6 +78,7 @@ impl<'a> WriteCss<'a> for StyleRule<'a> {
impl<'a> WriteCss<'a> for AtRule<'a> {
fn write_css<W: CssWriter>(&self, sink: &mut W) -> Result {
match self {
Self::Charset(rule) => rule.write_css(sink),
Self::Page(rule) => rule.write_css(sink),
Self::Unknown(rule) => rule.write_css(sink),
}
Expand Down

0 comments on commit 73a914e

Please sign in to comment.