What is lQuery?

lQuery is a DOM manipulation library written in Common Lisp, inspired by and based on the jQuery syntax and functions. It uses Closure-XML and CSS-Selectors in the background to achieve its work. Its main idea is to replace HTML templating systems and allow generated HTML for websites while relying on pure HTML files. This achieves a much cleaner separation of static and dynamic page parts.

How To

Load lQuery with ASDF or Quicklisp.

(ql:quickload :lquery)

First, lQuery needs to be initialized with a document to work on:

($ (initialize #p"/path/to/input.html"))

After that, you can use the $ function to select and manipulate the DOM:

($ "article")
($ "article" (add-class "fancy") (attr :foo "bar"))

To render the HTML to a string use serialize. If you want to save it to a file directly, there's also write-to-file.

($ (serialize))
($ (write-to-file #p"/path/to/output.html"))

So a quick file manipulation could look something like this:

($ (initialize #p"/path/to/input.html") "article" (append-to "content") (add-class "foo") (write-to-file #p"/path/to/output.html"))

Aside from using selectors as the first step, it's also possible to use any other variable or list and operate on it. Since 2.0: Literal function calls need to be added with (inline). Note that the result of the inline function will be used as if literally put in place. For example, an inlined function that evaluates to a string will result in a CSS-select.

($ (inline (list node-a node-b)) "article" (serialize))

Selectors can come at any point in the sequence of lQuery operations and will always act on the current set of elements. If an operation evaluates to a list or a single node, the current set of elements is set to this result.

($ "a" (text "Link") ($ "p") (text "Paragraph"))

This is equivalent to the following:

($ "a" (text "Link"))
($ "p" (text "Paragraph"))

While this sort of chaining is possible, it is discouraged and multiple statements should be used instead to ensure proper readability.

Functions in the argument list will be translated to a function invocation with the current list of elements as their argument.

($ "a" #'(lambda (els) (first els)))

lQuerySince 2.0 also supports compile-time evaluation of forms, whose results are then put in place of their function calls:

($ (eval (format NIL "~a" *selector*)))

Keep in mind that the lexical environment is not the same at compile-time as at run-time.

Extending lQuery For 2.0

lQuery allows extension in a couple of ways. The most important of which are node operations themselves, which come in two flavours: node-funs and node-list-funs. Any node operation resides in the package :lquery-funcs, which is automatically scanned by the $ macro. The two macros responsible for defining new node functions automatically place the resulting operations in this package for you.

(define-node-function name (node-name &rest arguments) &optional docstring &body body)
(define-node-list-function name (list-name &rest arguments) &optional docstring &body body)

Any function generated by these macros can be called either with a single node or a list of nodes. In the case of a regular node operation, if it receives a list of nodes, the function is called once for each node and the results are collected into a list, which is then returned. If it receives a single node, only a single result is returned. In the case of a node list function, the return value can be either a list or a single value, depending on what the goal of the operation is.

The $ macro itself can be extended as well by providing additional argument- or symbol-handlers. The following two macros make this possible:

(define-argument-handler type (argsname nodesname) &body body)

Argument handlers transform the arguments at compile-time. For example, this would allow an extension to turn literal arrays into lists so they can be processed as well.

(define-symbol-handler type (symbolname nodesname) &body body)

Symbol handlers on the other hand determine the action at run-time. This is mostly useful for defining special actions on certain variable values.

Other Guff

lQuery is a sub-project of TyNETv5 ("Radiance"), licensed under the Artistic License 2.0 and ©2013 TymoonNET/NexT, Nicolas Hafner.
This library can be obtained via git on git://git.tymoon.eu/lquery.git. For questions, patches or suggestions, please contact me via email.

lQuery Package Function Index

lQuery-Funcs Package Function Index