Compare commits

...

8 Commits

Author SHA1 Message Date
Mark Dumay
0660a4c6e9 Merge pull request #942 from gethinode/image
Fix conversion of image dimensions
2024-05-20 09:00:30 +02:00
Mark Dumay
cba7768e39 Merge branch 'main' into image 2024-05-20 08:45:01 +02:00
Mark Dumay
a040ab42c3 Bump package release 2024-05-20 08:44:27 +02:00
Mark Dumay
fa6c01a380 Fix conversion of image dimensions 2024-05-20 08:43:49 +02:00
Mark Dumay
ed6c415bb2 Merge pull request #940 from gethinode/image
Add support for image CDNs
2024-05-19 19:03:48 +02:00
Mark Dumay
59c71d9bb2 Add initial alpha release 2024-05-19 18:56:57 +02:00
Mark Dumay
7dde1b3bb7 Merge branch 'main' into image 2024-05-19 18:55:48 +02:00
Mark Dumay
1d994fa1fe Add support for cloudinary images 2024-05-19 18:55:16 +02:00
16 changed files with 454 additions and 237 deletions

View File

@@ -15,7 +15,7 @@ for = '/**'
https://*.google-analytics.com https://*.analytics.google.com https://*.googletagmanager.com; \
font-src 'self' https://fonts.gstatic.com; \
frame-src 'self' https://www.youtube-nocookie.com https://www.youtube.com; \
img-src 'self' data: https://i.vimeocdn.com https://i.ytimg.com https://*.google-analytics.com https://*.googletagmanager.com https://tile.openstreetmap.org; \
img-src 'self' data: https://*.cloudinary.com https://i.vimeocdn.com https://i.ytimg.com https://*.google-analytics.com https://*.googletagmanager.com https://tile.openstreetmap.org; \
manifest-src 'self'; \
media-src 'self' \
"""

48
data/dimensions.yml Normal file
View File

@@ -0,0 +1,48 @@
- ratio: 4x3
dimensions:
- 576x432
- 768x576
- 992x744
- 1200x900
- 1400x1050
- 2800x2100
- ratio: 3x2
dimensions:
- 576x384
- 768x512
- 992x661
- 1200x800
- 1400x933
- 2800x1866
- ratio: 1x1
dimensions:
- 576x576
- 768x768
- 992x992
- 1200x1200
- 1400x1400
- 2800x2800
- ratio: 16x9
dimensions:
- 576x324
- 768x432
- 992x558
- 1200x675
- 1400x788
- 2800x1576
- ratio: 21x9
dimensions:
- 576x247
- 768x329
- 992x425
- 1200x514
- 1400x600
- 2800x1200
- ratio: auto
dimensions:
- 576
- 768
- 992
- 1200
- 1400
- 2800

View File

@@ -0,0 +1,62 @@
comment: >-
Defines the interface to be implemented by a CDN image adapter.
arguments:
host:
type: string
optional: true
comment: >-
Host of an URL. For example, the host of the URL
'https://example.com/first/second/third.webp' equals 'example.com'.
dir:
type: string
optional: true
comment: >-
All but the last element of an URL extension. For example, the dir of the
URL 'https://example.com/first/second/third.webp' equals '/first/second/'.
file:
type: string
optional: false
comment: >-
The last element of an URL extension. For example, the file of the
URL 'https://example.com/first/second/third.webp' equals 'third.webp'.
absoluteURL:
type: string
optional: true
default: false
comment: >-
Defines if a local image should use absolute instead of relative paths.
img:
type: "*resources.resourceAdapter"
optional: true
comment: >-
Image resource to process. Must be set when handling local images.
format:
type: select
optional: true
comment: >-
Image format; leave empty for an auto format (if supported) or default
format (usually jpg).
options:
values:
- png
- jpg
- gif
- tiff
- bmp
- webp
transform:
type: select
optional: false
comment: Image transformation.
options:
values:
- fill
- fit
height:
type: int
optional: false
comment: Height of the image in pixels.
width:
type: int
optional: false
comment: Width of the image in pixels.

View File

@@ -15,7 +15,7 @@ for = '/**'
https://*.google-analytics.com https://*.analytics.google.com https://*.googletagmanager.com; \
font-src 'self' https://fonts.gstatic.com; \
frame-src 'self' https://www.youtube-nocookie.com https://www.youtube.com; \
img-src 'self' data: https://i.vimeocdn.com https://i.ytimg.com https://*.google-analytics.com https://*.googletagmanager.com https://tile.openstreetmap.org; \
img-src 'self' data: https://*.cloudinary.com https://i.vimeocdn.com https://i.ytimg.com https://*.google-analytics.com https://*.googletagmanager.com https://tile.openstreetmap.org; \
manifest-src 'self'; \
media-src 'self' \
"""

View File

@@ -0,0 +1,24 @@
---
author: Mark Dumay
title: Local and remote images
date: 2024-05-19
description: Include responsive images from local sources and selected CDN image providers.
tags: ["blog"]
thumbnail:
url: https://res.cloudinary.com/demo/image/upload/v1689803100/ai/hiker.jpg
author: Nathan Dumlao
authorURL: https://unsplash.com/@nate_dumlao
origin: Unsplash
originURL: https://unsplash.com/photos/QLPWQvHvmII
---
## Cloudinary
As an example, the following shortcode displays an image with rounded corners and a 21x9 aspect ratio.
<!-- markdownlint-disable MD037 -->
{{< example lang="hugo" >}}
{{</* image src="https://res.cloudinary.com/demo/image/upload/dog.webp"
ratio="21x9" caption="Cloudinary image" class="rounded" */>}}
{{< /example >}}
<!-- markdownlint-enable MD037 -->

View File

@@ -492,6 +492,7 @@
"carrousel",
"carte",
"chronologie",
"cloudinary",
"collapse",
"collapse-1",
"command-prompt",

View File

@@ -0,0 +1,43 @@
<!--
Copyright © 2024 The Hinode Team / Mark Dumay. All rights reserved.
Use of this source code is governed by The MIT License (MIT) that can be found in the LICENSE file.
Visit gethinode.com/license for more details.
-->
{{ $error := false }}
<!-- Validate arguments -->
{{ if partial "utilities/IsInvalidArgs.html" (dict "structure" "image-adapter" "args" . "group" "partial") }}
{{ errorf "partial [assets/adapter/cloudinary.html] - Invalid arguments" -}}
{{ $error = true }}
{{ end }}
<!-- Initialize arguments -->
{{ $host := .host }}
{{ $dir := .dir }}
{{ $file := .file }}
{{ $format := .format }}
{{ $transform := .transform }}
{{ $height := .height }}
{{ $width := .width }}
{{ if eq $transform "fill" }}{{ $transform = "c_fill" }}{{ else }}{{ $transform = "c_fit" }}{{ end }}
{{ $element := "" }}
<!-- Split path between upload dir and sub dir -->
{{ $newdir := urls.JoinPath (index (split $dir "upload") 0) "upload" }}
{{ $file = urls.JoinPath (index (split $dir "upload") 1) $file }}
{{ $dir = $newdir }}
<!-- Generate image URL -->
{{ if not $error }}
{{ $operation := "" }}
{{ if $format }}
{{ $operation = printf "%s,h_%d,w_%d" $transform $height $width }}
{{ $file = printf "%s.%s" (path.BaseName $file) $format }}
{{ else }}
{{ $operation = printf "f_auto,%s,h_%d,w_%d" $transform $height $width }}
{{ end }}
{{- $element = urls.JoinPath (slice "https://" $host $dir $operation $file) -}}
{{ end }}
{{ return $element }}

View File

@@ -0,0 +1,64 @@
<!--
Copyright © 2024 The Hinode Team / Mark Dumay. All rights reserved.
Use of this source code is governed by The MIT License (MIT) that can be found in the LICENSE file.
Visit gethinode.com/license for more details.
-->
{{ $error := false }}
<!-- Validate arguments -->
{{ if partial "utilities/IsInvalidArgs.html" (dict "structure" "image-adapter" "args" . "group" "partial") }}
{{ errorf "partial [assets/adapter/hugo.html] - Invalid arguments" -}}
{{ $error = true }}
{{ end }}
<!-- Initialize arguments -->
{{ $host := .host }}
{{ $dir := .dir }}
{{ $file := .file }}
{{ $img := .img }}
{{ $transform := .transform }}
{{ $height := .height }}
{{ $width := .width }}
{{ $element := "" }}
{{ $absoluteURL := .absoluteURL }}
{{ $url := urls.JoinPath $dir $file }}
{{ if $host }}
{{ $url = urls.JoinPath "https://" $host $url }}
{{ end }}
<!-- Initialize image if needed -->
{{ $format := .format | default "webp" }}
{{ if and (not $img) (ne $format "svg") }}
{{- $res := partial "utilities/GetImage.html" (dict "url" $url "page" page) -}}
{{ if $res }}
{{ $img = $res.resource }}
<!-- TODO: $res.mirror -->
{{ end }}
{{ if not $img }}
{{ errorf "partial [assets/adapter/hugo.html] - Expected 'img' argument" -}}
{{ $error = true }}
{{ end }}
{{ end }}
<!-- Process image and generate image URL -->
{{ if not $error }}
{{ $scaled := "" }}
{{ if eq $transform "fill" }}
{{- $scaled = $img.Fill (printf "%dx%d %s" $width $height $format) -}}
{{ else }}
{{- $scaled = $img.Fit (printf "%dx%d %s" $width $height $format) -}}
{{ end }}
{{- $clean := path.Ext $img.RelPermalink -}}
{{- $scaled = $scaled | resources.Copy (replace $img.RelPermalink $clean (printf "-%dx%d.%s" $width $height $format)) -}}
{{- if $absoluteURL -}}
{{- $element = $scaled.Permalink -}}
{{- else -}}
{{- $element = $scaled.RelPermalink -}}
{{- end -}}
{{ end }}
{{ return $element }}

View File

@@ -0,0 +1,13 @@
<!--
Copyright © 2024 The Hinode Team / Mark Dumay. All rights reserved.
-->
{{ $ratio := .ratio }}
{{ $dim := "" }}
{{ $matches := first 1 (where site.Data.dimensions "ratio" $ratio) }}
{{ if eq ($matches | len) 1 }}
{{ $dim = (index $matches 0).dimensions }}
{{ end }}
{{ return $dim }}

View File

@@ -0,0 +1,23 @@
{{- $dim := .dim -}}
{{- $dimensions := slice }}
{{- $dimensions = $dimensions | append $dim -}}
{{- $portraits := slice }}
{{- range $d := $dimensions -}}
{{- $p := split $d "x" }}
{{ if ne (len $p) 2 }}
{{- warnf "partial [assets/image.html] - Invalid dimension: %s" $d -}}
{{- $portraits = $portraits | append $d -}}
{{- else -}}
{{- $portraits = $portraits | append (printf "%sx%s" (index $p 1) (index $p 0)) -}}
{{- end -}}
{{- end -}}
{{- $ret := "" }}
{{- if reflect.IsSlice $dim -}}
{{ $ret = $portraits -}}
{{- else if gt (len $portraits) 0 -}}
{{- $ret = index $portraits 0 -}}
{{- end -}}
{{- return $ret -}}

View File

@@ -0,0 +1,118 @@
<!-- Initialize arguments -->
{{- $page := .page -}}
{{- $ratio := .ratio -}}
{{- $portrait := .portrait -}}
{{- $wrapper := .wrapper -}}
{{- $class := .class -}}
{{- $title := .title -}}
{{- $caption := .caption -}}
{{- $figclass := .figclass -}}
{{- $lazy := .lazy -}}
{{- $priority := .priority -}}
{{- $sizes := .sizes -}}
{{- $absoluteURL := .absoluteURL -}}
{{- $url := .url -}}
{{- $mode := .mode -}}
{{- $modes := .modes -}}
{{- $fallbackURL := "" -}}
{{- $anchor := "" -}}
{{- $imgset := "" -}}
{{- $isVector := false -}}
<!-- Split url into base and anchor when applicable (only relevant for vector images) -->
{{- $segments := split $url "#" -}}
{{- if gt (len $segments) 2 -}}
{{- errorf "Invalid path or url: %q" $url -}}
{{- else if eq (len $segments) 2 }}
{{- $url = index $segments 0 -}}
{{- $anchor = index $segments 1 -}}
{{- end -}}
<!-- TODO: improve CDN detection / handling -->
{{ $hook := "hugo" }}
{{ if findRE "cloudinary" (urls.Parse $url).Hostname }}
{{ $hook = "cloudinary" }}
{{- end -}}
<!-- Define image dimensions -->
{{ $dims := slice }}
{{- $res := "" -}}
{{- $img := "" -}}
{{ $transform := "" }}
{{- if hasSuffix $url "svg" -}}
{{- $res = partial "utilities/GetResource.html" (dict "url" $url "page" $page) -}}
{{ if not $res }}
{{- if not (fileExists (path.Join "/static" $url)) -}}
{{ warnf "Cannot find vector image resource: %q" $url -}}
{{ else }}
{{ $width := string (partial "utilities/GetWidth.html" (dict "path" $url "height" 500)) }}
{{ $dims = $dims | append (printf "%sx500" $width) }}
{{ end }}
{{ end }}
{{ else if $ratio }}
{{ $transform = "fill" }}
{{ $dims = partial "assets/helpers/GetDimension.html" (dict "ratio" $ratio) }}
{{ if not $dims }}{{ errorf "partial [assets/image.html] - Cannot find dimension data: %s" $ratio }}{{ end }}
{{ else }}
{{ $transform = "fit" }}
{{- $res := partial "utilities/GetImage.html" (dict "url" $url "page" $page) -}}
{{ with $res }}
{{ $img = $res.resource }}
{{ if $res.mirror }}{{ $class = printf "%s mirrorred" $class }}{{ end }}
{{ end }}
{{ $widths := partial "assets/helpers/GetDimension.html" (dict "ratio" "auto") }}
{{ range $width := $widths -}}
{{- $dims = $dims | append (printf "%dx%d" (int $width) (int (math.Round (mul (div (float $width) $img.Width) $img.Height)))) -}}
{{- end -}}
{{ end }}
<!-- Derive image width and height -->
{{ $width := "" }}
{{ $height := "" }}
{{ range $dim := ($dims | last 1) }}
{{ $width = (int (index (split $dim "x") 0)) }}
{{ $height = (int (index (split $dim "x") 1)) }}
{{ end }}
<!-- Generate image urls -->
{{ if hasSuffix $url "svg" }}
{{- $fallbackURL = $url -}}
{{ else }}
{{- $fallbackURL = partial "assets/helpers/image-set.html" (dict "url" $url "img" $img "dims" ($dims | last 1) "transform" $transform "hook" $hook "format" "jpg" "includeWidth" false) -}}
{{- $imgset = partial "assets/helpers/image-set.html" (dict "url" $url "img" $img "dims" $dims "transform" $transform "hook" $hook) -}}
{{ end }}
<!-- Add color modes -->
{{- range $none := $modes -}}
{{- if ne $none $mode -}}
{{- $wrapper = printf "%s d-none-%s" (or $wrapper "") $none -}}
{{- end -}}
{{- end -}}
<!-- Generate image definition -->
{{- if $caption -}}
<figure {{ with $wrapper }}class="{{ . }}"{{ end }}>
{{ end }}
<div class="{{ if not $caption }}{{ $wrapper }}{{ end }}">
{{- if not $anchor -}}
<img class="img-fluid {{ $class }}"
src="{{ $fallbackURL }}"
{{ if $lazy }}loading="lazy"{{ end }}
{{ with $priority }}fetchpriority="{{ . }}"{{ end }}
{{ with $imgset -}}srcset="{{ . }}" sizes="{{ $sizes }}"{{- end }}
{{ with $height }}height="{{ . }}"{{ end }}
{{ with $width }}width="{{ . }}"{{ end }}
{{ with (or $title $caption) }}alt="{{ . }}"{{ end }}>
{{- else }}
<svg class="{{ $class }}">
<use href="{{ $fallbackURL }}#{{ $anchor }}"></use>
</svg>
{{ end }}
</div>
{{- if $caption -}}
<figcaption class="figure-caption{{ with $figclass }} {{ . }}{{ end }}">{{ $caption | safeHTML }}</figcaption>
</figure>
{{- end -}}

View File

@@ -0,0 +1,39 @@
{{- $url := .url -}}
{{ $img := .img }}
{{ $absoluteURL := .absoluteURL }}
{{ $dims := .dims }}
{{- $ratio := .ratio -}}
{{ $hook := .hook }}
{{ $transform := .transform }}
{{ $format := .format }}
{{ $includeWidth := .includeWidth | default true }}
{{ $host := (urls.Parse $url).Hostname }}
{{ $dir := (urls.Parse $url).Path }}
{{ $file := index ((split $dir "/") | collections.Reverse) 0 }}
{{ $dir = strings.TrimSuffix $file $dir }}
{{ $imgset := slice }}
{{- range $index, $dim := $dims -}}
{{ $width := (int (index (split $dim "x") 0)) }}
{{ $height := (int (index (split $dim "x") 1)) }}
{{- $element := partial (printf "assets/adapters/%s.html" $hook) (dict
"host" $host
"dir" $dir
"file" $file
"img" $img
"absoluteURL" $absoluteURL
"transform" $transform
"width" $width
"height" $height
"format" $format
)}}
{{ if $includeWidth }}
{{ $imgset = $imgset | append (printf "%s %dw" $element $width) }}
{{ else }}
{{ $imgset = $imgset | append $element }}
{{ end }}
{{- end -}}
{{ return (delimit $imgset ", ") }}

View File

@@ -13,250 +13,29 @@
{{ end }}
<!-- Initialize arguments -->
{{ $destination := .destination }}
<!-- Initialize arguments -->
{{- $absoluteURL := site.Params.main.canonifyAssetsURLs | default false -}}
{{- $page := .page -}}
{{- $ratio := .ratio -}}
{{- $portrait := .portrait -}}
{{- $url := .url -}}
{{- $mode := .mode -}}
{{- $modes := site.Params.main.modes | default (slice "light" "dark") -}}
{{- $wrapper := .wrapper -}}
{{- $class := .class -}}
{{- $title := .title -}}
{{- $caption := .caption -}}
{{- $figclass := .figclass -}}
{{- $page := .page -}}
{{- $loading := .loading -}}
{{- $lazy := eq $loading "lazy" -}}
{{- $priority := .priority -}}
{{- if eq $priority "auto" }}{{ $priority = "" }}{{ end -}}
{{- $sizes := .sizes | default "100vw" -}}
{{- $absoluteURL := site.Params.main.canonifyAssetsURLs | default false -}}
{{- $url := .url -}}
{{- $mode := .mode -}}
{{- $modes := site.Params.main.modes | default (slice "light" "dark") -}}
{{- define "partials/image-portrait.html" -}}
{{- $dimensions := slice }}
{{- $dim := .dim -}}
{{- $dimensions = $dimensions | append $dim -}}
{{- $portraits := slice }}
{{- range $d := $dimensions -}}
{{- $p := split $d "x" }}
{{ if ne (len $p) 2 }}
{{- warnf "partial [assets/image.html] - Invalid dimension: %s" $d -}}
{{- $portraits = $portraits | append $d -}}
{{- else -}}
{{- $portraits = $portraits | append (printf "%sx%s" (index $p 1) (index $p 0)) -}}
{{- end -}}
{{- end -}}
{{- $ret := "" }}
{{- if reflect.IsSlice $dim -}}
{{ $ret = $portraits -}}
{{- else if gt (len $portraits) 0 -}}
{{- $ret = index $portraits 0 -}}
{{- end -}}
{{- return $ret -}}
{{- end -}}
<!-- Generate a fallback image of type jpg -->
{{- define "partials/image-default.html" -}}
{{- $img := .img -}}
{{- $ratio := .ratio -}}
{{- $portrait := and .portrait .ratio -}}
{{- $width := "1400" -}}
{{- $dim := "" -}}
{{- $fallback := "" -}}
{{- with $img -}}
{{- if eq $ratio "4x3" -}}{{- $dim = "1400x1050" }}
{{- else if eq $ratio "3x2" -}}{{- $dim = "1400x933" }}
{{- else if eq $ratio "1x1" -}}{{- $dim = "1400x1400" }}
{{- else if eq $ratio "16x9" -}}{{- $dim = "1400x788" -}}
{{- else if eq $ratio "21x9" -}}{{- $dim = "1400x600" -}}
{{- else -}}
{{- $dim = printf "%sx%d" $width (int (math.Round (mul (div (float $width) $img.Width) $img.Height))) -}}
{{- end -}}
{{- if $portrait -}}{{- $dim = partial "partials/image-portrait.html" (dict "dim" $dim) -}}{{- end -}}
{{- if $ratio -}}
{{- $fallback = ($img.Fill (printf "%s jpg" $dim)) -}}
{{- else -}}
{{- $fallback = ($img.Fit (printf "%s jpg" $dim)) -}}
{{- end -}}
{{- $clean := path.Ext $img.RelPermalink -}}
{{- $ext := path.Ext $img.RelPermalink -}}
{{- $fallback = $fallback | resources.Copy (replace $img.RelPermalink $clean (printf "-%s%s" $dim $ext)) -}}
{{- end -}}
{{- return $fallback -}}
{{- end -}}
<!-- Generate a image set of type webp -->
{{- define "partials/image-scaled.html " -}}
{{- $absoluteURL := site.Params.main.canonifyAssetsURLs | default false -}}
{{- $img := .img -}}
{{- $ratio := .ratio -}}
{{- $portrait := and .portrait .ratio -}}
{{- $imgset := "" -}}
{{- $widths := slice "576" "768" "992" "1200" "1400" -}}
{{- $dims := slice -}}
{{- with $img -}}
{{- if eq $ratio "4x3" -}}
{{- $dims = slice "576x432" "768x576" "992x744" "1200x900" "1400x1050" -}}
{{- else if eq $ratio "3x2" -}}
{{- $dims = slice "576x384" "768x512" "992x661" "1200x800" "1400x933" -}}
{{- else if eq $ratio "1x1" -}}
{{- $dims = slice "576x576" "768x768" "992x992" "1200x1200" "1400x1400" -}}
{{- else if eq $ratio "16x9" -}}
{{- $dims = slice "576x324" "768x432" "992x558" "1200x675" "1400x788" -}}
{{- else if eq $ratio "21x9" -}}
{{- $dims = slice "576x247" "768x329" "992x425" "1200x514" "1400x600" -}}
{{- else -}}
{{- range $width := $widths -}}
{{- $dims = $dims | append (printf "%sx%d" $width (int (math.Round (mul (div (float $width) $img.Width) $img.Height)))) -}}
{{- end -}}
{{- end -}}
{{- if $portrait -}}
{{- $dims = partial "partials/image-portrait.html" (dict "dim" $dims) -}}
{{- end -}}
{{- $scaled := "" -}}
{{- range $index, $dim := $dims -}}
{{- $clean := path.Ext $img.RelPermalink -}}
{{- if $ratio -}}
{{- $scaled = $img.Fill (printf "%s webp" $dim) -}}
{{- else -}}
{{- $scaled = $img.Fit (printf "%s webp" $dim) -}}
{{- end -}}
{{- $scaled = $scaled | resources.Copy (replace $img.RelPermalink $clean (printf "-%s.webp" $dim)) -}}
{{- if $absoluteURL -}}
{{- $imgset = printf "%s, %s %sw" $imgset $scaled.Permalink (index $widths $index) -}}
{{- else -}}
{{- $imgset = printf "%s, %s %sw" $imgset $scaled.RelPermalink (index $widths $index) -}}
{{- end -}}
{{- end -}}
{{- $imgset = strings.TrimPrefix ", " $imgset -}}
{{- end -}}
{{- return $imgset -}}
{{- end -}}
<!-- Define the img with optional caption -->
{{- define "partials/image-definition.html" -}}
{{- $absoluteURL := site.Params.main.canonifyAssetsURLs | default false -}}
{{- $ratio := .ratio -}}
{{- $portrait := .portrait -}}
{{- $url := .url -}}
{{- $wrapper := .wrapper -}}
{{- $class := .class -}}
{{- $title := .title -}}
{{- $caption := .caption -}}
{{- $figclass := .figclass -}}
{{- $fallbackURL := "" -}}
{{- $anchor := "" -}}
{{- $imgset := "" -}}
{{- $mode := .mode -}}
{{- $modes := .modes -}}
{{- $lazy := .lazy -}}
{{- $page := .page -}}
{{- $sizes := .sizes -}}
{{- $priority := .priority -}}
{{- $isVector := false -}}
{{- $segments := split $url "#" -}}
{{- if gt (len $segments) 2 -}}
{{- errorf "Invalid path or url: %q" $url -}}
{{- else if eq (len $segments) 2 }}
{{- $url = index $segments 0 -}}
{{- $anchor = index $segments 1 -}}
{{- end -}}
{{- if hasSuffix $url "svg" -}}
{{- $fallbackURL = $url -}}
{{- $isVector = true -}}
{{- $res := partial "utilities/GetResource.html" (dict "url" $url "page" $page) -}}
{{ if not $res }}
{{- if not (fileExists (path.Join "/static" $url)) -}}
{{ warnf "Cannot find vector image resource: %q" $url -}}
{{ end }}
{{ end }}
{{- else -}}
{{- $res := partial "utilities/GetImage.html" (dict "url" $url "page" $page) -}}
{{- $img := "" -}}
{{ with $res }}
{{ $img = $res.resource }}
{{ if $res.mirror }}{{ $class = printf "%s mirrorred" $class }}{{ end }}
{{ end }}
{{- if $img -}}
{{- $fallback := partial "partials/image-default.html" (dict "img" $img "ratio" $ratio "portrait" $portrait) -}}
{{- if $absoluteURL -}}
{{- $fallbackURL = $fallback.Permalink -}}
{{- else -}}
{{- $fallbackURL = $fallback.RelPermalink -}}
{{- end -}}
{{- $imgset = partial "partials/image-scaled.html " (dict "img" $img "ratio" $ratio "portrait" $portrait) -}}
{{- end -}}
{{- end -}}
{{- range $none := $modes -}}
{{- if ne $none $mode -}}
{{- $wrapper = printf "%s d-none-%s" (or $wrapper "") $none -}}
{{- end -}}
{{- end -}}
{{- $width := "" -}}
{{- $height := "" -}}
{{- $input := (split (path.BaseName $fallbackURL) "-") | collections.Reverse -}}
{{ if $isVector }}
{{- $height = "500" -}}
{{ $width = string (partial "utilities/GetWidth.html" (dict "path" $fallbackURL "height" 500)) }}
{{- else if gt ($input | len) 1 -}}
{{- $dim := (split (index $input 0) "x") -}}
{{- if eq ($dim | len) 2 -}}
{{- $width = index $dim 0 -}}
{{- $height = index $dim 1 -}}
{{- end -}}
{{- end }}
{{- if $caption -}}
<figure {{ with $wrapper }}class="{{ . }}"{{ end }}>
{{ end }}
<div class="{{ if not $caption }}{{ $wrapper }}{{ end }}">
{{- if not $anchor -}}
<img class="img-fluid {{ $class }}"
src="{{ $fallbackURL }}"
{{ if $lazy }}loading="lazy"{{ end }}
{{ with $priority }}fetchpriority="{{ . }}"{{ end }}
{{ with $imgset -}}srcset="{{ . }}" sizes="{{ $sizes }}"{{- end }}
{{ with $height }}height="{{ . }}"{{ end }}
{{ with $width }}width="{{ . }}"{{ end }}
{{ with $title }}alt="{{ . }}"{{ end }}>
{{- else }}
<svg class="{{ $class }}">
<use href="{{ $fallbackURL }}#{{ $anchor }}"></use>
</svg>
{{ end }}
</div>
{{- if $caption -}}
<figcaption class="figure-caption{{ with $figclass }} {{ . }}{{ end }}">{{ $caption | safeHTML }}</figcaption>
</figure>
{{- end -}}
{{- end -}}
<!-- Initiate the regular or color-mode image -->
<!-- Main code -->
{{ $params := dict }}
{{- $params = merge $params (dict
"page" $page
"ratio" $ratio
"portrait" $portrait
"wrapper" $wrapper
@@ -267,7 +46,8 @@
"lazy" $lazy
"priority" $priority
"sizes" $sizes
"page" $page)
"absoluteURL" $absoluteURL
)
-}}
{{- if $mode -}}
@@ -284,9 +64,11 @@
"mode" $suffix
"modes" $modes)
-}}
{{- partial "partials/image-definition.html" $params -}}
{{- end -}}
{{ else }}
{{- $params = merge $params (dict "url" $url) -}}
{{- partial "partials/image-definition.html" $params -}}
{{- end -}}
{{ if not $error }}
{{- partial "assets/helpers/image-definition.html" $params -}}
{{ end }}

View File

@@ -33,7 +33,7 @@
font-src 'self' https://*.netlify.app https://fonts.gstatic.com; \
frame-src 'self' https://www.youtube-nocookie.com https://www.youtube.com \
app.netlify.com; \
img-src 'self' data: https://*.netlify.app https://i.vimeocdn.com https://i.ytimg.com https://*.google-analytics.com https://*.googletagmanager.com https://tile.openstreetmap.org; \
img-src 'self' data: https://*.cloudinary.com https://*.netlify.app https://i.vimeocdn.com https://i.ytimg.com https://*.google-analytics.com https://*.googletagmanager.com https://tile.openstreetmap.org; \
manifest-src 'self'; \
media-src 'self' \
"""

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@gethinode/hinode",
"version": "0.23.21",
"version": "0.24.0-alpha2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@gethinode/hinode",
"version": "0.23.21",
"version": "0.24.0-alpha2",
"license": "MIT",
"devDependencies": {
"@fullhuman/postcss-purgecss": "^6.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@gethinode/hinode",
"version": "0.23.21",
"version": "0.24.0-alpha2",
"description": "Hinode is a clean documentation and blog theme for Hugo, an open-source static site generator",
"keywords": [
"hugo",