Add documentation/courses/tutorials layout

- Close #405
- See #681 (improve consistency after #571 Bootstrap 4 migration)
- Add `search_results` to language file
- example site: Add example `tutorial` folder
- example site: Set privacy page to hidden (draft)
This commit is contained in:
George Cushen committed 2018-09-09 23:28:36 +01:00
1 parent f45e2c0ca5
commit 674bb67364
21 files changed
+476 -83

No files matched your search

+4
View File
@@ -59,6 +59,10 @@
version = "2.9.0"
sri = "sha256-cJXigylnJlxvAdfFNHeS+IiMcKWS3Rf/cy3bl9bb0ng="
url = "https://cdnjs.cloudflare.com/ajax/libs/instantsearch.js/%s/instantsearch.min.js"
[js.anchor]
version = "4.1.1"
sri = "sha256-pB/deHc9CGfFpJRjC43imB29Rse8tak+5eXqntO94ck="
url = "https://cdnjs.cloudflare.com/ajax/libs/anchor-js/%s/anchor.min.js"
# CSS
+2 -2
View File
@@ -280,8 +280,8 @@ enableGitInfo = false
weight = 4
[[menu.main]]
name = "Teaching"
url = "#teaching"
name = "Tutorials"
url = "/tutorial/"
weight = 5
[[menu.main]]
+1 -1
View File
@@ -2,7 +2,7 @@
title = "Privacy Policy"
date = 2018-06-28T00:00:00
draft = false
draft = true
# [header]
# image = ""
+33
View File
@@ -0,0 +1,33 @@
+++
title = "Overview"
date = 2018-09-09T00:00:00
# lastmod = 2018-09-09T00:00:00
draft = false # Is this a draft? true/false
toc = true # Show table of contents? true/false
type = "docs" # Do not modify.
# Add menu entry to sidebar.
[menu.docs]
name = "Overview"
weight = 1
# Featured image.
# Uncomment below lines to use.
# [header]
# image = "headers/getting-started.png"
# caption = "Image credit: [**Academic**](https://github.com/gcushen/hugo-academic/)"
+++
This feature can be used for publishing content such as:
* **Project or software documentation**
* **Online courses**
* **Tutorials**
The parent folder may be renamed, for example, to `docs` for project documentation or `course` for creating an online course.
To disable this feature, either delete the parent folder, or set `draft = true` in the front matter of all its pages.
After renaming or deleting the parent folder, you may wish to update any `[[menu.main]]` menu links to it in the `config.toml`.
+32
View File
@@ -0,0 +1,32 @@
+++
title = "Example Page"
date = 2018-09-09T00:00:00
# lastmod = 2018-09-09T00:00:00
draft = false # Is this a draft? true/false
toc = true # Show table of contents? true/false
type = "docs" # Do not modify.
# Add menu entry to sidebar.
linktitle = "Example Page"
[menu.docs]
parent = "Example Topic"
weight = 1
# Featured image.
# Uncomment below lines to use.
# [header]
# image = "headers/getting-started.png"
# caption = "Image credit: [**Academic**](https://github.com/gcushen/hugo-academic/)"
+++
In this tutorial, I'll share my top 10 tips for getting started with Academic:
## Tip 1
...
## Tip 2
...
+3
View File
@@ -145,6 +145,9 @@
- id: search_placeholder
translation: Search...
- id: search_results
translation: Search Results
- id: search_no_results
translation: No results found
+2 -4
View File
@@ -9,9 +9,8 @@
{{ partial "header_image.html" . }}
<div class="article-container">
{{ with .Title }}<h1 class="my-4">{{ . }}</h1>{{ end }}
<div class="universal-wrapper">
{{ with .Title }}<h1 class="pt-3">{{ . }}</h1>{{ end }}
{{ with .Content }}
<div class="article-style" itemprop="articleBody">{{ . }}</div>
@@ -34,7 +33,6 @@
{{ end }}
{{ partial "pagination" . }}
</div>
{{ partial "footer_container.html" . }}
{{ partial "footer.html" . }}
+1
View File
@@ -0,0 +1 @@
{{ partial "docs_layout.html" . }}
+1
View File
@@ -0,0 +1 @@
{{ partial "docs_layout.html" . }}
+238 -8
View File
@@ -268,7 +268,7 @@ small,
overflow-x: hidden;
}
#search-query {
#search-box #search-query {
border: 1px solid #dedede;
border-radius: 1rem;
padding: 1rem 1rem 1rem 2rem; /* Wider left padding for search icon to fit in. */
@@ -299,6 +299,11 @@ small,
display: none;
}
.form-control:focus {
border-color: {{ .Get "primary" }};
box-shadow: 0 0 0 .2rem {{ .Get "primary_light" }};
}
/*************************************************
* Modals.
**************************************************/
@@ -1499,20 +1504,245 @@ div.alert a:hover {
}
/*************************************************
* Documentation layout
**************************************************/
.docs-article-container {
max-width: 760px;
}
/* Documentation: article footer. */
.docs .body-footer {
border-top: 1px solid #e8e8e8;
margin-top: 30px;
padding-top: 10px;
font-size: 14px;
color: #707070;
}
/* Docs content. */
.docs-content {
order: 1;
position: relative;
}
.docs-content>h2[id],
.docs-content>h3[id],
.docs-content>h4[id] {
pointer-events: none;
}
.docs-content>ol li,
.docs-content>ul li {
margin-bottom: .25rem;
}
/* Docs search. */
.docs-search {
position: relative;
padding: 1rem 15px;
margin-right: -15px;
margin-left: -15px;
border-bottom: 1px solid rgba(0, 0, 0, .05);
}
.docs-search .form-control:focus {
border-color: {{ .Get "primary" }};
box-shadow: 0 0 0 3px {{ .Get "primary_light" }};
}
/* Docs sidebar. */
.docs-sidebar {
order: 0;
border-bottom: 1px solid rgba(0, 0, 0, .1)
}
@media (min-width:768px) {
.docs-sidebar {
border-right: 1px solid rgba(0, 0, 0, .1)
}
@supports ((position:-webkit-sticky) or (position:sticky)) {
.docs-sidebar {
position: -webkit-sticky;
position: sticky;
top: 71px;
z-index: 1000;
height: calc(100vh - 71px)
}
}
}
@media (min-width:1200px) {
.docs-sidebar {
flex: 0 1 320px
}
}
/* Docs sidebar li>a. */
.docs-sidebar .nav>li>a {
display: block;
padding: .25rem 1.5rem;
font-size: 90%;
color: rgba(0, 0, 0, .65);
}
.docs-sidebar .nav>li>a:hover {
color: rgba(0, 0, 0, .85);
text-decoration: none;
background-color: transparent;
}
.docs-sidebar .docs-toc-item.active a,
.docs-sidebar .nav>.active:hover>a,
.docs-sidebar .nav>.active>a {
font-weight: bold;
color: {{ .Get "primary" }};
background-color: transparent;
}
/* Docs links. */
.docs-links {
padding-top: 1rem;
padding-bottom: 1rem;
margin-right: -15px;
margin-left: -15px;
}
@media (min-width:768px) {
@supports (position: sticky) {
.docs-links {
max-height: calc(100vh - 5rem - 71px);
overflow-y: auto;
}
}
}
@media (min-width:768px) {
.docs-links {
display: block!important;
}
}
/* Docs TOC. */
.docs-toc {
order: 2;
padding-top: 1.5rem;
padding-bottom: 1.5rem;
font-size: .875rem
}
@supports ((position:-webkit-sticky) or (position:sticky)) {
.docs-toc {
position: -webkit-sticky;
position: sticky;
top: 4rem;
height: calc(100vh - 4rem);
overflow-y: auto
}
}
/* Docs TOC item links. */
.docs-toc-link {
display: block;
padding: .25rem 1.5rem;
font-weight: bold;
color: rgba(0, 0, 0, .65);
}
.docs-toc-link:hover {
color: rgba(0, 0, 0, .85);
text-decoration: none;
}
.docs-toc-item.active {
margin-bottom: 1rem;
}
.docs-toc-item.active:not(:first-child) {
margin-top: 1rem;
}
.docs-toc-item.active>.docs-toc-link {
color: rgba(0, 0, 0, .85);
}
.docs-toc-item.active>.docs-toc-link:hover {
background-color: transparent;
}
.docs-toc-item.active>.docs-sidenav {
display: block;
}
/* Docs TOC nav. */
#TableOfContents {
padding-left: 0;
border-left: 1px solid #eee;
}
#TableOfContents ul {
padding-left: 1rem;
}
#TableOfContents ul ul {
display: none;
}
#TableOfContents li {
display: block;
}
#TableOfContents li a {
display: block;
padding: .125rem 1.5rem;
color: #99979c;
}
#TableOfContents li a:hover {
color: {{ .Get "primary" }};
text-decoration: none;
}
/* Docs achnorjs links. */
.anchorjs-link {
font-weight: 400;
color: {{ .Get "primary_dark" }};
transition: color .16s linear;
}
.anchorjs-link:hover {
color: {{ .Get "primary" }};
text-decoration: none;
}
/*************************************************
* Dark themed components
**************************************************/
body.dark {
body.dark,
.dark .docs-toc-link,
.dark .docs-sidebar .nav > li:not(.active) > a,
.dark .modal button.close,
.dark input,
.dark .form-control:focus {
color: rgb(248, 248, 242);
}
.dark input {
color: rgb(248, 248, 242);
}
.dark .modal button.close {
color: rgb(248, 248, 242);
.dark .form-control:focus {
background-color: rgb(68, 71, 90);
border-color: {{ .Get "primary" }};
box-shadow: 0 0 0 .2rem {{ .Get "primary_dark" }};
}
.dark h1,
+47
View File
@@ -0,0 +1,47 @@
{{ partial "header.html" . }}
{{ partial "navbar.html" . }}
{{ $current_page := . }}
<div class="container-fluid docs">
<div class="row flex-xl-nowrap">
<div class="col-12 col-md-3 col-xl-2 docs-sidebar">
{{ partial "docs_sidebar.html" . }}
</div>
{{ if .Params.toc }}
<div class="d-none d-xl-block col-xl-2 docs-toc">
{{ .TableOfContents }}
</div>
{{ end }}
<main class="col-12 col-md-9 col-xl-8 py-md-3 pl-md-5 docs-content" role="main">
<div id="search-hits">
<!-- Search results will appear here -->
</div>
<article class="article" itemscope itemtype="http://schema.org/Article">
{{ partial "header_image.html" . }}
<div class="docs-article-container">
<h1 itemprop="name">{{ .Title }}</h1>
<div class="article-style" itemprop="articleBody">
{{ .Content }}
</div>
{{ partial "tags.html" . }}
</div>
<div class="body-footer">
{{ i18n "last_updated" }} {{ $.Lastmod.Format $.Site.Params.date_format }}
</div>
</article>
{{ partial "footer_section.html" . }}
</main>
</div>
</div>
{{ partial "footer.html" . }}
+26
View File
@@ -0,0 +1,26 @@
{{ $current_page := . }}
{{ if eq $.Site.Params.search.engine 1 }}
<form class="docs-search d-flex align-items-center">
<input name="q" type="search" class="form-control" id="search-query" placeholder="{{ i18n "search_placeholder" }}" autocomplete="off">
</form>
{{ end }}
<nav class="docs-links" id="docs-nav">
{{ range .Site.Menus.docs.ByWeight }}
<div class="docs-toc-item{{ if $current_page.IsMenuCurrent "docs" . }} active{{ end }}">
<a class="docs-toc-link" {{ if .URL }}href="{{ .URL }}"{{else if .HasChildren }}href="{{ (index .Children 0).URL }}"{{end}}>{{ .Name }}</a>
{{- if .HasChildren }}
<ul class="nav docs-sidenav">
{{ range .Children }}
<li {{ if $current_page.IsMenuCurrent "docs" . }}class="active"{{ end }}>
<a href="{{ .URL }}">{{ .Name }}</a>
</li>
{{ end }}
</ul>
{{ end }}
</div>
{{ end }}
</nav>
+37
View File
@@ -69,6 +69,7 @@
const search_index_filename = {{ "/index.json" | relURL }};
const i18n = {
'placeholder': {{ i18n "search_placeholder" }},
'results': {{ i18n "search_results" }},
'no_results': {{ i18n "search_no_results" }}
};
const content_type = {
@@ -80,6 +81,14 @@
</script>
{{ end }}
{{/* Load hash anchors for documentation pages. */}}
{{ if eq .Type "docs" }}
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.anchor.url $js.anchor.version) $js.anchor.sri | safeHTML }}
<script>
anchors.add();
</script>
{{ end }}
{{/* Fuse search engine. */}}
{{ if eq .Site.Params.search.engine 1 }}
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.fuse.url $js.fuse.version) $js.fuse.sri | safeHTML }}
@@ -160,5 +169,33 @@
</script>
{{ end }}
{{ if eq $.Site.Params.search.engine 1 }}
{{/* Fuse search result template. */}}
<script id="search-hit-fuse-template" type="text/x-template">
<div class="search-hit" id="summary-{{"{{key}}"}}">
<div class="search-hit-content">
<div class="search-hit-name">
{{ printf "<a href=\"%s\">%s</a>" "{{relpermalink}}" "{{title}}" | safeHTML }}
<div class="article-metadata search-hit-type">{{"{{type}}"}}</div>
<p class="search-hit-description">{{"{{snippet}}"}}</p>
</div>
</div>
</div>
</script>
{{ else if eq $.Site.Params.search.engine 2 }}
{{/* Algolia search result template. */}}
<script id="search-hit-algolia-template" type="text/html">
<div class="search-hit">
<div class="search-hit-content">
<div class="search-hit-name">
{{ printf "<a href=\"%s\">{{{_highlightResult.title.value}}}</a>" "{{relpermalink}}" | safeHTML }}
</div>
<div class="article-metadata search-hit-type">{{"{{type}}"}}</div>
<p class="search-hit-description">{{ safeHTML "{{{_highlightResult.summary.value}}}" }}</p>
</div>
</div>
</script>
{{ end }}
</body>
</html>
+3 -28
View File
@@ -1,31 +1,6 @@
<footer class="site-footer">
<div class="container">
{{ with .Site.GetPage "privacy.md" }}
<p class="powered-by">
{{ printf "<a href=\"%s\">%s</a>" .Permalink .Title | safeHTML }}
</p>
{{ end }}
<p class="powered-by">
{{ with .Site.Copyright }}{{ . | markdownify}} &middot; {{ end }}
Powered by the
<a href="https://sourcethemes.com/academic/" target="_blank" rel="noopener">Academic theme</a> for
<a href="https://gohugo.io" target="_blank" rel="noopener">Hugo</a>.
<span class="float-right" aria-hidden="true">
<a href="#" id="back_to_top">
<span class="button_icon">
<i class="fas fa-chevron-up fa-2x"></i>
</span>
</a>
</span>
</p>
</div>
</footer>
<div class="container">
{{ partial "footer_section.html" . }}
</div>
<!-- Citation modal -->
<div id="modal" class="modal fade" role="dialog">
+23
View File
@@ -0,0 +1,23 @@
<footer class="site-footer">
{{ with .Site.GetPage "privacy.md" }}
<p class="powered-by">
{{ printf "<a href=\"%s\">%s</a>" .Permalink .Title | safeHTML }}
</p>
{{ end }}
<p class="powered-by">
{{ with .Site.Copyright }}{{ . | markdownify}} &middot; {{ end }}
Powered by the
<a href="https://sourcethemes.com/academic/" target="_blank" rel="noopener">Academic theme</a> for
<a href="https://gohugo.io" target="_blank" rel="noopener">Hugo</a>.
<span class="float-right" aria-hidden="true">
<a href="#" id="back_to_top">
<span class="button_icon">
<i class="fas fa-chevron-up fa-2x"></i>
</span>
</a>
</span>
</p>
</footer>
-28
View File
@@ -23,31 +23,3 @@
</div>
</div>
{{ if eq $.Site.Params.search.engine 1 }}
{{/* Fuse search result template. */}}
<script id="search-hit-fuse-template" type="text/x-template">
<div class="search-hit" id="summary-{{"{{key}}"}}">
<div class="search-hit-content">
<div class="search-hit-name">
{{ printf "<a href=\"%s\">%s</a>" "{{relpermalink}}" "{{title}}" | safeHTML }}
<div class="article-metadata search-hit-type">{{"{{type}}"}}</div>
<p class="search-hit-description">{{"{{snippet}}"}}</p>
</div>
</div>
</div>
</script>
{{ else }}
{{/* Algolia search result template. */}}
<script id="search-hit-algolia-template" type="text/html">
<div class="search-hit">
<div class="search-hit-content">
<div class="search-hit-name">
{{ printf "<a href=\"%s\">{{{_highlightResult.title.value}}}</a>" "{{relpermalink}}" | safeHTML }}
</div>
<div class="article-metadata search-hit-type">{{"{{type}}"}}</div>
<p class="search-hit-description">{{ safeHTML "{{{_highlightResult.summary.value}}}" }}</p>
</div>
</div>
</script>
{{ end }}
+1 -1
View File
@@ -5,7 +5,7 @@
<div class="universal-wrapper">
<h1 class="my-4">{{ .Title | default (i18n "posts") }}</h1>
<h1 class="pt-3">{{ .Title | default (i18n "posts") }}</h1>
{{ with .Content }}
<div class="article-style" itemprop="articleBody">{{ . }}</div>
+6 -6
View File
@@ -3,10 +3,10 @@
{{ partial "header_image.html" . }}
<div class="container">
<div class="row">
<div class="universal-wrapper">
<div class="row pt-3">
<div class="col-lg-12">
<h1 class="my-4">{{ .Title | default (i18n "publications") }}</h1>
<h1>{{ .Title | default (i18n "publications") }}</h1>
{{ with .Content }}
<div class="article-style" itemprop="articleBody">{{ . }}</div>
@@ -18,11 +18,11 @@
{{ $.Scratch.SetInMap "years" $year $year }}
{{ end }}
<div class="row">
<div class="form-row mb-3">
<div class="col-auto">
{{ i18n "filter_by_type" }}:
</div>
<div class="form-group col-auto">
<div class="col-auto">
<select class="pub-filters pubtype-select form-control form-control-sm" data-filter-group="pubtype">
<option value="*">{{ i18n "filter_all" }}</option>
{{ range $index, $taxonomy := .Site.Taxonomies.publication_types }}
@@ -32,7 +32,7 @@
{{ end }}
</select>
</div>
<div class="form-group col-auto">
<div class="col-auto">
<select class="pub-filters form-control form-control-sm" data-filter-group="year">
<option value="*">{{ i18n "filter_all" }}</option>
{{ $years_sorted := $.Scratch.GetSortedMapValues "years" }}
+3 -3
View File
@@ -3,10 +3,10 @@
{{ partial "header_image.html" . }}
<div class="container">
<div class="row">
<div class="universal-wrapper">
<div class="row pt-3">
<div class="col-lg-12">
<h1 class="my-4">{{ .Title | default (i18n "talks") }}</h1>
<h1>{{ .Title | default (i18n "talks") }}</h1>
{{ with .Content }}
<div class="article-style" itemprop="articleBody">{{ . }}</div>
+3
View File
@@ -330,6 +330,9 @@
// Initialise Google Maps if necessary.
initMap();
// Fix Hugo's inbuilt Table of Contents.
$('#TableOfContents > ul > li > ul').unwrap().unwrap();
});
})(jQuery);
+10 -2
View File
@@ -49,8 +49,12 @@ function initSearch(force, fuse) {
let query = $("#search-query").val();
// If query deleted, clear results.
if ( query.length < 1)
if ( query.length < 1) {
$('#search-hits').empty();
$('.docs-content .article').show();
} else {
$('.docs-content .article').hide();
}
// Check for timer event (enter key not pressed) and query less than minimum length required.
if (!force && query.length < fuseOptions.minMatchCharLength)
@@ -67,6 +71,10 @@ function initSearch(force, fuse) {
function searchAcademic(query, fuse) {
let results = fuse.search(query);
// console.log({"results": results});
if ($('.docs-content').length > 0)
$('#search-hits').append('<h1>' + i18n.results + '</h1>');
if (results.length > 0) {
parseResults(query, results);
} else {
@@ -102,7 +110,7 @@ function parseResults(query, results) {
var template = $('#search-hit-fuse-template').html();
// Localize content types.
let content_key = value.item.type;
let content_key = value.item.section;
if (content_key in content_type) {
content_key = content_type[content_key];
}