mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Parse sizes attribute values.
This commit is contained in:
parent
8397c5b0a2
commit
c31b0e4bd2
7 changed files with 179 additions and 1 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2676,6 +2676,7 @@ dependencies = [
|
||||||
"msg 0.0.1",
|
"msg 0.0.1",
|
||||||
"script 0.0.1",
|
"script 0.0.1",
|
||||||
"servo_url 0.0.1",
|
"servo_url 0.0.1",
|
||||||
|
"style 0.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use app_units::{Au, AU_PER_PX};
|
use app_units::{Au, AU_PER_PX};
|
||||||
|
use cssparser::{Parser, ParserInput};
|
||||||
use document_loader::{LoadType, LoadBlocker};
|
use document_loader::{LoadType, LoadBlocker};
|
||||||
use dom::activation::Activatable;
|
use dom::activation::Activatable;
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
|
@ -52,10 +53,17 @@ use script_thread::{Runnable, ScriptThread};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use servo_url::origin::ImmutableOrigin;
|
use servo_url::origin::ImmutableOrigin;
|
||||||
use std::cell::{Cell, RefMut};
|
use std::cell::{Cell, RefMut};
|
||||||
|
use std::char;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::i32;
|
use std::i32;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
|
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
|
||||||
|
use style::context::QuirksMode;
|
||||||
|
use style::media_queries::MediaQuery;
|
||||||
|
use style::parser::ParserContext;
|
||||||
|
use style::values::specified::{Length, ViewportPercentageLength};
|
||||||
|
use style::values::specified::length::NoCalcLength;
|
||||||
|
use style_traits::ParsingMode;
|
||||||
use task_source::TaskSource;
|
use task_source::TaskSource;
|
||||||
|
|
||||||
#[derive(Clone, Copy, HeapSizeOf, JSTraceable)]
|
#[derive(Clone, Copy, HeapSizeOf, JSTraceable)]
|
||||||
|
@ -66,6 +74,13 @@ enum State {
|
||||||
CompletelyAvailable,
|
CompletelyAvailable,
|
||||||
Broken,
|
Broken,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Size {
|
||||||
|
pub query: Option<MediaQuery>,
|
||||||
|
pub length: Length,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, HeapSizeOf, JSTraceable)]
|
#[derive(Clone, Copy, HeapSizeOf, JSTraceable)]
|
||||||
enum ImageRequestPhase {
|
enum ImageRequestPhase {
|
||||||
Pending,
|
Pending,
|
||||||
|
@ -780,6 +795,60 @@ impl LayoutHTMLImageElementHelpers for LayoutJS<HTMLImageElement> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//https://html.spec.whatwg.org/multipage/#parse-a-sizes-attribute
|
||||||
|
pub fn parse_a_sizes_attribute(input: DOMString, width: Option<u32>) -> Vec<Size> {
|
||||||
|
let mut sizes = Vec::<Size>::new();
|
||||||
|
for unparsed_size in input.split(',') {
|
||||||
|
let whitespace = unparsed_size.chars().rev().take_while(|c| char::is_whitespace(*c)).count();
|
||||||
|
let trimmed: String = unparsed_size.chars().take(unparsed_size.chars().count() - whitespace).collect();
|
||||||
|
|
||||||
|
if trimmed.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut input = ParserInput::new(&trimmed);
|
||||||
|
let url = ServoUrl::parse("about:blank").unwrap();
|
||||||
|
let context = ParserContext::new_for_cssom(&url,
|
||||||
|
None,
|
||||||
|
ParsingMode::empty(),
|
||||||
|
QuirksMode::NoQuirks);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
|
let length = parser.try(|i| Length::parse_non_negative(&context, i));
|
||||||
|
match length {
|
||||||
|
Ok(len) => sizes.push(Size {
|
||||||
|
length: len,
|
||||||
|
query: None
|
||||||
|
}),
|
||||||
|
Err(_) => {
|
||||||
|
let mut media_query_parser = parser;
|
||||||
|
let media_query = media_query_parser.try(|i| MediaQuery::parse(&context, i));
|
||||||
|
if let Ok(query) = media_query {
|
||||||
|
let length = Length::parse_non_negative(&context, &mut media_query_parser);
|
||||||
|
if let Ok(length) = length {
|
||||||
|
sizes.push(Size {
|
||||||
|
length: length,
|
||||||
|
query: Some(query)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sizes.is_empty() {
|
||||||
|
let size = match width {
|
||||||
|
Some(w) => Size {
|
||||||
|
length: Length::from_px(w as f32),
|
||||||
|
query: None
|
||||||
|
},
|
||||||
|
None => Size {
|
||||||
|
length: Length::NoCalc(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(100.))),
|
||||||
|
query: None
|
||||||
|
},
|
||||||
|
};
|
||||||
|
sizes.push(size);
|
||||||
|
}
|
||||||
|
sizes
|
||||||
|
}
|
||||||
|
|
||||||
impl HTMLImageElementMethods for HTMLImageElement {
|
impl HTMLImageElementMethods for HTMLImageElement {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-img-alt
|
// https://html.spec.whatwg.org/multipage/#dom-img-alt
|
||||||
make_getter!(Alt, "alt");
|
make_getter!(Alt, "alt");
|
||||||
|
|
|
@ -15,6 +15,10 @@ pub mod area {
|
||||||
pub use dom::htmlareaelement::{Area, Shape};
|
pub use dom::htmlareaelement::{Area, Shape};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod sizes {
|
||||||
|
pub use dom::htmlimageelement::{parse_a_sizes_attribute, Size};
|
||||||
|
}
|
||||||
|
|
||||||
pub mod size_of {
|
pub mod size_of {
|
||||||
use dom::characterdata::CharacterData;
|
use dom::characterdata::CharacterData;
|
||||||
use dom::element::Element;
|
use dom::element::Element;
|
||||||
|
|
|
@ -164,7 +164,7 @@ pub enum ExpressionKind {
|
||||||
/// http://dev.w3.org/csswg/mediaqueries-3/#media1
|
/// http://dev.w3.org/csswg/mediaqueries-3/#media1
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Expression(ExpressionKind);
|
pub struct Expression(pub ExpressionKind);
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
/// The kind of expression we're, just for unit testing.
|
/// The kind of expression we're, just for unit testing.
|
||||||
|
|
|
@ -14,3 +14,4 @@ euclid = "0.15"
|
||||||
msg = {path = "../../../components/msg"}
|
msg = {path = "../../../components/msg"}
|
||||||
script = {path = "../../../components/script"}
|
script = {path = "../../../components/script"}
|
||||||
servo_url = {path = "../../../components/url"}
|
servo_url = {path = "../../../components/url"}
|
||||||
|
style = {path = "../../../components/style"}
|
||||||
|
|
101
tests/unit/script/htmlimageelement.rs
Normal file
101
tests/unit/script/htmlimageelement.rs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use script::test::DOMString;
|
||||||
|
use script::test::sizes::{parse_a_sizes_attribute, Size};
|
||||||
|
use style::media_queries::{MediaQuery, MediaQueryType};
|
||||||
|
use style::media_queries::Expression;
|
||||||
|
use style::servo::media_queries::{ExpressionKind, Range};
|
||||||
|
use style::values::specified::{Length, NoCalcLength, AbsoluteLength, ViewportPercentageLength};
|
||||||
|
|
||||||
|
pub fn test_length_for_no_default_provided(len: f32) -> Length {
|
||||||
|
let length = Length::NoCalc(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(len)));
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_default_provided() {
|
||||||
|
let mut a = vec![];
|
||||||
|
let length = test_length_for_no_default_provided(100f32);
|
||||||
|
let size = Size { query: None, length: length };
|
||||||
|
a.push(size);
|
||||||
|
assert_eq!(parse_a_sizes_attribute(DOMString::new(), None), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test_length_for_default_provided(len: f32) -> Length {
|
||||||
|
let length = Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(len)));
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_provided() {
|
||||||
|
let mut a = vec![];
|
||||||
|
let length = test_length_for_default_provided(2f32);
|
||||||
|
let size = Size { query: None, length: length };
|
||||||
|
a.push(size);
|
||||||
|
assert_eq!(parse_a_sizes_attribute(DOMString::new(), Some(2)), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test_media_query(len: f32) -> MediaQuery {
|
||||||
|
let length = Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(len)));
|
||||||
|
let expr = Expression(ExpressionKind::Width(Range::Max(length)));
|
||||||
|
let media_query = MediaQuery {
|
||||||
|
qualifier: None,
|
||||||
|
media_type: MediaQueryType::All,
|
||||||
|
expressions: vec![expr]
|
||||||
|
};
|
||||||
|
media_query
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test_length(len: f32) -> Length {
|
||||||
|
let length = Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(len)));
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn one_value() {
|
||||||
|
let mut a = vec![];
|
||||||
|
let media_query = test_media_query(200f32);
|
||||||
|
let length = test_length(545f32);
|
||||||
|
let size = Size { query: Some(media_query), length: length };
|
||||||
|
a.push(size);
|
||||||
|
assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 200px) 545px"), None), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn more_then_one_value() {
|
||||||
|
let media_query = test_media_query(900f32);
|
||||||
|
let length = test_length(1000f32);
|
||||||
|
let size = Size { query: Some(media_query), length: length };
|
||||||
|
let media_query1 = test_media_query(900f32);
|
||||||
|
let length1 = test_length(50f32);
|
||||||
|
let size1 = Size { query: Some(media_query1), length: length1 };
|
||||||
|
let a = &[size, size1];
|
||||||
|
assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 900px) 1000px, (max-width: 900px) 50px"),
|
||||||
|
None), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_extra_whitespace() {
|
||||||
|
let mut a = vec![];
|
||||||
|
let media_query = test_media_query(200f32);
|
||||||
|
let length = test_length(545f32);
|
||||||
|
let size = Size { query: Some(media_query), length: length };
|
||||||
|
a.push(size);
|
||||||
|
assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 200px) 545px"), None), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extra_whitespace() {
|
||||||
|
let media_query = test_media_query(900f32);
|
||||||
|
let length = test_length(1000f32);
|
||||||
|
let size = Size { query: Some(media_query), length: length };
|
||||||
|
let media_query1 = test_media_query(900f32);
|
||||||
|
let length1 = test_length(50f32);
|
||||||
|
let size1 = Size { query: Some(media_query1), length: length1 };
|
||||||
|
let a = &[size, size1];
|
||||||
|
assert_eq!(parse_a_sizes_attribute(
|
||||||
|
DOMString::from("(max-width: 900px) 1000px, (max-width: 900px) 50px"),
|
||||||
|
None), a);
|
||||||
|
}
|
|
@ -6,10 +6,12 @@ extern crate euclid;
|
||||||
extern crate msg;
|
extern crate msg;
|
||||||
extern crate script;
|
extern crate script;
|
||||||
extern crate servo_url;
|
extern crate servo_url;
|
||||||
|
extern crate style;
|
||||||
|
|
||||||
#[cfg(test)] mod origin;
|
#[cfg(test)] mod origin;
|
||||||
#[cfg(all(test, target_pointer_width = "64"))] mod size_of;
|
#[cfg(all(test, target_pointer_width = "64"))] mod size_of;
|
||||||
#[cfg(test)] mod textinput;
|
#[cfg(test)] mod textinput;
|
||||||
#[cfg(test)] mod headers;
|
#[cfg(test)] mod headers;
|
||||||
#[cfg(test)] mod htmlareaelement;
|
#[cfg(test)] mod htmlareaelement;
|
||||||
|
#[cfg(test)] mod htmlimageelement;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue