| Parameter | Required | Description |
|-----------|----------|-------------|
-| src | Yes | Path or URL to the image file |
-| alt | No | Alt text for accessibility |
+| src | Conditional | Path or URL to the image file (required unless inner content is provided) |
+| alt | No | Alt text for accessibility (default: "Image") |
| caption | No | Optional caption displayed below the image |
-| class | No | Custom CSS classes (default: "w-full h-auto rounded-lg border border-border/30"). Overrides all defaults when specified. |
+| class | No | CSS classes for the `<img>` element (default: "w-full h-auto rounded-lg border border-border"). Overrides all defaults when specified. |
+| link | No | URL to wrap the image in a clickable link |
+| figure-class | No | CSS classes applied to the outer `<figure>` element (e.g., for centering or custom layout) |
### Example
{{< image src="/images/mountain.jpg" alt="Mountain landscape" class="w-2/3 mx-auto rounded-lg shadow-lg border-2 border-accent" >}}
```
+With link:
+```
+{{< image src="/images/mountain.jpg" alt="Mountain landscape" link="https://github.com/example" caption="Click to view project" >}}
+```
+
+Centered image with figure-class:
+```
+{{< image src="/images/mountain.jpg" alt="Mountain landscape" caption="Alpine view" figure-class="text-center" >}}
+```
+
### Common CSS Classes for Image Sizing
Use Tailwind CSS utility classes to customize image appearance:
| Parameter | Required | Description |
|-----------|----------|-------------|
-| src | Yes | Path or URL to the video file (supports .webm, .mp4, .ogv) |
-| width | No | Video width (default: 100%, can be px or % values) |
-| height | No | Video height (default: auto) |
+| src | Conditional | Path or URL to the video file (required if `id` is not provided; supports .webm, .mp4, .ogv) |
+| id | Conditional | YouTube video ID (required if `src` is not provided; triggers YouTube embed mode) |
+| title | No | Descriptive title for accessibility (default: "Video"; used as iframe title attribute) |
+| width | No | Video width (default: 100%, can be px or % values; video mode only) |
+| height | No | Video height (default: auto; video mode only) |
| class | No | Custom CSS classes for styling |
-| autoplay | No | Set to "true" to autoplay (default: false) |
-| loop | No | Set to "true" for looping playback (default: false) |
-| muted | No | Set to "true" to mute by default (default: false) |
+| autoplay | No | Set to "true" to autoplay (default: false; video mode only) |
+| loop | No | Set to "true" for looping playback (default: false; video mode only) |
+| muted | No | Set to "true" to mute by default (default: false; video mode only) |
### Example
{{< video src="https://example.com/video.mp4" width="100%" >}}
```
+YouTube embed (recommended for privacy and performance):
+```
+{{< video id="dQw4w9WgXcQ" title="Example YouTube video" >}}
+```
+
+YouTube with custom sizing:
+```
+{{< video id="dQw4w9WgXcQ" title="Example YouTube video" class="max-w-2xl mx-auto" >}}
+```
+
### Page Bundle Videos
Videos stored in the same directory as your article's `index.md` are automatically resolved:
- **Tabs**: Tabbed content sections for organizing related information
- **Code**: Enhanced code blocks with syntax highlighting and line numbers
- **Audio**: Audio player for podcast episodes and sound files
-- **YouTube/Vimeo**: Privacy-friendly embedded video players
+
+## Deprecated Shortcodes
+
+The following shortcodes have been consolidated and are no longer available:
+
+| Deprecated | Replacement | Migration |
+|-----------|------------|-----------|
+| `{{< figure >}}` | `{{< image >}}` | Use `{{< image >}}` with the `figure-class` parameter for styling the figure element |
+| `{{< img >}}` | `{{< image >}}` | Directly replace with `{{< image >}}` and add proper `alt` text |
+| `{{< gal-img >}}` | Markdown syntax inside `{{< gallery >}}` | Replace `{{< gal-img ... >}}` calls with standard markdown: `` |
+| `{{< youtube ID >}}` | `{{< video id="ID" >}}` | Change `{{< youtube ID >}}` to `{{< video id="ID" title="Description" >}}` |
+
+### Why These Changes?
+
+The consolidation reduces maintenance overhead and provides better functionality:
+- **`image` shortcode** now supports all image display modes with flexible parameters
+- **`video` shortcode** unifies local video and YouTube embeds in one interface
+- **`gallery` shortcode** uses standard markdown image syntax for better clarity
+- **WCAG AA compliance** improved with required `title` attributes on YouTube iframes
## Accessibility Notes
# danix.xyz Week 6+ TODO List
+- [ ] Content review (correct post type, fix thumbnails, metadata, etc.)
- [✅] Related Articles widget in sidebar.
- [✅] social sharing sidebar widget
- [✅] titles redesign (mono font // Title)
- [✅] Sidebar widgets redesign (no box, mono font "# Title")
- [ ] Footer redesign (3-column, social badges, fortune cookie, tech badges, etc.)
+- [✅] related articles debug
- [ ] shortcodes cleanup (remove duplicates)
- [ ] Search functionality
- [ ] Open Graph meta tags for social sharing
image = "/uppies/2021/05/PXL_20210501_114542849.jpg"
categories = ["3D Printing", "diy"]
tags = ["3D printing", "cad", "cura", "fusion360", "slicer", "solvespace"]
+typora-root-url = "../../static"
+++
{{< quote source="semicit. Eminem" >}}
The software you mainly use with a 3D printer is a slicer, which is a piece of software that takes a 3D rendering of the item you want to print and slice it into many layers, stacked one on top of the other, you can manipulate the layers in various ways in order to alter the properties of the final printed item.
-{{< image class="max-w-m mx-auto" caption="Ultimaker Cura 4.9 main interface" src="2021-04-25-183336_1366x768_scrot.png" alt="Screenshot from Ultimaker Cura 4.9 main interface" >}}
+{{< image class="max-w-md mx-auto" caption="Ultimaker Cura 4.9 main interface" src="/uppies/2021/05/2021-04-25-183336_1366x768_scrot.png" alt="Screenshot from Ultimaker Cura 4.9 main interface" >}}{{< /image >}}
I’ve chosen [Ultimaker Cura](https://ultimaker.com/software/ultimaker-cura) as my main slicer, I started with it and I found it’s easy enough for a noob like me, but manages to give the user a lot of room for customization when you start understanding how it works.
## Meet SolveSpace
-{{< image class="max-w-m mx-auto" caption="solvespace interface" src="2021-04-25-190246_1366x768_scrot.png" alt="Screenshot from solvespace interface" >}}
+{{< image class="max-w-md mx-auto" caption="solvespace interface" src="/uppies/2021/05/2021-04-25-190246_1366x768_scrot.png" alt="Screenshot from solvespace interface" >}}{{< /image >}}
[SolveSpace](https://solvespace.com/index.pl) is a 2D/3D parametric cad Software, it’s totally free, licensed under the GPLv3 and available for windows, mac and of course GNU/Linux.
-{{< video class="max-w-m mx-auto" autoplay="false" loop="false" src="/solvespace_demo.webm" alt="Solvespace video demo" >}}
+{{< video class="max-w-md mx-auto" src="/uppies/2021/05/solvespace_demo.webm" >}}
I’ve watched this introductory video and was able to pick it up and start designing in a matter of minutes, it’s very straightforward and even if it does things a bit differently than Fusion, it’s still very comfortable to use.
categories = ["code", "diy", "fotografia"]
tags = ["bash", "convert", "gif", "imagemagik", "mogrify", "script"]
+++
-{{< image class="max-w-lg mx-auto" src="piscaturi.gif" alt="piccoli pescatori crescono" caption="gif image created using gify.sh" >}}
+{{< image class="max-w-lg mx-auto" src="/uppies/2016/01/piscaturi.gif" alt="piccoli pescatori crescono" caption="gif image created using gify.sh" >}}{{< /image >}}
Today I'll present you a useful script that will help you create amazing gifs from your still photos using a couple tools from the [IMAGEMAGIK](https://www.imagemagick.org) suite, so without further ado, here it is, straight from github's gists.
I've added a new user and group to my server but before doing so I added /usr/bin/git-shell to /etc/shells in order to use it as login shell for my git user.
-{{< highlight bash >}}
+```bash
echo "/usr/bin/git-shell" >> /etc/shells
groupadd git
mkdir /var/git
useradd -d /var/git -g git -M -s /usr/bin/git-shell
-{{< /highlight >}}
+```
now the user is all set and ready to be used. Next step will be to create the .ssh directory and the authorized_keys file to hold the keys for the developers that have to access the git server. Here's how I did it:
tags = ["imagine", "john lennon"]
format = "image"
+++
-{{< figure class="align-center" src="https://danix.xyz/wp-content/uploads/2020/10/imagine_colors.jpg" />}}
+{{< image src="https://danix.xyz/wp-content/uploads/2020/10/imagine_colors.jpg" alt="Imagine by John Lennon as a comic strip" >}}{{< /image >}}
via [http://www.filmsforaction.org/articles/john-lennons-imagine-made-into-a-comic-strip/](http://www.filmsforaction.org/articles/john-lennons-imagine-made-into-a-comic-strip/)
Enjoy.
-{{< gallery >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/Boy-on-Mount-Fuji-large.jpg" alt="Boy on Mount Fuji" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/Choshi-in-Shimosa-Province-Soshu-Choshi-large.jpg" alt="Choshi in Shimosa Province" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/Hibiscus-and-Sparrow-large.jpg" alt="Hibiscus and Sparrow" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/Mt.-Fuji-in-the-Sunset-large.jpg" alt="Mt. Fuji in the Sunset" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/Yoro-Waterfall-in-Mino-Province-Mino-no-kuni-Yoro-no-taki-large.jpg" alt="Yoro Waterfall in Mino Province Mino no kuni Yoro no taki" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/White-Shell-Shiragai-large.jpg" alt="White Shell Shiragai" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/Waterfall-where-Yoshitsune-Washed-his-Horse-at-Yoshino-in-Yamato-Province-Washu-Yoshino-Yoshitsune-uma-arai-no-taki-large.jpg" alt="Waterfall where Yoshitsune Washed his Horse at Yoshino in Yamato Province Washu Yoshino Yoshitsune uma arai no taki" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/The-Great-Wave-Off-Kanagawa-1823-large.jpg" alt="The Great Wave Off Kanagawa" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/The-dragon-on-Smoke-Escaping-from-Mt-Fuji-large.jpg" alt="The dragon on Smoke Escaping from Mt Fuji" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/Surimono-Totsuka-large.jpg" alt="Surimono Totsuka" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/South-Wind-at-Clear-Dawn-Gaifu-kaisei-large.jpg" alt="South Wind at Clear Dawn Gaifu kaisei" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/Shower-Below-the-Summit-Sanka-hakuu-large.jpg" alt="Shower Below the Summit Sanka hakuu" >}}
- {{< gal-img divClass="col-3 gtr-uniform" src="/uploads/2011/07/Plum-Blossom-and-the-Moon-large.jpg" alt="Plum Blossom and the Moon" >}}
+{{< gallery cols="3" >}}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{< /gallery >}}
I hope you liked them. I'll see you on the next one.
<!--more-->
-{{< figure src="/uploads/2010/11/email-at1-300x211.gif" class="align-left" />}}
+{{< image src="/uploads/2010/11/email-at1-300x211.gif" alt="Email at symbol illustration" >}}{{< /image >}}
Già vi immagino, voi fedeli (3) lettori, subito pronti a dire: "_ma cosa vorrai mai insegnarci sulle email che già non sappiamo?_" beh, iniziamo dalla prima cosa che colpisce l'occhio di chi riceve una mail, l'**oggetto**.
Eh già, si chiama oggetto perchè serve a descrivere ciò di cui l'email parla, l'oggetto del messaggio appunto. Non ha quindi senso lasciare il campo in bianco o scrivere cose senza senso tipo "email da tizio:, "comunicazione da sempronio: eccetera, per sapere chi è il mittente dell'email c'è il campo "From: o "Da: oppure indovinate un po', "Mittente:, l'avreste mai detto?! :)
Un altro problema che affligge spesso chi riceve email è l'invio di foto! Su questo punto potremmo spendere fiumi di parole parlando del fatto che al giorno d'oggi con le adsl super veloci che ci ritroviamo non sia più un problema ricevere allegati pesanti, ma non capisco perchè io debba stare a scaricare una foto da 12 megapixel a 300 <acronym title="dot per inches (punti per pollice)">dpi</acronym> se non dovrò nemmeno stamparla, ma al massimo condividerla sul blog o su facebook; perdete un attimino del vostro <span style="text-decoration: line-through">prezioso</span> tempo anche voi e riducete le dimensioni delle foto che inviate, già ridurre la risoluzione da 300 a 72 [dpi][4] aiuterà notevolmente chi dovrà ricevere la mail oltre che farvi risparmiare molto tempo in invio.. Un altro appunto relativo alle dimensioni delle foto, se state mandando una foto di un tenero cucciolo che dovrà fare da sfondo al piccì del vostro/a amato/a, che senso ha che misuri 4000 pixel sul lato corto?! Una risoluzione decente potrebbe essere 1600 pixel sul lato lungo e il lato corto dimensionato in proporzione, in questo modo le dimensioni scenderanno ulteriormente senza che si perda la qualità del vostro pregevolissimo scatto! ;)
-{{< figure class="align-right" src="/uploads/2010/11/url-300x197.jpg" />}}
+{{< image src="/uploads/2010/11/url-300x197.jpg" alt="URL structure illustration" >}}{{< /image >}}
[5]Il punto successivo di questa carrellata potrebbe avere un titolo e un articolo a se, "_come inviare link. Il modo corretto di condividere i famigerati [URL][6]_"; fin dagli albori di internet si è avvertita infatti la necessità di condividere link interessanti con i nostri contatti, e sopratutto negli ultimi tempi i link sono diventati sempre più lunghi e complessi, cose tipo:
```
categories = ["blogging"]
tags = ["john green", "nerds"]
+++
-{{< figure class="align-center" caption="We are nerds. Resistance is futile" >}}
-{{< img src="/uploads/2011/08/nerdslikeus.png" alt="nerds like us" >}}
-{{< /figure >}}
+{{< image src="/uploads/2011/08/nerdslikeus.png" alt="nerds like us" caption="We are nerds. Resistance is futile" figure-class="text-center" >}}{{< /image >}}
via [ipstenu.org][1]
categories = ["code", "diy"]
tags = ["colors", "github", "html5", "palette", "php", "viewer"]
+++
-{{< figure src="https://danix.xyz/wp-content/uploads/2016/02/palette-1.jpg" class="image fit" link="https://github.com/danixland/palette-viewer" caption="palette-viewer on github" />}}
+{{< image src="https://danix.xyz/wp-content/uploads/2016/02/palette-1.jpg" alt="palette-viewer screenshot" link="https://github.com/danixland/palette-viewer" caption="palette-viewer on github" >}}{{< /image >}}
{{< dropcap >}}
Today I decided I wanted to have a little "old school" fun, so instead of working on some WordPress theme/plugin, I went for the "lemme write some php from scratch" approach.
format = "video"
+++
-{{< youtube ku9JVNK6rLU >}}
+{{< video id="ku9JVNK6rLU" title="Sunset in Siderno - GoPro timelapse" >}}
my first video, an experiment with a GoPro Hero+ LCD and Kdenlive.
margin-bottom: 3rem;
}
-.my-4 {
- margin-top: 1rem;
- margin-bottom: 1rem;
-}
-
.my-6 {
margin-top: 1.5rem;
margin-bottom: 1.5rem;
+++ /dev/null
-{{- $src := .Get "src" -}}
-{{- $alt := .Get "alt" -}}
-{{- $class := .Get "class" -}}
-<figure class="my-6 {{ $class }}">
- {{- if $src -}}<img src="{{ $src }}" alt="{{ $alt }}" class="w-full" />{{ end -}}
- {{- .Inner -}}
- {{- if .Get "caption" -}}<figcaption class="text-sm text-text-dim mt-2">{{ .Get "caption" }}</figcaption>{{ end -}}
-</figure>
+++ /dev/null
-<div class="{{ .Get "divClass" }}">
- <img src="{{ .Get "src" }}" alt="{{ .Get "alt" }}" class="image fit" />
-</div>
{{- $src := .Get "src" -}}
{{- $alt := .Get "alt" | default "Image" -}}
{{- $caption := .Get "caption" -}}
-{{- $class := .Get "class" | default "w-full h-auto rounded-lg border border-border/30" -}}
+{{- $class := .Get "class" | default "w-full h-auto rounded-lg border border-border" -}}
+{{- $link := .Get "link" -}}
+{{- $figureClass := .Get "figure-class" -}}
-{{- if $src -}}
- <figure class="my-8">
- <img
- src="{{ $src }}"
- alt="{{ $alt }}"
- class="{{ $class }}"
- loading="lazy"
- />
+{{- if or $src .Inner -}}
+ <figure class="my-8{{- with $figureClass }} {{ . }}{{- end -}}">
+ {{- if .Inner -}}
+ {{- .Inner -}}
+ {{- else -}}
+ {{- if $link -}}<a href="{{ $link }}">{{- end -}}
+ <img src="{{ $src }}" alt="{{ $alt }}" class="{{ $class }}" loading="lazy" />
+ {{- if $link -}}</a>{{- end -}}
+ {{- end -}}
{{- if $caption -}}
- <figcaption class="mt-3 text-center text-sm text-text-dim italic">
- {{ $caption }}
- </figcaption>
+ <figcaption class="mt-3 text-center text-sm text-text-dim italic">{{ $caption }}</figcaption>
{{- end -}}
</figure>
{{- else -}}
- {{- errorf "image shortcode: 'src' parameter is required" -}}
+ {{- errorf "image shortcode: 'src' parameter or inner content is required" -}}
{{- end -}}
+++ /dev/null
-<img src="{{ .Get "src" }}" alt="{{ .Get "alt" }}" class="w-full my-4" />
-{{/*
- * The video shortcode:
- * All arguments are optional, except for src which is where you define your video file
- * This shortcode supports only webm video files.
- * Args:
- * class: [string] The class(es) to give to the video block.
- * width: [int] The width of the video
- * height: [int] The height of the video
- * autoplay: [bool] true or false for autoplay - defaults to false
- * loop: [bool] true or false for loop - defaults to false
- * mute: [bool] true or false for mute - defaults to false
- *
- * Usage:
- * {{< video src="my-awesome-video.mp4" width=600 height=600 autoplay=true loop=true mute=true class="some class" >}}
- *
- * Output:
- * <video class="some class" controls preload="auto" width="600" height="600" autoplay loop muted>
- <source src="my-awesome-video.mp4" type="video/webm">
- * </video>
- *
- */}}
+{{- $src := .Get "src" -}}
+{{- $id := .Get "id" -}}
+{{- $title := .Get "title" | default "Video" -}}
+{{- $class := .Get "class" | default "" -}}
-{{ $srcParam := .Get "src" }}
-{{ $ext := $srcParam | path.Ext }}
-{{ $filetype := slicestr $ext 1 }}
-
-{{ $videoURL := $srcParam }}
-{{ $resource := .Page.Resources.GetMatch $srcParam }}
-{{ if $resource }}
- {{ $videoURL = $resource.RelPermalink }}
-{{ end }}
-
-<video{{ with .Get "class" }} class="{{ . }}"{{ end }}
- controls
- preload="auto"
- {{ with .Get "width" }}width="{{.}}"{{ end }}
- {{ with .Get "height" }}height="{{.}}"{{ end }}
- {{ if eq (.Get "autoplay") "true" }}autoplay {{ end }}
- {{ if eq (.Get "loop") "true" }}loop {{ end }}
- {{ if eq (.Get "muted") "true" }}muted {{ end }}
- playsinline >
+{{- if $id -}}
+ <div class="my-6{{- with $class }} {{ . }}{{- end -}}">
+ <iframe
+ class="w-full aspect-video"
+ src="https://www.youtube.com/embed/{{ $id }}"
+ title="{{ $title }}"
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
+ allowfullscreen
+ ></iframe>
+ </div>
+{{- else if $src -}}
+ {{- $ext := $src | path.Ext -}}
+ {{- $filetype := slicestr $ext 1 -}}
+ {{- $videoURL := $src -}}
+ {{- $resource := .Page.Resources.GetMatch $src -}}
+ {{- if $resource -}}{{- $videoURL = $resource.RelPermalink -}}{{- end -}}
+ <video
+ {{- with $class }} class="{{ . }}"{{ end }}
+ controls
+ preload="auto"
+ playsinline
+ {{- with .Get "width" }} width="{{ . }}"{{ end }}
+ {{- with .Get "height" }} height="{{ . }}"{{ end }}
+ {{- if eq (.Get "autoplay") "true" }} autoplay{{ end }}
+ {{- if eq (.Get "loop") "true" }} loop{{ end }}
+ {{- if eq (.Get "muted") "true" }} muted{{ end }}
+ >
<source src="{{ $videoURL }}" type="video/{{ $filetype }}">
-</video>
+ </video>
+{{- else -}}
+ {{- errorf "video shortcode: either 'src' or 'id' parameter is required" -}}
+{{- end -}}
+++ /dev/null
-<iframe class="w-full aspect-video my-6" src="https://www.youtube.com/embed/{{ .Get "id" }}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>