hamacs/ha-org-publishing.org
Howard Abrams b2c0b1ed49 Using jack-html for my HTML specifications
Now I don't have to escape quotes.
2023-12-19 20:15:47 -08:00

242 lines
10 KiB
Org Mode
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#+title: Publishing my Website with Org
#+author: Howard X. Abrams
#+date: 2020-12-22
#+tags: emacs org
A literate programming file for publishing my website using org.
#+begin_src emacs-lisp :exports none
;;; org-publishing --- Publishing my website using org. -*- lexical-binding: t; -*-
;;
;; © 2020-2023 Howard X. Abrams
;; Licensed under a Creative Commons Attribution 4.0 International License.
;; See http://creativecommons.org/licenses/by/4.0/
;;
;; Author: Howard X. Abrams <http://gitlab.com/howardabrams>
;; Maintainer: Howard X. Abrams
;; Created: December 22, 2020
;;
;; This file is not part of GNU Emacs.
;;
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
;; ~/other/hamacs/org-publishing.org
;; And tangle the file to recreate this one.
;;
;;; Code:
#+end_src
* 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 use the standard =org-publish= feature.
While the following packages come with Emacs, they aren't necessarily loaded:
#+begin_src emacs-lisp :results silent
(require 'ox-rss)
(require 'ox-publish)
#+end_src
Variable settings:
#+begin_src emacs-lisp
(setq org-export-with-broken-links t
org-mode-websrc-directory "~/website"
org-mode-publishing-directory (concat (getenv "HOME") "/website-pub/"))
#+end_src
Im not afraid of HTML, however, I like the idea of doing my HTML work in a Lisp-like way using the [[https://github.com/tonyaldon/jack][jack-html project]]:
#+begin_src emacs-lisp
(use-package jack)
#+end_src
So the Lisp code:
#+begin_src emacs-lisp :tangle no
(jack-html '(:p "Hello there"))
#+end_src
Returns the string:
#+begin_example
<p>Hello there</p>
#+end_example
* 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.
#+begin_src emacs-lisp
(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
,(jack-html
'(:meta (@ :http-equiv "X-Clacks-Overhead"
:content "GNU Terry Pratchett")
(:link (@ :rel "stylesheet"
:type "text/css"
:href "http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700&subset=latin,latin-ext"))
(:link (@ :rel "stylesheet"
:type "text/css"
:href "http://fonts.googleapis.com/css?family=Source+Serif+Pro:400,700&subset=latin,latin-ext"))
(:link (@ :rel "stylesheet"
:type "text/css"
:href "http://fonts.googleapis.com/css?family=Source+Code+Pro:400,700"))
(:link (@ :rel "stylesheet"
:type "text/css"
:href "/css/styles.css"))
(:script (@ :src "/js/magic.js"
:type "text/javascript"))
(:link (@ :rel "icon"
:href "/img/dragon.svg"))
(:link (@ :rel "shortcut icon"
:href "/img/dragon-head.svg"))
(: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 "https://howardism.org/img/dragon-head.png"
:publishing-directory ,org-mode-publishing-directory
:publishing-function (org-rss-publish-to-rss)
:html-link-home "https://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 ,(jack-html
'(:link (@ :rel "stylesheet"
:type "text/css"
:href "../css/styles.css")
:script (@ :type "text/javascript"
:src "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js")
:link (@ :ref "stylesheet"
:type "text/css"
:href "http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/smoothness/jquery-ui.css")
:script (@ :type "text/javascript"
:src "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js")
:script (@ :type "text/javascript"
:src "js/magic.js")))
: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)))
#+end_src
* Including Sections
In the project definitions, I reference a =pre-= and =postamble= that allow me to inject some standard HTML file headers and footers:
#+begin_src emacs-lisp
(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))))
#+end_src
Another helper function for the content of website is to make sure to update =index.org=, so that the RSS gets generated.
#+begin_src emacs-lisp
(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)))
#+end_src
* Keybindings
Make it easy to publish all or just some of my website:
#+begin_src emacs-lisp
(with-eval-after-load 'ha-org
(ha-leader :keymaps 'org-mode-map
;; "p" '(:ignore t :which-key "publishing")
"o p a" '("all" . org-publish-all)
"o p p" '("project" . org-publish-project)))
#+end_src
And let's put a /leader key/ sequence for my favorite file on my website:
#+begin_src emacs-lisp
(ha-leader
"f h" '(:ignore t :which-key "howards")
"f h i" '("website index" . (lambda ()
(find-file (expand-file-name "index.org" "~/website")))))
#+end_src
* Technical Artifacts :noexport:
Let's =provide= a name so we can =require= it:
#+begin_src emacs-lisp :exports none
(provide 'ha-org-publishing)
;;; ha-org-publishing.el ends here
#+end_src
Before you can build this on a new system, make sure that you put the cursor over any of these properties, and hit: ~C-c C-c~
#+DESCRIPTION: A literate programming version for publishing my website using org.
#+PROPERTY: header-args:sh :tangle no
#+PROPERTY: header-args:emacs-lisp :tangle yes
#+PROPERTY: header-args :results none :eval no-export :comments no mkdirp yes
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil date:nil
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil
#+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js