Add *of-type selectors
Mon Jan 4 06:32:07 UTC 2010 pix@kepibu.org
* Add *of-type selectors
diff -rN -u old-Oh, Ducks!/notes new-Oh, Ducks!/notes
--- old-Oh, Ducks!/notes 2013-07-24 10:34:58.000000000 +0000
+++ new-Oh, Ducks!/notes 2013-07-24 10:34:58.000000000 +0000
@@ -134,7 +134,7 @@
* [ ] selectors involving descendants
** write documentation
** improve selector support
-*** positional selectors [9/19]
+*** positional selectors [18/19]
* [X] :nth-child(an+b)
* [X] :nth-child(b)
* [X] :nth-child(odd|even)
@@ -143,16 +143,16 @@
* [X] :nth-last-child(odd|even)
* [X] :first-child
* [X] :last-child
- * [ ] :nth-of-type(an+b)
- * [ ] :nth-of-type(b)
- * [ ] :nth-of-type(odd|even)
- * [ ] :nth-last-of-type(an+b)
- * [ ] :nth-last-of-type(b)
- * [ ] :nth-last-of-type(odd|even)
- * [ ] :first-of-type
- * [ ] :last-of-type
+ * [X] :nth-of-type(an+b)
+ * [X] :nth-of-type(b)
+ * [X] :nth-of-type(odd|even)
+ * [X] :nth-last-of-type(an+b)
+ * [X] :nth-last-of-type(b)
+ * [X] :nth-last-of-type(odd|even)
+ * [X] :first-of-type
+ * [X] :last-of-type
* [X] :only-child
- * [ ] :only-of-type
+ * [X] :only-of-type
* [ ] :empty
*** attribute selectors [0/7]
* [ ] attribute-present [att]
diff -rN -u old-Oh, Ducks!/selectors.lisp new-Oh, Ducks!/selectors.lisp
--- old-Oh, Ducks!/selectors.lisp 2013-07-24 10:34:58.000000000 +0000
+++ new-Oh, Ducks!/selectors.lisp 2013-07-24 10:34:58.000000000 +0000
@@ -38,6 +38,8 @@
(defclass class-selector (simple-selector) ())
(defclass nth-child-selector (simple-selector) ())
(defclass nth-last-child-selector (nth-child-selector) ())
+(defclass nth-of-type-selector (nth-child-selector) ())
+(defclass nth-last-of-type-selector (nth-of-type-selector) ())
(defmethod initialize-instance :after ((selector nth-child-selector)
&key (asign "+") a
@@ -113,6 +115,18 @@
:asign asign :a a
:bsign bsign :b b)
(parse-selector &rest)))
+ (#T(regexp$ (":nth-of-type(" \s* an+b \s* ")")
+ (?asign ?a ?bsign ?b))
+ (cons (make-instance 'nth-of-type-selector
+ :asign asign :a a
+ :bsign bsign :b b)
+ (parse-selector &rest)))
+ (#T(regexp$ (":nth-last-of-type(" \s* an+b \s* ")")
+ (?asign ?a ?bsign ?b))
+ (cons (make-instance 'nth-last-of-type-selector
+ :asign asign :a a
+ :bsign bsign :b b)
+ (parse-selector &rest)))
;; absolute (B)
(#T(regexp$ (":nth-child(" \s* b \s* ")")
(?b))
@@ -122,6 +136,14 @@
(?b))
(cons (make-instance 'nth-last-child-selector :a 0 :b b)
(parse-selector &rest)))
+ (#T(regexp$ (":nth-of-type(" \s* b \s* ")")
+ (?b))
+ (cons (make-instance 'nth-of-type-selector :a 0 :b b)
+ (parse-selector &rest)))
+ (#T(regexp$ (":nth-last-of-type(" \s* b \s* ")")
+ (?b))
+ (cons (make-instance 'nth-last-of-type-selector :a 0 :b b)
+ (parse-selector &rest)))
;; named (odd, even)
(#T(regexp$ (":nth-child(" \s* odd/even \s* ")")
(?which))
@@ -131,6 +153,14 @@
(?which))
(cons (make-instance 'nth-last-child-selector :namedp t :b which)
(parse-selector &rest)))
+ (#T(regexp$ (":nth-of-type(" \s* odd/even \s* ")")
+ (?which))
+ (cons (make-instance 'nth-of-type-selector :namedp t :b which)
+ (parse-selector &rest)))
+ (#T(regexp$ (":nth-last-of-type(" \s* odd/even \s* ")")
+ (?which))
+ (cons (make-instance 'nth-last-of-type-selector :namedp t :b which)
+ (parse-selector &rest)))
;; Everybody else
(#T(regexp$ (":first-child") ())
(cons (make-instance 'nth-child-selector :a 0 :b 1)
@@ -142,6 +172,16 @@
(list* (make-instance 'nth-child-selector :a 0 :b 1)
(make-instance 'nth-last-child-selector :a 0 :b 1)
(parse-selector &rest)))
+ (#T(regexp$ (":first-of-type") ())
+ (cons (make-instance 'nth-of-type-selector :a 0 :b 1)
+ (parse-selector &rest)))
+ (#T(regexp$ (":last-of-type") ())
+ (cons (make-instance 'nth-last-of-type-selector :a 0 :b 1)
+ (parse-selector &rest)))
+ (#T(regexp$ (":only-of-type") ())
+ (list* (make-instance 'nth-of-type-selector :a 0 :b 1)
+ (make-instance 'nth-last-of-type-selector :a 0 :b 1)
+ (parse-selector &rest)))
(#T(regexp$ (#\# $name) (?id))
(cons (make-instance 'id-selector :arg id) (parse-selector &rest)))
(#T(regexp$ (#\. $name) (?class))
@@ -191,6 +231,21 @@
(parent (element-parent element)))
(an+b? (car arg) (cdr arg) element (reverse (element-children parent)))))
+(defmethod subject-p ((selector nth-of-type-selector) element)
+ (when-let* ((arg (selector-arg selector))
+ (parent (element-parent element)))
+ (an+b? (car arg) (cdr arg) element
+ (remove-if-not (rcurry #'element-type-equal (element-type element))
+ (element-children parent)))))
+
+(defmethod subject-p ((selector nth-last-of-type-selector) element)
+ (when-let* ((arg (selector-arg selector))
+ (parent (element-parent element)))
+ (an+b? (car arg) (cdr arg) element
+ (reverse
+ (remove-if-not (rcurry #'element-type-equal (element-type element))
+ (element-children parent))))))
+
(defmethod subject-p ((selector class-selector) element)
(member (selector-arg selector)
(element-classes element)
diff -rN -u old-Oh, Ducks!/tests.lisp new-Oh, Ducks!/tests.lisp
--- old-Oh, Ducks!/tests.lisp 2013-07-24 10:34:58.000000000 +0000
+++ new-Oh, Ducks!/tests.lisp 2013-07-24 10:34:58.000000000 +0000
@@ -59,10 +59,17 @@
"<div>I do <i>not</i> <i>like</i> cheese.</div><div><span>I like <i>cheese</i>.</span></div>")
(values div d2))
+(match (#t(html (:model dom)
+ (":nth-last-of-type(2)" . ?first)
+ (":nth-of-type(2)" . ?last))
+ "<div><span>1</span><i>i</i><span>2</span><i>i</i></div>")
+ (values first last))
+
(match (#T(html (:model dom)
- ("i:only-child" . ?i))
+ ("i:only-child" . ?i)
+ ("i:only-of-type" . ?i-type))
"<div>I do <i>not</i> <i>like</i> cheese.</div><div><span>I like <i>cheese</i>.</span></div>")
- (values i))
+ (values i i-type))
;; throws 'unification-failure
(match (#T(html (:model dom)