diff options
Diffstat (limited to 'layouts/_partials')
| -rw-r--r-- | layouts/_partials/footer.html | 41 | ||||
| -rw-r--r-- | layouts/_partials/head/css.html | 21 | ||||
| -rw-r--r-- | layouts/_partials/head/js.html | 16 | ||||
| -rw-r--r-- | layouts/_partials/head/meta.html | 27 | ||||
| -rw-r--r-- | layouts/_partials/head/seo.html | 46 | ||||
| -rw-r--r-- | layouts/_partials/header.html | 14 | ||||
| -rw-r--r-- | layouts/_partials/list/pagination.html | 28 | ||||
| -rw-r--r-- | layouts/_partials/list/post-card.html | 66 | ||||
| -rw-r--r-- | layouts/_partials/list/recent-posts.html | 45 | ||||
| -rw-r--r-- | layouts/_partials/navmenu.html | 48 | ||||
| -rw-r--r-- | layouts/_partials/select-language.html | 38 | ||||
| -rw-r--r-- | layouts/_partials/select-theme.html | 15 | ||||
| -rw-r--r-- | layouts/_partials/single/next-prev.html | 44 | ||||
| -rw-r--r-- | layouts/_partials/single/tags.html | 17 |
14 files changed, 466 insertions, 0 deletions
diff --git a/layouts/_partials/footer.html b/layouts/_partials/footer.html new file mode 100644 index 0000000..a0a30b2 --- /dev/null +++ b/layouts/_partials/footer.html @@ -0,0 +1,41 @@ +<footer class="site__footer" role="contentinfo"> + <p>© {{ now.Year }} {{ site.Params.author.name }}</p> + + <nav class="follow-me-links" aria-label="Follow me on:"> + <ul class="follow-me-list"> + {{- range site.Params.socials }} + <li class="follow-me-item"> + <a + href="{{ .url }}" + aria-label="{{ .name }}" + title="{{ .name }}" + rel="me noopener noreferrer" + target="_blank" + > + <img + src="{{ .icon }}" + class="icon icon-{{ lower .name }}" + alt="{{ .name }}" + aria-hidden="true" + /> + </a> + </li> + {{- end }} + <li class="follow-me-item"> + <a + href="{{ site.Home.Permalink }}index.xml" + aria-label="RSS Feed" + title="RSS Feed" + target="_blank" + > + <img + src="/rss.svg" + class="icon icon-rss" + alt="RSS Feed" + aria-hidden="true" + /> + </a> + </li> + </ul> + </nav> +</footer> diff --git a/layouts/_partials/head/css.html b/layouts/_partials/head/css.html new file mode 100644 index 0000000..d4e894e --- /dev/null +++ b/layouts/_partials/head/css.html @@ -0,0 +1,21 @@ +{{- with resources.Get "css/main.css" -}} + {{- $allStylesheets := slice + . + (resources.Get "css/header.css") + (resources.Get "css/navmenu.css") + (resources.Get "css/footer.css") + (resources.Get "css/post-card.css") + (resources.Get "css/page.css") + (resources.Get "css/post.css") + (resources.Get "css/list-navigation.css") + (resources.Get "css/search.css") + -}} + {{- $cssBundle := $allStylesheets | resources.Concat "css/bundle.css" -}} + + {{- if hugo.IsDevelopment -}} + <link rel="stylesheet" href="{{ $cssBundle.RelPermalink }}"> + {{- else -}} + {{- $css := $cssBundle | minify | fingerprint -}} + <link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}" crossorigin="anonymous"> + {{- end -}} +{{- end -}} diff --git a/layouts/_partials/head/js.html b/layouts/_partials/head/js.html new file mode 100644 index 0000000..0baf831 --- /dev/null +++ b/layouts/_partials/head/js.html @@ -0,0 +1,16 @@ +{{- with resources.Get "js/main.js" }} + {{- $opts := dict + "minify" (not hugo.IsDevelopment) + "sourceMap" (cond hugo.IsDevelopment "external" "") + "targetPath" "js/main.js" + }} + {{- with . | js.Build $opts }} + {{- if hugo.IsDevelopment }} + <script defer src="{{ .RelPermalink }}"></script> + {{- else }} + {{- with . | fingerprint }} + <script defer src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script> + {{- end }} + {{- end }} + {{- end }} +{{- end -}} diff --git a/layouts/_partials/head/meta.html b/layouts/_partials/head/meta.html new file mode 100644 index 0000000..f739838 --- /dev/null +++ b/layouts/_partials/head/meta.html @@ -0,0 +1,27 @@ +{{- /* Basic Meta */ -}} +<meta name="author" content="{{ site.Params.author.name | default site.Title }}"> +<meta name="robots" content="index, follow"> + +{{- /* Open Graph */ -}} +<meta property="og:title" content="{{ .Title | default site.Title }}"> +<meta property="og:description" content="{{ .Description | default .Summary }}"> +<meta property="og:type" content="{{ if .IsHome }}website{{ else }}article{{ end }}"> +<meta property="og:url" content="{{ .Permalink }}"> +<meta property="og:site_name" content="{{ site.Title }}"> +{{- with site.Params.logo }} + <meta property="og:image" content="{{ . | absURL }}"> +{{- end }} +{{- if .IsPage }} + <meta property="article:published_time" content="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}"> + {{- with .Lastmod }} + <meta property="article:modified_time" content="{{ .Format "2006-01-02T15:04:05Z07:00" }}"> + {{- end }} +{{- end }} + +{{- /* Twitter Card */ -}} +<meta name="twitter:card" content="summary_large_image"> +<meta name="twitter:title" content="{{ .Title | default site.Title }}"> +<meta name="twitter:description" content="{{ .Description | default .Summary }}"> +{{- with site.Params.logo }} + <meta name="twitter:image" content="{{ . | absURL }}"> +{{- end }} diff --git a/layouts/_partials/head/seo.html b/layouts/_partials/head/seo.html new file mode 100644 index 0000000..628ea2c --- /dev/null +++ b/layouts/_partials/head/seo.html @@ -0,0 +1,46 @@ +<script type="application/ld+json"> +{ + "@context": "https://schema.org", + "@type": "{{ if .IsPage }}Article{{ else }}WebSite{{ end }}", + "url": {{ .Permalink }}, + "name": {{ with .Title }}{{ . }}{{ else }}{{ site.Title }}{{ end }}, + "headline": {{ with .Title }}{{ . }}{{ else }}{{ site.Title }}{{ end }}, + "description": {{ with .Description }}{{ . }}{{ else }}{{ site.Params.description | default site.Title }}{{ end }}, + {{- with .Params.images }} + "image": [ + {{- range $i, $image := . }} + {{- if $i }},{{ end }} + "{{ $image | absURL }}" + {{- end }} + ], + {{- else }} + {{- with site.Params.logo }} + "image": ["{{ . | absURL }}"], + {{- end }} + {{- end }} + {{- if .IsPage }} + "datePublished": "{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}", + {{- with .Lastmod }} + "dateModified": "{{ .Format "2006-01-02T15:04:05Z07:00" }}", + {{- end }} + {{- end }} + "author": { + "@type": "Person", + "name": "{{ site.Params.author.name | default site.Title }}" + }, + "publisher": { + "@type": "Organization", + "name": "{{ site.Title }}" + {{- with site.Params.logo }}, + "logo": { + "@type": "ImageObject", + "url": "{{ . | absURL }}" + } + {{- end }} + }, + "mainEntityOfPage": { + "@type": "WebPage", + "@id": {{ .Permalink }} + } +} +</script> diff --git a/layouts/_partials/header.html b/layouts/_partials/header.html new file mode 100644 index 0000000..f38b6f2 --- /dev/null +++ b/layouts/_partials/header.html @@ -0,0 +1,14 @@ +<header class="site__header" role="banner"> + <a href="{{ site.Home.RelPermalink }}" rel="home" class="site-{{ if site.Params.logo }}logo{{ else }}title{{ end }}"> + {{- with site.Params.logo }} + <img src="{{ . }}" alt="{{ site.Title }}" /> + {{- else }} + {{ site.Title }} + {{- end }} + </a> + + <div class="site-selections"> + {{- partial "select-theme.html" . }} + {{- partial "select-language.html" . }} + </div> +</header> diff --git a/layouts/_partials/list/pagination.html b/layouts/_partials/list/pagination.html new file mode 100644 index 0000000..dfe8178 --- /dev/null +++ b/layouts/_partials/list/pagination.html @@ -0,0 +1,28 @@ +{{- $paginator := . }} +{{- if gt $paginator.TotalPages 1 }} +<nav class="pagination" aria-label="{{ lang.Translate "page_navigation" | default "Page navigation" }}"> + {{- if $paginator.HasPrev }} + <a href="{{ $paginator.Prev.URL }}" + class="pagination__link" + rel="prev" + aria-label="{{ lang.Translate "page_previous" | default "Previous page" }}" + > + ← {{ lang.Translate "previous" | default "Previous" }} + </a> + {{- end }} + + <p class="pagination__current"> + {{ lang.Translate "page_position" $paginator.PageNumber $paginator.TotalPages | default (printf "Page %d of %d" $paginator.PageNumber $paginator.TotalPages) }} + </p> + + {{- if $paginator.HasNext }} + <a href="{{ $paginator.Next.URL }}" + class="pagination__link" + rel="next" + aria-label="{{ lang.Translate "page_next" | default "Next page" }}" + > + {{ lang.Translate "next" | default "Next" }} → + </a> + {{- end }} +</nav> +{{- end }} diff --git a/layouts/_partials/list/post-card.html b/layouts/_partials/list/post-card.html new file mode 100644 index 0000000..6444701 --- /dev/null +++ b/layouts/_partials/list/post-card.html @@ -0,0 +1,66 @@ +{{- /* +Card with a summary of and link to a post. Accepts a dict with the following parameters: + +@context {Page} post: The post to display. +@context {bool} show_section: Whether to display a badge with the name of the section the post was published under (default: false). + +@example: {{ partial "list/post-card.html" (dict "post" . "show_section" true) }} +*/ -}} + +{{- $post := .post -}} +{{- $showSection := .show_section | default false -}} +<article class="post-card"> + <header class="post-card__header"> + <h3 class="post-card__title"> + <a href="{{ $post.RelPermalink }}" class="post-card__link"> + {{ $post.Title }} + </a> + </h3> + <div class="post-card__meta"> + <time datetime="{{ $post.Date.Format "2006-01-02T15:04:05Z07:00" }}" class="post-card__publish-date"> + {{ $post.Date | time.Format ":date_medium" }} + </time> + <!-- Uncomment for post meta info + <p class="post-card__meta-info"> + <span class="post-card__reading-time"> + • {{ lang.Translate "reading_time" $post.ReadingTime | default (printf "Estimated reading time: %s min" $post.ReadingTime) }} + </span> + | + <span class="post-card__word-count"> + {{ lang.Translate "word_count" $post.WordCount | default (printf "%s words" $post.WordCount) }} • + </span> + </p> + --> + {{- if $showSection }} + <span class="post-card__section-badge"> + {{ lang.Translate ($post.Section | singularize) | default ($post.Section | singularize | title) }} + </span> + {{- end }} + </div> + </header> + + {{- with $post.Summary }} + <div class="post-card__summary"> + {{ . }} + </div> + {{- end }} + + {{- with $post.Params.tags }} + <footer class="post-card__tags"> + <ul class="post-card__tags-list"> + {{- range first 3 . }} + <li class="post-card__tags-item"> + #{{ . }} + </li> + {{- end }} + {{- if gt (len .) 3 }} + <li class="post-card__tags-item post-card__tags-more"> + <span class="post-card__tags-more-count"> + +{{ sub (len .) 3 }} {{ lang.Translate "more" | default "more" }} + </span> + </li> + {{- end }} + </ul> + </footer> + {{- end }} +</article> diff --git a/layouts/_partials/list/recent-posts.html b/layouts/_partials/list/recent-posts.html new file mode 100644 index 0000000..464e9f7 --- /dev/null +++ b/layouts/_partials/list/recent-posts.html @@ -0,0 +1,45 @@ +{{- /* +List of specified number of the most recent and published posts. Accepts a dict with the following optional parameters: + +@context {int} count: Number of posts to display (default: 10). +@context {string} title: Section title (default: "Recent Articles"). +@context {bool} show_view_all: Whether to show "View All Posts" link (default: true). + +@example: {{ partial "list/recent-posts.html" (dict "count" 20 "title" "Latest updates" "show_view_all" true) }} +*/ -}} + +{{- $count := .count | default 10 -}} +{{- $title := .title | default (lang.Translate "posts_recent" | default "Recent Articles") -}} +{{- $showViewAll := .show_view_all | default true -}} +<section class="recent-posts" aria-labelledby="recent-posts-heading"> + <header class="recent-posts__header"> + <h2 id="recent-posts-heading" class="recent-posts__title"> + {{ $title }} + </h2> + </header> + + {{- $recentPosts := where site.RegularPages "Params.excludeFromLists" "!=" true | first $count }} + {{- if $recentPosts }} + <div class="recent-posts__content"> + <ul class="recent-posts__list" role="list"> + {{- range $recentPosts }} + <li class="recent-posts__list-item"> + {{- partial "list/post-card.html" (dict "post" . "show_section" true) }} + </li> + {{- end }} + </ul> + + {{- if $showViewAll }} + {{- with site.GetPage "/all-posts"}} + <a href="{{ .RelPermalink }}" class="recent-posts__view-all-link"> + {{ lang.Translate "posts_all_view" | default "View all posts" }} » + </a> + {{- end }} + {{- end }} + </div> + {{ else }} + <p class="recent-posts__empty-message"> + {{ lang.Translate "list_empty" | default "No posts in this section." }} + </p> + {{- end }} +</section> diff --git a/layouts/_partials/navmenu.html b/layouts/_partials/navmenu.html new file mode 100644 index 0000000..af0fc2e --- /dev/null +++ b/layouts/_partials/navmenu.html @@ -0,0 +1,48 @@ +{{- /* +Simplified version of the `hugo new template` menu.html default. Renders a menu for the given menu ID. + +@context {page} page: The current page. +@context {string} menuID: The menu ID. + +@example: {{ partial "navmenu.html" (dict "menuID" "main" "page" .) }} +*/}} + +{{- $currentPage := .page }} +{{- $menuID := .menuID }} + +{{- with index site.Menus $menuID }} +<nav role="navigation" aria-label="{{ lang.Translate "navmenu" | default "Site navigation" }}" class="header__navigation"> + <ul class="header__navigation-list"> + {{- range . }} + {{- $isCurrentPage := $currentPage.IsMenuCurrent .Menu . }} + {{- $isAncestorPage := $currentPage.HasMenuCurrent .Menu . }} + {{- $isActive := or $isCurrentPage $isAncestorPage }} + {{- $menuItemName := .Name }} + + {{- $attrs := dict "href" .URL }} + {{- if $currentPage.IsMenuCurrent .Menu . }} + {{- $attrs = merge $attrs (dict "class" "active" "aria-current" "page") }} + {{- else if $currentPage.HasMenuCurrent .Menu .}} + {{- $attrs = merge $attrs (dict "class" "ancestor" "aria-current" "true") }} + {{- end }} + + <!-- Translations --> + {{- with .Identifier }} + {{- with lang.Translate . }} + {{- $menuItemName = . }} + {{- end }} + {{- end }} + + <li class="header__navigation--list-item"> + <a + href="{{ .URL }}" + class="header__navigation-link{{ if $isActive }} header__navigation-link--active{{ end }}" + aria-current="{{ if $isCurrentPage }}page{{ else if $isAncestorPage }}true{{ end }}" + > + {{ $menuItemName }} + </a> + </li> + {{- end }} + </ul> +</nav> +{{- end -}} diff --git a/layouts/_partials/select-language.html b/layouts/_partials/select-language.html new file mode 100644 index 0000000..6efcc61 --- /dev/null +++ b/layouts/_partials/select-language.html @@ -0,0 +1,38 @@ +{{- /* +Selection of available languages. +Dynamically links to corresponding page/post if a translated version exists, otherwise to homepage of that language as fallback. + +Note: `$activeLang` and `$allTranslationsForPage` are technically unnecessary variables, their values could be called with `$.Lang` and `$.Translations` respectively. +These variables - together with the explicit naming of `.` context variables in other cases - were chosen for better readability and understandability of the code. +*/ -}} + +{{- if gt (len site.Languages) 1 }} +{{- $activeLang := .Lang }} +{{- $allTranslationsForPage := .Translations }} + <div class="language-select"> + <ul class="language-select__language-list"> + {{- range site.Languages }} + {{- $currLangSlice := . }} + {{- if ne $currLangSlice.Lang $activeLang }} + {{- $targetPage := index (where site.Home.Translations "Lang" $currLangSlice.Lang) 0 }} + {{- $translatedPage := index (where $allTranslationsForPage "Lang" $currLangSlice.Lang) 0 }} + {{- if $translatedPage }}{{- $targetPage = $translatedPage }}{{- end }} + <li class="language-select__language-item"> + <a + href="{{ $targetPage.RelPermalink }}" + hreflang="{{ $targetPage.Lang }}" + aria-label="{{ $targetPage.LinkTitle }} ({{ or $targetPage.Language.LanguageName $targetPage.Lang }})" + > + <img + src="/flags/{{ $targetPage.Lang }}.svg" + class="icon icon-flag" + alt="{{ $targetPage.LinkTitle }} ({{ or $targetPage.Language.LanguageName $targetPage.Lang }})" + aria-hidden="true" + /> + </a> + </li> + {{- end }} + {{- end }} + </ul> + </div> +{{- end }} diff --git a/layouts/_partials/select-theme.html b/layouts/_partials/select-theme.html new file mode 100644 index 0000000..914eacc --- /dev/null +++ b/layouts/_partials/select-theme.html @@ -0,0 +1,15 @@ +<button + type="button" + id="theme-toggle" + class="theme-toggle" + aria-label="{{ lang.Translate "toggle_dark" }}" + data-label-dark="{{ lang.Translate "toggle_dark" }}" + data-label-light="{{ lang.Translate "toggle_light" }}" +> + <svg class="icon icon-moon" xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 16 16" aria-hidden="true"> + <path fill="currentColor" d="M6 .278a.768.768 0 0 1 .08.858a7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277c.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316a.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71C0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"></path> + </svg> + <svg class="icon icon-sun" xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 16 16" aria-hidden="true"> + <path fill="currentColor" d="M8 12a4 4 0 1 0 0-8a4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"/> + </svg> +</button> diff --git a/layouts/_partials/single/next-prev.html b/layouts/_partials/single/next-prev.html new file mode 100644 index 0000000..932fcac --- /dev/null +++ b/layouts/_partials/single/next-prev.html @@ -0,0 +1,44 @@ +{{- /* Navigation for next & previous post and back to top */ -}} +{{- if ne .Params.excludeFromLists true }} +<nav class="post__navigation" aria-label="{{ lang.Translate "posts_navigation" | default "Post navigation" }}"> + <hr /> + <ul class="post__navigation-list"> + {{- with .PrevInSection }} + <li class="post__navigation-prev"> + <a href="{{ .RelPermalink }}" class="post__navigation-link" rel="prev"> + <span class="post__navigation-label"> + ← {{ lang.Translate "posts_previous" | default "Previous post:" }} + </span> + <span class="post__navigation-title"> + {{ .Title }} + </span> + </a> + </li> + {{- end }} + + {{- with .NextInSection }} + <li class="post__navigation-next"> + <a href="{{ .RelPermalink }}" class="post__navigation-link" rel="next"> + <span class="post__navigation-label"> + → {{ lang.Translate "posts_next" | default "Next post:" }} + </span> + <span class="post__navigation-title"> + {{ .Title }} + </span> + </a> + </li> + {{- end }} + </ul> +</nav> + +<a + href="#" + class="post__scroll-top" + aria-label="{{ lang.Translate "back_top" | default "Back to top" }}" + title="{{ lang.Translate "back_top" | default "Back to top" }}" +> + <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> + <path d="M17 15L12 10L7 15" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> + </svg> +</a> +{{- end }} diff --git a/layouts/_partials/single/tags.html b/layouts/_partials/single/tags.html new file mode 100644 index 0000000..0c10d20 --- /dev/null +++ b/layouts/_partials/single/tags.html @@ -0,0 +1,17 @@ +{{- with .GetTerms "tags" }} +<section class="post__tags" aria-labelledby="tags-heading"> + <p id="tags-heading" class="post__tags-heading"> + {{ lang.Translate "tags" | default "Tags" }} + </p> + + <ul class="post__tags-list"> + {{- range . }} + <li class="post__tags-item"> + <a href="{{ .RelPermalink }}" class="post__tags-link" rel="tag"> + #{{ .Title }} + </a> + </li> + {{- end }} + </ul> +</section> +{{- end }} |
