/ox-blog

minimal org-mode blog generator with livereload

Primary LanguageEmacs Lisp

ox-blog

The goal of ox-blog is to be a user-friendly, batteries-included blogging environment for emacs. It is built on top of the awesome org export framework and provides

  • development server with livereload
  • automatic export on save
  • post categories (with index page for each category)
  • small codebase & dependency list
    • dependencies: org-plus-contrib, htmlize
    • < 1000 lines of code
  • motivation to actually write posts (i wish… this package exists because I’m procrastinating and not writing posts)

Getting Started

  1. Put ox-blog.el into your load path
  2. Create a blog directory
  3. Create .dir-locals.el in the blog directory with the following contents
    ;; .dir-locals.el in ~/blog. Adapt directories to your liking
    ((nil . ((eval . (ox-blog-mode 1))
             (ox-blog-project . (:source-directory "~/blog/source/"
                                 :export-directory "~/blog/export/")))))
        
  4. Create a post in the source-directory and visit localhost:8000
    #+TITLE: Hello World
    #+DATE: <2018-01-01>
    #+TYPE: post
    
    Lorem Ipsum
        

Configuration

  • Check out the exported example blog and its source
  • ox-blog project option can be found under the org-export-blog group in customize.
    The values can be changed by setting the defaults or overwriting them in your ox-blog-project definition.
    (get 'org-export-blog 'custom-group)
        
    ((ox-blog-project custom-variable)
     (ox-blog-excluded-files custom-variable)
     (ox-blog-force-export custom-variable)
     (ox-blog-with-drafts custom-variable)
     (ox-blog-index-head custom-variable)
     (ox-blog-babel-header-args custom-variable)
     (ox-blog-babel-evaluate custom-variable)
     (ox-blog-server-idle-seconds custom-variable)
     (ox-blog-server-port custom-variable)
     (ox-blog-server-livereload-script custom-variable)
     (ox-blog-server-base-url custom-variable)
     (ox-blog-index-template custom-variable)
     (ox-blog-index-format-function custom-variable)
     (ox-blog-index-item-format-function custom-variable)
     (ox-blog-page-category custom-variable))
        
  • org-export-html options can be listed with (org-export-get-all-options 'html)
    (org-export-get-all-options 'html)
        
    ((:html-doctype "HTML_DOCTYPE" nil org-html-doctype)
     (:html-container "HTML_CONTAINER" nil org-html-container-element)
     (:description "DESCRIPTION" nil nil newline)
     (:keywords "KEYWORDS" nil nil space)
     (:html-html5-fancy nil "html5-fancy" org-html-html5-fancy)
     (:html-link-use-abs-url nil "html-link-use-abs-url" org-html-link-use-abs-url)
     (:html-link-home "HTML_LINK_HOME" nil org-html-link-home)
     (:html-link-up "HTML_LINK_UP" nil org-html-link-up)
     (:html-mathjax "HTML_MATHJAX" nil "" space)
     (:html-postamble nil "html-postamble" org-html-postamble)
     (:html-preamble nil "html-preamble" org-html-preamble)
     (:html-head "HTML_HEAD" nil org-html-head newline)
     (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline)
     (:subtitle "SUBTITLE" nil nil parse)
     (:html-head-include-default-style nil "html-style" org-html-head-include-default-style)
     (:html-head-include-scripts nil "html-scripts" org-html-head-include-scripts)
     (:html-allow-name-attribute-in-anchors nil nil org-html-allow-name-attribute-in-anchors)
     (:html-divs nil nil org-html-divs)
     (:html-checkbox-type nil nil org-html-checkbox-type)
     (:html-extension nil nil org-html-extension)
     (:html-footnote-format nil nil org-html-footnote-format)
     (:html-footnote-separator nil nil org-html-footnote-separator)
     (:html-footnotes-section nil nil org-html-footnotes-section)
     (:html-format-drawer-function nil nil org-html-format-drawer-function)
     (:html-format-headline-function nil nil org-html-format-headline-function)
     (:html-format-inlinetask-function nil nil org-html-format-inlinetask-function)
     (:html-home/up-format nil nil org-html-home/up-format)
     (:html-indent nil nil org-html-indent)
     (:html-infojs-options nil nil org-html-infojs-options)
     (:html-infojs-template nil nil org-html-infojs-template)
     (:html-inline-image-rules nil nil org-html-inline-image-rules)
     (:html-link-org-files-as-html nil nil org-html-link-org-files-as-html)
     (:html-mathjax-options nil nil org-html-mathjax-options)
     (:html-mathjax-template nil nil org-html-mathjax-template)
     (:html-metadata-timestamp-format nil nil org-html-metadata-timestamp-format)
     (:html-postamble-format nil nil org-html-postamble-format)
     (:html-preamble-format nil nil org-html-preamble-format)
     (:html-table-align-individual-fields nil nil org-html-table-align-individual-fields)
     (:html-table-caption-above nil nil org-html-table-caption-above)
     (:html-table-data-tags nil nil org-html-table-data-tags)
     (:html-table-header-tags nil nil org-html-table-header-tags)
     (:html-table-use-header-tags-for-first-column nil nil org-html-table-use-header-tags-for-first-column)
     (:html-tag-class-prefix nil nil org-html-tag-class-prefix)
     (:html-text-markup-alist nil nil org-html-text-markup-alist)
     (:html-todo-kwd-class-prefix nil nil org-html-todo-kwd-class-prefix)
     (:html-toplevel-hlevel nil nil org-html-toplevel-hlevel)
     (:html-use-infojs nil nil org-html-use-infojs)
     (:html-validation-link nil nil org-html-validation-link)
     (:html-viewport nil nil org-html-viewport)
     (:html-inline-images nil nil org-html-inline-images)
     (:html-table-attributes nil nil org-html-table-default-attributes)
     (:html-table-row-open-tag nil nil org-html-table-row-open-tag)
     (:html-table-row-close-tag nil nil org-html-table-row-close-tag)
     (:html-xml-declaration nil nil org-html-xml-declaration)
     (:html-klipsify-src nil nil org-html-klipsify-src)
     (:html-klipse-css nil nil org-html-klipse-css)
     (:html-klipse-js nil nil org-html-klipse-js)
     (:html-klipse-selection-script nil nil org-html-klipse-selection-script)
     (:infojs-opt "INFOJS_OPT" nil nil)
     (:creator "CREATOR" nil org-html-creator-string)
     (:with-latex nil "tex" org-html-with-latex)
     (:latex-header "LATEX_HEADER" nil nil newline))
        

Publishing

Publishing is done via git. Use ox-blog-publish to export & push the exported files. All you need to do is

  1. create a git repository in your :export-directory
  2. set the origin remote
  3. OPTIONAL
    • check out a branch
    • add a .gitignore file (e.g. to not push files in the drafts/ folder)

Github Pages

Follow https://pages.github.com/

In the :export-directory run

git init
git remote add origin git@github.com:username/username.github.io.git

Run ox-blog-publish

Develoment

make install
make test

Features

Planned

melpa

https://www.gnu.org/software/emacs/manual/html_node/elisp/Documentation-Tips.html emacsattic/org-magit#5

document org-export

  • :filter-alist overrides in project

publishing via git

Ideas

multi-post files

Sometimes posts are related and it would be nice to keep them in the same file. Problem: Caching via modified timestamp of file falls apart for multi-post files

custom theme for code highlighting

The emacs --batch already works using 2 lines of glue code so this is low priority.

  • Htmlize css classes seems like a fragile solution. Requires an up to date list of all faces used in the blog.
  • Export from clean emacs session using emacs --batch. Can load any theme and set variables to liking without conflicting with actual session. This already works (see Makefile export task)
  • Change where htmlize gets it’s face definitions from. loading a theme adds the face definitions to the face symbol. Could look at the symbol plist rather than the currently applied setting. Also look into htmlize-face-overrides

export rss / atom feed

  • :feed-template
  • :feed-function
  • :feed-item-function

rename node

naming is hard - no good ideas yet file-name -> file -> post (doesn’t work for non-post org-nodes)