tpl/images: Change signature of images.QR to images.QR TEXT OPTIONS

Closes #13230
This commit is contained in:
Joe Mooring 2025-01-08 10:10:18 -08:00 committed by Bjørn Erik Pedersen
parent d9594a96fc
commit b13d0a68e6
5 changed files with 42 additions and 35 deletions

View file

@ -6,7 +6,7 @@ action:
aliases: []
related: []
returnType: images.ImageResource
signatures: ['images.QR OPTIONS']
signatures: ['images.QR TEXT OPTIONS']
toc: true
math: true
---
@ -25,9 +25,6 @@ Although the default option values are sufficient for most applications, you sho
## Options
text
: (`string`) The text to encode.
level
: (`string`) The error correction level to use when encoding the text, one of `low`, `medium`, `quartile`, or `high`. Default is `medium`.
@ -51,8 +48,8 @@ targetDir
To create a QR code using the default values for `level` and `scale`:
```go-html-template
{{ $opts := dict "text" "https://gohugo.io" }}
{{ with images.QR $opts }}
{{ $text := "https://gohugo.io" }}
{{ with images.QR $text }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
{{ end }}
```
@ -62,13 +59,13 @@ To create a QR code using the default values for `level` and `scale`:
Specify `level`, `scale`, and `targetDir` as needed to achieve the desired result:
```go-html-template
{{ $text := "https://gohugo.io" }}
{{ $opts := dict
"text" "https://gohugo.io"
"level" "high"
"scale" 3
"targetDir" "codes"
}}
{{ with images.QR $opts }}
{{ with images.QR $text $opts }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
{{ end }}
```

View file

@ -135,14 +135,13 @@ var qrErrorCorrectionLevels = map[string]qr.Level{
// QR encodes the given text into a QR code using the specified options,
// returning an image resource.
func (ns *Namespace) QR(options any) (images.ImageResource, error) {
func (ns *Namespace) QR(args ...any) (images.ImageResource, error) {
const (
qrDefaultErrorCorrectionLevel = "medium"
qrDefaultScale = 4
)
opts := struct {
Text string // text to encode
Level string // error correction level; one of low, medium, quartile, or high
Scale int // number of image pixels per QR code module
TargetDir string // target directory relative to publishDir
@ -151,15 +150,26 @@ func (ns *Namespace) QR(options any) (images.ImageResource, error) {
Scale: qrDefaultScale,
}
err := mapstructure.WeakDecode(options, &opts)
if len(args) == 0 || len(args) > 2 {
return nil, errors.New("requires 1 or 2 arguments")
}
text, err := cast.ToStringE(args[0])
if err != nil {
return nil, err
}
if opts.Text == "" {
if text == "" {
return nil, errors.New("cannot encode an empty string")
}
if len(args) == 2 {
err := mapstructure.WeakDecode(args[1], &opts)
if err != nil {
return nil, err
}
}
level, ok := qrErrorCorrectionLevels[opts.Level]
if !ok {
return nil, errors.New("error correction level must be one of low, medium, quartile, or high")
@ -169,14 +179,14 @@ func (ns *Namespace) QR(options any) (images.ImageResource, error) {
return nil, errors.New("scale must be an integer greater than or equal to 2")
}
targetPath := path.Join(opts.TargetDir, fmt.Sprintf("qr_%s.png", hashing.HashStringHex(opts)))
targetPath := path.Join(opts.TargetDir, fmt.Sprintf("qr_%s.png", hashing.HashStringHex(text, opts)))
r, err := ns.createClient.FromOpts(
create.Options{
TargetPath: targetPath,
TargetPathHasHash: true,
CreateContent: func() (func() (hugio.ReadSeekCloser, error), error) {
code, err := qr.Encode(opts.Text, level)
code, err := qr.Encode(text, level)
if err != nil {
return nil, err
}

View file

@ -61,17 +61,17 @@ disableKinds = ['page','rss','section','sitemap','taxonomy','term']
-- layouts/index.html --
{{- $text := "https://gohugo.io" }}
{{- $optionMaps := slice
(dict "text" $text)
(dict "text" $text "level" "medium")
(dict "text" $text "level" "medium" "scale" 4)
(dict "text" $text "level" "low" "scale" 2)
(dict "text" $text "level" "medium" "scale" 3)
(dict "text" $text "level" "quartile" "scale" 5)
(dict "text" $text "level" "high" "scale" 6)
(dict "text" $text "level" "high" "scale" 6 "targetDir" "foo/bar")
(dict)
(dict "level" "medium")
(dict "level" "medium" "scale" 4)
(dict "level" "low" "scale" 2)
(dict "level" "medium" "scale" 3)
(dict "level" "quartile" "scale" 5)
(dict "level" "high" "scale" 6)
(dict "level" "high" "scale" 6 "targetDir" "foo/bar")
}}
{{- range $k, $opts := $optionMaps }}
{{- with images.QR $opts }}
{{- with images.QR $text $opts }}
<img data-id="{{ $k }}" data-img-hash="{{ .Content | hash.XxHash }}" data-level="{{ $opts.level }}" data-scale="{{ $opts.scale }}" data-targetDir="{{ $opts.targetDir }}" src="{{ .RelPermalink }}">
{{- end }}
{{- end }}
@ -79,14 +79,14 @@ disableKinds = ['page','rss','section','sitemap','taxonomy','term']
b := hugolib.Test(t, files)
b.AssertFileContent("public/index.html",
`<img data-id="0" data-img-hash="6ccacf8056c41475" data-level="" data-scale="" data-targetDir="" src="/qr_3601c357f288f47f.png">`,
`<img data-id="1" data-img-hash="6ccacf8056c41475" data-level="medium" data-scale="" data-targetDir="" src="/qr_3601c357f288f47f.png">`,
`<img data-id="2" data-img-hash="6ccacf8056c41475" data-level="medium" data-scale="4" data-targetDir="" src="/qr_3601c357f288f47f.png">`,
`<img data-id="3" data-img-hash="c29338c3d105b156" data-level="low" data-scale="2" data-targetDir="" src="/qr_232594637b3d9ac1.png">`,
`<img data-id="4" data-img-hash="8f7a639cea917b0e" data-level="medium" data-scale="3" data-targetDir="" src="/qr_5c02e7507f8e86e0.png">`,
`<img data-id="5" data-img-hash="2d15d6dcb861b5da" data-level="quartile" data-scale="5" data-targetDir="" src="/qr_c49dd961bcc47c06.png">`,
`<img data-id="6" data-img-hash="113c45f2c091bc4d" data-level="high" data-scale="6" data-targetDir="" src="/qr_17994d3244e3c686.png">`,
`<img data-id="7" data-img-hash="113c45f2c091bc4d" data-level="high" data-scale="6" data-targetDir="foo/bar" src="/foo/bar/qr_abd2f7b221eee6ea.png">`,
`<img data-id="0" data-img-hash="6ccacf8056c41475" data-level="" data-scale="" data-targetDir="" src="/qr_924bf7d80a564b23.png">`,
`<img data-id="1" data-img-hash="6ccacf8056c41475" data-level="medium" data-scale="" data-targetDir="" src="/qr_924bf7d80a564b23.png">`,
`<img data-id="2" data-img-hash="6ccacf8056c41475" data-level="medium" data-scale="4" data-targetDir="" src="/qr_924bf7d80a564b23.png">`,
`<img data-id="3" data-img-hash="c29338c3d105b156" data-level="low" data-scale="2" data-targetDir="" src="/qr_9bf1ce25c5f2c058.png">`,
`<img data-id="4" data-img-hash="8f7a639cea917b0e" data-level="medium" data-scale="3" data-targetDir="" src="/qr_7af14b329dd10af7.png">`,
`<img data-id="5" data-img-hash="2d15d6dcb861b5da" data-level="quartile" data-scale="5" data-targetDir="" src="/qr_9600ecb2010c2185.png">`,
`<img data-id="6" data-img-hash="113c45f2c091bc4d" data-level="high" data-scale="6" data-targetDir="" src="/qr_bdc74ee7f5c11cc6.png">`,
`<img data-id="7" data-img-hash="113c45f2c091bc4d" data-level="high" data-scale="6" data-targetDir="foo/bar" src="/foo/bar/qr_14162f02f2b83fff.png">`,
)
files = strings.ReplaceAll(files, "low", "foo")

View file

@ -64,8 +64,8 @@ Encodes the given text into a QR code using the specified options and renders th
{{- /* Render image. */}}
{{- if not $errors }}
{{- $opts := dict "text" $text "level" $level "scale" $scale "targetDir" $targetDir }}
{{- with images.QR $opts -}}
{{- $opts := dict "level" $level "scale" $scale "targetDir" $targetDir }}
{{- with images.QR $text $opts -}}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"
{{- with $alt }} alt="{{ $alt }}" {{- end }}
{{- with $class }} class="{{ $class }}" {{- end }}

View file

@ -730,7 +730,7 @@ https://gohugo.io"
b := hugolib.Test(t, files)
b.AssertFileContent("public/index.html",
`<img src="/codes/qr_1ad588024620edf6.png" width="148" height="148" alt="QR code linking to https://gohugo.io" class="my-class" id="my-id" title="My Title">`,
`<img src="/qr_7307530a297f2cc9.png" width="132" height="132">`,
`<img src="/codes/qr_be5d263c2671bcbd.png" width="148" height="148" alt="QR code linking to https://gohugo.io" class="my-class" id="my-id" title="My Title">`,
`<img src="/qr_472aab57ec7a6e3d.png" width="132" height="132">`,
)
}