%

Hugo : Gemini, Gopher… 'Quoi d'autres ?!'

Article publié, le et modifié le
9 minutes de lecture

Cet article contient 1800 mots.
Source brute de l'article :
Commit version : 719fd66

Description

Gemini et Gopher sont deux autres Internet, tout à fait légaux, dont le but est de la publication “légère” d’informations, principalement du texte. En fait, historiquement Gopher est né en 1991, en parallèle du Grand Net sur protocole HTTP ; tandis que Gemini est un protocole de communication récent, né courant juin 2019.

Tout comme le Grand Net sur HTTP(S), Gopher et Gemini ont leur propre protocole de communication, portant leur propre nom :

  • Gemini : gemini://
  • Gopher : gopher://

À savoir que le protocole gemini est basé sur TLS directement… De plus, bien que ces protocoles soient cloisonnés entre eux, en effet les protocoles Gemini, Gopher et HTTP(S) sont des réseaux différents, par des services différents, sur des ports différents, il existe des passerelles du côté de Gemini et Gopher, vers HTTP(S).

Ne cherchez pas toutes les fioritures que permet le protocole HTTP(S), exit les scripts CSS, JS, voire les images, avec Gemini et Gopher, on se concentre principalement sur la ressource importante : le texte. cf : cherchez Low Web ;-)


Comment modifier Hugo pour lui faire générer des fichiers à publier sur les protocoles Gemini, et Gopher ?

Dans les faits, vous prendrez plus de temps à lire cet article, qu’à faire vos modifications basiques, qui sont possibles d’être faites en moins de 5 minutes !!!

Il y a(ura) certainements de petites modifications à apporter… mais l’esprit de l’article est là, et fonctionnel. ;-)

Attention

Gemini

Concernant les modifications pour Gemini, voici le propos :

Configuration pour Gemini

Modifions très simplement le fichier de configuration de Hugo config.toml :

Configuration Gemini : ajout du mimetype

# Gemini
[mediaTypes."text/gemini"]
	suffixes = ["gmi"]

Configuration Gemini : ajout du format de sortie

# Gemini
[outputFormats.Gemini]
	isPlainText = true
	isHTML = false
	mediaType = "text/gemini"
	name = "gemini"
	path = "gemini/"
	permalinkable = true
	protocol = "gemini://"

Remarquons que la publication des fichiers gmi auront lieu dans un répertoire distinct, nommé gemini, dans le répertoire public/. Ce seront de purs fichiers texte, ayant l’extension .gmi.


Puis dans la configuration de la sortie, par exemple :

[outputs]
	home = ["HTML", "gemini", ]
	page = ["HTML", "gemini", ]

Bien sûr, ne pas utiliser les ‘…’ dans votre configuration ; ici, ils expriment les autres options de génération possible, sans les nommer !


Gemini est capable de lire des fichiers au format RSS, ce qui nous permet de générer un flux RSS ; ajoutons un nouveau format de sortie spécifique :

[outputFormats.GeminiRSS]
	isHTML = false	
	mediaType = "application/rss+xml"
	name = "GeminiRSS"
	protocol = "gemini://"
	path = "gemini/"

et modifions la génération de sortie, tel que par exemple :

[outputs]
	home = ["HTML", "gemini", "GeminiRSS", ]

Layouts pour Gemini

index.gmi

Ajoutons un fichier index.gmi dans le repertoire layouts/, qui pour l’exemple aura le code hugo basique suivant :

{{ range .Paginator.Pages }}
{{- if .OutputFormats.Get "gemini" }}
⇒ {{ replace .Permalink "/gemini" "" 1 }} {{ .Date.Format "January 2, 2006" }}: {{ .Title | safeHTML }}{{ end }}{{ end }}

Libre à vous de modifier, améliorer la pertinence du code Hugo pour obtenir le contenu que vous désirez publier…


index.geminirss.xml

Si vous désirez gérez un flux RSS pour Gemini, selon la configuration ci-dessus, ajoutons un fichier index.geminirss.xml, ayant le contenu de génération tel que :

{{- $pctx := . -}}
{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
{{- $pages := slice -}}
{{- if or $.IsHome $.IsSection -}}
{{- $pages = $pctx.RegularPages -}}
{{- else -}}
{{- $pages = $pctx.Pages -}}
{{- end -}}
{{- $limit := .Site.Config.Services.RSS.Limit -}}
{{- if ge $limit 1 -}}
{{- $pages = $pages | first $limit -}}
{{- end -}}
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>{{ .Site.Title | safeHTML }}</title>
    <link>{{ replace .Permalink "https" "gemini" 1 }}</link>
    <description>{{ .Site.Params.siteDescription | safeHTML }}</description>
    <generator>Hugo {{ hugo.Version }}  gohugo.io</generator>{{ with .Site.LanguageCode }}
    <language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
    <managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
    <webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
    <copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
    <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
    {{ with .OutputFormats.Get "RSS" }}
      {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
    {{ end }}
    {{ range $pages }}
    {{- if .OutputFormats.Get "gemini" -}}
    <item>
      <title>{{ .Title | safeHTML }}</title>
      {{ with .OutputFormats.Get "gemini" }}
      <link>{{replace .Permalink "/gemini" "" 1}}</link>
      {{ end }}
      <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
      {{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
      {{ with .OutputFormats.Get "gemini" }}
      <guid>{{replace .Permalink "/gemini" "" 1}}</guid>
      {{ end }}
    </item>
    {{- end -}}
    {{ end }}
  </channel>
</rss>

single.gmi

Dans le répertoire enfant _default du sous répertoire layouts/, ajoutons un simple fichier single.gmi qui s’occupera principalement de la génération des pages :

# {{ $.Title | safeHTML }}

{{ .RawContent }}

C’est basique ; ca fait le boulot, simplement. Là encore libre à vous de modifier, ajouter votre code Hugo, pour générer plus proprement afin de débarrasser du code Markdown, par exemple :

{{ $scratch := newScratch }}
{{ $content := .RawContent -}}
{{ $content := $content | replaceRE `#### ` "### " -}}
{{ $content := $content | replaceRE `\n- (.+?)` "\n* $1" -}}
{{ $content := $content | replaceRE `\n(\d+). (.+?)` "\n* $2" -}}
{{ $content := $content | replaceRE `\[\^(.+?)\]:?` "" -}}
{{ $content := $content | replaceRE `<br/??>` "\n" -}}
{{ $content := $content | replaceRE `<a .*href="(.+?)".*>(.+?)</a>` "[$2]($1)" -}}
{{ $content := $content | replaceRE `\sgemini://(\S*)` " [gemini://$1](gemini://$1)" -}}
{{ $content := $content | replaceRE "([^`])<.*?>([^`])" "$1$2" -}}
{{ $content := $content | replaceRE `\n\n!\[.*\]\((.+?) \"(.+?)\"\)` "\n\n=> $1 Image: $2" -}}
{{ $content := $content | replaceRE `\n\n!\[.*]\((.+?)\)` "\n\n=> $1 Embedded Image: $1" -}}
{{ $links := findRE `\n=> ` $content }}{{ $scratch.Set "ref" (add (len $links) 1) }}
{{ $refs := findRE `\[.+?\]\(.+?\)` $content }}
{{ $scratch.Set "content" $content }}{{ range $refs }}{{ $ref := $scratch.Get "ref" }}{{ $contentInLoop := $scratch.Get "content" }}{{ $url := (printf "%s #%d" . $ref) }}{{ $contentInLoop := replace $contentInLoop . $url -}}{{ $scratch.Set "content" $contentInLoop }}{{ $scratch.Set "ref" (add $ref 1) }}{{ end }}{{ $content := $scratch.Get "content" | replaceRE `\[(.+?)\]\((.+?)\) #(\d+)` "$1 [$3]" -}}
{{ $content | safeHTML }}

Explications :

Ce code - qui fait très bien son travail - est un copié-collé du code créé par un certain Wouter Groeneveld ; les explications sont fournies en anglais. N’ayant pas l’utilité de gérer des fichiers audio, vidéo, localement ou sur d’autres plateformes, j’ai simplement supprimé les lignes correspondantes.


Voilà (pour la partie Gemini) !

Il ne reste plus qu’à publier…

Gopher

Attaquons les modifications de configurations et de calques pour générer les fichiers textes pour Gopher. Là encore, nous générons les fichiers dans un répertoire dédié, nommé gopher dans le répertoire public/ afin de faciliter la synchronisation vers le serveur gopher…

Configuration pour Gopher

Modifions donc le fichier de configuration de Hugo, pour ajouter les formats de génération. En effet :

  • le premier va nous être utile pour la génération des pages, qui porteront le nom index, dans leur propre répertoire
  • le second pour générer les fichiers d’indexation gophermap

Tous auront l’extension de fichier .txt et seront publiés dans un sous-répertoire nommé gopher du répertoire public/.

[outputFormats.Gopher]
	baseName = "index"
	isPlainText = true
	isHTML = false
	mediaType = "text/plain"
	noUgly = false
	path = "gopher/"
	protocol = "gopher://"
	
[outputFormats.GopherMap]
	baseName = "gophermap"
	isPlainText = true
	isHTML = false
	mediaType = "text/plain"
	noUgly = false
	path = "gopher/"
	protocol = "gopher://"

Puis modifions la génération des sorties, tel que :

[outputs]
	home = ["HTML", "gemini", "GeminiRSS", "gophermap", ]
	page = ["HTML", "gemini", "gopher"]

Layouts pour Gopher

Attaquons la partie des fichiers à créer dans le sous-répertoire layouts/.

index.gophermap.txt

Restons simple :

{{ .Site.Title | safeHTML }}

⇒ Menu : 

{{ range .Site.Menus.main }}
{{- if (or (eq .Identifier "search") (eq .Identifier "lang-switcher") (eq .Identifier "theme-switcher") ) }}
{{- else }}
1{{ .Name }}	{{ .URL | safeURL }} 70
{{- end -}}
{{ end }}

⇒ Articles les plus récents : 
{{ $nb := 7 }}
{{ range first $nb .Paginator.Pages }}
0{{ .Title }}	{{ with .OutputFormats.Get "gopher" }}	{{ replaceRE "/gopher" "" .RelPermalink }} 70 {{ end }}
{{- end }}

Ce fichier gophermap nous permet de publier simplement l’équivalent du menu principal de Hugo, ainsi que promouvoir les x derniers articles. - ici, les 7 derniers -

Pour ceux qui n’auraient pas compris : les fichiers gophermap sont des fichiers d’indexation de contenu…

list.gophermap.txt

Ajoutons dans le répertoire enfant _default/ du sous-répertoire layout/, un fichier de génération de liste, qui peut avoir le contenu basique suivant :

!{{ .Title | safeHTML }}

{{ .RawContent }}

{{ range .Paginator.Pages }}
0{{ .Title }}	{{ with .OutputFormats.Get "gopher" -}}{{ .RelPermalink }}	{{ $.Site.Params.hostname}}	70 {{ end }}
{{ end }}

single.gopher.txt

Pour la génération des pages, ajoutons dans le même sous-répertoire _default/, un fichier nommé single.gopher.txt qui peut avoir le contenu basique suivant :

!{{ .Title | safeHTML }}

{{ .Date.Format (.Site.Params.dateform | default "01 January 2006") }} · {{ .ReadingTime }} minute(s) de lecture.
{{ if .Params.tags }}      
Tags :  {{ range .Params.tags }}{{ . }} {{ end }}
{{ end }}

---
      
{{ .RawContent }}

---

Publié le : {{.Date.Format "2 January 2006"}}.

0⇒ Revenir à la page d'accueil : / 70
h⇒ Lire l'article “{{ $.Title | safeHTML }}” sur le protocole HTTP(S) : {{ .Permalink | safeURL }} 443

Le contenu de ce site est diffusé sous Licence {{ $.Site.Copyright | safeHTML }}.

Encore une fois, à vous de modifier à votre convenance et autres imaginations nécessaires pour votre promotion…

Voilà (pour la partie Gopher) !

Il ne reste plus qu’à publier…

Documentations

Wikipedia

Remerciements

  • Drew Devault : un des premiers à modifier Hugo pour générer du contenu pour Gemini - voici son dépôt Git pour exemple !
  • Sylvain Durant : un parisien qui fait simple et dont je me suis inspiré pour la communauté “OpenBSD Pour Tous” : https://sylvaindurand.org/gemini-and-hugo/
  • le dépôt Git de la communauté “OpenBSD Pour Tous”, où vous retrouverez les modifications de génération pour gopher et gemini : https://tildegit.org/obsd4a/www