davideisinger.com

My personal website
Log | Files | Refs | README

sylvaindurand-org-jylksq.txt (4758B)


      1 [1]sylvain durand
      2 
      3 Gemini and Hugo
      4 
      5 2020-12-04
      6 
      7 For a few years, I have been using Hugo, a static site generator, to produce
      8 these pages. At the same time very fast and corresponding perfectly to my
      9 needs, it is above all very modular.
     10 
     11 I was therefore not surprised to see that it was quite easy to convert, with
     12 little effort, my site for the Gemini protocol. This was not done without some
     13 tricks. Let’s see how!
     14 
     15 Declaring Gemini as an output format
     16 
     17 Hugo can output content in multiple formats: most of them are already
     18 predefined, but it is also possible to create your own. This is what we are
     19 going to do for Gemini.
     20 
     21 First, in the configuration file config.yml we will declare a new type text/
     22 gemini with the file suffix .gmi:
     23 
     24 mediaTypes:
     25   text/gemini:
     26     suffixes:
     27       - "gmi"
     28 
     29 Once this is done, we declare a new output format, which uses this type, which
     30 is given the name GEMINI.
     31 
     32 outputFormats:
     33   GEMINI:
     34     name: GEMINI
     35     isPlainText: true
     36     isHTML: false
     37     mediaType: text/gemini
     38     protocol: "gemini://"
     39     permalinkable: true
     40 
     41 Finally, it only remains to ask Hugo to generate pages for the different
     42 contents. For example, in my case:
     43 
     44 outputs:
     45   home: ["HTML", "RSS", "GEMINI"]
     46   page: ["HTML", "GEMINI"]
     47 
     48 To be able to generate the files, it is now necessary to create layouts to see
     49 how to display them!
     50 
     51 Index page
     52 
     53 To start with the index, we can start with layout/index.gmi. For example, here
     54 is a simple text, followed by a list of posts:
     55 
     56 ## List of posts
     57 
     58 {{ range .RegularPages }}
     59 => {{ .RelPermalink }} {{ .Title }}
     60 {{- end }}
     61 
     62 Here, I sort the articles in descending chronological order, grouping them by
     63 date. This gives the following code:
     64 
     65 ## Posts grouped by year
     66 
     67 {{ range .RegularPages.GroupByDate "2006" }}
     68 ### {{ .Key }}
     69 {{ range .Pages.ByDate.Reverse }}
     70 => {{ .RelPermalink }} {{ .Title }}
     71 {{- end }}
     72 {{ end }}
     73 
     74 Posts
     75 
     76 For posts, we can create a layout/_default/single.gmi. Basically, it would
     77 suffice to display the title and content:
     78 
     79 # {{ .Title }}
     80 
     81 {{ .RawContent }}
     82 
     83 Images
     84 
     85 For images, I extract them with a simple regex and show them as a link:
     86 
     87 {{- $content := .RawContent -}}
     88 {{- $content = $content | replaceRE `\!\[(.+?)\]\((.+?)\)` "=> $2 Image: $1" }}
     89 {{ $content }}
     90 
     91 Links
     92 
     93 For the links, I decided to simply not use inline links on the site, but only
     94 put the links on a single paragraph. This allows me, as before, a very simple
     95 regex:
     96 
     97 {{- range findRE `\[.+?\]\(.+?\)` $content }}
     98     {{- $content = $content | replaceRE `\[(.+?)\]\((.+?)\)(.+)` "$1$3\n\n=> $2 $1 " }}
     99 {{- end }}
    100 
    101 However, this is not a very satisfactory method when you have a site that has a
    102 lot of links online. A solution, proposed by the site Brain Baking, allows you
    103 to reference each link with a number ([1], [2]…) and then to put the links
    104 underneath, automatically, thanks to a clever code from [2]Brainbaking.
    105 
    106 Navigation to other pages
    107 
    108 If you want to add links for previous and next articles with:
    109 
    110 {{ if .Next }}=> {{ .Next.RelPermalink }} ← Newer: {{ .Next.Title }}{{ end }}
    111 {{ if .Prev -}}=> {{ .Prev.RelPermalink }} → Older: {{ .Prev.Title }}{{- end }}
    112 
    113 Feeds
    114 
    115 To create RSS feeds, we can create a new output format, then define its layout.
    116 
    117 RSS
    118 
    119 We will do the same here! In config.yml, we define:
    120 
    121 outputFormats:
    122   GEMINI_RSS:
    123     baseName: "feed"
    124     mediaType: "application/rss+xml"
    125     isPlainText: false
    126 
    127 outputs:
    128   home: ["HTML", "GEMINI", ..., "GEMINI_RSS"]
    129 
    130 Then, we create layouts/index.gemini_rss.xml with the following content:
    131 
    132 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    133   <channel>
    134     <title>{{ .Site.Title }}</title>
    135     <description>{{ i18n "description" }}</description>
    136     <link>{{ (replace .Permalink "https://" "gemini://") | safeURL }}</link>
    137     <atom:link href="{{ .Permalink | safeURL }}feed.xml" rel="self" type="application/rss+xml" />
    138     {{- range .RegularPages }}
    139     <item>
    140       <title>{{ .Title }}</title>
    141       <link>{{ (replace .Permalink "https://" "gemini://") | safeURL }}</link>
    142       <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
    143       <guid>{{ (replace .Permalink "https://" "gemini://") | safeURL }}</guid>
    144     </item>
    145     {{ end }}
    146   </channel>
    147 </rss>
    148 
    149 The RSS feed is now available on /feed.xml.
    150 
    151 Export
    152 
    153 I use rsync to easily export my files to the server:
    154 
    155 hugo
    156 
    157 rsync -avz --no-perms --no-owner --no-group \
    158       --no-times --delete public/ vps:/var/gemini
    159 
    160 rm -rf public
    161 
    162 This last folder is then read by a gemini server, as explained in the previous
    163 article “[3]Discovering the Gemini protocol”.
    164 
    165 
    166 References:
    167 
    168 [1] https://sylvaindurand.org/
    169 [2] https://brainbaking.com/post/2021/04/using-hugo-to-launch-a-gemini-capsule/
    170 [3] https://sylvaindurand.org/discovering-the-gemini-protocol/