Installing/Updating Hugo
- Make sure installed version of Go is >= 1.18:
- Check Go version:
go version- Install/update Go: https://go.dev/doc/install
- Check Hugo:
hugo version- Update Hugo:
- Download latest version: https://github.com/gohugoio/hugo/releases
- Install .deb file:
sudo dpkg --install ./hugo_0.110.0_linux-amd64.deb
- Update Hugo:
- Check Go version:
Creating a New Site
- Install Hugo and prerequisites: https://gohugo.io/installation/
- Create two repositories on Github:
- “Blog Repository” - Repository for storing website code: “Blog”
- Make Public, no README, simply click “Create repository”
- “Production Repository” - Repository for deploying website that’s hosted through Github Pages: “MParnin.github.io”
- Make Public, no README, simply click “Create repository”
- “Blog Repository” - Repository for storing website code: “Blog”
- Choose theme for site: https://themes.gohugo.io/ (PaperMod was used for this site)
- Clone “Blog” to local machine:
git clone git@github.com:MParnin/Blog.git - Change to “Blog” directory:
cd Blog - Create a new Hugo site:
hugo new site MParnin.github.io - Change to new directory:
cd MParnin.github.io - Clone theme to newly created boiler plate code for website:
git clone https://github.com/adityatelange/hugo-PaperMod themes/PaperMod --depth=1 - Setup the config file:
- Open the config file in a text editor:
code config.toml - Add the theme to the end of the config file:
theme = "PaperMod" - Change the title:
MP - Change the base URL to match Github production repo:
baseURL = https://MParnin.github.io/ - Save changes and exit code editor
- Open the config file in a text editor:
- Preview site locally:
- Make sure in directory with config.toml
- Run Hugo server:
hugo server - Visit the address of the local site:
http://localhost:1313/(can ctrl-click link in terminal) - Stop server when finished viewing:
Ctrl+c
- Test creating a new post:
- Create file:
hugo new posts/hellomom.md - Edit file:
code /content/posts/hellomom.md- Set title of post:
title: "Hello Mom!"
- Set title of post:
- Delete draft mode line
- Add content below second “—”:
- Add plaintext:
Hey Mom checkout my new site! - Add code:
1print("Hello Mom!")- Save and exit
- Add plaintext:
- Create file:
- Add “Blog” as submodule to store static assets for website:
- Need one commit for “MParnin.github.io” repo and set the main branch to “main”:
- Make a temp directory to clone repo to:
mkdir ~/tmp - Change to temp directory:
cd ~/tmp - Clone Production repository:
git clone git@github.com:MParnin/MParnin.github.io.git - Change to cloned directory:
cd MParnin.github.io - Checkout a new branch:
git checkout -b main - Create a readme file:
touch README.md - Check status to see untracked files:
git status - Add new all new files to be tracked:
git add . - Commit tracked files:
git commit -m "Adding README" - Push to Main branch on Github:
git push origin main - Confirm on Github the file was added and branch is set to “main”
- Delete temp files:
rm -rf tmp
- Make a temp directory to clone repo to:
- Add a git submodule which will reference “Production” repository:
- Change to root site directory:
cd ~/Documents/Blog/MParnin.github.io - Create submodule within root to deploy site from (site deployed from “public” submodule directory; static files that Hugo generates get added to this directory):
git submodule add -b main git@github.com:MParnin/MParnin.github.io.git public
- Change to root site directory:
- Need one commit for “MParnin.github.io” repo and set the main branch to “main”:
- Review site before deploying:
hugo server - Generate static files into “public”:
- Change to root site directory:
cd ~/Documents/Blog/MParnin.github.io - Create files for selected theme:
hugo -t PaperMod - Confirm files were generated:
cd public - Confirm origin is directed to Production repository:
git remote -v - Check status of files:
git status - Add all static files:
git add . - Commit static files:
git commit -m "Initial commit" - Push the origin files to the main branch:
git push origin main- Confirm all static files are in Production repo on Github. These files are now automatically deployed to
https://MParnin.github.io. This site is published because it is hosted through Github Pages which can be seen in “Settings > Pages” for the Production repositories settings.
- Confirm all static files are in Production repo on Github. These files are now automatically deployed to
- Change to root site directory:
Creating a New Post
- Create a new post:
- Navigate to root of site:
cd /Documents/Blog/MParnin.github.io - Create new post file:
hugo new posts/<name.md> - Edit post:
code /content/posts/<post-title>.md- Set title of post:
title: "Hello Mom!" - Delete draft mode
- Save and exit
- Set title of post:
- Navigate to root of site:
- Generate static files into “public” and push to github to update site:
- Change to root site directory:
cd ~/Documents/Blog/MParnin.github.io - Create files for selected theme:
hugo -t PaperMod - Confirm files were generated:
cd public - Confirm origin is directed to Production repository:
git remote -v - Check status of files:
git status - Add all static files:
git add . - Commit static files:
git commit -m "Initial commit" - Push the origin files to the main branch:
git push origin main
- Change to root site directory:
Modifications
- Moved table of contents to left side of page:
- Replace the contents of
themes/PaperMod/layouts/partials/toc.htmlwith the following (comment out what is currently in the file):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154{{- $headers := findRE "<h[1-6].*?>(.|\n])+?</h[1-6]>" .Content -}} {{- $has_headers := ge (len $headers) 1 -}} {{- if $has_headers -}} <aside id="toc-container" class="toc-container wide"> <div class="toc"> <details {{if (.Param "TocOpen") }} open{{ end }}> <summary accesskey="c" title="(Alt + C)"> <span class="details">{{- i18n "toc" | default "Table of Contents" }}</span> </summary> <div class="inner"> {{- $largest := 6 -}} {{- range $headers -}} {{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}} {{- $headerLevel := len (seq $headerLevel) -}} {{- if lt $headerLevel $largest -}} {{- $largest = $headerLevel -}} {{- end -}} {{- end -}} {{- $firstHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers 0) 1) 0)) -}} {{- $.Scratch.Set "bareul" slice -}} <ul> {{- range seq (sub $firstHeaderLevel $largest) -}} <ul> {{- $.Scratch.Add "bareul" (sub (add $largest .) 1) -}} {{- end -}} {{- range $i, $header := $headers -}} {{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}} {{- $headerLevel := len (seq $headerLevel) -}} {{/* get id="xyz" */}} {{- $id := index (findRE "(id=\"(.*?)\")" $header 9) 0 }} {{- /* strip id="" to leave xyz, no way to get regex capturing groups in hugo */ -}} {{- $cleanedID := replace (replace $id "id=\"" "") "\"" "" }} {{- $header := replaceRE "<h[1-6].*?>((.|\n])+?)</h[1-6]>" "$1" $header -}} {{- if ne $i 0 -}} {{- $prevHeaderLevel := index (findRE "[1-6]" (index $headers (sub $i 1)) 1) 0 -}} {{- $prevHeaderLevel := len (seq $prevHeaderLevel) -}} {{- if gt $headerLevel $prevHeaderLevel -}} {{- range seq $prevHeaderLevel (sub $headerLevel 1) -}} <ul> {{/* the first should not be recorded */}} {{- if ne $prevHeaderLevel . -}} {{- $.Scratch.Add "bareul" . -}} {{- end -}} {{- end -}} {{- else -}} </li> {{- if lt $headerLevel $prevHeaderLevel -}} {{- range seq (sub $prevHeaderLevel 1) -1 $headerLevel -}} {{- if in ($.Scratch.Get "bareul") . -}} </ul> {{/* manually do pop item */}} {{- $tmp := $.Scratch.Get "bareul" -}} {{- $.Scratch.Delete "bareul" -}} {{- $.Scratch.Set "bareul" slice}} {{- range seq (sub (len $tmp) 1) -}} {{- $.Scratch.Add "bareul" (index $tmp (sub . 1)) -}} {{- end -}} {{- else -}} </ul> </li> {{- end -}} {{- end -}} {{- end -}} {{- end }} <li> <a href="#{{- $cleanedID -}}" aria-label="{{- $header | plainify -}}">{{- $header | safeHTML -}}</a> {{- else }} <li> <a href="#{{- $cleanedID -}}" aria-label="{{- $header | plainify -}}">{{- $header | safeHTML -}}</a> {{- end -}} {{- end -}} <!-- {{- $firstHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers 0) 1) 0)) -}} --> {{- $firstHeaderLevel := $largest }} {{- $lastHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers (sub (len $headers) 1)) 1) 0)) }} </li> {{- range seq (sub $lastHeaderLevel $firstHeaderLevel) -}} {{- if in ($.Scratch.Get "bareul") (add . $firstHeaderLevel) }} </ul> {{- else }} </ul> </li> {{- end -}} {{- end }} </ul> </div> </details> </div> </aside> <script> let activeElement; let elements; window.addEventListener('DOMContentLoaded', function (event) { checkTocPosition(); elements = document.querySelectorAll('h1[id],h2[id],h3[id],h4[id],h5[id],h6[id]'); // Make the first header active activeElement = elements[0]; const id = encodeURI(activeElement.getAttribute('id')).toLowerCase(); document.querySelector(`.inner ul li a[href="#${id}"]`).classList.add('active'); }, false); window.addEventListener('resize', function(event) { checkTocPosition(); }, false); window.addEventListener('scroll', () => { // Check if there is an object in the top half of the screen or keep the last item active activeElement = Array.from(elements).find((element) => { if ((getOffsetTop(element) - window.pageYOffset) > 0 && (getOffsetTop(element) - window.pageYOffset) < window.innerHeight/2) { return element; } }) || activeElement elements.forEach(element => { const id = encodeURI(element.getAttribute('id')).toLowerCase(); if (element === activeElement){ document.querySelector(`.inner ul li a[href="#${id}"]`).classList.add('active'); } else { document.querySelector(`.inner ul li a[href="#${id}"]`).classList.remove('active'); } }) }, false); const main = parseInt(getComputedStyle(document.body).getPropertyValue('--article-width'), 10); const toc = parseInt(getComputedStyle(document.body).getPropertyValue('--toc-width'), 10); const gap = parseInt(getComputedStyle(document.body).getPropertyValue('--gap'), 10); function checkTocPosition() { const width = document.body.scrollWidth; if (width - main - (toc * 2) - (gap * 4) > 0) { document.getElementById("toc-container").classList.add("wide"); } else { document.getElementById("toc-container").classList.remove("wide"); } } function getOffsetTop(element) { if (!element.getClientRects().length) { return 0; } let rect = element.getBoundingClientRect(); let win = element.ownerDocument.defaultView; return rect.top + win.pageYOffset; } </script> {{- end }} - Replace the contents of