aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/components/style/selector_matching.rs76
-rw-r--r--src/components/style/selectors.rs22
-rw-r--r--src/test/ref/basic.list7
-rw-r--r--src/test/ref/first_of_type_pseudo_a.html52
-rw-r--r--src/test/ref/first_of_type_pseudo_b.html48
-rw-r--r--src/test/ref/last_of_type_pseudo_a.html52
-rw-r--r--src/test/ref/last_of_type_pseudo_b.html48
-rw-r--r--src/test/ref/nth_child_pseudo_a.html89
-rw-r--r--src/test/ref/nth_child_pseudo_b.html74
-rw-r--r--src/test/ref/nth_last_child_pseudo_a.html89
-rw-r--r--src/test/ref/nth_last_child_pseudo_b.html74
-rw-r--r--src/test/ref/nth_last_of_type_pseudo_a.html131
-rw-r--r--src/test/ref/nth_last_of_type_pseudo_b.html116
-rw-r--r--src/test/ref/nth_of_type_pseudo_a.html131
-rw-r--r--src/test/ref/nth_of_type_pseudo_b.html115
-rw-r--r--src/test/ref/only_of_type_pseudo_a.html47
-rw-r--r--src/test/ref/only_of_type_pseudo_b.html42
17 files changed, 1207 insertions, 6 deletions
diff --git a/src/components/style/selector_matching.rs b/src/components/style/selector_matching.rs
index db6afabccb2..f36decd8fc7 100644
--- a/src/components/style/selector_matching.rs
+++ b/src/components/style/selector_matching.rs
@@ -489,14 +489,24 @@ 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),
+ OnlyChild => matches_first_child(element) &&
+ matches_last_child(element),
Root => matches_root(element),
+ NthChild(a, b) => matches_generic_nth_child(element, a, b, false, false),
+ NthLastChild(a, b) => matches_generic_nth_child(element, a, b, false, true),
+ NthOfType(a, b) => matches_generic_nth_child(element, a, b, true, false),
+ NthLastOfType(a, b) => matches_generic_nth_child(element, a, b, true, true),
+
+ FirstOfType => matches_generic_nth_child(element, 0, 1, true, false),
+ LastOfType => matches_generic_nth_child(element, 0, 1, true, true),
+ OnlyOfType => matches_generic_nth_child(element, 0, 1, true, false) &&
+ matches_generic_nth_child(element, 0, 1, true, true),
+
Negation(ref negated) => {
!negated.iter().all(|s| matches_simple_selector(s, element))
},
@@ -511,6 +521,66 @@ fn url_is_visited(_url: &str) -> bool {
}
#[inline]
+fn matches_generic_nth_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
+ element: &T, a: i32, b: i32, is_of_type: bool, is_from_end: bool) -> bool {
+ let mut node = element.clone();
+ // fail if we can't find a parent or if the node is the root element
+ // of the document (Cf. Selectors Level 3)
+ match node.node().parent_node() {
+ Some(parent) => if parent.is_document() {
+ return false;
+ },
+ None => return false
+ };
+
+ let mut local_name = "";
+ if is_of_type {
+ // FIXME this is wrong
+ // TODO when the DOM supports namespaces on elements
+ do element.with_imm_element_like |element: &E| {
+ local_name = element.get_local_name();
+ }
+ }
+
+ let mut index = 1;
+ loop {
+ if is_from_end {
+ match node.node().next_sibling() {
+ None => break,
+ Some(next_sibling) => node = next_sibling
+ }
+ } else {
+ match node.node().prev_sibling() {
+ None => break,
+ Some(prev_sibling) => node = prev_sibling
+ }
+ }
+
+ if node.is_element() {
+ if is_of_type {
+ // FIXME this is wrong
+ // TODO when the DOM supports namespaces on elements
+ do node.with_imm_element_like |node: &E| {
+ if local_name == node.get_local_name() {
+ index += 1;
+ }
+ }
+ } else {
+ index += 1;
+ }
+ }
+
+ }
+
+ if a == 0 {
+ return b == index;
+ }
+
+ let (n, r) = (index - b).div_rem(&a);
+ n >= 0 && r == 0
+}
+
+#[inline]
fn matches_root<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
element: &T) -> bool {
match element.node().parent_node() {
diff --git a/src/components/style/selectors.rs b/src/components/style/selectors.rs
index d668b8085a4..c6042ee655d 100644
--- a/src/components/style/selectors.rs
+++ b/src/components/style/selectors.rs
@@ -5,6 +5,7 @@
use std::{vec, iter};
use std::ascii::StrAsciiExt;
use cssparser::ast::*;
+use cssparser::parse_nth;
use namespaces::NamespaceMap;
@@ -66,7 +67,13 @@ pub enum SimpleSelector {
// Empty,
Root,
// Lang(~str),
-// NthChild(i32, i32),
+ NthChild(i32, i32),
+ NthLastChild(i32, i32),
+ NthOfType(i32, i32),
+ NthLastOfType(i32, i32),
+ FirstOfType,
+ LastOfType,
+ OnlyOfType
// ...
}
@@ -192,7 +199,10 @@ fn compute_specificity(mut selector: &CompoundSelector,
| &AttrPrefixMatch(*) | &AttrSubstringMatch(*) | &AttrSuffixMatch(*)
| &AnyLink | &Link | &Visited
| &FirstChild | &LastChild | &OnlyChild | &Root
-// | &Empty | &Lang(*) | &NthChild(*)
+// | &Empty | &Lang(*)
+ | &NthChild(*) | &NthLastChild(*)
+ | &NthOfType(*) | &NthLastOfType(*)
+ | &FirstOfType | &LastOfType | &OnlyOfType
=> specificity.class_like_selectors += 1,
&NamespaceSelector(*) => (),
&Negation(ref negated)
@@ -441,6 +451,9 @@ fn parse_simple_pseudo_class(name: &str) -> Option<SimpleSelector> {
"last-child" => Some(LastChild),
"only-child" => Some(OnlyChild),
"root" => Some(Root),
+ "first-of-type" => Some(FirstOfType),
+ "last-of-type" => Some(LastOfType),
+ "only-of-type" => Some(OnlyOfType),
// "empty" => Some(Empty),
_ => None
}
@@ -452,7 +465,10 @@ fn parse_functional_pseudo_class(name: ~str, arguments: ~[ComponentValue],
-> Option<SimpleSelector> {
match name.to_ascii_lower().as_slice() {
// "lang" => parse_lang(arguments),
-// "nth-child" => parse_nth(arguments).map(|&(a, b)| NthChild(a, b)),
+ "nth-child" => parse_nth(arguments).map(|(a, b)| NthChild(a, b)),
+ "nth-last-child" => parse_nth(arguments).map(|(a, b)| NthLastChild(a, b)),
+ "nth-of-type" => parse_nth(arguments).map(|(a, b)| NthOfType(a, b)),
+ "nth-last-of-type" => parse_nth(arguments).map(|(a, b)| NthLastOfType(a, b)),
"not" => if inside_negation { None } else { parse_negation(arguments, namespaces) },
_ => None
}
diff --git a/src/test/ref/basic.list b/src/test/ref/basic.list
index 649d35a28ca..a18747e8ab9 100644
--- a/src/test/ref/basic.list
+++ b/src/test/ref/basic.list
@@ -5,3 +5,10 @@
== 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
+== nth_child_pseudo_a.html nth_child_pseudo_b.html
+== nth_last_child_pseudo_a.html nth_last_child_pseudo_b.html
+== nth_of_type_pseudo_a.html nth_of_type_pseudo_b.html
+== nth_last_of_type_pseudo_a.html nth_last_of_type_pseudo_b.html
+== first_of_type_pseudo_a.html first_of_type_pseudo_b.html
+== last_of_type_pseudo_a.html last_of_type_pseudo_b.html
+== only_of_type_pseudo_a.html only_of_type_pseudo_b.html
diff --git a/src/test/ref/first_of_type_pseudo_a.html b/src/test/ref/first_of_type_pseudo_a.html
new file mode 100644
index 00000000000..1edc27fa325
--- /dev/null
+++ b/src/test/ref/first_of_type_pseudo_a.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:first-of-type test</title>
+ <style type="text/css">
+ /* should not match according to Selectors 3 because html has no parent element */
+ html:first-of-type { background: red; }
+
+ div > p,
+ div > div,
+ div > address {
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
+ margin-right: 10px;
+ padding: 0px;
+ }
+ div > p {
+ background: white;
+ }
+ div > div,
+ div > address {
+ background: black;
+ }
+ body > div { clear: both; margin-bottom: 10px; }
+
+ #d1 > .ok { background: red; }
+ #d1 > *:first-of-type { background: green }
+
+ </style>
+ </head>
+ <body>
+ <div id="d1">
+ <p class="ok"> </p>
+ <div class="ok"> </div>
+ <div> </div>
+ <p> </p>
+ <address class="ok"> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/first_of_type_pseudo_b.html b/src/test/ref/first_of_type_pseudo_b.html
new file mode 100644
index 00000000000..46e9528f8ef
--- /dev/null
+++ b/src/test/ref/first_of_type_pseudo_b.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:first-of-type test</title>
+ <style type="text/css">
+ div > p,
+ div > div,
+ div > address {
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
+ margin-right: 10px;
+ padding: 0px;
+ }
+ div > p {
+ background: white;
+ }
+ div > div,
+ div > address {
+ background: black;
+ }
+ body > div { clear: both; margin-bottom: 10px; }
+
+ #d1 > .ok { background: green; }
+
+ </style>
+ </head>
+ <body>
+ <div id="d1">
+ <p class="ok"> </p>
+ <div class="ok"> </div>
+ <div> </div>
+ <p> </p>
+ <address class="ok"> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/last_of_type_pseudo_a.html b/src/test/ref/last_of_type_pseudo_a.html
new file mode 100644
index 00000000000..244355ff765
--- /dev/null
+++ b/src/test/ref/last_of_type_pseudo_a.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:last-of-type test</title>
+ <style type="text/css">
+ /* should not match according to Selectors 3 because html has no parent element */
+ html:last-of-type { background: red; }
+
+ div > p,
+ div > div,
+ div > address {
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
+ margin-right: 10px;
+ padding: 0px;
+ }
+ div > p {
+ background: white;
+ }
+ div > div,
+ div > address {
+ background: black;
+ }
+ body > div { clear: both; margin-bottom: 10px; }
+
+ #d1 > .ok { background: red; }
+ #d1 > *:last-of-type { background: green }
+
+ </style>
+ </head>
+ <body>
+ <div id="d1">
+ <p> </p>
+ <div> </div>
+ <div> </div>
+ <p> </p>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <address> </address>
+ <address class="ok"> </address>
+ <p> </p>
+ <div class="ok"> </div>
+ <p> </p>
+ <p class="ok"> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/last_of_type_pseudo_b.html b/src/test/ref/last_of_type_pseudo_b.html
new file mode 100644
index 00000000000..18ebcdfa078
--- /dev/null
+++ b/src/test/ref/last_of_type_pseudo_b.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:last-of-type test</title>
+ <style type="text/css">
+ div > p,
+ div > div,
+ div > address {
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
+ margin-right: 10px;
+ padding: 0px;
+ }
+ div > p {
+ background: white;
+ }
+ div > div,
+ div > address {
+ background: black;
+ }
+ body > div { clear: both; margin-bottom: 10px; }
+
+ #d1 > .ok { background: green; }
+
+ </style>
+ </head>
+ <body>
+ <div id="d1">
+ <p> </p>
+ <div> </div>
+ <div> </div>
+ <p> </p>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <address> </address>
+ <address class="ok"> </address>
+ <p> </p>
+ <div class="ok"> </div>
+ <p> </p>
+ <p class="ok"> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/nth_child_pseudo_a.html b/src/test/ref/nth_child_pseudo_a.html
new file mode 100644
index 00000000000..9603887b6c1
--- /dev/null
+++ b/src/test/ref/nth_child_pseudo_a.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:nth-child test</title>
+ <style type="text/css">
+ /* should not match according to Selectors 3 because html has no parent element */
+ html:nth-child(1) { background: red; }
+
+ div > p { float: left; width: 40px; height: 40px; margin-right: 10px; border: 1px solid black; }
+ div { clear: both; }
+
+ #odd > .odd { background: red; }
+ #odd > *:nth-child(odd) { background: green }
+
+ #even > .even { background: red; }
+ #even > *:nth-child(even) { background: green }
+
+ #nth > .nth { background: red; }
+ #nth > :nth-child(3n+5) { background: green; }
+
+ #nth2 > .nth2 { background: red; }
+ #nth2 > :nth-child(3n-5) { background: green; }
+
+ #negativen > .negativen { background: red; }
+ #negativen > :nth-child(-2n+5) { background: green; }
+ </style>
+ </head>
+ <body>
+ <div id="odd">
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ </div>
+ <div id="even">
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ </div>
+ <div id="nth">
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth"> </p>
+ </div>
+ <div id="nth2">
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ </div>
+ <div id="negativen">
+ <p class="negativen"> </p>
+ <p> </p>
+ <p class="negativen"> </p>
+ <p> </p>
+ <p class="negativen"> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/nth_child_pseudo_b.html b/src/test/ref/nth_child_pseudo_b.html
new file mode 100644
index 00000000000..b0112cb0777
--- /dev/null
+++ b/src/test/ref/nth_child_pseudo_b.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:nth-child test</title>
+ <style type="text/css">
+
+ div > p { float: left; width: 40px; height: 40px; margin-right: 10px; border: 1px solid black; }
+ div { clear: both; }
+
+ .odd, .even, .nth, .nth2, .negativen { background: green; }
+ </style>
+ </head>
+ <body>
+ <div id="odd">
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ </div>
+ <div id="even">
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ </div>
+ <div id="nth">
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth"> </p>
+ </div>
+ <div id="nth2">
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ </div>
+ <div id="negativen">
+ <p class="negativen"> </p>
+ <p> </p>
+ <p class="negativen"> </p>
+ <p> </p>
+ <p class="negativen"> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/nth_last_child_pseudo_a.html b/src/test/ref/nth_last_child_pseudo_a.html
new file mode 100644
index 00000000000..3afd8e37344
--- /dev/null
+++ b/src/test/ref/nth_last_child_pseudo_a.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:nth-last-child test</title>
+ <style type="text/css">
+ /* should not match according to Selectors 3 because html has no parent element */
+ html:nth-last-child(1) { background: red; }
+
+ div > p { float: left; width: 40px; height: 40px; margin-right: 10px; border: 1px solid black; }
+ div { clear: both; }
+
+ #odd > .odd { background: red; }
+ #odd > *:nth-last-child(odd) { background: green }
+
+ #even > .even { background: red; }
+ #even > *:nth-last-child(even) { background: green }
+
+ #nth > .nth { background: red; }
+ #nth > :nth-last-child(3n+5) { background: green; }
+
+ #nth2 > .nth2 { background: red; }
+ #nth2 > :nth-last-child(3n-5) { background: green; }
+
+ #negativen > .negativen { background: red; }
+ #negativen > :nth-last-child(-2n+5) { background: green; }
+ </style>
+ </head>
+ <body>
+ <div id="odd">
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ </div>
+ <div id="even">
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ </div>
+ <div id="nth">
+ <p class="nth"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth"> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ </div>
+ <div id="nth2">
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ </div>
+ <div id="negativen">
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p class="negativen"> </p>
+ <p> </p>
+ <p class="negativen"> </p>
+ <p> </p>
+ <p class="negativen"> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/nth_last_child_pseudo_b.html b/src/test/ref/nth_last_child_pseudo_b.html
new file mode 100644
index 00000000000..5be3dbb3416
--- /dev/null
+++ b/src/test/ref/nth_last_child_pseudo_b.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:nth-last-child test</title>
+ <style type="text/css">
+
+ div > p { float: left; width: 40px; height: 40px; margin-right: 10px; border: 1px solid black; }
+ div { clear: both; }
+
+ .odd, .even, .nth, .nth2, .negativen { background: green; }
+ </style>
+ </head>
+ <body>
+ <div id="odd">
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ <p> </p>
+ <p class="odd"> </p>
+ </div>
+ <div id="even">
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ <p class="even"> </p>
+ <p> </p>
+ </div>
+ <div id="nth">
+ <p class="nth"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth"> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ </div>
+ <div id="nth2">
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ <p> </p>
+ <p> </p>
+ <p class="nth2"> </p>
+ </div>
+ <div id="negativen">
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <p class="negativen"> </p>
+ <p> </p>
+ <p class="negativen"> </p>
+ <p> </p>
+ <p class="negativen"> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/nth_last_of_type_pseudo_a.html b/src/test/ref/nth_last_of_type_pseudo_a.html
new file mode 100644
index 00000000000..5ad59e770c5
--- /dev/null
+++ b/src/test/ref/nth_last_of_type_pseudo_a.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:nth-last-of-type test</title>
+ <style type="text/css">
+ /* should not match according to Selectors 3 because html has no parent element */
+ html:nth-last-of-type(1) { background: red; }
+
+ div > p,
+ div > div,
+ div > address {
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
+ margin-right: 10px;
+ padding: 0px;
+ }
+ div > p {
+ background: white;
+ }
+ div > div,
+ div > address {
+ background: black;
+ }
+ body > div { clear: both; margin-bottom: 10px; }
+
+ #odd > .odd { background: red; }
+ #odd > p:nth-last-of-type(odd) { background: green }
+
+ #even > .even { background: red; }
+ #even > p:nth-last-of-type(even) { background: green }
+
+ #nth > .nth { background: red; }
+ #nth > p:nth-last-of-type(3n+5) { background: green; }
+
+ #nth2 > .nth2 { background: red; }
+ #nth2 > p:nth-last-of-type(3n-5) { background: green; }
+
+ #negativen > .negativen { background: red; }
+ #negativen > p:nth-last-of-type(-2n+5) { background: green; }
+ </style>
+ </head>
+ <body>
+ <div id="odd">
+ <p> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p class="odd"> </p>
+ <p> </p>
+ <div> </div>
+ <p class="odd"> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p class="odd"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="odd"> </p>
+ </div>
+ <div id="even">
+ <p class="even"> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p class="even"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="even"> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p class="even"> </p>
+ <p> </p>
+ </div>
+ <div id="nth">
+ <p class="nth"> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <div> </div>
+ <p class="nth"> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ </div>
+ <div id="nth2">
+ <p> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p class="nth2"> </p>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p class="nth2"> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p class="nth2"> </p>
+ </div>
+ <div id="negativen">
+ <p> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <div> </div>
+ <p class="negativen"> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p class="negativen"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="negativen"> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/nth_last_of_type_pseudo_b.html b/src/test/ref/nth_last_of_type_pseudo_b.html
new file mode 100644
index 00000000000..fe04106efc6
--- /dev/null
+++ b/src/test/ref/nth_last_of_type_pseudo_b.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:nth-last-of-type test</title>
+ <style type="text/css">
+
+ div > p,
+ div > div,
+ div > address {
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
+ margin-right: 10px;
+ padding: 0px;
+ }
+ div > p {
+ background: white;
+ }
+ div > div,
+ div > address {
+ background: black;
+ }
+ body > div { clear: both; margin-bottom: 10px; }
+
+ .odd, .even, .nth, .nth2, .negativen { background: green; }
+ </style>
+ </head>
+ <body>
+ <div id="odd">
+ <p> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p class="odd"> </p>
+ <p> </p>
+ <div> </div>
+ <p class="odd"> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p class="odd"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="odd"> </p>
+ </div>
+ <div id="even">
+ <p class="even"> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p class="even"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="even"> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p class="even"> </p>
+ <p> </p>
+ </div>
+ <div id="nth">
+ <p class="nth"> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <div> </div>
+ <p class="nth"> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ </div>
+ <div id="nth2">
+ <p> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p class="nth2"> </p>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p class="nth2"> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p class="nth2"> </p>
+ </div>
+ <div id="negativen">
+ <p> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <div> </div>
+ <p class="negativen"> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p class="negativen"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="negativen"> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/nth_of_type_pseudo_a.html b/src/test/ref/nth_of_type_pseudo_a.html
new file mode 100644
index 00000000000..1f4416d7bbc
--- /dev/null
+++ b/src/test/ref/nth_of_type_pseudo_a.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:nth-of-type test</title>
+ <style type="text/css">
+ /* should not match according to Selectors 3 because html has no parent element */
+ html:nth-of-type(1) { background: red; }
+
+ div > p,
+ div > div,
+ div > address {
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
+ margin-right: 10px;
+ padding: 0px;
+ }
+ div > p {
+ background: white;
+ }
+ div > div,
+ div > address {
+ background: black;
+ }
+ body > div { clear: both; margin-bottom: 10px; }
+
+ #odd > .odd { background: red; }
+ #odd > p:nth-of-type(odd) { background: green }
+
+ #even > .even { background: red; }
+ #even > p:nth-of-type(even) { background: green }
+
+ #nth > .nth { background: red; }
+ #nth > p:nth-of-type(3n+5) { background: green; }
+
+ #nth2 > .nth2 { background: red; }
+ #nth2 > p:nth-of-type(3n-5) { background: green; }
+
+ #negativen > .negativen { background: red; }
+ #negativen > p:nth-of-type(-2n+5) { background: green; }
+ </style>
+ </head>
+ <body>
+ <div id="odd">
+ <p class="odd"> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p class="odd"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="odd"> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p class="odd"> </p>
+ <p> </p>
+ </div>
+ <div id="even">
+ <p> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p class="even"> </p>
+ <p> </p>
+ <div> </div>
+ <p class="even"> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p class="even"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="even"> </p>
+ </div>
+ <div id="nth">
+ <p> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p class="nth"> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p class="nth"> </p>
+ </div>
+ <div id="nth2">
+ <p class="nth2"> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <div> </div>
+ <p class="nth2"> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p class="nth2"> </p>
+ <p> </p>
+ </div>
+ <div id="negativen">
+ <p class="negativen"> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p class="negativen"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="negativen"> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/nth_of_type_pseudo_b.html b/src/test/ref/nth_of_type_pseudo_b.html
new file mode 100644
index 00000000000..8b76202920a
--- /dev/null
+++ b/src/test/ref/nth_of_type_pseudo_b.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:nth-of-type test</title>
+ <style type="text/css">
+ div > p,
+ div > div,
+ div > address {
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
+ margin-right: 10px;
+ padding: 0px;
+ }
+ div > p {
+ background: white;
+ }
+ div > div,
+ div > address {
+ background: black;
+ }
+ body > div { clear: both; margin-bottom: 10px; }
+
+ .odd, .even, .nth, .nth2, .negativen { background: green; }
+ </style>
+ </head>
+ <body>
+ <div id="odd">
+ <p class="odd"> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p class="odd"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="odd"> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p class="odd"> </p>
+ <p> </p>
+ </div>
+ <div id="even">
+ <p> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p class="even"> </p>
+ <p> </p>
+ <div> </div>
+ <p class="even"> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p class="even"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="even"> </p>
+ </div>
+ <div id="nth">
+ <p> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p class="nth"> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p class="nth"> </p>
+ </div>
+ <div id="nth2">
+ <p class="nth2"> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <div> </div>
+ <p class="nth2"> </p>
+ <p> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p class="nth2"> </p>
+ <p> </p>
+ </div>
+ <div id="negativen">
+ <p class="negativen"> </p>
+ <div> </div>
+ <address> </address>
+ <div> </div>
+ <p> </p>
+ <p class="negativen"> </p>
+ <div> </div>
+ <p> </p>
+ <p class="negativen"> </p>
+ <address> </address>
+ <address> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/only_of_type_pseudo_a.html b/src/test/ref/only_of_type_pseudo_a.html
new file mode 100644
index 00000000000..18b3d4f21dd
--- /dev/null
+++ b/src/test/ref/only_of_type_pseudo_a.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:only-of-type test</title>
+ <style type="text/css">
+ /* should not match according to Selectors 3 because html has no parent element */
+ html:only-of-type { background: red; }
+
+ div > p,
+ div > div,
+ div > address {
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
+ margin-right: 10px;
+ padding: 0px;
+ }
+ div > div,
+ div > p {
+ background: black;
+ }
+ body > div { clear: both; margin-bottom: 10px; }
+
+ #d1 > .ok { background: red; }
+ #d1 > *:only-of-type { background: green }
+
+ </style>
+ </head>
+ <body>
+ <div id="d1">
+ <p> </p>
+ <div> </div>
+ <div> </div>
+ <p> </p>
+ <address class="ok"> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ </div>
+ </body>
+</html>
diff --git a/src/test/ref/only_of_type_pseudo_b.html b/src/test/ref/only_of_type_pseudo_b.html
new file mode 100644
index 00000000000..c66c0faadda
--- /dev/null
+++ b/src/test/ref/only_of_type_pseudo_b.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>:only-of-type test</title>
+ <style type="text/css">
+ div > p,
+ div > div,
+ div > address {
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
+ margin-right: 10px;
+ padding: 0px;
+ }
+ div > div,
+ div > p {
+ background: black;
+ }
+ body > div { clear: both; margin-bottom: 10px; }
+
+ #d1 > .ok { background: green; }
+ </style>
+ </head>
+ <body>
+ <div id="d1">
+ <p> </p>
+ <div> </div>
+ <div> </div>
+ <p> </p>
+ <address class="ok"> </address>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ <p> </p>
+ <div> </div>
+ <p> </p>
+ <p> </p>
+ </div>
+ </body>
+</html>