Auto merge of #15464 - KiChjang:pseudo-lang, r=emilio

Support lang pseudo class

Fixes #8219.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15464)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-02-27 17:21:50 -08:00 committed by GitHub
commit 4b39431215
63 changed files with 250 additions and 238 deletions

View file

@ -354,6 +354,7 @@ pub trait LayoutElementHelpers {
fn style_attribute(&self) -> *const Option<Arc<RwLock<PropertyDeclarationBlock>>>;
fn local_name(&self) -> &LocalName;
fn namespace(&self) -> &Namespace;
fn get_lang_for_layout(&self) -> String;
fn get_checked_state_for_layout(&self) -> bool;
fn get_indeterminate_state_for_layout(&self) -> bool;
fn get_state_for_layout(&self) -> ElementState;
@ -693,6 +694,30 @@ impl LayoutElementHelpers for LayoutJS<Element> {
}
}
#[allow(unsafe_code)]
fn get_lang_for_layout(&self) -> String {
unsafe {
let mut current_node = Some(self.upcast::<Node>());
while let Some(node) = current_node {
current_node = node.parent_node_ref();
match node.downcast::<Element>().map(|el| el.unsafe_get()) {
Some(elem) => {
if let Some(attr) = (*elem).get_attr_val_for_layout(&ns!(xml), &local_name!("lang")) {
return attr.to_owned();
}
if let Some(attr) = (*elem).get_attr_val_for_layout(&ns!(), &local_name!("lang")) {
return attr.to_owned();
}
}
None => continue
}
}
// TODO: Check meta tags for a pragma-set default language
// TODO: Check HTTP Content-Language header
String::new()
}
}
#[inline]
#[allow(unsafe_code)]
fn get_checked_state_for_layout(&self) -> bool {
@ -2372,6 +2397,10 @@ impl<'a> ::selectors::Element for Root<Element> {
}
},
// FIXME(#15746): This is wrong, we need to instead use extended filtering as per RFC4647
// https://tools.ietf.org/html/rfc4647#section-3.3.2
NonTSPseudoClass::Lang(ref lang) => lang.eq_ignore_ascii_case(&self.get_lang()),
NonTSPseudoClass::ReadOnly =>
!Element::state(self).contains(pseudo_class.state_flag()),
@ -2576,6 +2605,19 @@ impl Element {
self.set_click_in_progress(false);
}
// https://html.spec.whatwg.org/multipage/#language
pub fn get_lang(&self) -> String {
self.upcast::<Node>().inclusive_ancestors().filter_map(|node| {
node.downcast::<Element>().and_then(|el| {
el.get_attribute(&ns!(xml), &local_name!("lang")).or_else(|| {
el.get_attribute(&ns!(), &local_name!("lang"))
}).map(|attr| String::from(attr.Value()))
})
// TODO: Check meta tags for a pragma-set default language
// TODO: Check HTTP Content-Language header
}).next().unwrap_or(String::new())
}
pub fn state(&self) -> ElementState {
self.state.get()
}