mirror of
https://github.com/servo/servo.git
synced 2025-07-26 00:30:22 +01:00
ext. filtering for lang matching
This commit is contained in:
parent
c62973b77b
commit
b6e6e84bcf
15 changed files with 74 additions and 94 deletions
|
@ -113,6 +113,64 @@ pub fn is_token(s: &[u8]) -> bool {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns whether the language is matched, as defined by
|
||||
/// [RFC 4647](https://tools.ietf.org/html/rfc4647#section-3.3.2).
|
||||
pub fn extended_filtering(tag: &str, range: &str) -> bool {
|
||||
let lang_ranges: Vec<&str> = range.split(',').collect();
|
||||
|
||||
lang_ranges.iter().any(|&lang_range| {
|
||||
// step 1
|
||||
let range_subtags: Vec<&str> = lang_range.split('\x2d').collect();
|
||||
let tag_subtags: Vec<&str> = tag.split('\x2d').collect();
|
||||
|
||||
let mut range_iter = range_subtags.iter();
|
||||
let mut tag_iter = tag_subtags.iter();
|
||||
|
||||
// step 2
|
||||
// Note: [Level-4 spec](https://drafts.csswg.org/selectors/#lang-pseudo) check for wild card
|
||||
if let (Some(range_subtag), Some(tag_subtag)) = (range_iter.next(), tag_iter.next()) {
|
||||
if !(range_subtag.eq_ignore_ascii_case(tag_subtag) || range_subtag.eq_ignore_ascii_case("*")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let mut current_tag_subtag = tag_iter.next();
|
||||
|
||||
// step 3
|
||||
for range_subtag in range_iter {
|
||||
// step 3a
|
||||
if range_subtag.eq_ignore_ascii_case("*") {
|
||||
continue;
|
||||
}
|
||||
match current_tag_subtag.clone() {
|
||||
Some(tag_subtag) => {
|
||||
// step 3c
|
||||
if range_subtag.eq_ignore_ascii_case(tag_subtag) {
|
||||
current_tag_subtag = tag_iter.next();
|
||||
continue;
|
||||
} else {
|
||||
// step 3d
|
||||
if tag_subtag.len() == 1 {
|
||||
return false;
|
||||
} else {
|
||||
// else step 3e - continue with loop
|
||||
current_tag_subtag = tag_iter.next();
|
||||
if current_tag_subtag.is_none() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// step 3b
|
||||
None => { return false; }
|
||||
}
|
||||
}
|
||||
// step 4
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// A DOMString.
|
||||
///
|
||||
/// This type corresponds to the [`DOMString`](idl) type in WebIDL.
|
||||
|
|
|
@ -25,7 +25,7 @@ use dom::bindings::js::{JS, LayoutJS, MutNullableJS};
|
|||
use dom::bindings::js::{Root, RootedReference};
|
||||
use dom::bindings::refcounted::{Trusted, TrustedPromise};
|
||||
use dom::bindings::reflector::DomObject;
|
||||
use dom::bindings::str::DOMString;
|
||||
use dom::bindings::str::{DOMString, extended_filtering};
|
||||
use dom::bindings::xmlname::{namespace_from_domstring, validate_and_extract, xml_name_type};
|
||||
use dom::bindings::xmlname::XMLName::InvalidXMLName;
|
||||
use dom::characterdata::CharacterData;
|
||||
|
@ -2402,7 +2402,7 @@ 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::Lang(ref lang) => extended_filtering(&*self.get_lang(), &*lang),
|
||||
|
||||
NonTSPseudoClass::ReadOnly =>
|
||||
!Element::state(self).contains(pseudo_class.state_flag()),
|
||||
|
|
|
@ -34,6 +34,7 @@ use atomic_refcell::AtomicRefCell;
|
|||
use dom::bindings::inheritance::{CharacterDataTypeId, ElementTypeId};
|
||||
use dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId};
|
||||
use dom::bindings::js::LayoutJS;
|
||||
use dom::bindings::str::extended_filtering;
|
||||
use dom::characterdata::LayoutCharacterDataHelpers;
|
||||
use dom::document::{Document, LayoutDocumentHelpers, PendingRestyle};
|
||||
use dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
|
||||
|
@ -53,7 +54,6 @@ use selectors::matching::ElementSelectorFlags;
|
|||
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
||||
use servo_atoms::Atom;
|
||||
use servo_url::ServoUrl;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
|
@ -621,7 +621,7 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
|
|||
|
||||
// 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.element.get_lang_for_layout()),
|
||||
NonTSPseudoClass::Lang(ref lang) => extended_filtering(&*self.element.get_lang_for_layout(), &*lang),
|
||||
|
||||
NonTSPseudoClass::ServoNonZeroBorder => unsafe {
|
||||
match (*self.element.unsafe_get()).get_attr_for_layout(&ns!(), &local_name!("border")) {
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[css3-selectors-lang-005.htm]
|
||||
type: testharness
|
||||
[A :lang value will match a lang attribute value when the latter contains additional subtags.]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[css3-selectors-lang-009.htm]
|
||||
type: testharness
|
||||
[A :lang value with a multiple subtags will match a lang attribute value with multiple subtags as long as the first part is the same.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[css3-selectors-lang-014.htm]
|
||||
type: testharness
|
||||
[A :lang value with language and region subtags will NOT match a lang attribute value with language, script and region subtags.]
|
||||
expected: FAIL
|
|
@ -1,5 +0,0 @@
|
|||
[css3-selectors-lang-005.xht]
|
||||
type: testharness
|
||||
[A :lang value will match a lang attribute value when the latter contains additional subtags.]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[css3-selectors-lang-009.xht]
|
||||
type: testharness
|
||||
[A :lang value with a multiple subtags will match a lang attribute value with multiple subtags as long as the first part is the same.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[css3-selectors-lang-014.xht]
|
||||
type: testharness
|
||||
[A :lang value with language and region subtags will NOT match a lang attribute value with language, script and region subtags.]
|
||||
expected: FAIL
|
|
@ -1,5 +0,0 @@
|
|||
[css3-selectors-lang-005.xht]
|
||||
type: testharness
|
||||
[A :lang value will match a lang attribute value when the latter contains additional subtags.]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[css3-selectors-lang-009.xht]
|
||||
type: testharness
|
||||
[A :lang value with a multiple subtags will match a lang attribute value with multiple subtags as long as the first part is the same.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[css3-selectors-lang-014.xht]
|
||||
type: testharness
|
||||
[A :lang value with language and region subtags will NOT match a lang attribute value with language, script and region subtags.]
|
||||
expected: FAIL
|
|
@ -1,14 +1,5 @@
|
|||
[Element-matches.html]
|
||||
type: testharness
|
||||
[In-document Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Detached Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Fragment Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[In-document Element.matches: Universal selector, matching all children of the specified reference element (with refNode Element): >*]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -18,9 +9,6 @@
|
|||
[In-document Element.matches: Universal selector, matching all descendants of the specified reference element (with refNode Element): *]
|
||||
expected: FAIL
|
||||
|
||||
[In-document Element.matches: :lang pseudo-class selector, matching specified language with partial value (1) (with no refNodes): #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[In-document Element.matches: Class selector, matching element with class value using non-ASCII characters (with no refNodes): .台北Táiběi]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
[ParentNode-querySelector-All-xht.xht]
|
||||
type: testharness
|
||||
[Document.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Document.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Document.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -30,12 +24,6 @@
|
|||
[Document.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter]
|
||||
expected: FAIL
|
||||
|
||||
[Detached Element.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Detached Element.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Detached Element.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -60,12 +48,6 @@
|
|||
[Detached Element.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter]
|
||||
expected: FAIL
|
||||
|
||||
[Fragment.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Fragment.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Fragment.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -90,12 +72,6 @@
|
|||
[Fragment.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter]
|
||||
expected: FAIL
|
||||
|
||||
[In-document Element.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[In-document Element.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[In-document Element.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
[ParentNode-querySelector-All.html]
|
||||
type: testharness
|
||||
[Document.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Document.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Document.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -30,12 +24,6 @@
|
|||
[Document.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter]
|
||||
expected: FAIL
|
||||
|
||||
[Detached Element.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Detached Element.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Detached Element.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -60,12 +48,6 @@
|
|||
[Detached Element.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter]
|
||||
expected: FAIL
|
||||
|
||||
[Fragment.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Fragment.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[Fragment.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -90,12 +72,6 @@
|
|||
[Fragment.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter]
|
||||
expected: FAIL
|
||||
|
||||
[In-document Element.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[In-document Element.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en)]
|
||||
expected: FAIL
|
||||
|
||||
[In-document Element.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line]
|
||||
expected: FAIL
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue