mirror of
https://github.com/servo/servo.git
synced 2025-07-16 20:03:39 +01:00
implement valid week string
This commit is contained in:
parent
b93579a8f0
commit
54c6028033
11 changed files with 103 additions and 128 deletions
22
Cargo.lock
generated
22
Cargo.lock
generated
|
@ -358,6 +358,15 @@ dependencies = [
|
|||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "0.21.1"
|
||||
|
@ -2044,6 +2053,16 @@ dependencies = [
|
|||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.34"
|
||||
|
@ -2538,6 +2557,7 @@ dependencies = [
|
|||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"canvas_traits 0.0.1",
|
||||
"caseless 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3776,6 +3796,7 @@ dependencies = [
|
|||
"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86765cb42c2a2c497e142af72517c1b4d7ae5bb2f25dfa77a5c69642f2342d89"
|
||||
"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9"
|
||||
"checksum clang-sys 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00048189ee171715296dfe3b2fcfd439563c7bfec0d98d3976ce3402d62c8f07"
|
||||
"checksum clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc34bf7d5d66268b466b9852bca925ec1d2650654dab4da081e63fd230145c2e"
|
||||
"checksum clipboard 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd3a9a938558f33ec1baaa6ca631a69c104aafaacbc66868d9ad28cf5f30564f"
|
||||
|
@ -3895,6 +3916,7 @@ dependencies = [
|
|||
"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
|
||||
"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40"
|
||||
"checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37"
|
||||
"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
|
||||
"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44"
|
||||
|
|
|
@ -39,6 +39,7 @@ byteorder = "1.0"
|
|||
canvas_traits = {path = "../canvas_traits"}
|
||||
caseless = "0.1.0"
|
||||
cookie = "0.10"
|
||||
chrono = "0.4"
|
||||
cssparser = "0.23.0"
|
||||
deny_public_fields = {path = "../deny_public_fields"}
|
||||
devtools_traits = {path = "../devtools_traits"}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
//! The `ByteString` struct.
|
||||
|
||||
use chrono::{Datelike, TimeZone};
|
||||
use chrono::prelude::{Weekday, Utc};
|
||||
use cssparser::CowRcStr;
|
||||
use html5ever::{LocalName, Namespace};
|
||||
use servo_atoms::Atom;
|
||||
|
@ -293,6 +295,13 @@ impl DOMString {
|
|||
pub fn is_valid_month_string(&self) -> bool {
|
||||
parse_month_string(&*self.0).is_ok()
|
||||
}
|
||||
|
||||
/// A valid week string should be like {YYYY}-W{WW}, such as "2017-W52"
|
||||
/// YYYY must be four or more digits, WW both must be two digits
|
||||
/// https://html.spec.whatwg.org/multipage/#valid-week-string
|
||||
pub fn is_valid_week_string(&self) -> bool {
|
||||
parse_week_string(&*self.0).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for DOMString {
|
||||
|
@ -445,6 +454,48 @@ fn parse_date_string(value: &str) -> Result<(u32, u32, u32), ()> {
|
|||
Ok((year_int, month_int, day_int))
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#parse-a-week-string
|
||||
fn parse_week_string(value: &str) -> Result<(u32, u32), ()> {
|
||||
// Step 1, 2, 3
|
||||
let mut iterator = value.split('-');
|
||||
let year = iterator.next().ok_or(())?;
|
||||
|
||||
// Step 4
|
||||
let year_int = year.parse::<u32>().map_err(|_| ())?;
|
||||
if year.len() < 4 || year_int == 0 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// Step 5, 6
|
||||
let week = iterator.next().ok_or(())?;
|
||||
let (week_first, week_last) = week.split_at(1);
|
||||
if week_first != "W" {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// Step 7
|
||||
let week_int = week_last.parse::<u32>().map_err(|_| ())?;
|
||||
if week_last.len() != 2 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// Step 8
|
||||
let max_week = max_week_in_year(year_int);
|
||||
|
||||
// Step 9
|
||||
if week_int < 1 || week_int > max_week {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// Step 10
|
||||
if iterator.next().is_some() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// Step 11
|
||||
Ok((year_int, week_int))
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#parse-a-month-component
|
||||
fn parse_month_component(value: &str) -> Result<(u32, u32), ()> {
|
||||
// Step 3
|
||||
|
@ -495,7 +546,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
|
|||
1|3|5|7|8|10|12 => Ok(31),
|
||||
4|6|9|11 => Ok(30),
|
||||
2 => {
|
||||
if year_num % 400 == 0 || (year_num % 4 == 0 && year_num % 100 != 0) {
|
||||
if is_leap_year(year_num) {
|
||||
Ok(29)
|
||||
} else {
|
||||
Ok(28)
|
||||
|
@ -504,3 +555,17 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
|
|||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#week-number-of-the-last-day
|
||||
fn max_week_in_year(year: u32) -> u32 {
|
||||
match Utc.ymd(year as i32, 1, 1).weekday() {
|
||||
Weekday::Thu => 53,
|
||||
Weekday::Wed if is_leap_year(year) => 53,
|
||||
_ => 52
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_leap_year(year: u32) -> bool {
|
||||
year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)
|
||||
}
|
||||
|
|
|
@ -1005,6 +1005,12 @@ impl HTMLInputElement {
|
|||
*textinput.single_line_content_mut() = "".into();
|
||||
}
|
||||
}
|
||||
InputType::Week => {
|
||||
let mut textinput = self.textinput.borrow_mut();
|
||||
if !textinput.single_line_content().is_valid_week_string() {
|
||||
*textinput.single_line_content_mut() = "".into();
|
||||
}
|
||||
}
|
||||
InputType::Color => {
|
||||
let mut textinput = self.textinput.borrow_mut();
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ extern crate bluetooth_traits;
|
|||
extern crate byteorder;
|
||||
extern crate canvas_traits;
|
||||
extern crate caseless;
|
||||
extern crate chrono;
|
||||
extern crate cookie as cookie_rs;
|
||||
#[macro_use] extern crate cssparser;
|
||||
#[macro_use] extern crate deny_public_fields;
|
||||
|
|
|
@ -29,7 +29,9 @@ rand = [
|
|||
"uuid",
|
||||
"ws",
|
||||
]
|
||||
num = []
|
||||
num = [
|
||||
"chrono",
|
||||
]
|
||||
|
||||
[ignore]
|
||||
# Ignored packages with duplicated versions
|
||||
|
|
|
@ -543087,7 +543087,7 @@
|
|||
"testharness"
|
||||
],
|
||||
"html/semantics/forms/the-input-element/week.html": [
|
||||
"851b1b794f820b1fb9b7ee57fe39f8f2977b7fe6",
|
||||
"95fa0e8176311adcbb5a8d0d408d3c4c8bea100c",
|
||||
"testharness"
|
||||
],
|
||||
"html/semantics/forms/the-label-element/.gitkeep": [
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
[change state from hidden to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from hidden to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from hidden to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -21,9 +18,6 @@
|
|||
[change state from text to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from text to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from text to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -36,9 +30,6 @@
|
|||
[change state from search to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from search to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from search to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -51,9 +42,6 @@
|
|||
[change state from tel to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from tel to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from tel to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -75,9 +63,6 @@
|
|||
[change state from url to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from url to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from url to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -108,9 +93,6 @@
|
|||
[change state from email to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from email to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from email to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -123,9 +105,6 @@
|
|||
[change state from password to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from password to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from password to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -171,27 +150,9 @@
|
|||
[change state from month to range]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to reset]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to button]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to email]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to number]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to hidden]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to number]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to range]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -228,9 +189,6 @@
|
|||
[change state from number to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from number to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from number to range]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -261,9 +219,6 @@
|
|||
[change state from range to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from range to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from range to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -273,9 +228,6 @@
|
|||
[change state from checkbox to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from checkbox to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from checkbox to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -288,9 +240,6 @@
|
|||
[change state from radio to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from radio to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from radio to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -303,9 +252,6 @@
|
|||
[change state from submit to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from submit to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from submit to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -318,9 +264,6 @@
|
|||
[change state from image to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from image to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from image to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -333,9 +276,6 @@
|
|||
[change state from reset to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from reset to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from reset to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -348,9 +288,6 @@
|
|||
[change state from button to datetime]
|
||||
expected: FAIL
|
||||
|
||||
[change state from button to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from button to number]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -402,18 +339,12 @@
|
|||
[change state from datetime-local to email]
|
||||
expected: FAIL
|
||||
|
||||
[change state from datetime-local to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from datetime-local to number]
|
||||
expected: FAIL
|
||||
|
||||
[change state from datetime-local to range]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to datetime-local]
|
||||
expected: FAIL
|
||||
|
||||
[change state from number to datetime-local]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -453,33 +384,6 @@
|
|||
[change state from datetime-local to password]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to text]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to search]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to tel]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to url]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to password]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to checkbox]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to radio]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to submit]
|
||||
expected: FAIL
|
||||
|
||||
[change state from week to image]
|
||||
expected: FAIL
|
||||
|
||||
[change state from number to text]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -513,9 +417,6 @@
|
|||
[change state from color to datetime-local]
|
||||
expected: FAIL
|
||||
|
||||
[change state from color to week]
|
||||
expected: FAIL
|
||||
|
||||
[change state from color to number]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -6,12 +6,6 @@
|
|||
[value IDL attribute of input type datetime with value attribute]
|
||||
expected: FAIL
|
||||
|
||||
[value IDL attribute of input type week without value attribute]
|
||||
expected: FAIL
|
||||
|
||||
[value IDL attribute of input type week with value attribute]
|
||||
expected: FAIL
|
||||
|
||||
[value IDL attribute of input type number without value attribute]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
[week.html]
|
||||
type: testharness
|
||||
[2014 has 52 weeks: Value should be empty]
|
||||
expected: FAIL
|
||||
|
||||
[Invalid value: year only]
|
||||
expected: FAIL
|
||||
|
||||
[Invalid value: no week number]
|
||||
expected: FAIL
|
||||
|
||||
[Invalid value: no '-' (U+002D)]
|
||||
expected: FAIL
|
||||
|
||||
[Invalid value: yearless week]
|
||||
expected: FAIL
|
||||
|
||||
[Invalid value: yearless week and no '-' (U+002D)]
|
||||
expected: FAIL
|
||||
|
|
@ -17,6 +17,9 @@
|
|||
{value: "2014W", expected: "", testname: "Invalid value: no week number"},
|
||||
{value: "2014W52", expected: "", testname: "Invalid value: no '-' (U+002D)"},
|
||||
{value: "-W52", expected: "", testname: "Invalid value: yearless week"},
|
||||
{value: "2017-w52", expected: "", testname: "Invalid value: should be capital letter 'W'"},
|
||||
{value: "2017-W52-", expected: "", testname: "Invalid value: incorrect with '-' at the end"},
|
||||
{value: "2017-W52-12", expected: "", testname: "Invalid value: value should be two parts"},
|
||||
{value: "W52", expected: "", testname: "Invalid value: yearless week and no '-' (U+002D)"},
|
||||
{value: "2014-W03", attributes: { min: "2014-W02" }, expected: "2014-W03", testname: "Value >= min attribute"},
|
||||
{value: "2014-W01", attributes: { min: "2014-W02" }, expected: "2014-W01", testname: "Value < min attribute"},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue