From d69061c72c8ea4c3d88ba54299118034ed38c2f2 Mon Sep 17 00:00:00 2001 From: Floren Munteanu <19806136+fmunteanu@users.noreply.github.com> Date: Mon, 23 Feb 2026 21:01:55 -0500 Subject: [PATCH 01/10] feat: plyr media support --- assets/css/components/media.css | 3 + assets/css/styles.css | 1 + docs/content/docs/guide/shortcodes/media.md | 101 ++++++++++++++++++++ layouts/_partials/scripts.html | 5 + layouts/_partials/scripts/plyr.html | 85 ++++++++++++++++ layouts/_partials/shortcodes/media.html | 23 +++++ layouts/_shortcodes/media.html | 54 +++++++++++ 7 files changed, 272 insertions(+) create mode 100644 assets/css/components/media.css create mode 100644 docs/content/docs/guide/shortcodes/media.md create mode 100644 layouts/_partials/scripts/plyr.html create mode 100644 layouts/_partials/shortcodes/media.html create mode 100644 layouts/_shortcodes/media.html diff --git a/assets/css/components/media.css b/assets/css/components/media.css new file mode 100644 index 00000000..8851215d --- /dev/null +++ b/assets/css/components/media.css @@ -0,0 +1,3 @@ +.content .plyr { + @apply hx:mx-auto hx:my-6 hx:rounded-md hx:overflow-hidden; +} diff --git a/assets/css/styles.css b/assets/css/styles.css index bafd9dfc..fa5c55b0 100644 --- a/assets/css/styles.css +++ b/assets/css/styles.css @@ -89,3 +89,4 @@ body { @import "./components/badge.css"; @import "./components/toc.css"; @import "./components/archives.css"; +@import "./components/media.css"; diff --git a/docs/content/docs/guide/shortcodes/media.md b/docs/content/docs/guide/shortcodes/media.md new file mode 100644 index 00000000..2ed76b98 --- /dev/null +++ b/docs/content/docs/guide/shortcodes/media.md @@ -0,0 +1,101 @@ +--- +title: "Media Player Component" +linktitle: "Media Player" +sidebar: + exclude: true +--- + +## Overview + +The media shortcode allows you to embed media using the [Plyr](https://plyr.io/) player in your Hugo site. It supports HTML5 video, HTML5 audio, YouTube, and Vimeo with a polished, accessible player interface. + +## Basic Usage + +### Local Files + +Place your media files in the `static/` directory: + +``` +your-site/ +├── static/ +│ └── media/ +│ ├── demo.mp4 +│ └── podcast.mp3 +└── content/ + └── my-page.md +``` + +Video: + +```markdown +{{< media src="media/demo.mp4" >}} +``` + +Audio: + +```markdown +{{< media src="media/podcast.mp3" type="audio" >}} +``` + +### YouTube + +Embed a YouTube video using its video ID: + +```markdown +{{< media src="bTqVqk7FSmY" provider="youtube" >}} +``` + +### Vimeo + +Embed a Vimeo video using its video ID: + +```markdown +{{< media src="76979871" provider="vimeo" >}} +``` + +## Advanced Usage + +Here's an example with all available parameters: + +```markdown +{{< media + src="media/demo.mp4" + poster="media/poster.jpg" + autoplay="true" + muted="true" + loop="true" +>}} +``` + +## Parameters + +| Parameter | Type | Default | Description | +| ---------- | ------- | --------- | ------------------------------------------------------------- | +| `src` | string | - | The source URL, path, or embed ID (required) | +| `provider` | string | `""` | The media provider: `"youtube"`, `"vimeo"`, or omit for HTML5 | +| `type` | string | `"video"` | The media type: `"video"` or `"audio"` | +| `autoplay` | boolean | `false` | Start playing automatically | +| `muted` | boolean | `false` | Mute the media | +| `loop` | boolean | `false` | Loop the media | +| `poster` | string | `""` | The poster image URL (HTML5 video only) | + +## Configuration + +By default, Plyr assets are loaded from the official CDN. You can customize the asset source in your site configuration: + +```yaml +params: + plyr: + base: "https://cdn.jsdelivr.net/npm/plyr@latest/dist" # Custom CDN base URL + css: "plyr.css" # Custom CSS file path + js: "plyr.polyfilled.js" # Custom JS file path +``` + +To use local assets, set `js` and/or `css` without `base`: + +```yaml +params: + plyr: + css: "css/plyr.css" # Path relative to assets/ + js: "js/plyr.polyfilled.js" # Path relative to assets/ +``` diff --git a/layouts/_partials/scripts.html b/layouts/_partials/scripts.html index abf6cd47..e184482a 100644 --- a/layouts/_partials/scripts.html +++ b/layouts/_partials/scripts.html @@ -18,3 +18,8 @@ {{- if (.Store.Get "hasImageZoom") -}} {{- partial "scripts/medium-zoom.html" . -}} {{- end -}} + +{{/* Plyr */}} +{{- if (.Store.Get "hasPlyr") -}} + {{- partial "scripts/plyr.html" . -}} +{{- end -}} diff --git a/layouts/_partials/scripts/plyr.html b/layouts/_partials/scripts/plyr.html new file mode 100644 index 00000000..2471cc77 --- /dev/null +++ b/layouts/_partials/scripts/plyr.html @@ -0,0 +1,85 @@ +{{- /* Plyr */ -}} + +{{- $plyrBase := "" -}} +{{- $useDefaultCdn := true -}} +{{- with site.Params.plyr.base -}} + {{- $plyrBase = . -}} + {{- $useDefaultCdn = false -}} +{{- end -}} + +{{- $plyrJsAsset := "" -}} +{{- with site.Params.plyr.js -}} + {{- $plyrJsAsset = . -}} +{{- end -}} + +{{- $plyrCssAsset := "" -}} +{{- with site.Params.plyr.css -}} + {{- $plyrCssAsset = . -}} +{{- end -}} + +{{- /* If only js/css is set without base, use local asset loading */ -}} +{{- if and $useDefaultCdn (or (ne $plyrJsAsset "") (ne $plyrCssAsset "")) -}} + {{- $useDefaultCdn = false -}} +{{- end -}} + +{{- /* Set default CDN base if needed */ -}} +{{- if $useDefaultCdn -}} + {{- $plyrBase = "https://cdn.jsdelivr.net/npm/plyr@latest/dist" -}} +{{- end -}} + +{{- $isRemoteBase := or (strings.HasPrefix $plyrBase "http://") (strings.HasPrefix $plyrBase "https://") -}} +{{- $minSuffix := cond hugo.IsProduction ".min" "" -}} + +{{- /* CSS retrieval */ -}} +{{- if $isRemoteBase -}} + {{- $cssPath := cond (ne $plyrCssAsset "") $plyrCssAsset "plyr.css" -}} + {{- $plyrCssUrl := printf "%s/%s" $plyrBase $cssPath -}} + {{- with try (resources.GetRemote $plyrCssUrl) -}} + {{- with .Err -}} + {{- errorf "Could not retrieve Plyr css file from %s. Reason: %s." $plyrCssUrl . -}} + {{- else with .Value -}} + {{- with resources.Copy "css/plyr.css" . -}} + {{- $plyrCss := . | fingerprint -}} + + {{- end -}} + {{- end -}} + {{- end -}} +{{- else if $plyrCssAsset -}} + {{- with resources.Get $plyrCssAsset -}} + {{- $plyrCss := . | fingerprint -}} + + {{- else -}} + {{- errorf "Plyr css asset not found at %q" $plyrCssAsset -}} + {{- end -}} +{{- end -}} + +{{- /* JS retrieval */ -}} +{{- if $isRemoteBase -}} + {{- $jsPath := cond (ne $plyrJsAsset "") $plyrJsAsset (printf "plyr.polyfilled%s.js" $minSuffix) -}} + {{- $plyrJsUrl := printf "%s/%s" $plyrBase $jsPath -}} + {{- with try (resources.GetRemote $plyrJsUrl) -}} + {{- with .Err -}} + {{- errorf "Could not retrieve Plyr js file from %s. Reason: %s." $plyrJsUrl . -}} + {{- else with .Value -}} + {{- with resources.Copy (printf "js/plyr.polyfilled%s.js" $minSuffix) . -}} + {{- $plyrJs := . | fingerprint -}} + + {{- end -}} + {{- end -}} + {{- end -}} +{{- else if $plyrJsAsset -}} + {{- with resources.Get $plyrJsAsset -}} + {{- $plyrJs := . | fingerprint -}} + + {{- else -}} + {{- errorf "Plyr js asset not found at %q" $plyrJsAsset -}} + {{- end -}} +{{- end -}} + + diff --git a/layouts/_partials/shortcodes/media.html b/layouts/_partials/shortcodes/media.html new file mode 100644 index 00000000..dcd67fad --- /dev/null +++ b/layouts/_partials/shortcodes/media.html @@ -0,0 +1,23 @@ +{{- /* Plyr partial: renders HTML5 audio, HTML5 video, Vimeo, or YouTube */ -}} +