A YASnippet for org-mode publishing
First published: August 26, 2018
Last updated: February 19, 2023
I love standards and templates. Cookiecutter is my favorite command line template generator and I use a custom template for my lab projects.
When it comes to emacs programming and org-mode, I use the amazing YASnippet for generating templates from files called snippets. I introduced a simple snippet in my post on adding and parsing edn metadata for my static website, and here I have an expanded version that I am happy with for posts to my website.
I have a standard format for all my pages on my website, and the default org-mode export options and standard format rarely change. The format requires the following:
ednmetadata at the top with a set of specific keys- Standard org-mode export options
- The date the page was created
- A note as to whether the page was updated and when
The snippet
Below is the text of my snippet. I will add comments in the lisp style with ;. Anything following the ;; is NOT part of the snippet, but is only there for annotation.
;; yas-snippet
# -*- mode: snippet -*-
# name: blog
# key: blog
# --
#+HTML: <div id="edn">
#+HTML: {:topic "programming" :title "${1:title}" :date "`(format-time-string "%Y-%m-%d")`" :tags ${2:["clojure"]}}
#+HTML: </div> ;; 1
#+OPTIONS: \n:1 toc:nil num:nil todo:nil ^:{} title:nil ;; 2
#+PROPERTY: header-args :eval never-export ;; 2
#+DATE: `(format-time-string "%Y-%m-%d %a")` ;; 3
#+TITLE $1 ;; 4
#+HTML:<h1 id="mainTitle">$1</h1> ;; 5
#+HTML:<div id="timedate"> ;; 6
/First published: {{{date}}}/ ;; 7
/Last updated: {{{time(%Y-%m-%d %a)}}}/ ;; 8
#+HTML:</div>
${3:#+TOC: headlines 2} ;; 9
$0
You can activate a snippet by typing its key and then pushing TAB. So whenever I make a new blog post, I type blog<TAB> and this snippet expands and prompts me for input.
- This is where the
divfor myednmetadata is generated. I wrote about it briefly in this post. In org-mode,#+HTMLwill export as literal html. So I am first prompted to enter a title"${1:title}", then the:dateis automatically inserted with the emacs-lisp code snippet surrounded by back ticks, and I am then prompted to enter a few tags in what will be parsed as a Clojure vector. - The
#+OPTIONSline and#+PROPERTYset some sane defaults for org-mode export. #+DATEis an org-mode metadata item where I have also inserted emacs-lisp code to generate the date. Yup, you can insert arbitrary emacs-lisp code in snippets to execute when expanded.- This line establishes the title for the post, will mirror whatever my title is (
$1mirrors${1:title}). - This line will be exported as raw html and establishes a special
<h1 id>for my main title. Again,$1mirrors the title. - Here I am starting another html
divthat will control another metadata feature. - The
{{{}}}is for org-mode org-mode macro replacement. Thedateinside this replacement macro will insert the value#+DATEvariable into that location upon export. - This org-mode macro inserts the date of last export.
- Optional table of contents. Org-mode will automatically generate a table of contents and it will be inserted wherever I put this line. I usually don't want a table of contents, so I typically delete this part but it is there just in case.
I really like this format. It allows me to standardize the metadata of my files and provides a really nice automatic record of when I posted and updated different posts. When I first publish an article, the date and macro described in #7 will be the same, as #+DATE is set once when the snippet is first generated. If I ever update and re-export a file, then #7 will re-evaluate and display the date of the most recent export!
More snippets
I have a bunch more snippets, which you can see in my emacs-config. I stole a lot from different places on the internet, but most of these are customized to address specific problems I had or to optimize for a specific workflow. For example, I made another snippet for my regular science writing workflow called pre sets up all of my normal export options and org-ref settings.
YASnippet's are just another reason why org-mode and emacs rock!