Make add-injection support more complex injections. Thanks @PuercoPop.

In short, an injection is now a FUNCTION that takes a
document and returns either a STRING to insert in the
page (possibly with data from the document) or NIL.
This commit is contained in:
Brit Butler 2014-09-22 14:26:20 -04:00
parent f474db77b2
commit e44d0bde9e
7 changed files with 28 additions and 27 deletions

View file

@ -4,13 +4,16 @@
instead of the previous symlinked, timestamped deploy strategy. instead of the previous symlinked, timestamped deploy strategy.
To retain the previous behavior, add `(versioned)` to your config's To retain the previous behavior, add `(versioned)` to your config's
`:plugins` list. `:plugins` list.
* **SITE-BREAKING CHANGE**: Custom themes will be broken by a change * **Incompatible Change**: Custom themes will be broken by a change
to URL handling. Previously, we were hand-constructing URLs in the to URL handling. Previously, we were hand-constructing URLs in the
templates. All site objects now store their URL in an instance slot. templates. All site objects now store their URL in an instance slot.
In general, hrefs should be of the form `<a href="{$config.domain}/{$obj.url}"> ...</a>`. In general, hrefs should be of the form `<a href="{$config.domain}/{$obj.url}"> ...</a>`.
* **Incompatible Change**: The interface of the `add-injection` function
has changed. If you have written a plugin which uses `add-injection`
you should update it to conform to the [new interface][add-inj-new].
* **Docs**: Improved README and Theming docs. New Config File docs.
* Changes to `:routing` would previously break links in the templates * Changes to `:routing` would previously break links in the templates
but now work seamlessly due to the updated URL handling. but now work seamlessly due to the updated URL handling.
* **Docs**: Improved README and Theming docs. New Config File docs.
* Loading content is more robust when empty lines or metadata are passed. * Loading content is more robust when empty lines or metadata are passed.
Thanks to @PuercoPop for the bug report and preliminary fix. Thanks to @PuercoPop for the bug report and preliminary fix.
* The config `:repo` option is now deprecated as its value has become * The config `:repo` option is now deprecated as its value has become
@ -21,6 +24,8 @@
* The templates are now HTML5 valid thanks to @Ferada. * The templates are now HTML5 valid thanks to @Ferada.
* Fixed a bug where RSS/Atom tag feeds were being published multiple times. * Fixed a bug where RSS/Atom tag feeds were being published multiple times.
[add-inj-new]: https://github.com/redline6561/coleslaw/blob/master/docs/plugin-api.md#extension-points
## Changes for 0.9.5 (2014-06-13): ## Changes for 0.9.5 (2014-06-13):
* A plugin for Incremental builds, cutting runtime for generating * A plugin for Incremental builds, cutting runtime for generating

View file

@ -213,7 +213,7 @@ order. Feeds exist to special case RSS and ATOM generation.
Currently, there is only 1 content type: POST, for blog entries. Currently, there is only 1 content type: POST, for blog entries.
PAGE, a content type for static page support, is available as a plugin. PAGE, a content type for static page support, is available as a plugin.
## Areas for Improvement ## Areas for Improvement (i.e. The Roadmap)
### TODO for 0.9.6 ### TODO for 0.9.6

View file

@ -15,14 +15,12 @@
# Extension Points # Extension Points
* **New functionality via JS**, for example the Disqus and Mathjax * **New functionality via JS**, for example the Disqus and Mathjax plugins.
plugins. In this case, the plugin's `enable` function should call In this case, the plugin's `enable` function should call
[`add-injection`](http://redlinernotes.com/docs/coleslaw.html#add-injection_func) [`add-injection`](http://redlinernotes.com/docs/coleslaw.html#add-injection_func)
with an injection and a keyword. The injection itself is a list of with an injection and a keyword. The injection is a function that takes a
the string to insert and a lambda or function that can be called on *Document* and returns a string to insert in the page or nil.
a content instance to determine whether the injection should be The keyword specifies whether the injected text goes in the HEAD or BODY element. The
included on the page. The keyword specifies whether the injected
text goes in the HEAD or BODY element. The
[Disqus plugin](http://github.com/redline6561/coleslaw/blob/master/plugins/disqus.lisp) [Disqus plugin](http://github.com/redline6561/coleslaw/blob/master/plugins/disqus.lisp)
is a good example of this. is a good example of this.

View file

@ -21,4 +21,5 @@
</script>") </script>")
(defun enable (&key tracking-code) (defun enable (&key tracking-code)
(add-injection (format nil *analytics-js* tracking-code) :head)) (let ((snippet (format nil *analytics-js* tracking-code)))
(add-injection (constantly snippet) :head)))

View file

@ -24,5 +24,7 @@
<a href=\"http://disqus.com\" class=\"dsq-brlink\">comments powered by <span class=\"logo-disqus\">Disqus</span></a>") <a href=\"http://disqus.com\" class=\"dsq-brlink\">comments powered by <span class=\"logo-disqus\">Disqus</span></a>")
(defun enable (&key shortname) (defun enable (&key shortname)
(add-injection (list (format nil *disqus-header* shortname) (flet ((inject-p (x)
(lambda (x) (typep x 'post))) :body)) (when (typep x 'post)
(format nil *disqus-header* shortname))))
(add-injection #'inject-p :body)))

View file

@ -24,6 +24,7 @@
(defun enable (&key force config (preset "TeX-AMS-MML_HTMLorMML") (defun enable (&key force config (preset "TeX-AMS-MML_HTMLorMML")
(location "http://cdn.mathjax.org/mathjax/latest/MathJax.js")) (location "http://cdn.mathjax.org/mathjax/latest/MathJax.js"))
(flet ((plugin-p (x) (or force (mathjax-p x)))) (flet ((inject-p (x)
(let ((mathjax-header (format nil *mathjax-header* config location preset))) (when (or force (mathjax-p x))
(add-injection (list mathjax-header #'plugin-p) :head)))) (format nil *mathjax-header* config location preset))))
(add-injection #'inject-p :head)))

View file

@ -4,21 +4,15 @@
"A list that stores pairs of (string . predicate) to inject in the page.") "A list that stores pairs of (string . predicate) to inject in the page.")
(defun add-injection (injection location) (defun add-injection (injection location)
"Adds an INJECTION to a given LOCATION for rendering. The INJECTION should be "Adds an INJECTION to a given LOCATION for rendering. The INJECTION should be a
a string which will always be added or a (string . lambda). In the latter case, function that takes a DOCUMENT and returns NIL or a STRING for template insertion."
the lambda takes a single argument, a content object, i.e. a POST or INDEX, and (push result (getf *injections* location)))
any return value other than nil indicates the injection should be added."
(let ((result (etypecase injection
(string (list injection #'identity))
(list injection))))
(push result (getf *injections* location))))
(defun find-injections (content) (defun find-injections (content)
"Iterate over *INJECTIONS* collecting any that should be added to CONTENT." "Iterate over *INJECTIONS* collecting any that should be added to CONTENT."
(flet ((injections-for (location) (flet ((injections-for (location)
(loop for (injection predicate) in (getf *injections* location) (loop for injection in (getf *injections* location)
when (funcall predicate content) collecting (funcall injection content))))
collect injection)))
(list :head (injections-for :head) (list :head (injections-for :head)
:body (injections-for :body)))) :body (injections-for :body))))