#+title: Org static blog
#+PROPERTY: header-args :tangle no :comments yes :results silent
* Vars and setup
#+begin_src emacs-lisp
(jao-load-path "org-static-blog")
(when (> emacs-major-version 26) (use-package htmlize :ensure t))
(defvar jao-blog-base-dir "~/doc/jao.io")
(defun jao-blog-dir (p) (expand-file-name p jao-blog-base-dir))
(setq jao-org-blog-tag-files
(seq-difference (directory-files (jao-blog-dir "blog") nil "tag-.*")
"tag-norss.html")
jao-org-blog-tags
(mapcar (lambda (f)
(string-match "tag-\\(.+\\)\\.html" f)
(format "%s"
f (match-string 1 f)))
jao-org-blog-tag-files)
jao-org-blog-tag-rss
(mapcar (lambda (f)
(string-match "\\(.+\\)-rss\\.xml" f)
(format "%s"
f (match-string 1 f)))
(directory-files (jao-blog-dir "blog") nil ".*-rss.xml"))
jao-org-blog-tag-names
(mapcar (lambda (f)
(string-match "tag-\\(.+\\)\\.html" f)
(match-string 1 f))
jao-org-blog-tag-files))
#+end_src
* HTML headers and footers
*** Header
#+begin_src emacs-lisp
(setq org-static-blog-page-header
(concat
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n")
org-static-blog-page-preamble
(concat
"
"))
#+end_src
*** Footer
#+begin_src html :tangle ~/.emacs.d/commons.html :comments no
jao.io by
jao
is licensed under a
Creative Commons Attribution-ShareAlike 3.0 Unported License.
#+end_src
#+begin_src emacs-lisp
(setq org-static-blog-page-postamble
(with-temp-buffer
(insert-file-contents "~/.emacs.d/commons.html")
(buffer-string)))
#+end_src
* Package
#+begin_src emacs-lisp
(use-package org-static-blog
:ensure t
:init
(setq org-static-blog-use-preview nil
org-static-blog-preview-link-p t
org-static-blog-index-length 10
org-static-blog-preview-convert-titles t
org-static-blog-preview-ellipsis "more ..."
org-static-blog-enable-tags t
org-static-blog-tags-file "tags.html"
org-static-blog-rss-file "rss.xml"
org-static-blog-publish-url "https://jao.io/blog/"
org-static-blog-publish-title "programming (and other) musings"
org-static-blog-posts-directory (jao-blog-dir "posts/")
org-static-blog-drafts-directory (jao-blog-dir "drafts/")
org-static-blog-publish-directory (jao-blog-dir "blog/")
org-static-blog-rss-extra "" ; "mail@jao.io\n"
org-static-blog-rss-max-entries 30
org-static-blog-rss-excluded-tag "norss"
org-static-blog-enable-tag-rss t
org-export-with-toc nil
org-export-with-section-numbers nil)
:config
(defun jao-org-static-post-path (pf dt)
(cond ((string-match-p "pages/.*" pf) (file-name-nondirectory pf))
((string-match-p "drafts/.*" pf) pf)
((string-match-p "^[[:digit:]]+-.*" pf) pf)
(t (concat (format-time-string "%Y-%m-%d-" dt)
(file-name-nondirectory pf)))))
(advice-add 'org-static-blog-generate-post-path :override
#'jao-org-static-post-path)
:bind (("H-s-b" . jao-hydra-org-blog/body)
:map org-mode-map (("C-c B" . jao-hydra-org-blog/body))))
#+end_src
* Commands
*** New entries
#+begin_src emacs-lisp
(defun jao-org-blog-publish-file (fname)
(interactive (list (read-file-name "Publish: "
nil
(buffer-file-name)
t
(buffer-file-name))))
(let ((geiser-active-implementations '(guile))
(geiser-default-implementation 'guile))
(org-static-blog-publish-file fname)))
(defun jao-org-static-blog-next-sundry ()
(require 'rst)
(let* ((nos (mapcar (lambda (d)
(string-match ".*-\\([ixvldc]+\\)\\.org" d)
(rst-roman-to-arabic (match-string 1 d)))
(directory-files org-static-blog-posts-directory
nil
"in-no-particular-order")))
(n (rst-arabic-to-roman (+ 1 (car (sort nos #'>))))))
(format "in no particular order %s" (downcase n))))
(defun jao-org-static-blog-create-new-post (&optional draft)
(interactive)
(let* ((kind (completing-read "Kind: " '(regular book sundry)))
(title (if (string= "sundry" kind)
(jao-org-static-blog-next-sundry)
(read-string "Title: ")))
(file (replace-regexp-in-string "\s" "-" (downcase title))))
(find-file (expand-file-name (concat file ".org")
(if draft
org-static-blog-drafts-directory
org-static-blog-posts-directory)))
(insert "#+title: " title "\n"
"#+date: " (format-time-string "<%Y-%m-%d %H:%M>") "\n"
"#+filetags: ")
(cond ((string= "book" kind)
(insert "books\n\n[[https://jao.io/img/" file ".jpg]]\n\n"))
((string= "sundry" kind)
(insert "sundry\n\nInteresting bits elsewhere:\n\n- "))
(t (insert (completing-read "Tag: " jao-org-blog-tag-names)
"\n\n")))))
#+end_src
*** Drafts
#+begin_src emacs-lisp
(defun jao-org-static-blog-create-new-draft ()
(interactive)
(jao-org-static-blog-create-new-post t))
(defun jao-org-static-blog-publish-draft ()
(interactive)
(let* ((from (read-file-name "Post: "
org-static-blog-drafts-directory
nil t))
(to (expand-file-name (file-name-nondirectory from)
org-static-blog-posts-directory)))
(rename-file from to)
(when-let ((b (get-buffer from)))
(kill-buffer b))
(find-file to)
(when (y-or-n-p "Update date? ")
(goto-char (point-min))
(when (re-search-forward "^#\\+date: " nil t)
(let ((kill-whole-line nil)) (kill-line))
(insert (format-time-string "<%Y-%m-%d %H:%M>"))
(save-buffer)))
(when (y-or-n-p "Generate HTML? ")
(jao-org-blog-publish))))
(defun jao-org-static-blog-edit-draft ()
(interactive)
(find-file (read-file-name "Edit: "
org-static-blog-drafts-directory
nil
t)))
#+end_src
*** Publish
#+begin_src emacs-lisp
(defun jao-org-blog-publish (&optional force)
(interactive "P")
(let ((geiser-active-implementations '(guile))
(geiser-default-implementation 'guile))
(org-static-blog-publish force)))
(defun jao-org-blog-republish ()
(interactive)
(jao-org-blog-publish t))
#+end_src
* Hydras
#+begin_src emacs-lisp
(pretty-hydra-define jao-hydra-org-blog (:color blue :quit-key "q")
("Edit"
(("n" jao-org-static-blog-create-new-post "create post")
("d" jao-org-static-blog-create-new-draft "create draft")
("e" jao-org-static-blog-edit-draft "edit draft"))
"Publish"
(("D" jao-org-static-blog-publish-draft "publish draft")
("f" jao-org-blog-publish-file "publish single file")
("p" jao-org-blog-publish "publish all")
("r" jao-org-blog-republish "republish"))))
(major-mode-hydra-define+ org-mode nil
("Utilities" (("b" jao-hydra-org-blog/body "Blog ops"))))
#+end_src