Creating This Blog Part 4: Adding a TikZ Gallery
Tags: Blog Setup , Hugo , Multilingual i18n , Tikz
TikZ is a programing language for creating images based on LaTeX. One writes TikZ “programing code” in a plain text file, and gets as output a pdf image file. The TikZ programming language was thought out to enable the code for a figure to be surprisingly human-readable. What I mean by this is that the reader can imagine the figure from the code because it looks like “drawing instructions for a human” instead of a bunch of obscure commands with lots hard to imagine numbers and coordinates. When carefully crafted, the TikZ code for an image can also be very easy to adjust to produce different images.
Developing clear, human-readable, and flexible TikZ code is art I cherish and practice. I really enjoy looking at well thought out, readable code, specially when displayed next to the image it creates (be it my code, or someone else’s).
I have wanted to create a system in this blog to display TikZ code for figures alongside the actual figures themselves, but had been holding off because I wanted an efficient setup that did not involve manually creating separate pages for each figure. Duplicating content goes against my belief in avoiding unnecessary repetition, which makes maintaining the content much more difficult, as any changes have to be replicated multiple times.
Well, I finally figured out a way to do this! See the new Tikz-gallery in the sidebar of this blog. It is automatically generated from the source image files. Each gallery entry also includes a list of the blog posts where it appears, all generated automatically.
I explain the setup for this automated gallery in detail in this blog post. You can read more about how I have set up this blog in these these blog posts.
How the system works right now
Here is an example to illustrate how the automated Tikz gallery works.
Below is a pretty Tikz image I made in 2020 (it is a schematic figure of the projective space $\mathbb{P}^3$, but that is the content of another future post):
To be able to include this image in this post, I already have the following files:
- The Tikz source file
3DProyectiveCoords.tex
. This is a tiny file with the “programing code” to generate the image. - The pdf vector graphics file 3DProyectiveCoords.pdf which is what LaTeX generates when one compiles the Tikz source file.
- A web-friendly png file 3DProyectiveCoords.png (the one that is being displayed above) that I created with Image Magick out of the pdf (see this related blog post).
To add this image to the Tikz gallery, all I have to do is create a new file (say 3DProyectiveCoords.md
) with this simple content:
---
source: "3DProyectiveCoords"
---
source:
attribute points to 3DProyectiveCoords
which is the name of the source code .tex
file, but without the .tex
extension)
Then I place this new tiny file in the tikz-gallery
folder that lives next to the folder with all the regular post entry files:
content
├── posts
| ├── ... <-- where all the regular blog post texts are placed.
| └── ...
└── tikz-gallery
└── 3DProyectiveCoords.md <-- new Tikz-gallery entry file here
That’s it! Hugo takes this tiny file and automatically:
- Adds it to the Tikz Gallery list with a thumbnail
- Creates an HTML page for the image in which it:
- displays the png of the image
- displays the LaTeX code that produced the image with syntax highlighting
- makes a link to download the vector graphic pdf version of the image
- lists all the blog posts in which the image appears
No content duplication, no copy pasting of source, no repetitive creation of pages in which the only thing that changes is a filename… just as it should be!
For the above example image, here is:
- the automatically generated page for the image
- how it shows up in the automatically generated Tikz-gallery
If there is a Spanish version of the image (say, in this case, named 3DProyectiveCoords.es
), then I just create the corresponding file 3DProyectiveCoords.es.md
with the contents
---
source: "3DProyectiveCoords.es"
---
and everything just works!
The pieces of the system
This is all set up using Hugo, the system that I use to create this blog. These are all the pieces that go into making the system work:
- Hugo Template for a page to display one Tikz image: in the file
layouts/tikz-gallery/single.html
- Hugo Template for the page that shows the full gallery (list of thumbnails): in the file
layouts/tikz-gallery/single.html
- Add an entry to the sidebar menu for the Galley by adjusting the Hugo configuration file
- Adjust the multilingual dictionary for all the headings and common texts that need Spanish and English versions.
In what follows, I explain the details for each piece. I’ll start with the multilingual setup since it makes the code for the templates easier to understand.
Multilingual texts for the templates
To have the templates work both in Spanish and English one needs to set up multilingual text “snippets”. For example, to get a title that says “Tikz Code Viewer” in English and “Visualizador de Tikz” in Spanish, one can define a text snippet (which I decided to call tikz-gallery-single-title
) and then have the title in the template be
<h1>{{ i18n "tikz-gallery-single-title"}}</h1>
Here, the code {{ i18n "tikz-gallery-single-title"}}
gets replaced by the right text in Spanish or English. This avoids needing to create separate template files for each language (again, the principle of avoiding unnecessary duplication). You can read more about this in this
other post in which I explain how that whole multilingual system is set up.
Template for a page to display one Tikz image together with its source code
The template file is placed here:
layouts
├── default
| ├── ...
| └── ...
├── partials
| ├── ...
| └── ...
├── shortcodes
| ├── ...
| └── ...
└── tikz-gallery
└── single.html <-- Template file here
This is the content of the single.html
template file. I explain below what some key pieces in this template file do.
{{ define "main" -}}
{{ $source := .Params.source }}
{{ $sourceFile := (print $source ".tex") }}
{{ $sourceFileWithPath := (print "static/" $source ".tex") }}
{{ $imageFile := (print $source ".png") }}
{{ $pdfFile := (print $source ".pdf") }}
<div class="tikz-gallery-entry">
<h1>{{ i18n "tikz-gallery-single-title" }} </h1>
<image src="{{ $imageFile }}" />
<h3>{{ i18n "tikz-gallery-source-code" }}</h3>
<p> {{ $sourceFile }} </p>
<!-- Load file contents -->
{{ $fileContents := readFile $sourceFileWithPath | safeHTML }}
<!-- Display code with latex syntax highligthing -->
{{ highlight $fileContents "latex" }}
<h3>{{ i18n "tikz-gallery-pdf-heading" }}</h3>
Download <a href="{{ $pdfFile }}">here</a>
<h3>{{ i18n "tikz-gallery-posts-where-appears" }}</h3>
<ul>
{{ range .Site.Pages }}
{{ if in .Content $source }}
<li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
{{ end }}
{{ end }}
</ul>
<div>
{{ .Content }}
</div>
</div>
{{ partial "footer.html" . }}
{{- end }}
Generation of variables with all the relevant filenames
Note first lines of the template:
{{ $source := .Params.source }}
{{ $sourceFile := (print $source ".tex") }}
{{ $sourceFileWithPath := (print "static/" $source ".tex") }}
{{ $imageFile := (print $source ".png") }}
{{ $pdfFile := (print $source ".pdf") }}
These lines generate all the filenames from the “source” property in the gallery file for that figure.
For example, if the image we are adding to the gallery is content/tikz-gallery/3DProyectiveCoords.md
and its contents are
---
source: "3DProyectiveCoords"
---
variable | value |
---|---|
$source | “3DProyectiveCoords” |
$sourceFile | “3DProyectiveCoords.tex” |
$sourceFileWithPath | “static/3DProyectiveCoords.tex” |
$imageFile | “3DProyectiveCoords.png” |
$pdfFile | “3DProyectiveCoords.pdf” |
With those filenames now stored in variables, the whole page for the image can be built easily and with very readable code.
Inserting the png image
The following piece of the template inserts the image 3DProyectiveCoords.png
in the webpage:
<image src="{{ $imageFile }}" />
This uses the $imageFile
variable that was created above.
Inserting the Tikz source
The following piece of the template displays the content of 3DProyectiveCoords.tex
using “latex” syntax highlighting. No manual copy-pasting involved!
<!-- Load file contents -->
{{ $fileContents := readFile $sourceFileWithPath | safeHTML }}
<!-- Display code with latex syntax highlighting -->
{{ highlight $fileContents "latex" }}
Listing all the post entries in which the image is included
This is probably the most interesting piece of the template in terms of automation:
<h3>{{ i18n "tikz-gallery-posts-where-appears" }}</h3>
<ul>
{{ range .Site.Pages }}
{{ if in .Content $source }}
<li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
{{ end }}
{{ end }}
</ul>
What it does: it lists all the post entries in which the image is included. It does this by
- looping over the blog post entries looking for the appearance of $source (this is what the
range
command does). - whenever it finds the string specified by the variable
$source
in a post entry, it lists (the<li>
) a link to the post (the<a>
) with link text equal to the post title (the{{ .Title }}
).
Template for the page that shows the list of thumbnails (the gallery)
This is the other template file. It is placed right next to the other one, but this one is called list.html
(this is standard Hugo setup – there always is a “list” layout and a “single” layout, corresponding to the list of blog posts and the posts themselves):
layouts
├── default
| ├── ...
| └── ...
├── partials
| ├── ...
| └── ...
├── shortcodes
| ├── ...
| └── ...
└── tikz-gallery
├── list.html <-- Template file here
└── single.html
Since this list.html
template is inside the layouts/tikz-gallery
folder, it works as a template to list the content placed in content/tikz-gallery
(a manifestation of the clever design of Hugo: the folder and file organization corresponds to functionality of the website).
Here is the list.html
template (is is simple compared to the single.html
template):
{{ define "main" -}}
<h1> {{ i18n "tikz-gallery-list-title" }} </h1>
<ul class="tikz-gallery">
{{ range .Data.Pages -}}
<!-- create the filename with .png extension -->
{{ $imageFile := (print .Params.source ".png") }}
<li>
<span>
<a href="{{ .Permalink }}">
{{ .Params.source }}
<image src="{{ $imageFile }}" width="350px" />
</a>
</span>
</li>
{{- end }}
</ul>
{{- end }}
This template just loops over the .Data.Pages
, which in this case are the files inside the content/tikz-gallery
folder, and generates a list (the <ul>
) in which each list entry (the <li>
) is a link (the <a>
) that points to the corresponding single-tikz
page with link text equal to {{ .Params.source }}
which is the image filename followed by the image (the <image>
) with a reduced width to make images display small.
Done!
Then galley of Tikz images is now automatically generated and easy to maintain!
More on Creating This Blog
See other posts under the Blog setup tag.