diff options
author | Alexander Neonxp Kiryukhin <i@neonxp.ru> | 2024-11-03 20:08:36 +0300 |
---|---|---|
committer | Alexander Neonxp Kiryukhin <i@neonxp.ru> | 2024-11-03 20:08:36 +0300 |
commit | 59c7d4567380d1a9c80e96eb958fdbdd512ce006 (patch) | |
tree | 65410cfc10dbc7d060ec23be110662d9b7f6b0e9 /themes/hugo-theme-stack/layouts |
новая жизнь блога
Diffstat (limited to 'themes/hugo-theme-stack/layouts')
70 files changed, 1867 insertions, 0 deletions
diff --git a/themes/hugo-theme-stack/layouts/404.html b/themes/hugo-theme-stack/layouts/404.html new file mode 100644 index 0000000..98f4a67 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/404.html @@ -0,0 +1,45 @@ +{{ define "main" }} + <div class="not-found-card"> + <h1 class="article-title">{{ T "notFound.title" }}</h1> + <h2 class="article-subtitle">{{ T "notFound.subtitle" }}</h2> + </div> + + {{- $query := first 1 (where .Site.Pages "Layout" "==" "search") -}} + {{- $searchPage := index $query 0 -}} + + {{- with $searchPage -}} + <form action="{{ $searchPage.RelPermalink }}" class="search-form widget" {{ with .OutputFormats.Get "json" -}}data-json="{{ .Permalink }}" {{- end }}> + <p> + <label>{{ T "search.title" }}</label> + <input id="searchInput" name="keyword" required placeholder="{{ T `search.placeholder` }}" /> + + <button title="{{ T `search.title` }}"> + {{ partial "helper/icon" "search" }} + </button> + </p> + </form> + + <div class="search-result"> + <h3 class="search-result--title section-title"></h3> + <div class="search-result--list article-list--compact"></div> + </div> + + <script> + window.searchResultTitleTemplate = "{{ T `search.resultTitle` }}" + </script> + + {{- $opts := dict "minify" hugo.IsProduction "JSXFactory" "createElement" -}} + {{- $searchScript := resources.Get "ts/search.tsx" | js.Build $opts -}} + <script type="text/javascript" src="{{ $searchScript.RelPermalink }}" defer></script> + + <script> + const wrongUrl = new URL(window.location.href); + + /// Get the search keyword from the wrong URL by removing all slashes and dashes + const searchKeyword = wrongUrl.pathname.split(/[/|-]/).join(' ').trim(); + + document.getElementById('searchInput').setAttribute('value', searchKeyword); + </script> + {{- end -}} + {{ partialCached "footer/footer" . }} +{{ end }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/_default/_markup/render-heading.html b/themes/hugo-theme-stack/layouts/_default/_markup/render-heading.html new file mode 100644 index 0000000..f79308a --- /dev/null +++ b/themes/hugo-theme-stack/layouts/_default/_markup/render-heading.html @@ -0,0 +1,6 @@ +<h{{ .Level }} id="{{ .Anchor }}"> + {{- if site.Params.Article.HeadingAnchor -}} + <a href="#{{ .Anchor }}" class="header-anchor"></a> + {{- end -}} + {{ .Text | safeHTML }} +</h{{ .Level }}>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/_default/_markup/render-image.html b/themes/hugo-theme-stack/layouts/_default/_markup/render-image.html new file mode 100644 index 0000000..0ed5584 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/_default/_markup/render-image.html @@ -0,0 +1,41 @@ +{{- $image := .Page.Resources.GetMatch (printf "%s" (.Destination | safeURL)) -}} +{{- $Permalink := .Destination | relURL | safeURL -}} +{{- $alt := .PlainText | safeHTML -}} +{{- $Width := 0 -}} +{{- $Height := 0 -}} +{{- $Srcset := "" -}} + +{{/* SVG and external images won't work with gallery layout, because their width and height attributes are unknown */}} +{{- $galleryImage := false -}} + +{{- if $image -}} + {{- $notSVG := ne (path.Ext .Destination) ".svg" -}} + {{- $Permalink = $image.RelPermalink -}} + + {{- if $notSVG -}} + {{- $Width = $image.Width -}} + {{- $Height = $image.Height -}} + {{- $galleryImage = true -}} + + {{- if (default true .Page.Site.Params.imageProcessing.content.enabled) -}} + {{- $small := $image.Resize `480x` -}} + {{- $big := $image.Resize `1024x` -}} + {{- $Srcset = printf `%s 480w, %s 1024w` $small.RelPermalink $big.RelPermalink -}} + {{- end -}} + {{- end -}} +{{- end -}} + +<img src="{{ $Permalink }}" + {{ with $Width }}width="{{ . }}"{{ end }} + {{ with $Height }}height="{{ . }}"{{ end }} + {{ with $Srcset }}srcset="{{ . }}"{{ end }} + loading="lazy" + {{ with $alt }} + alt="{{ . }}" + {{ end }} + {{ if $galleryImage }} + class="gallery-image" + data-flex-grow="{{ div (mul $image.Width 100) $image.Height }}" + data-flex-basis="{{ div (mul $image.Width 240) $image.Height }}px" + {{ end }} +>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/_default/_markup/render-link.html b/themes/hugo-theme-stack/layouts/_default/_markup/render-link.html new file mode 100644 index 0000000..843854d --- /dev/null +++ b/themes/hugo-theme-stack/layouts/_default/_markup/render-link.html @@ -0,0 +1,3 @@ +<a class="link" href="{{ .Destination | safeURL }}" {{ with .Title}} title="{{ . }}" + {{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener" + {{ end }}>{{ .Text | safeHTML }}</a>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/_default/archives.html b/themes/hugo-theme-stack/layouts/_default/archives.html new file mode 100644 index 0000000..5d5243c --- /dev/null +++ b/themes/hugo-theme-stack/layouts/_default/archives.html @@ -0,0 +1,35 @@ +{{ define "body-class" }}template-archives{{ end }} +{{ define "main" }} + <header> + {{- $taxonomy := $.Site.GetPage "taxonomyTerm" "categories" -}} + {{- $terms := $taxonomy.Pages -}} + {{ if $terms }} + <h2 class="section-title">{{ $taxonomy.Title }}</h2> + <div class="subsection-list"> + <div class="article-list--tile"> + {{ range $terms }} + {{ partial "article-list/tile" (dict "context" . "size" "250x150" "Type" "taxonomy") }} + {{ end }} + </div> + </div> + {{ end }} + </header> + + {{ $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections }} + {{ $notHidden := where .Site.RegularPages "Params.hidden" "!=" true }} + {{ $filtered := ($pages | intersect $notHidden) }} + + {{ range $filtered.GroupByDate "2006" }} + {{ $id := lower (replace .Key " " "-") }} + <div class="archives-group" id="{{ $id }}"> + <h2 class="archives-date section-title"><a href="{{ $.RelPermalink }}#{{ $id }}">{{ .Key }}</a></h2> + <div class="article-list--compact"> + {{ range .Pages }} + {{ partial "article-list/compact" . }} + {{ end }} + </div> + </div> + {{ end }} + + {{ partialCached "footer/footer" . }} +{{ end }} diff --git a/themes/hugo-theme-stack/layouts/_default/baseof.html b/themes/hugo-theme-stack/layouts/_default/baseof.html new file mode 100644 index 0000000..83fdaa3 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/_default/baseof.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html lang="{{ .Site.LanguageCode }}" dir="{{ default `ltr` .Language.LanguageDirection }}"> + <head> + {{- partial "head/head.html" . -}} + {{- block "head" . -}}{{ end }} + </head> + <body class="{{ block `body-class` . }}{{ end }}"> + {{- partial "head/colorScheme" . -}} + + {{/* The container is wider when there's any activated widget */}} + {{- $hasWidget := false -}} + {{- range .Site.Params.widgets -}} + {{- if gt (len .) 0 -}} + {{- $hasWidget = true -}} + {{- end -}} + {{- end -}} + <div class="container main-container flex on-phone--column {{ if $hasWidget }}extended{{ else }}compact{{ end }}"> + {{- block "left-sidebar" . -}} + {{ partial "sidebar/left.html" . }} + {{- end -}} + {{- block "right-sidebar" . -}}{{ end }} + <main class="main full-width"> + {{- block "main" . }}{{- end }} + </main> + </div> + {{ partial "footer/include.html" . }} + </body> +</html> diff --git a/themes/hugo-theme-stack/layouts/_default/list.html b/themes/hugo-theme-stack/layouts/_default/list.html new file mode 100644 index 0000000..9bc618d --- /dev/null +++ b/themes/hugo-theme-stack/layouts/_default/list.html @@ -0,0 +1,85 @@ +{{ define "main" }} + <header> + <h3 class="section-title"> + {{ if eq .Parent (.GetPage "/") }} + {{ T "list.section" }} + {{ else }} + {{ .Parent.Title }} + {{ end }} + </h3> + + <div class="section-card"> + <div class="section-details"> + <h3 class="section-count">{{ T "list.page" (len .Pages) }}</h3> + <h1 class="section-term">{{ .Title }}</h1> + {{ with .Params.description }} + <h2 class="section-description">{{ . }}</h2> + {{ end }} + </div> + + {{- $image := partialCached "helper/image" (dict "Context" . "Type" "section") .RelPermalink "section" -}} + {{ if $image.exists }} + <div class="section-image"> + {{ if $image.resource }} + {{- $Permalink := $image.resource.RelPermalink -}} + {{- $Width := $image.resource.Width -}} + {{- $Height := $image.resource.Height -}} + + {{- if (default true .Page.Site.Params.imageProcessing.cover.enabled) -}} + {{- $thumbnail := $image.resource.Fill "120x120" -}} + {{- $Permalink = $thumbnail.RelPermalink -}} + {{- $Width = $thumbnail.Width -}} + {{- $Height = $thumbnail.Height -}} + {{- end -}} + + <img src="{{ $Permalink }}" + width="{{ $Width }}" + height="{{ $Height }}" + loading="lazy"> + {{ else }} + <img src="{{ $image.permalink }}" loading="lazy" /> + {{ end }} + </div> + {{ end }} + </div> + </header> + + {{- $subsections := .Sections -}} + {{- $pages := .Pages | complement $subsections -}} + + {{- if eq (len $pages) 0 -}} + {{/* If there are no normal pages, display subsections in list style, with pagination */}} + {{/* This happens with taxonomies like categories or tags */}} + {{- $pages = $subsections -}} + {{- $subsections = slice -}} + {{- end -}} + + {{- with $subsections -}} + <aside> + <h2 class="section-title">{{ T "list.subsection" (len $subsections) }}</h2> + <div class="subsection-list"> + <div class="article-list--tile"> + {{ range . }} + {{ partial "article-list/tile" (dict "context" . "size" "250x150" "Type" "section") }} + {{ end }} + </div> + </div> + </aside> + {{- end -}} + + {{/* List only pages that are not a subsection */}} + {{ $paginator := .Paginate $pages }} + <section class="article-list--compact"> + {{ range $paginator.Pages }} + {{ partial "article-list/compact" . }} + {{ end }} + </section> + + {{- partial "pagination.html" . -}} + + {{ partialCached "footer/footer" . }} +{{ end }} + +{{ define "right-sidebar" }} + {{ partial "sidebar/right.html" (dict "Context" . "Scope" "homepage") }} +{{ end }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/_default/rss.xml b/themes/hugo-theme-stack/layouts/_default/rss.xml new file mode 100644 index 0000000..3d2e592 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/_default/rss.xml @@ -0,0 +1,48 @@ +{{- $pctx := . -}} +{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}} +{{- $pages := slice -}} +{{- if or $.IsHome $.IsSection -}} +{{- $pages = $pctx.RegularPages -}} +{{- else -}} +{{- $pages = $pctx.Pages -}} +{{- end -}} +{{- $pages := where $pages "Params.hidden" "!=" true -}} +{{- $limit := .Site.Config.Services.RSS.Limit -}} +{{- if ge $limit 1 -}} +{{- $pages = $pages | first $limit -}} +{{- end -}} +{{- 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>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title> + <link>{{ .Permalink }}</link> + <description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}</description> + <generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }} + <language>{{.}}</language>{{end}}{{ with .Site.Params.Author.email }} + <managingEditor>{{.}}{{ with $.Site.Params.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Params.Author.email }} + <webMaster>{{.}}{{ with $.Site.Params.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }} + <copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }} + <lastBuildDate>{{ (index $pages.ByLastmod.Reverse 0).Lastmod.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 $pages }} + {{- $content := safeHTML (.Summary | html) -}} + {{- if .Site.Params.rssFullContent -}} + {{- $content = safeHTML (.Content | html) -}} + {{- end -}} + <item> + <title>{{ .Title }}</title> + <link>{{ .Permalink }}</link> + <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate> + {{ with .Site.Params.Author.email }}<author>{{.}}{{ with $.Site.Params.Author.name }} ({{.}}){{end}}</author>{{end}} + <guid>{{ .Permalink }}</guid> + <description> + {{- $image := partial "helper/image" (dict "Context" . "Type" "rss") -}} + {{- if $image.exists -}} + {{ "<" | html }}img src="{{ $image.permalink | absURL }}" alt="Featured image of post {{ .Title }}" {{ "/>" | html}} + {{- end -}}{{ $content }}</description> + </item> + {{ end }} + </channel> +</rss> diff --git a/themes/hugo-theme-stack/layouts/_default/single.html b/themes/hugo-theme-stack/layouts/_default/single.html new file mode 100644 index 0000000..5f300bf --- /dev/null +++ b/themes/hugo-theme-stack/layouts/_default/single.html @@ -0,0 +1,46 @@ +{{ define "body-class" }} + article-page + {{/* + Enable the right sidebar if + - Widget different from 'TOC' is enabled + - TOC is enabled and not empty + */}} + {{- $HasWidgetNotTOC := false -}} + {{- $TOCWidgetEnabled := false -}} + {{- range .Site.Params.widgets.page -}} + {{- if ne .type "toc" -}} + {{ $HasWidgetNotTOC = true -}} + {{- else -}} + {{ $TOCWidgetEnabled = true -}} + {{- end -}} + {{- end -}} + + {{- $TOCManuallyDisabled := eq .Params.toc false -}} + {{- $TOCEnabled := and (not $TOCManuallyDisabled) $TOCWidgetEnabled -}} + {{- $hasTOC := ge (len .TableOfContents) 100 -}} + {{- .Scratch.Set "TOCEnabled" (and $TOCEnabled $hasTOC) -}} + + {{- .Scratch.Set "hasWidget" (or $HasWidgetNotTOC (and $TOCEnabled $hasTOC)) -}} +{{ end }} + +{{ define "main" }} + {{ partial "article/article.html" . }} + + {{ if .Params.links }} + {{ partial "article/components/links" . }} + {{ end }} + + {{ partial "article/components/related-content" . }} + + {{ if not (eq .Params.comments false) }} + {{ partial "comments/include" . }} + {{ end }} + + {{ partialCached "footer/footer" . }} + + {{ partialCached "article/components/photoswipe" . }} +{{ end }} + +{{ define "right-sidebar" }} + {{ if .Scratch.Get "hasWidget" }}{{ partial "sidebar/right.html" (dict "Context" . "Scope" "page") }}{{ end}} +{{ end }} diff --git a/themes/hugo-theme-stack/layouts/index.html b/themes/hugo-theme-stack/layouts/index.html new file mode 100644 index 0000000..0cd0b88 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/index.html @@ -0,0 +1,19 @@ +{{ define "main" }} + {{ $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections }} + {{ $notHidden := where .Site.RegularPages "Params.hidden" "!=" true }} + {{ $filtered := ($pages | intersect $notHidden) }} + {{ $pag := .Paginate ($filtered) }} + + <section class="article-list"> + {{ range $index, $element := $pag.Pages }} + {{ partial "article-list/default" . }} + {{ end }} + </section> + + {{- partial "pagination.html" . -}} + {{- partial "footer/footer" . -}} +{{ end }} + +{{ define "right-sidebar" }} + {{ partial "sidebar/right.html" (dict "Context" . "Scope" "homepage") }} +{{ end }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/page/search.html b/themes/hugo-theme-stack/layouts/page/search.html new file mode 100644 index 0000000..fbfb74d --- /dev/null +++ b/themes/hugo-theme-stack/layouts/page/search.html @@ -0,0 +1,33 @@ +{{ define "body-class" }}template-search{{ end }} +{{ define "head" }} + {{- with .OutputFormats.Get "json" -}} + <link rel="preload" href="{{ .RelPermalink }}" as="fetch" crossorigin="anonymous"> + {{- end -}} +{{ end }} +{{ define "main" }} +<form action="{{ .RelPermalink }}" class="search-form"{{ with .OutputFormats.Get "json" -}} data-json="{{ .RelPermalink }}"{{- end }}> + <p> + <label>{{ T "search.title" }}</label> + <input name="keyword" placeholder="{{ T `search.placeholder` }}" /> + </p> + + <button title="{{ T `search.title` }}"> + {{ partial "helper/icon" "search" }} + </button> +</form> + +<div class="search-result"> + <h3 class="search-result--title section-title"></h3> + <div class="search-result--list article-list--compact"></div> +</div> + +<script> + window.searchResultTitleTemplate = "{{ T `search.resultTitle` }}" +</script> + +{{- $opts := dict "minify" hugo.IsProduction "JSXFactory" "createElement" -}} +{{- $searchScript := resources.Get "ts/search.tsx" | js.Build $opts -}} +<script type="text/javascript" src="{{ $searchScript.RelPermalink }}" defer></script> + +{{ partialCached "footer/footer" . }} +{{ end }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/page/search.json b/themes/hugo-theme-stack/layouts/page/search.json new file mode 100644 index 0000000..5d4e627 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/page/search.json @@ -0,0 +1,26 @@ +{{- $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections -}} +{{- $notHidden := where .Site.RegularPages "Params.hidden" "!=" true -}} +{{- $filtered := ($pages | intersect $notHidden) -}} + +{{- $result := slice -}} + +{{- range $filtered -}} + {{- $data := dict "title" .Title "date" .Date "permalink" .Permalink "content" (.Plain) -}} + + {{- $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" -}} + {{- if $image.exists -}} + {{- $imagePermalink := "" -}} + {{- if and $image.resource (default true .Page.Site.Params.imageProcessing.cover.enabled) -}} + {{- $thumbnail := $image.resource.Fill "120x120" -}} + {{- $imagePermalink = (absURL $thumbnail.Permalink) -}} + {{- else -}} + {{- $imagePermalink = $image.permalink -}} + {{- end -}} + + {{- $data = merge $data (dict "image" (absURL $imagePermalink)) -}} + {{- end -}} + + {{- $result = $result | append $data -}} +{{- end -}} + +{{ jsonify $result }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/article-list/compact.html b/themes/hugo-theme-stack/layouts/partials/article-list/compact.html new file mode 100644 index 0000000..376512a --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article-list/compact.html @@ -0,0 +1,40 @@ +<article> + <a href="{{ .RelPermalink }}"> + <div class="article-details"> + <h2 class="article-title"> + {{- .Title -}} + </h2> + <footer class="article-time"> + <time datetime='{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}'> + {{- .Date.Format (or .Site.Params.dateFormat.published "Jan 02, 2006") -}} + </time> + </footer> + </div> + + {{- $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" -}} + {{ if $image.exists }} + <div class="article-image"> + {{ if $image.resource }} + {{- $Permalink := $image.resource.RelPermalink -}} + {{- $Width := $image.resource.Width -}} + {{- $Height := $image.resource.Height -}} + + {{- if (default true .Page.Site.Params.imageProcessing.cover.enabled) -}} + {{- $thumbnail := $image.resource.Fill "120x120" -}} + {{- $Permalink = $thumbnail.RelPermalink -}} + {{- $Width = $thumbnail.Width -}} + {{- $Height = $thumbnail.Height -}} + {{- end -}} + + <img src="{{ $Permalink }}" + width="{{ $Width }}" + height="{{ $Height }}" + alt="{{ .Title }}" + loading="lazy"> + {{ else }} + <img src="{{ $image.permalink }}" loading="lazy" alt="Featured image of post {{ .Title }}" /> + {{ end }} + </div> + {{ end }} + </a> +</article>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/article-list/default.html b/themes/hugo-theme-stack/layouts/partials/article-list/default.html new file mode 100644 index 0000000..02e0b30 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article-list/default.html @@ -0,0 +1,4 @@ +{{ $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" }} +<article class="{{ if $image.exists }}has-image{{ end }}"> + {{ partial "article/components/header" . }} +</article>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/article-list/tile.html b/themes/hugo-theme-stack/layouts/partials/article-list/tile.html new file mode 100644 index 0000000..be5744b --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article-list/tile.html @@ -0,0 +1,39 @@ +{{ $image := partialCached "helper/image" (dict "Context" .context "Type" .Type) .context.RelPermalink .Type }} +<article class="{{ if $image.exists }}has-image{{ end }}"> + <a href="{{ .context.RelPermalink }}"> + + {{ if $image.exists }} + <div class="article-image"> + {{ if $image.resource }} + {{- $imageRaw := $image.resource | resources.Fingerprint "md5" -}} + {{- $Permalink := $imageRaw.RelPermalink -}} + {{- $Width := $imageRaw.Width -}} + {{- $Height := $imageRaw.Height -}} + + {{- if .context.Site.Params.imageProcessing.cover.enabled -}} + {{- $thumbnail := $imageRaw.Fill .size -}} + {{- $Permalink = $thumbnail.RelPermalink -}} + {{- $Width = $thumbnail.Width -}} + {{- $Height = $thumbnail.Height -}} + {{- end -}} + + <img src="{{ $Permalink }}" + width="{{ $Width }}" + height="{{ $Height }}" + loading="lazy" + alt="Featured image of post {{ .context.Title }}" + {{ with .context.Slug }}data-key="{{ . }}" {{ end }} + data-hash="{{ $imageRaw.Data.Integrity }}"> + {{ else }} + <img src="{{ $image.permalink }}" loading="lazy" data-key="{{ .context.Slug }}" data-hash="{{ $image.permalink }}"/> + {{ end }} + </div> + {{ end }} + + <div class="article-details"> + <h2 class="article-title"> + {{- .context.Title -}} + </h2> + </div> + </a> +</article> diff --git a/themes/hugo-theme-stack/layouts/partials/article/article.html b/themes/hugo-theme-stack/layouts/partials/article/article.html new file mode 100644 index 0000000..f3f7e90 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article/article.html @@ -0,0 +1,11 @@ +<article class="{{ if .Params.image }}has-image {{ end }}main-article"> + {{ partial "article/components/header" . }} + + {{ partial "article/components/content" . }} + + {{ partial "article/components/footer" . }} + + {{ if or .Params.math .Site.Params.article.math }} + {{ partialCached "article/components/math.html" . }} + {{ end }} +</article>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/article/components/content.html b/themes/hugo-theme-stack/layouts/partials/article/components/content.html new file mode 100644 index 0000000..61e536c --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article/components/content.html @@ -0,0 +1,5 @@ +<section class="article-content"> + <!-- Refer to https://discourse.gohugo.io/t/responsive-tables-in-markdown/10639/5 --> + {{ $wrappedTable := printf "<div class=\"table-wrapper\">${1}</div>" }} + {{ .Content | replaceRE "(<table>(?:.|\n)+?</table>)" $wrappedTable | safeHTML }} +</section> diff --git a/themes/hugo-theme-stack/layouts/partials/article/components/details.html b/themes/hugo-theme-stack/layouts/partials/article/components/details.html new file mode 100644 index 0000000..7c27302 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article/components/details.html @@ -0,0 +1,61 @@ +<div class="article-details"> + {{ if .Params.categories }} + <header class="article-category"> + {{ range (.GetTerms "categories") }} + <a href="{{ .RelPermalink }}" {{ with .Params.style }}style="background-color: {{ .background }}; color: {{ .color }};"{{ end }}> + {{ .LinkTitle }} + </a> + {{ end }} + </header> + {{ end }} + + <div class="article-title-wrapper"> + <h2 class="article-title"> + <a href="{{ .RelPermalink }}"> + {{- .Title -}} + </a> + </h2> + + {{ with .Params.description }} + <h3 class="article-subtitle"> + {{ . }} + </h3> + {{ end }} + </div> + + {{ $showReadingTime := .Params.readingTime | default (.Site.Params.article.readingTime) }} + {{ $showDate := not .Date.IsZero }} + {{ $showFooter := or $showDate $showReadingTime }} + {{ if $showFooter }} + <footer class="article-time"> + {{ if $showDate }} + <div> + {{ partial "helper/icon" "date" }} + <time class="article-time--published"> + {{- .Date | time.Format (or .Site.Params.dateFormat.published "Jan 02, 2006") -}} + </time> + </div> + {{ end }} + + {{ if $showReadingTime }} + <div> + {{ partial "helper/icon" "clock" }} + <time class="article-time--reading"> + {{ T "article.readingTime" .ReadingTime }} + </time> + </div> + {{ end }} + </footer> + {{ end }} + + {{ if .IsTranslated }} + <footer class="article-translations"> + {{ partial "helper/icon" "language" }} + <div> + {{ range .Translations }} + <a href="{{ .Permalink }}" class="link">{{ .Language.LanguageName }}</a> + {{ end }} + </div> + </footer> + {{ end }} +</div> diff --git a/themes/hugo-theme-stack/layouts/partials/article/components/footer.html b/themes/hugo-theme-stack/layouts/partials/article/components/footer.html new file mode 100644 index 0000000..9795880 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article/components/footer.html @@ -0,0 +1,19 @@ +<footer class="article-footer"> + {{ partial "article/components/tags" . }} + + {{ if and (.Site.Params.article.license.enabled) (not (eq .Params.license false)) }} + <section class="article-copyright"> + {{ partial "helper/icon" "copyright" }} + <span>{{ default .Site.Params.article.license.default .Params.license | markdownify }}</span> + </section> + {{ end }} + + {{- if ne .Lastmod .Date -}} + <section class="article-lastmod"> + {{ partial "helper/icon" "clock" }} + <span> + {{ T "article.lastUpdatedOn" }} {{ .Lastmod | time.Format ( or .Site.Params.dateFormat.lastUpdated "Jan 02, 2006 15:04 MST" ) }} + </span> + </section> + {{- end -}} +</footer> diff --git a/themes/hugo-theme-stack/layouts/partials/article/components/header.html b/themes/hugo-theme-stack/layouts/partials/article/components/header.html new file mode 100644 index 0000000..7582ec2 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article/components/header.html @@ -0,0 +1,35 @@ +<header class="article-header"> + {{- $image := partialCached "helper/image" (dict "Context" . "Type" "article") .RelPermalink "article" -}} + {{ if $image.exists }} + <div class="article-image"> + <a href="{{ .RelPermalink }}"> + {{ if $image.resource }} + {{- $Permalink := $image.resource.RelPermalink -}} + {{- $Width := $image.resource.Width -}} + {{- $Height := $image.resource.Height -}} + {{- $Srcset := "" -}} + + {{- if (default true .Page.Site.Params.imageProcessing.cover.enabled) -}} + {{- $thumbnail := $image.resource.Resize "800x" -}} + {{- $thumbnailRetina := $image.resource.Resize "1600x" -}} + {{- $Srcset = printf "%s 800w, %s 1600w" $thumbnail.RelPermalink $thumbnailRetina.RelPermalink -}} + {{- $Permalink = $thumbnail.RelPermalink -}} + {{- $Width = $thumbnail.Width -}} + {{- $Height = $thumbnail.Height -}} + {{- end -}} + + <img src="{{ $Permalink }}" + {{ with $Srcset }}srcset="{{ . }}"{{ end }} + width="{{ $Width }}" + height="{{ $Height }}" + loading="lazy" + alt="Featured image of post {{ .Title }}" /> + {{ else }} + <img src="{{ $image.permalink }}" loading="lazy" alt="Featured image of post {{ .Title }}" /> + {{ end }} + </a> + </div> + {{ end }} + + {{ partialCached "article/components/details" . .RelPermalink }} +</header>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/article/components/links.html b/themes/hugo-theme-stack/layouts/partials/article/components/links.html new file mode 100644 index 0000000..a2ac26c --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article/components/links.html @@ -0,0 +1,30 @@ +<div class="article-list--compact links"> + {{ range $i, $link := .Params.links }} + <article> + <a href="{{ $link.website }}" target="_blank" rel="noopener"> + <div class="article-details"> + <h2 class="article-title"> + {{- $link.title -}} + </h2> + <footer class="article-time"> + {{ with $link.description }} + {{ . }} + {{ else }} + {{ $link.website }} + {{ end }} + </footer> + </div> + + {{ with $link.image }} + {{ $permalink := . }} + {{ with ($.Resources.GetMatch (printf "%s" (. | safeURL))) }} + {{ $permalink = .RelPermalink }} + {{ end }} + <div class="article-image"> + <img src="{{ $permalink }}" loading="lazy"> + </div> + {{ end }} + </a> + </article> + {{ end }} +</div>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/article/components/math.html b/themes/hugo-theme-stack/layouts/partials/article/components/math.html new file mode 100644 index 0000000..bd1a7f8 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article/components/math.html @@ -0,0 +1,13 @@ +{{- partial "helper/external" (dict "Context" . "Namespace" "KaTeX") -}} +<script> + window.addEventListener("DOMContentLoaded", () => { + renderMathInElement(document.body, { + delimiters: [ + { left: "$$", right: "$$", display: true }, + { left: "$", right: "$", display: false }, + { left: "\\(", right: "\\)", display: false }, + { left: "\\[", right: "\\]", display: true } + ], + ignoredClasses: ["gist"] + });}) +</script>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/article/components/photoswipe.html b/themes/hugo-theme-stack/layouts/partials/article/components/photoswipe.html new file mode 100644 index 0000000..c33ff49 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article/components/photoswipe.html @@ -0,0 +1,68 @@ +<!-- Root element of PhotoSwipe. Must have class pswp. --> +<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true"> + + <!-- Background of PhotoSwipe. + It's a separate element as animating opacity is faster than rgba(). --> + <div class="pswp__bg"></div> + + <!-- Slides wrapper with overflow:hidden. --> + <div class="pswp__scroll-wrap"> + + <!-- Container that holds slides. + PhotoSwipe keeps only 3 of them in the DOM to save memory. + Don't modify these 3 pswp__item elements, data is added later on. --> + <div class="pswp__container"> + <div class="pswp__item"></div> + <div class="pswp__item"></div> + <div class="pswp__item"></div> + </div> + + <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. --> + <div class="pswp__ui pswp__ui--hidden"> + + <div class="pswp__top-bar"> + + <!-- Controls are self-explanatory. Order can be changed. --> + + <div class="pswp__counter"></div> + + <button class="pswp__button pswp__button--close" title="Close (Esc)"></button> + + <button class="pswp__button pswp__button--share" title="Share"></button> + + <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button> + + <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button> + + <!-- Preloader demo https://codepen.io/dimsemenov/pen/yyBWoR --> + <!-- element will get class pswp__preloader--active when preloader is running --> + <div class="pswp__preloader"> + <div class="pswp__preloader__icn"> + <div class="pswp__preloader__cut"> + <div class="pswp__preloader__donut"></div> + </div> + </div> + </div> + </div> + + <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"> + <div class="pswp__share-tooltip"></div> + </div> + + <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"> + </button> + + <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"> + </button> + + <div class="pswp__caption"> + <div class="pswp__caption__center"></div> + </div> + + </div> + + </div> + +</div> + +{{- partial "helper/external" (dict "Context" . "Namespace" "PhotoSwipe") -}}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/article/components/related-content.html b/themes/hugo-theme-stack/layouts/partials/article/components/related-content.html new file mode 100644 index 0000000..aba88e3 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article/components/related-content.html @@ -0,0 +1,13 @@ +{{ $related := (where (.Site.RegularPages.Related .) "Params.hidden" "!=" true) | first 5 }} +{{ with $related }} +<aside class="related-content--wrapper"> + <h2 class="section-title">{{ T "article.relatedContent" }}</h2> + <div class="related-content"> + <div class="flex article-list--tile"> + {{ range . }} + {{ partial "article-list/tile" (dict "context" . "size" "250x150" "Type" "articleList") }} + {{ end }} + </div> + </div> +</aside> +{{ end }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/article/components/tags.html b/themes/hugo-theme-stack/layouts/partials/article/components/tags.html new file mode 100644 index 0000000..aae38b4 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/article/components/tags.html @@ -0,0 +1,7 @@ +{{ if .Params.Tags }} + <section class="article-tags"> + {{ range (.GetTerms "tags") }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + {{ end }} + </section> +{{ end }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/comments/include.html b/themes/hugo-theme-stack/layouts/partials/comments/include.html new file mode 100644 index 0000000..a3d0618 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/include.html @@ -0,0 +1,3 @@ +{{ if .Site.Params.comments.enabled }} + {{ partial (printf "comments/provider/%s" .Site.Params.comments.provider) . }} +{{ end }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/beaudar.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/beaudar.html new file mode 100644 index 0000000..761801f --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/beaudar.html @@ -0,0 +1,46 @@ +<script + src="https://beaudar.lipk.org/client.js" + repo="{{ .Site.Params.comments.beaudar.repo }}" + issue-term="{{ .Site.Params.comments.beaudar.issueTerm }}" + {{ with .Site.Params.comments.beaudar.label }} + label="{{ . }}" + {{ end }} + theme="{{ .Site.Params.comments.beaudar.theme }}" + crossorigin="anonymous" + async +></script> + +<style> + .beaudar { + max-width: unset; + } +</style> + +<script> + let beaudarLoaded = false; + + function setBeaudarTheme(theme) { + let beaudar = document.querySelector(".beaudar iframe"); + if (beaudar) { + beaudar.contentWindow.postMessage( + { + type: "set-theme", + theme: `github-${theme}`, + }, + "https://beaudar.lipk.org" + ); + } + } + + addEventListener("message", (event) => { + if (event.origin !== "https://beaudar.lipk.org") return; + /// Called when Beaudar is ready + beaudarLoaded = true; + setBeaudarTheme(document.documentElement.dataset.scheme); + }); + + window.addEventListener("onColorSchemeChange", (e) => { + if (!beaudarLoaded) return; + setBeaudarTheme(e.detail); + }); +</script> diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/cactus.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/cactus.html new file mode 100644 index 0000000..ae172d3 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/cactus.html @@ -0,0 +1,29 @@ +{{- with .Site.Params.comments.cactus -}} +{{- partial "helper/external" (dict "Context" $ "Namespace" "Cactus") -}} + +<style> + .cactus-editor-textarea { + color: var(--body-text-color); + } + + .cactus-comment-header { + color: var(--card-text-color-main); + } + + .cactus-message-text > p { + color: var(--body-text-color); + } +</style> + +<div id="comment-section"></div> + +<script> + initComments({ + node: document.getElementById("comment-section"), + defaultHomeserverUrl: "{{ .defaultHomeserverUrl | safeJS }}", + serverName: "{{ .serverName }}", + siteName: "{{ .siteName }}", + commentSectionId: "{{ $.File.UniqueID }}" + }) +</script> +{{- end -}} diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/cusdis.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/cusdis.html new file mode 100644 index 0000000..a89746c --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/cusdis.html @@ -0,0 +1,21 @@ +{{- $host := default "https://cusdis.com" .Site.Params.comments.cusdis.host -}} +<div id="cusdis_thread" + data-host="{{ $host }}" + data-app-id="{{ .Site.Params.comments.cusdis.id }}" + data-page-id="{{ .File.UniqueID }}" + data-page-url="{{ .Permalink }}" + data-page-title="{{ .Title }}"></div> +<script async defer src="{{ $host }}/js/cusdis.es.js"></script> + +<script> + function setCusdisTheme(theme) { + let cusdis = document.querySelector('#cusdis_thread iframe'); + if (cusdis) { + window.CUSDIS.setTheme(theme) + } + } + + window.addEventListener('onColorSchemeChange', (e) => { + setCusdisTheme(e.detail) + }) +</script> diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/disqus.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/disqus.html new file mode 100644 index 0000000..fb17b77 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/disqus.html @@ -0,0 +1,22 @@ +<div class="disqus-container"> + {{ template "_internal/disqus.html" . }} +</div> + +<style> + .disqus-container { + background-color: var(--card-background); + border-radius: var(--card-border-radius); + box-shadow: var(--shadow-l1); + padding: var(--card-padding); + } +</style> + +<script> + window.addEventListener('onColorSchemeChange', (e) => { + if (typeof DISQUS == 'object') { + DISQUS.reset({ + reload: true + }); + } + }) +</script>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/disqusjs.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/disqusjs.html new file mode 100644 index 0000000..967c38c --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/disqusjs.html @@ -0,0 +1,61 @@ +{{- $pc := .Site.Config.Privacy.Disqus -}} +{{- $disqusjs := .Site.Params.Comments.disqusjs -}} +{{- if and (not $pc.Disable) (and $disqusjs.Shortname $disqusjs.ApiKey) -}} + +{{- $style := resources.Get "scss/partials/comments/disqusjs.scss" | toCSS | minify -}} +<link rel="stylesheet" href="{{ $style.RelPermalink }}"> + +<div class="disqus-container"> + <div id="disqus_thread"></div> + <script type="application/javascript"> + let disqusjs; + function loadDisqusJS() { + disqusjs = new DisqusJS({ + shortname: {{ $disqusjs.Shortname }}, + siteName: {{ .Site.Title }}, + apikey: {{ $disqusjs.ApiKey }}, + {{ with $disqusjs.ApiUrl }}api: {{ . }},{{ end }} + {{ with $disqusjs.Admin }}admin: {{ . }},{{ end }} + {{ with $disqusjs.AdminLabel }}adminLabel: {{ . }}{{ end }} + }); + } + + function lazyLoadDisqusJS() { + if (["localhost", "127.0.0.1"].indexOf(window.location.hostname) != -1) { + document.getElementById('disqus_thread').innerHTML = 'Disqus comments not available by default when the website is previewed locally.'; + return; + } + + let d = document.createElement('script'); + d.src = 'https://cdn.jsdelivr.net/npm/disqusjs@1.3/dist/disqus.js'; + d.async = false; + document.body.appendChild(d); + d.onload = () => { + loadDisqusJS(); + window.addEventListener('onColorSchemeChange', (e) => { + if (disqusjs) { + loadDisqusJS(); + } + }) + } + } + + let runningOnBrowser = typeof window !== "undefined"; + let isBot = runningOnBrowser && !("onscroll" in window) || typeof navigator !== "undefined" && /(gle|ing|ro|msn)bot|crawl|spider|yand|duckgo/i.test(navigator.userAgent); + let supportsIntersectionObserver = runningOnBrowser && "IntersectionObserver" in window; + + if (!isBot && supportsIntersectionObserver) { + let disqus_observer = new IntersectionObserver(function(entries) { + if (entries[0].isIntersecting) { + lazyLoadDisqusJS(); + disqus_observer.disconnect(); + } + }); + disqus_observer.observe(document.getElementById('disqus_thread')); + } else { + lazyLoadDisqusJS(); + } + </script> + <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +</div> +{{- end -}}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/giscus.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/giscus.html new file mode 100644 index 0000000..97fbb77 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/giscus.html @@ -0,0 +1,52 @@ +{{- with .Site.Params.comments.giscus -}} +<script + src="https://giscus.app/client.js" + data-repo="{{- .repo -}}" + data-repo-id="{{- .repoID -}}" + data-category="{{- .category -}}" + data-category-id="{{- .categoryID -}}" + data-mapping="{{- default `title` .mapping -}}" + data-strict="{{- default 0 .strict -}}" + data-reactions-enabled="{{- default 1 .reactionsEnabled -}}" + data-emit-metadata="{{- default 0 .emitMetadata -}}" + data-input-position="{{- default `top` .inputPosition -}}" + data-theme="{{- default `light` .lightTheme -}}" + data-lang="{{- default (default `en` $.Language.LanguageCode) .lang -}}" + data-loading="{{- .loading -}}" + crossorigin="anonymous" + async +></script> +<script> + function setGiscusTheme(theme) { + let giscus = document.querySelector("iframe.giscus-frame"); + if (giscus) { + giscus.contentWindow.postMessage( + { + giscus: { + setConfig: { + theme: theme, + }, + }, + }, + "https://giscus.app" + ); + } + } + + (function () { + addEventListener("message", (e) => { + if (event.origin !== "https://giscus.app") return; + handler(); + }); + window.addEventListener("onColorSchemeChange", handler); + + function handler() { + if (document.documentElement.dataset.scheme === "light") { + setGiscusTheme('{{- default "light" .lightTheme -}}'); + } else { + setGiscusTheme('{{- default "dark_dimmed" .darkTheme -}}'); + } + } + })(); +</script> +{{- end -}} diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/gitalk.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/gitalk.html new file mode 100644 index 0000000..54bfcba --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/gitalk.html @@ -0,0 +1,31 @@ +{{- with .Site.Params.comments.gitalk -}} +<div id="gitalk-container"></div> +<link + rel="stylesheet" + href="https://cdn.jsdelivr.net/npm/gitalk@1.7.2/dist/gitalk.css" +/> +<script src="https://cdn.jsdelivr.net/npm/gitalk@1.7.2/dist/gitalk.min.js"></script> +<script src="https://cdn.jsdelivr.net/npm/blueimp-md5@2.18.0/js/md5.min.js"></script> +<script> + const gitalk = new Gitalk({ + clientID: "{{- .clientID -}}", + clientSecret: "{{- .clientSecret -}}", + repo: "{{- .repo -}}", + owner: "{{- .owner -}}", + admin: ["{{- .admin -}}"], + distractionFreeMode: false, // Facebook-like distraction free mode + id: md5(location.pathname), // Max Location.pathname Legth:75 https://github.com/gitalk/gitalk/issues/102 + proxy: {{- .proxy -}}, + }); + (function () { + if ( + ["localhost", "127.0.0.1"].indexOf(window.location.hostname) != -1 + ) { + document.getElementById("gitalk-container").innerHTML = + "Gitalk comments not available by default when the website is previewed locally."; + return; + } + gitalk.render("gitalk-container"); + })(); +</script> +{{ end }} diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/remark42.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/remark42.html new file mode 100644 index 0000000..18acf1b --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/remark42.html @@ -0,0 +1,29 @@ +{{- with .Site.Params.comments.remark42 -}} +<div id="remark42"></div> +<script> + var remark_config = { + host: '{{ .host }}', + site_id: '{{ .site }}', + components: ['embed'], + url: '{{ $.Permalink }}', + max_shown_comments: {{ default 15 .max_shown_comments }}, + theme: document.documentElement.dataset.scheme, + page_title: '{{ $.Title }}', + locale: '{{ default "en" .locale }}', + show_email_subscription: {{ default true .show_email_subscription }} + }; + + !function(e, n) { + for (var o = 0; o < e.length; o++) { + var r = n.createElement('script'), + c = '.js', + d = n.head || n.body; + 'noModule' in r ? (r.type = 'module', c = '.mjs') : r.async = !0, r.defer = !0, r.src = remark_config.host + '/web/' + e[o] + c, d.appendChild(r) + } + }(remark_config.components || ['embed'], document); + + window.addEventListener('onColorSchemeChange', (e) => { + window.REMARK42.changeTheme(e.detail); + }) +</script> +{{- end -}} diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/twikoo.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/twikoo.html new file mode 100644 index 0000000..8c22507 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/twikoo.html @@ -0,0 +1,58 @@ +<script src="//cdn.jsdelivr.net/npm/twikoo@1.6.39/dist/twikoo.all.min.js"></script> +<div id="tcomment"></div> +<style> + .twikoo { + background-color: var(--card-background); + border-radius: var(--card-border-radius); + box-shadow: var(--shadow-l1); + padding: var(--card-padding); + } + :root[data-scheme="dark"] { + --twikoo-body-text-color-main: rgba(255, 255, 255, 0.9); + --twikoo-body-text-color: rgba(255, 255, 255, 0.7); + } + .twikoo .el-input-group__prepend, + .twikoo .tk-action-icon, + .twikoo .tk-submit-action-icon, + .twikoo .tk-time, + .twikoo .tk-comments-no, + .twikoo .tk-comments-count { + color: var(--twikoo-body-text-color); + } + .twikoo .el-input__inner, + .twikoo .el-textarea__inner, + .twikoo .tk-preview-container, + .twikoo .tk-content, + .twikoo .tk-nick, + .twikoo .tk-send { + color: var(--twikoo-body-text-color-main); + } + .twikoo .el-button{ + color: var(--twikoo-body-text-color)!important; + } + .twikoo .el-input__count { + color: var(--twikoo-body-text-color) !important; + } + .OwO .OwO-body { + background-color: var(--body-background) !important; + color: var(--body-text-color) !important; + } +</style> + +{{- with .Site.Params.comments.twikoo -}} +<script> + twikoo.init({ + envId: '{{- .envId -}}', + el: '#tcomment', + {{- with .region -}} + region: '{{- . -}}', + {{- end -}} + {{- with .path -}} + path: '{{- . -}}', + {{- end -}} + {{- with .lang -}} + lang: '{{- . -}}', + {{- end -}} + }) +</script> +{{- end -}} diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/utterances.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/utterances.html new file mode 100644 index 0000000..b1e370b --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/utterances.html @@ -0,0 +1,46 @@ +<script src="https://utteranc.es/client.js" + repo="{{ .Site.Params.comments.utterances.repo }}" + issue-term="{{ .Site.Params.comments.utterances.issueTerm }}" + {{ with .Site.Params.comments.utterances.label }} + label="{{ . }}" + {{ end }} + crossorigin="anonymous" + async + > +</script> + +<style> + .utterances { + max-width: unset; + } +</style> + +<script> + let utterancesLoaded = false; + + function setUtterancesTheme(theme) { + let utterances = document.querySelector('.utterances iframe'); + if (utterances) { + utterances.contentWindow.postMessage( + { + type: 'set-theme', + theme: `github-${theme}` + }, + 'https://utteranc.es' + ); + } + } + + addEventListener('message', event => { + if (event.origin !== 'https://utteranc.es') return; + + /// Called when Utterances is ready + utterancesLoaded = true; + setUtterancesTheme(document.documentElement.dataset.scheme) + }); + + window.addEventListener('onColorSchemeChange', (e) => { + if (!utterancesLoaded) return; + setUtterancesTheme(e.detail) + }) +</script> diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/vssue.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/vssue.html new file mode 100644 index 0000000..79ac381 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/vssue.html @@ -0,0 +1,27 @@ +{{- with .Site.Params.comments.vssue -}} +<link rel="stylesheet" href="https://unpkg.com/vssue/dist/vssue.min.css" /> + +<div id="vssue"></div> + +<script src="https://unpkg.com/vue@2/dist/vue.runtime.min.js"></script> +<script src="https://unpkg.com/vssue/dist/vssue.{{ .platform }}.min.js"></script> + +<script> + new Vue({ + el: "#vssue", + render: (h) => + h("Vssue", { + props: { + title: "{{ $.Title }}", + options: { + autoCreateIssue: {{ default false .autoCreateIssue }}, + owner: "{{ .owner }}", + repo: "{{ .repo }}", + clientId: "{{ .clientId }}", + clientSecret: "{{ .clientSecret }}", + }, + }, + }), + }); +</script> +{{- end -}} diff --git a/themes/hugo-theme-stack/layouts/partials/comments/provider/waline.html b/themes/hugo-theme-stack/layouts/partials/comments/provider/waline.html new file mode 100644 index 0000000..9d1a2a0 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/comments/provider/waline.html @@ -0,0 +1,34 @@ +<script src='//unpkg.com/@waline/client@v2/dist/waline.js'></script>
+<link href='//unpkg.com/@waline/client@v2/dist/waline.css' rel='stylesheet'/>
+<div id="waline" class="waline-container"></div>
+<style>
+ .waline-container {
+ background-color: var(--card-background);
+ border-radius: var(--card-border-radius);
+ box-shadow: var(--shadow-l1);
+ padding: var(--card-padding);
+ --waline-font-size: var(--article-font-size);
+ }
+ .waline-container .wl-count {
+ color: var(--card-text-color-main);
+ }
+</style>
+
+{{- with .Site.Params.comments.waline -}}
+{{- $config := dict "el" "#waline" "dark" `html[data-scheme="dark"]` -}}
+{{- $replaceKeys := dict "serverurl" "serverURL" "requiredmeta" "requiredMeta" "wordlimit" "wordLimit" "pagesize" "pageSize" "imageuploader" "imageUploader" "texrenderer" "texRenderer" -}}
+
+{{- range $key, $val := . -}}
+ {{- if ne $val nil -}}
+ {{- $replaceKey := index $replaceKeys $key -}}
+ {{- $k := default $key $replaceKey -}}
+
+ {{- $config = merge $config (dict $k $val) -}}
+ {{- end -}}
+{{- end -}}
+
+<script>
+ /// Waline client configuration see: https://waline.js.org/en/reference/client.html
+ Waline.init({{ $config | jsonify | safeJS }});
+</script>
+{{- end -}}
diff --git a/themes/hugo-theme-stack/layouts/partials/data/description.html b/themes/hugo-theme-stack/layouts/partials/data/description.html new file mode 100644 index 0000000..7f6cc32 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/data/description.html @@ -0,0 +1,17 @@ +<!-- Use site subtitle by default --> +{{ $description := .Site.Params.sidebar.subtitle }} + +<!-- Seprate description exists --> +{{ if .Site.Params.description }} + {{ $description = .Site.Params.description }} +{{ end }} + +{{ if .Description }} + <!-- Page description exists --> + {{ $description = .Description }} +{{ else if .IsPage }} + <!-- Use page summary --> + {{ $description = .Summary }} +{{ end }} + +{{ return (replaceRE "\n" " " $description | plainify) }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/data/title.html b/themes/hugo-theme-stack/layouts/partials/data/title.html new file mode 100644 index 0000000..85a7bc7 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/data/title.html @@ -0,0 +1,38 @@ +{{- $title := .Title -}} +{{- $siteTitle := .Site.Title -}} + +{{- if .IsHome -}} + <!-- Homepage, and it's pagination --> + + <!-- Build paginator --> + {{ $pages := where .Site.RegularPages "Section" "in" .Site.Params.mainSections }} + {{ $notHidden := where .Site.RegularPages "Params.hidden" "!=" true }} + {{ $filtered := ($pages | intersect $notHidden) }} + {{ $pag := .Paginate ($filtered) }} + + {{ if .Paginator.HasPrev }} + <!-- Paginated. Append page number to title --> + {{ $title = printf "%s - %s" .Paginator $siteTitle }} + {{ else }} + {{ $title = $siteTitle}} + {{ end }} +{{- else if eq .Kind "term" -}} + <!-- Taxonomy page --> + + <!-- Build paginator --> + {{ $notHidden := where .Pages "Params.hidden" "!=" true }} + {{ $pag := .Paginate ($notHidden) }} + + <!-- {TAXONOMY_TYPE}: {TAXONOMY_TERM} --> + {{ $title = slice (title .Data.Singular) ": " $title }} + + {{ if .Paginator.HasPrev }} + <!-- Add page number--> + {{ $title = $title | append " - " .Paginator }} + {{ end }} + + {{ $title = $title | append " - " $siteTitle }} + {{ $title = delimit $title "" }} +{{- end -}} + +{{ return $title }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/footer/components/custom-font.html b/themes/hugo-theme-stack/layouts/partials/footer/components/custom-font.html new file mode 100644 index 0000000..8e2ff37 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/footer/components/custom-font.html @@ -0,0 +1,11 @@ +<script> + (function () { + const customFont = document.createElement('link'); + customFont.href = "https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap"; + + customFont.type = "text/css"; + customFont.rel = "stylesheet"; + + document.head.appendChild(customFont); + }()); +</script>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/footer/components/script.html b/themes/hugo-theme-stack/layouts/partials/footer/components/script.html new file mode 100644 index 0000000..3dc96cb --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/footer/components/script.html @@ -0,0 +1,12 @@ +{{- partial "helper/external" (dict "Context" . "Namespace" "Vibrant") -}} + +{{- $opts := dict "minify" hugo.IsProduction -}} +{{- $script := resources.Get "ts/main.ts" | js.Build $opts | fingerprint -}} + +<script type="text/javascript" src="{{ $script.RelPermalink }}" defer></script> + +{{- with resources.Get "ts/custom.ts" -}} + {{/* Place your custom script in HUGO_SITE_FOLDER/assets/ts/custom.ts */}} + {{- $customScript := . | js.Build $opts | fingerprint -}} + <script type="text/javascript" src="{{ $customScript.RelPermalink }}" defer></script> +{{- end -}}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/footer/custom.html b/themes/hugo-theme-stack/layouts/partials/footer/custom.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/footer/custom.html diff --git a/themes/hugo-theme-stack/layouts/partials/footer/footer.html b/themes/hugo-theme-stack/layouts/partials/footer/footer.html new file mode 100644 index 0000000..9c28779 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/footer/footer.html @@ -0,0 +1,23 @@ +{{- $ThemeVersion := "3.29.0" -}} +<footer class="site-footer"> + <section class="copyright"> + © + {{ if and (.Site.Params.footer.since) (ne .Site.Params.footer.since (int (now.Format "2006"))) }} + {{ .Site.Params.footer.since }} - + {{ end }} + {{ now.Format "2006" }} {{ default .Site.Title .Site.Copyright }} + </section> + + <section class="powerby"> + {{ with .Site.Params.footer.customText }} + {{ . | safeHTML }} <br/> + {{ end }} + + {{- $Generator := `<a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a>` -}} + {{- $Theme := printf `<b><a href="https://github.com/CaiJimmy/hugo-theme-stack" target="_blank" rel="noopener" data-version="%s">Stack</a></b>` $ThemeVersion -}} + {{- $DesignedBy := `<a href="https://jimmycai.com" target="_blank" rel="noopener">Jimmy</a>` -}} + + {{ T "footer.builtWith" (dict "Generator" $Generator) | safeHTML }} <br /> + {{ T "footer.designedBy" (dict "Theme" $Theme "DesignedBy" $DesignedBy) | safeHTML }} + </section> +</footer> diff --git a/themes/hugo-theme-stack/layouts/partials/footer/include.html b/themes/hugo-theme-stack/layouts/partials/footer/include.html new file mode 100644 index 0000000..4b50a88 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/footer/include.html @@ -0,0 +1,3 @@ +{{ partialCached "footer/components/script.html" . }} +{{ partialCached "footer/components/custom-font.html" . }} +{{ partial "footer/custom.html" . }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/head/colorScheme.html b/themes/hugo-theme-stack/layouts/partials/head/colorScheme.html new file mode 100644 index 0000000..42f4dd8 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/head/colorScheme.html @@ -0,0 +1,39 @@ +{{- $defaultColorScheme := default "auto" .Site.Params.colorScheme.default -}} +{{- if not (default false .Site.Params.colorScheme.toggle) -}} + {{/* If toggle is disabled, force default scheme */}} + <script> + (function() { + const colorSchemeKey = 'StackColorScheme'; + localStorage.setItem(colorSchemeKey, "{{ $defaultColorScheme }}"); + })(); + </script> +{{- else -}} + {{/* Otherwise set to default scheme only if no preference is set by user */}} + <script> + (function() { + const colorSchemeKey = 'StackColorScheme'; + if(!localStorage.getItem(colorSchemeKey)){ + localStorage.setItem(colorSchemeKey, "{{ $defaultColorScheme }}"); + } + })(); + </script> +{{- end -}} + +<script> + (function() { + const colorSchemeKey = 'StackColorScheme'; + const colorSchemeItem = localStorage.getItem(colorSchemeKey); + const supportDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches === true; + + if (colorSchemeItem == 'dark' || colorSchemeItem === 'auto' && supportDarkMode) { + /** + * Enable dark mode if: + * 1. If dark mode is set already (in local storage) + * 2. Auto mode & prefere color scheme is dark + */ + document.documentElement.dataset.scheme = 'dark'; + } else { + document.documentElement.dataset.scheme = 'light'; + } + })(); +</script> diff --git a/themes/hugo-theme-stack/layouts/partials/head/custom.html b/themes/hugo-theme-stack/layouts/partials/head/custom.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/head/custom.html diff --git a/themes/hugo-theme-stack/layouts/partials/head/head.html b/themes/hugo-theme-stack/layouts/partials/head/head.html new file mode 100644 index 0000000..a7991c1 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/head/head.html @@ -0,0 +1,26 @@ +<meta charset='utf-8'> +<meta name='viewport' content='width=device-width, initial-scale=1'> + +{{- $description := partialCached "data/description" . .RelPermalink -}} +<meta name='description' {{ printf "content=%q" $description | safeHTMLAttr }}> +{{ with .Params.Keywords }}<meta name="keywords" content="{{ delimit . ", " }}">{{ end }} + +{{- $title := partial "data/title" . -}} +<title>{{ $title }}</title> + +<link rel='canonical' href='{{ .Permalink }}'> + +{{- partial "head/style.html" . -}} +{{- partial "head/script.html" . -}} +{{- partial "head/opengraph/include.html" . -}} + +{{- range .AlternativeOutputFormats -}} + <link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}"> +{{- end -}} + +{{ with .Site.Params.favicon }} + <link rel="shortcut icon" href="{{ . | relURL }}" /> +{{ end }} + +{{- template "_internal/google_analytics.html" . -}} +{{- partial "head/custom.html" . -}} diff --git a/themes/hugo-theme-stack/layouts/partials/head/opengraph/include.html b/themes/hugo-theme-stack/layouts/partials/head/opengraph/include.html new file mode 100644 index 0000000..3a43f48 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/head/opengraph/include.html @@ -0,0 +1,2 @@ +{{ partial "head/opengraph/provider/base" . }} +{{ partial "head/opengraph/provider/twitter" . }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/head/opengraph/provider/base.html b/themes/hugo-theme-stack/layouts/partials/head/opengraph/provider/base.html new file mode 100644 index 0000000..055745d --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/head/opengraph/provider/base.html @@ -0,0 +1,43 @@ +{{- $title := partialCached "data/title" . .RelPermalink -}} +{{- $description := partialCached "data/description" . .RelPermalink -}} + +<meta property='og:title' {{ printf "content=%q" $title | safeHTMLAttr }}> +<meta property='og:description' {{ printf "content=%q" $description | safeHTMLAttr }}> +<meta property='og:url' content='{{ .Permalink }}'> +<meta property='og:site_name' content='{{ .Site.Title }}'> +<meta property='og:type' content=' + {{- if .IsPage -}} + article + {{- else -}} + website + {{- end -}} +'> + +{{- with .Params.locale -}} + <meta property='og:locale' content='{{ . }}'> +{{- end -}} + +{{- if .IsPage -}} + <meta property='article:section' content='{{ .Section | title }}' /> + {{- range .Params.tags -}} + <meta property='article:tag' content='{{ . }}' /> + {{- end -}} +{{- end -}} + +{{- if .IsPage -}} + {{- if not .Date.IsZero -}} + <meta property='article:published_time' content='{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}'/> + {{- end -}} + {{- if not .Lastmod.IsZero -}} + <meta property='article:modified_time' content='{{ .Lastmod.Format "2006-01-02T15:04:05-07:00" | safeHTML }}'/> + {{- end -}} +{{- else -}} + {{- if not .Site.Lastmod.IsZero -}} + <meta property='og:updated_time' content='{{ .Site.Lastmod.Format " 2006-01-02T15:04:05-07:00 " | safeHTML }}'/> + {{- end -}} +{{- end -}} + +{{ $image := partialCached "helper/image" (dict "Context" . "Type" "opengraph") .RelPermalink "opengraph" }} +{{- if $image.exists -}} + <meta property='og:image' content='{{ absURL $image.permalink }}' /> +{{- end -}}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/head/opengraph/provider/twitter.html b/themes/hugo-theme-stack/layouts/partials/head/opengraph/provider/twitter.html new file mode 100644 index 0000000..c39eba3 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/head/opengraph/provider/twitter.html @@ -0,0 +1,16 @@ +{{- with .Site.Params.opengraph.twitter.site -}} + <meta name="twitter:site" content="@{{ . }}"> + <meta name="twitter:creator" content="@{{ . }}"> +{{- end -}} + +{{- $title := partialCached "data/title" . .RelPermalink -}} +{{- $description := partialCached "data/description" . .RelPermalink -}} + +<meta name="twitter:title" {{ printf "content=%q" $title | safeHTMLAttr }}> +<meta name="twitter:description" {{ printf "content=%q" $description | safeHTMLAttr }}> + +{{- $image := partialCached "helper/image" (dict "Context" . "Type" "opengraph") .RelPermalink "opengraph" -}} +{{- if $image.exists -}} + <meta name="twitter:card" content="{{ default `summary_large_image` .Site.Params.opengraph.twitter.card }}"> + <meta name="twitter:image" content='{{ absURL $image.permalink }}' /> +{{- end -}}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/head/script.html b/themes/hugo-theme-stack/layouts/partials/head/script.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/head/script.html diff --git a/themes/hugo-theme-stack/layouts/partials/head/style.html b/themes/hugo-theme-stack/layouts/partials/head/style.html new file mode 100644 index 0000000..30ca26e --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/head/style.html @@ -0,0 +1,3 @@ +{{ $sass := resources.Get "scss/style.scss" }} +{{ $style := $sass | toCSS | minify | resources.Fingerprint "sha256" }} +<link rel="stylesheet" href="{{ $style.RelPermalink }}">
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/helper/external.html b/themes/hugo-theme-stack/layouts/partials/helper/external.html new file mode 100644 index 0000000..88d9525 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/helper/external.html @@ -0,0 +1,29 @@ +{{- $List := index .Context.Site.Data.external .Namespace -}} +{{- with $List -}} + {{- range . -}} + {{- if eq .type "script" -}} + <script + src="{{ .src }}" + {{- with .integrity -}} + integrity="{{ . }}" + {{- end -}} + crossorigin="anonymous" + {{ if .defer }}defer{{ end }} + > + </script> + {{- else if eq .type "style" -}} + <link + rel="stylesheet" + href="{{ .src }}" + {{- with .integrity -}} + integrity="{{ . }}" + {{- end -}} + crossorigin="anonymous" + > + {{- else -}} + {{- errorf "Error: unknown external resource type: %s" .type -}} + {{- end -}} + {{- end -}} +{{- else -}} + {{- errorf "Error: external resource '%s' is not found" .Namespace -}} +{{- end -}}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/helper/icon.html b/themes/hugo-theme-stack/layouts/partials/helper/icon.html new file mode 100644 index 0000000..72162e8 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/helper/icon.html @@ -0,0 +1,6 @@ +{{- $iconFile := resources.GetMatch (printf "icons/%s.svg" .) -}} +{{- if $iconFile -}} + {{- $iconFile.Content | safeHTML -}} +{{- else -}} + {{- errorf "Error: icon '%s.svg' is not found under 'assets/icons' folder" . -}} +{{- end -}}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/helper/image.html b/themes/hugo-theme-stack/layouts/partials/helper/image.html new file mode 100644 index 0000000..11fc3b6 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/helper/image.html @@ -0,0 +1,61 @@ +{{ $result := dict "exists" false "permalink" nil "resource" nil "isDefault" false }} +{{ $imageField := default "image" .Context.Site.Params.featuredImageField }} +{{ $imageValue := index .Context.Params $imageField }} + +{{ if $imageValue }} + <!-- If page has `image` field set --> + {{ $result = merge $result (dict "exists" true) }} + {{ $url := urls.Parse $imageValue }} + + {{ if or (eq $url.Scheme "http") (eq $url.Scheme "https") }} + <!-- Is an external image --> + {{ $result = merge $result (dict "permalink" $imageValue) }} + {{ else }} + {{ $pageResourceImage := .Context.Resources.GetMatch (printf "%s" ($imageValue | safeURL)) }} + + {{ if $pageResourceImage }} + <!-- If image is found under page bundle --> + {{ $result = merge $result (dict "permalink" $pageResourceImage.RelPermalink) }} + + <!-- Disable SVG image processing, not supported by Hugo --> + {{ if ne (path.Ext $imageValue) ".svg" }} + {{ $result = merge $result (dict "resource" $pageResourceImage) }} + {{ end }} + {{ else }} + <!-- Can not find the image under page bundle. Could be a relative linked image --> + {{ $result = merge $result (dict "permalink" (relURL $imageValue)) }} + {{ end }} + + {{ end }} + +{{ else if and (ne .Type nil) (index .Context.Site.Params.defaultImage .Type) }} + <!-- Type arg is set, check for defaultImage setting --> + {{ $defaultImageSetting := index .Context.Site.Params.defaultImage .Type }} + + {{ if $defaultImageSetting.enabled }} + {{ $result = merge $result (dict "isDefault" true) }} + {{ $result = merge $result (dict "exists" true) }} + + {{ if $defaultImageSetting.local }} + {{ $siteResourceImage := resources.GetMatch (printf "%s" ($defaultImageSetting.src | safeURL)) }} + + {{ if $siteResourceImage }} + <!-- Try search image under site's assets folder --> + {{ $result = merge $result (dict "permalink" $siteResourceImage.RelPermalink) }} + {{ $result = merge $result (dict "resource" $siteResourceImage) }} + {{ else }} + <!-- Can not find the image --> + {{ errorf "Failed loading image: %q" $defaultImageSetting.src }} + {{ $result = merge $result (dict "exists" false) }} + {{ end }} + + {{ else }} + <!-- External image --> + {{ $result = merge $result (dict "permalink" (relURL $defaultImageSetting.src)) }} + {{ end }} + + {{ end }} + +{{ end }} + +{{ return $result }} diff --git a/themes/hugo-theme-stack/layouts/partials/pagination.html b/themes/hugo-theme-stack/layouts/partials/pagination.html new file mode 100644 index 0000000..7756050 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/pagination.html @@ -0,0 +1,26 @@ +{{ if gt .Paginator.TotalPages 1 }} + <nav class='pagination'> + {{ $.Scratch.Set "hasPrevDots" false }} + {{ $.Scratch.Set "hasNextDots" false }} + + {{ range .Paginator.Pagers }} + {{ if eq . $.Paginator }} + <span class='page-link current'> + {{- .PageNumber -}} + </span> + {{ else if or (or (eq . $.Paginator.First) (eq . $.Paginator.Prev)) (or (eq . $.Paginator.Next) (eq . $.Paginator.Last )) }} + <a class='page-link' href='{{ .URL }}'> + {{- .PageNumber -}} + </a> + {{ else }} + {{ if and (not ($.Scratch.Get "hasPrevDots")) (lt .PageNumber $.Paginator.PageNumber) }} + {{ $.Scratch.Set "hasPrevDots" true }} + <span class='page-link dots'>…</span> + {{ else if and (not ($.Scratch.Get "hasNextDots")) (gt .PageNumber $.Paginator.PageNumber) }} + {{ $.Scratch.Set "hasNextDots" true }} + <span class='page-link dots'>…</span> + {{ end }} + {{ end }} + {{ end }} + </nav> +{{ end }} diff --git a/themes/hugo-theme-stack/layouts/partials/sidebar/left.html b/themes/hugo-theme-stack/layouts/partials/sidebar/left.html new file mode 100644 index 0000000..21e7d3e --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/sidebar/left.html @@ -0,0 +1,103 @@ +<aside class="sidebar left-sidebar sticky {{ if .Site.Params.sidebar.compact }}compact{{ end }}"> + <button class="hamburger hamburger--spin" type="button" id="toggle-menu" aria-label="{{ T `toggleMenu` }}"> + <span class="hamburger-box"> + <span class="hamburger-inner"></span> + </span> + </button> + + <header> + {{ with .Site.Params.sidebar.avatar }} + {{ if (default true .enabled) }} + <figure class="site-avatar"> + <a href="{{ .Site.BaseURL | relLangURL }}"> + {{ if not .local }} + <img src="{{ .src }}" width="300" height="300" class="site-logo" loading="lazy" alt="Avatar"> + {{ else }} + {{ $avatar := resources.Get (.src) }} + + {{ if $avatar }} + {{ $avatarResized := $avatar.Resize "300x" }} + <img src="{{ $avatarResized.RelPermalink }}" width="{{ $avatarResized.Width }}" + height="{{ $avatarResized.Height }}" class="site-logo" loading="lazy" alt="Avatar"> + {{ else }} + {{ errorf "Failed loading avatar from %q" . }} + {{ end }} + {{ end }} + </a> + {{ with $.Site.Params.sidebar.emoji }} + <span class="emoji">{{ . }}</span> + {{ end }} + </figure> + {{ end }} + {{ end }} + + <div class="site-meta"> + <h1 class="site-name"><a href="{{ .Site.BaseURL | relLangURL }}">{{ .Site.Title }}</a></h1> + <h2 class="site-description">{{ .Site.Params.sidebar.subtitle }}</h2> + </div> + </header> + + {{- with .Site.Menus.social -}} + <ol class="menu-social"> + {{ range . }} + <li> + <a + href='{{ .URL }}' + {{ if eq (default true .Params.newTab) true }}target="_blank"{{ end }} + {{ with .Name }}title="{{ . }}"{{ end }} + rel="me" + > + {{ $icon := default "link" .Params.Icon }} + {{ with $icon }} + {{ partial "helper/icon" . }} + {{ end }} + </a> + </li> + {{ end }} + </ol> + {{- end -}} + + <ol class="menu" id="main-menu"> + {{ $currentPage := . }} + {{ range .Site.Menus.main }} + {{ $active := or (eq $currentPage.Title .Name) (or ($currentPage.HasMenuCurrent "main" .) ($currentPage.IsMenuCurrent "main" .)) }} + <li {{ if $active }} class='current' {{ end }}> + <a href='{{ .URL }}' {{ if eq .Params.newTab true }}target="_blank"{{ end }}> + {{ $icon := default .Pre .Params.Icon }} + {{ if .Pre }} + {{ warnf "Menu item [%s] is using [pre] field to set icon, please use [params.icon] instead.\nMore information: https://stack.jimmycai.com/config/menu" .URL }} + {{ end }} + {{ with $icon }} + {{ partial "helper/icon" . }} + {{ end }} + <span>{{- .Name -}}</span> + </a> + </li> + {{ end }} + <li class="menu-bottom-section"> + <ol class="menu"> + {{- $currentLanguageCode := .Language.Lang -}} + {{ if ( compare.Gt .Site.Home.AllTranslations.Len 1 ) }} + {{ with .Site.Home.AllTranslations }} + <li id="i18n-switch"> + {{ partial "helper/icon" "language" }} + <select name="language" title="language" onchange="window.location.href = this.selectedOptions[0].value"> + {{ range . }} + <option value="{{ .Permalink }}" {{ if eq .Language.Lang $currentLanguageCode }}selected{{ end }}>{{ .Language.LanguageName }}</option> + {{ end }} + </select> + </li> + {{ end }} + {{ end }} + + {{ if (default false .Site.Params.colorScheme.toggle) }} + <li id="dark-mode-toggle"> + {{ partial "helper/icon" "toggle-left" }} + {{ partial "helper/icon" "toggle-right" }} + <span>{{ T "darkMode" }}</span> + </li> + {{ end }} + </ol> + </li> + </ol> +</aside> diff --git a/themes/hugo-theme-stack/layouts/partials/sidebar/right.html b/themes/hugo-theme-stack/layouts/partials/sidebar/right.html new file mode 100644 index 0000000..6333f10 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/sidebar/right.html @@ -0,0 +1,16 @@ +{{- $scope := default "homepage" .Scope -}} +{{- $context := .Context -}} +{{- with (index .Context.Site.Params.widgets $scope) -}} + <aside class="sidebar right-sidebar sticky"> + {{ range $widget := . }} + {{ if templates.Exists (printf "partials/widget/%s.html" .type) }} + <!-- Ensure that the `params` is not nil --> + {{- $params := default dict .params -}} + + {{ partial (printf "widget/%s" .type) (dict "Context" $context "Params" $params) }} + {{ else }} + {{ warnf "Widget %s not found" .type }} + {{ end }} + {{ end }} + </aside> +{{ end }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/widget/archives.html b/themes/hugo-theme-stack/layouts/partials/widget/archives.html new file mode 100644 index 0000000..1f2abc5 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/widget/archives.html @@ -0,0 +1,35 @@ +{{- $query := first 1 (where .Context.Site.Pages "Layout" "==" "archives") -}} +{{- $context := .Context -}} +{{- $limit := default 5 .Params.limit -}} +{{- if $query -}} + {{- $archivesPage := index $query 0 -}} + <section class="widget archives"> + <div class="widget-icon"> + {{ partial "helper/icon" "infinity" }} + </div> + <h2 class="widget-title section-title">{{ T "widget.archives.title" }}</h2> + + {{ $pages := where $context.Site.RegularPages "Type" "in" $context.Site.Params.mainSections }} + {{ $notHidden := where $context.Site.RegularPages "Params.hidden" "!=" true }} + {{ $filtered := ($pages | intersect $notHidden) }} + {{ $archives := $filtered.GroupByDate "2006" }} + + <div class="widget-archive--list"> + {{ range $index, $item := first (add $limit 1) ($archives) }} + {{- $id := lower (replace $item.Key " " "-") -}} + <div class="archives-year"> + <a href="{{ $archivesPage.RelPermalink }}#{{ $id }}"> + {{ if eq $index $limit }} + <span class="year">{{ T "widget.archives.more" }}</span> + {{ else }} + <span class="year">{{ .Key }}</span> + <span class="count">{{ len $item.Pages }}</span> + {{ end }} + </a> + </div> + {{ end }} + </div> + </section> +{{- else -}} + {{- warnf "Archives page not found. Create a page with layout: archives." -}} +{{- end -}}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/widget/categories.html b/themes/hugo-theme-stack/layouts/partials/widget/categories.html new file mode 100644 index 0000000..10c8a35 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/widget/categories.html @@ -0,0 +1,16 @@ +{{- $context := .Context -}} +{{- $limit := default 10 .Params.limit -}} +<section class="widget tagCloud"> + <div class="widget-icon"> + {{ partial "helper/icon" "categories" }} + </div> + <h2 class="widget-title section-title">{{ T "widget.categoriesCloud.title" }}</h2> + + <div class="tagCloud-tags"> + {{ range first $limit $context.Site.Taxonomies.categories.ByCount }} + <a href="{{ .Page.RelPermalink }}" class="font_size_{{ .Count }}"> + {{ .Page.Title }} + </a> + {{ end }} + </div> +</section> diff --git a/themes/hugo-theme-stack/layouts/partials/widget/search.html b/themes/hugo-theme-stack/layouts/partials/widget/search.html new file mode 100644 index 0000000..7b0fc73 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/widget/search.html @@ -0,0 +1,16 @@ +{{- $query := first 1 (where .Context.Site.Pages "Layout" "==" "search") -}} +{{- if $query -}} + {{- $searchPage := index $query 0 -}} + <form action="{{ $searchPage.RelPermalink }}" class="search-form widget" {{ with .OutputFormats.Get "json" -}}data-json="{{ .Permalink }}" {{- end }}> + <p> + <label>{{ T "search.title" }}</label> + <input name="keyword" required placeholder="{{ T `search.placeholder` }}" /> + + <button title="{{ T `search.title` }}"> + {{ partial "helper/icon" "search" }} + </button> + </p> + </form> +{{- else -}} + {{- warnf "Search page not found. Create a page with layout: search." -}} +{{- end -}}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/widget/tag-cloud.html b/themes/hugo-theme-stack/layouts/partials/widget/tag-cloud.html new file mode 100644 index 0000000..e64e5e2 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/widget/tag-cloud.html @@ -0,0 +1,16 @@ +{{- $context := .Context -}} +{{- $limit := default 10 .Params.limit -}} +<section class="widget tagCloud"> + <div class="widget-icon"> + {{ partial "helper/icon" "tag" }} + </div> + <h2 class="widget-title section-title">{{ T "widget.tagCloud.title" }}</h2> + + <div class="tagCloud-tags"> + {{ range first $limit $context.Site.Taxonomies.tags.ByCount }} + <a href="{{ .Page.RelPermalink }}" class="font_size_{{ .Count }}"> + {{ .Page.Title }} + </a> + {{ end }} + </div> +</section>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/partials/widget/toc.html b/themes/hugo-theme-stack/layouts/partials/widget/toc.html new file mode 100644 index 0000000..e311de3 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/partials/widget/toc.html @@ -0,0 +1,12 @@ +{{ if (.Context.Scratch.Get "TOCEnabled") }} + <section class="widget archives"> + <div class="widget-icon"> + {{ partial "helper/icon" "hash" }} + </div> + <h2 class="widget-title section-title">{{ T "article.tableOfContents" }}</h2> + + <div class="widget--toc"> + {{ .Context.TableOfContents }} + </div> + </section> +{{ end }}
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/shortcodes/bilibili.html b/themes/hugo-theme-stack/layouts/shortcodes/bilibili.html new file mode 100644 index 0000000..cb72e43 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/shortcodes/bilibili.html @@ -0,0 +1,23 @@ +{{ $vid := (.Get 0) }}
+{{ $videopage := default 1 (.Get 1) }}
+{{ $basicQuery := querify "page" $videopage "high_quality" 1 "as_wide" 1 }}
+{{ $videoQuery := "" }}
+
+{{ if strings.HasPrefix (lower $vid) "av" }}
+ {{ $videoQuery = querify "aid" (strings.TrimPrefix "av" (lower $vid)) }}
+{{ else if strings.HasPrefix (lower $vid) "bv" }}
+ {{ $videoQuery = querify "bvid" $vid }}
+{{ else }}
+ <p>Bilibili 视频av号或BV号错误!请检查视频av号或BV号是否正确</p>
+ <p>当前视频av或BV号:{{ $vid }},视频分P:{{ $videopage }}</p>
+{{ end }}
+
+<div class="video-wrapper">
+ <iframe src="https://player.bilibili.com/player.html?{{ $basicQuery | safeURL }}&{{ $videoQuery | safeURL }}"
+ scrolling="no"
+ frameborder="no"
+ framespacing="0"
+ allowfullscreen="true"
+ >
+ </iframe>
+</div>
diff --git a/themes/hugo-theme-stack/layouts/shortcodes/gitlab.html b/themes/hugo-theme-stack/layouts/shortcodes/gitlab.html new file mode 100644 index 0000000..b5a16cf --- /dev/null +++ b/themes/hugo-theme-stack/layouts/shortcodes/gitlab.html @@ -0,0 +1,4 @@ +<script + type="application/javascript" + src="https://gitlab.com/-/snippets/{{ index .Params 0 }}.js" +></script>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/shortcodes/quote.html b/themes/hugo-theme-stack/layouts/shortcodes/quote.html new file mode 100644 index 0000000..09bb07c --- /dev/null +++ b/themes/hugo-theme-stack/layouts/shortcodes/quote.html @@ -0,0 +1,15 @@ +<blockquote> + <p>{{ .Inner | markdownify }}</p> + {{- if or (.Get "author") (.Get "source") -}} + <span class="cite"><span>― </span> + {{- if .Get "author" -}} + <span> + {{- .Get "author" -}}{{- if .Get "source" -}}, {{ end -}} + </span> + {{- end -}} + {{- with .Get "url" -}}<a href="{{ . }}">{{- end -}} + <cite>{{ .Get "source" }}</cite> + {{- if .Get "url" -}}</a>{{- end -}} + </span> + {{- end -}} +</blockquote>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/shortcodes/tencent.html b/themes/hugo-theme-stack/layouts/shortcodes/tencent.html new file mode 100644 index 0000000..463dec5 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/shortcodes/tencent.html @@ -0,0 +1,10 @@ +{{ $vid := .Get 0 }}
+<div class="video-wrapper">
+ <iframe src="https://v.qq.com/txp/iframe/player.html?vid={{ $vid }}&auto=0"
+ scrolling="no"
+ frameborder="no"
+ framespacing="0"
+ allowfullscreen="true"
+ >
+ </iframe>
+</div>
\ No newline at end of file diff --git a/themes/hugo-theme-stack/layouts/shortcodes/video.html b/themes/hugo-theme-stack/layouts/shortcodes/video.html new file mode 100644 index 0000000..5324754 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/shortcodes/video.html @@ -0,0 +1,14 @@ +{{- $src := .Get "src" | default (.Get 0) -}} +<div class="video-wrapper"> + <video + controls + src="{{- $src -}}" + {{ with .Get "poster" }}poster="{{- . -}}"{{ end }} + {{ with .Get "autoplay" }}autoplay{{ end }} + > + <p> + Your browser doesn't support HTML5 video. Here is a + <a href="{{- $src -}}">link to the video</a> instead. + </p> + </video> +</div> diff --git a/themes/hugo-theme-stack/layouts/shortcodes/youtube.html b/themes/hugo-theme-stack/layouts/shortcodes/youtube.html new file mode 100644 index 0000000..2f85931 --- /dev/null +++ b/themes/hugo-theme-stack/layouts/shortcodes/youtube.html @@ -0,0 +1,13 @@ +{{- $pc := .Page.Site.Config.Privacy.YouTube -}} +{{- if not $pc.Disable -}} +{{- $ytHost := cond $pc.PrivacyEnhanced "www.youtube-nocookie.com" "www.youtube.com" -}} +{{- $id := .Get "id" | default (.Get 0) -}} +<div class="video-wrapper"> + <iframe loading="lazy" + src="https://{{ $ytHost }}/embed/{{ $id }}{{ with .Get "autoplay" }}{{ if eq . "true" }}?autoplay=1{{ end }}{{ end }}" + allowfullscreen + title="YouTube Video" + > + </iframe> +</div> +{{ end -}}
\ No newline at end of file |