171 lines
4.6 KiB
Plaintext
171 lines
4.6 KiB
Plaintext
[1]sylvain durand
|
||
|
||
Gemini and Hugo
|
||
|
||
2020-12-04
|
||
|
||
For a few years, I have been using Hugo, a static site generator, to produce
|
||
these pages. At the same time very fast and corresponding perfectly to my
|
||
needs, it is above all very modular.
|
||
|
||
I was therefore not surprised to see that it was quite easy to convert, with
|
||
little effort, my site for the Gemini protocol. This was not done without some
|
||
tricks. Let’s see how!
|
||
|
||
Declaring Gemini as an output format
|
||
|
||
Hugo can output content in multiple formats: most of them are already
|
||
predefined, but it is also possible to create your own. This is what we are
|
||
going to do for Gemini.
|
||
|
||
First, in the configuration file config.yml we will declare a new type text/
|
||
gemini with the file suffix .gmi:
|
||
|
||
mediaTypes:
|
||
text/gemini:
|
||
suffixes:
|
||
- "gmi"
|
||
|
||
Once this is done, we declare a new output format, which uses this type, which
|
||
is given the name GEMINI.
|
||
|
||
outputFormats:
|
||
GEMINI:
|
||
name: GEMINI
|
||
isPlainText: true
|
||
isHTML: false
|
||
mediaType: text/gemini
|
||
protocol: "gemini://"
|
||
permalinkable: true
|
||
|
||
Finally, it only remains to ask Hugo to generate pages for the different
|
||
contents. For example, in my case:
|
||
|
||
outputs:
|
||
home: ["HTML", "RSS", "GEMINI"]
|
||
page: ["HTML", "GEMINI"]
|
||
|
||
To be able to generate the files, it is now necessary to create layouts to see
|
||
how to display them!
|
||
|
||
Index page
|
||
|
||
To start with the index, we can start with layout/index.gmi. For example, here
|
||
is a simple text, followed by a list of posts:
|
||
|
||
## List of posts
|
||
|
||
{{ range .RegularPages }}
|
||
=> {{ .RelPermalink }} {{ .Title }}
|
||
{{- end }}
|
||
|
||
Here, I sort the articles in descending chronological order, grouping them by
|
||
date. This gives the following code:
|
||
|
||
## Posts grouped by year
|
||
|
||
{{ range .RegularPages.GroupByDate "2006" }}
|
||
### {{ .Key }}
|
||
{{ range .Pages.ByDate.Reverse }}
|
||
=> {{ .RelPermalink }} {{ .Title }}
|
||
{{- end }}
|
||
{{ end }}
|
||
|
||
Posts
|
||
|
||
For posts, we can create a layout/_default/single.gmi. Basically, it would
|
||
suffice to display the title and content:
|
||
|
||
# {{ .Title }}
|
||
|
||
{{ .RawContent }}
|
||
|
||
Images
|
||
|
||
For images, I extract them with a simple regex and show them as a link:
|
||
|
||
{{- $content := .RawContent -}}
|
||
{{- $content = $content | replaceRE `\!\[(.+?)\]\((.+?)\)` "=> $2 Image: $1" }}
|
||
{{ $content }}
|
||
|
||
Links
|
||
|
||
For the links, I decided to simply not use inline links on the site, but only
|
||
put the links on a single paragraph. This allows me, as before, a very simple
|
||
regex:
|
||
|
||
{{- range findRE `\[.+?\]\(.+?\)` $content }}
|
||
{{- $content = $content | replaceRE `\[(.+?)\]\((.+?)\)(.+)` "$1$3\n\n=> $2 $1 " }}
|
||
{{- end }}
|
||
|
||
However, this is not a very satisfactory method when you have a site that has a
|
||
lot of links online. A solution, proposed by the site Brain Baking, allows you
|
||
to reference each link with a number ([1], [2]…) and then to put the links
|
||
underneath, automatically, thanks to a clever code from [2]Brainbaking.
|
||
|
||
Navigation to other pages
|
||
|
||
If you want to add links for previous and next articles with:
|
||
|
||
{{ if .Next }}=> {{ .Next.RelPermalink }} ← Newer: {{ .Next.Title }}{{ end }}
|
||
{{ if .Prev -}}=> {{ .Prev.RelPermalink }} → Older: {{ .Prev.Title }}{{- end }}
|
||
|
||
Feeds
|
||
|
||
To create RSS feeds, we can create a new output format, then define its layout.
|
||
|
||
RSS
|
||
|
||
We will do the same here! In config.yml, we define:
|
||
|
||
outputFormats:
|
||
GEMINI_RSS:
|
||
baseName: "feed"
|
||
mediaType: "application/rss+xml"
|
||
isPlainText: false
|
||
|
||
outputs:
|
||
home: ["HTML", "GEMINI", ..., "GEMINI_RSS"]
|
||
|
||
Then, we create layouts/index.gemini_rss.xml with the following content:
|
||
|
||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||
<channel>
|
||
<title>{{ .Site.Title }}</title>
|
||
<description>{{ i18n "description" }}</description>
|
||
<link>{{ (replace .Permalink "https://" "gemini://") | safeURL }}</link>
|
||
<atom:link href="{{ .Permalink | safeURL }}feed.xml" rel="self" type="application/rss+xml" />
|
||
{{- range .RegularPages }}
|
||
<item>
|
||
<title>{{ .Title }}</title>
|
||
<link>{{ (replace .Permalink "https://" "gemini://") | safeURL }}</link>
|
||
<pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
|
||
<guid>{{ (replace .Permalink "https://" "gemini://") | safeURL }}</guid>
|
||
</item>
|
||
{{ end }}
|
||
</channel>
|
||
</rss>
|
||
|
||
The RSS feed is now available on /feed.xml.
|
||
|
||
Export
|
||
|
||
I use rsync to easily export my files to the server:
|
||
|
||
hugo
|
||
|
||
rsync -avz --no-perms --no-owner --no-group \
|
||
--no-times --delete public/ vps:/var/gemini
|
||
|
||
rm -rf public
|
||
|
||
This last folder is then read by a gemini server, as explained in the previous
|
||
article “[3]Discovering the Gemini protocol”.
|
||
|
||
|
||
References:
|
||
|
||
[1] https://sylvaindurand.org/
|
||
[2] https://brainbaking.com/post/2021/04/using-hugo-to-launch-a-gemini-capsule/
|
||
[3] https://sylvaindurand.org/discovering-the-gemini-protocol/
|