mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
auto merge of #1297 : SimonSapin/servo/last-child, r=SimonSapin
Same as #1296, with a fixed commit message.
This commit is contained in:
commit
df7ec2613b
7 changed files with 132 additions and 2 deletions
|
@ -478,6 +478,10 @@ fn matches_simple_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: Ele
|
||||||
}
|
}
|
||||||
FirstChild => matches_first_child(element),
|
FirstChild => matches_first_child(element),
|
||||||
|
|
||||||
|
LastChild => matches_last_child(element),
|
||||||
|
|
||||||
|
OnlyChild => matches_first_child(element) && matches_last_child(element),
|
||||||
|
|
||||||
Root => matches_root(element),
|
Root => matches_root(element),
|
||||||
|
|
||||||
Negation(ref negated) => {
|
Negation(ref negated) => {
|
||||||
|
@ -525,6 +529,29 @@ fn matches_first_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: Element
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn matches_last_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
|
||||||
|
element: &T) -> bool {
|
||||||
|
let mut node = element.clone();
|
||||||
|
loop {
|
||||||
|
match node.node().next_sibling() {
|
||||||
|
Some(next_sibling) => {
|
||||||
|
node = next_sibling;
|
||||||
|
if node.is_element() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => match node.node().parent_node() {
|
||||||
|
// Selectors level 3 says :last-child does not match the
|
||||||
|
// root of the document; Warning, level 4 says, for the time
|
||||||
|
// being, the contrary...
|
||||||
|
Some(parent) => return !parent.is_document(),
|
||||||
|
None => return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn match_attribute<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
|
fn match_attribute<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
|
||||||
attr: &AttrSelector, element: &T, f: &fn(&str)-> bool) -> bool {
|
attr: &AttrSelector, element: &T, f: &fn(&str)-> bool) -> bool {
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub enum SimpleSelector {
|
||||||
AnyLink,
|
AnyLink,
|
||||||
Link,
|
Link,
|
||||||
Visited,
|
Visited,
|
||||||
FirstChild,
|
FirstChild, LastChild, OnlyChild,
|
||||||
// Empty,
|
// Empty,
|
||||||
Root,
|
Root,
|
||||||
// Lang(~str),
|
// Lang(~str),
|
||||||
|
@ -191,7 +191,7 @@ fn compute_specificity(mut selector: &CompoundSelector,
|
||||||
| &AttrExists(*) | &AttrEqual(*) | &AttrIncludes(*) | &AttrDashMatch(*)
|
| &AttrExists(*) | &AttrEqual(*) | &AttrIncludes(*) | &AttrDashMatch(*)
|
||||||
| &AttrPrefixMatch(*) | &AttrSubstringMatch(*) | &AttrSuffixMatch(*)
|
| &AttrPrefixMatch(*) | &AttrSubstringMatch(*) | &AttrSuffixMatch(*)
|
||||||
| &AnyLink | &Link | &Visited
|
| &AnyLink | &Link | &Visited
|
||||||
| &FirstChild | &Root
|
| &FirstChild | &LastChild | &OnlyChild | &Root
|
||||||
// | &Empty | &Lang(*) | &NthChild(*)
|
// | &Empty | &Lang(*) | &NthChild(*)
|
||||||
=> specificity.class_like_selectors += 1,
|
=> specificity.class_like_selectors += 1,
|
||||||
&NamespaceSelector(*) => (),
|
&NamespaceSelector(*) => (),
|
||||||
|
@ -438,6 +438,8 @@ fn parse_simple_pseudo_class(name: &str) -> Option<SimpleSelector> {
|
||||||
"link" => Some(Link),
|
"link" => Some(Link),
|
||||||
"visited" => Some(Visited),
|
"visited" => Some(Visited),
|
||||||
"first-child" => Some(FirstChild),
|
"first-child" => Some(FirstChild),
|
||||||
|
"last-child" => Some(LastChild),
|
||||||
|
"only-child" => Some(OnlyChild),
|
||||||
"root" => Some(Root),
|
"root" => Some(Root),
|
||||||
// "empty" => Some(Empty),
|
// "empty" => Some(Empty),
|
||||||
_ => None
|
_ => None
|
||||||
|
|
|
@ -3,3 +3,5 @@
|
||||||
== margin_a.html margin_b.html
|
== margin_a.html margin_b.html
|
||||||
== root_pseudo_a.html root_pseudo_b.html
|
== root_pseudo_a.html root_pseudo_b.html
|
||||||
== first_child_pseudo_a.html first_child_pseudo_b.html
|
== first_child_pseudo_a.html first_child_pseudo_b.html
|
||||||
|
== last_child_pseudo_a.html last_child_pseudo_b.html
|
||||||
|
== only_child_pseudo_a.html only_child_pseudo_b.html
|
||||||
|
|
25
src/test/ref/last_child_pseudo_a.html
Normal file
25
src/test/ref/last_child_pseudo_a.html
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>:last-child test</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html:last-child { background: red; }
|
||||||
|
html { background: yellow;}
|
||||||
|
|
||||||
|
p { width: 20px; height: 20px; background: orange; float: left; margin-left: 10px; }
|
||||||
|
div { clear: both; }
|
||||||
|
#p1, #p2, #p3 { background: red; }
|
||||||
|
#d1 > *:last-child { background: green }
|
||||||
|
#d2 > *:last-child { background: green }
|
||||||
|
#d3 > *:last-child { background: green }
|
||||||
|
#p4 { background: green; }
|
||||||
|
#d4 > *:last-child { background: red }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="d1"><p> </p><p id="p1"> </p></div>
|
||||||
|
<div id="d2"><p> </p><p id="p2"> </p> </div>
|
||||||
|
<div id="d3"><p> </p><p id="p3"> </p><!-- comment --></div>
|
||||||
|
<div id="d4"><p> </p><p id="p4"> </p><span> </span></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
22
src/test/ref/last_child_pseudo_b.html
Normal file
22
src/test/ref/last_child_pseudo_b.html
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>:last-child test</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html { background: yellow;}
|
||||||
|
|
||||||
|
p { width: 20px; height: 20px; background: orange; float: left; margin-left: 10px; }
|
||||||
|
div { clear: both; }
|
||||||
|
#p1 { background: green; }
|
||||||
|
#p2 { background: green; }
|
||||||
|
#p3 { background: green; }
|
||||||
|
#p4 { background: green; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="d1"><p> </p><p id="p1"> </p></div>
|
||||||
|
<div id="d2"><p> </p><p id="p2"> </p> </div>
|
||||||
|
<div id="d3"><p> </p><p id="p3"> </p><!-- comment --></div>
|
||||||
|
<div id="d4"><p> </p><p id="p4"> </p><span> </span></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
29
src/test/ref/only_child_pseudo_a.html
Normal file
29
src/test/ref/only_child_pseudo_a.html
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>:only-child test</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html:only-child { background: red; }
|
||||||
|
html { background: yellow;}
|
||||||
|
|
||||||
|
p { width: 20px; height: 20px; background: orange; float: left; margin-left: 10px; }
|
||||||
|
div { clear: both; }
|
||||||
|
#d1 > p, #d2 > p, #d3 > p, #d4 > p { background: red; }
|
||||||
|
#d1 > *:only-child { background: green }
|
||||||
|
#d2 > *:only-child { background: green }
|
||||||
|
#d3 > *:only-child { background: green }
|
||||||
|
#d4 > *:only-child { background: green }
|
||||||
|
#p5, #p6 { background: green; }
|
||||||
|
#d5 > *:only-child { background: red }
|
||||||
|
#d6 > *:only-child { background: red }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="d1"><p> </p></div>
|
||||||
|
<div id="d2"> <p> </p></div>
|
||||||
|
<div id="d3"><p> </p><!-- comment --></div>
|
||||||
|
<div id="d4"><!-- comment --><p> </p></div>
|
||||||
|
<div id="d5"><p id="p5"> </p><span> </span></div>
|
||||||
|
<div id="d6"><span> </span><p id="p6"> </p></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
23
src/test/ref/only_child_pseudo_b.html
Normal file
23
src/test/ref/only_child_pseudo_b.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>:only-child test</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html:only-child { background: red; }
|
||||||
|
html { background: yellow;}
|
||||||
|
|
||||||
|
p { width: 20px; height: 20px; background: orange; float: left; margin-left: 10px; }
|
||||||
|
div { clear: both; }
|
||||||
|
#d1 > p, #d2 > p, #d3 > p, #d4 > p { background: green; }
|
||||||
|
#p5, #p6 { background: green; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="d1"><p> </p></div>
|
||||||
|
<div id="d2"> <p> </p></div>
|
||||||
|
<div id="d3"><p> </p><!-- comment --></div>
|
||||||
|
<div id="d4"><!-- comment --><p> </p></div>
|
||||||
|
<div id="d5"><p id="p5"> </p><span> </span></div>
|
||||||
|
<div id="d6"><span> </span><p id="p6"> </p></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue