aboutsummaryrefslogtreecommitdiff

ennum is a purely functional Org Mode based static blog generator written in Emacs Lisp. It is intended as a complete blog-specific replacement for the org-publish system.

Features

  • minimal rebuilds
  • purely functional
  • resize and optimize images for file size
  • tag posts
  • generate post listings (of all posts, and filtered by tag)
  • generate Atom feeds
  • translate posts to multiple languages
  • tangle source blocks embedded in posts
  • simple HTTP server to view blog locally
  • built-in link types to ease linking to images, other posts, etc.

Features in detail

Minimal rebuilds

When an input file did not change, it is not rebuilt. This saves a lot of time and makes the "edit-compile-debug" cycle really fast.

Purely functional

ennum is purely functional in that the built output always corresponds to the current source. The built output is guaranteed to not contain artifacts from previous builds. For example, when a source file is deleted, the corresponding output file is also deleted in the next rebuild.

Note that ennum's purely functional nature is not achieved by merely deleting the output directory and creating a new one in its place. That would be an enormous waste of time and a violation of the "minimal rebuilds" principle. Instead ennum uses what we call "ennum expressions"—a caching and dependency tracking system inspired by the Guix store and G-expressions.

Resize and optimize images for file size

ennum resizes and optimizes images in posts so that pages load quicker and are light on network use.

Generate post listings and Atom feeds

ennum generates index pages listing all posts, and posts filtered by tag.

Multiple languages

ennum understands posts translated to multiple languages. It automatically links to translations of a post, and generates separate post listings for different languages.

Tangle source blocks embedded in posts

ennum lets you tangle source blocks embedded in posts and write them to a separate source file. Thus, you can make the source code in your blog available for download without having to duplicate your code in two places.

Simple HTTP server to view blog locally

ennum comes with a simple HTTP server to view blog locally before publishing.

Pure Emacs Lisp

ennum is written purely in Emacs Lisp 1. No need to pull up your terminal emulator or shell mode to rebuild your blog.

Installation

Clone the repository.

$ git clone https://git.systemreboot.net/ennum/

Add the path to the cloned repository to your load path, and load ennum.

(add-to-list 'load-path "~/ennum")
(require 'ennum)

Usage

Set up ennum-blog with settings relevant for your blog. A simple sample ennum-blog is given below. For detailed documentation of all available settings, see its docstring.

(setq ennum-blog
      '(:working-directory "~/blog"
        :output-directory "output"
        :posts-directory "posts"
        :images-directory "images"
        :static-directory "files"
        :video-directory "videos"

        :blog-title "Muthu Mani Maalai"
        :blog-subtitle "Mani's blog"
        :blog-domain "example.org"
        :blog-license "All content is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License."))

Run M-x ennum-publish to export the blog to the output directory. To start a local HTTP server (by default, listening on http://localhost:8080) serving the exported output, run M-x ennum-server-start. You can use this to preview the exported output. Once happy with the output, shut down the server using M-x ennum-server-stop.

Post format

Posts are written as Org mode documents. Keywords TITLE, DATE, FILETAGS are used to indicate the title, date, and tags respectively. The SUMMARY keyword is used to specify the short text that should describe the post in post listings such as the index page.

#+TITLE: Gandikota
#+DATE: <2022-07-02>
#+FILETAGS: :travel:
#+SUMMARY: Last week, I visited Gandikota, the ruins of a fort in Andhra Pradesh.

Furthermore, the theory of syntactic features developed earlier is not
to be considered in determining a parasitic gap construction. However,
this assumption is not correct, since this analysis of a formative as
a pair of sets of features can be defined in such a way as to impose
the traditional practice of grammarians. We will bring evidence in
favor of the following thesis: a case of semigrammaticalness of a
different sort is, apparently, determined by the system of base rules
exclusive of the lexicon. Conversely, this selectionally introduced
contextual feature is necessary to impose an interpretation on an
important distinction in language use. Clearly, most of the
methodological work in modern linguistics is to be regarded as
nondistinctness in the sense of distinctive feature theory.

Link types

ennum comes with several built-in link types. The post link type can be used to refer to other of your own posts. The image and thumbnail link types refer to images scaled to different sizes. The static, video and tangle link types refer to static files, videos and tangled output respectively. The tag link type refers to a page listing posts of a specific tag. Example usage for these link types is shown below.

Link to post whose basename (that is, filename without the extension) is /foo/
[[post:foo]]

Link to image /bar.jpg/
[[image:bar.jpg]]

Link to thumbnail sized version of image file /bar.jpg/
[[thumbnail:bar.jpg]]

Link to static file
[[static:attached-document.odt]]

Link to video
[[video:movie.webm]]

Link to tangled output file
[[tangle:macros.scm]]

Link to page listing posts tagged /travel/
[[tag:travel]]

Posts in multiple languages

Optionally, you can write your post in a different language and specify the language using the LANGUAGE keyword. If you have the same post translated to different languages, you can group them together using the TRANSLATIONGROUP keyword. All posts with the same TRANSLATIONGROUP will be considered translations of each other, and will link to each other in the exported output. If the TRANSLATIONGROUP keyword is not specified, it defaults to the basename (that is, filename without the extension) of the file. For example, if a post has a filename foo-bar.org, then its basename is foo-bar.

#+TITLE: Gandikota
#+DATE: <2022-07-02>
#+FILETAGS: :travel:
#+SUMMARY: Lorem ipsum dolor sit amet
#+LANGUAGE: la
#+TRANSLATION_GROUP: gandikota

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.

Why is it called "ennum"?

ennum is a Tamil word meaning "thought". A blog is an instrument to record and publish your thoughts with.

Footnotes:

1

except for the image processing code, for which we shell out to external command-line tools