Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start using the ToCss trait, to be used for CSS serialization #4455

Merged
merged 8 commits into from Dec 29, 2014

Implement ToCss for types in style::properties::common_values::specified

  • Loading branch information
SimonSapin committed Dec 29, 2014
commit 45a08c94a448f7c16b19ea48be7661e474902d65
@@ -50,3 +50,49 @@ pub fn plugin_registrar(reg: &mut Registry) {
reg.register_lint_pass(box lints::InheritancePass as LintPassObject);
}


#[macro_export]
macro_rules! define_css_keyword_enum {
($name: ident: $( $css: expr => $variant: ident ),+,) => {
define_css_keyword_enum!($name: $( $css => $variant ),+)
};
($name: ident: $( $css: expr => $variant: ident ),+) => {
#[allow(non_camel_case_types)]
#[deriving(Clone, Eq, PartialEq, FromPrimitive)]
pub enum $name {
$( $variant ),+
}

impl $name {
pub fn parse(component_value: &::cssparser::ast::ComponentValue) -> Result<$name, ()> {
use std::ascii::AsciiExt;
match component_value {
&::cssparser::ast::Ident(ref value) => {
match value.to_ascii_lower().as_slice() {
$( concat!($css) => Ok($name::$variant), )+
_ => Err(())
}
}
_ => Err(())
}
}
}

impl ::std::fmt::Show for $name {
#[inline]
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
use cssparser::ToCss;
self.fmt_to_css(f)
}
}

impl ::cssparser::ToCss for $name {
fn to_css<W>(&self, dest: &mut W) -> ::text_writer::Result
where W: ::text_writer::TextWriter {
match self {
$( &$name::$variant => dest.write_str($css) ),+
}
}
}
}
}
@@ -18,6 +18,7 @@ extern crate collections;
extern crate geom;
extern crate serialize;
extern crate sync;
extern crate text_writer;
extern crate url;

extern crate cssparser;
@@ -27,6 +28,9 @@ extern crate string_cache;
#[phase(plugin)]
extern crate string_cache_macros;

#[phase(plugin)]
extern crate plugins;

#[phase(plugin)]
extern crate lazy_static;

@@ -14,11 +14,11 @@ pub mod specified {
use std::ascii::AsciiExt;
use std::f64::consts::PI;
use std::fmt;
use std::fmt::{Formatter, FormatError, Show};
use std::fmt::{Formatter, Show};
use url::Url;
use cssparser;
use cssparser::ast;
use cssparser::{mod, ast, ToCss, CssStringWriter};
use cssparser::ast::*;
use text_writer::{mod, TextWriter};
use parsing_utils::{mod, BufferedIter, ParserIter};
use super::{Au, CSSFloat};

@@ -42,11 +42,16 @@ pub mod specified {
})
}
}

impl fmt::Show for CSSColor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for CSSColor {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self.authored {
Some(ref s) => write!(f, "{}", s),
None => write!(f, "{}", self.parsed),
Some(ref s) => dest.write_str(s.as_slice()),
None => self.parsed.to_css(dest),
}
}
}
@@ -57,22 +62,30 @@ pub mod specified {
pub authored: Option<String>,
}
impl fmt::Show for CSSRGBA {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for CSSRGBA {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self.authored {
Some(ref s) => write!(f, "{}", s),
None => write!(f, "{}", self.parsed),
Some(ref s) => dest.write_str(s.as_slice()),
None => self.parsed.to_css(dest),
}
}
}

#[deriving(Clone, PartialEq)]
pub struct CSSImage(pub Option<Image>);

impl fmt::Show for CSSImage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let &CSSImage(ref url) = self;
match url {
&Some(ref image) => write!(f, "{}", image),
&None => write!(f, "none"),
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for CSSImage {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&CSSImage(Some(ref image)) => image.to_css(dest),
&CSSImage(None) => dest.write_str("none"),
}
}
}
@@ -97,17 +110,24 @@ pub mod specified {
// Vmin(CSSFloat),
// Vmax(CSSFloat),
}

impl fmt::Show for Length {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for Length {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&Length::Au(length) => write!(f, "{}", length),
&Length::Em(length) => write!(f, "{}em", length),
&Length::Ex(length) => write!(f, "{}ex", length),
&Length::Rem(length) => write!(f, "{}rem", length),
&Length::ServoCharacterWidth(_) => panic!("internal CSS values should never be serialized"),
&Length::Au(length) => write!(dest, "{}px", length.to_subpx()),
&Length::Em(length) => write!(dest, "{}em", length),
&Length::Ex(length) => write!(dest, "{}ex", length),
&Length::Rem(length) => write!(dest, "{}rem", length),
&Length::ServoCharacterWidth(_)
=> panic!("internal CSS values should never be serialized"),
}
}
}

const AU_PER_PX: CSSFloat = 60.;
const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
@@ -156,11 +176,17 @@ pub mod specified {
Length(Length),
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
}

impl fmt::Show for LengthOrPercentage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for LengthOrPercentage {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&LengthOrPercentage::Length(length) => write!(f, "{}", length),
&LengthOrPercentage::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
&LengthOrPercentage::Length(length) => length.to_css(dest),
&LengthOrPercentage::Percentage(percentage)
=> write!(dest, "{}%", percentage * 100.),
}
}
}
@@ -195,12 +221,18 @@ pub mod specified {
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
Auto,
}

impl fmt::Show for LengthOrPercentageOrAuto {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for LengthOrPercentageOrAuto {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&LengthOrPercentageOrAuto::Length(length) => write!(f, "{}", length),
&LengthOrPercentageOrAuto::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
&LengthOrPercentageOrAuto::Auto => write!(f, "auto"),
&LengthOrPercentageOrAuto::Length(length) => length.to_css(dest),
&LengthOrPercentageOrAuto::Percentage(percentage)
=> write!(dest, "{}%", percentage * 100.),
&LengthOrPercentageOrAuto::Auto => dest.write_str("auto"),
}
}
}
@@ -235,12 +267,18 @@ pub mod specified {
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
None,
}

impl fmt::Show for LengthOrPercentageOrNone {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for LengthOrPercentageOrNone {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&LengthOrPercentageOrNone::Length(length) => write!(f, "{}", length),
&LengthOrPercentageOrNone::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
&LengthOrPercentageOrNone::None => write!(f, "none"),
&LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
&LengthOrPercentageOrNone::Percentage(percentage)
=> write!(dest, "{}%", percentage * 100.),
&LengthOrPercentageOrNone::None => dest.write_str("none"),
}
}
}
@@ -312,10 +350,14 @@ pub mod specified {
#[deriving(Clone, PartialEq, PartialOrd)]
pub struct Angle(pub CSSFloat);

impl Show for Angle {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
impl fmt::Show for Angle {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for Angle {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
let Angle(value) = *self;
write!(f, "{}", value)
write!(dest, "{}rad", value)
}
}

@@ -353,11 +395,20 @@ pub mod specified {
LinearGradient(LinearGradient),
}

impl Show for Image {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
impl fmt::Show for Image {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for Image {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&Image::Url(ref url) => write!(f, "url(\"{}\")", url),
&Image::LinearGradient(ref grad) => write!(f, "linear-gradient({})", grad),
&Image::Url(ref url) => {
try!(dest.write_str("url(\""));
try!(write!(CssStringWriter::new(dest), "{}", url));
try!(dest.write_str("\")"));
Ok(())
}
&Image::LinearGradient(ref gradient) => gradient.to_css(dest)
}
}
}
@@ -405,12 +456,19 @@ pub mod specified {
pub stops: Vec<ColorStop>,
}

impl Show for LinearGradient {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
let _ = write!(f, "{}", self.angle_or_corner);
impl fmt::Show for LinearGradient {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for LinearGradient {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
try!(dest.write_str("linear-gradient("));
try!(self.angle_or_corner.to_css(dest));
for stop in self.stops.iter() {
let _ = write!(f, ", {}", stop);
try!(dest.write_str(", "));
try!(stop.to_css(dest));
}
try!(dest.write_char(')'));
Ok(())
}
}
@@ -422,11 +480,21 @@ pub mod specified {
Corner(HorizontalDirection, VerticalDirection),
}

impl Show for AngleOrCorner {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
impl fmt::Show for AngleOrCorner {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl ToCss for AngleOrCorner {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&AngleOrCorner::Angle(angle) => write!(f, "{}", angle),
&AngleOrCorner::Corner(horiz, vert) => write!(f, "to {} {}", horiz, vert),
&AngleOrCorner::Angle(angle) => angle.to_css(dest),
&AngleOrCorner::Corner(horizontal, vertical) => {
try!(dest.write_str("to "));
try!(horizontal.to_css(dest));
try!(dest.write_char(' '));
try!(vertical.to_css(dest));
Ok(())
}
}
}
}
@@ -442,45 +510,23 @@ pub mod specified {
pub position: Option<LengthOrPercentage>,
}

impl Show for ColorStop {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
let _ = write!(f, "{}", self.color);
self.position.map(|pos| {
let _ = write!(f, " {}", pos);
});
Ok(())
}
}

#[deriving(Clone, PartialEq)]
pub enum HorizontalDirection {
Left,
Right,
impl fmt::Show for ColorStop {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}

impl Show for HorizontalDirection {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
match self {
&HorizontalDirection::Left => write!(f, "left"),
&HorizontalDirection::Right => write!(f, "right"),
impl ToCss for ColorStop {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
try!(self.color.to_css(dest));
if let Some(position) = self.position {
try!(dest.write_char(' '));
try!(position.to_css(dest));
}
Ok(())
}
}

#[deriving(Clone, PartialEq)]
pub enum VerticalDirection {
Top,
Bottom,
}

impl Show for VerticalDirection {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
match self {
&VerticalDirection::Top => write!(f, "top"),
&VerticalDirection::Bottom => write!(f, "bottom"),
}
}
}
define_css_keyword_enum!(HorizontalDirection: "left" => Left, "right" => Right)
define_css_keyword_enum!(VerticalDirection: "top" => Top, "bottom" => Bottom)

fn parse_color_stop(source: ParserIter) -> Result<ColorStop,()> {
let color = match source.next() {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.