mirror of
https://github.com/foo-dogsquared/hugo-theme-contentful.git
synced 2025-02-07 06:19:02 +00:00
329 lines
17 KiB
HTML
329 lines
17 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en-us"><title>Extending Contentful</title>
|
||
<link rel="stylesheet" href="https://foo-dogsquared.github.io/hugo-theme-contentful/css/index.min.11618edd7e3b000c8d9629ad7f78c9229d907cb12f420c0242dfb9185eb5ff8e.css" /><meta name="generator" content="Hugo 0.98.0" />
|
||
<meta charset="utf-8">
|
||
<meta name="author" content="John Doe" />
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<meta name="referrer" content="no-referrer" />
|
||
<meta name="description" content="Extending a Hugo theme is nothing new and a few places provide a place for the most common extensions. In this post, I’ll be listing a few personal recipes I’ve always used for extending a Hugo theme. Though this only applies specifically to Contentful and may need some tweaking when applying it other themes.
|
||
Customizing your <head> Let’s start with the most basic and perhaps most useful customization: modifying the <head>." /><meta name="twitter:card" content="summary"/>
|
||
<meta name="twitter:title" content="Extending Contentful"/>
|
||
<meta name="twitter:description" content="Extending a Hugo theme is nothing new and a few places provide a place for the most common extensions. In this post, I’ll be listing a few personal recipes I’ve always used for extending a Hugo theme. Though this only applies specifically to Contentful and may need some tweaking when applying it other themes.
|
||
Customizing your <head> Let’s start with the most basic and perhaps most useful customization: modifying the <head>."/>
|
||
<meta property="og:title" content="Extending Contentful" />
|
||
<meta property="og:description" content="Extending a Hugo theme is nothing new and a few places provide a place for the most common extensions. In this post, I’ll be listing a few personal recipes I’ve always used for extending a Hugo theme. Though this only applies specifically to Contentful and may need some tweaking when applying it other themes.
|
||
Customizing your <head> Let’s start with the most basic and perhaps most useful customization: modifying the <head>." />
|
||
<meta property="og:type" content="article" />
|
||
<meta property="og:url" content="https://foo-dogsquared.github.io/hugo-theme-contentful/articles/extending-contentful/" /><meta property="article:section" content="articles" />
|
||
<meta property="article:published_time" content="2020-05-12T17:25:55+08:00" />
|
||
<meta property="article:modified_time" content="2022-05-13T18:08:06+08:00" />
|
||
|
||
<meta itemprop="name" content="Extending Contentful">
|
||
<meta itemprop="description" content="Extending a Hugo theme is nothing new and a few places provide a place for the most common extensions. In this post, I’ll be listing a few personal recipes I’ve always used for extending a Hugo theme. Though this only applies specifically to Contentful and may need some tweaking when applying it other themes.
|
||
Customizing your <head> Let’s start with the most basic and perhaps most useful customization: modifying the <head>."><meta itemprop="datePublished" content="2020-05-12T17:25:55+08:00" />
|
||
<meta itemprop="dateModified" content="2022-05-13T18:08:06+08:00" />
|
||
<meta itemprop="wordCount" content="1055">
|
||
<meta itemprop="keywords" content="theme,extending," /><link rel="canonical" type="text/html" href="https://foo-dogsquared.github.io/hugo-theme-contentful/articles/extending-contentful/" />
|
||
|
||
|
||
<body><nav aria-label="Primary navigation">
|
||
<a class="site__title" href="https://foo-dogsquared.github.io/hugo-theme-contentful/">Contentful</a>
|
||
<div class="site__links">
|
||
|
|
||
<a href="https://foo-dogsquared.github.io/hugo-theme-contentful/about/">About</a> |
|
||
<a href="https://foo-dogsquared.github.io/hugo-theme-contentful/categories/">Categories</a> |
|
||
<a href="https://foo-dogsquared.github.io/hugo-theme-contentful/recipes/">Recipes</a> |
|
||
<a href="https://foo-dogsquared.github.io/hugo-theme-contentful/tags/">Tags</a> |
|
||
|
||
</div>
|
||
</nav>
|
||
|
||
|
||
<article>
|
||
<header>
|
||
<h1>Extending Contentful</h1>
|
||
</header>
|
||
<div class="post__meta--single">
|
||
|
||
|
||
|
||
<p data-content-publication-date="2020-05-12 17:25:55 +0800 +0800">Created: <time datetime="2020-05-12">2020-05-12</time></p>
|
||
|
||
|
||
<p data-content-modification-date="2022-05-13 18:08:06 +0800 +0800">Updated: <time datetime="2022-05-13">2022-05-13</time></p>
|
||
|
||
|
||
</div>
|
||
<hr>
|
||
|
||
|
||
|
||
|
||
<main>
|
||
|
||
<div id="preamble">
|
||
<div class="sectionbody">
|
||
<div class="paragraph">
|
||
<p>Extending a Hugo theme is nothing new and a <a href="https://gohugo.io/content-management/sections/">few</a> <a href="http://hugocodex.org/add-ons/">places</a> provide a place for the most common extensions.
|
||
In this post, I’ll be listing a few personal recipes I’ve always used for extending a Hugo theme.
|
||
Though this only applies specifically to Contentful and may need some tweaking when applying it other themes.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect1">
|
||
<h2 id="_customizing_your_head">Customizing your <code><head></code></h2>
|
||
<div class="sectionbody">
|
||
<div class="paragraph">
|
||
<p>Let’s start with the most basic and perhaps most useful customization: modifying the <code><head</code>>.
|
||
This is useful for adding your own CSS and JavaScript files, changing certain metadata, or adding icons.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>First, copy the <code>head</code> partial from the theme (<code>theme/contentful/layouts/partials/head.html</code>) to your own (<code>layouts/partials/head.html</code>).
|
||
We’re simply taking advantage of <a href="https://gohugo.io/templates/lookup-order/">Hugo’s lookup order</a> where we’ve override the <code>head</code> partial with our own copy.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Then, feel free to add your own (or others') scripts and stylesheets, <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">icons and other metadata</a>, or whatever suitable things.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>In my case, I often use certain JavaScript libraries like <a href="https://www.mathjax.org/">MathJax</a> for mathematical typesetting, <a href="https://prismjs.com/">Prism</a> for syntax highlighting, and <a href="https://github.com/francoischalifour/medium-zoom/">medium-zoom</a> for interactive image zooms.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Here’s the modified code.
|
||
(The example code is snipped for brevity.)</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="highlight"><code class="language-go" data-lang="go"><!--snip-->
|
||
|
||
{{- /* MathJax */ -}}
|
||
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
|
||
<script id="MathJax-script" defer src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
||
|
||
{{- /* Prism.js */ -}}
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism-tomorrow.min.css" type="text/css">
|
||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/components/prism-core.min.js"></script>
|
||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js">
|
||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/keep-markup/prism-keep-markup.min.js">
|
||
|
||
{{- /* medium-zoom */ -}}
|
||
<script defer src="https://cdn.jsdelivr.net/npm/medium-zoom@1.0.5/dist/medium-zoom.min.js"></script>
|
||
<script>window.addEventListener('load', () => mediumZoom('article img', { 'background': 'rgba(0, 0, 0, 0.75)' }))</script></code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Since most of the JavaScript libraries used here are not really a requirement (except for MathJax for mathematical typesetting), I’ve set them to be loaded at the end of the page loading with <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script"><code>defer</code> attribute</a>.
|
||
If you have an inline script, you can simply wrap it in an event listener for page loading (<code>window.addEventListener("load", your_function_goes_here)</code>).</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>If you want document-specific libraries, you have to pass some raw HTML through the parser of the document.
|
||
For Goldmark, the default Markdown parser starting <a href="https://gohugo.io/news/0.60.0-relnotes/">Hugo v0.60.0</a>, blocks raw HTML by default and you can disable it by setting <code>markup.goldmark.renderer.unsafe</code> to <code>true</code>.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>For Blackfriday, it parses even the raw HTML just fine.
|
||
Though, you have to set it as the default Markdown parser.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>For <a href="https://asciidoctor.org/">Asciidoctor</a>, you can use <a href="https://asciidoctor.org/docs/user-manual/#passthroughs">passthroughs</a> to get raw HTML through.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect1">
|
||
<h2 id="_twitter_cards">Twitter cards</h2>
|
||
<div class="sectionbody">
|
||
<div class="paragraph">
|
||
<p>This will add <a href="https://developer.twitter.com/en/docs/tweets/optimize-with-cards/guides/getting-started">Twitter cards</a> for your webpages.
|
||
(Be sure to copy the <code>head</code> partial first in your own layout folder.)</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Thankfully, Hugo already has <a href="https://gohugo.io/templates/internal/#twitter-cards">an internal template for Twitter cards</a>.
|
||
Simply add <code>{{- template "_internal/twitter_cards.html" . -}}</code> somewhere in your own copy.
|
||
(For reference, <a href="https://github.com/gohugoio/hugo/blob/25a6b33693992e8c6d9c35bc1e781ce3e2bca4be/tpl/tplimpl/embedded/templates/twitter_cards.html">here’s the source code for the internal template</a>.)</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>You could also roll your own Twitter cards but I recommend to modify the internal template instead fitting your specific needs.
|
||
(Copy the internal template from the given link, create it as a partial in <code>layouts/partials/twitter_cards.html</code>, modify it, and insert the template with <code>{{- partial "twitter_cards.html" -}}</code>.)</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect1">
|
||
<h2 id="_open_graph_protocol">Open Graph protocol</h2>
|
||
<div class="sectionbody">
|
||
<div class="paragraph">
|
||
<p>Next up, we’re implementing <a href="https://opengraphprotocol.org/">Open Graph protocol</a> for our webpages.
|
||
Commonly used for making suitable format when sharing the content on certain sites like Facebook.
|
||
(Be sure to copy the <code>head</code> partial first in your own layout folder.)</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Similar to Twitter cards, Hugo has <a href="https://gohugo.io/templates/internal/#open-graph">an internal template for this</a>.
|
||
Simply add <code>{{- template "_internal/opengraph.html" . -}}</code> somewhere in your own copy.
|
||
(For reference, <a href="https://github.com/gohugoio/hugo/blob/25a6b33693992e8c6d9c35bc1e781ce3e2bca4be/tpl/tplimpl/embedded/templates/opengraph.html">here’s the source code for the internal template</a>.)</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>If you want more control and customized version of the output, I recommend to copy the internal template and create a partial (e.g., <code>layouts/partials/opengraph.html</code>) and modify it.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect1">
|
||
<h2 id="_an_archive_page">An archive page</h2>
|
||
<div class="sectionbody">
|
||
<div class="paragraph">
|
||
<p>This will add an archive page similar to archive pages <a href="https://davidtranscend.com/archives/">like</a> <a href="https://lukesmith.xyz/blogindex.html">these</a>.</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="highlight"><code class="language-go" data-lang="go">{{- define "main" -}}
|
||
|
||
<h1>{{ .Title }}</h1>
|
||
|
||
{{ .Content }}
|
||
|
||
<hr>
|
||
|
||
{{- /* Creating a section that lists out regular pages by year */ -}}
|
||
{{ range $.Site.RegularPages.GroupByPublishDate "2006" }}
|
||
{{- /* Skip regular pages with an invalid creation date string. */ -}}
|
||
{{- /* This is convenient if we want to exclude certain posts to be listed by giving no value to `date` in the frontmatter. */ -}}
|
||
{{- /* We will also exclude hidden pages. */ -}}
|
||
{{ if ne .Key "0001" }}
|
||
<section data-year="{{ .Key }}">
|
||
<h2 id="{{ .Key }}">{{ .Key }}</h2>
|
||
<ul>
|
||
{{- range where .Pages "Params.hidden" "!=" true -}}
|
||
<li>
|
||
<date>{{ .Date.Format "2006-01-02" }}</date> -
|
||
<a aria-label="{{ .Title }}" href="{{ .Permalink }}">{{ .Title }}</a>
|
||
</li>
|
||
{{- end -}}
|
||
</ul>
|
||
</section>
|
||
{{- end }}
|
||
{{ end }}
|
||
|
||
{{- end -}}</code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>We will simply add this as a layout in our customized theme.
|
||
Let’s call it <code>archives</code> so we have to add a file in <code>layouts/_default/archives.html</code> then set a page of our project with the <code>layout</code> key in the frontmatter.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>We want the archives page to be accessed at <code>$.Site.BaseURL/archives</code> so we’ll simply create <code>archives.adoc</code> (<a href="https://gohugo.io/content-management/formats/#list-of-content-formats">any valid content files with certain file extensions can do</a>, I’m using <a href="https://asciidoctor.org/">Asciidoctor</a>) with the following example content.</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="highlight"><code class="language-asciidoctor" data-lang="asciidoctor">---
|
||
title: "Archives"
|
||
layout: "archive"
|
||
---
|
||
|
||
= Archives
|
||
|
||
This is the archives of the century.</code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect1">
|
||
<h2 id="_configurable_social_media_links">Configurable social media links</h2>
|
||
<div class="sectionbody">
|
||
<div class="paragraph">
|
||
<p>Most themes offer quick social media links with site configuration.
|
||
However, it is only limited to popular media sites such as Facebook, Twitter, Instagram, GitHub, etc.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>To get around this, we’ll make use of <a href="https://gohugo.io/templates/data-templates/">data templates</a>.
|
||
Let’s create a quick game plan how does it work.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>The data is a top-level dictionary/object with each key contains an object with the following fields.</p>
|
||
</div>
|
||
<div class="ulist">
|
||
<ul>
|
||
<li>
|
||
<p><code>url</code> is the… contact link itself and it is required to have it.</p>
|
||
</li>
|
||
<li>
|
||
<p><code>name</code> is the text to appear in the output.
|
||
Also required to have.</p>
|
||
</li>
|
||
<li>
|
||
<p><code>weight</code> is an integer similar to how Hugo sorts the pages with the lower weight having high precedence;
|
||
if this key is absent, it will be interpreted as 0.</p>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>And here’s the data example in TOML which is placed in <code>data/contact.toml</code>.</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="highlight"><code class="language-toml" data-lang="toml">[github]
|
||
name = "GitHub"
|
||
url = "https://github.com/foo-dogsquared"
|
||
|
||
[gitlab]
|
||
name = "Gitlab"
|
||
url = "https://gitlab.com/foo-dogsquared"
|
||
|
||
[keybase]
|
||
name = "Keybase"
|
||
url = "https://keybase.io/foo_dogsquared"
|
||
weight = -1
|
||
|
||
[twitter]
|
||
name = "Twitter"
|
||
url = "https://twitter.com/foo_dogsquared"</code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>I want my Keybase profile to appear first than anything else for whatever reason so the <code>weight</code> key is set to -1.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>With this data, we can then create a template out of it.
|
||
I’ve put the following template in a partial named <code>contacts</code> (i.e., <code>layouts/partials/contacts</code>).</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="highlight"><code class="language-go" data-lang="go"><address>
|
||
{{- range (sort $.Site.Data.contact "weight" "asc") -}}
|
||
| <a rel="me" href="{{ .url }}">{{- .name -}}</a> |
|
||
{{- end -}}
|
||
</address></code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>A suggestion (and an exercise) for extending this is to create image links.
|
||
Maybe add another key named <code>image</code> that accepts either URL.
|
||
The <code>name</code> would now be the image alternative text.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</main>
|
||
</article>
|
||
|
||
<hr>
|
||
<footer>
|
||
|
||
<p><a href="https://foo-dogsquared.github.io/hugo-theme-contentful/">Back to home</a></p>
|
||
</footer>
|
||
|
||
|
||
|
||
<p>Available in other languages:
|
||
<span class="site__languages">|
|
||
|
||
<a href="/hugo-theme-contentful/en">English</a> |
|
||
|
||
<a href="/hugo-theme-contentful/tl">Tagalog</a> |
|
||
|
||
</span>
|
||
</p>
|
||
|
||
|
||
|
||
<p>© 2022 Contentful</p>
|
||
</body>
|
||
</html>
|