Compare commits
9 Commits
main
...
5b355aca6a
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b355aca6a | |||
| a849a21e59 | |||
| 267f580648 | |||
| 188e996581 | |||
| 6efbecc07a | |||
| 6745469841 | |||
| 208a873d80 | |||
| 5e00c0c7c4 | |||
| 7f614688d0 |
@@ -7,12 +7,6 @@ disableHugoGeneratorInject: true
|
||||
enableEmoji: true
|
||||
timeZone: Europe/Paris
|
||||
theme: ["2026"]
|
||||
security:
|
||||
funcs:
|
||||
getenv:
|
||||
- "^HUGO_"
|
||||
- "^CI$"
|
||||
- "^MEILI_SEARCH_API_KEY$"
|
||||
params:
|
||||
lists:
|
||||
layout: spotlight
|
||||
|
||||
@@ -2,12 +2,12 @@ favicon: /favicon.png
|
||||
# Pas de / pour les ressources qui seront transformées
|
||||
# Et les placer dans /assets et non dans /static
|
||||
logo: logo-large.png
|
||||
description: "Richard Dern et ses opinions impopulaires"
|
||||
themeColor: "#060c14"
|
||||
description: "et ses opinions impopulaires"
|
||||
search:
|
||||
action: /recherche/
|
||||
param: q
|
||||
meilisearch:
|
||||
endpoint: /api/search
|
||||
indexUid: blog_posts
|
||||
apiKey: "cf49bcdb1b08e5c502c41956d38ce0be80d5e79e9f084e6f15f4485f87d63c30"
|
||||
hitsPerPage: 20
|
||||
|
||||
|
Before Width: | Height: | Size: 408 KiB After Width: | Height: | Size: 419 KiB |
@@ -1,4 +0,0 @@
|
||||
#title: ""
|
||||
#attribution: ""
|
||||
description: "L'alias `comportement_suspect` se remplit tout seul désormais."
|
||||
#prompt: ""
|
||||
@@ -1,4 +0,0 @@
|
||||
#title: ""
|
||||
#attribution: ""
|
||||
description: "Vue simplifiée de mon architecture réseau."
|
||||
#prompt: ""
|
||||
@@ -1,4 +0,0 @@
|
||||
#title: ""
|
||||
attribution: "ChatGPT Auto"
|
||||
description: "Collaboration entre Caddy et OPNsense pour filtrer les comportements suspects sur mon site."
|
||||
prompt: "Dynamic digital illustration showing collaboration between a Caddy web server and an OPNsense firewall to block suspicious IP addresses while remaining bot-friendly. Split cyber-security themed scene: on the left a modern server rack with the Caddy logo and a glowing blue protective shield, friendly small robot bots representing legitimate crawlers; on the right an OPNsense firewall server emitting an orange security shield. In the center a digital warning panel reading ‘Access Denied – Suspicious IP’ with network traffic being filtered. Dark cyber-security environment with world map, network lines, glowing circuits, blue vs orange lighting contrast, cinematic lighting, high-detail, wide banner illustration suitable as a blog header."
|
||||
@@ -1,4 +0,0 @@
|
||||
#title: ""
|
||||
#attribution: ""
|
||||
description: "Ce petit malotru vérifie si je fais tourner WordPress. Pour la dernière fois."
|
||||
#prompt: ""
|
||||
@@ -1,15 +0,0 @@
|
||||
flowchart LR
|
||||
internet[Internet]
|
||||
freebox[Freebox<br/>mode bridge]
|
||||
opnsense[Routeur<br/>OPNsense + Caddy]
|
||||
|
||||
internet --> freebox --> opnsense
|
||||
|
||||
subgraph lan[Réseau local]
|
||||
direction TB
|
||||
server[server-main<br/>NixOS + Caddy<br/>Héberge mon blog]
|
||||
others[Autres machines physiques<br/>Autres services web]
|
||||
end
|
||||
|
||||
opnsense -->|Reverse-proxy| server
|
||||
opnsense -->|Reverse-proxy| others
|
||||
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 371 KiB |
@@ -1,18 +0,0 @@
|
||||
{{- $description := .Description | default "" -}}
|
||||
{{- if not $description -}}
|
||||
{{- $description = .Summary | plainify | htmlUnescape -}}
|
||||
{{- end -}}
|
||||
{{- if not $description -}}
|
||||
{{- $description = .Plain | htmlUnescape -}}
|
||||
{{- end -}}
|
||||
{{- if not $description -}}
|
||||
{{- $description = .Content | plainify | htmlUnescape -}}
|
||||
{{- end -}}
|
||||
{{- if not $description -}}
|
||||
{{- $description = site.Params.description | default "" -}}
|
||||
{{- end -}}
|
||||
{{- $description = $description | replaceRE "\\s+" " " | strings.TrimSpace -}}
|
||||
{{- if gt (len $description) 180 -}}
|
||||
{{- $description = truncate 180 $description -}}
|
||||
{{- end -}}
|
||||
{{- return $description -}}
|
||||
@@ -1,68 +0,0 @@
|
||||
{{- $title := site.Title -}}
|
||||
{{- if not .IsHome -}}
|
||||
{{- $title = printf "%s | %s" .Title site.Title -}}
|
||||
{{- end -}}
|
||||
{{- $socialTitle := site.Title -}}
|
||||
{{- if not .IsHome -}}
|
||||
{{- $socialTitle = .Title -}}
|
||||
{{- end -}}
|
||||
{{- $description := partial "head/description.html" . -}}
|
||||
{{- $socialImage := partial "head/social-image.html" . -}}
|
||||
{{- $searchPath := site.Params.search.action | relURL -}}
|
||||
{{- $isSearchPage := eq .RelPermalink $searchPath -}}
|
||||
{{- $robots := "max-image-preview:large" -}}
|
||||
{{- if $isSearchPage -}}
|
||||
{{- $robots = "noindex, follow" -}}
|
||||
{{- end -}}
|
||||
{{- $ogType := "website" -}}
|
||||
{{- if and .IsPage (not $isSearchPage) -}}
|
||||
{{- $ogType = "article" -}}
|
||||
{{- end -}}
|
||||
{{- $localeCode := site.LanguageCode | default site.Language.LanguageCode | default "fr-FR" -}}
|
||||
{{- $locale := replace $localeCode "-" "_" -}}
|
||||
<title>{{ $title }}</title>
|
||||
{{- with $description }}
|
||||
<meta name="description" content="{{ . }}">
|
||||
{{- end }}
|
||||
<meta name="theme-color" content="{{ site.Params.themeColor | default "#060c14" }}">
|
||||
<meta name="robots" content="{{ $robots }}">
|
||||
<link rel="canonical" href="{{ .Permalink }}">
|
||||
<meta property="og:locale" content="{{ $locale }}">
|
||||
<meta property="og:site_name" content="{{ site.Title }}">
|
||||
<meta property="og:type" content="{{ $ogType }}">
|
||||
<meta property="og:title" content="{{ $socialTitle }}">
|
||||
<meta property="og:url" content="{{ .Permalink }}">
|
||||
{{- with $description }}
|
||||
<meta property="og:description" content="{{ . }}">
|
||||
{{- end }}
|
||||
{{- with $socialImage.url }}
|
||||
<meta property="og:image" content="{{ . }}">
|
||||
{{- end }}
|
||||
{{- with $socialImage.width }}
|
||||
<meta property="og:image:width" content="{{ . }}">
|
||||
{{- end }}
|
||||
{{- with $socialImage.height }}
|
||||
<meta property="og:image:height" content="{{ . }}">
|
||||
{{- end }}
|
||||
{{- with $socialImage.alt }}
|
||||
<meta property="og:image:alt" content="{{ . }}">
|
||||
{{- end }}
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:title" content="{{ $socialTitle }}">
|
||||
{{- with $description }}
|
||||
<meta name="twitter:description" content="{{ . }}">
|
||||
{{- end }}
|
||||
{{- with $socialImage.url }}
|
||||
<meta name="twitter:image" content="{{ . }}">
|
||||
{{- end }}
|
||||
{{- with $socialImage.alt }}
|
||||
<meta name="twitter:image:alt" content="{{ . }}">
|
||||
{{- end }}
|
||||
{{- if eq $ogType "article" -}}
|
||||
{{- with .Date }}
|
||||
<meta property="article:published_time" content="{{ .Format "2006-01-02T15:04:05Z07:00" }}">
|
||||
{{- end }}
|
||||
{{- with .Lastmod }}
|
||||
<meta property="article:modified_time" content="{{ .Format "2006-01-02T15:04:05Z07:00" }}">
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
@@ -1,55 +0,0 @@
|
||||
{{- $image := false -}}
|
||||
{{- $isCoverImage := false -}}
|
||||
{{- $alt := "" -}}
|
||||
{{- with .Params.cover -}}
|
||||
{{- $cover := $.Resources.GetMatch . -}}
|
||||
{{- if and $cover (ne $cover.MediaType.SubType "svg") -}}
|
||||
{{- $image = $cover -}}
|
||||
{{- $isCoverImage = true -}}
|
||||
{{- $coverName := path.Base . | replaceRE "\\.[^.]+$" "" -}}
|
||||
{{- $coverDataFile := $.Resources.Get (printf "data/images/%s.yaml" $coverName) -}}
|
||||
{{- if not $coverDataFile -}}
|
||||
{{- $coverDataFile = $.Resources.Get (printf "data/%s.yaml" $coverName) -}}
|
||||
{{- end -}}
|
||||
{{- $coverData := dict -}}
|
||||
{{- if $coverDataFile -}}
|
||||
{{- $coverData = $coverDataFile.Content | transform.Unmarshal -}}
|
||||
{{- end -}}
|
||||
{{- $alt = index $coverData "description" | default "" -}}
|
||||
{{- if not $alt -}}
|
||||
{{- $alt = index $coverData "title" | default "" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if not $image -}}
|
||||
{{- $logoPath := site.Params.logo | default "logo-large.png" -}}
|
||||
{{- $logo := resources.GetMatch $logoPath -}}
|
||||
{{- if and $logo (ne $logo.MediaType.SubType "svg") -}}
|
||||
{{- $image = $logo -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if not $alt -}}
|
||||
{{- if and $image $isCoverImage -}}
|
||||
{{- if and .IsPage (not .IsHome) -}}
|
||||
{{- $alt = printf "Image de partage pour %s" .Title -}}
|
||||
{{- else -}}
|
||||
{{- $alt = printf "Logo du site %s" site.Title -}}
|
||||
{{- end -}}
|
||||
{{- else if $image -}}
|
||||
{{- $alt = printf "Logo du site %s" site.Title -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $data := dict -}}
|
||||
{{- if $image -}}
|
||||
{{- $data = dict
|
||||
"url" $image.Permalink
|
||||
"alt" ($alt | strings.TrimSpace | truncate 420)
|
||||
-}}
|
||||
{{- with $image.Width -}}
|
||||
{{- $data = merge $data (dict "width" .) -}}
|
||||
{{- end -}}
|
||||
{{- with $image.Height -}}
|
||||
{{- $data = merge $data (dict "height" .) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- return $data -}}
|
||||
@@ -1,10 +1,6 @@
|
||||
{{ define "main" }}
|
||||
{{- $search := .Site.Params.search -}}
|
||||
{{- $meili := $search.meilisearch -}}
|
||||
{{- $apiKey := getenv "MEILI_SEARCH_API_KEY" -}}
|
||||
{{- if eq $apiKey "" -}}
|
||||
{{- errorf "MEILI_SEARCH_API_KEY is required to render the search page" -}}
|
||||
{{- end -}}
|
||||
<header class="article-header">
|
||||
{{ partialCached "header-brand.html" .Site .Site.Title (.Site.Params.logo | default "logo-large.png") }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
@@ -13,7 +9,7 @@
|
||||
class="search-page"
|
||||
data-search-endpoint="{{ $meili.endpoint }}"
|
||||
data-search-index="{{ $meili.indexUid }}"
|
||||
data-search-api-key="{{ $apiKey }}"
|
||||
data-search-api-key="{{ $meili.apiKey }}"
|
||||
data-search-limit="{{ $meili.hitsPerPage }}"
|
||||
data-search-param="{{ $search.param }}"
|
||||
>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"scripts": {
|
||||
"icons:generate": "node tools/generate_apple_touch_icons.js",
|
||||
"links:refresh": "node tools/check_external_links.js",
|
||||
"stats:generate": "node tools/generate_stats.js"
|
||||
},
|
||||
|
||||
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 49 KiB |
6
test.sh
@@ -18,8 +18,4 @@ detect_dev_host() {
|
||||
DEV_HOST="$(detect_dev_host)"
|
||||
DEV_PORT=1313
|
||||
|
||||
if [ -z "${MEILI_SEARCH_API_KEY+x}" ]; then
|
||||
export MEILI_SEARCH_API_KEY="dummy"
|
||||
fi
|
||||
|
||||
hugo server -DEF --bind "$DEV_HOST" --port $DEV_PORT --baseURL "http://$DEV_HOST:$DEV_PORT"
|
||||
hugo server -DEF --bind "$DEV_HOST" --port $DEV_PORT --baseURL "http://$DEV_HOST:$DEV_PORT"
|
||||
@@ -858,49 +858,6 @@ aside section dl > div {
|
||||
padding-top: var(--space-2);
|
||||
}
|
||||
|
||||
body:has(> header.article-header) > main > aside.article-complementary-images {
|
||||
width: min(100%, var(--max-width-reading));
|
||||
margin-inline: auto;
|
||||
margin-top: var(--space-6);
|
||||
}
|
||||
|
||||
body:has(> header.article-header) > main > aside.article-complementary-images > section {
|
||||
margin-top: 0;
|
||||
border-top: 1px solid var(--color-border);
|
||||
padding-top: var(--space-3);
|
||||
}
|
||||
|
||||
body:has(> header.article-header) > main > aside.article-complementary-images > section > h2 {
|
||||
margin-top: 0;
|
||||
font-size: 1.02rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
body:has(> header.article-header) > main > aside.article-complementary-images > section > ul {
|
||||
list-style: none;
|
||||
margin-top: var(--space-3);
|
||||
padding-left: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
body:has(> header.article-header) > main > aside.article-complementary-images > section > ul > li {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
body:has(> header.article-header) > main > aside.article-complementary-images > section > ul > li > a {
|
||||
display: block;
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
body:has(> header.article-header) > main > aside.article-complementary-images > section > ul > li > a > img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
body:has(> header.article-header) > main > aside.article-toc {
|
||||
position: fixed;
|
||||
inset-inline-end: var(--space-2);
|
||||
|
||||
@@ -71,16 +71,8 @@
|
||||
{{- $coverImage = $page.Resources.GetMatch $coverPath -}}
|
||||
{{- if $coverImage -}}
|
||||
{{- $coverDisplay = $coverImage -}}
|
||||
{{- if ne $coverDisplay.MediaType.SubType "svg" -}}
|
||||
{{- $coverWidth := $coverDisplay.Width -}}
|
||||
{{- if gt $coverDisplay.Width 1480 -}}
|
||||
{{- $coverWidth = 1480 -}}
|
||||
{{- end -}}
|
||||
{{- $coverDisplay = partial "media/process-image.html" (dict
|
||||
"image" $coverImage
|
||||
"action" "Resize"
|
||||
"spec" (printf "%dx" $coverWidth)
|
||||
) -}}
|
||||
{{- if and (ne $coverDisplay.MediaType.SubType "svg") (gt $coverDisplay.Width 1480) -}}
|
||||
{{- $coverDisplay = $coverImage.Resize "1480x" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
{{- $page := . -}}
|
||||
{{- $bundleImages := slice -}}
|
||||
{{- range $page.Resources.ByType "image" -}}
|
||||
{{- if strings.HasPrefix .Name "images/" -}}
|
||||
{{- $bundleImages = $bundleImages | append . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if gt (len $bundleImages) 0 -}}
|
||||
{{- $coverPath := "" -}}
|
||||
{{- with $page.Params.cover -}}
|
||||
{{- $coverPath = strings.TrimSpace (printf "%v" .) -}}
|
||||
{{- end -}}
|
||||
{{- $coverImagePath := "" -}}
|
||||
{{- if ne $coverPath "" -}}
|
||||
{{- $coverPathLower := lower $coverPath -}}
|
||||
{{- if or (strings.HasSuffix $coverPathLower ".yaml") (strings.HasSuffix $coverPathLower ".yml") -}}
|
||||
{{- $coverDataFile := $page.Resources.GetMatch $coverPath -}}
|
||||
{{- if $coverDataFile -}}
|
||||
{{- $coverData := $coverDataFile.Content | transform.Unmarshal -}}
|
||||
{{- with index $coverData "file" -}}
|
||||
{{- $coverImagePath = strings.TrimSpace (printf "%v" .) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- $coverImagePath = $coverPath -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $coverImageName := "" -}}
|
||||
{{- if ne $coverImagePath "" -}}
|
||||
{{- $coverImageName = lower (path.Base $coverImagePath) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $contentImageNames := slice -}}
|
||||
{{- $contentImageStems := slice -}}
|
||||
{{- $imageTags := findRE `(?is)<img[^>]+src=["'][^"']+["'][^>]*>` .Content -}}
|
||||
{{- range $imageTags -}}
|
||||
{{- $srcMatch := findRESubmatch `(?is)src=["']([^"']+)["']` . -}}
|
||||
{{- if gt (len $srcMatch) 0 -}}
|
||||
{{- $src := lower (index (index $srcMatch 0) 1) -}}
|
||||
{{- if or (in $src "/images/") (strings.HasPrefix $src "images/") (strings.HasPrefix $src "./images/") -}}
|
||||
{{- $srcName := path.Base $src -}}
|
||||
{{- $srcName = replaceRE "\\?.*$" "" $srcName -}}
|
||||
{{- $srcName = replaceRE "#.*$" "" $srcName -}}
|
||||
{{- $srcName = replaceRE "_hu_[^.]*" "" $srcName -}}
|
||||
{{- $srcStem := $srcName | replaceRE "\\.[^.]+$" "" -}}
|
||||
{{- $contentImageNames = $contentImageNames | append $srcName -}}
|
||||
{{- $contentImageStems = $contentImageStems | append $srcStem -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $unusedImages := slice -}}
|
||||
{{- range $bundleImages -}}
|
||||
{{- $imageName := path.Base .Name -}}
|
||||
{{- $imageNameLower := lower $imageName -}}
|
||||
{{- $isCoverImage := false -}}
|
||||
{{- if and (ne $coverImageName "") (eq $imageNameLower $coverImageName) -}}
|
||||
{{- $isCoverImage = true -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $isCoverImage -}}
|
||||
{{- $imageStem := $imageName | replaceRE "\\.[^.]+$" "" -}}
|
||||
{{- $imageStemLower := lower $imageStem -}}
|
||||
{{- $isUsedInContent := false -}}
|
||||
{{- range $contentImageNames -}}
|
||||
{{- if eq . $imageNameLower -}}
|
||||
{{- $isUsedInContent = true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if not $isUsedInContent -}}
|
||||
{{- range $contentImageStems -}}
|
||||
{{- if eq . $imageStemLower -}}
|
||||
{{- $isUsedInContent = true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if not $isUsedInContent -}}
|
||||
{{- $unusedImages = $unusedImages | append . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if gt (len $unusedImages) 0 -}}
|
||||
<aside class="article-complementary-images">
|
||||
<section>
|
||||
<h2>Images complémentaires</h2>
|
||||
<ul>
|
||||
{{- range $unusedImages -}}
|
||||
{{- $imageName := path.Base .Name -}}
|
||||
{{- $imageStem := $imageName | replaceRE "\\.[^.]+$" "" -}}
|
||||
{{- $data := dict -}}
|
||||
{{- $dataFile := $page.Resources.Get (printf "data/images/%s.yaml" $imageStem) -}}
|
||||
{{- if not $dataFile -}}
|
||||
{{- $dataFile = $page.Resources.Get (printf "data/%s.yaml" $imageStem) -}}
|
||||
{{- end -}}
|
||||
{{- if $dataFile -}}
|
||||
{{- $data = $dataFile.Content | transform.Unmarshal -}}
|
||||
{{- end -}}
|
||||
{{- $title := default (printf "Image complémentaire : %s" $imageName) (index $data "title") -}}
|
||||
{{- $thumbnail := . -}}
|
||||
{{- if and (ne .MediaType.SubType "svg") (gt .Width 360) -}}
|
||||
{{- $thumbnail = partial "media/process-image.html" (dict
|
||||
"image" .
|
||||
"action" "Resize"
|
||||
"spec" "360x"
|
||||
) -}}
|
||||
{{- end -}}
|
||||
<li>
|
||||
<a href="{{ .RelPermalink }}" title="{{ $title }}">
|
||||
<img src="{{ $thumbnail.RelPermalink }}" alt="{{ $title }}" loading="lazy" decoding="async">
|
||||
</a>
|
||||
</li>
|
||||
{{- end -}}
|
||||
</ul>
|
||||
</section>
|
||||
</aside>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -109,11 +109,7 @@
|
||||
<a href="{{ $page.RelPermalink }}">
|
||||
<figure>
|
||||
{{- with $image -}}
|
||||
{{- $resized := partial "media/process-image.html" (dict
|
||||
"image" .
|
||||
"action" "Fill"
|
||||
"spec" $thumbnailTransform
|
||||
) -}}
|
||||
{{- $resized := .Fill $thumbnailTransform -}}
|
||||
<img src="{{ $resized.RelPermalink }}" alt="Image de couverture pour {{ $page.Title }}" loading="lazy">
|
||||
{{- end -}}
|
||||
</figure>
|
||||
@@ -129,11 +125,7 @@
|
||||
<a href="{{ $page.RelPermalink }}">
|
||||
<figure>
|
||||
{{- with $image -}}
|
||||
{{- $resized := partial "media/process-image.html" (dict
|
||||
"image" .
|
||||
"action" "Fill"
|
||||
"spec" $thumbnailTransform
|
||||
) -}}
|
||||
{{- $resized := .Fill $thumbnailTransform -}}
|
||||
<img src="{{ $resized.RelPermalink }}" alt="Image de couverture pour {{ $page.Title }}" loading="lazy">
|
||||
{{- end -}}
|
||||
</figure>
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
{{ partial "head/metadata.html" . }}
|
||||
<title>{{ if .IsHome }}{{ site.Title }}{{ else }}{{ printf "%s | %s" .Title site.Title }}{{ end }}</title>
|
||||
{{ with .Description }}
|
||||
<meta name="description" content="{{ . }}">
|
||||
{{ else }}
|
||||
{{ with site.Params.description }}
|
||||
<meta name="description" content="{{ . }}">
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<link rel="icon" href="{{ "favicon.ico" | absURL }}" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="{{ "favicon.ico" | absURL }}" type="image/x-icon">
|
||||
<link rel="icon" href="{{ "favicon.png" | absURL }}" type="image/png" sizes="256x256">
|
||||
<link rel="apple-touch-icon" href="{{ "apple-touch-icon.png" | absURL }}" sizes="180x180">
|
||||
{{ partialCached "head/css.html" . }}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
{{- $image := .image -}}
|
||||
{{- $showMeta := .showMeta -}}
|
||||
{{- $forceCentered := .forceCentered -}}
|
||||
{{- $alt := .alt -}}
|
||||
{{- $title := .title -}}
|
||||
{{- $display := $image -}}
|
||||
|
||||
{{- if ne $image.MediaType.SubType "svg" -}}
|
||||
{{- if gt $image.Width $image.Height -}}
|
||||
{{- $maxWidth := 1400 -}}
|
||||
{{- if and $showMeta (not $forceCentered) -}}
|
||||
{{- $maxWidth = 900 -}}
|
||||
{{- end -}}
|
||||
{{- $targetWidth := $image.Width -}}
|
||||
{{- if gt $image.Width $maxWidth -}}
|
||||
{{- $targetWidth = $maxWidth -}}
|
||||
{{- end -}}
|
||||
{{- $display = partial "media/process-image.html" (dict
|
||||
"image" $image
|
||||
"action" "Resize"
|
||||
"spec" (printf "%dx" $targetWidth)
|
||||
) -}}
|
||||
{{- else -}}
|
||||
{{- $targetHeight := $image.Height -}}
|
||||
{{- if gt $image.Height 900 -}}
|
||||
{{- $targetHeight = 900 -}}
|
||||
{{- end -}}
|
||||
{{- $display = partial "media/process-image.html" (dict
|
||||
"image" $image
|
||||
"action" "Resize"
|
||||
"spec" (printf "x%d" $targetHeight)
|
||||
) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
<img src="{{ $display.RelPermalink }}" alt="{{ $alt }}" title="{{ $title }}">
|
||||
@@ -1,30 +0,0 @@
|
||||
{{/* Préserve les GIF animés en évitant toute transformation Hugo. */}}
|
||||
{{- $image := .image -}}
|
||||
{{- if not $image -}}
|
||||
{{- errorf "media/process-image.html: missing image resource" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $action := .action -}}
|
||||
{{- if not $action -}}
|
||||
{{- errorf "media/process-image.html: missing image action for %q" $image.Name -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $spec := .spec -}}
|
||||
{{- if not $spec -}}
|
||||
{{- errorf "media/process-image.html: missing image spec for %q" $image.Name -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $result := $image -}}
|
||||
{{- $subType := lower $image.MediaType.SubType -}}
|
||||
{{- if and (ne $subType "svg") (ne $subType "gif") -}}
|
||||
{{- $options := printf "%s webp q80" $spec -}}
|
||||
{{- if eq $action "Fill" -}}
|
||||
{{- $result = $image.Fill $options -}}
|
||||
{{- else if eq $action "Resize" -}}
|
||||
{{- $result = $image.Resize $options -}}
|
||||
{{- else -}}
|
||||
{{- errorf "media/process-image.html: unsupported image action %q for %q" $action $image.Name -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- return $result -}}
|
||||
@@ -13,6 +13,10 @@
|
||||
{{- if not $image -}}
|
||||
{{- return -}}
|
||||
{{- end -}}
|
||||
{{- $display := $image -}}
|
||||
{{- if and (ne $display.MediaType.SubType "svg") (gt $display.Height 810) -}}
|
||||
{{- $display = $image.Resize "x810" -}}
|
||||
{{- end -}}
|
||||
{{- $metaTitle := index $data "title" -}}
|
||||
{{- $hasMeta := or $metaTitle (or $description (or $data.attribution $data.prompt)) -}}
|
||||
{{- $attributes := .Attributes | default dict -}}
|
||||
@@ -52,13 +56,7 @@
|
||||
{{- end -}}
|
||||
<figure class="{{ delimit $figureClasses " " }}">
|
||||
<a href="{{ $image.RelPermalink }}" title="Cliquez pour agrandir l'image">
|
||||
{{- partial "media/display-img.html" (dict
|
||||
"image" $image
|
||||
"showMeta" $showMeta
|
||||
"forceCentered" $forceCentered
|
||||
"alt" $alt
|
||||
"title" $title
|
||||
) -}}
|
||||
<img src="{{ $display.RelPermalink }}" alt="{{ $alt }}" title="{{ $title }}">
|
||||
</a>
|
||||
{{- if $showMeta -}}
|
||||
<figcaption class="figure-media-meta cover-meta">
|
||||
|
||||
@@ -4,16 +4,12 @@
|
||||
{{- $assetPath := "images/oeuvres/l-anankeisme.png" -}}
|
||||
{{- $source := resources.Get $assetPath -}}
|
||||
{{- if $source -}}
|
||||
{{- $img := partial "media/process-image.html" (dict
|
||||
"image" $source
|
||||
"action" "Resize"
|
||||
"spec" "320x"
|
||||
) -}}
|
||||
{{- $img := $source.Resize "320x" -}}
|
||||
<img src="{{ $img.RelPermalink }}" width="{{ $img.Width }}" height="{{ $img.Height }}" alt="Couverture de L'Anankéisme" loading="lazy">
|
||||
{{- end -}}
|
||||
</figure>
|
||||
<h2>L'Anankéisme</h2>
|
||||
<p><em>L'Anankéisme</em> propose, en dix axiomes, une pensée du réel fondée sur le déterminisme intégral. Vérité, vivant, morale, mort : cet essai explore avec méthode les conséquences d'un monde où rien n'advient sans cause et invite à mesurer jusqu'où peut aller une pensée qui n'accorde rien au hasard ni à la transcendance.</p>
|
||||
<p><em>L'Anankéisme</em> propose un cadre axiomatique en dix propositions pour penser un déterminisme absolu, une vérité indépendante de toute cognition et une définition rigoureuse du vivant.</p>
|
||||
<p>
|
||||
<a class="ui-button" href="https://librairie.bod.fr/lanankeisme-richard-dern-9782322634903">Acheter le livre</a>
|
||||
<a class="ui-button" href="https://anankeisme.fr/">Découvrir le site dédié à l'Anankéisme</a>
|
||||
|
||||
@@ -4,16 +4,12 @@
|
||||
{{- $assetPath := "images/oeuvres/l-humain-cette-espece-primitive.jpeg" -}}
|
||||
{{- $source := resources.Get $assetPath -}}
|
||||
{{- if $source -}}
|
||||
{{- $img := partial "media/process-image.html" (dict
|
||||
"image" $source
|
||||
"action" "Resize"
|
||||
"spec" "320x"
|
||||
) -}}
|
||||
{{- $img := $source.Resize "320x" -}}
|
||||
<img src="{{ $img.RelPermalink }}" width="{{ $img.Width }}" height="{{ $img.Height }}" alt="Couverture de L'Humain, cette espèce primitive" loading="lazy">
|
||||
{{- end -}}
|
||||
</figure>
|
||||
<h2>L'Humain, cette espèce primitive</h2>
|
||||
<p><em>L'Humain, cette espèce primitive</em> pose une question inconfortable : et si notre sophistication technique masquait surtout un profond retard social, cognitif et moral ? En prenant l'exploration spatiale comme révélateur, cet essai secoue notre récit du progrès et montre pourquoi, avant de prétendre conquérir l'univers, nous avons encore à apprendre à habiter lucidement le monde.</p>
|
||||
<p><em>L'Humain, cette espèce primitive</em> est un essai dans lequel vous explorez plusieurs facettes de ce que nous appelons notre évolution, en adoptant la perspective de l'exploration spatiale.</p>
|
||||
<p>
|
||||
<a class="ui-button" href="https://www.amazon.fr/dp/B08VF4D2NT">Acheter la version numérique</a>
|
||||
<a class="ui-button" href="/interets/philosophie/2023/05/18/lhumain-cette-espece-primitive-lhumain-cette-espece-primitive/">Lire le livre en ligne</a>
|
||||
|
||||
@@ -6,11 +6,7 @@
|
||||
{{- $logo := resources.GetMatch $logoPath -}}
|
||||
<a href="{{ "/" | relURL }}" aria-label="Revenir à l'accueil">
|
||||
{{- with $logo -}}
|
||||
{{- $resized := partial "media/process-image.html" (dict
|
||||
"image" .
|
||||
"action" "Resize"
|
||||
"spec" "64x"
|
||||
) -}}
|
||||
{{- $resized := .Resize "64x" -}}
|
||||
<img src="{{ $resized.RelPermalink }}" alt="">
|
||||
{{- end -}}
|
||||
<strong>{{ $site.Title }}</strong>
|
||||
|
||||
@@ -36,11 +36,7 @@
|
||||
{{- with $image -}}
|
||||
<a href="{{ $page.RelPermalink }}">
|
||||
<figure>
|
||||
{{- $resized := partial "media/process-image.html" (dict
|
||||
"image" .
|
||||
"action" "Fill"
|
||||
"spec" "600x340"
|
||||
) -}}
|
||||
{{- $resized := .Fill "600x340" -}}
|
||||
<img src="{{ $resized.RelPermalink }}" alt="Image de couverture pour {{ $page.Title }}" loading="lazy">
|
||||
</figure>
|
||||
</a>
|
||||
|
||||
@@ -8,16 +8,11 @@
|
||||
{{- $extension := path.Ext $remoteURL -}}
|
||||
{{- $cleanFilename := printf "%s%s" $hash $extension | replace "?raw=true" "" -}}
|
||||
{{- $localImage := $remoteImage | resources.Copy (printf "remote-images/%s" $cleanFilename) -}}
|
||||
{{- $resizedImage := $localImage.Resize "1024x" -}}
|
||||
{{- $hasMeta := or $title (or $description $attribution) -}}
|
||||
<figure class="figure-media{{ if $hasMeta }} figure-media-with-meta{{ else }} figure-media-without-meta{{ end }}">
|
||||
<a href="{{ $localImage.RelPermalink }}" title="Cliquez pour agrandir l'image">
|
||||
{{- partial "media/display-img.html" (dict
|
||||
"image" $localImage
|
||||
"showMeta" $hasMeta
|
||||
"forceCentered" false
|
||||
"alt" $title
|
||||
"title" $title
|
||||
) -}}
|
||||
<img src="{{ $resizedImage.RelPermalink }}" alt="{{ $title }}" title="{{ $title }}">
|
||||
</a>
|
||||
{{- if $hasMeta -}}
|
||||
<figcaption class="figure-media-meta cover-meta">
|
||||
|
||||
@@ -104,36 +104,13 @@
|
||||
{{- end -}}
|
||||
{{- $collectionsEntries = sort $collectionsEntries "LatestDateKey" "desc" -}}
|
||||
|
||||
{{- $critiquesDisplayed := slice -}}
|
||||
|
||||
{{- $critiquesCategoryDefs := slice -}}
|
||||
{{- $critiquesCategoryDefs = $critiquesCategoryDefs | append (dict "Path" "/critiques/films") -}}
|
||||
{{- $critiquesCategoryDefs = $critiquesCategoryDefs | append (dict "Path" "/critiques/series") -}}
|
||||
{{- $critiquesCategoryDefs = $critiquesCategoryDefs | append (dict "Path" "/critiques/jeux-video") -}}
|
||||
{{- $critiquesCategoryDefs = $critiquesCategoryDefs | append (dict "Path" "/critiques/livres") -}}
|
||||
{{- $critiquesCategoryEntries := slice -}}
|
||||
{{- range $critiqueDef := $critiquesCategoryDefs -}}
|
||||
{{- $critiquePath := index $critiqueDef "Path" -}}
|
||||
{{- $critiqueSection := $site.GetPage $critiquePath -}}
|
||||
{{- $critiquePages := slice -}}
|
||||
{{- with $critiqueSection -}}
|
||||
{{- range .RegularPagesRecursive.ByDate.Reverse -}}
|
||||
{{- if eq (partial "is-dossier-lead.html" .) "true" -}}
|
||||
{{- $critiquePages = $critiquePages | append . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if gt (len $critiquePages) 0 -}}
|
||||
{{- $latestDateKey := "00000000000000" -}}
|
||||
{{- with index $critiquePages 0 -}}
|
||||
{{- $latestDateKey = .Date.Format "20060102150405" -}}
|
||||
{{- end -}}
|
||||
{{- $critiquesCategoryEntries = $critiquesCategoryEntries | append (dict
|
||||
"Section" $critiqueSection
|
||||
"Pages" (first 8 $critiquePages)
|
||||
"LatestDateKey" $latestDateKey
|
||||
) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $critiquesCategoryEntries = sort $critiquesCategoryEntries "LatestDateKey" "desc" -}}
|
||||
|
||||
<main class="home-main">
|
||||
{{- if gt (len $interestsSpotlight) 0 -}}
|
||||
@@ -232,9 +209,22 @@
|
||||
</section>
|
||||
{{- end -}}
|
||||
|
||||
{{- range $critiqueIndex, $critiqueEntry := $critiquesCategoryEntries -}}
|
||||
{{- $critiqueSection := index $critiqueEntry "Section" -}}
|
||||
{{- $critiqueSpotlight := index $critiqueEntry "Pages" -}}
|
||||
{{- range $critiqueIndex, $critiqueDef := $critiquesCategoryDefs -}}
|
||||
{{- $critiquePath := index $critiqueDef "Path" -}}
|
||||
{{- $critiquePrefix := printf "%s/" (strings.TrimSuffix "/" $critiquePath) -}}
|
||||
{{- $critiqueSection := $site.GetPage $critiquePath -}}
|
||||
{{- $critiquePool := slice -}}
|
||||
{{- range $critiquesArticles -}}
|
||||
{{- if and (strings.Contains .RelPermalink $critiquePrefix) (not (in $critiquesDisplayed .File.Path)) -}}
|
||||
{{- $critiquePool = $critiquePool | append . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $critiqueSpotlight := first 8 $critiquePool -}}
|
||||
{{- range $critiqueSpotlight -}}
|
||||
{{- $critiquesDisplayed = $critiquesDisplayed | append .File.Path -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if gt (len $critiqueSpotlight) 0 -}}
|
||||
<section class="home-critiques-category">
|
||||
<header>
|
||||
@@ -315,11 +305,7 @@
|
||||
<a href="{{ $page.RelPermalink }}">
|
||||
<figure>
|
||||
{{- with $image -}}
|
||||
{{- $resized := partial "media/process-image.html" (dict
|
||||
"image" .
|
||||
"action" "Fill"
|
||||
"spec" "166x91"
|
||||
) -}}
|
||||
{{- $resized := .Fill "166x91" -}}
|
||||
<img src="{{ $resized.RelPermalink }}" alt="Capture du lien {{ $page.Title }}" loading="lazy">
|
||||
{{- end -}}
|
||||
</figure>
|
||||
@@ -405,11 +391,7 @@
|
||||
<a href="{{ $item.RelPermalink }}" title="{{ $item.Title }}">
|
||||
<figure>
|
||||
{{- with $itemImage -}}
|
||||
{{- $resized := partial "media/process-image.html" (dict
|
||||
"image" .
|
||||
"action" "Resize"
|
||||
"spec" "x128"
|
||||
) -}}
|
||||
{{- $resized := .Resize "x128" -}}
|
||||
<img src="{{ $resized.RelPermalink }}" alt="{{ $item.Title }}" title="{{ $item.Title }}" loading="lazy">
|
||||
{{- end -}}
|
||||
</figure>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
{{ partial "liens-morts/report.html" (dict "Page" .) }}
|
||||
{{ partial "article-footer.html" . }}
|
||||
</article>
|
||||
{{ partial "asides/complementary-images.html" . }}
|
||||
{{ partial "asides/toc.html" . }}
|
||||
</main>
|
||||
{{ end }}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
{{ .Content }}
|
||||
{{ partial "article-footer.html" . }}
|
||||
</article>
|
||||
{{ partial "asides/complementary-images.html" . }}
|
||||
{{ partial "asides/toc.html" . }}
|
||||
</main>
|
||||
{{ end }}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
{{ partial "head/metadata.html" . }}
|
||||
<title>{{ if .IsHome }}{{ site.Title }}{{ else }}{{ printf "%s | %s" .Title site.Title }}{{ end }}</title>
|
||||
<link rel="icon" href="{{ "favicon.ico" | absURL }}" type="image/x-icon" />
|
||||
<link rel="shortcut icon" href="{{ "favicon.ico" | absURL }}" type="image/x-icon" />
|
||||
<link rel="icon" href="{{ "favicon.png" | absURL }}" type="image/png" sizes="256x256" />
|
||||
<link rel="apple-touch-icon" href="{{ "apple-touch-icon.png" | absURL }}" sizes="180x180" />
|
||||
{{ partialCached "head/css.html" . }}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const sharp = require("sharp");
|
||||
|
||||
const PROJECT_ROOT = path.resolve(__dirname, "..");
|
||||
const SOURCE_ICON_PATH = path.join(PROJECT_ROOT, "static", "favicon.png");
|
||||
const APPLE_TOUCH_ICON_SIZE = 180;
|
||||
const APPLE_TOUCH_ICON_BACKGROUND = "#060c14";
|
||||
const OUTPUT_ICON_PATHS = [
|
||||
path.join(PROJECT_ROOT, "static", "apple-touch-icon.png"),
|
||||
path.join(PROJECT_ROOT, "static", "apple-touch-icon-precomposed.png"),
|
||||
];
|
||||
|
||||
/**
|
||||
* Génère le PNG Apple Touch à partir du favicon principal du site.
|
||||
*
|
||||
* L'image finale est rendue opaque sur le fond sombre du thème actif pour
|
||||
* éviter les rendus incohérents des zones transparentes sur certains appareils iOS.
|
||||
*
|
||||
* @returns {Promise<Buffer>}
|
||||
*/
|
||||
function buildAppleTouchIconBuffer() {
|
||||
return sharp(SOURCE_ICON_PATH)
|
||||
.resize(APPLE_TOUCH_ICON_SIZE, APPLE_TOUCH_ICON_SIZE, {
|
||||
fit: "cover",
|
||||
})
|
||||
.flatten({
|
||||
background: APPLE_TOUCH_ICON_BACKGROUND,
|
||||
})
|
||||
.png({
|
||||
compressionLevel: 9,
|
||||
adaptiveFiltering: true,
|
||||
})
|
||||
.toBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Écrit la même icône sous les deux noms historiques encore demandés par les navigateurs.
|
||||
*
|
||||
* @param {Buffer} iconBuffer
|
||||
*/
|
||||
function writeAppleTouchIcons(iconBuffer) {
|
||||
for (const outputPath of OUTPUT_ICON_PATHS) {
|
||||
fs.writeFileSync(outputPath, iconBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
(async function main() {
|
||||
const iconBuffer = await buildAppleTouchIconBuffer();
|
||||
writeAppleTouchIcons(iconBuffer);
|
||||
})();
|
||||