Skip to content

Commit

Permalink
ensure !important is output for properties including custom ones
Browse files Browse the repository at this point in the history
  • Loading branch information
keithamus committed Aug 5, 2023
1 parent 14f0b90 commit e1c3398
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 48 deletions.
32 changes: 18 additions & 14 deletions crates/hdx_parser/src/css/properties.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
/// Properties
use hdx_ast::css::{properties::*, unknown::UnknownDeclaration, values::*};
use hdx_ast::css::{
component_values::ComponentValue, properties::*, unknown::UnknownDeclaration, values::*,
};
use miette::Result;

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

impl<'a> Parse<'a> for Custom<'a> {
fn parse(parser: &mut Parser<'a>) -> Result<Spanned<Self>> {
let span = parser.cur().span;
if !parser.at(Kind::Ident) {
todo!()
}
let mut important = false;
let name = parser.expect_ident_cased()?;
match parser.cur().kind {
Kind::Colon => {
parser.advance();
}
_ => {
todo!();
}
}
parser.expect(Kind::Colon)?;
let checkpoint = parser.checkpoint();
let value_span = parser.cur().span;
let value_like = ValueLike::parse(parser)
.unwrap_or(ValueLike::Unknown.spanned(value_span.up_to(&parser.cur().span)));
parser.rewind(checkpoint);
let value = parser.parse_component_values(Kind::Semicolon, true)?;
let mut value = parser.parse_component_values(Kind::Semicolon, true)?;
if parser.at(Kind::Semicolon) {
parser.advance();
}
Ok(Self { name, value_like, value: parser.boxup(value), important: false }
if let Some(Spanned { node: ComponentValue::Token(tok), .. }) = value.last() {
if tok.kind == Kind::Ident && tok.as_atom_lower().unwrap() == atom!("important") {
let len = value.len();
if let Some(Spanned { node: ComponentValue::Token(tok), .. }) = value.get(len - 2) {
if tok.kind == Kind::Delim && tok.value.as_char().unwrap() == '!' {
value.truncate(len - 2);
important = true
}
}
}
}
Ok(Self { name, value_like, value: parser.boxup(value), important }
.spanned(span.up_to(&parser.cur().span)))
}
}
Expand Down
33 changes: 1 addition & 32 deletions crates/hdx_writer/src/css/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ use std::{fmt::Result, ops::Deref};
use hdx_ast::{
css::{
component_values::{ComponentValue, Function, SimpleBlock},
properties::Custom,
rules::{Charset, PageMarginRule, PageRule, PageSelector, PageSelectorList},
stylesheet::{AtRule, StyleRule, Stylesheet, StylesheetRule},
unknown::{UnknownAtRule, UnknownDeclaration, UnknownPrelude, UnknownRule},
values::ValueLike,
},
Spanned,
};
use hdx_atom::{atom, Atomizable};
use hdx_atom::Atomizable;
use hdx_lexer::{Kind, PairWise, Token};
use oxc_allocator::Box;

Expand Down Expand Up @@ -276,36 +275,6 @@ impl<'a> WriteCss<'a> for UnknownDeclaration<'a> {
}
}

impl<'a> WriteCss<'a> for Custom<'a> {
fn write_css<W: CssWriter>(&self, sink: &mut W) -> Result {
sink.write_str(self.name.as_ref())?;
sink.write_char(':')?;
sink.write_trivia_char(' ')?;
match &self.value_like {
Spanned { span: _, node: ValueLike::Color(color) } => color.write_css(sink)?,
Spanned { span: _, node: ValueLike::Length(length) } => length.write_css(sink)?,
Spanned { span: _, node: ValueLike::LengthPercentage(length) } => {
length.write_css(sink)?
}
Spanned { span: _, node: ValueLike::FontFamily(font) } => font.write_css(sink)?,
_ => {
let mut values = self.value.iter().peekable();
while let Some(value) = values.next() {
value.write_css(sink)?;
if values.peek().is_some() {
sink.write_char(' ')?;
}
}
}
}
if self.important {
sink.write_trivia_char(' ')?;
sink.write_str("!important")?;
}
Ok(())
}
}

impl<'a> WriteCss<'a> for ComponentValue<'a> {
fn write_css<W: CssWriter>(&self, sink: &mut W) -> Result {
match self {
Expand Down
39 changes: 37 additions & 2 deletions crates/hdx_writer/src/css/properties.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,44 @@
use std::fmt::Result;

use hdx_ast::css::properties::*;
use hdx_ast::{
css::{properties::*, values::ValueLike},
Spanned,
};

use crate::{CssWriter, WriteCss};

impl<'a> WriteCss<'a> for Todo {
fn write_css<W: CssWriter>(&self, sink: &mut W) -> Result {
todo!()
todo!("Cannot write out Todo values")
}
}

impl<'a> WriteCss<'a> for Custom<'a> {
fn write_css<W: CssWriter>(&self, sink: &mut W) -> Result {
sink.write_str(self.name.as_ref())?;
sink.write_char(':')?;
sink.write_trivia_char(' ')?;
match &self.value_like {
Spanned { span: _, node: ValueLike::Color(color) } => color.write_css(sink)?,
Spanned { span: _, node: ValueLike::Length(length) } => length.write_css(sink)?,
Spanned { span: _, node: ValueLike::LengthPercentage(length) } => {
length.write_css(sink)?
}
Spanned { span: _, node: ValueLike::FontFamily(font) } => font.write_css(sink)?,
_ => {
let mut values = self.value.iter().peekable();
while let Some(value) = values.next() {
value.write_css(sink)?;
if values.peek().is_some() {
sink.write_char(' ')?;
}
}
}
}
if self.important {
sink.write_str("!important")?;
}
Ok(())
}
}

Expand All @@ -19,6 +51,9 @@ macro_rules! write_properties {
sink.write_char(':')?;
sink.write_trivia_char(' ')?;
self.value.write_css(sink)?;
if self.important {
sink.write_str("!important")?;
}
Ok(())
}
}
Expand Down

0 comments on commit e1c3398

Please sign in to comment.