hamacs/ha-org-publishing.org
Howard Abrams 0afe98086d Integrating my publishing system using org-publish
Seems like I may need to purge my web site source, or maybe use a
less-intense system.
2021-11-11 21:00:39 -08:00

9.2 KiB

Publishing my Website with Org

A literate programming file for publishing my website using org.

Introduction

While the Emacs community have a plethora of options for generating a static website from org-formatted files, I keep my pretty simple, and just use the standard org-publish feature.

While the following packages come with Emacs, they aren't necessarily loaded:

(require 'ox-rss)
(require 'ox-publish)

Variable settings:

(setq org-export-with-broken-links t
      org-mode-websrc-directory "/Volumes/Personal/dropbox/website"
      org-mode-publishing-directory (concat (getenv "HOME") "/website-public/"))

The Projects

I separate my website into distinct projects separately built:

blog-content
The bulk of rendering my website org files into HTML
blog-static
All of the assets, like images are easily copied in place
blog-rss
Regenerate the feeder files
org-notes
Optionally render a non-web site collection of notes.
  (setq org-publish-project-alist
        `(("all"
           :components ("blog-content" "blog-static" "org-notes" "blog-rss"))

          ("blog-content"
           :base-directory       ,org-mode-websrc-directory
           :base-extension       "org"
           :publishing-directory ,org-mode-publishing-directory
           :recursive            t
           :publishing-function  org-html-publish-to-html
           :preparation-function org-mode-blog-prepare
           :export-with-tags     nil
           :headline-levels      4
           :auto-preamble        t
           :auto-postamble       nil
           :auto-sitemap         t
           :sitemap-title        "Howardisms"
           :section-numbers      nil
           :table-of-contents    nil
           :with-toc             nil
           :with-author          nil
           :with-creator         nil
           :with-tags            nil
           :with-smart-quotes    t

           :html-doctype         "html5"
           :html-html5-fancy     t
           ;; :html-preamble  org-mode-blog-preamble
           ;; :html-postamble org-mode-blog-postamble
           ;; :html-postamble "<hr><div id='comments'></div>"
           :html-head  "<meta http-equiv=\"X-Clacks-Overhead\" content=\"GNU Terry Pratchett\" />
                <link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
                <link href='http://fonts.googleapis.com/css?family=Source+Serif+Pro:400,700&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
                <link href='http://fonts.googleapis.com/css?family=Source+Code+Pro:400,700' rel='stylesheet' type='text/css'>
                <link rel=\"stylesheet\" href=\"/css/styles.css\" type=\"text/css\"/>\n"
           :html-head-extra "<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js\"></script>
                <script src=\"/js/magic.js\"></script>
                <link rel=\"icon\" href=\"/img/dragon.svg\">
                <link rel=\"shortcut icon\" href=\"/img/dragon-head.png\">
                <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />"
           :html-head-include-default-style nil)

          ("blog-static"
           :base-directory       ,org-mode-websrc-directory
           :base-extension       "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|svg"
           :publishing-directory ,org-mode-publishing-directory
           :recursive            t
           :publishing-function  org-publish-attachment)

          ("blog-rss"
           :base-directory        ,org-mode-websrc-directory
           :base-extension        "org"
           :rss-image-url         "http://howardism.org/img/dragon-head.png"
           :publishing-directory  ,org-mode-publishing-directory
           :publishing-function   (org-rss-publish-to-rss)
           :html-link-home        "http://www.howardism.org/"
           :html-link-use-abs-url t
           :with-toc              nil
           :exclude               ".*"
           :include               ("index.org"))

          ("org-notes"
           :base-directory        "~/technical/"
           :base-extension       "org"
           :publishing-directory ,(concat org-mode-publishing-directory "/notes/")
           :recursive            t
           :publishing-function  org-html-publish-to-html
           :headline-levels      4  ; Just the default for this project.
           :auto-preamble        t
           :auto-sitemap         t  ; Generate sitemap.org automagically...
           :makeindex            t
           :section-numbers      nil
           :style                "<link rel=\"stylesheet\" href=\"../css/styles.css\" type=\"text/css\"/> <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js\" type=\"text/javascript\"></script> <link href=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/smoothness/jquery-ui.css\" type=\"text/css\" rel=\"stylesheet\" />    <script src=\"https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js\" type=\"text/javascript\"></script> <script =\"text/javascript\" src=\"js/magic.js\"></script>"
           :table-of-contents    nil
           :with-author          nil
           :with-creator         nil
           :with-tags            nil)

          ("org-notes-static"
           :base-directory       "~/technical/"
           :base-extension       "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
           :publishing-directory ,(concat org-mode-publishing-directory "/other/")
           :recursive            t
           :publishing-function  org-publish-attachment)))

Including Sections

In the project definitions, I reference a pre- and postamble that allow me to inject some standard HTML file headers and footers:

(defun org-mode-blog-preamble (options)
  "The function that creates the preamble top section for the blog.
    OPTIONS contains the property list from the org-mode export."
  (message "Preamble options: %s" (princ options))
  (let ((base-directory (plist-get options :base-directory)))
    (org-babel-with-temp-filebuffer (expand-file-name "top-bar.html" base-directory) (buffer-string))))

(defun org-mode-blog-postamble (options)
  "The function that creates the postamble, or bottom section for the blog.
  OPTIONS contains the property list from the org-mode export."
  (let ((base-directory (plist-get options :base-directory)))
    (org-babel-with-temp-filebuffer (expand-file-name "bottom.html" base-directory) (buffer-string))))

Another helper function for the content of website is to make sure to update index.org, so that the RSS gets generated.

(defun org-mode-blog-prepare (&optional options)
  "`index.org' should always be exported so touch the file before publishing."
  (let* ((base-directory (plist-get options :base-directory))
         (buffer (find-file-noselect (expand-file-name "index.org" base-directory) t)))
    (with-current-buffer buffer
      (set-buffer-modified-p t)
      (save-buffer 0))
    (kill-buffer buffer)))

Keybindings

Make it easy to publish all or just some of my website:

  (general-evil-define-key 'normal org-mode-map
    :prefix "SPC m"
      "p"  '(:ignore t :which-key "publishing")
      "p a" '("all" . org-publish-all)
      "p p" '("project" . org-publish-project))

And let's put a leader key sequence for my favorite file on my website:

  (ha-leader
        "f h"  '(:ignore t :which-key "howards")
        "f h w" '("website index" . (lambda ()
                                      (find-file (expand-file-name "index.org" "~/website")))))