Description
Depuis la version 0.141.0 de Hugo, le SSG est capable de gérer nativement la génération de QRCode.
Un shortcode par défaut est embarqué actuellement. Il est possible de le surcharger en écrivant un shortcode portant le même nom dans le répertoire layouts/_shortcodes.
La documentation est bien faite et vraiment rien de bien compliqué…
Fin de l’histoire ! Quoique…
Oui, mais… moi, je veux mon beau logo dans le QRCode !!!
Cliquez donc, sur le lien “Détails relatifs à l’article”, et… “oh, le joli QRCode que voilà !”
au cas où vous auriez raté ceux en page d’acceuil, on ne sait jamais, hein.
Cas concret
Je prends mon logo, et comme c’est une ressource globale dans mon contexte, je peux donc utiliser la fonction .Resize.
{{ $logo := resources.Get "images/logo.png" }}
Ensuite, il faut s’assurer que la ressource soit “travaillable”…
{{ with reflect.IsImageResourceProcessable $logo }}
{{ $height := int (mul $logo.Height 0.20) }}
{{ $width := int (mul $logo.Width 0.20) }}
{{ $mini = $logo.Resize (printf "%dx%d" $height $width) }}
{{ end }}
Les fonctions reflect ont commencé à être disponibles depuis la version 0.154.0, celle utilisée l’est depuis la v0.157.0. Cette dernière permet de s’assurer que l’objet Resource retourne une valeur permettant à Hugo d’extraire des données correspondantes et d’effectuer de futures opérations.
Dans ce cas, après m’être assurer que c’est bien une ressource utilisable, je “génère” une nouvelle ressource nommée mini qui a la douce particularité de ne faire que 20 % en largeur et hauteur de la ressource précédente, à savoir le logo.
Pourquoi 20 % ?
Les recommandations relatives à une image embarquée dans le QRCode semblent donner la fourchette entre 15 et 20 % d’occupation maximale dudit QRCode. Il est aussi nécessaire de préférer un niveau de correction d’erreurs le plus haut, soit high, ainsi que l’entier relatif au nombre de pixels supérieur ou égale à 3 - plus cet entier sera haut, plus le QRCode pesera en poids. Hugo par défaut utilise un niveau medium, et l’entier 4. Il nous faut donc fixer le niveau de corrections.
Ce qui est fait par l’usage d’un dictionnaire d’options adéquat :
{{ $opts := dict
"level" "high"
"scale" 4
"targetDir" "images/qr"
}}
Ce dictionnaire est fourni en argument de la fonction images.QR.
Concernant l’option targetDir, je vous renvoie à la documentation officielle, à un détail près : le futur QRCode généré ne sera pas une ressource globale, et c’est important de le comprendre, au cas où…
L’astuce suivante pour générer une mini, tel mon logo, dans le QRCode est d’utiliser la méthode de l’overlay pour créer un calque dessus le QRCode, futur (dé)généré.
Et, oui, il est nécessaire de bien faire attention aux valeurs utilisées, car sinon c’est la catastrophe, le QRCode sera inexploitable.
{{ with images.QR $txt $opts }}
{{ $x := div (sub .Width $mini.Width) 2 }}
{{ $y := div (sub .Height $mini.Height) 2 }}
{{ $qr := .Filter (images.Overlay $mini $x $y) }}
{{ return $qr }}
{{ end }}
Pour le bon positionnement de la mini en tant que calque, on soustrait la taille de la future mini à la taille du QRCode final, divisée par 2 ; ce qui permet de placer le calque enfermant la mini, au milieu du QRCode.
Reste plus qu’à appeler ce partiel correctement et à utiliser ses valeurs dans le code HTML final, tel que :
{{ with partial "utils/qr" (dict "link" .Permalink "title" .Title) }}
<figure>
<img class="qr" loading="lazy" height="{{ .Height }}" src="{{ .RelPermalink }}" width="{{ .Width }}">
</figure>
{{ end }}
Ahhh si un détail intéressant :
- pour l’instant, il n’est pas possible de fixer la taille du QRCode ; il dépend des ressources utilisées… ou alors, je n’ai pas compris le détail ad hoc.
Quoiqu’il en soit, pour que visuellement sur le site, les QRCodes affichés semble avoir la même taille, l’utilisation du code CSS suivant peut s’avérer utile :
.qr {
height: 128px;
image-rendering: pixelated;
width: 128px;
}
L’utilisation de la propriété CSS image-rendering est utile dans ce cas, où la pixelisation permet d’améliorer le rendu du QRCode, ainsi traité.
- pour l’instant, de même il semble ne pas être possible de générer de QRCode avec des couleurs…
Et, voilà !
TL;DR
Pour les explications, lisez l’article…
{{ $link := .link | safeURL }}
{{ $title := .title | htmlUnescape }}
{{ with site.Params.img.logo }}
{{ $logo := resources.Get (printf "%s/%s" (index site.Params.img.logo.dir 0) (index site.Params.img.logo.name 0)) }}
{{ $mini := "" }}
{{ with reflect.IsImageResourceProcessable $logo }}
{{ $height := int (mul $logo.Height 0.20) }}
{{ $width := int (mul $logo.Width 0.20) }}
{{ $mini = $logo.Resize (printf "%dx%d" $height $width) }}
{{ end }}
{{ with $logo }}
{{ $opts := dict
"level" "high"
"scale" 4
"targetDir" "images/qr"
}}
{{ $txt := printf "%s\n%s\n%s" site.Title $title $link }}
{{ with images.QR $txt $opts }}
{{ $x := div (sub .Width $mini.Width) 2 }}
{{ $y := div (sub .Height $mini.Height) 2 }}
{{ $qr := .Filter (images.Overlay $mini $x $y) }}
{{ return $qr }}
{{ end }}
{{ else }}
{{ warnf "Logo: Unable to get resource %q" . }}
{{ end }}
{{ end }}
Documentation
La documentation officielle :
- Hugo Documentation : Shortcodes > Qr
- Hugo Documentation : Functions images > Filter
- Hugo Documentation : Functions reflect > Isimageresource