HUGO Relearn Theme Customization

relearn-banner

The number of Themes has been increased rapidly over time and since the very beginning of HUGO - a static web site generator.

The HUGO Relearn theme has one outstanding feature as it fully supports file mode, which means that there is no web server required to get access to the web site content.

Once a site has been generated, it is only required to double click on the main <my-user-directory>\public\index.html file. All dependent files are served from the file system via the file:// protocol which is supported by all modern browsers. Dependencies are relative to the main root and so there is also no problem with CORS policy whatsoever.

When rendering a site:

  • the BaseUrl which usually is the web server address name (like e.g. https://johann-oberdorfer.eu)
  • is replaced by ./
  • and subsequently all articles are represented by a trailing index.html

With this nomenclature in place, there is no name resolving needed (which usually is done by a web server). In the underlying theme template files, relative notation for urls is used.

Beside other great features, for me this was one of the main reasons for choosing this theme (to build a local documentation system).

Use cases

The theme claims to be a “documentation” theme. In this respect it fits perfectly to build a personal or a local documentation system (intranet) for example.

Benefits:

  • Personal or company information is pure text (markdown) and thus future prove, stored locally without the need of a database and ready for serverless operation.

  • Markdown editing (no proprietary data and software required).

  • File structure in the content directory is used to build up the site navigation menu, a really nice feature most useful for documentations etc,…

  • Build in search functionality.

  • Text and layout is separated (except for the shortcodes used, they need to be embedded in markdown).

  • Easily maintainable and expandable (if required).

  • Attachments of existing PDF’s can be added to an article quite easy.

  • Print capability to print one article, chapters or even the whole site articles at once.

Overall, a modern way to edit, manage and present information.


Theme Customizations

To make the theme even more useful I added some more functionality to it.

Functions added so far:

Categories and Tags Cloud

shortcode/tag_cloud.html...

image

{{/*
	--- shortcode/widgets/tag_cloud.html
	Credits:
		This code was inspired by the academic theme.
		Thanks to: George Cushen
	Purpose:
		This function does not take any arguments into account.
		Read all "tags" and "categories" from the site's taxonomies
		and create a test cloud which can be used to navigate the site.
	
	(c) 2020, Johann Oberdorfer - Engineering Support | CAD | Software
		www.johann-oberdorfer.eu
	This source file is distributed under the MIT license.
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the MIT License for more details.
*/}}

{{ $read_tags := true }}

{{ $fontSmall := .Page.Params.design.font_size_min | default 0.9 }}
{{ $fontBig := .Page.Params.design.font_size_max | default 1.5 }}
{{ $fontDelta := sub $fontBig $fontSmall }}

{{/* read "categories"... */}}
{{ $data := .Site.Taxonomies.categories.ByCount }}

{{/* read "tags"
     and add this information to the data array... */}}

{{ if $read_tags }}

	{{ $tags := .Site.Taxonomies.tags.ByCount }}

	{{ if ne (len $tags) 0 }}
		{{ $data = $data | append $tags }}
	{{ end }}

{{ end }}

{{/* output goes here... */}}

{{ if ne (len $data) 0 }}
	<style>
		.tag-cloud-tags {
			display: block;
			margin: 0;
			list-style-type: none;
		}
		.tag-cloud-tags a {
			display: inline-block;
			padding: 0.3rem 0.3rem 0rem 0.3rem;
			line-height: 1em;
			word-break: break-word;
			white-space: normal;
			text-decoration: none;
			border-bottom: 1px solid LightGrey;
		}
		.tag-cloud-tags a:nth-child(5n+1) { transform: rotate(-2deg); }
		.tag-cloud-tags a:nth-child(3n+3) { transform: rotate(1deg); }
		.tag-cloud-tags a:nth-child(3n+4) { transform: rotate(-3deg); }
		.tag-cloud-tags a:nth-child(5n+5) { transform: rotate(3deg); }

		/* underline animation from left */

		.hover-animate-from-left {
		  display: inline-block;
		  vertical-align: middle;
		  -webkit-transform: perspective(1px) translateZ(0);
		  transform: perspective(1px) translateZ(0);
		  box-shadow: 0 0 1px rgba(0, 0, 0, 0);
		  position: relative;
		  overflow: hidden;
		}
		
		.hover-animate-from-left:before {
		  content: "";
		  position: absolute;
		  z-index: -1;
		  left: 0;
		  right: 100%;
		  bottom: -1px;
		  background: #2098D1;
		  height: 3px;
		  -webkit-transition-property: right;
		  transition-property: right;
		  -webkit-transition-duration: 0.8s;
		  transition-duration: 0.8s;
		  -webkit-transition-timing-function: ease-out;
		  transition-timing-function: ease-out;
		}

		.hover-animate-from-left:hover:before,
		.hover-animate-from-left:focus:before,
		.hover-animate-from-left:active:before {
		  right: 0;
		}
	</style>

	{{/* Warning:
			Hugo's `Reverse` function appears to operate in-place,
			hence the order of performing $max/$min matters.
	*/}}

	{{ $max := add (len (index $data 0).Pages) 1 }}
	{{ $min := len (index ($data).Reverse 0).Pages }}
	{{ $delta := sub $max $min }}
	{{ $fontStep := div $fontDelta $delta }}

	<div class="row" style="padding:5px"> <!-- background-color:HoneyDew; -->
	<div class="heading text-center" style="margin-top:5px">

	<div> <!-- class="col-12 text-center" -->

		<!-- <span>Categories & Tags</span> -->

		<div class="tag-cloud-tags">
		{{ range $item := (sort $data ".Page.Title" "asc") }}

			{{ $tagCount := len $item.Pages }}
			{{ $weight := div (sub (math.Log $tagCount) (math.Log $min)) (sub (math.Log $max) (math.Log $min)) }}
			{{ $fontSize := add $fontSmall (mul (sub $fontBig $fontSmall) $weight) }}

			<!-- class="button button-border button-mini button-border-thin button-blue button-circle" -->

			<!--
			.Page.RelPermalink changed to
			partial "relLangPrettyUglyURL.hugo" (dict "to" .Page)
			-->
			{{ if ne (upper .Page.Title) "ARCHIVED" }}
				<a 	href='{{ partial "relLangPrettyUglyURL.hugo" (dict "to" .Page) }}'
					style="font-size:{{ $fontSize }}rem" class="hover-animate-from-left">
					{{- .Page.Title | upper -}}
					<span style="color: LightGrey; font-size:{{ $fontSmall }}rem"> ({{ $tagCount }}) </span>
				</a>
			{{ end }}

		{{ end }}
		</div>

	</div>
	</div>
	</div>
{{ end }}

Sitemap

shortcodes/custom/sitemap.html...

image

{{/*
	-- shortcode/sitemap.html shortcode

	general note:
		make sure a template name is only defined once throughout
		the entire repository, otherwise side effects might occure which
		are hard do debug !
	
	relearn theme: .RelPermalink needs to be replaced by
	               partial "relLangPrettyUglyURL.hugo" (dict "to" .)
*/}}

<style>
	/* quick fix,
		so that the structured list looks o.k.
	*/
	li.no-bullets, ul.no-bullets {
		list-style-type: none;
	}
</style>

{{- $currentNode := . }}

{{- if eq .Site.Params.ordersectionsby "title"}}
	{{- range .Site.Home.Sections.ByTitle}}
		{{- template "sitemap-tree-nav" dict "sect" . "currentnode" $currentNode }}
	{{- end}}
{{- else}}
	{{- range .Site.Home.Sections.ByWeight}}
		{{- template "sitemap-tree-nav" dict "sect" . "currentnode" $currentNode }}
	{{- end}}
{{- end}}

<!-- templates -->
{{- define "sitemap-tree-nav" }}

	{{- $currentNode := .currentnode }}

	{{- with .sect}}
		{{- if and .IsSection (or (not .Params.hidden) $.showhidden)}}
			{{- $numberOfPages := (add (len .Pages) (len .Sections)) }}
			{{- safeHTML .Params.head}}
			<li class="no-bullets">
				<div>
					<a href='{{ partial "relLangPrettyUglyURL.hugo" (dict "to" .) }}'>
						{{safeHTML .Params.Pre}}{{.Title}}{{safeHTML .Params.Post}}
					</a>
				</div>
				{{- if ne $numberOfPages 0 }}
					<ul class="no-bullets">
					{{- .Scratch.Set "pages" .Pages }}
					{{- if .Sections}}
						{{- .Scratch.Set "pages" (.Pages | union .Sections) }}
					{{- end}}

					{{- $pages := (.Scratch.Get "pages") }}

					{{- if eq .Site.Params.ordersectionsby "title"}}
						{{- range $pages.ByTitle }}
							{{- if and .Params.hidden (not $.showhidden) }}
							{{- else}}
								{{- template "sitemap-tree-nav" dict "sect" . "currentnode" $currentNode }}
							{{- end}}
						{{- end}}
					{{- else}}
						{{- range $pages.ByWeight }}
							{{- if and .Params.hidden (not $.showhidden) }}
							{{- else}}
								{{- template "sitemap-tree-nav" dict "sect" . "currentnode" $currentNode }}
							{{- end}}
						{{- end}}
					{{- end}}
					</ul>
				{{- end}}
			</li>

		{{- else}}
			{{- if not .Params.Hidden }}
				<li class="no-bullets">
					<div>
						<a href='{{ partial "relLangPrettyUglyURL.hugo" (dict "to" .) }}'>
							{{safeHTML .Params.Pre}}{{.LinkTitle}}{{safeHTML .Params.Post}}
						</a>
					</div>
				</li>
			{{- end}}
		{{- end}}
	{{- end}}
{{- end}}

To render the sitemap, create a new index.md file in the root of the document contents section using the following code:

+++
title = " "
weight = 6
hidden = false
disableToc = true
headingPost = "<h2><i class='far fa-fw fa-map'></i> Sitemap</h2>"
menuPre = "<br/><i class='far fa-fw fa-map'></i> Sitemap"
+++

<style>
	#R-body {background-color: var(--CODE-INLINE-BG-color);}
</style>

{{/* < custom/sitemap > */}}

Columns Shortcode

shortcodes/columns.html...

image

<style>
.flex{display:flex}
.flex-auto{flex:auto}
.flex-even{flex:1 1}
.flex-wrap{flex-wrap:wrap}
.book-columns>div{margin:1rem 0;min-width:10rem;padding:0 1rem}
.markdown-inner>:first-child{margin-top:0}
.markdown-inner>:last-child{margin-bottom:0}
</style>

<div class="book-columns flex flex-wrap">
{{ range split .Inner "<--->" }}
  <div class="flex-even markdown-inner">
    {{ . | $.Page.RenderString }}
  </div>
{{ end }}
</div>

support for custom.css

partials/custom-header.html...

<!--
<style>
  #body img.bg-white {background-color: white;}
</style>
-->

{{- $assetBusting := not .Site.Params.disableAssetsBusting }}
<link href='{{"css/custom.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}' rel="stylesheet">

footer bar with previous and next article

partials/custom-comments.html...

<style>
.bottom-container {
    height:45px;
    clear:both;
    position:absolute;
    bottom:0;
    width:100%;
	color:var(--MENU-SECTIONS-LINK-color);
	background-color:var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color);
	/* test: background-color:green; */
}
</style>

{{- if or .PrevInSection .NextInSection }}

	<div class="bottom-container">

	{{- if .NextInSection }}

		{{ $next := .NextInSection.Permalink }}

		<div class="btn cstyle transparent w3-display-left w3-margin-left">
			<a href='{{ partial "relLangPrettyUglyURL.hugo" (dict "to" .NextInSection) }}'>
				<i class="fa fa-angle-left"></i>
				{{- with .NextInSection }}
					{{ .Title | truncate 30 }}
				{{- end }}
			</a>
		</div>
	{{- end }}

	{{- if .PrevInSection }}
	
		{{ $prev := .PrevInSection.Permalink }}
	
		<div class="btn cstyle transparent w3-display-right w3-margin-right">
			<a href='{{ partial "relLangPrettyUglyURL.hugo"  (dict "to" .PrevInSection) }}'> 
				{{- with .PrevInSection }}
					{{ .Title | truncate 30 }}
				{{- end }}
				<i class="fa fa-angle-right"></i>
			</a>
		</div>
	{{- end }}

	</div>

{{- end }}

Page Taxonomy in the header for each article

content-header.html...

image

<style>
.entry-meta {
	font-style:italic;
	font-size:small;
	display: flex;
	justify-content: center;
	margin-top:0px;
	padding:0px;
	font-weight:300;
}
</style>

{{- if not (eq .Params.archetype "home") }}
{{- if eq .Params.type "docs" }}

<div class="entry-meta box cstyle transparent w3-animate-fading-mod1">

	<small>
		<span>
			<i class="far fa-calendar" style="color:var(--CODE-BLOCK-BORDER-color);"></i>
			Posted:
			{{ .Date.Format .Site.Params.date_format }}
		</span>
		
		{{ if ne .Date .Lastmod }}
			<span>
				,
				<i class="far fa-calendar" style="color:var(--CODE-BLOCK-BORDER-color);"></i>
				Last modified:
				{{ .Params.lastmod.Format .Site.Params.date_format }}
			</span>
		{{ end }}

		{{ if isset .Params "author" }}
			<span>
				,
				<i class="far fa-user-circle" style="color:var(--CODE-BLOCK-BORDER-color);"></i>
				{{ i18n "author" }}{{ .Params.author }}
			</span>
		{{ else }}
			<span>
				,
				<i class="far fa-user-circle" style="color:var(--CODE-BLOCK-BORDER-color);"></i>
				Admin
			</span>
		{{ end }}
	
		<!-- hans: copied over from tags.html -->
		{{- $page := . }}
		{{- if .Params.categories }}
		<br/>
		<span class="categories">
			{{- $categories := slice | append .Params.categories }}
			{{- range sort $categories }}
				{{- if gt (len .) 0 }}
					{{- $category := . }}
					{{- with $page.Site.GetPage (printf "%s%s" ("/categories/" | relURL ) ( $category | anchorize ) ) }}
						{{- $to := . }}
						<span>
							<i class="fa fa-tags" style="color:var(--CODE-BLOCK-BORDER-color);"></i>
							<a href='{{ partial "relLangPrettyUglyURL.hugo" (dict "to" $to) }}'>{{ $category | upper }}</a>
						</span>
					{{- end }}
				{{- end }}
			{{- end }}
		</span>
		{{- end }}

		<!-- hans: copied over from tags.html -->
		{{- if .Params.tags }}
		<span class="tags">
			{{- $tags := slice | append .Params.tags }}
			{{- range sort $tags }}
				{{- if gt (len .) 0 }}
					{{- $tag := . }}
					{{- with $page.Site.GetPage (printf "%s%s" ("/tags/" | relURL ) ( $tag | anchorize ) ) }}
						{{- $to := . }}
						<span>
							<i class="fa fa-hashtag" style="color:var(--CODE-BLOCK-BORDER-color);"></i>
							<a href='{{ partial "relLangPrettyUglyURL.hugo" (dict "to" $to) }}'>{{ $tag | upper }}</a>
						</span>
					{{- end }}
				{{- end }}
			{{- end }}
		</span>
		{{- end }}

		<span>
			,
			<i class="far fa-clock" style="color:var(--CODE-BLOCK-BORDER-color);"> </i>
			Time to read:
			{{ .ReadingTime }} min.
		</span>

	</small>
</div>

{{- end }}
{{- end }}

Animated scroll-up buttom

goto_top_rocket.html...

image

<!-- scroll to top -->
<button onclick='topFunction()' id='myBtn' title='Go to top'></button>

<style>
	#myBtn {
		display:none;position:fixed;bottom:45px;right:30px;z-index:99;
		border:2px;outline:none;background-color:HoneyDew;cursor:pointer;padding:15px;
		border-radius:15px;width:40px;height:40px;	background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAABJ0AAASdAHeZh94AAAAB3RJTUUH5wcPDRE1IGQ5vAAABEdJREFUWMPNWc9LMl0YPX5Egos2ThQpUhAk7kwNxJixaNWmbcuCWrd00SIUwj8gBFdta+ULoiC6caJFYEGLQKPciEKDtioT0Tjv4s35mnz7cvxR3wMXnHvvc+fMfc557g8NJDEskySJACDLsmFog5IcSnG73QRAAHS73RzWuEMZJBAIEAAfHh748PBAAAwEAvxfALy9vSUARqNRdiwajRIAb29v+eMAAdDlcvGjLS4u8g+DfhBgKBQiAFar1S6A1WqVABgKhQYCaehXxaVSifPz8xBFEYeHh6jVapp2QRCwv7+Ps7Mz3N/fw2azGb5VxUdHR6pqvypHR0f89hADYDAY5FcWDAYH4mJfToVCgQCYy+W+BJjL5QiAhUKB38bB5eVlNptN5HK5nvp7PB4YjUacn5/r5uE/eh1arRYqlQqWlpY09eFwGH6/H36/H+FwWNO2tLSESqWCVqs1epFks1kC4NPTE0ny7u5OFYMkSXxbjwmAd3d3JMmnpycCYDab5cg5mE6nO6Qn//CDFouFiqKodYqi0GKxdPVLp9OjB7i1tUWz2UyS1JGoaTabub29PXqAdrudGxsbJElRFClJ0qcKliSJoiiSJDc2Nmi323UD1C2SQqEAURR1c10URRQKBYxcxQAwNzcHAFhdXYUsy3h8fOzq8/j4CFmWsbq6qvEZuYoBMJlMashvs9k0PKxWq7TZbBqRJJPJvlaUsX4/6n3I7XY7JicnIUkS3rb8atvffEYSYpLqmcNg+HdBWFhYAEkcHByoX935vbCwoPbr+LyJavghNplMagKOx+PUa/F4XPU3mUwcqoqtVivb7bYapmKxqDtUHR+SaLfbsFqtHEqIY7EYK5UKyuUyAGB6eho3Nze6Ad7c3GBmZgYAUC6XUalUEIvFOHCIAXBvb08N1c7ODgVB0B1iQRC4u7urPu/t7fWk6v9szGQyBMDr62t14JOTE0366NUA8OTkRH2+vr4mAGYyGfYN0OVy0efzaV4kyzIBsF6v9wyuXq8TAGVZ1tT7fL7OiVC/SBqNBhRFgcfj0dQ7HA5MTEwgEon0zL9IJIKJiQk4HI6ujayiKGg0Gvo5eHV1RQDM5/NdM7K+vk6n09nzDDqdTq6vr3fV5/N5AuDV1RV1hziVSn3KtUQiQQAsFotfgisWiwTARCLxKTdTqRR1L3Wd7fnl5SUURdG0zc7OAgCOj4/h9/vRbDb/OobRaEQ2m1V9ksmkpn1qakrzLl0hfp/5R13eVqbh3iy8HYY4OTnZNTMdW1tbw/PzMy4uLvq/L+z3QN1rPgTAX79+8dvvZgwGA3VORF+zONbvzMdiMYyPj8Nms6FWq+Hl5QWCIAAAarUaTCYTBEFAqVRCu93+uSvg98fJlZUVrqys8MPxdKDxxzAEq9frAIDX19euukFtYIBer1fNi+/5PDs7C6/XOzDAgdLMR9vc3CQAnJ6eDu1viN9K6g7T3mN8QAAAAABJRU5ErkJggg),no-repeat;
	}
	#myBtn:hover {
		background-color: var(--INTERNAL-MENU-SECTIONS-LINK-HOVER-color);
	}
</style>

<script type="text/javascript">

	let mybutton = document.getElementById('myBtn');
	let elmnt = document.getElementById("R-body-inner");
	elmnt.style.scrollBehavior = 'smooth';

	function scrollFunction() {
		// probably deactivated/overwritten by perfect-scrollbar.js:
		// document.body.scrollTop, document.documentElement.scrollTop
		// let y = elmnt.scrollTop;
		// console.log(y);

		if (elmnt.scrollTop > 20 ) {
			mybutton.style.display = 'block';
		} else {
			mybutton.style.display = 'none';
		}
	}
	function topFunction() {
		elmnt.scrollTop = 0; // for Safari
		// document.documentElement.scrollTop = 0; // for Chrome, Firefox, IE and Opera
	}
	
	// window.onscroll = function() {scrollFunction()};
	// the following works:
	window.addEventListener('scroll', function() {
		scrollFunction();
	}, true);

</script>
<!-- scroll to top -->

The shortcode goes here:

body.html...

{{- partial "goto_top_rocket.html" . }}

{{- $page := .page }}
{{- $content := .content }}
{{- $outputFormat := partial "output-format.hugo" .page }}
{{- partial "single-article.hugo" (dict "page" $page "content" $content "outputFormat" $outputFormat) }}

Support for Custom Style

Custom style support with some more font size adjustments (custom.css):

custom.css...

/* Hans:
	partly copied from the theme ksu-cs-textbooks-hugo-theme-relearn-main
	to override css properties declared in theme.css
*/
.brown {
	color:Brown;
	font-weight:bold;
}
.lbrown {
	color:Bisque;
	font-weight:bold;
	text-shadow:0px 0px 4px #000000;
}
.lred {
	color:Crimson;
	font-weight:bold;
}
.yellow {
	color:Yellow;
	font-weight:bold;
	text-shadow:0px 0px 4px #000000;
}

table {
	/* width:auto;
	  height:auto; */
	line-height:12px;
}

.w3-display-container{position:relative;}
.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0}
.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
.w3-display-position{position:absolute}
.w3-center .w3-bar{display:inline-block;width:auto}
.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}
.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}
.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}

.w3-animate-fading-mod {
	animation:fading 4s linear
}
@keyframes fading {
	0%{opacity:0}
	25%{opacity:0.25}
	50%{opacity:0.5}
	75%{opacity:0.75}
	100%{opacity:1}
}

.w3-animate-fading-mod1 {
	animation:fading1 1s linear
}
@keyframes fading1 {
	0%{opacity:0}
	50%{opacity:0.5}
	100%{opacity:1}
}

/*
	-------------------
	theme.css overrides
	-------------------
*/

/* EMBED page should be 100% width */
.embed {
    width: 100%;
}

/* Fix Font Weights for Lato */
body {
    font-size: 1.1rem; /* --- 1.015625rem; --- */
    font-weight: 400;
    line-height: 1.2; /* --- 1.574; --- */
}

h1 {
    font-size: 1.85rem; /* --- 3.25rem; --- */
}

h2 {
    font-size: 1.8rem; /* --- 2.2rem; --- */
    font-weight: 500;
}

h3, .article-subheading {
    font-size: 1.5rem; /* --- 1.8rem; --- */
    font-weight: 500;
}

#R-body h2 {
    font-weight: 700;
    font-size: 1.5rem;
}
#R-body h3 {
    font-weight: 600;
    font-size: 1.3rem;
}
#R-body h4 {
    font-weight: 600;
    font-size: 1.3rem;
}

#R-sidebar {
    font-size: .953125rem; /* --- .953125rem; --- */
    line-height: 1.2; /* 1.574; */
}
#R-sidebar ul li {
    line-height: 1.0;
}
#R-sidebar ul.collapsible-menu li.active > a {
    border-inline-end-color: var(--INTERNAL-MENU-BORDER-color);
}
#R-sidebar ul.collapsible-menu > li > label {
    margin-left: 2px;
}

/* Sidebar Titles */
#R-sidebar ul.topics > li > a b {
    font-weight: 400;
    opacity: 0.5;
    line-height: 1;
}

#R-body .flex-block-wrapper {
	/*
    margin-left: auto;
    margin-right: auto;
	*/

    max-width: /* calc( 81.25rem - 18.75rem - 2 * 3.25rem ); */
				  calc( 88.25rem - 18.75rem - 2 * 1.25rem );
}


/* we limit width if we have large screens */
@media screen and ( min-width: 88.25rem ){ /* #R-sidebar/width + ./max-width */
    #R-body .flex-block-wrapper {
        width: calc( 88.25rem - var(--INTERNAL-MENU-WIDTH-L) - 2 * 3.25rem );
    }
    body:not(.print) #R-body .narrow .flex-block-wrapper {
        width: calc( 88.25rem - var(--INTERNAL-MENU-WIDTH-L) - 2 * 9.75rem );
    }
}

Full Page Reader View - experimental

Read more...

image

In this view, the side menu will not appear so that the focus is purely on the article itself. In order to achive this, each single page will be rendered in another format, watch out for the “embed” keyword in the customized configuration section. The source code is provided at at the end of this article and can be downloaded as a zip file.
If there are already some customized files available, make sure not to overwrite them by mistake (as files in the zip file have the same names acc. to the overload mechanism declared by the hugo static file generator).

Global Configuration settings

In the overall configuration file (config.toml), the following declarations are needed to support local mode and also to tell hugo to generate required “embed” type output files:

Read more...


# true -> all relative URLs would instead be canonicalized using baseURL
canonifyURLs = true

# required value to serve this page from a webserver AND the file system;
# if you don't want to serve your page from the file system, you can also set this value to false
# true -> rewrite all relative URLs to be relative to the current content
relativeURLs = true

# if you set uglyURLs to false, this theme will append 'index.html' to any branch bundle link
# so your page can be also served from the file system; if you don't want that,
# set disableExplicitIndexURLs=true in the [params] section
# true -> basic/index.html -> basic.html
uglyURLs = false

[outputs]
  home = ["HTML", "RSS", "PRINT", "SEARCH", "SEARCHPAGE"]
  section = ["HTML", "RSS", "PRINT"]
  page = ["HTML", "RSS", "PRINT", "EMBED"]

[outputFormats]
  [outputFormats.EMBED]
    name= "EMBED"
    baseName = "index.embed"
    isHTML = true
    mediaType = 'text/html'
    permalinkable = true

[languages]	
	[[languages.en.menu.shortcuts]]
	 	name = "<br/><i class='far fa-fw fa-map'></i> Sitemap"
	 	pageRef = "sitemap/"
	 	weight = 10

[params]
  date_format = "2006-01-02"

  showVisitedLinks = false
  collapsibleMenu = true
  disableBreadcrumb = false
  disableInlineCopyToClipBoard = true
  disableNextPrev = false
  disableLandingPageButton = true
  breadcrumbSeparator = ">"
  titleSeparator = "::"
  disableAssetsBusting = true

  themeVariant = [
	{ identifier = "zen-light",     name = "Light" },
	{ identifier = "zen-dark",      name = "Dark" },
	{ identifier = "relearn-bright", name = "Bright" },
	{ identifier = "neon"           },
	{ identifier = "blue"           },
	{ identifier = "green"          },
  ]
	

Software Versions needed

Software versions needed (minimum required) are as following:

  • In the time of writing this article, the actual theme version is:

    relearn-theme 6.0.0

  • hugo version which is also the minimum version required to run the relearn-theme 6.0.0:

    v0.121.0-e321c3502aa8e80a7a7c951359339a985f082757+extended windows/amd64

File name:Size / byte:
relearn-theme-6.0.0-customization.zip26785

Credits: