Skip to content

Commit

Permalink
Merge pull request #12 from ruricolist/master
Browse files Browse the repository at this point in the history
query1 and :empty pseudo selector
  • Loading branch information
bobbysmith007 committed Aug 4, 2014
2 parents 57500b8 + 172322e commit 713674d
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 29 deletions.
17 changes: 11 additions & 6 deletions README.md
Expand Up @@ -11,14 +11,14 @@ first)
### query

```
(query
(query
(or css-selector-string match-fn)
(or nodes *document*))
```

Similar to jQuery('css-selector', NodeList or *document*)

Returns a list of matching nodes.
Returns a list of matching nodes.

if the first argument is a css-selector string, compile it (as with compile-css-node-matcher)
into a matcher function and call query again with it
Expand All @@ -28,15 +28,20 @@ and to test whether or not that node matches the css-selector match function

If the css-selector-string is constantp, it will be compiled at compile time

The second argument is either a dom-node, a list of dom-nodes or the a dom document.
The second argument is either a dom-node, a list of dom-nodes or the a dom document.
It defaults to buildnode:*document*.

For full examples, please see the test suite, but a basic query call looks like:
```
(css-selectors:query "a" document)
(css-selectors:query "a" document)
```
which will return a list of all "a" tags in the document.

### query1

Exactly the same as `(first (query ...))`, except that it avoids
consing up an intermediate list.

### node-matches?

```
Expand All @@ -58,7 +63,7 @@ If the css-selector-string is constantp, it will be compiled at compile time
```

Parses a css3 selector into an AST representing the selector expression.
Probably only useful for debugging or implementing a different compiler.
Probably only useful for debugging or implementing a different compiler.

Uses clppcre and *VERY* basic flex parser (defined in parse.lisp) to
create a lexer. Combines that lexer with a parser generated by
Expand All @@ -74,7 +79,7 @@ Turns a parse-tree or css-selector-string into a compiled lambda
matcher function this matcher function can be used with query and
node-matches?. The matcher function takes two arguments

### Pseudo Selectors
### Pseudo Selectors

#### Implementing new pseudo selectors

Expand Down
20 changes: 20 additions & 0 deletions src/compile.lisp
Expand Up @@ -190,14 +190,34 @@
(for tree in (alexandria:ensure-list trees))
(appending (%do-query matcher tree)))))

(defun %query1 (inp &optional (trees buildnode:*document*))
(let* ((matcher (compile-css-node-matcher inp)))
;; ensure that queries on a list dont return the items in that list
(iter
(for tree in (alexandria:ensure-list trees))
(thereis (%do-query matcher tree :first? t)))))

(defun query (inp &optional (trees buildnode:*document*))
"Given a css selector, attempt to find the matching nodes in the passed in
dom-trees (defaults to the document)"
(%query inp trees))

(defun query1 (inp &optional (trees buildnode:*document*))
"Given a css selector, attempt to find the first matching node in
the passed in dom-trees (defaults to the document)"
(%query1 inp trees))

(define-compiler-macro query (inp &optional (trees 'buildnode:*document*) &environment e)
`(%query
,(if (constantp inp e)
`(load-time-value (compile-css-node-matcher ,inp))
inp)
,trees))

(define-compiler-macro query1 (inp &optional (trees 'buildnode:*document*)
&environment e)
`(%query1
,(if (constantp inp e)
`(load-time-value (compile-css-node-matcher ,inp))
inp)
,trees))
9 changes: 5 additions & 4 deletions src/packages.lisp
Expand Up @@ -23,14 +23,15 @@
(:nicknames :css)
(:use :cl :iterate)
(:export :query
:node-matches?
:parse-results
:compile-css-node-matcher))
:query1
:node-matches?
:parse-results
:compile-css-node-matcher))


(defpackage :css-selectors.pseudo
(:nicknames :pseudo)
(:shadow :not)
(:use :css :iter :cl)
(:export #:not #:has #:is #:root #:first-child #:last-child
#:only-child #:nth-child #:nth-last-child))
#:only-child #:nth-child #:nth-last-child #:empty))
31 changes: 17 additions & 14 deletions src/pseudo.lisp
Expand Up @@ -32,36 +32,39 @@
;; css uses one based indexes http://www.w3.org/TR/css3-selectors/#nth-child-pseudo
(let ((pos (+ 1 (position node (child-nodes (parent-element node))))))
(eql (if (and mul (not (zerop mul)))
(mod pos mul)
pos)
(if (plusp add)
add
(+ mul add)))))
(mod pos mul)
pos)
(if (plusp add)
add
(+ mul add)))))

(defun pseudo:nth-last-child (node mul add)
;; css uses one based indexes http://www.w3.org/TR/css3-selectors/#nth-child-pseudo
(let* ((kids (child-nodes (parent-element node)))
(pos (- (length kids) (position node kids))))
(pos (- (length kids) (position node kids))))
(eql (if (and mul (not (zerop mul)))
(mod pos mul)
pos)
(if (plusp add)
add
(+ mul add)))))
(mod pos mul)
pos)
(if (plusp add)
add
(+ mul add)))))

(defun pseudo:last-child (node &optional sub-sel-function)
(when sub-sel-function
(error "last-child pseudo selector doesnt support sub-selection arguments"))
(and (parent-element node)
(let ((kids (child-nodes (parent-element node))))
(eql node (elt kids (- (length kids) 1))))))
(eql node (elt kids (- (length kids) 1))))))

(defun pseudo:only-child (node &optional sub-sel-function)
(when sub-sel-function
(error "only-child pseudo selector doesnt support sub-selection arguments"))
(and (parent-node node)
(let ((kids (child-nodes (parent-node node))))
(and (= (length kids) 1)
(and (= (length kids) 1)
(eql node (elt kids 0))))))


(defun pseudo:empty (node &optional sub-sel-function)
(when sub-sel-function
(error "empty pseudo selector doesnt support sub-selection arguments"))
(null (child-nodes node)))
8 changes: 3 additions & 5 deletions src/stp.lisp
Expand Up @@ -37,11 +37,9 @@
node))
elt)
(let ((matches '()))
(stp:filter-recursively
(lambda (node)
(when (and (element-p node) (funcall matcher node))
(push node matches)))
elt)
(stp:do-recursively (node elt)
(when (and (element-p node) (funcall matcher node))
(push node matches)))
(nreverse matches))))

(defmethod %do-query (matcher (elt stp:element) &key (first? nil))
Expand Down

0 comments on commit 713674d

Please sign in to comment.