diff --git a/README.md b/README.md index 3b73cd4..14755bf 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ git submodule add https://github.com/clente/hugo-bearcub themes/hugo-bearcub To finish off, append a line to the site configuration file: ```sh -echo 'theme = "hugo-bearcub"' >> config.toml +echo 'theme = "hugo-bearcub"' >> hugo.toml ``` ## Features @@ -85,8 +85,8 @@ have to think about it again. My `_headers` file, for example, looks like this: ### Multilingual If you need to write a blog that supports more than one language, **Bear Cub** -has you covered! Check out the demo's [`config.toml` -file](https://github.com/clente/hugo-bearcub/blob/main/exampleSite/config.toml) +has you covered! Check out the demo's [`hugo.toml` +file](https://github.com/clente/hugo-bearcub/blob/main/exampleSite/hugo.toml) for a sample of how you can setup multilingual support. By default, the theme creates a translation button that gets disabled when the @@ -107,7 +107,7 @@ already implemented: matter](https://gohugo.io/content-management/front-matter/). You can also add `render: false` to your [build options](https://gohugo.io/content-management/build-options/#readout) to avoid - rendering a blank post. + rendering blank posts. - Skip link: a "skip to main content" link that is temporarily invisible, but can be focused by people who need a keyboard to navigate the web (see [PR #5](https://github.com/clente/hugo-bearcub/pull/5) by @@ -115,14 +115,21 @@ already implemented: - Reply by email: if you supply an email address, the theme creates a "Reply to this post by email" button at the end of every post (see Kev Quirk's [original implementation](https://kevquirk.com/adding-the-post-title-to-my-reply-by-email-button)). +- `absfigure` shortcode: a shortcut to use the `figure` shortcode that also + converts relative URLs into absolute URLs by using the `absURL` function. - Single-use CSS (EXPERIMENTAL): you can add some styles to a single page by writing the CSS you need in `assets/{custom_css}.css` and then including `style: "{custom_css}.css"` in the [front matter](https://gohugo.io/content-management/front-matter/) of said page. - Conditional CSS (EXPERIMENTAL): since **Bear Cub** does syntax highlighting - without inline styles (see `config.toml` for more information), it only load - its `syntax.css` if, and only if, a code block is actually present in the - current page. + without inline styles (see `hugo.toml` for more information), it only load its + `syntax.css` if, and only if, a code block is actually present in the current + page. +- Alternative "Herman" style (EXPERIMENTAL): if you want to check out a more + modern CSS style, you can change the `themeStyle` parameter to `"herman"` in + order to activate [Herman Martinus's](https://herman.bearblog.dev/) version of + the [Blogster Minimal](https://blogster-minimal.netlify.app/) theme for + [Astro](https://astro.build/). - Dynamic social card generation (EXPERIMENTAL): if you don't add preview images to a post, this template will generate one based on the title. You can see an example below. @@ -131,8 +138,8 @@ already implemented: ## Configuration -**Bear Cub** can be customized with a `config.toml` file. Check out the -[configuration](https://github.com/clente/hugo-bearcub/blob/main/exampleSite/config.toml) +**Bear Cub** can be customized with a `hugo.toml` file. Check out the +[configuration](https://github.com/clente/hugo-bearcub/blob/main/exampleSite/hugo.toml) of the [demo](https://clente.github.io/hugo-bearcub/) for more information. ```toml @@ -145,11 +152,6 @@ defaultContentLanguage = "en" # Generate a nice robots.txt for SEO enableRobotsTXT = true -# Your name. For more information on why this must be a list, see -# https://discourse.gohugo.io/t/site-author-usage/31459/8 -[author] - name = "John Doe" - # Setup syntax highlighting without inline styles. For more information about # why you'd want to avoid inline styles, see # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src#unsafe_inline_styles @@ -206,18 +208,29 @@ enableRobotsTXT = true # have the theme simply not show any link hideUntranslated = false + # (EXPERIMENTAL) This theme has two options for its CSS styles: "original" and + # "herman". The former is what you see on Bear Cub's demo (an optimized + # version of Hugo Bear Blog), while the latter has a more modern look based on + # Herman Martinus's version of the Blogster Minimal theme for Astro. + themeStyle = "original" + # (EXPERIMENTAL) This theme is capable of dynamically generating social cards # for posts that don't have `images` defined in their front matter; By setting # `generateSocialCard` to false, you can prevent this behavior. For more - # information see layouts/partials/seo_tags.html + # information see layouts/partials/social_card.html generateSocialCard = true # Social media. Delete any item you aren't using to make sure it won't show up # in your website's metadata. - [social] - email = "me@example.com" # Added to the footer so readers can reply to posts + [params.social] twitter = "example" # Twitter handle (without '@') facebook_admin = "0000000000" # Facebook Page Admin ID + + # Author metadata. This is mostly used for the RSS feed of your site, but the + # email is also added to the footer of each post + [params.author] + name = "John Doe" # Your name as shown in the RSS feed metadata + email = "me@example.com" # Added to the footer so readers can reply to posts ``` ## Contributing diff --git a/assets/herman.css b/assets/herman.css new file mode 100644 index 0000000..f2573c3 --- /dev/null +++ b/assets/herman.css @@ -0,0 +1,202 @@ +:root { + font-size: 62.5%; /* 10px */ + --color-dark: #181a20; + --color-light: #fafafa; + --color-primary: #1a8fe3; + --size: 1rem; + --spacing: calc(var(--size) * 2.4); +} + +body { + background: var(--color-dark); + color: var(--color-light); + padding: 4rem; + font-family: Avenir, 'Avenir Next LT Pro', Montserrat, Corbel, 'URW Gothic', + source-sans-pro, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol", "Noto Color Emoji"; + font-size: calc(var(--size) * 1.8); + line-height: 1.5; + min-height: 80vh; + max-width: 1600px; + margin: 0 auto; + word-wrap: break-word; +} + +header, +main, +footer { + max-width: 70ch; + margin-inline: auto; +} + +header { + padding-bottom: var(--spacing); +} + +nav a, a.blog-tags { + margin-right: calc(var(--spacing) / 2); +} +a.blog-tags { + line-height: 2; +} + +main { + padding-bottom: var(--spacing); +} + +footer { + text-align: center; + padding-top: var(--spacing); +} + +a { + color: currentColor; + text-decoration-color: var(--color-primary); + text-decoration-thickness: 0.3ex; + text-underline-offset: 0.3ex; +} + +a:hover { + text-decoration-thickness: 0.4ex; +} + +img { + display: block; + max-width: 100%; + height: auto; +} + +h1, +h2, +h3, +h4 { + font-weight: 700; + line-height: 1.3; +} + +h1 { + font-size: calc(var(--size) * 4.2); +} +h2 { + font-size: calc(var(--size) * 3.4); +} +h3 { + font-size: calc(var(--size) * 2.6); +} +h4 { + font-size: calc(var(--size) * 1.8); +} + +ul, +ol { + padding-inline-start: var(--spacing); +} +li { + margin-block-start: var(--spacing); +} + +blockquote { + padding-inline-start: var(--spacing); + border-inline-start: 0.2em solid; + font-style: italic; + max-width: 50ch; +} + +:is(h1, h2, h3, h4, blockquote) { + margin-block-end: calc(var(--spacing) / 2); +} +:is(h1, h2, h3, h4) + * { + margin-block-start: calc(var(--spacing) / 3); +} +:is(h1, h2, h3, h4) + :where(h2, h3, h4) { + margin-block-start: calc(var(--spacing) * 2); +} + +.title { + text-decoration: none; +} +.title h1 { + font-size: calc(var(--size) * 3.4); + margin-top: calc(var(--spacing) / 2); +} + +ul.blog-posts { + list-style-type: none; + padding: unset; +} +ul.blog-posts li { + display: flex; + flex-direction: column; +} +ul.blog-posts li span { + min-width: 11ch; +} + +p.byline { + opacity: 0.5; +} + +code { + font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', + Menlo, Consolas, 'DejaVu Sans Mono', monospace; + padding: 2px calc(var(--spacing) / 4); + background-color: #282a36; + font-size: calc(var(--size) * 1.4); +} +pre code { + display: block; + padding: var(--spacing); + overflow-x: auto; + -webkit-text-size-adjust: 100%; + -moz-text-size-adjust: 100%; +} + +table { + width: 100%; +} +table, +th, +td { + border: 1px solid; + border-collapse: collapse; + border-color: var(--color-light); + padding: calc(var(--spacing) / 2); +} + +.disabled { + color: currentColor; + cursor: not-allowed; + opacity: 0.5; +} + +@media screen and (min-width: 600px) { + ul.blog-posts li { + flex-direction: row; + gap: calc(var(--spacing) / 2); + } +} + +/* "Skip to main content" link */ +.skip-link { + position: absolute; + top: 5; + transform: translateY(-600%); + transition: transform 0.5s; + background-color: #181a20; + padding: 6px; +} + +.skip-link:focus { + transform: translateY(0%); +} + +figure { + margin-inline-start: 0em; + margin-inline-end: 0em; +} + +figcaption > p { + margin-block-start: 9px; + text-align: center; + font-style: italic; +} diff --git a/assets/images/social_card_bg.png b/assets/images/social_card_bg.png index ad1d528..857ea63 100644 Binary files a/assets/images/social_card_bg.png and b/assets/images/social_card_bg.png differ diff --git a/assets/images/social_card_fg.png b/assets/images/social_card_fg.png index 01b207c..e005b0a 100644 Binary files a/assets/images/social_card_fg.png and b/assets/images/social_card_fg.png differ diff --git a/assets/style.css b/assets/original.css similarity index 98% rename from assets/style.css rename to assets/original.css index 0173a36..3492237 100644 --- a/assets/style.css +++ b/assets/original.css @@ -134,6 +134,7 @@ ul.blog-posts li a:visited { a.blog-tags { line-height: 2; + margin-right: 12px; } h3.blog-filter { diff --git a/assets/syntax.css b/assets/syntax.css index 5f15788..a28d967 100644 --- a/assets/syntax.css +++ b/assets/syntax.css @@ -69,11 +69,11 @@ /* Operator */ .chroma .o { color: #ff79c6 } /* OperatorWord */ .chroma .ow { color: #ff79c6 } /* Punctuation .chroma .p { } */ -/* Comment */ .chroma .c { color: #7c90d0 } -/* CommentHashbang */ .chroma .ch { color: #7c90d0 } -/* CommentMultiline */ .chroma .cm { color: #7c90d0 } -/* CommentSingle */ .chroma .c1 { color: #7c90d0 } -/* CommentSpecial */ .chroma .cs { color: #7c90d0 } +/* Comment */ .chroma .c { color: #8491b8 } +/* CommentHashbang */ .chroma .ch { color: #8491b8 } +/* CommentMultiline */ .chroma .cm { color: #8491b8 } +/* CommentSingle */ .chroma .c1 { color: #8491b8 } +/* CommentSpecial */ .chroma .cs { color: #8491b8 } /* CommentPreproc */ .chroma .cp { color: #ff79c6 } /* CommentPreprocFile */ .chroma .cpf { color: #ff79c6 } /* Generic .chroma .g { } */ diff --git a/exampleSite/config.toml b/exampleSite/hugo.toml similarity index 82% rename from exampleSite/config.toml rename to exampleSite/hugo.toml index d5eff2b..c037e60 100644 --- a/exampleSite/config.toml +++ b/exampleSite/hugo.toml @@ -7,11 +7,6 @@ defaultContentLanguage = "en" # Generate a nice robots.txt for SEO enableRobotsTXT = true -# Your name. For more information on why this must be a list, see -# https://discourse.gohugo.io/t/site-author-usage/31459/8 -[author] - name = "John Doe" - # Setup syntax highlighting without inline styles. For more information about # why you'd want to avoid inline styles, see # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src#unsafe_inline_styles @@ -68,15 +63,26 @@ enableRobotsTXT = true # have the theme simply not show any link hideUntranslated = false + # (EXPERIMENTAL) This theme has two options for its CSS styles: "original" and + # "herman". The former is what you see on Bear Cub's demo (an optimized + # version of Hugo Bear Blog), while the latter has a more modern look based on + # Herman Martinus's version of the Blogster Minimal theme for Astro. + themeStyle = "original" + # (EXPERIMENTAL) This theme is capable of dynamically generating social cards # for posts that don't have `images` defined in their front matter; By setting # `generateSocialCard` to false, you can prevent this behavior. For more - # information see layouts/partials/seo_tags.html + # information see layouts/partials/social_card.html generateSocialCard = true # Social media. Delete any item you aren't using to make sure it won't show up # in your website's metadata. - [social] - email = "me@example.com" # Added to the footer so readers can reply to posts + [params.social] twitter = "example" # Twitter handle (without '@') facebook_admin = "0000000000" # Facebook Page Admin ID + + # Author metadata. This is mostly used for the RSS feed of your site, but the + # email is also added to the footer of each post + [params.author] + name = "John Doe" # Your name as shown in the RSS feed metadata + email = "me@example.com" # Added to the footer so readers can reply to posts diff --git a/images/social_card.webp b/images/social_card.webp index 43ae186..24bf927 100644 Binary files a/images/social_card.webp and b/images/social_card.webp differ diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index 475d6f9..294749a 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -11,7 +11,7 @@ {{- partial "seo_tags.html" . -}} - {{ $style := resources.Get "style.css" | minify }} + {{ $style := print (default "original" .Site.Params.themeStyle) ".css" | resources.Get | minify }} {{ if (.Page.Store.Get "hasCodeBlock") }} diff --git a/layouts/_default/list.html b/layouts/_default/list.html index 354bc9c..e6cc177 100644 --- a/layouts/_default/list.html +++ b/layouts/_default/list.html @@ -16,7 +16,7 @@ {{ if .Params.link }} {{ .Title }} ↪ {{ else }} - {{ .Title }} + {{ .Title }} {{ end }} {{ else }} @@ -28,7 +28,7 @@ {{ if not .Data.Singular }}
{{ range (.GetTerms "tags") }} - #{{ .LinkTitle }} + #{{ lower .LinkTitle }} {{ end }}
-{{ with .Site.Social.email }} +{{ with .Site.Params.author.email }}
{{ i18n "email-reply" }} ↪
diff --git a/layouts/partials/header.html b/layouts/partials/header.html
index 5a66907..42b5c10 100644
--- a/layouts/partials/header.html
+++ b/layouts/partials/header.html
@@ -1,4 +1,4 @@
{{ i18n "skip-link" }}
-
+ {{- .Get "caption" | markdownify -}}
+ {{- with .Get "attrlink" }}
+
+ {{- end -}}
+ {{- .Get "attr" | markdownify -}}
+ {{- if .Get "attrlink" }}{{ end }}{{ .Site.Title }}
+{{ .Site.Title }}
diff --git a/layouts/partials/nav.html b/layouts/partials/nav.html
index 5f40267..53be338 100644
--- a/layouts/partials/nav.html
+++ b/layouts/partials/nav.html
@@ -12,7 +12,7 @@
{{ range where .Site.Languages "Lang" "!=" .Page.Lang }}
{{ with (index $translations .Lang) }}
- {{ .Language.LanguageName }}
+ {{ .Language.LanguageName }}
{{ else }}
{{ if not .Params.hideUntranslated }}
diff --git a/layouts/partials/social_card.html b/layouts/partials/social_card.html
index 68bb4ca..d171da0 100644
--- a/layouts/partials/social_card.html
+++ b/layouts/partials/social_card.html
@@ -3,22 +3,33 @@
{{ $fg := resources.Get "images/social_card_fg.png"}}
{{ $bg := resources.Get "images/social_card_bg.png"}}
-{{ $fg = $fg.Filter (images.Text .Title (dict
+{{ if gt (len .Title) 45 }}
+ {{ $fg = $fg.Filter (images.Text .Title (dict
"font" $font
- "color" "#f8f8f2"
+ "color" "#fafafa"
+ "size" 95
+ "linespacing" 16
+ "x" 0
+ "y" 0
+ )) }}
+{{ else }}
+ {{ $fg = $fg.Filter (images.Text .Title (dict
+ "font" $font
+ "color" "#fafafa"
"size" 130
"linespacing" 20
"x" 0
"y" 0
-)) }}
+ )) }}
+{{ end }}
{{ $date := .Date.Format (default "2006-01-02" .Site.Params.dateFormat) }}
-{{ $author := (default $.Site.Author.name ($.Param "author") ) }}
+{{ $author := (default $.Site.Params.author.name ($.Param "author") ) }}
{{ $byline := (printf "%s | %s" $author $date) }}
{{ $fg = $fg.Filter (images.Text $byline (dict
"font" $font
- "color" "#c9d1d9"
+ "color" "#898a8d"
"size" 60
"linespacing" 30
"x" 0
@@ -29,7 +40,7 @@
{{ $card := $card.Resize "900x webp q100" }}
-
+
@@ -63,22 +74,52 @@
{{ end }}{{ end }}
{{- end }}
+{{- /* Deprecate site.Social.facebook_admin in favor of site.Params.social.facebook_admin */}}
+{{- $facebookAdmin := "" }}
+{{- with site.Params.social }}
+ {{- if reflect.IsMap . }}
+ {{- $facebookAdmin = .facebook_admin }}
+ {{- end }}
+{{- else }}
+ {{- with site.Social.facebook_admin }}
+ {{- $facebookAdmin = . }}
+ {{- warnf "The social key in site configuration is deprecated. Use params.social.facebook_admin instead." }}
+ {{- end }}
+{{- end }}
+
{{- /* Facebook Page Admin ID for Domain Insights */}}
-{{- with .Site.Social.facebook_admin }}{{ end }}
+{{ with $facebookAdmin }}{{ end }}
-
-{{ with .Site.Social.twitter -}}
-
-{{ end -}}
+
+{{- /* Deprecate site.Social.twitter in favor of site.Params.social.twitter */}}
+{{- $twitterSite := "" }}
+{{- with site.Params.social }}
+ {{- if reflect.IsMap . }}
+ {{- $twitterSite = .twitter }}
+ {{- end }}
+{{- else }}
+ {{- with site.Social.twitter }}
+ {{- $twitterSite = . }}
+ {{- warnf "The social key in site configuration is deprecated. Use params.social.twitter instead." }}
+ {{- end }}
+{{- end }}
+
+{{- with $twitterSite }}
+ {{- $content := . }}
+ {{- if not (strings.HasPrefix . "@") }}
+ {{- $content = printf "@%v" $twitterSite }}
+ {{- end }}
+
+{{- end }}
-
+
diff --git a/layouts/shortcodes/absfigure.html b/layouts/shortcodes/absfigure.html
new file mode 100644
index 0000000..ad60c6c
--- /dev/null
+++ b/layouts/shortcodes/absfigure.html
@@ -0,0 +1,29 @@
+
+ {{- if .Get "link" }}{{ end -}}
+ {{- if or (or (.Get "title") (.Get "caption")) (.Get "attr") -}}
+
{{ . }}
+ {{- end -}}
+ {{- if or (.Get "caption") (.Get "attr") -}}