mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Implement something like CSS value serialization. Fetch actual inline style declarations from owning elements.
This commit is contained in:
parent
2e14b653bf
commit
505e1855a3
8 changed files with 375 additions and 55 deletions
|
@ -10,6 +10,7 @@ use dom::bindings::global;
|
|||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
|
||||
use dom::cssstyledeclaration::CSSStyleDeclaration;
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::window::Window;
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
|
@ -37,15 +38,15 @@ macro_rules! css_setter(
|
|||
)
|
||||
|
||||
impl CSS2Properties {
|
||||
fn new_inherited() -> CSS2Properties {
|
||||
fn new_inherited(owner: JSRef<HTMLElement>) -> CSS2Properties {
|
||||
CSS2Properties {
|
||||
cssstyledeclaration: CSSStyleDeclaration::new_inherited(),
|
||||
cssstyledeclaration: CSSStyleDeclaration::new_inherited(Some(owner)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: &JSRef<Window>) -> Temporary<CSS2Properties> {
|
||||
reflect_dom_object(box CSS2Properties::new_inherited(),
|
||||
global::Window(*global),
|
||||
pub fn new(global: JSRef<Window>, owner: JSRef<HTMLElement>) -> Temporary<CSS2Properties> {
|
||||
reflect_dom_object(box CSS2Properties::new_inherited(owner),
|
||||
global::Window(global),
|
||||
CSS2PropertiesBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,55 +3,67 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
|
||||
use dom::bindings::codegen::InheritTypes::ElementCast;
|
||||
use dom::bindings::error::{ErrorResult, Fallible};
|
||||
use dom::bindings::js::JSRef;
|
||||
use dom::bindings::js::{JS, JSRef, OptionalRootedRootable};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::element::{Element, ElementHelpers};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use servo_util::str::DOMString;
|
||||
use string_cache::atom::Atom;
|
||||
use style::longhands_from_shorthand;
|
||||
use style::PropertyDeclaration;
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct CSSStyleDeclaration {
|
||||
reflector_: Reflector,
|
||||
owner: Option<JS<HTMLElement>>,
|
||||
}
|
||||
|
||||
fn get_longhands_from_shorthand(shorthand: &Atom) -> Vec<Atom> {
|
||||
match shorthand.as_slice() {
|
||||
"background" =>
|
||||
vec!(Atom::from_slice("background-color"), Atom::from_slice("background-position"),
|
||||
Atom::from_slice("background-attachment"), Atom::from_slice("background-image"),
|
||||
Atom::from_slice("background-repeat")),
|
||||
_ => vec!(),
|
||||
}
|
||||
}
|
||||
|
||||
type Declaration = int;
|
||||
|
||||
fn serialize_list(property: String, list: Vec<Declaration>) -> DOMString {
|
||||
let mut result = property;
|
||||
result.push_str(": ");
|
||||
fn serialize_list(list: &Vec<PropertyDeclaration>) -> DOMString {
|
||||
let mut result = String::new();
|
||||
for declaration in list.iter() {
|
||||
result.push_str(serialize_declaration(declaration).as_slice());
|
||||
result.push_str(serialize_value(declaration).as_slice());
|
||||
result.push_str(" ");
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn serialize_declaration(_declaration: &Declaration) -> DOMString {
|
||||
"".to_string()
|
||||
}
|
||||
|
||||
fn get_declaration(_property: &Atom) -> Option<Declaration> {
|
||||
None
|
||||
fn serialize_value(declaration: &PropertyDeclaration) -> DOMString {
|
||||
declaration.value().unwrap()
|
||||
}
|
||||
|
||||
impl CSSStyleDeclaration {
|
||||
pub fn new_inherited() -> CSSStyleDeclaration {
|
||||
pub fn new_inherited(owner: Option<JSRef<HTMLElement>>) -> CSSStyleDeclaration {
|
||||
CSSStyleDeclaration {
|
||||
reflector_: Reflector::new()
|
||||
reflector_: Reflector::new(),
|
||||
owner: owner.map(|owner| JS::from_rooted(owner)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait PrivateCSSStyleDeclarationHelpers {
|
||||
fn get_declaration(self, property: &Atom) -> Option<PropertyDeclaration>;
|
||||
}
|
||||
|
||||
impl<'a> PrivateCSSStyleDeclarationHelpers for JSRef<'a, CSSStyleDeclaration> {
|
||||
fn get_declaration(self, property: &Atom) -> Option<PropertyDeclaration> {
|
||||
self.owner.root().and_then(|owner| {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(*owner);
|
||||
let inline_declarations = element.style_attribute().borrow();
|
||||
inline_declarations.as_ref().and_then(|declarations| {
|
||||
for declaration in declarations.normal.iter().chain(declarations.important.iter()) {
|
||||
if declaration.matches(property.as_slice()) {
|
||||
return Some(declaration.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
|
||||
fn CssText(self) -> DOMString {
|
||||
"".to_string()
|
||||
|
@ -75,39 +87,38 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
|
|||
let property = Atom::from_slice(property.as_slice().to_ascii_lower().as_slice());
|
||||
|
||||
// 2. If property is a shorthand property, then follow these substeps:
|
||||
let longhand_properties = get_longhands_from_shorthand(&property);
|
||||
if !longhand_properties.is_empty() {
|
||||
let longhand_properties = longhands_from_shorthand(property.as_slice());
|
||||
if longhand_properties.is_some() {
|
||||
// 1. Let list be a new empty array.
|
||||
let mut list = vec!();
|
||||
|
||||
// 2. For each longhand property longhand that property maps to, in canonical order,
|
||||
// follow these substeps:
|
||||
for longhand in longhand_properties.iter() {
|
||||
for longhand in longhand_properties.unwrap().iter() {
|
||||
// 1. If longhand is a case-sensitive match for a property name of a
|
||||
// CSS declaration in the declarations, let declaration be that CSS
|
||||
// declaration, or null otherwise.
|
||||
let declaration = get_declaration(longhand);
|
||||
let declaration = self.get_declaration(&Atom::from_slice(longhand.as_slice()));
|
||||
|
||||
// 2. If declaration is null, return the empty string and terminate these
|
||||
// steps.
|
||||
if declaration.is_none() {
|
||||
return "".to_string();
|
||||
}
|
||||
|
||||
//XXXjdm ambiguous? this suggests that if we're missing a longhand we return nothing at all.
|
||||
if declaration.is_some() {
|
||||
// 3. Append the declaration to list.
|
||||
list.push(declaration.unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Return the serialization of list and terminate these steps.
|
||||
return serialize_list(property.as_slice().to_string(), list);
|
||||
return serialize_list(&list);
|
||||
}
|
||||
|
||||
// 3. If property is a case-sensitive match for a property name of a CSS declaration
|
||||
// in the declarations, return the result of invoking serialize a CSS value of that
|
||||
// declaration and terminate these steps.
|
||||
// 4. Return the empty string.
|
||||
let declaration = get_declaration(&property);
|
||||
declaration.as_ref().map(|declaration| serialize_declaration(declaration))
|
||||
let declaration = self.get_declaration(&property);
|
||||
declaration.as_ref().map(|declaration| serialize_value(declaration))
|
||||
.unwrap_or("".to_string())
|
||||
}
|
||||
|
||||
|
|
|
@ -73,8 +73,8 @@ impl<'a> PrivateHTMLElementHelpers for JSRef<'a, HTMLElement> {
|
|||
impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> {
|
||||
fn Style(self) -> Temporary<CSSStyleDeclaration> {
|
||||
if self.style_decl.get().is_none() {
|
||||
let global = window_from_node(self);
|
||||
let style_props = CSS2Properties::new(&*global.root()).root();
|
||||
let global = window_from_node(self).root();
|
||||
let style_props = CSS2Properties::new(*global, self).root();
|
||||
let style_decl: JSRef<CSSStyleDeclaration> = CSSStyleDeclarationCast::from_ref(*style_props);
|
||||
self.style_decl.assign(Some(style_decl));
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ pub struct SharedLayoutData {
|
|||
/// Encapsulates the abstract layout data.
|
||||
pub struct LayoutData {
|
||||
chan: Option<LayoutChan>,
|
||||
_shared_data: SharedLayoutData,
|
||||
pub shared_data: SharedLayoutData,
|
||||
_data: *const (),
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#![comment = "The Servo Parallel Browser Project"]
|
||||
#![license = "MPL"]
|
||||
|
||||
#![feature(globs, macro_rules)]
|
||||
#![feature(globs, macro_rules, if_let)]
|
||||
|
||||
#![deny(unused_imports)]
|
||||
#![deny(unused_variables)]
|
||||
|
@ -42,7 +42,7 @@ pub use selector_matching::{CommonStyleAffectingAttributeInfo, CommonStyleAffect
|
|||
pub use selector_matching::{matches, matches_simple_selector, common_style_affecting_attributes};
|
||||
pub use selector_matching::{rare_style_affecting_attributes};
|
||||
pub use selector_matching::{RECOMMENDED_SELECTOR_BLOOM_FILTER_SIZE, SELECTOR_WHITESPACE};
|
||||
pub use properties::{cascade, cascade_anonymous, computed};
|
||||
pub use properties::{cascade, cascade_anonymous, computed, longhands_from_shorthand};
|
||||
pub use properties::{PropertyDeclaration, ComputedValues, computed_values, style_structs};
|
||||
pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes
|
||||
pub use properties::{CSSFloat, DeclaredValue, PropertyDeclarationParseResult};
|
||||
|
|
|
@ -13,6 +13,7 @@ pub type CSSFloat = f64;
|
|||
pub mod specified {
|
||||
use std::ascii::AsciiExt;
|
||||
use std::f64::consts::PI;
|
||||
use std::fmt::{Formatter, FormatError, Show};
|
||||
use url::Url;
|
||||
use cssparser::ast;
|
||||
use cssparser::ast::*;
|
||||
|
@ -20,7 +21,7 @@ pub mod specified {
|
|||
use super::{Au, CSSFloat};
|
||||
pub use cssparser::Color as CSSColor;
|
||||
|
||||
#[deriving(Clone, Show)]
|
||||
#[deriving(Clone)]
|
||||
pub enum Length {
|
||||
Au(Au), // application units
|
||||
Em(CSSFloat),
|
||||
|
@ -40,6 +41,17 @@ pub mod specified {
|
|||
// Vmin(CSSFloat),
|
||||
// Vmax(CSSFloat),
|
||||
}
|
||||
impl Show for Length {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
@ -83,12 +95,19 @@ pub mod specified {
|
|||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Show)]
|
||||
#[deriving(Clone)]
|
||||
pub enum LengthOrPercentage {
|
||||
Length(Length),
|
||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
}
|
||||
|
||||
impl Show for LengthOrPercentage {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
match self {
|
||||
&LengthOrPercentage::Length(length) => write!(f, "{}", length),
|
||||
&LengthOrPercentage::Percentage(percentage) => write!(f, "{}%", percentage),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl LengthOrPercentage {
|
||||
fn parse_internal(input: &ComponentValue, negative_ok: bool)
|
||||
-> Result<LengthOrPercentage, ()> {
|
||||
|
@ -120,6 +139,15 @@ pub mod specified {
|
|||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
Auto,
|
||||
}
|
||||
impl Show for LengthOrPercentageOrAuto {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
match self {
|
||||
&LengthOrPercentageOrAuto::Length(length) => write!(f, "{}", length),
|
||||
&LengthOrPercentageOrAuto::Percentage(percentage) => write!(f, "{}%", percentage),
|
||||
&LengthOrPercentageOrAuto::Auto => write!(f, "auto"),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl LengthOrPercentageOrAuto {
|
||||
fn parse_internal(input: &ComponentValue, negative_ok: bool)
|
||||
-> Result<LengthOrPercentageOrAuto, ()> {
|
||||
|
@ -151,6 +179,15 @@ pub mod specified {
|
|||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
None,
|
||||
}
|
||||
impl Show for LengthOrPercentageOrNone {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
match self {
|
||||
&LengthOrPercentageOrNone::Length(length) => write!(f, "{}", length),
|
||||
&LengthOrPercentageOrNone::Percentage(percentage) => write!(f, "{}%", percentage),
|
||||
&LengthOrPercentageOrNone::None => write!(f, "none"),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl LengthOrPercentageOrNone {
|
||||
fn parse_internal(input: &ComponentValue, negative_ok: bool)
|
||||
-> Result<LengthOrPercentageOrNone, ()> {
|
||||
|
@ -219,6 +256,13 @@ pub mod specified {
|
|||
#[deriving(Clone, PartialEq, PartialOrd)]
|
||||
pub struct Angle(pub CSSFloat);
|
||||
|
||||
impl Show for Angle {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
let Angle(value) = *self;
|
||||
write!(f, "{}", value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Angle {
|
||||
pub fn radians(self) -> f64 {
|
||||
let Angle(radians) = self;
|
||||
|
@ -253,6 +297,15 @@ pub mod specified {
|
|||
LinearGradient(LinearGradient),
|
||||
}
|
||||
|
||||
impl Show for Image {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
match self {
|
||||
&Image::Url(ref url) => write!(f, "url({})", url),
|
||||
&Image::LinearGradient(ref grad) => write!(f, "linear-gradient({})", grad),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Image {
|
||||
pub fn from_component_value(component_value: &ComponentValue, base_url: &Url)
|
||||
-> Result<Image,()> {
|
||||
|
@ -296,6 +349,16 @@ 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);
|
||||
for stop in self.stops.iter() {
|
||||
let _ = write!(f, ", {}", stop);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Specified values for an angle or a corner in a linear gradient.
|
||||
#[deriving(Clone, PartialEq)]
|
||||
pub enum AngleOrCorner {
|
||||
|
@ -303,6 +366,15 @@ pub mod specified {
|
|||
Corner(HorizontalDirection, VerticalDirection),
|
||||
}
|
||||
|
||||
impl Show for AngleOrCorner {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
match self {
|
||||
&AngleOrCorner::Angle(angle) => write!(f, "{}", angle),
|
||||
&AngleOrCorner::Corner(horiz, vert) => write!(f, "to {} {}", horiz, vert),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Specified values for one color stop in a linear gradient.
|
||||
#[deriving(Clone)]
|
||||
pub struct ColorStop {
|
||||
|
@ -314,18 +386,46 @@ 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 Show for HorizontalDirection {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
match self {
|
||||
&HorizontalDirection::Left => write!(f, "left"),
|
||||
&HorizontalDirection::Right => write!(f, "right"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_color_stop(source: ParserIter) -> Result<ColorStop,()> {
|
||||
let color = match source.next() {
|
||||
Some(color) => try!(CSSColor::parse(color)),
|
||||
|
@ -466,6 +566,7 @@ pub mod computed {
|
|||
pub use super::super::longhands::computed_as_specified as compute_CSSColor;
|
||||
use super::*;
|
||||
use super::super::longhands;
|
||||
use std::fmt;
|
||||
use url::Url;
|
||||
|
||||
pub struct Context {
|
||||
|
@ -518,11 +619,19 @@ pub mod computed {
|
|||
}
|
||||
}
|
||||
|
||||
#[deriving(PartialEq, Clone, Show)]
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub enum LengthOrPercentage {
|
||||
Length(Au),
|
||||
Percentage(CSSFloat),
|
||||
}
|
||||
impl fmt::Show for LengthOrPercentage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&LengthOrPercentage::Length(length) => write!(f, "{}", length),
|
||||
&LengthOrPercentage::Percentage(percentage) => write!(f, "{}%", percentage),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn compute_LengthOrPercentage(value: specified::LengthOrPercentage, context: &Context)
|
||||
|
@ -535,7 +644,7 @@ pub mod computed {
|
|||
}
|
||||
}
|
||||
|
||||
#[deriving(PartialEq, Clone, Show)]
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub enum LengthOrPercentageOrAuto {
|
||||
Length(Au),
|
||||
Percentage(CSSFloat),
|
||||
|
@ -554,7 +663,7 @@ pub mod computed {
|
|||
}
|
||||
}
|
||||
|
||||
#[deriving(PartialEq, Clone, Show)]
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub enum LengthOrPercentageOrNone {
|
||||
Length(Au),
|
||||
Percentage(CSSFloat),
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
// This file is a Mako template: http://www.makotemplates.org/
|
||||
|
||||
pub use std::ascii::AsciiExt;
|
||||
use std::fmt::Show;
|
||||
|
||||
use servo_util::logical_geometry::{WritingMode, LogicalMargin};
|
||||
use sync::Arc;
|
||||
|
@ -159,13 +160,23 @@ pub mod longhands {
|
|||
<%self:single_component_value name="${name}" experimental="${experimental}">
|
||||
${caller.body()}
|
||||
pub mod computed_value {
|
||||
use std::fmt;
|
||||
#[allow(non_camel_case_types)]
|
||||
#[deriving(PartialEq, Clone, FromPrimitive, Show)]
|
||||
#[deriving(PartialEq, Clone, FromPrimitive)]
|
||||
pub enum T {
|
||||
% for value in values.split():
|
||||
${to_rust_ident(value)},
|
||||
% endfor
|
||||
}
|
||||
impl fmt::Show for T {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
% for value in values.split():
|
||||
&T::${to_rust_ident(value)} => write!(f, "${value}"),
|
||||
% endfor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub type SpecifiedValue = computed_value::T;
|
||||
#[inline] pub fn get_initial_value() -> computed_value::T {
|
||||
|
@ -455,11 +466,20 @@ pub mod longhands {
|
|||
pub use super::computed_as_specified as to_computed_value;
|
||||
pub type SpecifiedValue = computed_value::T;
|
||||
pub mod computed_value {
|
||||
use std::fmt;
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub enum T {
|
||||
Auto,
|
||||
Number(i32),
|
||||
}
|
||||
impl fmt::Show for T {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&T::Auto => write!(f, "auto"),
|
||||
&T::Number(number) => write!(f, "{}", number),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl T {
|
||||
pub fn number_or_zero(self) -> i32 {
|
||||
|
@ -538,6 +558,7 @@ pub mod longhands {
|
|||
${switch_to_style_struct("InheritedBox")}
|
||||
|
||||
<%self:single_component_value name="line-height">
|
||||
use std::fmt;
|
||||
#[deriving(Clone)]
|
||||
pub enum SpecifiedValue {
|
||||
Normal,
|
||||
|
@ -545,6 +566,15 @@ pub mod longhands {
|
|||
Number(CSSFloat),
|
||||
// percentage are the same as em.
|
||||
}
|
||||
impl fmt::Show for SpecifiedValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&SpecifiedValue::Normal => write!(f, "normal"),
|
||||
&SpecifiedValue::Length(length) => write!(f, "{}%", length),
|
||||
&SpecifiedValue::Number(number) => write!(f, "{}", number),
|
||||
}
|
||||
}
|
||||
}
|
||||
/// normal | <number> | <length> | <percentage>
|
||||
pub fn from_component_value(input: &ComponentValue, _base_url: &Url)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
|
@ -586,6 +616,7 @@ pub mod longhands {
|
|||
${switch_to_style_struct("Box")}
|
||||
|
||||
<%self:single_component_value name="vertical-align">
|
||||
use std::fmt;
|
||||
<% vertical_align_keywords = (
|
||||
"baseline sub super top text-top middle bottom text-bottom".split()) %>
|
||||
#[allow(non_camel_case_types)]
|
||||
|
@ -596,6 +627,16 @@ pub mod longhands {
|
|||
% endfor
|
||||
LengthOrPercentage(specified::LengthOrPercentage),
|
||||
}
|
||||
impl fmt::Show for SpecifiedValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
% for keyword in vertical_align_keywords:
|
||||
&SpecifiedValue::${to_rust_ident(keyword)} => write!(f, "${keyword}"),
|
||||
% endfor
|
||||
&SpecifiedValue::LengthOrPercentage(lop) => write!(f, "{}", lop),
|
||||
}
|
||||
}
|
||||
}
|
||||
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
|
||||
/// | <percentage> | <length>
|
||||
pub fn from_component_value(input: &ComponentValue, _base_url: &Url)
|
||||
|
@ -660,10 +701,18 @@ pub mod longhands {
|
|||
<%self:longhand name="content">
|
||||
pub use super::computed_as_specified as to_computed_value;
|
||||
pub mod computed_value {
|
||||
use std::fmt;
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub enum ContentItem {
|
||||
StringContent(String),
|
||||
}
|
||||
impl fmt::Show for ContentItem {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&ContentItem::StringContent(ref s) => write!(f, "{}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[allow(non_camel_case_types)]
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub enum T {
|
||||
|
@ -671,6 +720,20 @@ pub mod longhands {
|
|||
none,
|
||||
Content(Vec<ContentItem>),
|
||||
}
|
||||
impl fmt::Show for T {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&T::normal => write!(f, "normal"),
|
||||
&T::none => write!(f, "none"),
|
||||
&T::Content(ref content) => {
|
||||
for c in content.iter() {
|
||||
let _ = write!(f, "{} ", c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub type SpecifiedValue = computed_value::T;
|
||||
#[inline] pub fn get_initial_value() -> computed_value::T { T::normal }
|
||||
|
@ -784,14 +847,24 @@ pub mod longhands {
|
|||
</%self:single_component_value>
|
||||
|
||||
<%self:longhand name="background-position">
|
||||
use std::fmt;
|
||||
|
||||
pub mod computed_value {
|
||||
use super::super::super::common_types::computed::LengthOrPercentage;
|
||||
use std::fmt;
|
||||
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub struct T {
|
||||
pub horizontal: LengthOrPercentage,
|
||||
pub vertical: LengthOrPercentage,
|
||||
}
|
||||
impl fmt::Show for T {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let _ = write!(f, "{}", self.horizontal);
|
||||
let _ = write!(f, "{}", self.vertical);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
|
@ -799,6 +872,13 @@ pub mod longhands {
|
|||
pub horizontal: specified::LengthOrPercentage,
|
||||
pub vertical: specified::LengthOrPercentage,
|
||||
}
|
||||
impl fmt::Show for SpecifiedValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let _ = write!(f, "{}", self.horizontal);
|
||||
let _ = write!(f, "{}", self.vertical);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecifiedValue {
|
||||
fn new(first: specified::PositionComponent, second: specified::PositionComponent)
|
||||
|
@ -927,6 +1007,7 @@ pub mod longhands {
|
|||
<%self:longhand name="font-family">
|
||||
pub use super::computed_as_specified as to_computed_value;
|
||||
pub mod computed_value {
|
||||
use std::fmt;
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub enum FontFamily {
|
||||
FamilyName(String),
|
||||
|
@ -944,7 +1025,22 @@ pub mod longhands {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Show for FontFamily {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&FontFamily::FamilyName(ref name) => write!(f, "{}", name),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub type T = Vec<FontFamily>;
|
||||
/*impl fmt::Show for T {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for font in self.iter() {
|
||||
write!(f, "{} ", font);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}*/
|
||||
}
|
||||
pub type SpecifiedValue = computed_value::T;
|
||||
|
||||
|
@ -998,6 +1094,7 @@ pub mod longhands {
|
|||
${single_keyword("font-variant", "normal small-caps")}
|
||||
|
||||
<%self:single_component_value name="font-weight">
|
||||
use std::fmt;
|
||||
#[deriving(Clone)]
|
||||
pub enum SpecifiedValue {
|
||||
Bolder,
|
||||
|
@ -1006,6 +1103,17 @@ pub mod longhands {
|
|||
SpecifiedWeight${weight},
|
||||
% endfor
|
||||
}
|
||||
impl fmt::Show for SpecifiedValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&SpecifiedValue::Bolder => write!(f, "bolder"),
|
||||
&SpecifiedValue::Lighter => write!(f, "lighter"),
|
||||
% for weight in range(100, 901, 100):
|
||||
&SpecifiedValue::SpecifiedWeight${weight} => write!(f, "{}", ${weight}i),
|
||||
% endfor
|
||||
}
|
||||
}
|
||||
}
|
||||
/// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
||||
pub fn from_component_value(input: &ComponentValue, _base_url: &Url)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
|
@ -1193,6 +1301,7 @@ pub mod longhands {
|
|||
|
||||
<%self:longhand name="text-decoration">
|
||||
pub use super::computed_as_specified as to_computed_value;
|
||||
use std::fmt;
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub struct SpecifiedValue {
|
||||
pub underline: bool,
|
||||
|
@ -1201,6 +1310,20 @@ pub mod longhands {
|
|||
// 'blink' is accepted in the parser but ignored.
|
||||
// Just not blinking the text is a conforming implementation per CSS 2.1.
|
||||
}
|
||||
impl fmt::Show for SpecifiedValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.underline {
|
||||
let _ = write!(f, "underline ");
|
||||
}
|
||||
if self.overline {
|
||||
let _ = write!(f, "overline ");
|
||||
}
|
||||
if self.line_through {
|
||||
let _ = write!(f, "line-through ");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub mod computed_value {
|
||||
pub type T = super::SpecifiedValue;
|
||||
#[allow(non_upper_case_globals)]
|
||||
|
@ -1518,6 +1641,7 @@ pub mod longhands {
|
|||
|
||||
<%self:longhand name="box-shadow">
|
||||
use cssparser;
|
||||
use std::fmt;
|
||||
|
||||
pub type SpecifiedValue = Vec<SpecifiedBoxShadow>;
|
||||
|
||||
|
@ -1531,6 +1655,20 @@ pub mod longhands {
|
|||
pub inset: bool,
|
||||
}
|
||||
|
||||
impl fmt::Show for SpecifiedBoxShadow {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.inset {
|
||||
let _ = write!(f, "inset ");
|
||||
}
|
||||
let _ = write!(f, "{} {} {} {}", self.offset_x, self.offset_y,
|
||||
self.blur_radius, self.spread_radius);
|
||||
if let Some(ref color) = self.color {
|
||||
let _ = write!(f, "{}", color);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub mod computed_value {
|
||||
use super::super::Au;
|
||||
use super::super::super::computed;
|
||||
|
@ -2314,6 +2452,15 @@ pub enum DeclaredValue<T> {
|
|||
// depending on whether the property is inherited.
|
||||
}
|
||||
|
||||
impl<T: Show> DeclaredValue<T> {
|
||||
pub fn specified_value(&self) -> Option<String> {
|
||||
match self {
|
||||
&DeclaredValue::SpecifiedValue(ref inner) => Some(format!("{}", inner)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub enum PropertyDeclaration {
|
||||
% for property in LONGHANDS:
|
||||
|
@ -2329,8 +2476,41 @@ pub enum PropertyDeclarationParseResult {
|
|||
ValidOrIgnoredDeclaration,
|
||||
}
|
||||
|
||||
|
||||
impl PropertyDeclaration {
|
||||
pub fn name(&self) -> String {
|
||||
match self {
|
||||
% for property in LONGHANDS:
|
||||
% if property.derived_from is None:
|
||||
&PropertyDeclaration::${property.camel_case}Declaration(..) => "${property.name}".to_string(),
|
||||
% endif
|
||||
% endfor
|
||||
_ => "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn value(&self) -> Option<String> {
|
||||
match self {
|
||||
% for property in LONGHANDS:
|
||||
% if property.derived_from is None:
|
||||
&PropertyDeclaration::${property.camel_case}Declaration(ref value) => value.specified_value(),
|
||||
% endif
|
||||
% endfor
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn matches(&self, name: &str) -> bool {
|
||||
let name_lower = name.as_slice().to_ascii_lower();
|
||||
match (self, name_lower.as_slice()) {
|
||||
% for property in LONGHANDS:
|
||||
% if property.derived_from is None:
|
||||
(&PropertyDeclaration::${property.camel_case}Declaration(..), "${property.name}") => true,
|
||||
% endif
|
||||
% endfor
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(name: &str, value: &[ComponentValue],
|
||||
result_list: &mut Vec<PropertyDeclaration>,
|
||||
base_url: &Url,
|
||||
|
@ -2964,6 +3144,18 @@ pub fn cascade_anonymous(parent_style: &ComputedValues) -> ComputedValues {
|
|||
result
|
||||
}
|
||||
|
||||
pub fn longhands_from_shorthand(shorthand: &str) -> Option<Vec<String>> {
|
||||
match shorthand {
|
||||
% for property in SHORTHANDS:
|
||||
"${property.name}" => Some(vec!(
|
||||
% for sub in property.sub_properties:
|
||||
"${sub.name}".to_string(),
|
||||
% endfor
|
||||
)),
|
||||
% endfor
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Only re-export the types for computed values.
|
||||
pub mod computed_values {
|
||||
|
|
7
tests/html/test_style.html
Normal file
7
tests/html/test_style.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<div id="test" style="display: block; background-color: black; background-position: top left;"></div>
|
||||
<script>
|
||||
alert(document.getElementById('test').style.display);
|
||||
alert(document.getElementById('test').style.background);
|
||||
alert(document.getElementById('test').style.backgroundColor);
|
||||
alert(document.getElementById('test').style.backgroundPosition);
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue