Flexible Lisp Blogware. Fork for personal use. Mirrored from https://github.com/kingcons/coleslaw originally.

coleslaw.lisp 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. (in-package :coleslaw)
  2. (defgeneric render (object &key &allow-other-keys)
  3. (:documentation "Render the given OBJECT to HTML."))
  4. (defgeneric render-content (text format)
  5. (:documentation "Compile TEXT from the given FORMAT to HTML for display.")
  6. (:method (text (format (eql :html)))
  7. text)
  8. (:method (text (format (eql :md)))
  9. (let ((3bmd-code-blocks:*code-blocks* t))
  10. (with-output-to-string (str)
  11. (3bmd:parse-string-and-print-to-stream text str)))))
  12. (defgeneric page-path (object)
  13. (:documentation "The path to store OBJECT at once rendered."))
  14. (defmethod page-path :around ((object t))
  15. (let ((result (call-next-method)))
  16. (if (pathname-type result)
  17. result
  18. (make-pathname :type "html" :defaults result))))
  19. (defun render-page (content &optional theme-fn &rest render-args)
  20. "Render the given CONTENT to disk using THEME-FN if supplied.
  21. Additional args to render CONTENT can be passed via RENDER-ARGS."
  22. (funcall (or theme-fn (theme-fn 'base))
  23. (list :config *config*
  24. :content content
  25. :raw (apply 'render content render-args)
  26. :pubdate (make-pubdate)
  27. :injections (find-injections content))))
  28. (defun write-page (filepath page)
  29. "Write the given PAGE to FILEPATH."
  30. (ensure-directories-exist filepath)
  31. (with-open-file (out filepath
  32. :direction :output
  33. :if-does-not-exist :create)
  34. (write-line page out)))
  35. (defun compile-blog (staging)
  36. "Compile the blog to a STAGING directory as specified in .coleslawrc."
  37. (when (probe-file staging)
  38. (run-program "rm -R ~a" staging))
  39. (ensure-directories-exist staging)
  40. (with-current-directory staging
  41. (dolist (dir (list (app-path "themes/~a/css" (theme *config*))
  42. (merge-pathnames "static" (repo *config*))))
  43. (when (probe-file dir)
  44. (run-program "cp -R ~a ." dir)))
  45. (do-ctypes (publish ctype))
  46. (render-indices)
  47. (render-feeds (feeds *config*))))
  48. (defgeneric deploy (staging)
  49. (:documentation "Deploy the STAGING dir, updating the .prev and .curr symlinks.")
  50. (:method (staging)
  51. (with-current-directory coleslaw-conf:*basedir*
  52. (let* ((dest (deploy *config*))
  53. (new-build (rel-path dest "generated/~a" (get-universal-time)))
  54. (prev (rel-path dest ".prev"))
  55. (curr (rel-path dest ".curr")))
  56. (ensure-directories-exist new-build)
  57. (run-program "mv ~a ~a" staging new-build)
  58. (when (probe-file prev)
  59. (let ((dest (truename prev)))
  60. (if (equal prev dest)
  61. (delete-file prev)
  62. (run-program "rm -R ~a" dest))))
  63. (when (probe-file curr)
  64. (update-symlink prev (truename curr)))
  65. (update-symlink curr new-build)))))
  66. (defun main (config-key)
  67. "Load the user's config section corresponding to CONFIG-KEY, then
  68. compile and deploy the blog."
  69. (let (*injections*)
  70. (load-config config-key)
  71. (load-content)
  72. (compile-theme (theme *config*))
  73. (compile-blog (staging *config*))
  74. (deploy (staging *config*))))