Repository: gohugoio/hugo (language: go)

Issue:
Change images.QR(opts) to images.QR(text, opts)
I do understand that I argued differently days ago, but I'm doing some test work in that package and this is in line with other funcs:

```
images.Text "Hugo Rocks!" $textOpts )
```

And it makes sense to separate the "options" so they can be reused/stored in config etc.



Discussion / hints:
I'd be happy to take this one if you'd like.

Fix patch:
diff --git a/docs/content/en/functions/images/QR.md b/docs/content/en/functions/images/QR.md
index c1b8fb4657f..9d58e716394 100644
--- a/docs/content/en/functions/images/QR.md
+++ b/docs/content/en/functions/images/QR.md
@@ -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 }}
 ```
diff --git a/tpl/images/images.go b/tpl/images/images.go
index 106c2b2800f..6296a721445 100644
--- a/tpl/images/images.go
+++ b/tpl/images/images.go
@@ -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
 				}
diff --git a/tpl/tplimpl/embedded/templates/shortcodes/qr.html b/tpl/tplimpl/embedded/templates/shortcodes/qr.html
index cae7e56705b..252ebeae7a7 100644
--- a/tpl/tplimpl/embedded/templates/shortcodes/qr.html
+++ b/tpl/tplimpl/embedded/templates/shortcodes/qr.html
@@ -64,8 +64,8 @@
 
 {{- /* 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 }}


Test patch:
diff --git a/tpl/images/images_integration_test.go b/tpl/images/images_integration_test.go
index 0f89dbe0954..2847128e1f4 100644
--- a/tpl/images/images_integration_test.go
+++ b/tpl/images/images_integration_test.go
@@ -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")
diff --git a/tpl/tplimpl/tplimpl_integration_test.go b/tpl/tplimpl/tplimpl_integration_test.go
index 04abb5b31cb..8088a0551c1 100644
--- a/tpl/tplimpl/tplimpl_integration_test.go
+++ b/tpl/tplimpl/tplimpl_integration_test.go
@@ -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">`,
 	)
 }