Ox-Hugo: A carefully crafted Org exporter back-end for Hugo
ox-hugo is an Org exporter backend that exports Org to
Hugo-compatible Markdown (Blackfriday) and also generates the
front-matter (in TOML or YAML format).
This project consists of ox-blackfriday.el too. It is a derivation
of =ox-gfm= with support added for Blackfriday Markdown tables and
many other tweaks. ox-hugo backend extends from this.
Table of Contents
Screenshots
Before you read further, you can see below how ox-hugo translates
Org to Markdown (Org on the left; exported Markdown with Hugo
front-matter on the right).
One post per Org subtree (preferred)
One post per Org file
Editorial
The preferred way to organize the posts is as Org subtrees (also the main reason to write this package, as nothing like that was out there) as it makes the meta-data management for Hugo front-matter pretty effortless.
If you are a one Org-file per post type of a person, that flow works
too! Just note that in this flow many of those #+HUGO_ properties
need to be managed manually.. just as one would manage the front-matter
in Markdown files — See the Org versions in the above screenshots for
comparison.
Documentation
ox-hugo uses itself to generate its documentation!
You can generate the same too! Simply clone this repo and do make
doc.
Make sure you visit the above link to read more on:
- Why
ox-hugo? - Auto exporting to Markdown each time the Org file is saved
- Using Org Capture to start a new blog post
- .. and many more topics and examples
Source of the Documentation site
- Org source
ox-hugoexported Markdown files
Demo
Org source → Exported Markdown → *Hugo published test site*
Now, the test site doesn’t look pretty, I know :) .. because:
- It is designed to verify if all the content translates from Org to Markdown as expected.
- It uses a *bare_min* theme written just for the debug purpose (not presentation).
See Hugo Themes for examples of really good site prettification and presentation styles.
Actual usage examples
- https://ox-hugo.scripter.co –
ox-hugoDocumentation Site - https://scripter.co – My blog
Installation
This package requires emacs 24.5+ and Org 9.0+. It is available on Melpa (https://melpa.org/#/ox-hugo).
Usage
Once the package is installed, you will need to require it so that
the ox-hugo export options are available in the Org Export
Dispatcher menu (the one you see when you hit C-c C-e to initiate
any export).
You can do that by adding the below to your config:
(with-eval-after-load 'ox
(require 'ox-hugo))If you use use-package, you can do the below instead:
(use-package ox-hugo
:after ox)Spacemacs
Spacemacs users can choose to add this snippet to their
dotspacemacs/user-config function in .spacemacs:
(defun dotspacemacs/user-config ()
;; Other stuff
;; ..
;; ox-hugo config
(use-package ox-hugo
:ensure t ;Auto-install the package from Melpa
:after ox))If you do so, you also need to add ox-hugo to
dotspacemacs-additional-packages.
Verified to work on Spacemacs =develop= branch with =spacemacs-base= distribution, =emacs= editing style.
Before you export
Before you export check that these properties are set as you need:
- HUGO_SECTION
- The default Hugo section name for all the posts. See
here for more information on Hugo sections. It is
common for this property to be set to
postsorblog. The default value is set usingorg-hugo-default-section-directory. - HUGO_BASE_DIR
- Root directory of the source for the Hugo site. If
this is set to
~/hugo/, the exported Markdown files will be saved to~/hugo/content/<HUGO_SECTION>/directory. By default, the Markdown files reside in a hierarchy under thecontent/directory in the site root directory (ref). If you try to export without setting this property, you will get this error:user-error: It is mandatory to set the HUGO_BASE_DIR property
Important: If you choose to export an Org subtree as a post, you
need to set the EXPORT_FILE_NAME subtree property. That property is
used by this package to figure out where the current post starts.
Export bindings
The common ox-hugo export bindings are:
| Binding | Description |
|---|---|
C-c C-e H H | Export only the current valid subtree (has the EXPORT_FILE_NAME property set) |
C-c C-e H A | Export all valid subtrees (those that have the EXPORT_FILE_NAME property set) |
C-c C-e H h | Export the whole Org file to a single post |
Customization Options
Do M-x customize-group, and select org-export-hugo to see the
available customization options for this package.
Changelog
v0.4.1 <2017-10-29 Sun>
Features
- Support specifying the
:heightparameter in the#+ATTR_HTMLabove image links. That eventually gets transformed to theheightparameter in thefiguretag in the HTML generated by Hugo. This feature requires building Hugo from its master branch with commit 488631fe (or Hugo v0.31+).
Fixes
- Fix
EXPORT_HUGO_SECTIONnot getting inherited [90].
v0.4 <2017-10-28 Sat>
Backward-incompatible changes
- Restore the default Org behavior of
#+TAGS. Now that keyword (and theEXPORT_TAGSproperty) is not used byox-hugo. Fixes [89]. - File-based exports must now use
#+HUGO_TAGSto set the post tags. - Subtree-based exports can use the
EXPORT_HUGO_TAGSproperty to override Org-style tags on the same headline (and the ones inherited from Org-style tags from any of the parent subtrees and#+FILETAGS).- Note that for subtree-based exports,
#+FILETAGScan be used to set tags globally in the file. Earlier#+TAGSwas used for that purpose.
- Note that for subtree-based exports,
- Subtree-based exports can use the
EXPORT_HUGO_CATEGORIESproperty to override Org-style categories (tags with “@” prefix) on the same headline (and the ones inherited from Org-style categories from any of the parent subtrees and#+FILETAGS).- Note that for subtree-based exports,
#+FILETAGScan be used to set categories (tags with “@”) globally in the file.
- Note that for subtree-based exports,
See the new section added to documentation: *Tags and Categories*
Features
- Support specifying the
:widthparameter in the#+ATTR_HTMLabove image links. That eventually gets transformed to thewidthparameter in thefiguretag in the HTML generated by Hugo.
v0.3.2 <2017-10-24 Tue>
Fixes
- Fix issue with headline metadata parsing (ALLTAGS, CLOSED, TODO) when a post Org heading was immediately followed by that post’s sub-heading. This issue was seen in subtree-based exports [87].
v0.3.1 <2017-10-19 Thu>
Fixes
- Fix the source block line number annotation when the line numbers increased in number of digits in the same code block.
v0.3 <2017-10-18 Wed>
Features
- Source blocks can now be exported with line numbers and/or
highlighting!
See Source Blocks for details.
v0.2.3 <2017-10-11 Wed>
Fixes
org-hugo-slugearlier stripped off only thecodeHTML tag (<code> .. </code>) from the input string, if present. Now it does that for any HTML tag, likespan. For example, this HTML gets stripped off from the above heading (only insideorg-hugo-slugwhen deriving the slug string): ~<span class=”timestamp-wrapper”><span class=”timestamp”><2017-10-11 Wed></span></span>~.
v0.2.2 <2017-10-10 Tue>
Backward-incompatible changes
- Now
ox-hugoby default requires text, to be sub/super-scripted, to be wrapped in{}. So nowa_bwill be exported asa_b, buta_{b}will be exported asa<sub>b</sub>. To revert back to the earlier behavior, user needs to add#+OPTIONS: ^:tto their Org file.
v0.2.1 <2017-09-28 Thu>
Fixes
- Single column tables now export correctly [84].
- Ignore
HUGO_WEIGHTset toautofor per-file exports [83].
v0.2 <2017-09-27 Wed>
Features
- Add support for all Hugo
figureshortcode parameters [79]. - New option
org-hugo-delete-trailing-wsdefaults tot; now Hugo deletes trailing white-spaces by default. - New options
org-hugo-default-static-subdirectory-for-externalsandorg-hugo-external-file-extensions-allowed-for-copying(related to [69]).
Fixes
- Remove
HUGO_STATIC_IMAGEoption; fix attachment re-write [69]. - Fix incorrectly inserted hard line-breaks [72]. Added a
new option
HUGO_PRESERVE_FILLING. - Fix error happening when a post title was set to an empty string [ba9e8365].
Backward-incompatible changes
- Switch the default value of
org-hugo-use-code-for-kbdoption tonil[88ba15ae].
v0.1.3 <2017-09-13 Wed>
- Now a HUGO key value set to =”nil”=, like
#+HUGO_CODE_FENCE: nil, will evaluate as nil instead of t, as noworg-hugo--plist-get-true-pis used to parse boolean keys instead ofplist-get.
v0.1.2 <2017-09-12 Tue>
- Make DateTime matching better; new internal variable
org-hugo--date-time-regexp. Earlier time zones ahead of UTC (with+sign) were not detected as dates inorg-hugo--quote-stringand thus were unnecessarily quoted.
v0.1.1 <2017-09-11 Mon>
- Use CLOSED log drawer info if available to set the date in front-matter [68].
- Code optimization: Use of
org-entry-getat places instead of maintaining global variables.
Thanks
- Matt Price (@titaniumbones)
- Puneeth Chaganti (@punchagan)
- Also thanks to holgerschurig.de, whyarethingsthewaytheyare.com and the =goorgeous= project by Chase Adams (@chaseadamsio) for inspiration to start this project.

