Clss
Author: Nicolas Hafner <shinmera@tymoon.eu>
Description: A DOM tree searching engine based on CSS selectors.

## About CLSS

CLSS is a DOM traversal engine based on CSS selectors. It makes use of the Plump-DOM and is used by lQuery.

## How To

Load CLSS through Quicklisp or ASDF:

    (ql:quickload :clss)

Using a standard CSS selector you can retrieve a vector of nodes from the DOM:

    (clss:select "img" (plump:parse "<div><p>A beautiful image: <img src="//example.com/image.png" alt="image" /></p></div>"))

CLSS implements Level 3 selectors and offers most of the features from the spec. Some things were left out as they make no sense outside a CSS context. As Plump supports XML as well as HTML, it also includes special handling for a few nodes that are not elements and are thus not reachable by standard CSS selectors. In order to solve this problem, CLSS adds an extra operator, the `^` caret. The caret is followed by a Plump-DOM class-name and will then match any elements that conform to a `typep` test against it.

    (clss:select "^CDATA" (plump:parse "<foo><![CDATA[bar]]></foo>"))

CSS selectors in themselves also don't support XML namespaces due to the ambiguity arising with pseudo-selectors. CLSS solves this by interpreting a double colon as a name. Thus, a tag with the name of `foo:bar` is selected by `foo::bar`.

CLSS attempts to be a fast engine and various parts of it have been tuned for this purpose, which limits the extensibility of CLSS a bit. However, it is still possible to f.e. programmatically construct a selector.

## Extending CLSS

Using `define-pseudo-selector` you can add your own extensions to CLSS:

    (clss:define-pseudo-selector outside-link (node)
      (let ((href (plump:attribute node "href")))
        (and href (cl-ppcre:scan "^(http|https)://" href))))

    (clss:select "a:outside-link" (plump:parse "<foo><a href=\"/baloney\"/><a href=\"http://example.com\"/></foo>"))

## Copyright

clss is licensed under the Artistic license. © Nicolas Hafner <shinmera@tymoon.eu> .

## Package Index

- ### CLSS (ORG.SHIRAKUMO.CLSS)

  - condition

    #### `PSEUDO-SELECTOR-NOT-AVAILABLE`

        Condition signalled when a pseudo selector is defined according to spec,
        but makes no sense in the context of CLSS and has thus been left
        unimplemented.

  - condition

    #### `SELECTOR-MALFORMED`

        Signalled when a selector or matcher has been found to be malformed.
        This really shouldn't happen unless you're passing raw lists
        for the selector to the matcher.

  - condition

    #### `UNDEFINED-PSEUDO-SELECTOR`

        Condition signalled when trying to use a pseudo selector that has not
        been defined. This is signalled at match-time, rather than at
        selector-compile-time.

  - accessor `(`

    #### `NAME`

    `` `CONDITION``)`
    No docstring provided.
  - accessor `(`

    #### `PSEUDO-SELECTOR`

    `` `NAME``)`

        Returns the pseudo-selector function associated with NAME, if any.

  - accessor `(`

    #### `SELECTOR`

    `` `CONDITION``)`
    No docstring provided.
  - function `(`

    #### `MAKE-ANY-CONSTRAINT`

    `` ```)`
    No docstring provided.
  - function `(`

    #### `MAKE-ATTRIBUTE-CONSTRAINT`

    `` `ATTRIBUTE &OPTIONAL VALUE (COMPARATOR :=)``)`
    No docstring provided.
  - function `(`

    #### `MAKE-CLASS-CONSTRAINT`

    `` `CLASS``)`
    No docstring provided.
  - function `(`

    #### `MAKE-CLSS-MATCHER`

    `` `&REST CONSTRAINTS``)`
    No docstring provided.
  - function `(`

    #### `MAKE-ID-CONSTRAINT`

    `` `ID``)`
    No docstring provided.
  - function `(`

    #### `MAKE-PSEUDO-CONSTRAINT`

    `` `FUNCTION &REST ARGS``)`
    No docstring provided.
  - function `(`

    #### `MAKE-SELECTOR`

    `` `&REST GROUPS``)`
    No docstring provided.
  - function `(`

    #### `MAKE-TAG-CONSTRAINT`

    `` `TAG``)`
    No docstring provided.
  - function `(`

    #### `MAKE-TYPE-CONSTRAINT`

    `` `NAME``)`
    No docstring provided.
  - function `(`

    #### `MATCH-CONSTRAINT`

    `` `CONSTRAINT NODE``)`

        Attempts to match the CONSTRAINT form against the node.
        Returns NIL if it fails to do so, unspecified otherwise.

  - function `(`

    #### `MATCH-GROUP`

    `` `GROUP ROOT-NODE &OPTIONAL (SEARCH-TYPE :DEPTH-FIRST)``)`

        Match a matcher group against the root-node and possibly all its children.
        Returns an array of mached nodes.

  - function `(`

    #### `MATCH-GROUP-BACKWARDS`

    `` `GROUP NODE``)`
    No docstring provided.
  - function `(`

    #### `MATCH-MATCHER`

    `` `MATCHER NODE``)`

        Attempts to match a matcher against a node.
        Returns T if all constraints match, NIL otherwise.

  - function `(`

    #### `MATCH-SELECTOR`

    `` `SELECTOR ROOT-NODE SEARCH-TYPE``)`

        Match a selector against the root-node and possibly all its children.
        Returns an array of matched nodes.

  - function `(`

    #### `NODE-MATCHES-P`

    `` `SELECTOR NODE``)`

        Tests whether the node matches the selector.

        SELECTOR --- A CSS-selector string or a compiled selector list.
        NODE     --- The node to test.

  - function `(`

    #### `PARSE-SELECTOR`

    `` `STRING``)`

        Parse a selector string into its "compiled" list form.

  - function `(`

    #### `REMOVE-PSEUDO-SELECTOR`

    `` `NAME``)`

        Removes the pseudo-selector associated with NAME.

  - function `(`

    #### `SELECT`

    `` `SELECTOR ROOT-NODE &OPTIONAL (SEARCH-TYPE :DEPTH-FIRST)``)`

        Match the given selector against the root-node and possibly all its children.
        Returns an array of matched nodes.

        SELECTOR    --- A CSS-selector string or a compiled selector list.
        ROOT-NODE   --- A single node, list or vector of nodes to start matching from.
        SEARCH-TYPE --- Select the search algorithm, options are ":depth-first" and ":breadth-first".

  - macro `(`

    #### `DEFINE-PSEUDO-SELECTOR`

    `` `NAME (NODENAME &REST ARGS-LAMBDA) &BODY BODY``)`

        Define a new pseudo-selector of NAME.

        NAME        --- A symbol or string naming the selector (case insensitive always).
        NODENAME    --- A variable symbol the matched node is bound to.
        ARGS-LAMBDA --- A lambda-list of the expected arguments for the pseudo-selector.
                        Note that keyword arguments make no sense in this context.
        BODY        ::= form*