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/