Repository: gohugoio/hugo (language: go)

Issue:
Vimeo Shortcode feature: lazy loading iframe
The YouTube shortcode template has a very useful option for adding `loading="lazy"` (https://gohugo.io/shortcodes/youtube/#loading) to the iframe.

I use this a lot, it's very helpful if you have a YouTube embed at the bottom of the page so it doesn't automatically begin downloading a lot of CSS/JS from youtube.com on page load improving performance and saving resources.

I'd really like to see this option also be added to the Vimeo shortcode too! Especially as Vimeo loads a LOT of JavaScript for its embeds.
https://gohugo.io/shortcodes/vimeo/


Discussion / hints:

Fix patch:
diff --git a/tpl/tplimpl/embedded/templates/shortcodes/vimeo.html b/tpl/tplimpl/embedded/templates/shortcodes/vimeo.html
index b3fc781a394..d1ec746bbc8 100644
--- a/tpl/tplimpl/embedded/templates/shortcodes/vimeo.html
+++ b/tpl/tplimpl/embedded/templates/shortcodes/vimeo.html
@@ -1,14 +1,52 @@
-{{- $pc := site.Config.Privacy.Vimeo -}}
-{{- if not $pc.Disable -}}
-{{- if $pc.Simple -}}
-{{ template "_internal/shortcodes/vimeo_simple.html" . }}
-{{- else -}}
-{{ if .IsNamedParams }}<div {{ if .Get "class" }}class="{{ .Get "class" }}"{{ else }}style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"{{ end }}>
-  <iframe src="https://player.vimeo.com/video/{{ .Get "id" }}{{- if $pc.EnableDNT -}}?dnt=1{{- end -}}" {{ if not (.Get "class") }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}{{ if .Get "title"}}title="{{ .Get "title" }}"{{ else }}title="vimeo video"{{ end }} webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
-</div>{{ else }}
-<div {{ if gt (len .Params) 1 }}class="{{ .Get 1 }}"{{ else }}style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"{{ end }}>
-  <iframe src="https://player.vimeo.com/video/{{ .Get 0 }}{{- if $pc.EnableDNT -}}?dnt=1{{- end -}}" {{ if len .Params | eq 1 }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}{{ if len .Params | eq 3 }}title="{{ .Get 2 }}"{{ else }}title="vimeo video"{{ end }} webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
-</div>
-{{ end }}
-{{- end -}}
-{{- end -}}
+{{- /*
+Renders an embedded Vimeo video.
+
+Accepts named or positional arguments. If positional, order is id, class,
+title, then loading.
+
+@param {string} [class] The class attribute of the wrapping div element. When specified, removes the style attributes from the iframe element and its wrapping div element.
+@param {string} [id] The video id. Optional if the id is provided as first positional argument.
+@param {string} [loading=eager] The loading attribute of the iframe element.
+@param {string} [title=Vimeo video] The title attribute of the iframe element.
+
+@returns {template.HTML}
+
+@example {{< vimeo 55073825 >}}
+@example {{< vimeo id=55073825 class="foo bar" loading=lazy title="My Video" >}}
+*/}}
+{{- $pc := site.Config.Privacy.Vimeo }}
+{{- if not $pc.Disable }}
+  {{- if $pc.Simple }}
+    {{- template "_internal/shortcodes/vimeo_simple.html" . }}
+  {{- else }}
+    {{- $id := or (.Get "id") (.Get 0) "" }}
+    {{- $class := or (.Get "class") (.Get 1) "" }}
+    {{- $title := or (.Get "title") (.Get 2) "Vimeo video" }}
+    {{- $loading := or (.Get "loading") (.Get 3) "eager" }}
+    {{- $dnt := cond $pc.EnableDNT 1 0 }}
+
+    {{- $divStyle := "position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;" }}
+    {{- $iframeStyle := "position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" }}
+
+    {{- with $id }}
+      {{- $src := printf "https://player.vimeo.com/video/%v?dnt=%v" . $dnt }}
+      <div
+        {{- with $class }}
+          class="{{ . }}"
+        {{- else }}
+          style="{{ $divStyle | safeCSS }}"
+        {{- end }}>
+        <iframe webkitallowfullscreen mozallowfullscreen allowfullscreen
+          src="{{- $src }}"
+          {{- if not $class }}
+            style="{{ $iframeStyle | safeCSS }}"
+          {{- end }}
+          {{- with $loading }} loading="{{ . }}" {{- end }}
+          {{- with $title }} title="{{ . }}" {{- end }}>
+        </iframe>
+      </div>
+    {{- else }}
+      {{- errorf "The %q shortcode requires a video id, either as the first positional argument or an argument named id. See %s" .Name .Position }}
+    {{- end }}
+  {{- end }}
+{{- end }}


Test patch:
diff --git a/tpl/tplimpl/shortcodes_integration_test.go b/tpl/tplimpl/shortcodes_integration_test.go
index d669bb33374..dd3cab88f51 100644
--- a/tpl/tplimpl/shortcodes_integration_test.go
+++ b/tpl/tplimpl/shortcodes_integration_test.go
@@ -478,12 +478,12 @@ Content: {{ .Content }}
 
 	// Regular mode
 	b := hugolib.Test(t, files)
-	b.AssertFileContent("public/index.html", "d5b2a079cc37d0ed")
+	b.AssertFileContent("public/index.html", "d1f592d2256ac3ff")
 
 	// Simple mode
 	files = strings.ReplaceAll(files, "privacy.vimeo.simple = false", "privacy.vimeo.simple = true")
 	b = hugolib.Test(t, files)
-	b.AssertFileContent("public/index.html", "73b8767ce8bdf694")
+	b.AssertFileContent("public/index.html", "c5bf16d87e2a370b")
 
 	// Simple mode with non-existent id
 	files = strings.ReplaceAll(files, "{{< vimeo 55073825 >}}", "{{< vimeo __id_does_not_exist__ >}}")