miniblog

Miniblog: A command-line static blog system in Common Lisp
Log | Files | Refs | README | LICENSE

commit 534e01650d00df913e665e4f3a881286de93007f
parent efc058474dd7c7fa7e9d9e5a85a1f1962d40d650
Author: Decay <decay@todayiwilllaunchmyinfantsonintoorbit.com>
Date:   Sat,  2 Nov 2024 16:41:29 -0700

Add a bunch of extension blocks to the default templates

Each post and page has the following new blocks:

- title, which contains the title
- article, which contains the full text of the page or post
- footer, which has the creation and modification dates

For posts, the same blocks exist with suffixes -collapsed and -expanded,
so that posts hidden behind a read-more can be customized separately
from fully-expanded posts (ie, the front page or archive pages vs a
single post page). Posts also have an additional block:

- post, wrapping the entire post content

An unfortunate limitation of Djula: {{ super }} won't work with these
new blocks (for posts) because there's multiple occurrences in a post
list with the result that the blocks can be extended, but attempting to
call super blows up.

Diffstat:
Msrc/data.lisp | 8++++----
Msrc/db.lisp | 12+++++++++---
Mtemplates/page.dtl | 8+++++++-
Mtemplates/posts.dtl | 63+++++++++++++++++++++++++++++++++++++++++++--------------------
4 files changed, 63 insertions(+), 28 deletions(-)

diff --git a/src/data.lisp b/src/data.lisp @@ -50,8 +50,8 @@ :created-by (page-username entry) :last-updated-by (page-last-updated-by entry)))) -(defun add-entry (title content &key rendered-content (username "nobody") draftp) - (miniblog.db:add-entry title content :rendered-content rendered-content :draftp draftp :username username :transform #'xform)) +(defun add-entry (title content &key parent rendered-content (username "nobody") draftp) + (miniblog.db:add-entry title content :parent parent :rendered-content rendered-content :draftp draftp :username username :transform #'xform)) (defun make-entry-tree (id subtree) (let ((dict (make-hash-table))) @@ -103,11 +103,11 @@ range or count" (make-entry-tree 0 (miniblog.db:get-entries :year year :month month :drafts include-drafts-p :max-entries max-entries :transform #'xform))) -(defun update-entry (id title content &key rendered-content (username "nobody") draftp reset-timestamp-p) +(defun update-entry (id title content &key rendered-content parent (username "nobody") created-by draftp reset-timestamp-p) "Update entry by id. Returns the updated entry or nil if the id doesn't exist." (miniblog.db:update-entry id title content :rendered-content rendered-content :draftp draftp :reset-timestamp-p reset-timestamp-p - :username username :transform #'xform)) + :parent parent :created-by created-by :username username :transform #'xform)) (defun update-entry-rendered-content (id rendered-content &key (username "nobody")) "Updated entry RENDERED-CONTENT by ID. Returns the updated page or NIL if ID doesn't exist." diff --git a/src/db.lisp b/src/db.lisp @@ -57,9 +57,10 @@ t 'nil)) -(defun add-entry (title content &key rendered-content (username "nobody") (transform #'identity) draftp) +(defun add-entry (title content &key rendered-content (username "nobody") parent (transform #'identity) draftp) "Add a new blog entry to the database" (funcall transform (create-dao 'blog-entries + :parent parent :title title :content content :rendered-content rendered-content @@ -110,7 +111,9 @@ ((eql :drafts-only) '((:= :draftp "true"))) (null '((:= :draftp "false")))))) (if (or date-clauses drafts-clause) - (where `(:and ,@date-clauses ,@drafts-clause (:or (:is-null :parent) (:= :parent 0)))))))) + (where `(:and ,@date-clauses ,@drafts-clause + ,@(when (not (eql drafts :drafts-only)) + '((:or (:is-null :parent) (:= :parent 0)))))))))) (let ((entries (select-dao 'blog-entries (where-clause year month) @@ -139,7 +142,7 @@ (mapcar transform subentries) subentries)))) -(defun update-entry (id title content &key rendered-content (username "nobody") (transform #'identity) draftp reset-timestamp-p) +(defun update-entry (id title content &key rendered-content parent (username "nobody") created-by (transform #'identity) draftp reset-timestamp-p) "Update entry by id. Returns the updated entry or nil if the id doesn't exist." (let ((entry (get-raw-entry id))) (if entry @@ -147,7 +150,10 @@ (progn (setf (entry-title entry) title) (setf (entry-content entry) content) (setf (entry-rendered-content entry) rendered-content) + (setf (entry-parent entry) parent) (setf (entry-last-updated-by entry) username) + (when created-by + (setf (entry-username entry) created-by)) (setf (entry-draftp entry) (as-sql-bool draftp)) (when reset-timestamp-p (setf (mito.dao.mixin:object-created-at entry) (local-time:now))) ; FIXME: This is a horrible abuse of Mito diff --git a/templates/page.dtl b/templates/page.dtl @@ -12,8 +12,13 @@ {% endblock %} {% block main %} {% if page.rendered-content %} - <h2>{{ page.title }}</h2> + {% block title %} + <h2>{{ page.title }}</h2> + {% endblock %} + {% block article %} <article>{{ page.rendered-content|safe }}</article> + {% endblock %} + {% block footer %} <p role="note"> <small> Posted by {{ page.created-by }} on {{ page.created-at-long }} @@ -23,6 +28,7 @@ {% endifnotequal %} </small> </p> + {% endblock %} {% else %} No page found. {% endif %} diff --git a/templates/posts.dtl b/templates/posts.dtl @@ -21,27 +21,50 @@ <hr> {% endif %} {% ifchanged post.created-at-short %} - <h1>{{ post.created-at-short }}</h1> + <h1>{{ post.created-at-short }}</h1> {% endifchanged %} - <a name="{{ post.id }}"></a> - {% if collapse-posts-p %} - <h2><a href="{{ post.link }}">{{ post.title }}</a></h2> - <article> - {{ post.rendered-content|safe|read-more:post.link }} - </article> - {% else %} - <h2>{{ post.title }}</h2> - <article>{{ post.rendered-content|safe }}</article> - {% endif %} - <p role="note"> - <small> - Posted by {{ post.created-by }} on {{ post.created-at-long }} - {% ifnotequal post.created-at-long post.last-updated-at-long %} - <br> - Last updated by {{ post.last-updated-by }} on {{ post.last-updated-at-long }} - {% endifnotequal %} - </small> - </p> + {% block post %} + <a name="{{ post.id }}"></a> + {% if collapse-posts-p %} + {% block title-collapsed %} + <h2><a href="{{ post.link }}">{{ post.title }}</a></h2> + {% endblock %} + {% block article-collapsed %} + <article> + {{ post.rendered-content|safe|read-more:post.link }} + </article> + {% endblock %} + {% block footer-collapsed %} + <p role="note"> + <small> + Posted by {{ post.created-by }} on {{ post.created-at-long }} + {% ifnotequal post.created-at-long post.last-updated-at-long %} + <br> + Last updated by {{ post.last-updated-by }} on {{ post.last-updated-at-long }} + {% endifnotequal %} + </small> + </p> + {% endblock %} + {% else %} + {% block title-expanded %} + <h2>{{ post.title }}</h2> + {% endblock %} + {% block article-expanded %} + <article>{{ post.rendered-content|safe }}</article> + {% endblock %} + {% block footer-expanded %} + <p role="note"> + <small> + Posted by {{ post.created-by }} on {{ post.created-at-long }} + {% ifnotequal post.created-at-long post.last-updated-at-long %} + <br> + Last updated by {{ post.last-updated-by }} on {{ post.last-updated-at-long }} + {% endifnotequal %} + </small> + </p> + {% endblock %} + {% endif %} + {% endblock %} {% endfor %} {% else %} No posts found.