diff options
author | Raphael Aguiar <rmaguiar@tuta.io> | 2020-06-22 21:17:46 +0300 |
---|---|---|
committer | Raphael Aguiar <rmaguiar@tuta.io> | 2020-06-22 21:17:46 +0300 |
commit | 8f8de1e97b3ffc5a5818742961158564f7f19b1e (patch) | |
tree | cc3d70f9f9917304d73501d0301850cb5d55430b /layouts |
Initial commit
Diffstat (limited to 'layouts')
24 files changed, 1575 insertions, 0 deletions
diff --git a/layouts/404.html b/layouts/404.html new file mode 100644 index 0000000..44e7d29 --- /dev/null +++ b/layouts/404.html @@ -0,0 +1,8 @@ +{{ define "main" }} + + <main> + <h1>{{ .Site.Params.notFound.title }}</h1> + <p>{{ .Site.Params.notFound.text }}</p> + </main> + +{{ end }} diff --git a/layouts/_default/_markup/render-heading.html b/layouts/_default/_markup/render-heading.html new file mode 100644 index 0000000..85e04c9 --- /dev/null +++ b/layouts/_default/_markup/render-heading.html @@ -0,0 +1,18 @@ +<!-- + Anchor links will be only set with level 2 and 3 headings + + TODO + It looks weird when the heading is also a link, + but then that's also true for links in ToCs + Would like to test a few more things +--> + +{{ $svgBundle := ($.Page.Scratch.Get "svgBundle").RelPermalink }} + +{{ $anchoredLinkLevels := slice 2 3 }} + +{{ if in $anchoredLinkLevels .Level }} + <h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }} {{ printf "<a class=\"anchor\" href=\"#%s\" title='%s \"%s\".'><svg aria-hidden=\"true\"><use xlink:href=\"%s#hashtag\"/></svg></a>" (.Anchor | safeURL) (T "anchor_for") (.Text | plainify | safeHTML) $svgBundle | safeHTML }}</h{{ .Level }}> +{{ else }} + <h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }}</h{{ .Level }}> +{{ end }} diff --git a/layouts/_default/_markup/render-image.html b/layouts/_default/_markup/render-image.html new file mode 100644 index 0000000..25bac7f --- /dev/null +++ b/layouts/_default/_markup/render-image.html @@ -0,0 +1,69 @@ +<!-- + It always expects the image is inside a folder called "img". + File will be converted into 3 versions: 500w, 800w and 1200w. + + Usage: + img "weird_cat.jpg" "Something that can (or not) be a cat." + img file="weird_cat.jpg" alt="Something that can (or not) be a cat." +--> + +{{ $file := .Destination }} +{{ $altText := .Text }} + +{{ $class := .Page.Param "markupImgClass" | default "borderless" }} + + +{{ $imgPath := .Page.Param "imgPath" }} + +{{ if $imgPath }} + {{ $file = path.Join $imgPath $file }} +{{ end }} + +{{ $encodedPixel := "image/gif;base64,R0lGODdhAQABAIABAICAgP///ywAAAAAAQABAAACAkQBADs=" }} + +<!-- Assume file is local --> +{{ with $.Page.Resources.GetMatch $file }} + + {{ $placeholder := (.Resize "800x png") | images.Filter (images.Contrast -100) }} + {{ $encodedPlaceholder := printf "image/png;base64,%s" ($placeholder.Content | base64Encode) }} + + <img + class="lazyload {{ $class }}" + loading="lazy" + data-srcset="{{ (.Resize "1200x").RelPermalink }} 1200w, {{ (.Resize "800x").RelPermalink }} 800w, {{ (.Resize "500x q90").RelPermalink }} 500w" + src="data:{{ $encodedPlaceholder }}" + data-src="{{ (.Resize "800x").RelPermalink }}" + {{ with $altText }}alt="{{ . }}"{{ end }} + /> + + <noscript> + <img + {{ with $class }}class="{{ . }}"{{ end }} + loading="lazy" + srcset="{{ (.Resize "1200x").RelPermalink }} 1200w, {{ (.Resize "800x").RelPermalink }} 800w, {{ (.Resize "500x q90").RelPermalink }} 500w" + src="data:{{ $encodedPlaceholder }}" + {{ with $altText }}alt="{{ . }}"{{ end }} + /> + </noscript> +{{ else }} + {{ with (.Destination | safeURL) }} + <!-- If local file isn't found, assume it's a remote file --> + <img + class="lazyload {{ $class }}" + loading="lazy" + src="data:{{ $encodedPixel }}" + data-src="{{ . }}" + {{ with $altText }}alt="{{ . }}"{{ end }} + /> + + <noscript> + <img + {{ with $class }}class="{{ . }}"{{ end }} + loading="lazy" + src="{{ . }}" + {{ with $altText }}alt="{{ . }}"{{ end }} + /> + </noscript> + + {{ end }} +{{ end }} diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html new file mode 100644 index 0000000..74f0a26 --- /dev/null +++ b/layouts/_default/baseof.html @@ -0,0 +1,54 @@ +<!-- + Generate and set SVG bundle + Currently here to avoid certain priority issues... +--> + +{{- $svgBundle := resources.Get "bundle.svg" | resources.ExecuteAsTemplate "img/bundle.svg" . | minify | resources.Fingerprint "md5" -}} +{{- $.Page.Scratch.Set "svgBundle" $svgBundle -}} + +<!DOCTYPE html> +<html lang="{{ .Site.Language.Lang }}" data-mode="{{ if .Site.Params.Style.isDark }}dark{{ else }}light{{ end }}"> + <head prefix="og: http://ogp.me/ns#"> + {{ partial "head" . }} + </head> + + <body> + + <header> + {{ partial "header" . }} + </header> + + <div class="filler"> + {{ block "main" . }} + <!-- Stuff --> + {{ end }} + </div> + + <footer> + {{ partial "footer" . }} + </footer> + + <!-- + Remnant JavaScript + If not using Hugo server, remove every "console.log()" + --> + + {{ with resources.Get "js/postpone.js" | resources.ExecuteAsTemplate .Page . | minify }} + + <script> + {{ if $.Site.IsServer }} + {{ .Content | safeJS }} + {{ else }} + {{ .Content | replaceRE "console.log(.*?);" "" | safeJS }} + {{ end }} + </script> + + {{ end }} + + <!-- KaTeX --> + {{ if or .Params.katex .Site.Params.katex .Params.math .Site.Params.math }} + {{ partial "katex.html" . }} + {{ end }} + + </body> +</html> diff --git a/layouts/_default/index.xml b/layouts/_default/index.xml new file mode 100644 index 0000000..2f83faf --- /dev/null +++ b/layouts/_default/index.xml @@ -0,0 +1,44 @@ +{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }} +<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> + <channel> + <title>{{ .Site.Title }}</title> + <link>{{ .Permalink }}</link> + <description>{{ .Site.Params.description }}</description> + <generator>Hugo -- gohugo.io</generator> + + {{ with .Site.Language }} + <language>{{ . }}</language> + {{end}} + + {{ with .Site.Author.email }} + <managingEditor>{{ . }}{{ with $.Site.Author.name }} ({{ . }}){{ end }}</managingEditor> + {{end}} + + {{ with .Site.Author.email }} + <webMaster>{{ . }}{{ with $.Site.Author.name }} ({{ . }}){{ end }}</webMaster> + {{end}} + + {{ with .Site.Copyright }} + <copyright>{{ . | markdownify | plainify }}</copyright> + {{end}} + + {{ if not .Date.IsZero }} + <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate> + {{ end }} + + {{ with .OutputFormats.Get "RSS" }} + {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }} + {{ end }} + + {{ range (where .Site.RegularPages ".Params.sitemap_exclude" "!=" "true") }} + <item> + <title>{{ .Title | emojify }}</title> + <link>{{ .Permalink }}</link> + <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate> + {{ with .Site.Author.email }}<author>{{ . }}{{ with $.Site.Author.name }} ({{ . }}){{ end }}</author>{{ end }} + <guid>{{ .Permalink }}</guid> + <description>{{ if .Description }}{{ .Description | emojify }}{{ else }}{{ .Summary | plainify | truncate 140 }}{{ end }}</description> + </item> + {{ end }} + </channel> +</rss> diff --git a/layouts/_default/list.html b/layouts/_default/list.html new file mode 100644 index 0000000..1ea0aa3 --- /dev/null +++ b/layouts/_default/list.html @@ -0,0 +1,50 @@ +{{ define "main" }} + + {{ $currentTitle := .Scratch.Get "currentTitle" }} + + <main class="list"> + + <h1>{{ $currentTitle }}</h1> + + {{ if eq .Kind "taxonomyTerm" }} + {{ if eq .Type "categories" }} + {{ partial "categories" . }} + {{ else if eq .Type "tags" }} + {{ partial "tags" . }} + {{ end }} + {{ else }} + + <!-- + range last 9 + .Format "2006-01-02" + | dateFormat "Jan 02" + --> + + {{ $pages := where site.RegularPages "Type" "in" .Site.Params.mainSections }} + + {{ $paginator := .Paginate .Pages }} + + <ul class="posts"> + {{ range $paginator.Pages }} + <li> + <a class="btn" href="{{ .RelPermalink }}"> + <p>{{ .Title | emojify }}</p> + {{ if not .Date.IsZero }}<time datetime="{{ .Date | dateFormat "2006-01-02" }}">{{ .Date.Format "2006-01-02" }}</time>{{ end }} + </a> + </li> + {{ end }} + </ul> + + {{ partial "pagination" . }} + + {{ if and (gt (len .Site.Taxonomies.tags) 1) (ne .Section "categories") }} + <hr> + <h2>{{ T "tags" }}</h2> + {{ partial "tags" . }} + {{ end }} + + {{ end }} + + </main> + +{{ end }}
\ No newline at end of file diff --git a/layouts/_default/single.html b/layouts/_default/single.html new file mode 100644 index 0000000..33dd41e --- /dev/null +++ b/layouts/_default/single.html @@ -0,0 +1,100 @@ +{{ define "main" }} + + {{ $svgBundle := ($.Page.Scratch.Get "svgBundle").RelPermalink }} + + <main> + <article> + <header> + + <h1>{{ .Title }}</h1> + + {{ if or .Params.categories .Params.tags }} + <aside class="tags"> + <ul> + {{- with .Params.categories -}} + {{- range sort . -}} + <li class="cats"><a class="btn" href="/categories/{{ . | urlize }}">{{ . }}</a></li> + {{- end -}} + {{- end -}} + {{- with .Params.tags -}} + {{- range sort . -}} + <li><a class="btn" href="/tags/{{ . | urlize }}">{{ . }}</a></li> + {{- end -}} + {{ end }} + </aside> + {{- end -}} + + {{ if not .Date.IsZero }} + <p> + {{ if eq .PublishDate .Lastmod }} + {{ T "published_on" }} <time datetime="{{ .PublishDate.Format "2006-01-02" }}">{{ .PublishDate.Format "2006-01-02" }}</time> + {{ else }} + {{ T "last_updated_on" }} <time datetime="{{ .Lastmod.Format "2006-01-02" }}">{{ .Lastmod.Format "2006-01-02" }}</time> + {{ end }} + </p> + {{ end }} + + {{ if .Params.cover }} + {{ partial "cover" . }} + {{ end }} + + </header> + + {{ if and .Params.toc (gt (len .Page.TableOfContents) 32) }} + <details class="toc" open> + <summary>{{ T "table_of_contents" }}</summary> + {{ .Page.TableOfContents }} + </details> + {{ end }} + + <!-- + For some reason, Chrome will ignore some elements when using TAB + (while Firefox will not). Since Chrome is used by the majority, + I feel like I need to "fix" this. + + For now, I'll be using "tabindex=0" (but then it makes Firefox + complain about accessibility). OH, THIS GONNA BE GREAT. + + Also, sorry for my REGEX skills. + --> + + <!-- i18n --> + {{ $references := (printf "${1}<h2>%s</h2>" (T "references")) }} + {{ $seeFootnotes := (printf "${1} title=\"%s\"" (T "see_footnotes")) }} + {{ $returnToText := (printf "${1} title=\"%s\"" (T "return_to_text")) }} + + <!-- a11y, kind of (probably useless) --> + {{ $highlightLabel := (printf "${1} aria-label=\"%s\" tabindex=0${2}" (T "box_containing_code")) }} + + <!-- Wrapped to make use of overflow-x property (plus the tabindex thing) --> + {{ $improvedTable := printf "<section class=scroll tabindex=0> ${1} </section>" }} + + <!-- Replace the footnote return links with a text label --> + {{ $footnoteReturnLink := ( printf "${1}%s${2}" (T "return")) }} + + <!-- OR replace the footnote return links with a SVG icon --> + {{ if .Site.Params.Style.hasIconAsFootnoteReturnLink }} + {{ $footnoteReturnLink = ( printf "${1}<svg transform=\"rotate(180) translate(0 -1)\" aria-hidden=\"true\" ><use xlink:href=\"%s#caret-down\"/></svg>${2}" $svgBundle) }} + {{ end }} + + <!-- + This is doing 4 things right now (or is it): + + * Adding "tabindex=0" to native table and code fences; + * Making tables scrollable; + * Localizing some text; + * Adding a "h2" to footnotes. + --> + + <!-- + For some reason, I don't seem to be able to capture the "↩" (not even using \x{21A9}). + To bypass this, I basically captured everything but the "↩"... + --> + + {{ .Content | replaceRE "(<table>(?:.|\n)+?</table>)" $improvedTable | replaceRE "(<div class=\"highlight\"><(?:pre|div) class=\"chroma\")(>)" $highlightLabel | replaceRE "(class=\"footnote-ref\")" $seeFootnotes | replaceRE "(class=\"footnote-backref\")" $returnToText | replaceRE "(<section class=\"footnotes\" role=\"doc-endnotes\">)" $references | replaceRE "(<a (?:.*) class=\"footnote-backref\" (?:.*)>)(?:.*)(</a>)" $footnoteReturnLink | safeHTML }} + + </article> + + </main> + +{{ end }} diff --git a/layouts/_default/sitemap.xml b/layouts/_default/sitemap.xml new file mode 100644 index 0000000..d3fecaa --- /dev/null +++ b/layouts/_default/sitemap.xml @@ -0,0 +1,27 @@ +{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }} +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" + xmlns:xhtml="http://www.w3.org/1999/xhtml"> + {{ range (where .Site.RegularPages ".Params.sitemap_exclude" "!=" "true") }} + <url> + <loc>{{ .Permalink }}</loc> + + {{ if not .Lastmod.IsZero }} + <lastmod>{{ safeHTML ( .Lastmod.Format "2006-01-02T15:04:05-07:00" ) }}</lastmod> + {{ end }} + + {{ with .Sitemap.ChangeFreq }} + <changefreq>{{ . }}</changefreq> + {{ end }} + + {{ if ge .Sitemap.Priority 0.0 }} + <priority>{{ .Sitemap.Priority }}</priority> + {{ end }} + + {{ if .IsTranslated }} + {{ range .Translations }} + <xhtml:link rel="alternate" hreflang="{{ .Lang }}" href="{{ .Permalink }}" /> + {{ end }} + {{ end }} + </url> + {{ end }} +</urlset>
\ No newline at end of file diff --git a/layouts/index.html b/layouts/index.html new file mode 100644 index 0000000..62c2b9e --- /dev/null +++ b/layouts/index.html @@ -0,0 +1,32 @@ +{{ define "main" }} + + {{ $pages := where site.RegularPages "Type" "in" .Site.Params.mainSections }} + + <main class="index"> + {{ if .Content }} + <h1>{{ .Title | emojify }}</h1> + {{ .Content }} + {{ else }} + + {{ $paginator := .Paginate $pages }} + + <h1>{{ T "posts" }}</h1> + + <ul class="posts"> + {{ range $paginator.Pages }} + <li> + <a class="btn" href="{{ .Permalink }}"> + <p>{{ .Title | emojify }}</p> + {{ if not .Date.IsZero }}<time datetime="{{ .Date | dateFormat "2006-01-02" }}">{{ .Date.Format "2006-01-02" }}</time>{{ end }} + </a> + </li> + {{ end }} + </ul> + + {{ partial "pagination" . }} + + {{ end }} + + </main> + +{{ end }} diff --git a/layouts/partials/categories.html b/layouts/partials/categories.html new file mode 100644 index 0000000..965b291 --- /dev/null +++ b/layouts/partials/categories.html @@ -0,0 +1,5 @@ +<ul class="labels"> + {{ range .Site.Taxonomies.categories }} + <li><a class="btn" href="{{ .Page.RelPermalink }}" aria-label="{{ .Page.Title }} ({{ .Count }})">{{ .Page.Title }}</a></li> + {{ end }} +</ul> diff --git a/layouts/partials/cover.html b/layouts/partials/cover.html new file mode 100644 index 0000000..047dd39 --- /dev/null +++ b/layouts/partials/cover.html @@ -0,0 +1,45 @@ +{{ $file := (.Params.cover) }} +{{ $altText := (.Params.coverAlt) }} + +<!-- https://discourse.gohugo.io/t/ability-to-access-site-params-in-the-front-matter-of-archetypes/9744/6 --> +{{ $imgPath := .Page.Param "imgPath" }} + +{{ if $imgPath }} + {{ $file = path.Join $imgPath $file }} +{{ end }} + +{{ with $.Page.Resources.GetMatch $file }} + + {{ $placeholder := (.Resize "800x png") | images.Filter (images.Contrast -100) }} + {{ $encodedPlaceholder := printf "image/png;base64,%s" ($placeholder.Content | base64Encode) }} + + {{ $encodedPixel := "image/gif;base64,R0lGODdhAQABAIABAICAgP///ywAAAAAAQABAAACAkQBADs=" }} + + <!-- + WARNING + For some reason I'm not able to printf the whole data URI + The ":" seems to be the culprit + Trying to escape it didn't work, for now I'm out of ideas + so I'll be simply using "data:[printf]" for now + --> + {{ $testEncodedPlaceholder := printf "data%cimage/png;base64,%s" "\u003A" ($placeholder.Content | base64Encode) }} + + <img + class="lazyload cover" + loading="lazy" + data-srcset="{{ (.Resize "1200x").RelPermalink }} 1200w, {{ (.Resize "800x").RelPermalink }} 800w, {{ (.Resize "500x q90").RelPermalink }} 500w" + src="data:{{ $encodedPlaceholder }}" + data-src="{{ (.Resize "800x").RelPermalink }}" + {{ with $altText }}alt="{{ . }}"{{ end }} + /> + + <noscript> + <img + class="cover" + loading="lazy" + srcset="{{ (.Resize "1200x").RelPermalink }} 1200w, {{ (.Resize "800x").RelPermalink }} 800w, {{ (.Resize "500x q90").RelPermalink }} 500w" + src="data:{{ $encodedPlaceholder }}" + {{ with $altText }}alt="{{ . }}"{{ end }} + /> + </noscript> +{{ end }} diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html new file mode 100644 index 0000000..6462b80 --- /dev/null +++ b/layouts/partials/footer.html @@ -0,0 +1,40 @@ +<!-- Set SVG bundle --> +{{ $icons := (.Scratch.Get "svgBundle").RelPermalink }} + +<!-- Custom footer or default copyright --> +{{ if or (templates.Exists "partials/custom/footer") (templates.Exists "partials/custom/footer.html") }} + {{ partialCached "custom/footer" . }} +{{ else }} + <p>{{ .Site.Copyright | markdownify | emojify }}</p> +{{ end }} + +<!-- + TODO + Maybe I should rethink this +--> + +{{ if gt (len .Translations) 0 }} + + {{ $processedKeys := slice }} + + {{ range .Translations }} + {{ $currentKey := printf "<a rel=\"alternate\" hreflang=\"%s\" href=\"%s\">%s</a>" .Language.Lang .RelPermalink .Language.LanguageName }} + {{ $processedKeys = $processedKeys | append $currentKey }} + {{ end }} + + <p>{{ T "also_available" }}: {{ delimit $processedKeys ", " (T "and") }}.</p> + +{{ end }} + + +<!-- Fancy stuff --> +<aside class="js"> + <button title="{{ T "change_mode" }}"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><use xlink:href="{{ $icons }}#adjust"/></svg></button><input type="color" list="presets" value="{{ if .Site.Params.Style.isDark }}{{ .Site.Params.style.darkAccent }}{{ else }}{{ .Site.Params.style.lightAccent }}{{ end }}" title="{{ T "change_accent" }}"><datalist id="presets"><option value="{{ .Site.Params.style.lightAccent }}"><option value="{{ .Site.Params.style.darkAccent }}"><!-- Extra colors -->{{- range .Site.Params.style.presets -}}<option value="{{ . }}">{{ end }}</datalist> +</aside> + +<!-- noscript notice --> +{{ if .Site.Params.hasNoscriptNotice }} + <noscript> + <p class="noscript">{{ T "noscript" }}</p> + </noscript> +{{ end }} diff --git a/layouts/partials/head.html b/layouts/partials/head.html new file mode 100644 index 0000000..fe89a10 --- /dev/null +++ b/layouts/partials/head.html @@ -0,0 +1,394 @@ +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1"> + +<!-- I'm 99% sure there's a smarter way of doing it but whatever --> +{{ $currentTitle := (.Title | emojify) }} +{{ $mainTitle := .Params.mainTitle }} + + +{{ $titleSeparator := .Site.Params.titleSeparator }} + + +{{ if (eq .Kind "404") }} + + <!-- If 404 page --> + {{ $currentTitle = .Site.Params.notFound.title }} + +{{ else if (eq .Kind "section") }} + + <!-- If it's a post list --> + {{ if gt .Paginator.TotalPages 1 }} + {{ $mainTitle = printf "%s, %s %s %s %s" .Title (T "page") (string .Paginator.PageNumber) (T "of") (string .Paginator.TotalPages) }} + {{ end }} + +{{ else if (and (ne .Kind "taxonomyTerm") (eq .Type "tags")) }} + + <!-- If it's a post list for a tag --> + {{ $currentTitle = printf "%s: \"%s\"" (T "tag") .Title }} + + {{ if gt .Paginator.TotalPages 1 }} + {{ $mainTitle = printf "%s: \"%s\", %s %s %s %s" (T "tag") .Title (T "page") (string .Paginator.PageNumber) (T "of") (string .Paginator.TotalPages) }} + {{ else }} + {{ $mainTitle = printf "%s: \"%s\"" (T "tag") .Title }} + {{ end }} + +{{ else if (and (eq .Kind "taxonomyTerm") (eq .Type "tags")) }} + + <!-- /categories/ page --> + {{ $currentTitle = (T "tags") }} + +{{ else if (and (eq .Kind "taxonomyTerm") (eq .Type "categories")) }} + + <!-- /tags/ page --> + {{ $currentTitle = (T "categories") }} + +{{ else if and (.IsHome) (not .Content) }} + + <!-- If it's the home page without content --> + {{ $currentTitle = (.Site.Title | emojify) }} + +{{ end }} + + +{{ $currentDesc := (.Params.Description | emojify) }} + +{{ if .IsHome }} + {{ $currentDesc = (.Site.Params.description | emojify) }} +{{ else if and (ne .Kind "taxonomyTerm") (eq .Type "tags") (not .Params.description) }} + {{ $currentDesc = (T "posts_under_tag" .) }} +{{ else if and (ne .Kind "taxonomyTerm") (eq .Type "categories") (not .Params.description) }} + {{ $currentDesc = (T "posts_under_category" .) }} +{{ else if eq .Kind "taxonomyTerm" }} + {{ $currentDesc = printf "%s %s." (T "page_containing") ($currentTitle | lower) }} +{{ else if (eq .Kind "404") }} + {{ $currentDesc = .Site.Params.notFound.description }} +{{ end }} + + +<!-- Scratch --> +{{ $.Scratch.Set "currentTitle" $currentTitle }} + + + +<!-- Beginning of the SEO madness --> + +<title> + {{- if and $titleSeparator (not .Params.disableTitleSeparator ) -}} + {{ if $mainTitle }} + {{- $mainTitle = printf "%s %s %s" $mainTitle $titleSeparator .Site.Title -}} + {{ else }} + {{- $mainTitle = printf "%s %s %s" $currentTitle $titleSeparator .Site.Title -}} + {{ end }} + {{- end -}} + + {{- if $mainTitle -}} + {{- $mainTitle -}} + {{ else }} + {{- $currentTitle -}} + {{- end -}} +</title> + + +{{ with .Site.Params.author }}<meta name="author" content="{{ . }}">{{ end }} +{{ with $currentDesc }}<meta name="description" content="{{ . }}">{{ end }} + + +<meta name="robots" content="{{ if and (ne .Kind "404") (ne .Params.noindex true) }}index follow{{ else }}noindex follow{{ end }}"> +<meta name="referrer" content="no-referrer-when-downgrade"> + + +<!-- Canon --> +{{ if and (.IsPage) (not .Params.sitemap_exclude) }} + {{ if .Params.canonicalURL }} + <link rel="canonical" href="{{ .Params.canonicalURL }}"> + {{ else if and (ne .Kind "404") (ne .Params.sitemap_exclude true) }} + <link rel="canonical" href="{{ .Permalink }}"> + {{ end }} +{{ else if (eq .Kind "section") }} + <link rel="canonical" href="{{ .Paginator.URL | absURL }}"> + + {{ if .Paginator.HasPrev }} + <link rel="prev" href="{{ .Paginator.Prev.URL | absURL }}"> + {{ end }} + + {{ if .Paginator.HasNext }} + <link rel="next" href="{{ .Paginator.Next.URL | absURL }}"> + {{ end }} +{{ end }} + + + +<!-- Reserved --> +{{ if or (templates.Exists "partials/custom/head") (templates.Exists "partials/custom/head.html") }} + {{ partial "custom/head" . }} +{{ end }} + + + +<!-- Open Graph / Twitter Card --> +<meta property="og:site_name" content="{{ .Site.Title }}"> +<meta property="og:title" content="{{ $currentTitle }}"> +{{ with $currentDesc }}<meta property="og:description" content="{{ . }}">{{ end }} + +{{- if ne .Kind "404" }} + <meta property="og:url" content="{{ .Permalink }}"> +{{ end -}} + + +<!-- Generated images for Open Graph, Twitter Cards and also Schema.org --> + +{{ $imgPath := .Page.Param "imgPath" }} + +{{- if .Params.cover }} + + {{ $file := .Params.cover }} + + {{ if $imgPath }} + {{ $file = path.Join $imgPath $file }} + {{ end }} + + {{- with .Resources.GetMatch $file }} + <meta property="og:image" content="{{ (.Fill "1200x630").Permalink }}"> + <meta property="og:image:width" content="1200"> + <meta property="og:image:height" content="630"> + {{ with $.Params.coverAlt }} + <meta property="og:image:alt" content="{{ . }}"> + {{ end }} + <meta name="twitter:card" content="summary_large_image"> + <meta name="twitter:image" content="{{ (.Fill "1280x640").Permalink }}"> + + {{ $.Scratch.Set "schemaCover" (.Fill "960x540").Permalink }} + {{ end -}} +{{ else if .Site.Params.cover }} + {{ with resources.Get (.Site.Params.cover | default "img/cover.jpg") }} + <meta property="og:image" content="{{ (.Fill "1200x630 center").Permalink }}"> + <meta property="og:image:width" content="1200"> + <meta property="og:image:height" content="630"> + {{ with $.Site.Params.coverAlt }} + <meta property="og:image:alt" content="{{ . }}"> + {{ end }} + <meta name="twitter:card" content="summary_large_image"> + <meta name="twitter:image" content="{{ (.Fill "1280x640 center").Permalink }}"> + + {{ $.Scratch.Set "schemaCover" (.Fill "960x540").Permalink }} + {{ end }} +{{ end -}} + +<!-- More social crap --> +{{ if and (.IsPage) (not .Params.sitemap_exclude) }} + <meta property="og:type" content="article"> + + {{ if not .Date.IsZero }} + <meta property="article:published_time" content="{{ .PublishDate.Format "2006-01-02" | safeHTML }}"> + <meta property="article:modified_time" content="{{ .Lastmod.Format "2006-01-02" | safeHTML }}"> + <meta property="og:updated_time" content="{{ .Lastmod.Format "2006-01-02" | safeHTML }}"> + {{ end }} + + {{ with .Params.author }} + <meta property="article:author" content="{{ . }}"> + {{ end }} + + {{ with .Site.Params.Social.Centralized.twitter }} + <meta name="twitter:creator" content="{{ (urls.Parse (index . 0)).Path | replaceRE "/" "@" }}"> + {{ end}} + +{{ else }} + <meta property="og:type" content="website"> +{{ end -}} + +{{ with .Site.Params.Social.Centralized.twitter }} + <meta name="twitter:site" content="{{ (urls.Parse (index . 0)).Path | replaceRE "/" "@" }}"> +{{ end }} + + + +{{ with .Site.Params.locale }} + <meta property="og:locale" content="{{ . }}"> +{{ end }} + +{{ if .Site.Config.Privacy.Twitter.EnableDNT }} + <meta name="twitter:dnt" content="on"> +{{ end }} + +<!-- Feed --> +<link rel="alternate" type="application/rss+xml" href="{{ "index.xml" | relURL }}" title="{{ .Site.Title }}"> + +<!-- i18n --> +{{ if .IsTranslated }} + {{ range .Translations }} + <link rel="alternate" hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}" title="{{ .Language.LanguageName }}"> + {{ end }} +{{ end }} + + +<!-- Will be replaced by JS anyway --> +<meta name="theme-color" content="#222"> + +<meta name="apple-mobile-web-app-capable" content="yes"> +<meta name="apple-mobile-web-app-status-bar-style" content="default"> + + +<!-- Social on Schema.org --> +{{ $sameAs := slice }} + +{{ range .Site.Params.Social.Centralized }} + {{ $sameAs = $sameAs | append (index . 0) }} +{{ end }} + +{{ range .Site.Params.Social.Decentralized }} + {{ range . }} + {{ $sameAs = $sameAs | append (index . 0) }} + {{ end }} +{{ end }} + + + +<!-- Schema Markup / Structured Data --> + +<!-- + TODO + The lack of "datePublished" will throw an error, + but I don't know if leaving it as "0001-01-01" is any better. + + Also, there's something wrong with the Google's validation tool. It's ignoring the "Person" type for https://schema.org/publisher. + + Reference: https://www.drupal.org/project/schema_metatag/issues/3097526 +--> + +{{ if and (in .Site.Params.mainSections .Section) (not .Params.sitemap_exclude) }} + <script type="application/ld+json"> + { + "@context": "https://schema.org", + "@type": "Article", + "mainEntityOfPage": { + "@type": "WebSite", + "@id": "{{ .Site.BaseURL }}" + }, + "headline": {{ $currentTitle }}, + "description": {{ $currentDesc }}, + {{ with $.Scratch.Get "schemaCover" }}"image": "{{ . }}",{{ end }} + "url": "{{ .Permalink }}", + "inLanguage": "{{ .Site.Language.Lang }}", + "datePublished": "{{ .PublishDate.Format "2006-01-02" | safeHTML }}", + {{ with .Lastmod }}"dateModified": "{{ .Format "2006-01-02" | safeHTML }}",{{ end }} + "wordCount" : "{{ .WordCount }}", + "publisher": { + "@type": "Person", + "name": "{{ .Site.Params.author }}" + }, + "author": { + "@type": "Person", + "name": "{{ .Site.Params.author }}", + {{ with .Site.Params.authorDesc }}"description": {{ . }},{{ end }} + {{ if gt (len $sameAs) 0 }}"sameAs": {{ $sameAs }}{{ end }} + } + } + </script> +{{ else }} + <script type="application/ld+json"> + { + "@context": "https://schema.org", + "@type": "WebSite", + "url": "{{ .Site.BaseURL }}", + "inLanguage": "{{ .Site.Language.Lang }}", + "name": {{ .Site.Title }}, + "description": {{ .Site.Params.description | emojify }}, + "publisher": "{{ .Site.Params.author }}" + } + </script> +{{ end }} + + + +<!-- Main CSS --> +{{ $main := resources.Get "scss/main.scss" | resources.ExecuteAsTemplate "css/main.scss" . | toCSS | minify | resources.Fingerprint "sha512" }} +<link rel="stylesheet" href="{{ $main.RelPermalink }}" integrity="{{ $main.Data.Integrity }}"> + + +<!-- If JS is disabled --> +<noscript> + + <!-- Not properly tested? --> + <meta name="theme-color" content="{{ .Site.Params.Style.lightAccent }}" {{ if .Site.Params.Style.isDark }}media="(prefers-color-scheme: light)"{{ end }}> + <meta name="theme-color" content="{{ .Site.Params.Style.darkAccent }}" {{ if not .Site.Params.Style.isDark }}media="(prefers-color-scheme: dark)"{{ end }}> + + <style> + + html { + --accent: {{ if .Site.Params.Style.isDark }}{{ .Site.Params.Style.darkAccent }}{{ else }}{{ .Site.Params.Style.lightAccent }}{{ end }}; + } + + .js, + img.lazyload { + display: none; + } + + </style> +</noscript> + + +<!-- Exclusive CSS / CSS that "ideally" should appear once --> +{{ if or (.HasShortcode "contact-form") (.HasShortcode "social") }} + <style> + {{ if .HasShortcode "contact-form" }} + {{ with resources.Get "scss/exclusive/contact-form.scss" | resources.ExecuteAsTemplate .Layout . | toCSS | minify }} + {{ .Content | safeCSS }} + {{ end }} + {{ end }} + + {{ if .HasShortcode "social" }} + {{ with resources.Get "scss/exclusive/social.scss" | resources.ExecuteAsTemplate .Layout . | toCSS | minify }} + {{ .Content | safeCSS }} + {{ end }} + {{ end }} + </style> +{{ end }} + + +<!-- Should be loaded even if browser has native lazy load support --> + +{{ $lazysizes := resources.Get "lazysizes@5.2.2/lazysizes.min.js" | resources.ExecuteAsTemplate "js/lazysizes.min.js" . | minify | resources.Fingerprint "sha512" }} + +<script defer src="{{ $lazysizes.RelPermalink }}" integrity="{{ $lazysizes.Data.Integrity }}" crossorigin="anonymous"></script> + + +<!-- KaTeX --> +{{ if or .Params.katex .Site.Params.katex .Params.math .Site.Params.math }} + <!-- Preconnect --> + <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin> +{{ end }} + + +<!-- + rel="me" + Not even sure how useful is this nowdays, + but since it's easy to implement... +--> + +{{ range .Site.Params.Social.Centralized }} + <link rel="me" href="{{ index . 0 }}"/> +{{ end }} + +{{ range .Site.Params.Social.Decentralized }} + {{ range . }} + <link rel="me" href="{{ index . 0 }}"/> + {{ end }} +{{ end }} + + +<!-- + Priority JavaScript + If not using Hugo server, remove every "console.log()" +--> + +{{ with resources.Get "js/prepone.js" | resources.ExecuteAsTemplate .Page . | minify }} + + <script> + {{ if $.Site.IsServer }} + {{ .Content | safeJS }} + {{ else }} + {{ .Content | replaceRE "console.log(.*?);" "" | safeJS }} + {{ end }} + </script> + +{{ end }} diff --git a/layouts/partials/header.html b/layouts/partials/header.html new file mode 100644 index 0000000..413b592 --- /dev/null +++ b/layouts/partials/header.html @@ -0,0 +1,21 @@ +<!-- Site title --> +{{ if or (templates.Exists "partials/custom/header") (templates.Exists "partials/custom/header.html") }} + {{ partialCached "custom/header" . }} +{{ else }} + <a href="{{ .Site.BaseURL | relLangURL }}">{{ .Site.Title }}</a> +{{ end }} + +<!-- Menu --> +{{ if .Site.Menus.main }} + {{ with .Site.Menus.main }} + <nav> + <ul> + {{ range . }} + <li> + <a class="btn" href="{{ .URL | relLangURL }}">{{ .Name }}</a> + </li> + {{ end }} + </ul> + </nav> + {{ end }} +{{ end }} diff --git a/layouts/partials/katex.html b/layouts/partials/katex.html new file mode 100644 index 0000000..64b9a37 --- /dev/null +++ b/layouts/partials/katex.html @@ -0,0 +1,45 @@ +<!-- KaTeX -->
+<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css" integrity="sha512-SBL9R0mkYbWGuy/0DLHNxYHPScUMar9Y55t8vrnN42ZYfLZ4SnjXqCFfEhPTnj9pedAs5F+WZkzjq1qGS8+VGg==" crossorigin="anonymous">
+<script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.js" integrity="sha512-2k+W+3OGhtd3whnGt33ek/oA1M/aqB6Mir+WIcCrSuIC2yD6iTX6IuPf5q1oEJGQT06jma5K6ca7Xqb4u7Urow==" crossorigin="anonymous"></script>
+
+<!-- mchem extension -->
+{{ if or (in .Params.katexExtensions "mchem") (in .Site.Params.katexExtensions "mchem") }}
+ <script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/contrib/mhchem.min.js" integrity="sha512-B4sSu3isYYpaurfStmXsh1wL71s8xKFZyNjCCuUHw8feCh9RlpG03x8+a3egFiZ1VuCoj6463IY18VnrDBbKuA==" crossorigin="anonymous"></script>
+{{ end }}
+
+<!-- copy-tex extension -->
+{{ if or (in .Params.katexExtensions "copy-tex") (in .Site.Params.katexExtensions "copy-tex") }}
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/contrib/copy-tex.css" integrity="sha512-gLOBccbZVR13Jvu/EZJAGz9C6P8CGD10sCGt/EdH5xHMKU3S9m43i6BX0ZqWIKeRo0JYXJiLi3Lv0gCAxFqz+Q==" crossorigin="anonymous">
+ <script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/contrib/copy-tex.min.js" integrity="sha512-DJT2Gf9zoglFWNuxgFcMZ3zi9Ra9GPDxpw9/8kyQ6cji+SOaLlV1A49Its53eLZlGfb4WjwRCptEUdNju6Wxgw==" crossorigin="anonymous"></script>
+{{ end }}
+
+<!-- auto-render extension + tabIndex HACK (see below) -->
+<script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/contrib/auto-render.min.js" integrity="sha512-GicGrbLBXJh2kbF+DYD+sCW5hPavoOfVAKSOE7+qgYCgVTcwe+/D4LXegS9JVTY72ovc5Ung4Fml+i1uD3uOyQ==" crossorigin="anonymous" onload="renderMathInElement(document.body);addTabIndex()"></script>
+
+<!--
+ HACK
+ Google Chrome will ignore "scroll" elements while navigating via keyboard
+ I could "fix" such behavior by using "tabindex=0"
+ But since KaTeX stuff here is being injected with JS, it seems I need to fight JS with JS
+
+ (what a BS...)
+-->
+
+<script>
+
+ function addTabIndex() {
+
+ const $katexBlocks = getAll('span.katex-display');
+
+ // While we are at it... Some a11y
+ const $katexLabel = {{ T "box_containing_expression" }};
+
+ $katexBlocks.forEach(function ($el) {
+ $el.tabIndex = 0;
+
+ $el.setAttribute('aria-label', $katexLabel);
+ })
+
+ }
+
+</script>
diff --git a/layouts/partials/pagination.html b/layouts/partials/pagination.html new file mode 100644 index 0000000..4434645 --- /dev/null +++ b/layouts/partials/pagination.html @@ -0,0 +1,133 @@ +{{ $icons := (.Scratch.Get "svgBundle").RelPermalink }} + +{{ $pag := $.Paginator }} + + +<!-- + Blatantly copied from Glenn McComb + Source: https://glennmccomb.com/articles/how-to-build-custom-hugo-pagination/ +--> + +<!-- Number of links either side of the current page. Default value is 2 --> +{{ $adjacent_links := 1 }} + +<!-- $max_links = ($adjacent_links * 2) + 1 --> +{{ $max_links := (add (mul $adjacent_links 2) 1) }} + +<!-- $lower_limit = $adjacent_links + 1 --> +{{ $lower_limit := (add $adjacent_links 1) }} + +<!-- $upper_limit = $pag.TotalPages - $adjacent_links --> +{{ $upper_limit := (sub $pag.TotalPages $adjacent_links) }} + +<!-- If there's more than one page. --> +{{ if gt $pag.TotalPages 1 }} + + <nav> + <ul class="pagination"> + + <!-- First page. --> + {{ if ne $pag.PageNumber 1 }} + <li> + <a class="btn" href="{{ $pag.First.URL }}" aria-label="{{ T "go_to_first" }}"> + <svg aria-hidden="true"> + <use transform="rotate(180) translate(-18 -18)" xlink:href="{{ $icons }}#angle-double-right"/> + </svg> + </a> + </li> + {{ end }} + + <!-- Previous page. --> + {{ if $pag.HasPrev }} + <li> + <a class="btn" href="{{ $pag.Prev.URL }}" aria-label="{{ T "go_to_prev" }}"> + <svg transform="rotate(180)" aria-hidden="true"> + <use xlink:href="{{ $icons }}#angle-right"/> + </svg> + </a> + </li> + {{ end }} + + <!-- Page numbers. --> + {{ range $pag.Pagers }} + + {{ $.Scratch.Set "page_number_flag" false }} + + <!-- Advanced page numbers. --> + {{ if gt $pag.TotalPages $max_links }} + + <!-- Lower limit pages. --> + <!-- If the user is on a page which is in the lower limit. --> + {{ if le $pag.PageNumber $lower_limit }} + + <!-- If the current loop page is less than max_links. --> + {{ if le .PageNumber $max_links }} + {{ $.Scratch.Set "page_number_flag" true }} + {{ end }} + + + <!-- Upper limit pages. --> + <!-- If the user is on a page which is in the upper limit. --> + {{ else if ge $pag.PageNumber $upper_limit }} + + <!-- If the current loop page is greater than total pages minus $max_links --> + {{ if gt .PageNumber (sub $pag.TotalPages $max_links) }} + {{ $.Scratch.Set "page_number_flag" true }} + {{ end }} + + + <!-- Middle pages. --> + {{ else }} + + {{ if and ( ge .PageNumber (sub $pag.PageNumber $adjacent_links) ) ( le .PageNumber (add $pag.PageNumber $adjacent_links) ) }} + {{ $.Scratch.Set "page_number_flag" true }} + {{ end }} + + {{ end }} + + + <!-- Simple page numbers. --> + {{ else }} + + {{ $.Scratch.Set "page_number_flag" true }} + + {{ end }} + + <!-- Output page numbers. --> + {{ if eq ($.Scratch.Get "page_number_flag") true }} + <li {{ if eq . $pag }}class="current"{{ end }}> + {{ if eq . $pag }} + <p>{{ .PageNumber }}</p> + {{ else }} + <a class="btn" href="{{ .URL }}" aria-label="{{ T "go_to_pag" . }}" >{{ .PageNumber }}</a> + {{ end }} + </li> + {{ end }} + + {{ end }} + + <!-- Next page. --> + {{ if $pag.HasNext }} + <li> + <a class="btn" href="{{ $pag.Next.URL }}" aria-label="{{ T "go_to_next" }}"> + <svg aria-hidden="true"> + <use xlink:href="{{ $icons }}#angle-right"/> + </svg> + </a> + </li> + {{ end }} + + <!-- Last page. --> + {{ if ne $pag.PageNumber $pag.TotalPages }} + <li> + <a class="btn" href="{{ $pag.Last.URL }}" aria-label="{{ T "go_to_last" }}"> + <svg aria-hidden="true"> + <use xlink:href="{{ $icons }}#angle-double-right"/> + </svg> + </a> + </li> + {{ end }} + + </ul> + </nav> +{{ end }} diff --git a/layouts/partials/tags.html b/layouts/partials/tags.html new file mode 100644 index 0000000..c750c3a --- /dev/null +++ b/layouts/partials/tags.html @@ -0,0 +1,5 @@ +<ul class="tags"> + {{ range .Site.Taxonomies.tags }} + <li><a class="btn" href="{{ .Page.RelPermalink }}" aria-label="{{ .Page.Title }} ({{ .Count }})">{{ .Page.Title }} <span>{{ .Count }}</span></a></li> + {{ end }} +</ul> diff --git a/layouts/shortcodes/abbr.html b/layouts/shortcodes/abbr.html new file mode 100644 index 0000000..7884531 --- /dev/null +++ b/layouts/shortcodes/abbr.html @@ -0,0 +1,8 @@ +<!-- + abbr "idk" "I don't know" +--> + +{{ $abbr := (.Get 0) }} +{{ $title := (.Get 1) }} + +<abbr title="{{ $title }}">{{ $abbr }}</abbr> diff --git a/layouts/shortcodes/contact-form.html b/layouts/shortcodes/contact-form.html new file mode 100644 index 0000000..8e841d9 --- /dev/null +++ b/layouts/shortcodes/contact-form.html @@ -0,0 +1,47 @@ +{{ $autoComplete := "off" }} + +{{ if or .Page.Params.Contact.autoComplete .Site.Params.Contact.autoComplete }} + {{ $autoComplete = "on" }} +{{ end }} + + +<form id="contact" action="https://formspree.io/{{ or .Page.Params.Contact.formspreeFormId .Site.Params.Contact.formspreeFormId }}" method="post" accept-charset="utf-8"> + <label>{{ T "name" }} + <input aria-label="{{ T "name" }}" type="text" name="name" minlength="3" {{ with or .Page.Params.Contact.Placeholder.name .Site.Params.Contact.Placeholder.name }}placeholder="{{ . }}"{{ end }} autocomplete="{{ $autoComplete }}" required> + </label> + + <label>Email<input aria-label="Email" type="email" name="_replyto" {{ with or .Page.Params.Contact.Placeholder.email .Site.Params.Contact.Placeholder.email }}placeholder="{{ . }}"{{ end }} autocomplete="{{ $autoComplete }}" required></label> + + {{ with or .Page.Params.Contact.subject .Site.Params.Contact.subject }} + {{ if gt (len .) 1 }} + <label>{{ T "subject" }} + <select aria-label="{{ T "subject" }}" name="_subject"> + + {{ range . }} + <option>{{ . }}</option> + {{ end }} + + </select> + </label> + {{ else }} + <input type="hidden" name="_subject" value="{{ index . 0 }}" /> + {{ end }} + {{ else }} + + {{ with or .Page.Params.Contact.Placeholder.subject .Site.Params.Contact.Placeholder.subject }} + <label>{{ T "subject" }} + <input aria-label="{{ T "subject" }}" type="text" name="_subject" minlength="6" placeholder="{{ . }}" autocomplete="{{ $autoComplete }}" required> + </label> + {{ end }} + + {{ end }} + + + <label>{{ T "message" }}<textarea id="message" aria-label="{{ T "message" }}" rows="6" name="message" {{ with or .Page.Params.Contact.messageMinLength .Site.Params.Contact.messageMinLength }}minlength="{{ . }}"{{ end }} {{ with or .Page.Params.Contact.Placeholder.message .Site.Params.Contact.Placeholder.message }}placeholder="{{ . }}"{{ end }} required></textarea></label> + + <input type="text" name="_gotcha" style="display:none"> + + <input type="submit" value="{{ T "submit" }}"> + +</form> +
\ No newline at end of file diff --git a/layouts/shortcodes/figure.html b/layouts/shortcodes/figure.html new file mode 100644 index 0000000..8c6a85e --- /dev/null +++ b/layouts/shortcodes/figure.html @@ -0,0 +1,60 @@ +<!-- + It always expects the image is inside a folder called "img". + File will be converted into 3 versions: 500w, 800w and 1200w. + + Usage: + figure "weird_cat.jpg" "Something that can (or not) be a cat." + figure file="weird_cat.jpg" alt="Something that can (or not) be a cat." + figure class="border" file="weird_cat.jpg" alt="Something that can (or not) be a cat." + figure "weird_cat.jpg" "Something that can (or not) be a cat." "border" + figure class="border" file="weird_cat.jpg" caption="Something that can (or not) be a cat." alt="Ask someone blind if a caption and alt text are the same thing." + + Default classes: + border + borderless +--> + +{{ $file := .Get "file" | default (.Get 0) }} +{{ $caption := .Get "caption" | default (.Get 1) | markdownify }} +{{ $class := .Get "class" | default (.Get 2) }} +{{ $alt := .Get "alt" | default $caption }} + + +{{ $imgPath := .Page.Param "imgPath" }} + +{{ if $imgPath }} + {{ $file = path.Join $imgPath $file }} +{{ end }} + +{{ with $.Page.Resources.GetMatch $file }} + + {{ $placeholder := (.Resize "800x png") | images.Filter (images.Contrast -100) }} + {{ $encodedPlaceholder := printf "image/png;base64,%s" ($placeholder.Content | base64Encode) }} + {{ $encodedPixel := "image/gif;base64,R0lGODdhAQABAIABAICAgP///ywAAAAAAQABAAACAkQBADs=" }} + + <figure> + <img + class="lazyload {{ $class }}" + loading="lazy" + data-srcset="{{ (.Resize "1200x").RelPermalink }} 1200w, {{ (.Resize "800x").RelPermalink }} 800w, {{ (.Resize "500x q90").RelPermalink }} 500w" + src="data:{{ $encodedPlaceholder }}" + data-src="{{ (.Resize "800x").RelPermalink }}" + {{ with $alt }}alt="{{ . }}"{{ end }} + /> + + <noscript> + <img + {{ with $class }}class="{{ . }}"{{ end }} + loading="lazy" + srcset="{{ (.Resize "1200x").RelPermalink }} 1200w, {{ (.Resize "800x").RelPermalink }} 800w, {{ (.Resize "500x q90").RelPermalink }} 500w" + src="data:{{ $encodedPlaceholder }}" + {{ with $alt }}alt="{{ . }}"{{ end }} + /> + </noscript> + + {{ with $caption }} + <figcaption>{{ . }}</figcaption> + {{ end }} + + </figure> +{{ end }} diff --git a/layouts/shortcodes/gifoid.html b/layouts/shortcodes/gifoid.html new file mode 100644 index 0000000..715f20d --- /dev/null +++ b/layouts/shortcodes/gifoid.html @@ -0,0 +1,41 @@ +<!-- + Using videos as "GIFs" + + Convert them to video using ffmpeg or whatever, place them in a + folder named "video" (can be changed via params "videoPath"), + then use this shortcode. + + For reference: + https://web.dev/replace-gifs-with-videos/ + + More references: + ffmpeg -i "cat_n_laser.gif" -b:v 0 -crf 25 "cat_n_laser.mp4" + ffmpeg -i "cat_n_laser.gif" -c vp9 -b:v 0 -crf 41 "cat_n_laser.webm" + ffmpeg -i "cat_n_laser.mp4" -vframes 1 -q:v 2 "cat_n_laser.jpg" + + Usage: + gifoid "cat_n_laser" "It's your standard internet cat chasing a laser pointer." border + + Default classes: + border + borderless + + TODO + * Write a routine (using os.Stat?) that places the smallest file + at the top of the video tag, as it's apparently important. + * Allow the user to use the full filename and the shortcode will + strip its extension. +--> + +{{ $fileName := (.Get 0) }} +{{ $title := (.Get 1) }} +{{ $class := (.Get 2) }} + +{{ $videoPath := .Page.Params.videoPath | default "video" }} +{{ $filePath := path.Join $videoPath $fileName }} + +<video class="gifoid {{ $class }}" autoplay loop muted playsinline {{ with $title }}title="{{ . }}"{{ end }}> + <source src="{{ $filePath }}.mp4" type="video/mp4"> + <source src="{{ $filePath }}.webm" type="video/webm"> + <p class="error">{{ T "missing_codec" }}</p> +</video> diff --git a/layouts/shortcodes/img.html b/layouts/shortcodes/img.html new file mode 100644 index 0000000..0c4bd7a --- /dev/null +++ b/layouts/shortcodes/img.html @@ -0,0 +1,51 @@ +<!-- + It always expects the image is inside a folder called "img". + File will be converted into 3 versions: 500w, 800w and 1200w. + + Usage examples: + img "weird_cat.jpg" "Something that can (or not) be a cat." + img file="weird_cat.jpg" alt="Something that can (or not) be a cat." + img class="border" file="weird_cat.jpg" alt="Something that can (or not) be a cat." + img "weird_cat.jpg" "Something that can (or not) be a cat." "border" + + Default classes: + border + borderless +--> + +{{ $file := .Get "file" | default (.Get 0) }} +{{ $altText := .Get "alt" | default (.Get 1) }} +{{ $class := .Get "class" | default (.Get 2) }} + + +{{ $imgPath := .Page.Param "imgPath" }} + +{{ if $imgPath }} + {{ $file = path.Join $imgPath $file }} +{{ end }} + +{{ with $.Page.Resources.GetMatch $file }} + + {{ $placeholder := (.Resize "800x png") | images.Filter (images.Contrast -100) }} + {{ $encodedPlaceholder := printf "image/png;base64,%s" ($placeholder.Content | base64Encode) }} + {{ $encodedPixel := "image/gif;base64,R0lGODdhAQABAIABAICAgP///ywAAAAAAQABAAACAkQBADs=" }} + + <img + class="lazyload {{ $class }}" + loading="lazy" + data-srcset="{{ (.Resize "1200x").RelPermalink }} 1200w, {{ (.Resize "800x").RelPermalink }} 800w, {{ (.Resize "500x q90").RelPermalink }} 500w" + src="data:{{ $encodedPlaceholder }}" + data-src="{{ (.Resize "800x").RelPermalink }}" + {{ with $altText }}alt="{{ . }}"{{ end }} + /> + + <noscript> + <img + {{ with $class }}class="{{ . }}"{{ end }} + loading="lazy" + srcset="{{ (.Resize "1200x").RelPermalink }} 1200w, {{ (.Resize "800x").RelPermalink }} 800w, {{ (.Resize "500x q90").RelPermalink }} 500w" + src="data:{{ $encodedPlaceholder }}" + {{ with $altText }}alt="{{ . }}"{{ end }} + /> + </noscript> +{{ end }} diff --git a/layouts/shortcodes/kbd.html b/layouts/shortcodes/kbd.html new file mode 100644 index 0000000..e6421b3 --- /dev/null +++ b/layouts/shortcodes/kbd.html @@ -0,0 +1,21 @@ +<!-- + usage: + kdb "Ctrl" "Shift" "i" + + output: + Ctrl + Shift + i +--> + +{{ $semanticKeyboardKeys := slice }} + +{{ range .Params }} + {{ $currentKey := printf "<kbd>%s</kbd>" . }} + + {{ $semanticKeyboardKeys = $semanticKeyboardKeys | append $currentKey }} +{{ end }} + +{{ if gt $semanticKeyboardKeys 1 }} + <kbd>{{- delimit $semanticKeyboardKeys "+" -}}</kbd> +{{ else }} + {{- delimit $semanticKeyboardKeys "+" -}} +{{ end }}
\ No newline at end of file diff --git a/layouts/shortcodes/social.html b/layouts/shortcodes/social.html new file mode 100644 index 0000000..a27a962 --- /dev/null +++ b/layouts/shortcodes/social.html @@ -0,0 +1,257 @@ +{{ $svgBundle := resources.Get "bundle.svg" | resources.ExecuteAsTemplate "img/bundle.svg" . | minify | resources.Fingerprint "md5" }} +{{ $icons := $svgBundle.RelPermalink }} + +<section class="social"> + + {{ with or .Page.Params.Social.Centralized.facebook .Site.Params.Social.Centralized.facebook }} + + {{ $url := (index . 0) }} + {{ $label := "Facebook" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#facebook"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + + {{ with or .Page.Params.Social.Centralized.github .Site.Params.Social.Centralized.github }} + + {{ $url := (index . 0) }} + {{ $label := "GitHub" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#github"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + + {{ with or .Page.Params.Social.Centralized.gitlab .Site.Params.Social.Centralized.gitlab }} + + {{ $url := (index . 0) }} + {{ $label := "GitLab" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#gitlab"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + + {{ with or .Page.Params.Social.Centralized.instagram .Site.Params.Social.Centralized.instagram }} + + {{ $url := (index . 0) }} + {{ $label := "Instagram" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#instagram"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + + {{ with or .Page.Params.Social.Centralized.keybase .Site.Params.Social.Centralized.keybase }} + + {{ $url := (index . 0) }} + {{ $label := "Keybase" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#keybase"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + + {{ with or .Page.Params.Social.Centralized.linkedin .Site.Params.Social.Centralized.linkedin }} + + {{ $url := (index . 0) }} + {{ $label := "LinkedIn" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#linkedin"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + + + + + + + + + + {{ if or .Page.Params.Social.Decentralized.mastodon .Site.Params.Social.Decentralized.mastodon }} + + {{ range or .Page.Params.Social.Decentralized.mastodon .Site.Params.Social.Decentralized.mastodon }} + + <a rel="me nofollow" href="{{ index . 0 }}" title="{{ index . 1 }} (Mastodon)"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#mastodon"/> + </svg> + + <p>{{ index . 1 | truncate 15 }}</p> + </a> + + {{ end }} + + {{ end }} + + {{ if or .Page.Params.Social.Decentralized.matrix .Site.Params.Social.Decentralized.matrix }} + + {{ range or .Page.Params.Social.Decentralized.matrix .Site.Params.Social.Decentralized.matrix }} + <a rel="me nofollow" href="{{ index . 0 }}" title="{{ index . 1 }} (Matrix)"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#matrix"/> + </svg> + + <p>{{ index . 1 | truncate 15 }}</p> + </a> + {{ end }} + + {{ end }} + + + {{ with or .Page.Params.Social.Centralized.medium .Site.Params.Social.Centralized.medium }} + + {{ $url := (index . 0) }} + {{ $label := "Medium" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#medium"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + + + {{ with or .Page.Params.Social.Centralized.stackOverflow .Site.Params.Social.Centralized.stackOverflow }} + + {{ $url := (index . 0) }} + {{ $label := "Stack Overflow" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#stack-overflow"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + + + {{ with or .Page.Params.Social.Centralized.reddit .Site.Params.Social.Centralized.reddit }} + + {{ $url := (index . 0) }} + {{ $label := "Reddit" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#reddit"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + + + {{ with or .Page.Params.Social.Centralized.telegram .Site.Params.Social.Centralized.telegram }} + + {{ $url := (index . 0) }} + {{ $label := "Telegram" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#telegram"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + + {{ with or .Page.Params.Social.Centralized.twitter .Site.Params.Social.Centralized.twitter }} + + {{ $url := (index . 0) }} + {{ $label := "Twitter" }} + + {{ with (index . 1) }} + {{ $label = . }} + {{ end }} + + <a rel="me nofollow" href="{{ $url }}" title="{{ $label }}"> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <use xlink:href="{{ $icons }}#twitter"/> + </svg> + + <p>{{ $label }}</p> + </a> + + {{ end }} + +</section>
\ No newline at end of file |