Update with custom theme files

This commit is contained in:
Ben Goldsworthy 2022-11-10 22:48:02 -07:00
parent 3b303aee07
commit 0c277c2458
45 changed files with 4324 additions and 11 deletions

View file

@ -0,0 +1 @@
{{- with 1 -}}{{- end -}}<a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener"{{ end }}>{{ .Text | safeHTML }}</a>{{- with 1 -}}{{- end -}}

View file

@ -1,11 +1,49 @@
<!DOCTYPE html>
<html>
{{- partial "head.html" . -}}
<body>
{{- partial "header.html" . -}}
<div id="content">
{{- block "main" . }}{{- end }}
</div>
{{- partial "footer.html" . -}}
</body>
{{ partialCached "copying.html" . }}
<html itemscope itemtype="https://schema.org/WebSite">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, intitial-scale=1">
<meta name="robots" content="noindex">
<!--<meta http-equiv="Content-Security-Policy" content="default-src 'self'">-->
<meta name="theme-color" content="#FFFFF0">
<meta name="description" content="{{ block "head-description" . }}{{ $.Site.Params.description | html }}{{ end }}">
<meta name="twitter:dnt" content="on">
<title itemprop="name">{{- block "title" . -}}{{- .Site.Title }} | {{ .Site.Params.tagline -}}{{- end -}}</title>
<link rel="license" href="{{ block "head-license" . }}https://creativecommons.org/publicdomain/zero/1.0/{{ end }}">
<link rel="me" href="mailto:me+bg@bengoldsworthy.net">
<link rel="icon" sizes="192x192" href="/images/icon.png">
{{ with .OutputFormats.Get "rss" }}<link rel="{{ .Rel }}" type="{{ .MediaType.Type | html }}" href="{{ .RelPermalink }}" title="{{ $.Site.Title | safeHTML }}" />{{ end }}
<link href="/css/sanitize.css" rel="stylesheet" />
{{- $sass := resources.Get "css/main.scss" }}
{{- $style := $sass | resources.ToCSS | resources.Fingerprint }}
<link rel="stylesheet" type="text/css" href="{{ $style.RelPermalink }}" integrity="{{ $style.Data.Integrity | html }}">
{{- block "header-scripts" . -}}<!-- -->{{- end -}}
</head>
<body class="site-container site-container{{ block "main-class" . }}{{ end }}">
{{ block "header" . -}}
{{- partialCached "header/site-header.html" . -}}
{{- end }}
<main class="site-content site-content{{ block "main-class" . }}{{ end }}" itemscope itemtype="{{ block "main-type" . }}https://schema.org/Thing{{ end }}">
{{ block "main-header" . }}{{ end }}
{{ block "main-body" . }}{{ end }}
{{ block "main-footer" . }}{{ end }}
</main>
{{- block "footer" . -}}
<footer class="site-footer">
<p>By <a href="/">{{ $.Site.Author.name }}</a> | <a href="{{ $.Site.Params.reportIssueURL }}" target="_blank" rel="noopener noreferrer">Report an Issue</a> | <a href="/privacy-policy">Privacy Policy</a> | <a href="/{{ .Sitemap.Filename }}">Sitemap</a> | Built: {{ now.Format "2006-01-02T15:04:05" }}</p>
{{ block "footer-scripts" . }}<!-- -->{{ end }}
</footer>
{{- end -}}
</body>
</html>

View file

@ -0,0 +1,26 @@
{{ define "title" }}
{{ .Type | singularize }}: &lsquo;{{ .Page.Title | plainify }}&rsquo; | {{ .Site.Title }}
{{ end }}
{{ define "main-class" }}--list{{ end}}
{{ define "main-header" }}
<header class="site-content__header">
<h1 class="page-title">{{ .Type | singularize }}: <q>{{ .Title | safeHTML }}</q>
{{ range .AlternativeOutputFormats -}}
<a href="{{ .RelPermalink }}">
<img class="feed-icon" src="/images/feed-icon.png">
</a>
{{ end }}
</h1>
{{ .Content }}
<nav class="page-header__minor-links">
{{ partial "years-list.html" . }}
</nav>
</header>
{{ end }}
{{ define "main-body" }}
{{ partial "items-grid.html" . }}
{{ end }}

39
layouts/_default/rss.xml Normal file
View file

@ -0,0 +1,39 @@
{{- $pctx := . -}}
{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
{{- $pages := slice -}}
{{- if or $.IsHome $.IsSection -}}
{{- $pages = $pctx.RegularPages -}}
{{- else -}}
{{- $pages = $pctx.Pages -}}
{{- end -}}
{{- $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 | plainify }}{{ else }}{{ with .Title }}{{ . | plainify }} on {{ end }}{{ .Site.Title | plainify }}{{ end }}</title>
<link>{{ .Permalink }}</link>
<description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}</description>
{{ with .Site.LanguageCode }}<language>{{.}}</language>{{end}}
{{ with .Site.Author.email }}<managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}
{{ with .Site.Author.email }}<webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}
{{ with .Site.Copyright }}<copyright>{{.}}</copyright>{{end}}
{{ if not .Date.IsZero }}<lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
{{- with .OutputFormats.Get "RSS" -}}
{{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
{{- end -}}
{{ range $pages }}
<item>
<title>{{ .Title | plainify }}</title>
<link>{{ .Permalink }}</link>
<pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
{{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
<guid>{{ .Permalink }}</guid>
<description>{{ .Summary | html }}</description>
</item>
{{ end }}
</channel>
</rss>

View file

@ -0,0 +1,26 @@
{{ define "title" }}
{{ .Page.Title | plainify }} | {{ .Site.Title }}
{{ end }}
{{ define "main-class" }}--section{{ end }}
{{ define "main-type" }}.{{ .Params.mainType }}{{ end }}
{{ define "item-type" }}{{ .Params.itemsType }}{{ end }}
{{ define "main-header" }}
<header class="site-content__header">
<h1 class="page-title">{{ .Title | safeHTML }}
{{ range .AlternativeOutputFormats -}}
<a href="{{ .RelPermalink }}">
<img class="feed-icon" src="/images/feed-icon.png">
</a>
{{ end }}
</h1>
{{ .Content }}
</header>
{{ end }}
{{ define "main-body" }}
{{ partial "items-grid.html" . }}
{{ end }}

View file

@ -0,0 +1,120 @@
{{ define "title" }}{{ .Title | plainify }} | {{ .Site.Title }}{{ end }}
{{ define "head-description" }}{{ .Summary | plainify }}{{ end }}
{{ define "main-class" }}--single{{ end }}
{{ define "footer-scripts" }}
{{ with .Params.locations }}
<script src="https://www.openlayers.org/api/OpenLayers.js"></script>
<script>
map = new OpenLayers.Map("mapdiv");
map.addLayer(new OpenLayers.Layer.OSM());
var lonLats = [];
{{ range . }}
{{ with ( index $.Site.Data.locations . ) }}
lonLats.push(new OpenLayers.LonLat( {{ .lon }} , {{ .lat }} )
.transform(
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984
map.getProjectionObject() // to Spherical Mercator Projection
));
{{ else }}
{{ warnf "Could not find lat-lon for %q (%q)" . $.File.Path }}
{{ end }}
{{ end }}
/* TODO: Smarter zoom selection */
var zoom=5;
var markers = new OpenLayers.Layer.Markers( "Markers" );
map.addLayer(markers);
for (var i = 0; i < lonLats.length; i++) {
markers.addMarker(new OpenLayers.Marker(lonLats[i]));
}
/* TODO: Smarter centering */
map.setCenter(lonLats[0], zoom);
</script>
{{ end }}
{{ with .Params.scripts }}
{{ if in . "mathjax" }}
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<script src="/js/mathjax-config.js"></script>
{{ end }}
{{ end }}
{{ end }}
{{ define "main-header" }}
<header class="site-content__header">
<div class="article-header__featured-image"
{{ if .Params.featured_image }}
{{ if .Resources.GetMatch .Params.featured_image }}
style="background-image: url({{ ( .Resources.GetMatch .Params.featured_image ).RelPermalink }})"
{{ else }}
style="background-image: url({{ .Params.featured_image }})"
{{ end }}
{{ end }}>
<div class="article-header__title-wrapper">
<h1 class="article-header__title{{ if gt ( len ( .Title | plainify ) ) 40 }} article-header__title--long{{ end }}">
<span role="text" itemprop="name">{{ .Title | safeHTML }}</span>
</h1>
{{ with .Params.subtitle }}
<p class="article-header__subtitle">{{ . | safeHTML }}</p>
{{ end }}
</div>
{{ with .Resources.GetMatch .Params.featured_image }}
<p class="attr">
{{ if .Params.attrlink }}<a href="{{ .Params.attrlink }}" target="_blank" rel="noopener">{{ end }}
{{- .Params.Attr | safeHTML -}}
{{ if .Params.attrlink }}</a>{{ end }}
{{ if .Params.attrlicence }} ({{ .Params.attrlicence }}){{ end }}
<p>
{{ end }}
</div>
<p class="article-header__word-count">~<span itemprop="wordCount">{{ .FuzzyWordCount | lang.NumFmt 0 }}</span> words</p>
<p class="article-header__publish-date">Published: <span itemprop="datePublished" datetime="{{ .PublishDate }}">{{ .PublishDate.Format "January 2" }}<sup>{{ if in (slice 1 21 31) .PublishDate.Day}}st{{ else if in (slice 2 22) .PublishDate.Day}}nd{{ else if in (slice 3 23) .PublishDate.Day}}rd{{ else }}th{{ end }}</sup>, 1{{ .PublishDate.Format "2006" | lang.NumFmt 0 }}&nbsp;<abbr style="text-transform: small-caps; font-size: 0.8em;" title="Holocene Era">HE</abbr></span></p>
<p class="article-header__modified-date">Last modified: <span itemprop="dateModified" datetime="{{ .Lastmod }}">{{ .Lastmod.Format "January 2" }}<sup>{{ if in (slice 1 21 31) .Lastmod.Day}}st{{ else if in (slice 2 22) .Lastmod.Day}}nd{{ else if in (slice 3 23) .Lastmod.Day}}rd{{ else }}th{{ end }}</sup>, 1{{ .Lastmod.Format "2006" | lang.NumFmt 0 }}&nbsp;<abbr style="text-transform: small-caps; font-size: 0.8em;" title="Holocene Era">HE</abbr></span></p>
{{ $post_age_in_years := math.Round ( div ( div ( now.Sub .PublishDate ).Hours 24 ) 365 ) }}
{{ if ( or .Params.site .Params.controversial ( gt $post_age_in_years 2 ) ) }}
<aside class="article-header__warnings">
<ul>
{{ if ( gt $post_age_in_years 2 ) }}<li>This piece was written <strong>over {{ $post_age_in_years }} years ago</strong>. It may no longer accurately reflect my views now, or may be factually outdated.</li>{{ end }}
{{ if .Params.controversial }}<li>This piece has been marked as potentially <strong>controversial</strong>, whether due to the topic addressed, the content of the article, or both. Don't say you weren't warned.</li>{{ end }}
{{ if .Params.site }}<li>This piece was originally written for an older version of this site. As such, it may not have transferred over properly and some images and links might be broken.</li>{{ end }}
</ul>
</aside>
{{ end }}
{{ if .Params.notes }}
<aside class="article-header__notes">
<ul>
{{ range .Params.notes }}
<li>{{ . | safeHTML }}</li>
{{ end }}
</ul>
</aside>
{{ end }}
{{ if and ( .TableOfContents ) ( ne .TableOfContents "<nav id=\"TableOfContents\"></nav>" ) }}
<nav class="article-header__table-of-contents">
<h2 class="article-header__subtitle">Table of Contents</h2>
{{ .TableOfContents }}
</nav>
{{ end }}
</header>
{{ end }}
{{ define "main-body" }}
<article class="site-content__body">
{{ .Content }}
</article>
{{ end }}
{{ define "main-footer" }}
{{ partial "post-meta.html" . }}
{{ end }}

111
layouts/blog/section.html Normal file
View file

@ -0,0 +1,111 @@
{{ define "title" }}
{{ .Page.Title | plainify }} | {{ .Site.Title }}
{{ end }}
{{ define "main-class" }}--section{{ end }}
{{ define "main-type" }}{{ .Params.mainType }}{{ end }}
{{ define "footer-scripts" }}
<script>
// Source: https://css-tricks.com/the-complete-guide-to-lazy-loading-images/
document.addEventListener("DOMContentLoaded", function() {
var lazyloadImages;
if ("IntersectionObserver" in window) {
lazyloadImages = document.querySelectorAll(".lazy");
var imageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
console.log("Ding");
var image = entry.target;
image.classList.remove("lazy");
imageObserver.unobserve(image);
}
});
});
lazyloadImages.forEach(function(image) {
imageObserver.observe(image);
});
} else {
var lazyloadThrottleTimeout;
lazyloadImages = document.querySelectorAll(".lazy");
function lazyload () {
if(lazyloadThrottleTimeout) {
clearTimeout(lazyloadThrottleTimeout);
}
lazyloadThrottleTimeout = setTimeout(function() {
var scrollTop = window.pageYOffset;
lazyloadImages.forEach(function(img) {
if(img.offsetTop < (window.innerHeight + scrollTop)) {
img.src = img.dataset.src;
img.classList.remove('lazy');
}
});
if(lazyloadImages.length == 0) {
document.removeEventListener("scroll", lazyload);
window.removeEventListener("resize", lazyload);
window.removeEventListener("orientationChange", lazyload);
}
}, 20);
}
document.addEventListener("scroll", lazyload);
window.addEventListener("resize", lazyload);
window.addEventListener("orientationChange", lazyload);
}
});
</script>
{{ end }}
{{ define "main-header" }}
<header class="site-content__header">
<h1 class="page-title">{{ .Title | safeHTML }}
{{ if eq .Type "blog" }}
{{ with .GetPage "blog/posts" }}
{{ range .AlternativeOutputFormats -}}
<a href="{{ .RelPermalink }}">
<img class="feed-icon" src="{{ $.Site.Params.feedIcon }}">
</a>
{{ end }}
{{ end }}
{{ else }}
{{ range .AlternativeOutputFormats -}}
<a href="{{ .RelPermalink }}">
<img class="feed-icon" src="{{ $.Site.Params.feedIcon }}">
</a>
{{ end }}
{{ end }}
</h1>
{{ .Content }}
<nav class="page-header__minor-links">
<ul class="minor-links__categories">
<li><a href="/series"><h2>Series</h2></a> <p>({{ len .Site.Taxonomies.series }})</p></li>
{{ range .Site.Taxonomies.categories }}
<li><a href="{{ .Page.RelPermalink }}"><h2>{{ .Page.Title | safeHTML }}</h2></a> <p>({{ len . }})</p></li>
{{ end }}
</ul>
{{ if eq .Type "blog" }}
{{ with .GetPage "blog/posts" }}
{{ partial "years-list.html" . }}
{{ end }}
{{ else }}
{{ partial "years-list.html" . }}
{{ end }}
</nav>
</header>
{{ end }}
{{ define "main-body" }}
{{ if eq .Type "blog" }}
{{ with .GetPage "blog/posts" }}
{{ partial "items-grid.html" . }}
{{ end }}
{{ else }}
{{ partial "items-grid.html" . }}
{{ end }}
{{ end }}

127
layouts/blog/single.html Normal file
View file

@ -0,0 +1,127 @@
{{ define "title" }}
&ldquo;{{ .Title | plainify }}&rdquo; | {{ .Site.Title }}
{{ end }}
{{ define "main-class" }}--single{{ end }}
{{ define "footer-scripts" }}
{{ with .Params.locations }}
<script src="https://www.openlayers.org/api/OpenLayers.js"></script>
<script>
map = new OpenLayers.Map("mapdiv");
map.addLayer(new OpenLayers.Layer.OSM());
var lonLats = [];
{{ range . }}
{{ with ( index $.Site.Data.locations . ) }}
lonLats.push(new OpenLayers.LonLat( {{ .lon }} , {{ .lat }} )
.transform(
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984
map.getProjectionObject() // to Spherical Mercator Projection
));
{{ else }}
{{ warnf "Could not find lat-lon for %q (%q)" . $.File.Path }}
{{ end }}
{{ end }}
/* TODO: Smarter zoom selection */
var zoom=5;
var markers = new OpenLayers.Layer.Markers( "Markers" );
map.addLayer(markers);
for (var i = 0; i < lonLats.length; i++) {
markers.addMarker(new OpenLayers.Marker(lonLats[i]));
}
/* TODO: Smarter centering */
map.setCenter(lonLats[0], zoom);
</script>
{{ end }}
{{ with .Params.scripts }}
{{ if in . "mathjax" }}
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<script src="/js/mathjax-config.js"></script>
{{ end }}
{{ end }}
{{ end }}
{{ define "main-header" }}
<header class="site-content__header">
{{ if .Params.series }}
<p class="article-header__series">Part of series:
{{ range ( .GetTerms "series" ) }}
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
{{ end }}
</p>
{{ end }}
<div class="article-header__featured-image"
{{ if .Params.featured_image }}
{{ if .Resources.GetMatch .Params.featured_image }}
style="background-image: url({{ ( .Resources.GetMatch .Params.featured_image ).RelPermalink }})"
{{ else }}
style="background-image: url({{ .Params.featured_image }})"
{{ end }}
{{ end }}>
<div class="article-header__title-wrapper">
<h1 class="article-header__title{{ if gt ( len ( .Title | plainify ) ) 40 }} article-header__title--long{{ end }}">
<span role="text" itemprop="name">{{ .Title | safeHTML }}</span>
</h1>
{{ with .Params.subtitle }}
<p class="article-header__subtitle">{{ . | safeHTML }}</p>
{{ end }}
</div>
{{ with .Resources.GetMatch .Params.featured_image }}
<p class="attr">
{{ if .Params.attrlink }}<a href="{{ .Params.attrlink }}" target="_blank" rel="noopener">{{ end }}
{{- .Params.Attr | safeHTML -}}
{{ if .Params.attrlink }}</a>{{ end }}
{{ if .Params.attrlicence }} ({{ .Params.attrlicence }}){{ end }}
<p>
{{ end }}
</div>
<p class="article-header__word-count">~<span itemprop="wordCount">{{ .FuzzyWordCount | lang.NumFmt 0 }}</span> words</p>
<p class="article-header__publish-date">Published: <span itemprop="datePublished" datetime="{{ .PublishDate }}">{{ .PublishDate.Format "January 2" }}<sup>{{ if in (slice 1 21 31) .PublishDate.Day}}st{{ else if in (slice 2 22) .PublishDate.Day}}nd{{ else if in (slice 3 23) .PublishDate.Day}}rd{{ else }}th{{ end }}</sup>, 1{{ .PublishDate.Format "2006" | lang.NumFmt 0 }}&nbsp;<abbr style="text-transform: small-caps; font-size: 0.8em;" title="Holocene Era">HE</abbr></span></p>
<p class="article-header__modified-date">Last modified: <span itemprop="dateModified" datetime="{{ .Lastmod }}">{{ .Lastmod.Format "January 2" }}<sup>{{ if in (slice 1 21 31) .Lastmod.Day}}st{{ else if in (slice 2 22) .Lastmod.Day}}nd{{ else if in (slice 3 23) .Lastmod.Day}}rd{{ else }}th{{ end }}</sup>, 1{{ .Lastmod.Format "2006" | lang.NumFmt 0 }}&nbsp;<abbr style="text-transform: small-caps; font-size: 0.8em;" title="Holocene Era">HE</abbr></span></p>
{{ $post_age_in_years := math.Round ( div ( div ( now.Sub .PublishDate ).Hours 24 ) 365 ) }}
{{ if ( or .Params.site .Params.controversial ( gt $post_age_in_years 2 ) ) }}
<aside class="article-header__warnings">
<ul>
{{ if ( gt $post_age_in_years 2 ) }}<li>This piece was written <strong>over {{ $post_age_in_years }} years ago</strong>. It may no longer accurately reflect my views now, or may be factually outdated.</li>{{ end }}
{{ if .Params.controversial }}<li>This piece has been marked as potentially <strong>controversial</strong>, whether due to the topic addressed, the content of the article, or both. Don't say you weren't warned.</li>{{ end }}
{{ if .Params.site }}<li>This piece was originally written for an older version of this site. As such, it may not have transferred over properly and some images and links might be broken.</li>{{ end }}
</ul>
</aside>
{{ end }}
{{ if .Params.notes }}
<aside class="article-header__notes">
<ul>
{{ range .Params.notes }}
<li>{{ . | safeHTML }}</li>
{{ end }}
</ul>
</aside>
{{ end }}
{{ if and ( .TableOfContents ) ( ne .TableOfContents "<nav id=\"TableOfContents\"></nav>" ) }}
<nav class="article-header__table-of-contents">
<h2 class="article-header__subtitle">Table of Contents</h2>
{{ .TableOfContents }}
</nav>
{{ end }}
</header>
{{ end }}
{{ define "main-body" }}
<article class="site-content__body" itemprop="articleBody">
{{ .Content }}
</article>
{{ end }}
{{ define "main-footer" }}
{{ partial "post-meta.html" . }}
{{ end }}

200
layouts/cv/list.html Normal file
View file

@ -0,0 +1,200 @@
{{ define "title" }}
{{ .Page.Title | plainify }} | {{ .Site.Title }}
{{ end }}
{{ define "main-class" }}
{{- if .IsDescendant ( .GetPage "/cv/organisations" ) -}}--single{{- else -}}--section{{- end -}}
{{ end }}
{{ define "header-scripts" }}
{{ if ( or ( eq .Type "cv" ) ( .IsDescendant ( .GetPage "/cv/organisations" ) ) ) }}
<script type="text/javascript" src="/js/google-charts.js"></script>
{{ end }}
{{ end }}
{{ define "footer-scripts" }}
{{ if eq .Type "cv" }}
{{ $js := resources.Get "js/roles-chart.js" | resources.ExecuteAsTemplate "/js/render-roles-timeline.js" . }}
<script type="text/javascript" src="{{ $js.RelPermalink }}"></script>
{{ else if .IsDescendant ( .GetPage "/cv/organisations" ) }}
{{ $titles := .Scratch.Get "titles" }}
<script>
google.charts.load('current', {'packages':['timeline']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Type' });
dataTable.addColumn({ type: 'string', id: 'Job Title' });
dataTable.addColumn({ type: 'string', id: 'style', role: 'style' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
{{ range where ((.GetPage "cv").Sections) "Title" "Roles" -}}
{{- range where (where ( where .Site.Pages "Section" "cv" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles -}}
[
"{{- delimit (intersect .Params.organisations $titles ) "" | safeHTML -}}",
"{{- .Title | safeHTML -}}",
"{{ if .Params.end_date }}#FFFFF0{{ else }}#BBBBB0{{ end }}",
new Date("{{ .Date.Format "2006-01-02" }}"),
new Date("{{ if .Params.end_date }}{{ delimit ( first 1 .Params.end_date ) "" }}{{ else }}{{ now.Format "2006-01-02" }}{{ end }}")
],
{{- end -}}
{{ end -}}
]);
var options = {
title: '{{ .Title | plainify }} Roles Timeline',
timeline: { showBarLabels: true }
};
chart.draw(dataTable, options);
{{ if $titles }}
container.style.height = ( ( ( {{ len $titles }} - 1 ) * 41 ) + 15 )+ "px";
{{ end }}
}
</script>
{{ end }}
{{ end }}
{{ define "main-header" }}
{{ if .IsDescendant ( .GetPage "/cv/organisations" ) }}
<header class="site-content__header">
<div class="article-header__featured-image"
{{ if .Params.featured_image }}
{{ with .Resources.GetMatch .Params.featured_image }}
style="background-image: url({{ .RelPermalink }})"
{{ end }}
{{ end }}>
<div class="article-header__title-wrapper{{ if .Params.title_in_logo }} article-header__title-wrapper--no-title{{ end }}">
<h1 class="article-header__title">{{ .Title | safeHTML }}LIST</h1>
</div>
</div>
</header>
{{ else }}
<header class="site-content__header">
<h1 class="page-title">{{ .Title | safeHTML }}.</h1>
{{ .Content }}
{{ if eq .Type "cv" }}
<nav class="page-header__minor-links">
<ul>
{{ range ( where .Sections "Type" "not in" ( slice "cv/roles" ) ).ByTitle }}
<li><a href="{{ .RelPermalink }}"><h2>{{ .Title }}</h2></a> <p>({{ len (where ( where .Site.Pages "Section" "cv" ) "Parent.Title" .Title ) }})</p></li>
{{ end }}
</ul>
</nav>
{{ end }}
{{ if eq .Type "cv" }}
<aside class="timeline__legend">
<span><div class="colour-square colour-square--current"></div> <p>Current</p></span>
<span><div class="colour-square colour-square--past"></div> <p>Past</p></span>
</aside>
{{ end }}
</header>
{{ end }}
{{ end }}
{{ define "main-body" }}
{{ if .IsDescendant ( .GetPage "/cv/organisations" ) }}
{{ $titles := slice (.Title | plainify) }}
{{ range .Sections.ByTitle }}
{{ $titles = $titles | append (slice (.Title | plainify) )}}
{{ $titles = $titles | append ( partial "cv/organisations/recursive-children-titles.html" . ) }}
{{ end }}
{{ .Scratch.Set "titles" $titles }}
<main id="organisation-body" class="site-content__body">
<section id="description">
{{ .Content }}
</section>
<section id="roles-timelimne">
<aside class="timeline__legend">
<span><div class="colour-square colour-square--current"></div> <p>Current</p></span>
<span><div class="colour-square colour-square--past"></div> <p>Past</p></span>
</aside>
<div id="timeline" aria-label="Role Time" role="img">Javascript must be enabled to view this chart.</div>
</section>
<section id="related" class="row">
{{ if ne .Parent.Title "Organisations" }}
<section id="parents" class="col-6 col-m-12">
<h2 class="subheading">Parent</h2>
{{ with .Parent }}
<ul>
<li><a href="{{ .RelPermalink }}">{{ .Title | safeHTML }}</a></li>
</ul>
{{ end }}
</section>
{{ end }}
{{ if gt (len .Sections) 0 }}
<section id="children" class="col-6 col-m-12">
<h2 class="subheading">Children</h2>
<ul>
{{ range .Sections.ByTitle }}
<li>
<a href="{{ .RelPermalink }}">{{ .Title | safeHTML }}</a>
{{ partial "cv/organisations/recursive-children.html" . }}
</li>
{{ end }}
</ul>
</section>
{{ end }}
{{- $titles := .Scratch.Get "titles" -}}
{{ range (where ((.GetPage "blog").Sections) "Title" "Blog Posts") }}
{{ $section_title := .Title }}
{{ with where (where ( where .Site.Pages "Section" "blog" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles }}
{{ partial "cv/organisations/organisation-items.html" ( dict "section_title" $section_title "content" . ) }}
{{ end }}
{{ end }}
{{ range (where ((.GetPage "portfolio").Sections) "Title" "!=" "Appearances").ByTitle }}
{{ $section_title := .Title }}
{{ with where (where ( where .Site.Pages "Section" "portfolio" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles }}
{{ partial "cv/organisations/organisation-items.html" ( dict "section_title" $section_title "content" . ) }}
{{ end }}
{{ end }}
{{ range (where ((.GetPage "cv").Sections) "Title" "Qualifications") }}
{{ $section_title := .Title }}
{{ with where (where ( where .Site.Pages "Section" "portfolio" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles }}
{{ partial "cv/organisations/organisation-items.html" ( dict "section_title" $section_title "content" . ) }}
{{ end }}
{{ end }}
{{ range (where ((.GetPage "cv").Sections) "Title" "Awards") }}
{{ $section_title := .Title }}
{{ with where (where ( where .Site.Pages "Section" "portfolio" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles }}
{{ partial "cv/organisations/organisation-items.html" ( dict "section_title" $section_title "content" . ) }}
{{ end }}
{{ end }}
{{ range (where ((.GetPage "portfolio").Sections) "Title" "Appearances").ByTitle }}
{{ $section_title := .Title }}
{{ with where (where ( where .Site.Pages "Section" "portfolio" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles }}
{{ partial "cv/organisations/organisation-items.html" ( dict "section_title" $section_title "content" . ) }}
{{ end }}
{{ end }}
</section>
</main>
{{ else }}
{{ if eq .Type "cv" }}
<article class="site-content__body site-content__body--list">
<div id="timeline" width="1000" height="400" aria-label="Roles Timeline" role="img">Javascript must be enabled to view this chart.</div>
</article>
{{ else if eq .Type "cv/organisations" . }}
{{ with .GetPage "cv/organisations" }}
{{ partial "items-table.html" . }}
{{ end }}
{{ else }}
{{ partial "items-grid.html" . }}
{{ end }}
{{ end }}
{{ end }}

45
layouts/cv/locations.html Normal file
View file

@ -0,0 +1,45 @@
{{ define "title" }}
CV by Location | {{ .Site.Title }}
{{ end }}
{{ define "main-class" }}--section location-map{{ end }}
{{ define "footer-scripts" }}
<script src="https://www.openlayers.org/api/OpenLayers.js"></script>
<script>
map = new OpenLayers.Map("map");
map.addLayer(new OpenLayers.Layer.OSM());
var markers = new OpenLayers.Layer.Markers( "Markers" );
map.addLayer(markers);
{{ range $.Site.Data.locations }}
markers.addMarker(
new OpenLayers.Marker(
new OpenLayers.LonLat(
{{ .lon }},
{{ .lat }}
).transform(
new OpenLayers.Projection("EPSG:4326"),
map.getProjectionObject()
)
)
);
{{ end }}
map.setCenter([0,0], 5);
</script>
{{ end }}
{{ define "main-header" }}
<header class="site-content__header">
<h1 class="page-title">{{ .Title | safeHTML }}.</h1>
{{ .Content }}
</header>
{{ end }}
{{ define "main-body" }}
<article class="site-content__body site-content__body--chart">
<div id="map" style="width: 100%; height: 500px; margin: 0; display: block;"></div>
</article>
{{ end }}

217
layouts/cv/section.html Normal file
View file

@ -0,0 +1,217 @@
{{ define "title" }}
{{ .Page.Title | plainify }} | {{ .Site.Title }}
{{ end }}
{{ define "main-class" }}
{{- if .IsDescendant ( .GetPage "/cv/organisations" ) -}}--single{{- else -}}--section{{- end -}}
{{ end }}
{{ define "header-scripts" }}
{{ if ( or ( eq .Type "cv" ) ( .IsDescendant ( .GetPage "/cv/organisations" ) ) ) }}
<script type="text/javascript" src="/js/google-charts.js"></script>
{{ end }}
{{ end }}
{{ define "footer-scripts" }}
{{ if .IsDescendant ( .GetPage "/cv/organisations" ) }}
{{ $titles := .Scratch.Get "titles" }}
<script>
google.charts.load('current', {'packages':['timeline']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Type' });
dataTable.addColumn({ type: 'string', id: 'Job Title' });
dataTable.addColumn({ type: 'string', id: 'style', role: 'style' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
{{- $unpaid_past := "#FFFFF0" -}}
{{- $paid_past := "#FCFCA6" -}}
{{- $unpaid_current := "#BBBBB0" -}}
{{- $paid_current := "#BCBC7E" -}}
{{ with ( .GetPage "cv/roles" ).Pages -}}
{{- range ( where . ".Params.organisations" "intersect" $titles ) -}}
[
"{{- delimit ( intersect .Params.organisations $titles ) ", " | safeHTML -}}",
"{{- .Title | safeHTML -}}",
"{{ if .Params.end_date -}}
{{- if .Params.paid -}}
{{- $paid_past -}}
{{- else -}}
{{- $unpaid_past -}}
{{- end -}}
{{- else -}}
{{- if .Params.paid -}}
{{- $paid_current -}}
{{- else -}}
{{- $unpaid_current -}}
{{- end -}}
{{- end }}",
new Date("{{ .Date.Format "2006-01-02" }}"),
new Date("
{{- if .Params.end_date -}}
{{- .Params.end_date -}}
{{- else -}}
{{- now.Format "2006-01-02" -}}
{{- end -}}
")
],
{{- end -}}
{{ end -}}
]);
var options = {
title: '{{ .Title | plainify }} Roles Timeline',
height: '100%',
chartArea: {
width: '94%'
},
width: '100%',
timeline: { showBarLabels: true }
};
chart.draw(dataTable, options);
}
</script>
{{ else }}
{{ $js := resources.Get "js/roles-chart.js" | resources.ExecuteAsTemplate "/js/render-roles-timeline.js" ( .GetPage "cv/roles" ) }}
<script type="text/javascript" src="{{ $js.RelPermalink }}"></script>
{{ end }}
{{ end }}
{{ define "main-header" }}
{{ if .IsDescendant ( .GetPage "/cv/organisations" ) }}
<header class="site-content__header">
<div class="article-header__featured-image"
{{ if .Params.featured_image }}
{{ with .Resources.GetMatch .Params.featured_image }}
style="background-image: url({{ .RelPermalink }})"
{{ end }}
{{ end }}>
<div class="article-header__title-wrapper{{ if .Params.title_in_logo }} article-header__title-wrapper--no-title{{ end }}">
<h1 class="article-header__title">{{ if ( .Params.markup_title ) }}{{ .Params.markup_title | safeHTML }}{{ else }}{{ .Title }}{{ end }}</h1>
</div>
</div>
</header>
{{ else }}
<header class="site-content__header">
<h1 class="page-title">{{ .Title | safeHTML }}.</h1>
{{ .Content }}
{{ if eq .Type "cv" }}
<nav class="page-header__minor-links">
<ul>
{{ range ( where .Sections "Type" "not in" ( slice "cv/roles" ) ).ByTitle }}
<li><a href="{{ .RelPermalink }}"><h2>{{ .Title }}</h2></a> <p>({{ len (where ( where .Site.Pages "Section" "cv" ) "Parent.Title" .Title ) }})</p></li>
{{ end }}
</ul>
</nav>
{{ end }}
{{ if eq .Type "cv" }}
<aside class="timeline__legend">
<span><div class="colour-square colour-square--current"></div> <p>Current</p></span>
<span><div class="colour-square colour-square--past"></div> <p>Past</p></span>
</aside>
{{ end }}
</header>
{{ end }}
{{ end }}
{{ define "main-body" }}
<!-- TODO: Replace with check for 'cv/organsation' -->
{{ if .IsDescendant ( .GetPage "/cv/organisations" ) }}
{{ $titles := slice ( .Title | plainify ) }}
{{ with .Sections }}
{{ $titles = $titles | append ( partial "cv/organisations/recursive-children-titles.html" . ) }}
{{ end }}
{{ .Scratch.Set "titles" $titles }}
<main id="organisation-body" class="site-content__body">
<section id="description">
{{ .Content }}
</section>
<section id="roles-timeline">
<aside class="timeline__legend">
<span><div class="colour-square colour-square--current"></div> <p>Current</p></span>
<span><div class="colour-square colour-square--past"></div> <p>Past</p></span>
</aside>
<div id="timeline" aria-label="Role Time" role="img">Javascript must be enabled to view this chart.</div>
</section>
<section id="related" class="row">
{{- $titles := .Scratch.Get "titles" -}}
{{ range (where ((.GetPage "blog").Sections) "Title" "Blog Posts") }}
{{ $section_title := .Title }}
{{ with where (where ( where .Site.Pages "Section" "blog" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles }}
{{ partial "cv/organisations/organisation-items.html" ( dict "section_title" $section_title "content" . ) }}
{{ end }}
{{ end }}
{{ range (where ((.GetPage "portfolio").Sections) "Title" "!=" "Appearances").ByTitle }}
{{ $section_title := .Title }}
{{ with where (where ( where .Site.Pages "Section" "portfolio" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles }}
{{ partial "cv/organisations/organisation-items.html" ( dict "section_title" $section_title "content" . ) }}
{{ end }}
{{ end }}
{{ range (where ((.GetPage "cv").Sections) "Title" "Qualifications") }}
{{ $section_title := .Title }}
{{ with where (where ( where .Site.Pages "Section" "portfolio" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles }}
{{ partial "cv/organisations/organisation-items.html" ( dict "section_title" $section_title "content" . ) }}
{{ end }}
{{ end }}
{{ range (where ((.GetPage "cv").Sections) "Title" "Awards") }}
{{ $section_title := .Title }}
{{ with where (where ( where .Site.Pages "Section" "portfolio" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles }}
{{ partial "cv/organisations/organisation-items.html" ( dict "section_title" $section_title "content" . ) }}
{{ end }}
{{ end }}
{{ range (where ((.GetPage "portfolio").Sections) "Title" "Appearances").ByTitle }}
{{ $section_title := .Title }}
{{ with where (where ( where .Site.Pages "Section" "portfolio" ) "Parent.Title" .Title ) ".Params.organisations" "intersect" $titles }}
{{ partial "cv/organisations/organisation-items.html" ( dict "section_title" $section_title "content" . ) }}
{{ end }}
{{ end }}
</section>
</main>
{{ else }}
{{ if eq .Type "cv" }}
<article class="site-content__body site-content__body--chart">
<div id="timeline" aria-label="Roles Timeline" role="img">Javascript must be enabled to view this chart.</div>
</article>
{{ else if eq .Type "cv/organisations" . }}
{{ with .GetPage "cv/organisations" }}
{{ partial "items-table.html" . }}
{{ end }}
{{ else }}
{{ partial "items-grid.html" . }}
{{ end }}
{{ end }}
{{ end }}
{{ define "main-footer" }}
{{ if .IsDescendant ( .GetPage "/cv/organisations" ) }}
<footer class="site-content__footer">
<section id="hierarchy">
<h2 class="subheading">Hierarchy</h2>
{{ $.Scratch.Set "parents" ( slice ) }}
{{ partial "cv/organisations/recursive-parents.html" (dict "c" . "g" $ ) }}
{{- $parents := partial "reverse-slice.html" ( $.Scratch.Get "parents" ) -}}
{{- range $parents -}}<ul><li class="hierarchy-item hierarchy-item--parent"><a href="{{ .RelPermalink }}">{{ .Title | safeHTML }}</a>{{- end -}}
<ul><li class="hierarchy-item hierarchy-item--current">{{ .Title | safeHTML }}</li>
{{ range .Sections }}<ul>{{ partial "cv/organisations/recursive-children.html" . }}</ul>{{ end }}
</ul>
{{- range $parents -}}</li></ul>{{- end -}}
</section>
</footer>
{{ end }}
{{ end }}

View file

@ -0,0 +1,13 @@
{{ define "main-class" }}--homepage{{ end }}
{{ define "header" }} <!-- null --> {{ end }}
{{ define "main-body" }}
<h1 class="page-title">
{{- with .Site.Params.pre_nominals }}<span class="pre-nominals">{{ . | safeHTML }}</span> {{ end -}}
Ben Goldsworthy
{{- with .Site.Params.post_nominals }} <span class="post-nominals">{{ . | safeHTML }}</span>{{ end -}}
</h1>
{{ range ( where .Pages "Type" "in" site.Params.mainSections ).ByTitle }}<a href="{{ .RelPermalink }}"><h2>{{ .Title }}</h2></a>{{ end }}
{{ end }}

View file

@ -0,0 +1,12 @@
{{ "<!--" | safeHTML }}
{{ .Site.Title}} - {{ .Site.Params.tagline }}
Written in {{ now.Format "2006" }} by {{ .Site.Author.name }} <{{ .Site.Author.email }}>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
{{ "-->" | safeHTML }}

View file

@ -0,0 +1,8 @@
<!--. is .c-->
<!--$ is .g-->
{{ $scratch := .g.Scratch }}
{{ with ( where ( where .g.Site.Pages "Type" "organisations" ) "Params.parent" .g.File.ContentBaseName ) }}
{{ $scratch.Add "children" ( slice . ) }}
{{ partial "cv/organisations/recursive-children.html" (dict "c" . "g" $.g ) }}
{{ end }}

View file

@ -0,0 +1,26 @@
{{ if gt ( len .content ) 4 }}
<details id="posts" class="org-items row">
<summary>
<h2 class="subheading">{{ .section_title }} ({{ len .content }})</h2>
<div class="index">
{{ range first 4 .content }}
{{ partial "item-tile.html" . }}
{{ end }}
</div>
</summary>
<div class="index">
{{ range after 4 .content }}
{{ partial "item-tile.html" . }}
{{ end }}
</div>
</details>
{{ else }}
<div id="posts" class="org-items row">
<h2 class="subheading">{{ .section_title }} ({{ len .content }})</h2>
<div class="index">
{{ range first 4 .content }}
{{ partial "item-tile.html" . }}
{{ end }}
</div>
</div>
{{ end }}

View file

@ -0,0 +1,11 @@
{{ $titles := ( slice )}}
{{ range . }}
{{ $titles = $titles | append (slice (.Title | plainify) )}}
{{ with .Sections }}
{{ $titles = $titles | append ( partial "cv/organisations/recursive-children-titles.html" . ) }}
{{ end }}
{{ end }}
{{ return $titles }}

View file

@ -0,0 +1,5 @@
<li class="hierarchy-item hierarchy-item--child"><a href="{{ .RelPermalink }}">{{ .Title | safeHTML }}</a>
{{ range .Sections }}<ul>
{{ partial "cv/organisations/recursive-children.html" . }}
</ul>{{ end }}
</li>

View file

@ -0,0 +1,12 @@
<!--. is .c-->
<!--$ is .g-->
{{ $scratch := .g.Scratch }}
{{ if .c.Parent }}
{{ if ne .c.Parent.Type "cv/organisations" }}
{{ with .c.Parent }}
{{ $scratch.Add "parents" ( slice . ) }}
{{ partial "cv/organisations/recursive-parents.html" (dict "c" . "g" $.g ) }}
{{ end }}
{{ end }}
{{ end }}

View file

@ -0,0 +1,7 @@
{{ $organisations := slice }}
{{ range .Site.Pages }}
{{ if .IsDescendant ( .GetPage "cv/organisations" ) }}
{{ $organisations = $organisations | append . }}
{{ end }}
{{ end }}
{{ return $organisations }}

View file

@ -0,0 +1,5 @@
<div class="item-tile item-tile--heading" id="items-{{ .Key }}">
<header class="item-tile__header">
<h2 class="item-tile__title">{{ .Key }}</h1>
</header>
</div>

View file

@ -0,0 +1,8 @@
<header class="site-header">
{{ block "header" . }}
<h1 class="site-header__title" itemprop="name"><a href="{{ .Site.Home.RelPermalink }}">{{ .Site.Title }}</a></h1>
<p class="site-header__tagline" itemprop="about">Views my own. Discussion ≠ endorsement. Do try this at home.</p>
<p class="site-header__icons">~ <a href="mailto:{{ $.Site.Author.email }}" rel="me">&#128231;</a> ~ <a href="{{ .Site.Params.codeURL }}">&#128187;</a> ~ <a href="/{{ .Site.Params.keyfile }}">&#128272;</a> ~ <a href="/index.xml"><img class="feed-icon" src="/images/feed-icon.png"></a> ~</p>
{{ partial "header/site-nav.html" . }}
{{ end }}
</header>

View file

@ -0,0 +1,7 @@
<nav class="site-header__nav">
<ul>
{{ range ( where .Site.Sections.ByTitle "Type" "in" site.Params.mainSections ) }}
<a href="{{ .RelPermalink }}"><li>{{ .Title | safeHTML }}</li></a>
{{ end }}
</ul>
</nav>

View file

@ -0,0 +1,29 @@
<a id="{{ .Slug }}" class="link--tile" href="{{ .RelPermalink }}" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
<article class="item-tile lazy {{- with .Params.site }} item-tile--{{ . }}{{ end -}}"
{{ if .Params.featured_image }}
{{ if .Resources.GetMatch .Params.featured_image }}
style="background-image: url({{ ( .Resources.GetMatch .Params.featured_image ).RelPermalink }})"
{{ else }}
style="background-image: url({{ .Params.featured_image }})"
{{ end }}
{{ end }}
>
<header class="item-tile__header">
{{ if ( or .Params.series .Params.published_in ) }}
<span class="item-tile__banner item-tile__banner--{{ if .Params.series }}series{{ else if .Params.published_in }}published-in{{ end}}">
{{- if .Params.series -}}
{{ .Params.series | safeHTML }}
{{- else if .Params.published_in -}}
{{ .Params.published_in | safeHTML }}
{{- end -}}
</span>
{{ end }}
<h1 class="item-tile__title{{ if gt ( len ( .Title | plainify ) ) 40 }} item-tile__title--long{{ end }}" itemprop="name">
<span role="text">{{ .Title | safeHTML }}</span>
</h1>
{{ with .Params.subtitle }}
<p class="item-tile__subtitle">{{ . | safeHTML }}</p>
{{ end }}
</header>
</article>
</a>

View file

@ -0,0 +1,8 @@
<section class="site-content__body">
{{ range ( ( where .Pages "Draft" false ).GroupByPublishDate "2006" ) }}
{{ partial "header-tile.html" . }}
{{ range .Pages }}
{{ partial "item-tile.html" . }}
{{ end }}
{{ end }}
</section>

View file

@ -0,0 +1,32 @@
<section class="site-content__body">
<table class="organisations-table">
<thead>
<tr>
<th>Logo</th>
<th>Title</th>
<th>Children</th>
<th>Items</th>
</tr>
</thead>
<tbody>
{{ range .Pages }}
<tr>
<td>
{{- if .Params.featured_image -}}
<img width="150" height="auto" loading="lazy" src="
{{- if .Resources.GetMatch .Params.featured_image -}}
{{- ( .Resources.GetMatch .Params.featured_image ).RelPermalink -}}
{{- else -}}
{{- .Params.featured_image -}}
{{- end -}}
">
{{- end -}}
</td>
<td><a href="{{ .RelPermalink }}">{{ .Title | safeHTML }}</a></td>
<td>{{- if gt (len .Sections) 0 -}}&#10004;{{- end -}}</td>
<td></td>
</tr>
{{ end }}
</tbody>
</table>
</section>

View file

@ -0,0 +1,82 @@
<footer class="site-content__footer">
<h1>Meta</h1>
{{- if .GetTerms "categories" -}}
<section id="post-categories" class="article-footer__categories" aria-labelledby="post-categories-title">
<h2 id="post-categories-title">Categories</h2>
<ul>
{{- range (.GetTerms "categories") -}}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle | safeHTML }}</a></li>
{{- end -}}
</ul>
</section>
{{- end -}}
{{- with .Params.internal_links -}}
<section class="article-footer__links">
<h2>Internal Links</h2>
<ul>
{{- range . -}}
{{ if eq ( printf "%T" . ) "map[string]interface {}" }}
<li><a href="{{ .link }}">{{ .title | safeHTML }}</a></li>
{{ else }}
<li><a href="{{ . }}">Link</a></li>
{{ end }}
{{- end -}}
</ul>
</section>
{{- end -}}
{{- with .Params.external_links -}}
<section class="article-footer__links">
<h2>External Links</h2>
<ul>
{{- range . -}}
{{ if eq ( printf "%T" . ) "map[string]interface {}" }}
<li><a href="{{ .link }}" rel="noopener noreferrer" target="_blank">{{ .title | safeHTML }}</a></li>
{{ else }}
<li><a href="{{ . }}" rel="noopener noreferrer" target="_blank">Link</a></li>
{{ end }}
{{- end -}}
</ul>
</section>
{{- end -}}
{{- if .GetTerms "organisations" -}}
<section id="post-organisations" class="article-footer__organisations" aria-labelledby="post-organisations-title">
<h2 id="post-organisations-title">Organisations</h2>
<ul>
{{ $all_organisations := partialCached "get_all_organisations.html" . }}
<!-- TODO: Replace with hierarchy partial -->
{{- range ( .GetTerms "organisations" ) -}}
{{ with ( where $all_organisations "Title" ( .Title | plainify ) ) }}
{{ range . }}
<li><a href="{{ .RelPermalink }}">{{ if ( .Params.markup_title ) }}{{ .Params.markup_title | safeHTML }}{{ else }}{{ .Title }}{{ end }}</a></li>
{{ end }}
{{ else }}
{{ warnf "Could not find organisation %q (%q)" .Title $.File.Path }}
<li>{{ if ( .Params.markup_title ) }}{{ .Params.markup_title | safeHTML }}{{ else }}{{ .Title }}{{ end }}</li>
{{ end }}
{{- end -}}
</ul>
</section>
{{- end -}}
{{- if .GetTerms "locations" -}}
<section id="post-locations" class="article-footer__locations" aria-labelledby="post-locations-title">
<h2 id="post-locations-title">Locations</h2>
<div id="mapdiv" style="width: 100%; height: 500px; margin: 0; display: block;"></div>
</section>
{{- end -}}
{{- if .GetTerms "tags" -}}
<section id="post-tags" class="article-footer__tags" aria-labelledby="post-tags-title">
<h2 id="post-tags-title">Tags</h2>
<ul>
{{- range ( .GetTerms "tags" ).ByTitle -}}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle | safeHTML }}</a></li>
{{- end -}}
</ul>
</section>
{{- end -}}
</footer>

View file

@ -0,0 +1,9 @@
<!-- Source: https://discourse.gohugo.io/t/reverse-array/28753/2 -->
{{- $sliceOriginal := . -}}
{{- $len := len $sliceOriginal -}}
{{- $sliceReversed := slice -}}
{{- range seq $len -}}
{{- $sliceReversed = $sliceReversed | append (index $sliceOriginal (sub $len .)) }}
{{- end -}}
{{- return $sliceReversed -}}

View file

@ -0,0 +1,5 @@
<ul class="minor-links__years">
{{ range ( ( where .Pages "Draft" false ).GroupByDate "2006" ) }}
<li><a href="#items-{{ .Key }}">{{ .Key }}</a></li>
{{ end }}
</ul>

View file

@ -0,0 +1,94 @@
{{ define "title" }}
{{ .Page.Title | plainify }} | {{ .Site.Title }}
{{ end }}
{{ define "main-class" }}--section{{ end }}
{{ define "footer-scripts" }}
<script>
// Source: https://css-tricks.com/the-complete-guide-to-lazy-loading-images/
document.addEventListener("DOMContentLoaded", function() {
var lazyloadImages;
if ("IntersectionObserver" in window) {
lazyloadImages = document.querySelectorAll(".lazy");
var imageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
console.log("Ding");
var image = entry.target;
image.classList.remove("lazy");
imageObserver.unobserve(image);
}
});
});
lazyloadImages.forEach(function(image) {
imageObserver.observe(image);
});
} else {
var lazyloadThrottleTimeout;
lazyloadImages = document.querySelectorAll(".lazy");
function lazyload () {
if(lazyloadThrottleTimeout) {
clearTimeout(lazyloadThrottleTimeout);
}
lazyloadThrottleTimeout = setTimeout(function() {
var scrollTop = window.pageYOffset;
lazyloadImages.forEach(function(img) {
if(img.offsetTop < (window.innerHeight + scrollTop)) {
img.src = img.dataset.src;
img.classList.remove('lazy');
}
});
if(lazyloadImages.length == 0) {
document.removeEventListener("scroll", lazyload);
window.removeEventListener("resize", lazyload);
window.removeEventListener("orientationChange", lazyload);
}
}, 20);
}
document.addEventListener("scroll", lazyload);
window.addEventListener("resize", lazyload);
window.addEventListener("orientationChange", lazyload);
}
});
</script>
{{ end }}
{{ define "main-header" }}
<header class="site-content__header">
<h1 class="page-title">{{ .Title | safeHTML }}.
{{ range .AlternativeOutputFormats -}}
<a href="{{ .RelPermalink }}">
<img class="feed-icon" src="/images/feed-icon.png">
</a>
{{ end }}
</h1>
{{ .Content }}
{{ if ne .Type "portfolio" }}
<nav class="page-header__minor-links">
{{ partial "years-list.html" . }}
</nav>
{{ end }}
</header>
{{ end }}
{{ define "main-body" }}
{{ if eq .Type "portfolio" }}
<article class="site-content__body site-content__body--list">
<ul class="site-content__sections-list">
{{ range .Sections.ByWeight }}
{{ if eq .Weight 10 }}<hr>{{ end }}
<li><a href="{{ .RelPermalink }}"><h2>{{ .Title }}</h2></a> <p>({{ len .Pages }})</p></li>
{{ end }}
</ul>
</article>
{{ else }}
{{ partial "items-grid.html" . }}
{{ end }}
{{ end }}

2
layouts/robots.txt Normal file
View file

@ -0,0 +1,2 @@
User-agent: ia_archiver
Disallow: /

36
layouts/series/list.html Normal file
View file

@ -0,0 +1,36 @@
{{ define "title" }}
{{ .Type | singularize }}: &lsquo;{{ .Page.Title | plainify }}&rsquo; | {{ .Site.Title }}
{{ end }}
{{ define "main-class" }}--list{{ end}}
{{ define "main-header" }}
<header class="site-content__header">
<h1 class="page-title">
{{- if eq .Title "Series" -}}
{{- .Title | safeHTML }}&rsquo;
{{- else -}}
{{- .Type | singularize }}: <q>{{ .Title | safeHTML }}</q>
{{- end -}}.
{{ range .AlternativeOutputFormats -}}
<a href="{{ .RelPermalink }}">
<img class="feed-icon" src="{{ $.Site.Params.feedIcon }}">
</a>
{{ end }}
</h1>
{{ .Content }}
</header>
{{ end }}
{{ define "main-body" }}
{{ if eq .Title "Series" }}
<ul>
{{ range .Site.Taxonomies.series }}
<li><a href="{{ .Page.RelPermalink }}">{{ .Page.Title | safeHTML }}</a></li>
{{ end }}
</ul>
{{ else }}
{{ partial "items-grid.html" . }}
{{ end }}
{{ end }}

View file

@ -0,0 +1,44 @@
{{ $img := $.Page.Resources.GetMatch (.Get "src") }}
{{ $file := $.Page.Resources.GetMatch (.Get "link") }}
<figure{{ with .Get "class" }} class="{{ . }}"{{ end }}>
{{- if .Get "link" -}}
{{- if $file }}
<a href="{{ $file.RelPermalink }}"{{ with .Get "rel" }} rel="{{ . }}"{{ end }}>
{{ else }}
<a href="{{ .Get "link" }}"{{ with .Get "target" }} target="{{ . }}"{{ end }}{{ with .Get "rel" }} rel="{{ . }}"{{ end }}>
{{ end }}
{{- end -}}
{{ if $img }}
<img class="figure__image"
{{ with $img.Resize (printf "%dx%d webp" $img.Width $img.Height) }}
src="{{ .RelPermalink }}"
{{ end }}
{{- if or ($img.Params.alt) (.Get "caption") }}
alt="{{ with $img.Params.alt }}{{ . }}{{ else }}{{ .Get "caption" | markdownify| plainify }}{{ end }}"
{{- end -}}
{{- with $img.Params.title }} title="{{ . }}"{{ end -}}
width="{{ $img.Width }}"
height="{{ $img.Height }}"
/>
{{ end }}
{{- if .Get "link" }}</a>{{ end -}}
{{- if or (.Get "caption") ($img.Params.attr) -}}
<figcaption class="figure__caption{{ if not (.Get "caption") }} figure__caption--no-height{{ end }}">
{{- if $img.Params.attrlink -}}
<a class="figcaption__attrlink" href="{{ $img.Params.attrlink }}"
{{- with $img.Params.attrtarget }} target="{{ . }}"{{ end -}}
{{- with $img.Params.attrrel }} rel="{{ . }}"{{ end -}}
>
{{- end -}}
{{- with $img.Params.attr -}}<p class="figcaption__attr">{{ . | safeHTML }}{{ with $img.Params.attrlicence }} <span class="figcaption__licence">{{ . | safeHTML }}</span>{{ end }}</p>{{- end -}}
{{- if $img.Params.attrlink -}}
</a>
{{- end -}}
{{- with $img.Params.title -}}<h4 class="figcaption__title">{{ . }}</h4>{{- end -}}
{{- if .Get "caption" -}}
<p class="figcaption__caption">{{ .Get "caption" | markdownify }}</p>
{{- end -}}
</figcaption>
{{- end -}}
</figure>

View file

@ -0,0 +1,4 @@
{{ $resource := .Page.Resources.GetMatch ($.Get 0) }}
{{ with $resource }}
{{ $resource.RelPermalink }}
{{ end }}