jao-custom-blog.el 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. ;; -*- lexical-binding: t -*-
  2. ;;; Vars and setup
  3. (jao-load-path "org-static-blog")
  4. (when (> emacs-major-version 26) (use-package htmlize :ensure t))
  5. (defvar jao-blog-base-dir "~/doc/jao.io")
  6. (defun jao-blog-dir (p) (expand-file-name p jao-blog-base-dir))
  7. (setq jao-org-blog-tag-files
  8. (seq-difference (directory-files (jao-blog-dir "blog") nil "tag-.*")
  9. "tag-norss.html")
  10. jao-org-blog-tags
  11. (mapcar (lambda (f)
  12. (string-match "tag-\\(.+\\)\\.html" f)
  13. (format "<a href=\"/blog/%s\">%s</a>"
  14. f (match-string 1 f)))
  15. jao-org-blog-tag-files)
  16. jao-org-blog-tag-rss
  17. (mapcar (lambda (f)
  18. (string-match "\\(.+\\)-rss\\.xml" f)
  19. (format "<a href=\"/blog/%s\">%s</a>"
  20. f (match-string 1 f)))
  21. (directory-files (jao-blog-dir "blog") nil ".*-rss.xml"))
  22. jao-org-blog-tag-names
  23. (mapcar (lambda (f)
  24. (string-match "tag-\\(.+\\)\\.html" f)
  25. (match-string 1 f))
  26. jao-org-blog-tag-files))
  27. ;;; Header
  28. (setq org-static-blog-page-header
  29. (concat
  30. "<meta name=\"author\" content=\"jao\">\n"
  31. "<meta name=\"referrer\" content=\"no-referrer\">\n"
  32. "<link rel=\"stylesheet\" href=\"/static/style.css\""
  33. " type=\"text/css\">\n"
  34. "<link rel=\"apple-touch-icon\" sizes=\"180x180\""
  35. " href=\"/static/apple-touch-icon.png\" >\n"
  36. "<link rel=\"icon\" type=\"image/png\""
  37. " sizes=\"32x32\" href=\"/static/favicon-32x32.png\">\n"
  38. "<link rel=\"icon\" type=\"image/png\""
  39. " sizes=\"16x16\" href=\"/static/favicon-16x16.png\">\n"
  40. "<link rel=\"icon\" href=\"/static/favicon.ico\">\n"
  41. "<link rel=\"manifest\" href=\"/static/site.webmanifest\">\n")
  42. org-static-blog-page-preamble
  43. (concat
  44. "<div class=\"header\">"
  45. " <a href=\"https://jao.io\">programming (and other) musings</a>"
  46. " <div class=\"sitelinks\">"
  47. " <a href=\"/blog/about.html\">about</a>"
  48. " | <a href=\"/blog/hacking.html\">hacking</a>"
  49. " | <a href=\"/blog/archive.html\">archive</a>"
  50. " | <div class=\"dropdown\">"
  51. " <a href=\"/blog/tags.html\" class=\"dropbtn\">tags</a>"
  52. " <div class=\"dropdown-content\">"
  53. (mapconcat #'identity jao-org-blog-tags "")
  54. " </div>"
  55. " </div>"
  56. " | <div class=\"dropdown\">"
  57. " <a href=\"/blog/rss.xml\" class=\"dropbtn\">rss</a>"
  58. " <div class=\"dropdown-content\">"
  59. (mapconcat #'identity jao-org-blog-tag-rss "")
  60. " </div>"
  61. " </div>"
  62. " </div>"
  63. "</div>"))
  64. ;;; Footer
  65. (setq org-static-blog-page-postamble
  66. (with-temp-buffer
  67. (insert-file-contents "~/.emacs.d/commons.html")
  68. (buffer-string)))
  69. ;;; Package
  70. (use-package org-static-blog
  71. :ensure t
  72. :init
  73. (setq org-static-blog-use-preview t
  74. org-static-blog-preview-link-p t
  75. org-static-blog-preview-start "<!-- preview-start -->"
  76. org-static-blog-preview-end "<!-- preview-end -->"
  77. org-static-blog-preview-date-first-p t
  78. org-static-blog-index-length 30
  79. org-static-blog-preview-convert-titles t
  80. org-static-blog-preview-ellipsis "more ..."
  81. org-static-blog-enable-tags t
  82. org-static-blog-tags-file "tags.html"
  83. org-static-blog-rss-file "rss.xml"
  84. org-static-blog-publish-url "https://jao.io/blog/"
  85. org-static-blog-publish-title "programming (and other) musings"
  86. org-static-blog-posts-directory (jao-blog-dir "posts/")
  87. org-static-blog-drafts-directory (jao-blog-dir "pages/")
  88. org-static-blog-publish-directory (jao-blog-dir "blog/")
  89. org-static-blog-rss-extra "" ; "<author>mail@jao.io</author>\n"
  90. org-static-blog-rss-max-entries 30
  91. org-static-blog-rss-excluded-tag "norss"
  92. org-static-blog-enable-tag-rss t
  93. org-export-with-toc nil
  94. org-export-with-section-numbers nil)
  95. :config
  96. (defun jao-org-static-post-path (pf dt)
  97. (cond ((string-match-p "pages/.*\\|in-no-particular-order" pf)
  98. (file-name-nondirectory pf))
  99. ((string-match-p "drafts/.*" pf) pf)
  100. ((string-match-p "^[[:digit:]]+-.*" pf) pf)
  101. (t (concat (format-time-string "%Y-%m-%d-" dt)
  102. (file-name-nondirectory pf)))))
  103. (advice-add 'org-static-blog-generate-post-path :override
  104. #'jao-org-static-post-path)
  105. :bind (:map org-mode-map (("C-c B" . jao-transient-org-blog))))
  106. ;;; New entries
  107. (defun jao-org-blog-publish-file (fname)
  108. (interactive (list (read-file-name "Publish: "
  109. nil
  110. (buffer-file-name)
  111. t
  112. (buffer-file-name))))
  113. (let ((geiser-active-implementations '(guile))
  114. (geiser-default-implementation 'guile)
  115. (whitespace-style nil))
  116. (org-static-blog-publish-file fname)))
  117. (defconst jao-org-static-blog--prev-beg "#+html: <!-- preview-start -->")
  118. (defconst jao-org-static-blog--prev-end "#+html: <!-- preview-end -->")
  119. (defun jao-org-static-blog-create-new-post (&optional draft)
  120. (interactive)
  121. (let* ((title (read-string "Title: "))
  122. (file (replace-regexp-in-string "\s" "-" (downcase title)))
  123. (tags (completing-read-multiple "Tags: " jao-org-blog-tag-names)))
  124. (find-file (expand-file-name (concat file ".org")
  125. (if draft
  126. org-static-blog-drafts-directory
  127. org-static-blog-posts-directory)))
  128. (insert "#+title: " title "\n"
  129. "#+date: " (format-time-string "<%Y-%m-%d %H:%M>") "\n"
  130. "#+filetags: "
  131. (mapconcat #'identity tags " ")
  132. "\n\n")
  133. (when (member "books" tags)
  134. (insert jao-org-static-blog--prev-beg "\n\n[[../img/" file ".jpg]]\n\n"))
  135. (save-excursion (insert jao-org-static-blog--prev-end "\n"))))
  136. ;;; Drafts
  137. (defun jao-org-static-blog-update-date ()
  138. (interactive)
  139. (when (y-or-n-p "Update date? ")
  140. (goto-char (point-min))
  141. (when (re-search-forward "^#\\+date: " nil t)
  142. (delete-line)
  143. (insert (format-time-string "<%Y-%m-%d %H:%M>"))
  144. (save-buffer))))
  145. (defun jao-org-static-blog-create-new-draft ()
  146. (interactive)
  147. (jao-org-static-blog-create-new-post t))
  148. (defun jao-org-static-blog-publish-draft ()
  149. (interactive)
  150. (let* ((from (read-file-name "Post: "
  151. org-static-blog-drafts-directory
  152. nil t))
  153. (to (expand-file-name (file-name-nondirectory from)
  154. org-static-blog-posts-directory)))
  155. (rename-file from to)
  156. (when-let ((b (get-buffer from)))
  157. (kill-buffer b))
  158. (find-file to)
  159. (jao-org-static-blog-update-date)
  160. (when (y-or-n-p "Generate HTML? ")
  161. (jao-org-blog-publish))))
  162. (defun jao-org-static-blog-edit-draft ()
  163. (interactive)
  164. (find-file (read-file-name "Edit: "
  165. org-static-blog-drafts-directory
  166. nil
  167. t)))
  168. ;;; Publish
  169. (defun jao-org-blog-publish (&optional force)
  170. (interactive "P")
  171. (let ((geiser-active-implementations '(guile))
  172. (geiser-default-implementation 'guile)
  173. (whitespace-style nil))
  174. (org-static-blog-publish force)))
  175. (defun jao-org-blog-republish ()
  176. (interactive)
  177. (jao-org-blog-publish t))
  178. ;;; Transient
  179. (defun jao-org-static-prev-begin ()
  180. (interactive)
  181. (insert jao-org-static-blog--prev-beg))
  182. (defun jao-org-static-prev-end ()
  183. (interactive)
  184. (insert jao-org-static-blog--prev-end))
  185. (transient-define-prefix jao-transient-org-blog ()
  186. [["Insert blog snippet"
  187. ("s" "preview begin" jao-org-static-prev-begin)
  188. ("S" "preview end" jao-org-static-prev-end)
  189. ("T" "update date" jao-org-static-blog-update-date)]
  190. ["Edit blog"
  191. ("n" "create post" jao-org-static-blog-create-new-post)
  192. ("d" "create draft" jao-org-static-blog-create-new-draft)
  193. ("e" "edit draft" jao-org-static-blog-edit-draft)]
  194. ["Publish blog"
  195. ("D" "publish draft" jao-org-static-blog-publish-draft)
  196. ("f" "publish single file" jao-org-blog-publish-file)
  197. ("p" "publish all" jao-org-blog-publish)
  198. ("r" "republish" jao-org-blog-republish)]])
  199. ;;; .
  200. (provide 'jao-custom-blog)