author | Alan Dipert
<alan@dipert.org> 2019-11-15 03:35:33 UTC |
committer | Alan Dipert
<alan@dipert.org> 2019-11-15 03:35:33 UTC |
parent | 8fa01282c69b259d715d510235c928a5d7e99db1 |
Makefile | +2 | -2 |
scripts/gen.el | +42 | -44 |
templates/listing.html | +5 | -0 |
diff --git a/Makefile b/Makefile index 339b2b5..e93139e 100644 --- a/Makefile +++ b/Makefile @@ -21,8 +21,8 @@ all: public atom.xml: $(POSTS_MD) scripts/gen.el $(GEN) atom "posts" $(TITLE) $(AUTHOR) $(BLOG_URL) $(FEED_ID) $(POST_BASE_URL) > $@ -index.html: templates/index.html $(POSTS_HTML) scripts/gen.el - $(GEN) index "posts" $< > $@ +index.html: templates/index.html templates/listing.html $(POSTS_HTML) scripts/gen.el + $(GEN) index "posts" templates/index.html templates/listing.html > $@ %.html: %.md templates/article.html scripts/gen.el $(GEN) post $< > $@ diff --git a/scripts/gen.el b/scripts/gen.el index 58eea9c..be82b3b 100755 --- a/scripts/gen.el +++ b/scripts/gen.el @@ -3,7 +3,6 @@ (setq debug-on-error t dired-use-ls-dired nil) -(require 'avl-tree) (require 'cl-lib) (require 'json) (require 'parse-time) @@ -75,45 +74,37 @@ returns the result of body." "-V" (format "reading-time='%s'" (reading-time file)) file))) -(cl-defun post-before? (x y) - "True when post x has an 'internal time' time property that -precedes that of post y." - (apply #'time-less-p (mapcar (apply-partially #'alist-get 'time) (list x y)))) - (cl-defun replace-extension (filename new-ext) "Replaces the extension of filename with new-ext." (concat (file-name-sans-extension filename) "." new-ext)) -(cl-defun complement (func) - "Returns the complement of predicate func." - (lambda (&rest args) - (not (apply func args)))) - -(cl-defun sorted-posts (posts-dir compare-func &aux (avl-tree (avl-tree-create compare-func))) - "Provided a directory of posts and a function to compare them -by, returns an avl tree of the posts sorted by compare-func. -Posts are alists various properties given by the path to -posts-dir and the metadata in the posts." - (dolist (post (directory-files posts-dir nil "\\.md$" t) avl-tree) - (let* ((md-path (concat (file-name-as-directory posts-dir) post)) - (meta (json-read-from-string (blog-command-meta-json md-path))) - (time (parse-iso-date (alist-get 'date meta)))) - (avl-tree-enter avl-tree - `((path . ,(replace-extension md-path "html")) - (title . ,(alist-get 'title meta)) - (iso-date . ,(format-time-string "%FT%TZ" time)) - (id . ,(alist-get 'id meta)) - (abstract . ,(alist-get 'abstract meta)) - (short-iso-date . ,(format-time-string "%F" time)) - (time . ,time)))))) +(cl-defun posts (posts-dir) + "Returns a list of alists of post metadata, in chronological order." + (cl-sortn + (mapcar (lambda (post) + (let* ((md-path (concat (file-name-as-directory posts-dir) post)) + (meta (json-read-from-string (blog-command-meta-json md-path))) + (time (parse-iso-date (alist-get 'date meta)))) + `((path . ,(replace-extension md-path "html")) + (title . ,(alist-get 'title meta)) + (iso-date . ,(format-time-string "%FT%TZ" time)) + (id . ,(alist-get 'id meta)) + (abstract . ,(alist-get 'abstract meta)) + (short-iso-date . ,(format-time-string "%F" time)) + (time . ,time)))) + (directory-files posts-dir nil "\\.md$" t)) + #'time-less-p + :key (apply-partially #'alist-get 'time))) (cl-defun render-attrs (attrs) + "Renders a particular node's attribute list." (mapconcat (lambda (pair) (format "%s=\"%s\"" (car pair) (cdr pair))) attrs " ")) (cl-defun render-html (dom) + "Returns a string of HTML/XML markup provided a tree." (if (stringp dom) dom (cl-destructuring-bind (tag attrs &rest kids) dom @@ -125,24 +116,31 @@ posts-dir and the metadata in the posts." (mapconcat #'render-html kids "") tag))))) -(cl-defun index-post-entry (post) - `(li nil - (time ((datetime . ,(alist-get 'iso-date post))) - ,(alist-get 'short-iso-date post)) - " " - (a ((href . ,(alist-get 'path post))) - ,(alist-get 'title post)))) - -(cl-defun blog-command-index (posts-dir template-file) +(cl-defun fill-template (template-file alist) + "Given a template file and an alist of substitutions to +perform, substitute every occurrence of a template variable with +its value. Template variables are post metadata keys wrapped with +dollar signs, like $this$." + (with-temp-buffer + (insert-file-contents-literally template-file) + (dolist (pair alist) + (cl-destructuring-bind (varname . val) pair + (let ((to-find (concat "\\$" (symbol-name varname) "\\$"))) + (goto-char (point-min)) + (while (re-search-forward to-find nil t) + (replace-match val))))) + (buffer-string))) + +(cl-defun blog-command-index (posts-dir template-index template-listing) "Generates the blog index page." - (let* ((posts (avl-tree-mapcar - #'index-post-entry - (sorted-posts posts-dir (complement #'post-before?))))) + (let* ((posts (mapcar + (apply-partially #'fill-template template-listing) + (reverse (posts posts-dir))))) (with-temp-buffer - (insert-file-contents-literally template-file) + (insert-file-contents-literally template-index) (unless (re-search-forward "\\$posts\\$" nil t) (error "Couldn't find $posts$ variable in index template.")) - (replace-match (mapconcat #'render-html posts "")) + (replace-match (apply #'concat posts)) (buffer-string)))) (cl-defun blog-command-atom @@ -154,7 +152,7 @@ posts-dir and the metadata in the posts." entry-baseurl) "Generates the Atom feed." (let* ((feed-updated (format-time-string "%FT%TZ" nil t)) - (entries (avl-tree-mapcar + (entries (mapcar (lambda (entry) `(entry () (title () ,(alist-get 'title entry)) @@ -162,7 +160,7 @@ posts-dir and the metadata in the posts." (id () ,(alist-get 'id entry)) (updated () ,(alist-get 'iso-date entry)) (summary () ,(alist-get 'abstract entry)))) - (sorted-posts posts-dir #'post-before?)))) + (posts posts-dir)))) (concat "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" (render-html `(feed ((xmlns . "http://www.w3.org/2005/Atom")) diff --git a/templates/listing.html b/templates/listing.html new file mode 100644 index 0000000..3a6df8e --- /dev/null +++ b/templates/listing.html @@ -0,0 +1,5 @@ +<li> + <time datetime="$iso-date">$short-iso-date$</time> + + <a href="$path$">$title$</a> +</li>