10 Commits

Author SHA1 Message Date
Dave Gallant
e78c1db248 Remove theme toggle 2024-01-07 15:07:33 -05:00
Dave Gallant
fdc27aad3a Cleanup 2024-01-07 14:50:58 -05:00
Dave Gallant
bb5e1f688b Expand about section 2024-01-07 12:07:45 -05:00
Dave Gallant
e2883bc1e8 Remove image optimization to webp and fix gitea images 2024-01-07 11:04:42 -05:00
Dave Gallant
413b06bb8a Fix utterances auto theme 2024-01-07 10:26:45 -05:00
Dave Gallant
398cde5481 Fix credits 2024-01-07 10:22:29 -05:00
Dave Gallant
5e3b2d2dce Only save theme when toggle is done 2024-01-07 10:20:05 -05:00
Dave Gallant
51bd556992 Rename theme path 2024-01-07 10:19:25 -05:00
Dave Gallant
b9926ba634 Update menu 2024-01-07 09:55:06 -05:00
Dave Gallant
c7a2b2f4d2 Get rid of side panel to minimize noise in layout 2024-01-07 09:45:36 -05:00
165 changed files with 97 additions and 3672 deletions

View File

@@ -9,7 +9,6 @@ noJSConfigInAssets: true
params:
author: Dave Gallant
subtitle: blog
favicon: https://davegallant.ca/favicon.ico
logo:
text: davegallant.ca
@@ -48,11 +47,11 @@ params:
menu:
main:
- name: Posts
url: /
weight: 1
- name: About
url: /about
weight: 1
- name: Git
url: https://git.davegallant.ca/explore/repos
weight: 2
- name: RSS
url: /index.xml
@@ -68,15 +67,7 @@ markup:
module:
imports:
- path: github.com/davegallant/hugo-theme-gruvbox
- path: github.com/schnerring/hugo-mod-json-resume
mounts:
- source: data
target: data
- source: layouts
target: layouts
- source: assets/css/json-resume.css
target: assets/css/critical/44-json-resume.css
- path: hugo-theme-gruvbox
mounts:
- source: node_modules/simple-icons/icons
target: assets/simple-icons

View File

@@ -2,4 +2,4 @@
title: Welcome
---
This is a space where I share notes about problems and solutions I've been exploring. Please do not hesitate to reach out by email, social media, or by commenting on the posts below. Continuous improvement is what motivates me to keep learning.
This is a space where I share notes about problems and solutions I've been exploring. Check out the links in the menu bar for more information on how to connect with me.

View File

@@ -3,17 +3,27 @@ title: "About"
draft: false
---
Connect with me using any the following methods:
👋 I'm a software tinkerer with a passion for infra, security and self-hosting.
- Email: <mailto:me@davegallant.ca>
- LinkedIn: <https://www.linkedin.com/in/dave-gallant>
- Mastodon: <https://mastodon.social/@davegallant>
- GitHub: <https://github.com/davegallant>
- RSS Feed: <https://davegallant.ca/index.xml>
- Git: <https://git.davegallant.ca/explore/repos>
My primary motivation for hosting this website is to document my learnings and share them with others. I hope you find something useful here. Continuous improvement is what motivates me to keep learning.
I choose to self-host this site and other tools instead of relying exclusively on larger platforms because I believe in the open web. Interopability is often not a primary concern for popular platforms today and I find that concerning. I first got access to the internet in 1996 and have seen it evolve into what it is today. I want to do my part to keep it open and free.
If you would like to reach out, find out how to contact me [here](/contact/).
## Contact
Connect with me by using any of the following methods:
- [me@davegallant.ca](mailto:me@davegallant.ca)
- <https://www.linkedin.com/in/dave-gallant>
- <https://mastodon.social/@davegallant>
- <https://github.com/davegallant>
- <https://davegallant.ca/index.xml>
- <https://git.davegallant.ca/explore/repos>
## Credits
- This website is generated using [hugo](https://gohugo.io/)
- The site is generated with [hugo](https://gohugo.io/)
- The theme is a modified version of [hugo-theme-gruvbox](https://github.com/schnerring/hugo-theme-gruvbox)
- The comments system is powered by [utterances](https://github.com/utterance/utterances)
- The comments system uses [utterances](https://github.com/utterance/utterances)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -116,11 +116,24 @@ Something to consider is whether or not you want to use ssh with git. One method
After adding the above configuration, running `docker compose up -d` should be enough to get an instance up and running. It will be accessible at [https://gitea.my-tailnet-name.ts.net](https://gitea.my-tailnet-name.ts.net) from within the tailnet.
## Connecting a Runner
## Theming
I discovered some themes for gitea [here](https://git.sainnhe.dev/sainnhe/gitea-themes) and decided to try out gruvbox.
I added the theme by cloning [theme-gruvbox-auto.css](https://git.sainnhe.dev/sainnhe/gitea-themes/raw/branch/master/dist/theme-gruvbox-auto.css) into `./data/gitea/public/assets/css`. I then added the following to `environment` in `docker-compose.yml`:
```yaml
- GITEA__ui__DEFAULT_THEME=gruvbox-auto
- GITEA__ui__THEMES=gruvbox-auto
```
After restarting the gitea instance, the default theme was applied.
## Connecting runners
I installed the runner by [following the docs](https://docs.gitea.com/usage/actions/quickstart#set-up-runner). I opted for installing it on a separate host (another lxc container) as recommended in the docs. I used the systemd unit file to ensure that the runner comes back online after system reboots. I installed tailscale on this gitea runner as well, so that it can have the same "networking privileges" as the main instance.
After registering this runner and starting the daemon, it appeared in `/admin/actions/runners`:
After registering this runner and starting the daemon, the runner appeared in `/admin/actions/runners`. I added two other runners to help with parallelization.
![image](gitea-runners.png)
@@ -146,7 +159,7 @@ jobs:
matrix:
host:
- changedetection
- homelab
- homer
- invidious
- jackett
- ladder
@@ -154,6 +167,7 @@ jobs:
- plex
- qbittorrent
- tailscale-exit-node
- tailscale-subnet-router
- uptime-kuma
steps:
- name: Check out repository code
@@ -187,7 +201,7 @@ jobs:
And voilà:
{{< video poster="gitea-workflow" >}}
![image](gitea-workflow.png)
You may be wondering how the gitea runner is allowed to connect to the other hosts using ansible? Well, the nodes are in the same tailnet and have [tailscale ssh](https://tailscale.com/tailscale-ssh) enabled.

View File

@@ -1,29 +0,0 @@
{
"basics": {
"name": "Dave Gallant",
"image": "",
"email": "me@davegallant.ca",
"summary": "👋 I'm a software tinkerer with a passion for infra, security and self-hosting.",
"location": {
"region": "From 🇨🇦"
},
"profiles": [
{
"network": "LinkTree",
"url": "https://linktr.ee/davegallant"
},
{
"network": "GitHub",
"url": "https://github.com/davegallant"
},
{
"network": "Mastodon",
"url": "https://mastodon.social/@davegallant"
},
{
"network": "LinkedIn",
"url": "https://www.linkedin.com/in/dave-gallant"
}
]
}
}

View File

@@ -1,23 +1,29 @@
{{- $scriptSrc := "https://utteranc.es/client.js" -}}
{{- $issueTerm := .Page.Site.Params.comments.utterances.issueTerm -}}
{{- $label := .Page.Site.Params.comments.utterances.label -}}
{{- $username := .Page.Site.Params.comments.utterances.github.username -}}
{{- $repository := .Page.Site.Params.comments.utterances.github.repository -}}
{{- $scriptSrc := "https://utteranc.es/client.js" -}} {{- $issueTerm :=
.Page.Site.Params.comments.utterances.issueTerm -}} {{- $label :=
.Page.Site.Params.comments.utterances.label -}} {{- $username :=
.Page.Site.Params.comments.utterances.github.username -}} {{- $repository :=
.Page.Site.Params.comments.utterances.github.repository -}}
<script>
// load utteranc comment
var getTheme = window.localStorage && window.localStorage.getItem("theme");
getTheme = getTheme == null ? 'dark' : getTheme;
getTheme =
getTheme == null
? window.matchMedia &&
window.matchMedia("(prefers-color-scheme: light)").matches
? "light"
: "dark"
: getTheme;
getTheme = getTheme == null ? "dark" : getTheme;
let theme = getTheme === 'dark' ? 'gruvbox-dark' : 'github-light';
let s = document.createElement('script');
s.src = 'https://utteranc.es/client.js';
s.setAttribute('repo', '{{ print $username "/" $repository }}');
s.setAttribute('issue-term', '{{ $issueTerm }}');
s.setAttribute('theme', theme);
s.setAttribute('crossorigin', 'anonymous');
s.setAttribute('async', '');
document.querySelector('div.comments').innerHTML = '';
document.querySelector('div.comments').appendChild(s);
let theme = getTheme === "dark" ? "gruvbox-dark" : "github-light";
let s = document.createElement("script");
s.src = "https://utteranc.es/client.js";
s.setAttribute("repo", '{{ print $username "/" $repository }}');
s.setAttribute("issue-term", "{{ $issueTerm }}");
s.setAttribute("theme", theme);
s.setAttribute("crossorigin", "anonymous");
s.setAttribute("async", "");
document.querySelector("div.comments").innerHTML = "";
document.querySelector("div.comments").appendChild(s);
</script>

View File

@@ -1,5 +0,0 @@
module github.com/davegallant/hugo-theme-gruvbox
go 1.21
require github.com/schnerring/hugo-mod-json-resume v0.0.0-20231022202951-552402b37357 // indirect

View File

@@ -1,2 +0,0 @@
github.com/schnerring/hugo-mod-json-resume v0.0.0-20231022202951-552402b37357 h1:FR5kIQJNpHrB+P6yb8PrDVO8FpbUxF5fdTXLQp7UUpI=
github.com/schnerring/hugo-mod-json-resume v0.0.0-20231022202951-552402b37357/go.mod h1:an+FdylzRESQ2N+NuFK+iLerxnDRWbOqkxCDUXflGF4=

View File

@@ -1 +0,0 @@
{{ partial "image.html" (dict "src" .Destination "alt" .PlainText "caption" .Title "page" .Page "lazy" true) }}

View File

@@ -1,8 +0,0 @@
{{ define "main" }}
<article class="post">
<h1>{{ .Title | markdownify }}</h1>
<div class="post-content">
{{ .Content }}
</div>
</article>
{{ end }}

View File

@@ -1,30 +0,0 @@
<div class="sidebar">
{{ if .Params.toc }}
{{ with .TableOfContents }}
<aside class="toc">
<nav>
<p class="sidebar__heading">Table Of Contents</p>
{{ . }}
</nav>
</aside>
<hr />
{{ end }}
{{ end }}
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ if $cv.basics }}
<aside class="bio">
{{ partial "json-resume/basics.html" . }}
{{ if $.Site.Params.tagCloud.enable }}
<hr />
{{ end }}
</aside>
{{ end }}
{{ if $.Site.Params.tagCloud.enable }}
<aside>
{{ partial "tag-cloud.html" . }}
</aside>
{{ end }}
</div>

View File

@@ -1,20 +0,0 @@
{{ $url := .Permalink }}
{{ $title := .Title }}
{{ with $.Site.Params.socialShare }}
<div class="social-share">
<strong class="social-share__heading">Share this post: </strong>
{{ range . }}
{{ $href := .formatString }}
{{ $href := replace $href "{url}" (urlquery $url) }}
{{ $href := replace $href "{title}" (urlquery $title) }}
<a
class="social-share__item"
href="{{ $href | safeURL }}"
target="_blank"
rel="noreferrer"
>
{{ partial (printf "icons/%s" .iconSuite) .iconName }}
</a>
{{ end }}
</div>
{{ end }}

View File

@@ -1,32 +0,0 @@
<!--
Original work by Artem Sidorenko: https://www.sidorenko.io/post/2017/07/nice-tagcloud-with-hugo/
Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/)
-->
{{ with $.Site.Taxonomies.tags }}
{{ $fontUnit := "rem" }}
{{ $minFontSize := $.Site.Params.tagCloud.minFontSizeRem | default 0.8 }}
{{ $maxFontSize := $.Site.Params.tagCloud.maxFontSizeRem | default 2.0 }}
{{ $fontSizeSpread := sub $maxFontSize $minFontSize }}
{{ $min := len (index .ByCount.Reverse 0).Pages }}
{{ $max := add (len (index .ByCount 0).Pages) 1 }}
<div class="tag-cloud">
{{ range $tagName, $weightedPages := . }}
{{ $count := len $weightedPages.Pages }}
{{ $weight := div (sub (math.Log $count) (math.Log $min)) (sub (math.Log $max) (math.Log $min)) }}
{{ $fontSize := (add $minFontSize (mul $fontSizeSpread $weight) ) }}
<a
href="{{ "/tags/" | relLangURL }}{{ $tagName | urlize }}"
style="font-size:{{ $fontSize }}{{ $fontUnit }}"
{{ if eq $.Page.Params.title $tagName -}}
class="tag-cloud__tag tag-cloud__tag--active"
{{ else -}}
class="tag-cloud__tag"
{{ end -}}
>{{ $tagName }}</a
>
{{ end }}
</div>
{{ end }}

View File

@@ -1,7 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space

View File

@@ -1,40 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"],
"rebaseWhen": "behind-base-branch",
"npm": {
"fileMatch": ["(^|/)package\\.hugo\\.json$"],
"rangeStrategy": "bump",
"updateLockFiles": false,
"ignoreTests": true,
"ignorePaths": [
"package.json",
"**/node_modules/**",
"**/bower_components/**",
"**/vendor/**",
"**/examples/**",
"**/__tests__/**",
"**/test/**",
"**/tests/**",
"**/__fixtures__/**"
]
},
"gomod": {
"fileMatch": ["(^|/)go\\.mod$"],
"rangeStrategy": "bump",
"ignoreTests": true
},
"packageRules": [
{
"extends": "packages:linters",
"groupName": "linters"
},
{
"matchUpdateTypes": ["minor", "patch"],
"matchCurrentVersion": "!/^0/",
"automerge": true,
"automergeType": "branch"
}
]
}

View File

@@ -1,39 +0,0 @@
on:
push:
branches:
- main
jobs:
update_hugo_dependencies:
name: Update Hugo Dependencies
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Install Node
uses: actions/setup-node@v4
with:
node-version: "18"
- name: Install Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: "0.111.3"
extended: true
- name: Write composite package.json
run: hugo mod npm pack
- name: Install npm Packages
run: npm install
- name: Display Changes
run: git status
- name: Commit Changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: Update Hugo Dependencies

View File

@@ -1,139 +0,0 @@
# Created by https://www.toptal.com/developers/gitignore/api/hugo,node
# Edit at https://www.toptal.com/developers/gitignore?templates=hugo,node
### Hugo ###
# Generated files by hugo
/public/
/resources/_gen/
# Executable may be added to repository
hugo.exe
hugo.darwin
hugo.linux
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
.env.production
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
### Node Patch ###
# Serverless Webpack directories
.webpack/
# End of https://www.toptal.com/developers/gitignore/api/hugo,node

View File

@@ -1,4 +0,0 @@
#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged

View File

@@ -1,4 +0,0 @@
node_modules
public
resources

View File

@@ -1,11 +0,0 @@
{
"plugins": ["prettier-plugin-go-template"],
"overrides": [
{
"files": ["*.html"],
"options": {
"parser": "go-template"
}
}
]
}

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 Michael Schnerring
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,118 +0,0 @@
# hugo-mod-json-resume
A [Hugo module](https://gohugo.io/hugo-modules/) containing templates to
integrate multilingual [JSON Resume](https://jsonresume.org/) data into your
Hugo website.
## Getting Started
Initialize your Hugo site as a Hugo module:
```shell
hugo mod init example.com
```
Add the following to the `config.toml` file of your site to import the module:
```toml
[module]
[[module.imports]]
path = "github.com/schnerring/hugo-mod-json-resume"
[[module.mounts]]
source = "node_modules/simple-icons/icons"
target = "assets/simple-icons"
```
Install the module:
```shell
hugo mod get
```
Initialize the NPM `package.json` and install the dependencies:
```shell
hugo mod npm pack
npm install
```
The module offers a simple CSS stylesheet [assets/css/json-resume.css](./assets/css/json-resume.css)
that you can use.
Use the `json-resume` shortcode in markdown files:
```markdown
---
title: "CV"
draft: false
---
## Experience
{{< json-resume "work" >}}
## Education
{{< json-resume "education" >}}
```
Or use the partials in your layout files:
```html
<div class="sidebar">
<aside class="bio">{{ partial "json-resume/basics.html" . }}</aside>
</div>
```
## Data Structure
The module reads JSON Resume data from Hugo's `data/` directory:
```text
data/
├─ json_resume/
├─ de.json
├─ en.json
```
Each file must adhere to the [JSON Resume schema](https://github.com/jsonresume/resume-schema/blob/master/schema.json)
specification. At least one file with the name `<default content language code>.json`
must exist (defaults to `en`). See also [Hugo Multilingual Mode](https://gohugo.io/content-management/multilingual/).
## Styling
You can style the existing templates by using the pre-defined classes. There are
generic classes prefixed with `jr__` like `jr__item` or `jr__date-range` that
apply to any template.
Classes specific to resume sections are prefixed with `jr-<section>__<section-field>`,
like `jr-work__description` or `jr-basics__name`.
### Example
![Example resume section header screenshot](./screenshots/example-resume-section-headers.png)
The above requires the following CSS:
```css
.jr__item-meta {
align-items: center;
flex-flow: row wrap;
}
.jr__date,
.jr__date-range,
.jr-work__location {
flex-grow: 1;
text-align: right;
}
.jr-education__institution {
flex-basis: 100%;
}
```
## Attributions
To display social icons, [Simple Icons](https://simpleicons.org/) (CC0) are
used.

View File

@@ -1,75 +0,0 @@
.jr__item-meta {
flex-direction: column;
}
.jr__item-meta,
.jr-basics__image,
.jr-basics__item,
.jr-basics__profile-icon,
.jr-basics__profile-item {
align-items: center;
display: flex;
}
.jr-awards__title,
.jr-certificates__name,
.jr-education__area,
.jr-projects__roles,
.jr-publications__name,
.jr-volunteer__position,
.jr-work__position,
.jr-basics__name {
font-size: 1.125rem;
font-weight: bold;
}
.jr-basics__item {
flex-direction: column;
text-align: center;
}
.jr-basics__item hr {
margin: 1.5rem auto;
}
.jr-basics__image {
border-radius: 50%;
height: 250px;
justify-content: center;
overflow: hidden;
width: 250px;
}
.jr-basics__name,
.jr-basics__label,
.jr-basics__summary {
margin-top: 0.75rem;
}
.jr-basics__profile svg {
height: 24px;
width: 24px;
}
.jr-basics__profile,
.jr-basics__profile-item {
display: flex;
}
.jr-basics__profile-item {
display: flex;
padding: 0.2rem;
}
.jr-basics__profile--col {
flex-direction: column;
}
.jr-basics__profile--row {
flex-wrap: wrap;
justify-content: space-evenly;
}
.jr-basics__profile-icon {
padding: 0 0.75rem;
}

View File

@@ -1,161 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json",
"basics": {
"name": "Richard Hendriks",
"label": "Programmer",
"image": "",
"email": "richard.hendriks@mail.com",
"phone": "(912) 555-4321",
"url": "http://richardhendricks.example.com",
"summary": "Richard hails from Tulsa. He has earned degrees from the University of Oklahoma and Stanford. (Go Sooners and Cardinal!) Before starting Pied Piper, he worked for Hooli as a part time software developer. While his work focuses on applied information theory, mostly optimizing lossless compression schema of both the length-limited and adaptive variants, his non-work interests range widely, everything from quantum computing to chaos theory. He could tell you about it, but THAT would NOT be a “length-limited” conversation!",
"location": {
"address": "2712 Broadway St",
"postalCode": "CA 94115",
"city": "San Francisco",
"countryCode": "US",
"region": "California"
},
"profiles": [
{
"network": "Twitter",
"username": "neutralthoughts",
"url": ""
},
{
"network": "SoundCloud",
"username": "dandymusicnl",
"url": "https://soundcloud.example.com/dandymusicnl"
}
]
},
"work": [
{
"name": "Pied Piper",
"location": "Palo Alto, CA",
"description": "Awesome compression company",
"position": "CEO/President",
"url": "http://piedpiper.example.com",
"startDate": "2013-12-01",
"endDate": "2014-12-01",
"summary": "Pied Piper is a multi-platform technology based on a proprietary universal compression algorithm that has consistently fielded high Weisman Scores™ that are not merely competitive, but approach the theoretical limit of lossless compression.",
"highlights": [
"Build an algorithm for artist to detect if their music was violating copy right infringement laws",
"Successfully won Techcrunch Disrupt",
"Optimized an algorithm that holds the current world record for Weisman Scores"
]
}
],
"volunteer": [
{
"organization": "CoderDojo",
"position": "Teacher",
"url": "http://coderdojo.example.com/",
"startDate": "2012-01-01",
"endDate": "2013-01-01",
"summary": "Global movement of free coding clubs for young people.",
"highlights": [
"Awarded 'Teacher of the Month'"
]
}
],
"education": [
{
"institution": "University of Oklahoma",
"url": "https://www.ou.edu/",
"area": "Information Technology",
"studyType": "Bachelor",
"startDate": "2011-06-01",
"endDate": "2014-01-01",
"score": "4.0",
"courses": [
"DB1101 - Basic SQL",
"CS2011 - Java Introduction"
]
}
],
"awards": [
{
"title": "Digital Compression Pioneer Award",
"date": "2014-11-01",
"awarder": "Techcrunch",
"summary": "There is no spoon."
}
],
"publications": [
{
"name": "Video compression for 3d media",
"publisher": "Hooli",
"releaseDate": "2014-10-01",
"url": "http://en.wikipedia.org/wiki/Silicon_Valley_(TV_series)",
"summary": "Innovative middle-out compression algorithm that changes the way we store data."
}
],
"skills": [
{
"name": "Web Development",
"level": "Master",
"keywords": [
"HTML",
"CSS",
"Javascript"
]
},
{
"name": "Compression",
"level": "Master",
"keywords": [
"Mpeg",
"MP4",
"GIF"
]
}
],
"languages": [
{
"language": "English",
"fluency": "Native speaker"
}
],
"interests": [
{
"name": "Wildlife",
"keywords": [
"Ferrets",
"Unicorns"
]
}
],
"references": [
{
"name": "Erlich Bachman",
"reference": "It is my pleasure to recommend Richard, his performance working as a consultant for Main St. Company proved that he will be a valuable addition to any company."
}
],
"projects": [
{
"name": "Miss Direction",
"description": "A mapping engine that misguides you",
"highlights": [
"Won award at AIHacks 2016",
"Built by all women team of newbie programmers",
"Using modern technologies such as GoogleMaps, Chrome Extension and Javascript"
],
"keywords": [
"GoogleMaps", "Chrome Extension", "Javascript"
],
"startDate": "2016-08-24",
"endDate": "2016-08-24",
"url": "missdirection.example.com",
"roles": [
"Team lead", "Designer"
],
"entity": "Smoogle",
"type": "application"
}
],
"meta": {
"canonical": "https://raw.githubusercontent.com/jsonresume/resume-schema/master/resume.json",
"version": "v1.0.0",
"lastModified": "2017-12-24T15:53:00"
}
}

View File

@@ -1,3 +0,0 @@
module github.com/schnerring/hugo-mod-json-resume
go 1.21.5

View File

@@ -1,15 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.awards }}
<div class="jr__list jr-awards__list">
{{ range . }}
<div class="jr__item jr-awards__item">
<div class="jr__item-meta">
<div class="jr-awards__title">{{ .title }}</div>
<div class="jr__date jr-awards__date">{{ .date }}</div>
<div class="jr-awards__awarder">{{ .awarder }}</div>
</div>
<p class="jr__item-content">{{ .summary }}</p>
</div>
{{ end }}
</div>
{{ end }}

View File

@@ -1,10 +0,0 @@
{{ if .image }}
<div class="jr-basics__image">
<img
src="{{ .image }}"
alt="Picture{{ with .name }} of {{ . }}{{ end }}"
width="250"
height="250"
/>
</div>
{{ end }}

View File

@@ -1,72 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.basics }}
<div class="jr__item jr-basics__item">
{{ partial "json-resume/basics-image.html" . }}
{{ with .name }}
<div class="jr-basics__name">{{ . }}</div>
{{ end }}
{{ with .label }}
<div class="jr-basics__label">{{ . }}</div>
{{ end }}
{{ with .email }}
<div class="jr-basics__email">{{ . }}</div>
{{ end }}
{{ with .phone }}
<div class="jr-basics__phone">{{ . }}</div>
{{ end }}
{{ with .url }}
<div class="jr-basics__url">
<a href="{{ . }}">{{ . }}</a>
</div>
{{ end }}
{{ with .summary }}
<div class="jr-basics__summary">{{ . }}</div>
{{ end }}
{{ with .location }}
{{ with .address }}
<div class="jr-basics__location-address">{{ . }}</div>
{{ end }}
{{ with .postalCode }}
<div class="jr-basics__location-postalCode">{{ . }}</div>
{{ end }}
{{ with .city }}
<div class="jr-basics__location-city">{{ . }}</div>
{{ end }}
{{ with .countryCode }}
<div class="jr-basics__location-countryCode">{{ . }}</div>
{{ end }}
{{ with .region }}
<div class="jr-basics__location-region">{{ . }}</div>
{{ end }}
{{ end }}
{{ with where .profiles "username" "ne" nil }}
<hr />
<div class="jr-basics__profile jr-basics__profile--col">
{{ range . }}
{{ partial "simple-icon.html" (dict "url" .url "network" .network "username" .username) }}
{{ end }}
</div>
{{ end }}
{{ with where .profiles "username" "eq" nil }}
<hr />
<div class="jr-basics__profile jr-basics__profile--row">
{{ range . }}
{{ partial "simple-icon.html" (dict "url" .url "network" .network "username" .username) }}
{{ end }}
</div>
{{ end }}
</div>
{{ end }}

View File

@@ -1,22 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.certificates }}
<div class="jr__list jr-certificates__list">
{{ range . }}
<div class="jr__item jr-certificates__item">
<div class="jr__item-meta">
<div class="jr-certificates__name">
{{ if .url }}
<a href="{{ .url }}">
{{ .name }}
</a>
{{ else }}
<span>{{ .name }}</span>
{{ end }}
</div>
<div class="jr-certificates__date">{{ .date }}</div>
<div class="jr-certificates__issuer">{{ .issuer }}</div>
</div>
</div>
{{ end }}
</div>
{{ end }}

View File

@@ -1,11 +0,0 @@
<div class="jr__date-range">
<span>{{ .context.startDate }}</span>
<span>-</span>
<span>
{{- with .context.endDate -}}
{{- . -}}
{{- else -}}
{{ .site.Params.jsonResume.present | default "present" }}
{{- end -}}
</span>
</div>

View File

@@ -1,32 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.education }}
<div class="jr__list jr-education__list">
{{ range . }}
<div class="jr__item jr-education__item">
<div class="jr__item-meta">
<div class="jr-education__area">{{ .area }} ({{ .studyType }})</div>
{{ partial "json-resume/duration.html" (dict "context" . "site" $.Site) }}
{{ if .institution }}
<div class="jr-education__institution">
{{ if .url }}
<a href="{{ .url }}">{{ .institution }}</a>
{{ else }}
<span>{{ .institution }}</span>
{{ end }}
</div>
{{ end }}
</div>
<p class="jr-education__score">
{{ .score }}
</p>
{{ with .courses }}
<ul class="jr-education__courses">
{{ range . }}
<li>{{ . }}</li>
{{ end }}
</ul>
{{ end }}
</div>
{{ end }}
</div>
{{ end }}

View File

@@ -1,13 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.interests }}
<div class="jr__list jr-interests__list">
<ul>
{{ range . }}
<li class="jr__item jr-interests__item">
{{ .name }} —
{{ delimit .keywords ", " }}
</li>
{{ end }}
</ul>
</div>
{{ end }}

View File

@@ -1,13 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.languages }}
<div class="jr__list jr-languages__list">
<ul>
{{ range . }}
<li class="jr__item jr-languages__item">
{{ .language }} —
{{ .fluency }}
</li>
{{ end }}
</ul>
</div>
{{ end }}

View File

@@ -1,48 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.projects }}
<div class="jr__list jr-projects__list">
{{ range . }}
<div class="jr__item jr-projects__item">
<div class="jr__item-meta">
<div class="jr-projects__roles">
{{ delimit .roles ", " }}
</div>
{{ partial "json-resume/duration.html" (dict "context" . "site" $.Site) }}
<div class="jr-projects__name">
{{ if .url }}
<a href="{{ .url }}">{{ .name }}</a>
{{ else }}
<span>{{ .name }}</span>
{{ end }}
{{ with .type }}
({{ . }})
{{ end }}
{{ with .description }}
<span></span>
<span class="jr-projects__description">{{ . }}</span>
{{ end }}
</div>
{{ with .entity }}
<div class="jr-projects__entity">{{ . }}</div>
{{ end }}
</div>
<div class="jr__item-content">
{{ with .highlights }}
<ul>
{{ range . }}
<li>{{ . }}</li>
{{ end }}
</ul>
{{ end }}
</div>
{{ with .keywords }}
<p>
{{ delimit . ", " }}
</p>
{{ end }}
</div>
{{ end }}
</div>
{{ end }}

View File

@@ -1,24 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.publications }}
<div class="jr__list jr-publications__list">
{{ range . }}
<div class="jr__item jr-publications__item">
<div class="jr__item-meta">
<div class="jr-publications__name">
{{ if .url }}
<a href="{{ .url }}">{{ .name }}</a>
{{ else }}
<span>{{ .name }}</span>
{{ end }}
</div>
<div class="jr__date jr-publications__release-date">
{{ .releaseDate }}
</div>
<div class="jr-publications__publisher">{{ .publisher }}</div>
</div>
<p class="jr__item-content">{{ .summary }}</p>
</div>
{{ end }}
</div>
{{ end }}

View File

@@ -1,11 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.references }}
<div class="jr__list jr-references__list">
{{ range . }}
<blockquote class="jr__item jr-references__item">
<p>{{ .reference }}</p>
<p>— {{ .name }}</p>
</blockquote>
{{ end }}
</div>
{{ end }}

View File

@@ -1,17 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.skills }}
<div class="jr__list jr-skills__list">
<ul>
{{ range . }}
<li class="jr__item jr-skills__item">
<p><strong>{{ .name }} ({{ .level }})</strong></p>
{{ with .keywords }}
<p>
{{ delimit . ", " }}
</p>
{{ end }}
</li>
{{ end }}
</ul>
</div>
{{ end }}

View File

@@ -1,35 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.volunteer }}
<div class="jr__list jr-volunteer__list">
{{ range . }}
<div class="jr__item jr-volunteer__item">
<div class="jr__item-meta">
<div class="jr-volunteer__position">{{ .position }}</div>
{{ partial "json-resume/duration.html" (dict "context" . "site" $.Site) }}
{{ if .organization }}
<div class="jr-volunteer__organization">
{{ if .url }}
<a href="{{ .url }}">{{ .organization }}</a>
{{ else }}
<span>{{ .organization }}</span>
{{ end }}
</div>
{{ end }}
</div>
<div class="jr__item-content">
{{ with .summary }}
<p class="jr-volunteer__summary">{{ . }}</p>
{{ end }}
{{ with .highlights }}
<ul class="jr-volunteer__highlights">
{{ range . }}
<li>{{ . }}</li>
{{ end }}
</ul>
{{ end }}
</div>
</div>
{{ end }}
</div>
{{ end }}

View File

@@ -1,47 +0,0 @@
{{ $cv := index $.Site.Data.json_resume $.Site.Language.Lang }}
{{ with $cv.work }}
<div class="jr__list jr-work__list">
{{ range . }}
<div class="jr__item jr-work__item">
<div class="jr__item-meta">
<div class="jr-work__position">{{ .position }}</div>
{{ partial "json-resume/duration.html" (dict "context" . "site" $.Site) }}
{{ if or .name .location }}
<div class="jr-work__name">
{{ if .name }}
{{ if .url }}
<a href="{{ .url }}">
{{ .name }}
</a>
{{ else }}
<span>{{ .name }}</span>
{{ end }}
{{ end }}
{{ with .description }}
<span></span>
<span class="jr-work__description">{{ . }}</span>
{{ end }}
</div>
{{ end }}
{{ with .location }}
<div class="jr-work__location">{{ . }}</div>
{{ end }}
</div>
<div class="jr__item-content">
{{ with .summary }}
<p class="jr-work__summary">{{ . }}</p>
{{ end }}
{{ with .highlights }}
<ul class="jr-work__highlights">
{{ range . }}
<li>{{ . }}</li>
{{ end }}
</ul>
{{ end }}
</div>
</div>
{{ end }}
</div>
{{ end }}

View File

@@ -1,17 +0,0 @@
<!-- TODO see https://github.com/NiklasPor/prettier-plugin-go-template/issues/59 -->
<!-- prettier-ignore -->
{{ if .url }}<a href="{{ .url }}" target="_blank" rel="noreferrer me">{{ end }}
<div class="jr-basics__profile-item">
<div class="jr-basics__profile-icon">
{{ $path := printf "simple-icons/%s.svg" (lower .network) }}
{{ (resources.Get $path).Content | safeHTML }}
</div>
{{ if .username }}
<div class="jr-basics__profile-username">{{ .username }}</div>
{{ end }}
</div>
<!-- prettier-ignore -->
{{ if .url }}</a>{{ end }}

View File

@@ -1,2 +0,0 @@
{{ $jsonResumeSection := .Get 0 }}
{{ partial (printf "json-resume/%s" $jsonResumeSection) . }}

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +0,0 @@
{
"name": "hugo-mod-json-resume",
"version": "1.0.0",
"description": "Hugo shortcodes to add structured JSON Resume data to your Hugo site.",
"author": {
"name": "Michael Schnerring",
"email": "3743342+schnerring@users.noreply.github.com",
"url": "https://schnerring.net"
},
"license": "MIT",
"homepage": "https://github.com/schnerring/hugo-mod-json-resume#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/schnerring/hugo-mod-json-resume.git"
},
"bugs": {
"url": "https://github.com/schnerring/hugo-mod-json-resume/issues"
},
"keywords": ["hugo", "json-resume"],
"scripts": {
"lint:md": "markdownlint --fix **/*.md",
"lint": "npm run lint:css && npm run lint:js && npm run lint:md",
"prepare": "husky install"
},
"lint-staged": {
"*.md": "markdownlint --fix"
},
"dependencies": {
"simple-icons": "^11.0.0"
},
"devDependencies": {
"husky": "^8.0.3",
"lint-staged": "^15.2.0",
"markdownlint-cli": "^0.38.0",
"prettier": "^3.1.1",
"prettier-plugin-go-template": "^0.0.15"
}
}

View File

@@ -1,53 +0,0 @@
{
"author": {
"email": "3743342+schnerring@users.noreply.github.com",
"name": "Michael Schnerring",
"url": "https://schnerring.net"
},
"bugs": {
"url": "https://github.com/schnerring/hugo-mod-json-resume/issues"
},
"comments": {
"dependencies": {
"simple-icons": "project"
},
"devDependencies": {
"husky": "project",
"lint-staged": "project",
"markdownlint-cli": "project",
"prettier": "project",
"prettier-plugin-go-template": "project"
}
},
"dependencies": {
"simple-icons": "^11.0.0"
},
"description": "Hugo shortcodes to add structured JSON Resume data to your Hugo site.",
"devDependencies": {
"husky": "^8.0.3",
"lint-staged": "^15.2.0",
"markdownlint-cli": "^0.38.0",
"prettier": "^3.1.1",
"prettier-plugin-go-template": "^0.0.15"
},
"homepage": "https://github.com/schnerring/hugo-mod-json-resume#readme",
"keywords": [
"hugo",
"json-resume"
],
"license": "MIT",
"lint-staged": {
"*.md": "markdownlint --fix"
},
"name": "hugo-mod-json-resume",
"repository": {
"type": "git",
"url": "git+https://github.com/schnerring/hugo-mod-json-resume.git"
},
"scripts": {
"lint": "npm run lint:css && npm run lint:js && npm run lint:md",
"lint:md": "markdownlint --fix **/*.md",
"prepare": "husky install"
},
"version": "1.0.0"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

View File

@@ -86,10 +86,6 @@ Add the following to the `config.toml` file:
[[module.imports.mounts]]
source = "assets/css/json-resume.css"
target = "assets/css/critical/44-json-resume.css"
[[module.mounts]]
# required by hugo-mod-json-resume
source = "node_modules/simple-icons/icons"
target = "assets/simple-icons"
[[module.mounts]]
source = "assets"
target = "assets"

View File

@@ -13,7 +13,7 @@ main {
display: grid;
grid-area: main;
grid-template-areas: "empty content sidebar";
grid-template-columns: 1fr minmax(0, 650px) 4fr;
grid-template-columns: 2fr minmax(0, 860px) 2fr;
}
header {

View File

@@ -68,16 +68,3 @@ aside.toc {
}
}
}
.tag-cloud {
line-height: 1.1;
text-align: justify;
}
.tag-cloud__tag:hover {
color: var(--fg3);
}
.tag-cloud__tag--active {
text-decoration: underline;
}

View File

@@ -3,6 +3,10 @@ function getTheme() {
// User preference
return localStorage.getItem("theme");
}
// Undefined
}
function getOSTheme() {
if (window.matchMedia) {
// OS preference
return window.matchMedia("(prefers-color-scheme: light)").matches
@@ -21,20 +25,28 @@ function setTheme(theme) {
const prismLight = document.getElementById("prism-light");
prismDark.toggleAttribute("disabled", theme === "light");
prismLight.toggleAttribute("disabled", theme === "dark");
}
// Store user preference
function saveTheme(theme) {
localStorage.setItem("theme", theme);
}
// Initial load
const theme = getTheme();
if (theme) setTheme(theme);
const osTheme = getOSTheme();
if (theme) {
setTheme(theme);
// Store user preference
} else if (osTheme) {
setTheme(osTheme);
}
function toggleTheme(e) {
const theme = e.currentTarget.classList.contains("light--hidden")
? "light"
: "dark";
setTheme(theme);
saveTheme(theme);
}
// This script is inlined in the <head> of the document, so we have to wait

View File

@@ -3,21 +3,6 @@
[hugoVersion]
extended = true
min = "0.84.0"
[[imports]]
path = "github.com/schnerring/hugo-mod-json-resume"
[[imports.mounts]]
source = "data"
target = "data"
[[imports.mounts]]
source = "layouts"
target = "layouts"
[[imports.mounts]]
source = "assets/css/json-resume.css"
target = "assets/css/critical/44-json-resume.css"
[[mounts]]
# required by hugo-mod-json-resume
source = "node_modules/simple-icons/icons"
target = "assets/simple-icons"
[[mounts]]
source = "assets"
target = "assets"

Some files were not shown because too many files have changed in this diff Show More