From e44d0bde9ec81b1227901271257e374c9f3a78cc Mon Sep 17 00:00:00 2001 From: Brit Butler Date: Mon, 22 Sep 2014 14:26:20 -0400 Subject: [PATCH] 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. --- NEWS.md | 9 +++++++-- docs/hacking.md | 2 +- docs/plugin-api.md | 12 +++++------- plugins/analytics.lisp | 3 ++- plugins/disqus.lisp | 6 ++++-- plugins/mathjax.lisp | 7 ++++--- src/themes.lisp | 16 +++++----------- 7 files changed, 28 insertions(+), 27 deletions(-) diff --git a/NEWS.md b/NEWS.md index e66d0b8..cc776ae 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,13 +4,16 @@ instead of the previous symlinked, timestamped deploy strategy. To retain the previous behavior, add `(versioned)` to your config's `: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 templates. All site objects now store their URL in an instance slot. In general, hrefs should be of the form ` ...`. +* **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 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. Thanks to @PuercoPop for the bug report and preliminary fix. * 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. * 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): * A plugin for Incremental builds, cutting runtime for generating diff --git a/docs/hacking.md b/docs/hacking.md index 076fad1..effe1ea 100644 --- a/docs/hacking.md +++ b/docs/hacking.md @@ -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. 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 diff --git a/docs/plugin-api.md b/docs/plugin-api.md index f2108aa..c7979b2 100644 --- a/docs/plugin-api.md +++ b/docs/plugin-api.md @@ -15,14 +15,12 @@ # Extension Points -* **New functionality via JS**, for example the Disqus and Mathjax - plugins. In this case, the plugin's `enable` function should call +* **New functionality via JS**, for example the Disqus and Mathjax plugins. + In this case, the plugin's `enable` function should call [`add-injection`](http://redlinernotes.com/docs/coleslaw.html#add-injection_func) - with an injection and a keyword. The injection itself is a list of - the string to insert and a lambda or function that can be called on - a content instance to determine whether the injection should be - included on the page. The keyword specifies whether the injected - text goes in the HEAD or BODY element. The + with an injection and a keyword. The injection is a function that takes a + *Document* and returns a string to insert in the page or nil. + 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) is a good example of this. diff --git a/plugins/analytics.lisp b/plugins/analytics.lisp index d72e5ec..987b660 100644 --- a/plugins/analytics.lisp +++ b/plugins/analytics.lisp @@ -21,4 +21,5 @@ ") (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))) diff --git a/plugins/disqus.lisp b/plugins/disqus.lisp index 418320e..a2cab65 100644 --- a/plugins/disqus.lisp +++ b/plugins/disqus.lisp @@ -24,5 +24,7 @@ comments powered by Disqus") (defun enable (&key shortname) - (add-injection (list (format nil *disqus-header* shortname) - (lambda (x) (typep x 'post))) :body)) + (flet ((inject-p (x) + (when (typep x 'post) + (format nil *disqus-header* shortname)))) + (add-injection #'inject-p :body))) diff --git a/plugins/mathjax.lisp b/plugins/mathjax.lisp index df6bd80..31e7cc7 100644 --- a/plugins/mathjax.lisp +++ b/plugins/mathjax.lisp @@ -24,6 +24,7 @@ (defun enable (&key force config (preset "TeX-AMS-MML_HTMLorMML") (location "http://cdn.mathjax.org/mathjax/latest/MathJax.js")) - (flet ((plugin-p (x) (or force (mathjax-p x)))) - (let ((mathjax-header (format nil *mathjax-header* config location preset))) - (add-injection (list mathjax-header #'plugin-p) :head)))) + (flet ((inject-p (x) + (when (or force (mathjax-p x)) + (format nil *mathjax-header* config location preset)))) + (add-injection #'inject-p :head))) diff --git a/src/themes.lisp b/src/themes.lisp index 1d7947c..fded3ee 100644 --- a/src/themes.lisp +++ b/src/themes.lisp @@ -4,21 +4,15 @@ "A list that stores pairs of (string . predicate) to inject in the page.") (defun add-injection (injection location) - "Adds an INJECTION to a given LOCATION for rendering. The INJECTION should be -a string which will always be added or a (string . lambda). In the latter case, -the lambda takes a single argument, a content object, i.e. a POST or INDEX, and -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)))) + "Adds an INJECTION to a given LOCATION for rendering. The INJECTION should be a +function that takes a DOCUMENT and returns NIL or a STRING for template insertion." + (push result (getf *injections* location))) (defun find-injections (content) "Iterate over *INJECTIONS* collecting any that should be added to CONTENT." (flet ((injections-for (location) - (loop for (injection predicate) in (getf *injections* location) - when (funcall predicate content) - collect injection))) + (loop for injection in (getf *injections* location) + collecting (funcall injection content)))) (list :head (injections-for :head) :body (injections-for :body))))