Implement ToCss serialization for CSSRules

This commit is contained in:
Nazım Can Altınova 2016-11-15 23:25:03 +03:00
parent 22aebdf5d4
commit fdbadcdce2
10 changed files with 198 additions and 28 deletions

View file

@ -12,6 +12,7 @@ use dom::window::Window;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::sync::Arc; use std::sync::Arc;
use style::font_face::FontFaceRule; use style::font_face::FontFaceRule;
use style_traits::ToCss;
#[dom_struct] #[dom_struct]
pub struct CSSFontFaceRule { pub struct CSSFontFaceRule {
@ -44,7 +45,6 @@ impl SpecificCSSRule for CSSFontFaceRule {
} }
fn get_css(&self) -> DOMString { fn get_css(&self) -> DOMString {
// self.fontfacerule.read().to_css_string().into() self.fontfacerule.read().to_css_string().into()
"".into()
} }
} }

View file

@ -12,6 +12,7 @@ use dom::window::Window;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::sync::Arc; use std::sync::Arc;
use style::stylesheets::KeyframesRule; use style::stylesheets::KeyframesRule;
use style_traits::ToCss;
#[dom_struct] #[dom_struct]
pub struct CSSKeyframesRule { pub struct CSSKeyframesRule {
@ -44,7 +45,6 @@ impl SpecificCSSRule for CSSKeyframesRule {
} }
fn get_css(&self) -> DOMString { fn get_css(&self) -> DOMString {
// self.keyframesrule.read().to_css_string().into() self.keyframesrule.read().to_css_string().into()
"".into()
} }
} }

View file

@ -13,6 +13,7 @@ use dom::window::Window;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::sync::Arc; use std::sync::Arc;
use style::stylesheets::MediaRule; use style::stylesheets::MediaRule;
use style_traits::ToCss;
#[dom_struct] #[dom_struct]
pub struct CSSMediaRule { pub struct CSSMediaRule {
@ -45,7 +46,6 @@ impl SpecificCSSRule for CSSMediaRule {
} }
fn get_css(&self) -> DOMString { fn get_css(&self) -> DOMString {
// self.mediarule.read().to_css_string().into() self.mediarule.read().to_css_string().into()
"".into()
} }
} }

View file

@ -12,6 +12,7 @@ use dom::window::Window;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::sync::Arc; use std::sync::Arc;
use style::stylesheets::NamespaceRule; use style::stylesheets::NamespaceRule;
use style_traits::ToCss;
#[dom_struct] #[dom_struct]
pub struct CSSNamespaceRule { pub struct CSSNamespaceRule {
@ -44,7 +45,6 @@ impl SpecificCSSRule for CSSNamespaceRule {
} }
fn get_css(&self) -> DOMString { fn get_css(&self) -> DOMString {
// self.namespacerule.read().to_css_string().into() self.namespacerule.read().to_css_string().into()
"".into()
} }
} }

View file

@ -12,6 +12,7 @@ use dom::window::Window;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::sync::Arc; use std::sync::Arc;
use style::viewport::ViewportRule; use style::viewport::ViewportRule;
use style_traits::ToCss;
#[dom_struct] #[dom_struct]
pub struct CSSViewportRule { pub struct CSSViewportRule {
@ -44,7 +45,6 @@ impl SpecificCSSRule for CSSViewportRule {
} }
fn get_css(&self) -> DOMString { fn get_css(&self) -> DOMString {
// self.viewportrule.read().to_css_string().into() self.viewportrule.read().to_css_string().into()
"".into()
} }
} }

View file

@ -10,7 +10,9 @@ use computed_values::font_family::FontFamily;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser}; use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
use parser::{ParserContext, log_css_error}; use parser::{ParserContext, log_css_error};
use properties::longhands::font_family::parse_one_family; use properties::longhands::font_family::parse_one_family;
use std::fmt;
use std::iter; use std::iter;
use style_traits::ToCss;
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
@ -20,6 +22,22 @@ pub enum Source {
Local(FontFamily), Local(FontFamily),
} }
impl ToCss for Source {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
Source::Url(ref url) => {
try!(dest.write_str("local(\""));
try!(url.to_css(dest));
},
Source::Local(ref family) => {
try!(dest.write_str("url(\""));
try!(family.to_css(dest));
},
}
dest.write_str("\")")
}
}
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub struct UrlSource { pub struct UrlSource {
@ -27,6 +45,12 @@ pub struct UrlSource {
pub format_hints: Vec<String>, pub format_hints: Vec<String>,
} }
impl ToCss for UrlSource {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
dest.write_str(self.url.as_str())
}
}
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontFaceRule { pub struct FontFaceRule {
@ -34,6 +58,28 @@ pub struct FontFaceRule {
pub sources: Vec<Source>, pub sources: Vec<Source>,
} }
impl ToCss for FontFaceRule {
// Serialization of FontFaceRule is not specced.
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
try!(dest.write_str("@font-face { font-family: "));
try!(self.family.to_css(dest));
try!(dest.write_str(";"));
if self.sources.len() > 0 {
try!(dest.write_str(" src: "));
let mut iter = self.sources.iter();
try!(iter.next().unwrap().to_css(dest));
for source in iter {
try!(dest.write_str(", "));
try!(source.to_css(dest));
}
try!(dest.write_str(";"));
}
dest.write_str(" }")
}
}
pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser) pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
-> Result<FontFaceRule, ()> { -> Result<FontFaceRule, ()> {
let mut family = None; let mut family = None;

View file

@ -9,7 +9,9 @@ use parser::{ParserContext, log_css_error};
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock}; use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
use properties::PropertyDeclarationParseResult; use properties::PropertyDeclarationParseResult;
use properties::animated_properties::TransitionProperty; use properties::animated_properties::TransitionProperty;
use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use style_traits::ToCss;
/// A number from 1 to 100, indicating the percentage of the animation where /// A number from 1 to 100, indicating the percentage of the animation where
/// this keyframe should run. /// this keyframe should run.
@ -82,6 +84,21 @@ pub struct Keyframe {
pub block: Arc<RwLock<PropertyDeclarationBlock>>, pub block: Arc<RwLock<PropertyDeclarationBlock>>,
} }
impl ToCss for Keyframe {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
let mut iter = self.selector.percentages().iter();
try!(write!(dest, "{}%", iter.next().unwrap().0));
for percentage in iter {
try!(write!(dest, ", "));
try!(write!(dest, "{}%", percentage.0));
}
try!(dest.write_str(" { "));
try!(self.block.read().to_css(dest));
try!(dest.write_str(" }"));
Ok(())
}
}
/// A keyframes step value. This can be a synthetised keyframes animation, that /// A keyframes step value. This can be a synthetised keyframes animation, that
/// is, one autogenerated from the current computed values, or a list of /// is, one autogenerated from the current computed values, or a list of
/// declarations to apply. /// declarations to apply.

View file

@ -107,6 +107,20 @@ impl CssRule {
} }
} }
impl ToCss for CssRule {
// https://drafts.csswg.org/cssom/#serialize-a-css-rule
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
CssRule::Namespace(ref lock) => lock.read().to_css(dest),
CssRule::Style(ref lock) => lock.read().to_css(dest),
CssRule::FontFace(ref lock) => lock.read().to_css(dest),
CssRule::Viewport(ref lock) => lock.read().to_css(dest),
CssRule::Keyframes(ref lock) => lock.read().to_css(dest),
CssRule::Media(ref lock) => lock.read().to_css(dest),
}
}
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct NamespaceRule { pub struct NamespaceRule {
@ -115,18 +129,62 @@ pub struct NamespaceRule {
pub url: Namespace, pub url: Namespace,
} }
impl ToCss for NamespaceRule {
// https://drafts.csswg.org/cssom/#serialize-a-css-rule CSSNamespaceRule
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
try!(dest.write_str("@namespace "));
if let Some(ref prefix) = self.prefix {
try!(dest.write_str(&*prefix.to_string()));
try!(dest.write_str(" "));
}
try!(dest.write_str("url(\""));
try!(dest.write_str(&*self.url.to_string()));
dest.write_str("\");")
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct KeyframesRule { pub struct KeyframesRule {
pub name: Atom, pub name: Atom,
pub keyframes: Vec<Arc<RwLock<Keyframe>>>, pub keyframes: Vec<Arc<RwLock<Keyframe>>>,
} }
impl ToCss for KeyframesRule {
// Serialization of KeyframesRule is not specced.
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
try!(dest.write_str("@keyframes "));
try!(dest.write_str(&*self.name.to_string()));
try!(dest.write_str(" { "));
let iter = self.keyframes.iter();
for lock in iter {
let keyframe = lock.read();
try!(keyframe.to_css(dest));
}
dest.write_str(" }")
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct MediaRule { pub struct MediaRule {
pub media_queries: Arc<RwLock<MediaList>>, pub media_queries: Arc<RwLock<MediaList>>,
pub rules: CssRules, pub rules: CssRules,
} }
impl ToCss for MediaRule {
// Serialization of MediaRule is not specced.
// https://drafts.csswg.org/cssom/#serialize-a-css-rule CSSMediaRule
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
try!(dest.write_str("@media ("));
try!(self.media_queries.read().to_css(dest));
try!(dest.write_str(") {"));
for rule in self.rules.0.read().iter() {
try!(dest.write_str(" "));
try!(rule.to_css(dest));
}
dest.write_str(" }")
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct StyleRule { pub struct StyleRule {
pub selectors: Vec<Selector<TheSelectorImpl>>, pub selectors: Vec<Selector<TheSelectorImpl>>,

View file

@ -104,6 +104,13 @@ impl SpecifiedUrl {
self.resolved.as_ref() self.resolved.as_ref()
} }
pub fn as_str(&self) -> &str {
match self.resolved {
Some(ref url) => url.as_str(),
None => "",
}
}
/// Little helper for Gecko's ffi. /// Little helper for Gecko's ffi.
pub fn as_slice_components(&self) -> (*const u8, usize) { pub fn as_slice_components(&self) -> (*const u8, usize) {
match self.resolved { match self.resolved {

View file

@ -9,6 +9,7 @@
use app_units::Au; use app_units::Au;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important}; use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
use cssparser::ToCss as ParserToCss;
use euclid::scale_factor::ScaleFactor; use euclid::scale_factor::ScaleFactor;
use euclid::size::{Size2D, TypedSize2D}; use euclid::size::{Size2D, TypedSize2D};
use media_queries::Device; use media_queries::Device;
@ -26,32 +27,34 @@ use values::computed::{Context, ToComputedValue};
use values::specified::{Length, LengthOrPercentageOrAuto, ViewportPercentageLength}; use values::specified::{Length, LengthOrPercentageOrAuto, ViewportPercentageLength};
macro_rules! declare_viewport_descriptor { macro_rules! declare_viewport_descriptor {
( $( $variant: ident($data: ident), )+ ) => { ( $( $variant_name: expr => $variant: ident($data: ident), )+ ) => {
declare_viewport_descriptor_inner!([] [ $( $variant($data), )+ ] 0); declare_viewport_descriptor_inner!([] [ $( $variant_name => $variant($data), )+ ] 0);
}; };
} }
macro_rules! declare_viewport_descriptor_inner { macro_rules! declare_viewport_descriptor_inner {
( (
[ $( $assigned_variant: ident($assigned_data: ident) = $assigned_discriminant: expr, )* ] [ $( $assigned_variant_name: expr =>
$assigned_variant: ident($assigned_data: ident) = $assigned_discriminant: expr, )* ]
[ [
$next_variant: ident($next_data: ident), $next_variant_name: expr => $next_variant: ident($next_data: ident),
$( $variant: ident($data: ident), )* $( $variant_name: expr => $variant: ident($data: ident), )*
] ]
$next_discriminant: expr $next_discriminant: expr
) => { ) => {
declare_viewport_descriptor_inner! { declare_viewport_descriptor_inner! {
[ [
$( $assigned_variant($assigned_data) = $assigned_discriminant, )* $( $assigned_variant_name => $assigned_variant($assigned_data) = $assigned_discriminant, )*
$next_variant($next_data) = $next_discriminant, $next_variant_name => $next_variant($next_data) = $next_discriminant,
] ]
[ $( $variant($data), )* ] [ $( $variant_name => $variant($data), )* ]
$next_discriminant + 1 $next_discriminant + 1
} }
}; };
( (
[ $( $assigned_variant: ident($assigned_data: ident) = $assigned_discriminant: expr, )* ] [ $( $assigned_variant_name: expr =>
$assigned_variant: ident($assigned_data: ident) = $assigned_discriminant: expr, )* ]
[ ] [ ]
$number_of_variants: expr $number_of_variants: expr
) => { ) => {
@ -74,22 +77,37 @@ macro_rules! declare_viewport_descriptor_inner {
} }
} }
} }
impl ToCss for ViewportDescriptor {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
$(
ViewportDescriptor::$assigned_variant(val) => {
try!(dest.write_str($assigned_variant_name));
try!(dest.write_str(": "));
try!(val.to_css(dest));
},
)*
}
dest.write_str(";")
}
}
}; };
} }
declare_viewport_descriptor! { declare_viewport_descriptor! {
MinWidth(ViewportLength), "min-width" => MinWidth(ViewportLength),
MaxWidth(ViewportLength), "max-width" => MaxWidth(ViewportLength),
MinHeight(ViewportLength), "min-height" => MinHeight(ViewportLength),
MaxHeight(ViewportLength), "max-height" => MaxHeight(ViewportLength),
Zoom(Zoom), "zoom" => Zoom(Zoom),
MinZoom(Zoom), "min-zoom" => MinZoom(Zoom),
MaxZoom(Zoom), "max-zoom" => MaxZoom(Zoom),
UserZoom(UserZoom), "user-zoom" => UserZoom(UserZoom),
Orientation(Orientation), "orientation" => Orientation(Orientation),
} }
trait FromMeta: Sized { trait FromMeta: Sized {
@ -210,6 +228,16 @@ impl ViewportDescriptorDeclaration {
} }
} }
impl ToCss for ViewportDescriptorDeclaration {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
try!(self.descriptor.to_css(dest));
if self.important {
try!(dest.write_str(" !important"));
}
dest.write_str(";")
}
}
fn parse_shorthand(input: &mut Parser) -> Result<[ViewportLength; 2], ()> { fn parse_shorthand(input: &mut Parser) -> Result<[ViewportLength; 2], ()> {
let min = try!(ViewportLength::parse(input)); let min = try!(ViewportLength::parse(input));
match input.try(|input| ViewportLength::parse(input)) { match input.try(|input| ViewportLength::parse(input)) {
@ -467,6 +495,20 @@ impl ViewportRule {
} }
} }
impl ToCss for ViewportRule {
// Serialization of ViewportRule is not specced.
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
try!(dest.write_str("@viewport { "));
let mut iter = self.declarations.iter();
try!(iter.next().unwrap().to_css(dest));
for declaration in iter {
try!(dest.write_str(" "));
try!(declaration.to_css(dest));
}
dest.write_str(" }")
}
}
/// Computes the cascade precedence as according to /// Computes the cascade precedence as according to
/// http://dev.w3.org/csswg/css-cascade/#cascade-origin /// http://dev.w3.org/csswg/css-cascade/#cascade-origin
fn cascade_precendence(origin: Origin, important: bool) -> u8 { fn cascade_precendence(origin: Origin, important: bool) -> u8 {