servo: Merge #19385 - implement "Date type inputs", "Month type inputs" (from tigercosmos:b1); r=KiChjang

<!-- Please describe your changes on the following line: -->
implement "Date type inputs", "Month type inputs"

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] `./mach test-unit` does not report any errors

Source-Repo: https://github.com/servo/servo
Source-Revision: 68cefb1b0031c05c7f2f4aa433eb1a21e7863f8f

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 1cadc19ec7e70ded4bb31329408a5d89311d9919
This commit is contained in:
tigercosmos 2017-12-04 19:58:08 -06:00
Родитель bdd3f2c5da
Коммит b73dbbfaea
2 изменённых файлов: 114 добавлений и 1 удалений

Просмотреть файл

@ -279,6 +279,20 @@ impl DOMString {
_ => false
}
}
/// A valid date string should be "YYYY-MM-DD"
/// YYYY must be four or more digits, MM and DD both must be two digits
/// https://html.spec.whatwg.org/multipage/#valid-date-string
pub fn is_valid_date_string(&self) -> bool {
parse_date_string(&*self.0).is_ok()
}
/// A valid month string should be "YYYY-MM"
/// YYYY must be four or more digits, MM both must be two digits
/// https://html.spec.whatwg.org/multipage/#valid-month-string
pub fn is_valid_month_string(&self) -> bool {
parse_month_string(&*self.0).is_ok()
}
}
impl Borrow<str> for DOMString {
@ -403,3 +417,90 @@ impl Extend<char> for DOMString {
self.0.extend(iterable)
}
}
/// https://html.spec.whatwg.org/multipage/#parse-a-month-string
fn parse_month_string(value: &str) -> Result<(u32, u32), ()> {
// Step 1, 2, 3
let (year_int, month_int) = parse_month_component(value)?;
// Step 4
if value.split("-").nth(2).is_some() {
return Err(());
}
// Step 5
Ok((year_int, month_int))
}
/// https://html.spec.whatwg.org/multipage/#parse-a-date-string
fn parse_date_string(value: &str) -> Result<(u32, u32, u32), ()> {
// Step 1, 2, 3
let (year_int, month_int, day_int) = parse_date_component(value)?;
// Step 4
if value.split('-').nth(3).is_some() {
return Err(());
}
// Step 5, 6
Ok((year_int, month_int, day_int))
}
/// https://html.spec.whatwg.org/multipage/#parse-a-month-component
fn parse_month_component(value: &str) -> Result<(u32, u32), ()> {
// Step 3
let mut iterator = value.split('-');
let year = iterator.next().ok_or(())?;
let month = iterator.next().ok_or(())?;
// Step 1, 2
let year_int = year.parse::<u32>().map_err(|_| ())?;
if year.len() < 4 || year_int == 0 {
return Err(());
}
// Step 4, 5
let month_int = month.parse::<u32>().map_err(|_| ())?;
if month.len() != 2 || month_int > 12 || month_int < 1 {
return Err(());
}
// Step 6
Ok((year_int, month_int))
}
/// https://html.spec.whatwg.org/multipage/#parse-a-date-component
fn parse_date_component(value: &str) -> Result<(u32, u32, u32), ()> {
// Step 1
let (year_int, month_int) = parse_month_component(value)?;
// Step 3, 4
let day = value.split('-').nth(2).ok_or(())?;
let day_int = day.parse::<u32>().map_err(|_| ())?;
if day.len() != 2 {
return Err(());
}
// Step 2, 5
let max_day = max_day_in_month(year_int, month_int)?;
if day_int == 0 || day_int > max_day {
return Err(());
}
// Step 6
Ok((year_int, month_int, day_int))
}
fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
match month_num {
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) {
Ok(29)
} else {
Ok(28)
}
},
_ => Err(())
}
}

Просмотреть файл

@ -875,6 +875,18 @@ impl HTMLInputElement {
content.strip_newlines();
content.strip_leading_and_trailing_ascii_whitespace();
}
atom!("date") => {
let mut textinput = self.textinput.borrow_mut();
if !textinput.single_line_content().is_valid_date_string() {
*textinput.single_line_content_mut() = "".into();
}
}
atom!("month") => {
let mut textinput = self.textinput.borrow_mut();
if !textinput.single_line_content().is_valid_month_string() {
*textinput.single_line_content_mut() = "".into();
}
}
atom!("color") => {
let mut textinput = self.textinput.borrow_mut();
@ -1042,6 +1054,7 @@ impl VirtualMethods for HTMLInputElement {
let value = mutation.new_value(attr).map(|value| (**value).to_owned());
self.textinput.borrow_mut().set_content(
value.map_or(DOMString::new(), DOMString::from));
self.sanitize_value();
self.update_placeholder_shown_state();
},
&local_name!("name") if self.input_type.get() == InputType::InputRadio => {
@ -1117,7 +1130,6 @@ impl VirtualMethods for HTMLInputElement {
if let Some(ref s) = self.super_type() {
s.bind_to_tree(tree_in_doc);
}
self.upcast::<Element>().check_ancestors_disabled_state_for_form_control();
}