Kishore Vancheeshwaran
Resume in yaml and jinja templates

In my previous post I created my resume using yaml and orgmode. Even though I was satisfied to an extent with this solution, I still felt there was a limitation in using orgmode as a middleware to export my yaml into pdf and html. I realised that this challenge was partially due to my obsession to using emacs and orgmode. The main thing I was unhappy with was I could not edit the templates being exported easily without modifying emacs’s backend exporter. I needed a way to translate yaml to latex and html directly. Initially I started writing python scripts with a custom formatter but realised I was still trying to solve the wrong problem.

When I googled, I realised there is Jinja. Quoting from the documentation,

Jinja is a fast, expressive, extensible templating engine. Special placeholders in the template allow writing code similar to Python syntax. Then the template is passed data to render the final document.

This was wonderful and suited my needs. Searching further I could see other repositories here and here implementing this workflow. This workflow was much more straightforward.

A simple example is as below which can be expanded/modified for your use case.

resume.yaml

name: Kishore Vancheeshwaran
contact:
  email: personal.email@gmail.com
  linkedin: linkedin.com/in/kishvanchee
  phone: +91-0000000000
  location: Bangalore, IN
experience:
  - company: Company 2
    position: Software Engineer
    team: Awesome
    start_date: Jan 2015
    location: Bangalore
    summary:
      - I did something awesome
      - I automated some work
  - company: Company 1
    position: Software Engineer
    team: Awesome
    start_date: Jan 2005
    to_date: Dec 2014
    location: Bangalore
    summary:
      - I did something awesome
      - I automated some work

generate.py

import yaml
from jinja2 import Environment, FileSystemLoader
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-t", "--type", required=False, help="type of resume")
parser.add_argument("-o", "--outfile", required=True, help="output file name")
parser.add_argument("-j", "--template", required=True, help="jinja template")
args = parser.parse_args()

with open("resume.yaml", "r") as fin:
    resume = yaml.safe_load(fin)

# style.css which we will embed in the html directly
# to avoid requiring the stylesheet separately
with open("style.css") as fin:
    style = fin.read()
resume["style"] = style

# This modification is to make sure the syntax
# plays well with latex templates
env = Environment(
    block_start_string="\BLOCK{",
    block_end_string="}",
    variable_start_string="\VAR{",
    variable_end_string="}",
    comment_start_string="\#{",
    comment_end_string="}",
    line_statement_prefix="%%",
    line_comment_prefix="%#",
    trim_blocks=True,
    autoescape=False,
    loader=FileSystemLoader("./templates"),
)

template = env.get_template(args.template)
with open(args.outfile, "w") as fout:
    fout.write(template.render(resume=resume))

html.template

<!doctype html>
<!-- standard html stuff -->
<style type="text/css" media="screen">
 \VAR{resume['style']}
</style>

<body>
  \VAR{resume['name']}
  <br>
  \VAR{resume['contact']['phone']} |
  <a href="mailto:\VAR{resume['contact']['email']}">\VAR{resume['contact']['email']}</a> |
  <a href="https://\VAR{resume['contact']['linkedin']}">\VAR{resume['contact']['linkedin']}</a>

  \BLOCK{for exp in resume['experience']}
  \VAR{exp['position']}
  \VAR{exp['start_date']}
  \VAR{exp['to_date']}
  \VAR{exp['company']}
  \VAR{exp['location']}

  \BLOCK{for item in exp['summary']}
  <ul>
      <li>\VAR{item}</li>
  </ul>
  \BLOCK{endfor}

</body>

latex.template

\documentclass[letterpaper,11pt]{article}
\begin{document}
\begin{center}
    \textbf{\Huge \scshape \color{TextColor} \VAR{resume['name']}} \\ \vspace{1pt}
    \small \VAR{resume['contact']['phone']} $|$ \href{mailto:\VAR{resume['contact']['email']}}{\VAR{resume['contact']['email']}} $|$
    \href{https://\VAR{resume['contact']['linkedin']}}{\VAR{resume['contact']['linkedin']}}
\end{center}
\begin{itemize}
    \BLOCK{for item in exp['summary']}
    \item {\VAR{item}}
    \BLOCK{endfor}
\end{itemize}
\end{document}

Makefile

.PHONY: jake anon html image

all: pdf html

pdf:
	python generate.py -t pdf -j latex.template -o resume_kishore.tex
	pdflatex resume_kishore.tex

html:
	python generate.py -t html -j html.template -o resume_kishore.html

The benefits I can see in this approach is the use of python like syntax directly in the templating. Additionally the tempaltes are separated from the content.

Now I can make sure that I maintain my resume in plaintext and at the same time export it to different formats with a templating engine without worrying about a middle layer with customised exports. My process is finally(?) simplified.

If you would like to leave a comment, contact me via email.
Post 16/99 - part of 100DaystoOffload