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"
---
(the key here is that the 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:

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"
---
then those first lines in the template generate the variables:

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 }}).

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.

Subscribe

Want to get an email when a new post is added? If so, subscribe here.