2017-2-13

This web page is hosted with Github Pages automatically from my github repository for free. The tradeoff is that you can serve only static pages and content. This is where I and many others come up with creative solutions since noone likes to write plain html. I use .org files for my journal and other note taking things thus taking inspiration from {1-3} I compile my org sources to static htmls with single elisp script.

## Interface

Before diving in in configuration details I will show the things I can do. I can write $$\LaTeX$$ formulas in .org file, add images and with special html formating, videos, code, links to outside world and links to org which on html export are changed automatically to their counterparts. You can see all theese features with a following .org source text file

#+TITLE: Tests
#+DATE: 2017-2-16
- list item 1
- list item 2
- *bold* /italic/ =verbatim= ~code~ +strike tghrough+
$\LaTeX$ [[file:ideas.org][Ideas]]
$e^{i\pi} = -1$
#+ATTR_HTML: :style float:left; :height 200
[[file:../contents/profile.png]]
#+HTML: <video height="200" controls>
#+HTML: <source src="../contents/optimal-pulse.mp4#t=2" type="video/mp4">
#+HTML: </video>


When I am finished with .org file writing I compile it with single command in page-sources directory emacs --script publish.el --eval "(blog-publish)"~ or from my emacs ~M-x blog-publish where for output see test page. Then I test if page looks fine locally and do usual push to github repository from where Github Pages takes sources for hosting. Features like your own domain name is also possible as you can see from my page.

## Behind the sceenes

Many tools are avialable for generating static web pages from simpler source files like markdown, reStructuredText, org files. For example you can use pandoc for almost any such conversation to htmls and even more, Jekyl for gnerating static web page from markdown files or jinja2 for making html template and filling it with content (see as an example). I picked up org-publish feature from org mode mainly because I use emacs daily for my note taking but also because it is written in mature programming languge elisp.

When I started to consider emacs as tool for my programming I was expossed to elisp which initially looked as one of the dirtiest languages I had worken with. But after having learned some essential bits of it I get to like it and the ugliest part of it sexps becomes one of most productive part of it. For example code in elisp will have much less local variables for the same task and you don't waste your time thinking of best programming paradigm for your problem. Elisp and many other languges like them are also bececoming incresignly more popular with functional programming paradigm shift where one benefit I see is code to become more modular. Thus its valuable to learn one to get feeling why and when it is better.

All my configuration as can be seen here is written in emacs lisp so prepeare your eyes well while I break it into parts. As an example we might conisder a following project tree

.
├── input
│   └── example.org
├── output
│   └── example.html
├── publish.el


input is where all .org files are stored, output for converted .html files and publish.el is elisp compilation script. The following example of publish.el ilustrates the basic building block for converting all .org files to .html counterparts

(require 'ox)
(setq make-backup-files nil) ;; No need for backup files

(defvar my-base-directory (concat (file-name-directory load-file-name) "input")
"Org sources are taken from folder input relative to this file")

(defvar my-publishing-directory (concat (file-name-directory load-file-name) "output")
"Converted org files are in folder output relative to this file")

;; Right place for personalized template

(setq org-publish-project-alist
(
("publish"
:base-directory ,my-base-directory ;; Path to your org files.
:base-extension "org"
:publishing-directory ,my-publishing-directory
;;:publishing-function pd-html-publish-to-html
:publishing-function org-html-publish-to-html
:html-extension "html"
)
)
)

(defun blog-publish ()
(interactive)
(org-publish "publish" t)
)


The first line (require 'ox) loads the module from org-mode which has publishing feature org-publish. Configuration of the publishing project happens under assignment of global variable org-publish-project-alist which is used when publishing function is called in line (org-publish "publish" t). When code above is executed with command emacs --script publish.el --eval "(blog-publish)"~ it will produce ~.html files in output directory with very functional but not very nice looking default template.

Many configure default template to suit their needs as in {1} I wanted to go other way around producing template from my choosen perfect web page. Fortuantelly I found answer on emacs stackexchange how to do it with org-publish. In org-publish-project-alist I can bind my own publishing function pd-html-publish-to-html which defines how content and metadata is written to html file

(defun pd-html-template (contents info)
(concat
"<!DOCTYPE html>\n"
(format "<html lang=\"%s\">\n" (plist-get info :language))
(format "<meta charset=\"%s\">\n"
(coding-system-get org-html-coding-system 'mime-charset))
(format "<title>%s</title>\n"
(org-export-data (or (plist-get info :title) "") info))
(format "<meta name=\"author\" content=\"%s\">\n"
(org-export-data (plist-get info :author) info))
"<body>\n"
(format "<h1 class=\"title\">%s</h1>\n"
(org-export-data (or (plist-get info :title) "") info))
contents
"</body>\n"
"</html>\n"))

(org-export-define-derived-backend 'pd-html 'html
:translate-alist '((template . pd-html-template))
)

(defun pd-html-publish-to-html (plist filename pub-dir)
(org-publish-org-to 'pd-html filename ".html" plist pub-dir))


This function is passed to org-publish-project-alist variable with :publishing-function pd-html-publish-to-html` (commented line previosly).

To conclude I am very satisfied with my setup. It keeps me confident that I will be able to use this setup for long time since I don't have to compile the code, the elisp is not changing much and I use only single dependency which I can load locally without installing if major changes happens.