diff --git a/.eslintrc.json b/.eslintrc.json
index d356dbeb..73e1b4f6 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -46,5 +46,5 @@
"es6": true
}
}],
- "ignorePatterns": ["public/**", "postcss.config.js"]
+ "ignorePatterns": ["public/**", "postcss.config.js", "gulpfile.js", "webpack.config.js"]
}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a39895a2..923ebf73 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -34,8 +34,8 @@ jobs:
node-version: 14.x
- name: Install dependencies
run: yarn install --frozen-lockfile
- - name: Build preview
- run: yarn build:hugo --environment=development --baseURL=/ --buildDrafts --buildFuture
+ - name: Build site
+ run: yarn build
- name: Percy snapshots
uses: percy/snapshot-action@v0.1.2
env:
diff --git a/.github/workflows/post-deploy.yml b/.github/workflows/post-deploy.yml
index 922cb8ff..f85cae0c 100644
--- a/.github/workflows/post-deploy.yml
+++ b/.github/workflows/post-deploy.yml
@@ -16,6 +16,7 @@ jobs:
with:
fetch-depth: 0
- uses: getsentry/action-release@v1
+ if: github.event.deployment_status.environment == 'production'
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: jakejarvis
diff --git a/.gitignore b/.gitignore
index 259e953e..13a89299 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,10 @@ builds/
_vendor/
hugo_stats.json
+# webpack artifacts
+data/manifest.json
+static/assets/
+
# node/npm/yarn
node_modules/
package-lock.json
diff --git a/.lighthouserc.json b/.lighthouserc.json
index 5d7de9da..5f1cb37e 100644
--- a/.lighthouserc.json
+++ b/.lighthouserc.json
@@ -20,6 +20,7 @@
"unused-javascript": "warn",
"uses-optimized-images": "warn",
"uses-rel-preconnect": "warn",
+ "canonical": "off",
"is-crawlable": "off",
"modern-image-formats": "off",
"offscreen-images": "off",
diff --git a/.prettierignore b/.prettierignore
index d174760e..e28e173a 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -3,6 +3,7 @@ assets/**/vendor/
layouts/
static/
hugo_stats.json
+data/manifest.json
# output from Hugo
public/
@@ -13,6 +14,8 @@ _vendor/
# dotfiles/config
.*
postcss.config.js
+webpack.config.js
+gulpfile.js
babel.config.json
tsconfig.json
diff --git a/.stylelintrc b/.stylelintrc
index 9556eefb..737dbd5e 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -10,6 +10,7 @@
"rules": {
"color-hex-length": "long",
"max-nesting-depth": 6,
+ "order/order": null,
"order/properties-alphabetical-order": null,
"plugin/no-unsupported-browser-features": [true, {
"severity": "warning",
diff --git a/Dockerfile b/Dockerfile
index 468625ea..ba6af98e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,7 +2,12 @@
# https://github.com/jakejarvis/hugo-docker/blob/master/Dockerfile
FROM ghcr.io/jakejarvis/hugo-extended:0.83.1
+ADD package.json .
+ADD yarn.lock .
+RUN yarn install
+
# expose live-refresh server (on custom port)
EXPOSE 1337
-CMD ["server", "--disableFastRender", "--buildDrafts", "--buildFuture", "--port=1337", "--baseURL=/", "--appendPort=false", "--bind=0.0.0.0", "--verbose"]
+ENTRYPOINT ["yarn"]
+CMD ["start"]
diff --git a/static/vendor/fonts/comic-neue-bold-subset.woff b/assets/fonts/comic-neue-bold-subset.woff
similarity index 100%
rename from static/vendor/fonts/comic-neue-bold-subset.woff
rename to assets/fonts/comic-neue-bold-subset.woff
diff --git a/static/vendor/fonts/comic-neue-bold-subset.woff2 b/assets/fonts/comic-neue-bold-subset.woff2
similarity index 100%
rename from static/vendor/fonts/comic-neue-bold-subset.woff2
rename to assets/fonts/comic-neue-bold-subset.woff2
diff --git a/static/vendor/fonts/comic-neue-regular-subset.woff b/assets/fonts/comic-neue-regular-subset.woff
similarity index 100%
rename from static/vendor/fonts/comic-neue-regular-subset.woff
rename to assets/fonts/comic-neue-regular-subset.woff
diff --git a/static/vendor/fonts/comic-neue-regular-subset.woff2 b/assets/fonts/comic-neue-regular-subset.woff2
similarity index 100%
rename from static/vendor/fonts/comic-neue-regular-subset.woff2
rename to assets/fonts/comic-neue-regular-subset.woff2
diff --git a/static/vendor/fonts/inter-bold-italic-subset.woff b/assets/fonts/inter-bold-italic-subset.woff
similarity index 100%
rename from static/vendor/fonts/inter-bold-italic-subset.woff
rename to assets/fonts/inter-bold-italic-subset.woff
diff --git a/static/vendor/fonts/inter-bold-italic-subset.woff2 b/assets/fonts/inter-bold-italic-subset.woff2
similarity index 100%
rename from static/vendor/fonts/inter-bold-italic-subset.woff2
rename to assets/fonts/inter-bold-italic-subset.woff2
diff --git a/static/vendor/fonts/inter-bold-subset.woff b/assets/fonts/inter-bold-subset.woff
similarity index 100%
rename from static/vendor/fonts/inter-bold-subset.woff
rename to assets/fonts/inter-bold-subset.woff
diff --git a/static/vendor/fonts/inter-bold-subset.woff2 b/assets/fonts/inter-bold-subset.woff2
similarity index 100%
rename from static/vendor/fonts/inter-bold-subset.woff2
rename to assets/fonts/inter-bold-subset.woff2
diff --git a/static/vendor/fonts/inter-italic-subset.var.woff2 b/assets/fonts/inter-italic-subset.var.woff2
similarity index 100%
rename from static/vendor/fonts/inter-italic-subset.var.woff2
rename to assets/fonts/inter-italic-subset.var.woff2
diff --git a/static/vendor/fonts/inter-medium-italic-subset.woff b/assets/fonts/inter-medium-italic-subset.woff
similarity index 100%
rename from static/vendor/fonts/inter-medium-italic-subset.woff
rename to assets/fonts/inter-medium-italic-subset.woff
diff --git a/static/vendor/fonts/inter-medium-italic-subset.woff2 b/assets/fonts/inter-medium-italic-subset.woff2
similarity index 100%
rename from static/vendor/fonts/inter-medium-italic-subset.woff2
rename to assets/fonts/inter-medium-italic-subset.woff2
diff --git a/static/vendor/fonts/inter-medium-subset.woff b/assets/fonts/inter-medium-subset.woff
similarity index 100%
rename from static/vendor/fonts/inter-medium-subset.woff
rename to assets/fonts/inter-medium-subset.woff
diff --git a/static/vendor/fonts/inter-medium-subset.woff2 b/assets/fonts/inter-medium-subset.woff2
similarity index 100%
rename from static/vendor/fonts/inter-medium-subset.woff2
rename to assets/fonts/inter-medium-subset.woff2
diff --git a/static/vendor/fonts/inter-regular-italic-subset.woff b/assets/fonts/inter-regular-italic-subset.woff
similarity index 100%
rename from static/vendor/fonts/inter-regular-italic-subset.woff
rename to assets/fonts/inter-regular-italic-subset.woff
diff --git a/static/vendor/fonts/inter-regular-italic-subset.woff2 b/assets/fonts/inter-regular-italic-subset.woff2
similarity index 100%
rename from static/vendor/fonts/inter-regular-italic-subset.woff2
rename to assets/fonts/inter-regular-italic-subset.woff2
diff --git a/static/vendor/fonts/inter-regular-subset.woff b/assets/fonts/inter-regular-subset.woff
similarity index 100%
rename from static/vendor/fonts/inter-regular-subset.woff
rename to assets/fonts/inter-regular-subset.woff
diff --git a/static/vendor/fonts/inter-regular-subset.woff2 b/assets/fonts/inter-regular-subset.woff2
similarity index 100%
rename from static/vendor/fonts/inter-regular-subset.woff2
rename to assets/fonts/inter-regular-subset.woff2
diff --git a/static/vendor/fonts/inter-subset.var.woff2 b/assets/fonts/inter-subset.var.woff2
similarity index 100%
rename from static/vendor/fonts/inter-subset.var.woff2
rename to assets/fonts/inter-subset.var.woff2
diff --git a/static/vendor/fonts/roboto-mono-italic-subset.var.woff2 b/assets/fonts/roboto-mono-italic-subset.var.woff2
similarity index 100%
rename from static/vendor/fonts/roboto-mono-italic-subset.var.woff2
rename to assets/fonts/roboto-mono-italic-subset.var.woff2
diff --git a/static/vendor/fonts/roboto-mono-italic-subset.woff b/assets/fonts/roboto-mono-italic-subset.woff
similarity index 100%
rename from static/vendor/fonts/roboto-mono-italic-subset.woff
rename to assets/fonts/roboto-mono-italic-subset.woff
diff --git a/static/vendor/fonts/roboto-mono-italic-subset.woff2 b/assets/fonts/roboto-mono-italic-subset.woff2
similarity index 100%
rename from static/vendor/fonts/roboto-mono-italic-subset.woff2
rename to assets/fonts/roboto-mono-italic-subset.woff2
diff --git a/static/vendor/fonts/roboto-mono-regular-subset.woff b/assets/fonts/roboto-mono-regular-subset.woff
similarity index 100%
rename from static/vendor/fonts/roboto-mono-regular-subset.woff
rename to assets/fonts/roboto-mono-regular-subset.woff
diff --git a/static/vendor/fonts/roboto-mono-regular-subset.woff2 b/assets/fonts/roboto-mono-regular-subset.woff2
similarity index 100%
rename from static/vendor/fonts/roboto-mono-regular-subset.woff2
rename to assets/fonts/roboto-mono-regular-subset.woff2
diff --git a/static/vendor/fonts/roboto-mono-subset.var.woff2 b/assets/fonts/roboto-mono-subset.var.woff2
similarity index 100%
rename from static/vendor/fonts/roboto-mono-subset.var.woff2
rename to assets/fonts/roboto-mono-subset.var.woff2
diff --git a/assets/img/android-chrome-192x192.png b/assets/images/android-chrome-192x192.png
similarity index 100%
rename from assets/img/android-chrome-192x192.png
rename to assets/images/android-chrome-192x192.png
diff --git a/assets/img/android-chrome-512x512.png b/assets/images/android-chrome-512x512.png
similarity index 100%
rename from assets/img/android-chrome-512x512.png
rename to assets/images/android-chrome-512x512.png
diff --git a/assets/img/apple-touch-icon.png b/assets/images/apple-touch-icon.png
similarity index 100%
rename from assets/img/apple-touch-icon.png
rename to assets/images/apple-touch-icon.png
diff --git a/assets/img/favicon-128.png b/assets/images/favicon-128.png
similarity index 100%
rename from assets/img/favicon-128.png
rename to assets/images/favicon-128.png
diff --git a/assets/img/favicon-16.png b/assets/images/favicon-16.png
similarity index 100%
rename from assets/img/favicon-16.png
rename to assets/images/favicon-16.png
diff --git a/assets/img/favicon-192.png b/assets/images/favicon-192.png
similarity index 100%
rename from assets/img/favicon-192.png
rename to assets/images/favicon-192.png
diff --git a/assets/img/favicon-32.png b/assets/images/favicon-32.png
similarity index 100%
rename from assets/img/favicon-32.png
rename to assets/images/favicon-32.png
diff --git a/assets/img/favicon-48.png b/assets/images/favicon-48.png
similarity index 100%
rename from assets/img/favicon-48.png
rename to assets/images/favicon-48.png
diff --git a/assets/img/favicon-64.png b/assets/images/favicon-64.png
similarity index 100%
rename from assets/img/favicon-64.png
rename to assets/images/favicon-64.png
diff --git a/assets/img/favicon.ico b/assets/images/favicon.ico
similarity index 100%
rename from assets/img/favicon.ico
rename to assets/images/favicon.ico
diff --git a/assets/img/favicon.svg b/assets/images/favicon.svg
similarity index 100%
rename from assets/img/favicon.svg
rename to assets/images/favicon.svg
diff --git a/assets/img/logo.png b/assets/images/logo.png
similarity index 100%
rename from assets/img/logo.png
rename to assets/images/logo.png
diff --git a/assets/img/logo.svg b/assets/images/logo.svg
similarity index 100%
rename from assets/img/logo.svg
rename to assets/images/logo.svg
diff --git a/assets/img/maskable-192x192.png b/assets/images/maskable-192x192.png
similarity index 100%
rename from assets/img/maskable-192x192.png
rename to assets/images/maskable-192x192.png
diff --git a/assets/img/maskable-512x512.png b/assets/images/maskable-512x512.png
similarity index 100%
rename from assets/img/maskable-512x512.png
rename to assets/images/maskable-512x512.png
diff --git a/assets/img/me.jpg b/assets/images/me.jpg
similarity index 100%
rename from assets/img/me.jpg
rename to assets/images/me.jpg
diff --git a/assets/img/mstile-150x150.png b/assets/images/mstile-150x150.png
similarity index 100%
rename from assets/img/mstile-150x150.png
rename to assets/images/mstile-150x150.png
diff --git a/assets/img/mstile-310x310.png b/assets/images/mstile-310x310.png
similarity index 100%
rename from assets/img/mstile-310x310.png
rename to assets/images/mstile-310x310.png
diff --git a/assets/img/safari-pinned-tab.svg b/assets/images/safari-pinned-tab.svg
similarity index 100%
rename from assets/img/safari-pinned-tab.svg
rename to assets/images/safari-pinned-tab.svg
diff --git a/assets/images/tiny-selfie.jpg b/assets/images/tiny-selfie.jpg
new file mode 100644
index 00000000..c809b91e
Binary files /dev/null and b/assets/images/tiny-selfie.jpg differ
diff --git a/assets/js/vendor/twemoji.js b/assets/js/vendor/twemoji.js
index cd79f5c1..17ac7a56 100644
--- a/assets/js/vendor/twemoji.js
+++ b/assets/js/vendor/twemoji.js
@@ -1,4 +1,4 @@
-/*! Copyright Twitter Inc. and other contributors. Licensed under MIT *//*
+/* Copyright Twitter Inc. and other contributors. Licensed under MIT *//*
https://github.com/twitter/twemoji/blob/gh-pages/LICENSE
*/
@@ -12,7 +12,7 @@
/////////////////////////
// default assets url, by default will be Twitter Inc. CDN
- base: '/vendor/emoji/',
+ base: '/assets/emoji/',
// default assets file extensions, by default '.png'
ext: '.svg',
@@ -265,7 +265,7 @@
* @return string the image source to use
*/
function defaultImageSrcGenerator(icon, options) {
- return ''.concat(options.base, options.size, '/', icon, options.ext);
+ return ''.concat(options.base, icon, options.ext);
}
/**
diff --git a/assets/sass/abstracts/_functions.scss b/assets/sass/abstracts/_functions.scss
index d953ff4d..7855a3c3 100644
--- a/assets/sass/abstracts/_functions.scss
+++ b/assets/sass/abstracts/_functions.scss
@@ -1,4 +1,7 @@
-@charset "UTF-8";
+@use "sass:math";
+@use "sass:string";
+
+@use "settings";
// Gradient hack to get our custom underline to wrap:
// https://www.dannyguo.com/blog/animated-multiline-link-underlines-with-css/
@@ -10,16 +13,24 @@
// Less compatible but better for light/dark mode switching.
// We fall back to non-alpha hex colors with postcss-color-rgba-fallback to mitigate this.
- $color-opaque-alpha: rgba($color, $link-underline-opacity / 100%);
+ $color-opaque-alpha: rgba($color, math.div(settings.$link-underline-opacity, 100%));
// Return non-gradient linear-gradient():
@return linear-gradient($color-opaque-alpha, $color-opaque-alpha);
}
// Web fonts (see components/_typography.scss)
-@mixin font-face($family, $src, $weight: normal, $style: normal, $display: swap, $variable: false) {
+@mixin font-face(
+ $family,
+ $src,
+ $weight: normal,
+ $style: normal,
+ $display: swap,
+ $variable: false,
+ $base-path: "../fonts/"
+) {
@font-face {
- font-family: $family;
+ font-family: string.quote($family);
font-style: $style;
font-weight: $weight;
font-display: $display;
@@ -27,49 +38,13 @@
@if $variable {
// all browsers that support variable fonts also support woff2, so a woff file is unncessary
// draft spec for formats: https://www.w3.org/TR/css-fonts-4/#src-desc
- src: url($base-url + $src + ".woff2") format("woff2-variations"), url($base-url + $src + ".woff2") format("woff2");
+ src: url($base-path + $src + ".woff2") format("woff2-variations"),
+ url($base-path + $src + ".woff2") format("woff2");
} @else {
- src: url($base-url + $src + ".woff2") format("woff2"), url($base-url + $src + ".woff") format("woff");
+ src: url($base-path + $src + ".woff2") format("woff2"), url($base-path + $src + ".woff") format("woff");
}
// Allow additional rules to be passed in:
@content;
}
}
-
-// Simple dark/light theme switching via
class and $themes map in abstracts/_themes.scss
-// https://medium.com/@katiemctigue/how-to-create-a-dark-mode-in-sass-609f131a3995
-//
-// Note: ONLY color rules should go in here (eg: just `border-color`, not the whole `border` rule)
-$theme-map: (); // now declaring global variables this way: https://sass-lang.com/documentation/variables#scope
-@mixin colors() {
- @each $theme, $map in $themes {
- body.#{$theme} & {
- @each $key, $submap in $map {
- $value: map-get(map-get($themes, $theme), "#{$key}");
- $theme-map: map-merge(
- $theme-map,
- (
- $key: $value,
- )
- ) !global;
- }
- @content;
- }
- }
-}
-
-// Just @include colors() and call c() when a rule depends on which theme is active.
-// The argument is a key in the $themes array in abstracts/_themes.
-//
-// img {
-// border: 1px solid;
-//
-// @include colors() {
-// border-color: c(medium-dark); // ONLY the color rules here.
-// }
-// }
-//
-@function c($key) {
- @return map-get($theme-map, $key);
-}
diff --git a/assets/sass/abstracts/_reset.scss b/assets/sass/abstracts/_reset.scss
deleted file mode 100644
index 89ff60b9..00000000
--- a/assets/sass/abstracts/_reset.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-@charset "UTF-8";
-
-@import "modern-normalize/modern-normalize.css";
diff --git a/assets/sass/abstracts/_responsive.scss b/assets/sass/abstracts/_responsive.scss
index 9aa50446..05945d22 100644
--- a/assets/sass/abstracts/_responsive.scss
+++ b/assets/sass/abstracts/_responsive.scss
@@ -1,16 +1,28 @@
-@charset "UTF-8";
+@use "../abstracts/settings";
+
+@use "../components/global";
+@use "../components/header";
+@use "../components/footer";
+@use "../components/content";
+
+@use "../pages/home";
+@use "../pages/list";
+@use "../pages/single";
+@use "../pages/videos";
+@use "../pages/etc";
+@use "../pages/projects";
// Responsive Awesomeness
-@media screen and (max-width: $responsive-width) {
- @include responsive--global();
- @include responsive--header();
- @include responsive--footer();
- @include responsive--content();
+@media screen and (max-width: settings.$responsive-width) {
+ @include global.responsive();
+ @include header.responsive();
+ @include footer.responsive();
+ @include content.responsive();
- @include responsive--home();
- @include responsive--list();
- @include responsive--single();
- @include responsive--videos();
- @include responsive--etc();
- @include responsive--projects();
+ @include home.responsive();
+ @include list.responsive();
+ @include single.responsive();
+ @include videos.responsive();
+ @include etc.responsive();
+ @include projects.responsive();
}
diff --git a/assets/sass/abstracts/_settings.scss b/assets/sass/abstracts/_settings.scss
index e422e4e1..fc5d5f93 100644
--- a/assets/sass/abstracts/_settings.scss
+++ b/assets/sass/abstracts/_settings.scss
@@ -1,5 +1,3 @@
-@charset "UTF-8";
-
// Web fonts
$webfont-sans: "Inter";
$webfont-sans-variable: "Inter var";
@@ -17,7 +15,9 @@ $font-stack-variable: $webfont-sans-variable, $system-fonts-sans;
$font-stack-mono: $webfont-mono, $system-fonts-monospace;
$font-stack-mono-variable: $webfont-mono-variable, $system-fonts-monospace;
-// Width at which to switch to mobile styles
+// The maximum width of the content area:
+$max-width: 865px;
+// Width at which to switch to mobile styles:
$responsive-width: 800px;
// Fancy link underline settings
diff --git a/assets/sass/abstracts/_themes.scss b/assets/sass/abstracts/_themes.scss
index 3f4cdeb1..638ca6f8 100644
--- a/assets/sass/abstracts/_themes.scss
+++ b/assets/sass/abstracts/_themes.scss
@@ -1,4 +1,4 @@
-@charset "UTF-8";
+@use "sass:map";
// Dark & Light Themes
$themes: (
@@ -161,3 +161,13 @@ $icon-bulb-on: 'data:image/svg+xml;charset=utf-8,';
$icon-wand: 'data:image/svg+xml;charset=utf-8,';
+
+// ----------------------------------------
+
+@mixin themed($property, $key) {
+ @each $theme, $map in $themes {
+ @at-root body.#{$theme} #{&} {
+ #{$property}: map-get($map, $key);
+ }
+ }
+}
diff --git a/assets/sass/components/_animation.scss b/assets/sass/components/_animation.scss
index 4e8567c6..0d846531 100644
--- a/assets/sass/components/_animation.scss
+++ b/assets/sass/components/_animation.scss
@@ -1,4 +1,4 @@
-@charset "UTF-8";
+@use "../abstracts/themes";
/*! Magic Waving Hand Emojiā¢: https://jrvs.io/wave */
.wave {
@@ -6,14 +6,14 @@
animation: wave 5s infinite;
animation-delay: 1s;
transform-origin: 65% 80%;
- will-change: transform; // stylelint-disable-line plugin/no-unsupported-browser-features
+ will-change: transform;
}
.beat {
display: inline-block;
animation: beat 10s infinite; // 6 bpm, call 911 if you see this please.
animation-delay: 7.5s; // offset from wave animation
- will-change: transform; // stylelint-disable-line plugin/no-unsupported-browser-features
+ will-change: transform;
}
// modified from https://tobiasahlin.com/spinkit/
@@ -28,9 +28,7 @@
display: inline-block;
animation: loader 1.4s infinite ease-in-out both;
- @include colors() {
- background-color: c(medium-light);
- }
+ @include themes.themed(background-color, "medium-light");
}
.spin-bounce1 {
diff --git a/assets/sass/components/_content.scss b/assets/sass/components/_content.scss
index 6e0efe9c..454211a1 100644
--- a/assets/sass/components/_content.scss
+++ b/assets/sass/components/_content.scss
@@ -1,4 +1,4 @@
-@charset "UTF-8";
+@use "../abstracts/themes";
div#content {
font-size: 0.925em;
@@ -19,9 +19,7 @@ div#content {
padding-bottom: 0.25em;
border-bottom: 1px solid;
- @include colors() {
- border-color: c(kinda-light);
- }
+ @include themes.themed(border-color, "kinda-light");
}
p.center {
@@ -43,9 +41,7 @@ div#content {
line-height: 1.5;
margin-top: 0.5em;
- @include colors() {
- color: c(medium);
- }
+ @include themes.themed(color, "medium");
}
}
@@ -61,6 +57,6 @@ div#content {
}
// Responsive
-@mixin responsive--content() {
+@mixin responsive() {
// stylelint-disable-block block-no-empty
}
diff --git a/assets/sass/components/_embeds.scss b/assets/sass/components/_embeds.scss
index 46a77122..91fcbabb 100644
--- a/assets/sass/components/_embeds.scss
+++ b/assets/sass/components/_embeds.scss
@@ -1,5 +1,3 @@
-@charset "UTF-8";
-
div.embed {
&.tweet {
.twitter-tweet-rendered iframe {
diff --git a/assets/sass/components/_footer.scss b/assets/sass/components/_footer.scss
index 81bc7334..1449d354 100644
--- a/assets/sass/components/_footer.scss
+++ b/assets/sass/components/_footer.scss
@@ -1,4 +1,5 @@
-@charset "UTF-8";
+@use "../abstracts/settings";
+@use "../abstracts/themes";
// Global Footer Styles
footer {
@@ -7,21 +8,17 @@ footer {
padding: 1.25em 1.5em;
border-top: 1px solid;
- @include colors() {
- color: c(medium-dark);
- border-color: c(kinda-light);
- }
+ @include themes.themed(color, "medium-dark");
+ @include themes.themed(border-color, "kinda-light");
a {
- @include colors() {
- color: c(medium-dark);
- }
+ @include themes.themed(color, "medium-dark");
}
div.row {
display: flex;
width: 100%;
- max-width: $max-width;
+ max-width: settings.$max-width;
margin: 0 auto;
justify-content: space-between;
font-size: 0.85em;
@@ -33,14 +30,12 @@ footer {
padding-bottom: 2px;
border-bottom: 1px solid;
- @include colors() {
- border-color: c(light);
- }
+ @include themes.themed(border-color, "light");
}
}
// Responsive
-@mixin responsive--footer() {
+@mixin responsive() {
footer {
padding: 1em 1.25em 0 1.25em;
diff --git a/assets/sass/components/_global.scss b/assets/sass/components/_global.scss
index 88011ecf..741921e7 100644
--- a/assets/sass/components/_global.scss
+++ b/assets/sass/components/_global.scss
@@ -1,4 +1,8 @@
-@charset "UTF-8";
+@use "sass:map";
+
+@use "../abstracts/functions";
+@use "../abstracts/settings";
+@use "../abstracts/themes";
// Global Styles
body {
@@ -7,27 +11,47 @@ body {
margin: 0 auto;
scroll-behavior: smooth;
+ font-family: settings.$font-stack-sans;
+ font-kerning: normal;
+ font-variant-ligatures: normal;
+ font-feature-settings: "kern", "liga", "calt", "clig", "ss01";
+
// global base font size:
font-size: 0.975em;
-}
+ line-height: 1.5;
-// manually setting light/dark mode backgrounds and bulb icon
-// really just the color of header & footer
-body {
- &.light {
- background-color: map-get(map-get($themes, "light"), "background-outer");
-
- button.dark-mode-toggle {
- background-image: url($icon-bulb-on);
- }
+ // set themed lightbulb icons manually
+ &.light button.dark-mode-toggle {
+ background-image: url(themes.$icon-bulb-on);
}
- &.dark {
- background-color: map-get(map-get($themes, "dark"), "background-outer");
+ &.dark button.dark-mode-toggle {
+ background-image: url(themes.$icon-bulb-off);
+ }
+}
- button.dark-mode-toggle {
- background-image: url($icon-bulb-off);
- }
+code,
+pre,
+.monospace {
+ font-family: settings.$font-stack-mono;
+ letter-spacing: normal;
+}
+
+// need to set light/dark mode backgrounds outside of the body selector
+@include themes.themed(background-color, "background-outer");
+
+// override above font-family if browser supports variable fonts
+// https://caniuse.com/#feat=variable-fonts
+@supports (font-variation-settings: normal) {
+ body {
+ font-family: settings.$font-stack-variable;
+ font-optical-sizing: auto;
+ }
+
+ code,
+ pre,
+ .monospace {
+ font-family: settings.$font-stack-mono-variable;
}
}
@@ -36,36 +60,37 @@ main {
width: 100%;
padding: 0 1.5em;
- @include colors() {
- background-color: c(background-inner);
- color: c(text);
- }
+ @include themes.themed(color, "text");
+ @include themes.themed(background-color, "background-inner");
}
// this is what's extended by different layouts (in ../pages)
div.layout {
- max-width: $max-width;
+ max-width: settings.$max-width;
margin: 0 auto;
display: block; // https://stackoverflow.com/questions/28794718/max-width-not-working-for-ie-11
}
-// cool link underlines:
-// https://www.dannyguo.com/blog/animated-multiline-link-underlines-with-css/
a {
text-decoration: none;
background-position: 0% 100%;
background-repeat: no-repeat;
- background-size: 0% $link-underline-size;
- padding-bottom: $link-underline-size;
+ background-size: 0% settings.$link-underline-size;
+ padding-bottom: settings.$link-underline-size;
transition: background-size 0.25s ease-in-out;
- @include colors() {
- color: c(links);
- background-image: underline-hack(c(links));
+ @include themes.themed(color, "links");
+
+ // cool link underlines (via messy SCSS hacking):
+ // https://www.dannyguo.com/blog/animated-multiline-link-underlines-with-css/
+ @each $theme, $map in themes.$themes {
+ @at-root body.#{$theme} #{&} {
+ background-image: functions.underline-hack(map-get($map, "links"));
+ }
}
&:hover {
- background-size: 100% $link-underline-size;
+ background-size: 100% settings.$link-underline-size;
}
&.no-underline {
@@ -79,21 +104,13 @@ strong {
letter-spacing: 0.008em; // not sure why the discrepancy between weights
}
-code,
-pre,
-.monospace {
- letter-spacing: normal;
-}
-
blockquote {
margin-left: 0;
padding-left: 1.5em;
border-left: 3px solid;
- @include colors() {
- color: c(medium-dark);
- border-color: c(links);
- }
+ @include themes.themed(color, "medium-dark");
+ @include themes.themed(border-color, "links");
}
hr {
@@ -101,9 +118,7 @@ hr {
height: 2px;
border: 0;
- @include colors() {
- background-color: c(light);
- }
+ @include themes.themed(background-color, "light");
}
// make SVG twemojis relative to surrounding text
@@ -126,7 +141,7 @@ a img.emoji {
}
// Responsive
-@mixin responsive--global() {
+@mixin responsive() {
body {
// Safari iOS menu bar reappears below 44px:
// https://www.eventbrite.com/engineering/mobile-safari-why/
diff --git a/assets/sass/components/_header.scss b/assets/sass/components/_header.scss
index 5c36e355..13790ccb 100644
--- a/assets/sass/components/_header.scss
+++ b/assets/sass/components/_header.scss
@@ -1,4 +1,5 @@
-@charset "UTF-8";
+@use "../abstracts/settings";
+@use "../abstracts/themes";
// Global Header Styles
header {
@@ -6,13 +7,11 @@ header {
padding: 0.7em 1.5em;
border-bottom: 1px solid;
- @include colors() {
- border-color: c(kinda-light);
- }
+ @include themes.themed(border-color, "kinda-light");
nav {
width: 100%;
- max-width: $max-width;
+ max-width: settings.$max-width;
margin: 0 auto;
display: flex;
align-items: center;
@@ -22,9 +21,7 @@ header {
display: flex;
align-items: center;
- @include colors() {
- color: c(medium-dark);
- }
+ @include themes.themed(color, "medium-dark");
img#selfie {
width: 50px;
@@ -32,9 +29,7 @@ header {
border: 1px solid;
border-radius: 50%;
- @include colors() {
- border-color: c(light);
- }
+ @include themes.themed(border-color, "light");
}
span#name {
@@ -45,9 +40,7 @@ header {
}
&:hover {
- @include colors() {
- color: c(links);
- }
+ @include themes.themed(color, "links");
img#selfie {
opacity: 0.9;
@@ -70,18 +63,14 @@ header {
a {
display: inline-block;
transition: transform 0.15s ease-in-out;
- will-change: transform; // stylelint-disable-line plugin/no-unsupported-browser-features
+ will-change: transform;
- @include colors() {
- color: c(medium-dark);
- }
+ @include themes.themed(color, "medium-dark");
&:hover {
transform: scale(1.1);
- @include colors() {
- color: c(links);
- }
+ @include themes.themed(color, "links");
}
span.icon {
@@ -128,7 +117,7 @@ header {
}
// Responsive
-@mixin responsive--header() {
+@mixin responsive() {
header {
padding: 0.5em 1.25em;
diff --git a/assets/sass/components/_reset.scss b/assets/sass/components/_reset.scss
new file mode 100644
index 00000000..649cb710
--- /dev/null
+++ b/assets/sass/components/_reset.scss
@@ -0,0 +1,185 @@
+// stylelint-disable
+
+/*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */
+
+/*
+Document
+========
+*/
+
+/**
+Use a better box model (opinionated).
+*/
+
+*,
+::before,
+::after {
+ box-sizing: border-box;
+}
+
+/**
+1. Correct the line height in all browsers.
+2. Use a more readable tab size (opinionated).
+3. Prevent adjustments of font size after orientation changes in iOS.
+*/
+
+html {
+ line-height: 1.15; /* 1 */
+ tab-size: 4; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 3 */
+}
+
+/*
+Sections
+========
+*/
+
+/*
+Grouping content
+================
+*/
+
+/**
+1. Add the correct height in Firefox.
+2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
+*/
+
+hr {
+ height: 0; /* 1 */
+ color: inherit; /* 2 */
+}
+
+/*
+Text-level semantics
+====================
+*/
+
+/**
+Add the correct text decoration in Chrome, Edge, and Safari.
+*/
+
+abbr[title] {
+ text-decoration: underline dotted;
+}
+
+/**
+Add the correct font weight in Edge and Safari.
+*/
+
+b,
+strong {
+ font-weight: bolder;
+}
+
+/**
+Correct the odd 'em' font sizing in all browsers.
+*/
+
+code,
+kbd,
+samp,
+pre {
+ font-size: 1em;
+}
+
+/**
+Add the correct font size in all browsers.
+*/
+
+small {
+ font-size: 80%;
+}
+
+/**
+Prevent 'sub' and 'sup' elements from affecting the line height in all browsers.
+*/
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+/*
+Tabular data
+============
+*/
+
+/**
+1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
+2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
+*/
+
+table {
+ text-indent: 0; /* 1 */
+ border-color: inherit; /* 2 */
+}
+
+/*
+Forms
+=====
+*/
+
+/**
+1. Change the font styles in all browsers.
+2. Remove the margin in Firefox and Safari.
+*/
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: inherit; /* 1 */
+ font-size: 100%; /* 1 */
+ line-height: 1.15; /* 1 */
+ margin: 0; /* 2 */
+}
+
+/**
+Remove the inheritance of text transform in Edge and Firefox.
+*/
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers.
+*/
+
+legend {
+ padding: 0;
+}
+
+/**
+Add the correct vertical alignment in Chrome and Firefox.
+*/
+
+progress {
+ vertical-align: baseline;
+}
+
+/*
+Interactive
+===========
+*/
+
+/*
+Add the correct display in Chrome and Safari.
+*/
+
+summary {
+ display: list-item;
+}
diff --git a/assets/sass/components/_syntax.scss b/assets/sass/components/_syntax.scss
index 397e7df0..1d448ce2 100644
--- a/assets/sass/components/_syntax.scss
+++ b/assets/sass/components/_syntax.scss
@@ -1,5 +1,3 @@
-@charset "UTF-8";
-
// all code
code {
font-size: 0.925em;
diff --git a/assets/sass/components/_typography.scss b/assets/sass/components/_typography.scss
index 77d9c69f..23a58ee8 100644
--- a/assets/sass/components/_typography.scss
+++ b/assets/sass/components/_typography.scss
@@ -1,4 +1,5 @@
-@charset "UTF-8";
+@use "../abstracts/functions";
+@use "../abstracts/settings";
// Note to self: got this list after subsetting Inter with glyphhanger or pyftsubset:
// https://github.com/filamentgroup/glyphhanger
@@ -16,30 +17,30 @@ $unicode-subset: U+0000-00FF, U+2000-206F, U+2200-22FF, U+2122;
*/
// Variable
-@include font-face("Inter var", "vendor/fonts/inter-subset.var", 100 900, $variable: true) {
+@include functions.font-face("Inter var", "inter-subset.var", 100 900, $variable: true) {
unicode-range: $unicode-subset;
}
-@include font-face("Inter var", "vendor/fonts/inter-italic-subset.var", 100 900, italic, $variable: true) {
+@include functions.font-face("Inter var", "inter-italic-subset.var", 100 900, italic, $variable: true) {
unicode-range: $unicode-subset;
}
// Legacy
-@include font-face("Inter", "vendor/fonts/inter-regular-subset", 400) {
+@include functions.font-face("Inter", "inter-regular-subset", 400) {
unicode-range: $unicode-subset;
}
-@include font-face("Inter", "vendor/fonts/inter-regular-italic-subset", 400, italic) {
+@include functions.font-face("Inter", "inter-regular-italic-subset", 400, italic) {
unicode-range: $unicode-subset;
}
-@include font-face("Inter", "vendor/fonts/inter-medium-subset", 500) {
+@include functions.font-face("Inter", "inter-medium-subset", 500) {
unicode-range: $unicode-subset;
}
-@include font-face("Inter", "vendor/fonts/inter-medium-italic-subset", 500, italic) {
+@include functions.font-face("Inter", "inter-medium-italic-subset", 500, italic) {
unicode-range: $unicode-subset;
}
-@include font-face("Inter", "vendor/fonts/inter-bold-subset", 700) {
+@include functions.font-face("Inter", "inter-bold-subset", 700) {
unicode-range: $unicode-subset;
}
-@include font-face("Inter", "vendor/fonts/inter-bold-italic-subset", 700, italic) {
+@include functions.font-face("Inter", "inter-bold-italic-subset", 700, italic) {
unicode-range: $unicode-subset;
}
@@ -52,40 +53,23 @@ $unicode-subset: U+0000-00FF, U+2000-206F, U+2200-22FF, U+2122;
*/
// Variable
-@include font-face("Roboto Mono var", "vendor/fonts/roboto-mono-subset.var", 100 700, $variable: true);
-@include font-face("Roboto Mono var", "vendor/fonts/roboto-mono-italic-subset.var", 100 700, italic, $variable: true);
+@include functions.font-face("Roboto Mono var", "roboto-mono-subset.var", 100 700, $variable: true);
+@include functions.font-face("Roboto Mono var", "roboto-mono-italic-subset.var", 100 700, italic, $variable: true);
// Legacy
-@include font-face("Roboto Mono", "vendor/fonts/roboto-mono-regular-subset", 400);
-@include font-face("Roboto Mono", "vendor/fonts/roboto-mono-italic-subset", 400, italic);
+@include functions.font-face("Roboto Mono", "roboto-mono-regular-subset", 400);
+@include functions.font-face("Roboto Mono", "roboto-mono-italic-subset", 400, italic);
-/* --------- */
-
-body {
- font-family: $font-stack-sans;
- font-kerning: normal;
- font-variant-ligatures: normal;
- font-feature-settings: "kern", "liga", "calt", "clig", "ss01";
- line-height: 1.5;
+/*!
+ * Comic Neue typeface v2.5 - http://comicneue.com/
+ *
+ * Copyright (c) 2014 The Comic Neue Project Authors.
+ * Licensed under the SIL Open Font License, Version 1.1:
+ * https://github.com/crozynski/comicneue/blob/v2.5/OFL.txt
+ */
+@include functions.font-face("Comic Neue", "comic-neue-regular-subset", 400) {
+ unicode-range: U+0000-00FF, U+2000-206F, U+20A0-20CF, U+2190-21FF, U+2200-22FF, U+2122;
}
-
-code,
-pre,
-.monospace {
- font-family: $font-stack-mono;
-}
-
-// override above font-family if browser supports variable fonts
-// https://caniuse.com/#feat=variable-fonts
-@supports (font-variation-settings: normal) {
- body {
- font-family: $font-stack-variable;
- font-optical-sizing: auto;
- }
-
- code,
- pre,
- .monospace {
- font-family: $font-stack-mono-variable;
- }
+@include functions.font-face("Comic Neue", "comic-neue-bold-subset", 700) {
+ unicode-range: U+0000-00FF, U+2000-206F, U+20A0-20CF, U+2190-21FF, U+2200-22FF, U+2122;
}
diff --git a/assets/sass/main.scss b/assets/sass/main.scss
index 7847be02..31053b9e 100644
--- a/assets/sass/main.scss
+++ b/assets/sass/main.scss
@@ -1,40 +1,25 @@
@charset "UTF-8";
-// NOTE: all variables set by Hugo's config.toml MUST go here:
-// prettier-ignore
-$max-width: "{{ printf "%d%s" .Site.Params.Theme.maxWidth "px" }}";
-$base-url: "{{ strings.TrimRight "/" .Site.BaseURL }}" + "/";
-
-// those values need quotes because, even though prettier & stylelint are correct
-// in that it's insanely invalid SCSS, they refuse to ignore it. but $max-width is
-// a numerical value that can't have quotes, so let's remove them...
-$max-width: unquote($max-width);
-
-// Variables & Functions
-@import "abstracts/functions";
-@import "abstracts/settings";
-@import "abstracts/themes";
-@import "abstracts/reset";
-
// Global Styles
-@import "components/typography";
-@import "components/global";
-@import "components/header";
-@import "components/footer";
-@import "components/content";
-@import "components/embeds";
+@use "components/typography";
+@use "components/reset";
+@use "components/global";
+@use "components/header";
+@use "components/footer";
+@use "components/content";
+@use "components/embeds";
// Pages
-@import "pages/home";
-@import "pages/list";
-@import "pages/single";
-@import "pages/videos";
-@import "pages/etc";
-@import "pages/projects";
-
-// Responsive Mixins
-@import "abstracts/responsive";
+@use "pages/home";
+@use "pages/list";
+@use "pages/single";
+@use "pages/videos";
+@use "pages/etc";
+@use "pages/projects";
// Miscellaneous
-@import "components/syntax";
-@import "components/animation";
+@use "components/syntax";
+@use "components/animation";
+
+// Responsive Mixins
+@use "abstracts/responsive";
diff --git a/assets/sass/pages/_etc.scss b/assets/sass/pages/_etc.scss
index 0a3060b0..9e8ffa81 100644
--- a/assets/sass/pages/_etc.scss
+++ b/assets/sass/pages/_etc.scss
@@ -1,5 +1,3 @@
-@charset "UTF-8";
-
// Video Styles
div.layout-etc {
padding-top: 1.5em;
@@ -17,7 +15,7 @@ div.layout-etc {
}
// Responsive
-@mixin responsive--etc() {
+@mixin responsive() {
div.layout-etc {
h1 {
font-size: 1.6em;
diff --git a/assets/sass/pages/_home.scss b/assets/sass/pages/_home.scss
index 78108c36..f1defe34 100644
--- a/assets/sass/pages/_home.scss
+++ b/assets/sass/pages/_home.scss
@@ -1,4 +1,5 @@
-@charset "UTF-8";
+@use "../abstracts/functions";
+@use "../abstracts/themes";
// Home Styles
div.layout-home {
@@ -52,20 +53,18 @@ div.layout-home {
// easter egg emoji cursor
a#birthday {
&:hover {
- cursor: url($icon-wand) 0 0, auto;
+ cursor: url(themes.$icon-wand) 0 0, auto;
}
}
// non-link colors
span {
serverless {
- color: $color-serverless;
+ color: themes.$color-serverless;
}
shh {
- @include colors() {
- color: c(medium-light);
- }
+ @include themes.themed(color, "medium-light");
}
&.wave {
@@ -75,17 +74,17 @@ div.layout-home {
}
// Loop through $colors-home (see abstracts/_variables)
-@each $id, $colors in $colors-home {
+@each $id, $colors in themes.$colors-home {
@each $theme, $color in $colors {
- body.#{$theme} div.layout-home a##{$id} {
+ @at-root body.#{$theme} div.layout-home a##{$id} {
color: $color;
- background-image: underline-hack($color);
+ background-image: functions.underline-hack($color);
}
}
}
// Responsive
-@mixin responsive--home() {
+@mixin responsive() {
div.layout-home {
font-size: 0.975em;
padding-top: 1em;
diff --git a/assets/sass/pages/_list.scss b/assets/sass/pages/_list.scss
index 4dfd325e..1d65dda7 100644
--- a/assets/sass/pages/_list.scss
+++ b/assets/sass/pages/_list.scss
@@ -1,4 +1,4 @@
-@charset "UTF-8";
+@use "../abstracts/themes";
// Archive/List Styles
div.layout-list {
@@ -32,9 +32,7 @@ div.layout-list {
width: 5.25em;
flex-shrink: 0;
- @include colors() {
- color: c(medium);
- }
+ @include themes.themed(color, "medium");
}
&:last-child {
@@ -45,7 +43,7 @@ div.layout-list {
}
// Responsive
-@mixin responsive--list() {
+@mixin responsive() {
div.layout-list {
padding-top: 1em;
padding-bottom: 0;
diff --git a/assets/sass/pages/_projects.scss b/assets/sass/pages/_projects.scss
index bbed910e..063f8465 100644
--- a/assets/sass/pages/_projects.scss
+++ b/assets/sass/pages/_projects.scss
@@ -1,4 +1,4 @@
-@charset "UTF-8";
+@use "../abstracts/themes";
// Video Styles
div.layout-projects {
@@ -38,10 +38,8 @@ div.layout-projects {
border-radius: 6px;
font-size: 0.9em;
- @include colors() {
- color: c(medium-dark);
- border-color: c(kinda-light);
- }
+ @include themes.themed(color, "medium-dark");
+ @include themes.themed(border-color, "kinda-light");
a.repo-name {
font-size: 1.2em;
@@ -57,9 +55,7 @@ div.layout-projects {
margin-right: 12px;
font-size: 0.925em;
- @include colors() {
- color: c(medium);
- }
+ @include themes.themed(color, "medium");
svg {
display: inline-block;
@@ -84,7 +80,7 @@ div.layout-projects {
}
// Responsive
-@mixin responsive--projects() {
+@mixin responsive() {
div.layout-projects {
// stylelint-disable-block block-no-empty
}
diff --git a/assets/sass/pages/_single.scss b/assets/sass/pages/_single.scss
index 49004fd9..224f93ec 100644
--- a/assets/sass/pages/_single.scss
+++ b/assets/sass/pages/_single.scss
@@ -1,4 +1,4 @@
-@charset "UTF-8";
+@use "../abstracts/themes";
// Post Styles
div.layout-single {
@@ -11,9 +11,7 @@ div.layout-single {
letter-spacing: 0.04em;
margin-top: 0.3em;
- @include colors() {
- color: c(medium);
- }
+ @include themes.themed(color, "medium");
a {
color: inherit;
@@ -47,9 +45,7 @@ div.layout-single {
content: "#"; // cosmetically hashtagify tags
padding-right: 0.125em;
- @include colors() {
- color: c(light);
- }
+ @include themes.themed(color, "light");
}
&:last-of-type {
@@ -75,7 +71,7 @@ div.layout-single {
}
// Responsive
-@mixin responsive--single() {
+@mixin responsive() {
div.layout-single {
padding-top: 0.8em;
padding-bottom: 0.4em;
diff --git a/assets/sass/pages/_videos.scss b/assets/sass/pages/_videos.scss
index dcbe08ce..8aa11a79 100644
--- a/assets/sass/pages/_videos.scss
+++ b/assets/sass/pages/_videos.scss
@@ -1,4 +1,4 @@
-@charset "UTF-8";
+@use "../abstracts/themes";
// Video Styles
div.layout-video {
@@ -20,9 +20,7 @@ div.layout-video {
line-height: 1.5;
margin: 1.25em 1em 0.5em 1em;
- @include colors() {
- color: c(medium-light);
- }
+ @include themes.themed(color, "medium-light");
a {
font-weight: bold;
@@ -37,7 +35,7 @@ div.layout-video {
}
// Responsive
-@mixin responsive--videos() {
+@mixin responsive() {
div.layout-video {
padding: 1em 0;
diff --git a/babel.config.json b/babel.config.json
index 1d2e290c..4196da03 100644
--- a/babel.config.json
+++ b/babel.config.json
@@ -3,7 +3,11 @@
[
"@babel/preset-env",
{
- "include": ["transform-arrow-functions", "transform-block-scoping", "transform-template-literals"],
+ "include": [
+ "transform-arrow-functions",
+ "transform-block-scoping",
+ "transform-template-literals"
+ ],
"useBuiltIns": "entry",
"corejs": 3
}
@@ -11,7 +15,9 @@
[
"minify",
{
- "removeConsole": true
+ "removeConsole": true,
+ // https://github.com/babel/minify/issues/904#issuecomment-424367995
+ "builtIns": false
}
]
]
diff --git a/config.toml b/config.toml
index 52dfb703..3fb33a95 100644
--- a/config.toml
+++ b/config.toml
@@ -1,4 +1,4 @@
-baseURL = "https://jarv.is/"
+baseURL = "/"
languageCode = "en-us"
title = "Jake Jarvis"
@@ -26,8 +26,9 @@ disableAliases = true
[params]
description = "Hi there! I'm a frontend web developer based in Boston, Massachusetts specializing in the JAMstack, modern JavaScript frameworks, and progressive web apps."
- image = "img/logo.png" # relative to assetDir root
+ image = "images/logo.png" # relative to assetDir root
mainSection = "notes" # content that appears in feeds
+ baseURL = "https://jarv.is" # different from baseURL above, this is only used where necessary
[params.theme]
maxWidth = 865 # px
defaultTheme = "light" # light or dark?
@@ -42,7 +43,7 @@ disableAliases = true
[author]
name = "Jake Jarvis"
- image = "img/me.jpg" # relative to assetDir root
+ image = "images/me.jpg" # relative to assetDir root
email = "jake@jarv.is"
[author.social]
github = "jakejarvis"
@@ -56,18 +57,6 @@ disableAliases = true
instagram = "jakejarvis"
mastodon = "mastodon.social/@jakejarvis"
-[module]
- # we're grabbing Twemoji SVGs from an NPM helper package:
- # https://www.npmjs.com/package/twemoji-emojis
- [[module.mounts]]
- source = "node_modules/twemoji-emojis/vendor/svg"
- target = "static/vendor/emoji/svg"
- # this is required, or else the Twemoji mount completely takes over /static:
- # https://discourse.gohugo.io/t/can-hugo-copy-files-from-one-dir-to-another/24085/4
- [[module.mounts]]
- source = "static"
- target = "static"
-
[frontmatter]
lastmod = ["date", "publishDate", ":default"]
diff --git a/content/previously/index.md b/content/previously/index.md
index faed49e8..61d1343d 100644
--- a/content/previously/index.md
+++ b/content/previously/index.md
@@ -5,25 +5,9 @@ description: "An incredibly embarrassing and somewhat painful walkthrough of thi
image: "images/2001_12.png"
layout: etc
css: |
- /*!
- * Comic Neue typeface v2.5 - http://comicneue.com/
- *
- * Copyright (c) 2014 The Comic Neue Project Authors.
- * Licensed under the SIL Open Font License, Version 1.1:
- * https://github.com/crozynski/comicneue/blob/v2.5/OFL.txt
- */
- @font-face {
- font-family: "Comic Neue";
- font-style: normal;
- font-weight: 700;
- font-display: swap;
- src: url("{{ absURL "/vendor/fonts/comic-neue-bold-subset.woff2" | safeCSS }}") format("woff2"),
- url("{{ absURL "/vendor/fonts/comic-neue-bold-subset.woff" | safeCSS }}") format("woff");
- unicode-range: U+0000-00FF,U+2000-206F,U+20A0-20CF,U+2190-21FF,U+2200-22FF,U+2122;
- }
body {
font-family: "Comic Neue", "Comic Sans MS", "Comic Sans", "Inter", sans-serif;
- font-weight: 700;
+ font-weight: 700 !important;
}
div#content {
text-align: center;
@@ -40,17 +24,19 @@ css: |
border: 2px solid #e3d18c;
}
div#content code {
- font-weight: 400;
+ font-weight: 400 !important;
}
div#content span.limegreen {
color: #32cd32;
}
header nav a#logo span#name {
font-size: 1.5em;
+ font-weight: 700 !important;
}
header nav ul li a span.text {
font-size: 1.05em;
line-height: 1.05;
+ font-weight: 700 !important;
}
footer div#copyright, footer div#poweredby {
font-size: 1.1em;
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 00000000..972476da
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,92 @@
+const gulp = require("gulp");
+const execa = require("gulp-execa").task;
+const htmlmin = require("gulp-html-minifier-terser");
+const imagemin = require("gulp-imagemin");
+const del = require("del");
+
+// use up-to-date imagemin plugins instead of those bundled with gulp-imagemin:
+const imageminMozjpeg = require("imagemin-mozjpeg");
+const imageminPngquant = require("imagemin-pngquant");
+const imageminGifsicle = require("imagemin-gifsicle");
+const imageminSvgo = require("imagemin-svgo");
+
+exports.default = gulp.series(
+ clean,
+ npx("webpack", ["--mode", "production", "--profile"]),
+ npx("hugo"),
+ gulp.parallel(
+ optimizeHtml,
+ optimizeImages,
+ ),
+);
+
+exports.serve = gulp.parallel(
+ npx("webpack", ["serve"]),
+ npx("hugo", ["--watch", "--buildDrafts", "--buildFuture", "--verbose"]),
+);
+
+exports.clean = gulp.task(clean);
+
+function optimizeHtml() {
+ return gulp
+ .src("public/**/*.html", { base: "./" })
+ .pipe(
+ htmlmin(
+ {
+ html5: true,
+ preserveLineBreaks: true,
+ collapseWhitespace: true,
+ collapseBooleanAttributes: true,
+ removeComments: true,
+ minifyCSS: false,
+ minifyJS: false,
+ }
+ )
+ )
+ .pipe(gulp.dest(".", { overwrite: true }));
+}
+
+function optimizeImages() {
+ return gulp
+ .src(["public/**/*.{gif,jpg,png,svg}", "!public/assets/emoji/*"], { base: "./" })
+ .pipe(
+ imagemin([
+ imageminMozjpeg({
+ quality: 85,
+ progressive: true,
+ }),
+ imageminPngquant({
+ quality: [0.7, 0.9],
+ speed: 1,
+ strip: true,
+ }),
+ imageminGifsicle(),
+ imageminSvgo(),
+ ],
+ {
+ verbose: true,
+ })
+ )
+ .pipe(gulp.dest(".", { overwrite: true }));
+}
+
+function clean() {
+ return del([
+ "public/",
+ "builds/",
+ "_vendor/",
+ "static/assets/",
+ "data/manifest.json",
+ ]);
+}
+
+// run a locally installed (i.e. ./node_modules/.bin/foo) binary, similar to a package.json script
+function npx(bin, options) {
+ // WARNING: MAJOR HACKS AHEAD:
+ const cmd = `${bin} ${options ? options.join(" ") : ""}`.trim();
+ return execa(cmd, {
+ preferLocal: true,
+ shell: true,
+ stdio: "inherit",
+ });
+}
diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html
index e6b1a04b..1e198da7 100644
--- a/layouts/_default/baseof.html
+++ b/layouts/_default/baseof.html
@@ -1,6 +1,6 @@
{{ printf "" | safeHTML -}}
-{{ printf "" ("humans.txt" | absURL) | safeHTML }}
+{{ printf "" (print .Site.Params.baseURL "/humans.txt") | safeHTML }}
{{- printf "" | safeHTML }}
diff --git a/layouts/index.atom b/layouts/index.atom
index 02942e82..781b054d 100644
--- a/layouts/index.atom
+++ b/layouts/index.atom
@@ -2,24 +2,24 @@
{{ printf "" | safeHTML }}
{{ .Site.Title }}
- {{ .Permalink }}
+ {{ print .Site.Params.baseUrl .Permalink }}
{{ .Site.Title }}
- {{ .Permalink }}
+ {{ print .Site.Params.baseUrl .Permalink }}
Hugo -- gohugo.io
{{- with .Site.Copyright }}
{{ . }}
{{- end }}
{{- with .Scratch.Get "authorImage" }}
- {{ .Permalink }}
+ {{ print $.Site.Params.baseUrl .Permalink }}
{{- end }}
{{ .Site.LastChange.Format "2006-01-02T15:04:05Z" | safeHTML }}
{{- with .OutputFormats.Get "ATOM" }}
- {{ printf `` .MediaType.Type .Permalink | safeHTML }}
+ {{ printf `` .MediaType.Type (print $.Site.Params.baseUrl .Permalink) | safeHTML }}
{{- end }}
{{- range .AlternativeOutputFormats }}
- {{ printf `` .MediaType.Type .Permalink | safeHTML }}
+ {{ printf `` .MediaType.Type (print $.Site.Params.baseUrl .Permalink) | safeHTML }}
{{- end }}
{{- range (where .Site.RegularPages "Section" .Site.Params.mainSection) }}
@@ -27,10 +27,10 @@
{{- with .Site.Author.name }}
{{ . }}
- {{ $.Permalink }}
+ {{ print $.Site.Params.baseUrl $.Permalink }}
{{- end }}
- {{ .Permalink }}
+ {{ print $.Site.Params.baseUrl .Permalink }}
{{ .Date.UTC.Format "2006-01-02T15:04:05Z" | safeHTML }}
{{ .Date.UTC.Format "2006-01-02T15:04:05Z" | safeHTML }}
diff --git a/layouts/index.webmanifest b/layouts/index.webmanifest
index c0310662..e0900104 100644
--- a/layouts/index.webmanifest
+++ b/layouts/index.webmanifest
@@ -1,33 +1,33 @@
{
"name": "{{ .Site.Title }}",
- "short_name": "{{ (urls.Parse .Site.BaseURL).Host }}",
+ "short_name": "{{ (urls.Parse .Site.Params.baseURL).Host }}",
"icons": [
- {
- "src": "{{ (resources.Get "img/android-chrome-512x512.png").Permalink | safeJS }}",
+ {{ with index .Site.Data.manifest "images/android-chrome-512x512.png" }}{
+ "src": "{{ .src | absURL | safeJS }}",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
- },
- {
- "src": "{{ (resources.Get "img/android-chrome-192x192.png").Permalink | safeJS }}",
+ },{{ end }}
+ {{ with index .Site.Data.manifest "images/android-chrome-192x192.png" }}{
+ "src": "{{ .src | absURL | safeJS }}",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
- },
- {
- "src": "{{ (resources.Get "img/maskable-512x512.png").Permalink | safeJS }}",
+ },{{ end }}
+ {{ with index .Site.Data.manifest "images/maskable-512x512.png" }}{
+ "src": "{{ .src | absURL | safeJS }}",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
- },
- {
- "src": "{{ (resources.Get "img/maskable-192x192.png").Permalink | safeJS }}",
+ },{{ end }}
+ {{ with index .Site.Data.manifest "images/maskable-192x192.png" }}{
+ "src": "{{ .src | absURL | safeJS }}",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
- }
+ }{{ end }}
],
- "start_url": "{{ .Site.BaseURL | safeJS }}",
+ "start_url": "/",
"display": "browser",
"background_color": "#ffffff",
"theme_color": "#0e6dc2"
diff --git a/layouts/partials/functions/init.html b/layouts/partials/functions/init.html
index 2a49b4b3..161d2248 100644
--- a/layouts/partials/functions/init.html
+++ b/layouts/partials/functions/init.html
@@ -1,10 +1,54 @@
-{{- partial "scripts/_bundle" . -}}
+{{/* Pull in assets processed by Webpack */}}
+{{- define "__head_css" -}}
+ {{ with .Site.Data.manifest }}
+ {{ with index . "main.css" }}
+
+ {{ end }}
+ {{ end }}
+
+ {{/* Page-specific styles set via front matter, piped through PostCSS and inlined */}}
+ {{- with .Params.css -}}
+ {{/* NOTE: This file doesn't end up getting published (which is good) */}}
+ {{- $target := path.Join $.File.Dir "css/inline.scss" -}}
+ {{- $css := . | resources.FromString $target | resources.PostCSS (dict "config" "postcss.config.js") -}}
+
+ {{- end -}}
+{{- end -}}
+
+{{- define "__head_preload" -}}
+ {{ with .Site.Data.manifest }}
+ {{ with index . "fonts/inter-subset.var.woff2" }}
+
+ {{ end }}
+ {{ with index . "fonts/roboto-mono-subset.var.woff2" }}
+
+ {{ end }}
+ {{ with index . "main.js" }}
+
+ {{ end }}
+ {{ end }}
+{{- end -}}
+
+{{- define "__body_js" -}}
+
+
+
+ {{ with .Site.Data.manifest }}
+ {{ with index . "main.js" }}
+
+ {{ end }}
+ {{ end }}
+{{- end -}}
+
{{/* Strip any markdown styling from page title for use in meta tags */}}
{{- with .Title -}}
{{- $.Scratch.Set "plainTitle" (. | markdownify | htmlUnescape | plainify) -}}
{{- end -}}
+
{{/* If this is a page/post, link View Source to specific file on GitHub; otherwise, just link to repo homepage */}}
{{- with .Site.Params.social.githubRepo }}
{{- $githubURL := print "https://github.com/" . }}
@@ -15,12 +59,11 @@
{{- end }}
{{- end }}
+
{{/* Chooses and initializes various images for use by JSON schema & open graph tags */}}
{{/* Author image (default) */}}
-{{- with .Site.Author.image -}}
- {{- with resources.Get . -}}
- {{- $.Scratch.Set "authorImage" . -}}
- {{- end -}}
+{{- with index .Site.Data.manifest .Site.Author.image -}}
+ {{- $.Scratch.Set "authorImage" (dict "Permalink" (absURL .src) "Width" 1200 "Height" 1200 "MediaType" "image/jpeg") -}}
{{- end -}}
{{/* Page image (via frontmatter) */}}
{{- with .Params.image -}}
@@ -34,16 +77,6 @@
{{- end -}}
{{- end -}}
{{/* Site logo */}}
-{{- with .Site.Params.image -}}
- {{- with resources.Get . -}}
- {{- $.Scratch.Set "logoImage" . -}}
- {{- end -}}
-{{- end -}}
-
-{{/* Page-specific styles set via front matter, piped through PostCSS and inlined */}}
-{{- with .Params.css -}}
- {{/* NOTE: This file doesn't end up getting published (which is good) */}}
- {{- $target := path.Join $.File.Dir "css/inline.scss" -}}
- {{- $css := . | resources.FromString $target | resources.ExecuteAsTemplate $target . | resources.ToCSS (dict "targetPath" $target) | resources.PostCSS (dict "config" "postcss.config.js") -}}
- {{- $.Scratch.Set "pageCss" $css.Content -}}
+{{- with index .Site.Data.manifest .Site.Params.image -}}
+ {{- $.Scratch.Set "logoImage" (dict "Permalink" (absURL .src) "Width" 2048 "Height" 2048 "MediaType" "image/png") -}}
{{- end -}}
diff --git a/layouts/partials/head/_head.html b/layouts/partials/head/_head.html
index e553dd9f..30820157 100644
--- a/layouts/partials/head/_head.html
+++ b/layouts/partials/head/_head.html
@@ -4,8 +4,7 @@
{{ partialCached "head/mobile" . -}}
{{ partialCached "head/preload" . -}}
{{ partial "head/styles" . -}}
-{{ partialCached "head/favicons" (dict "pngSizes" "192 48 32 16" "icoSizes" "16 32") -}}
+{{ partialCached "head/favicons" (dict "pngSizes" "192 48 32 16" "icoSizes" "16 32" "manifest" .Site.Data.manifest) -}}
{{ partialCached "head/feeds" . -}}
{{ partial "head/canonical" . -}}
-{{ partialCached "head/webmention" . -}}
{{ partial "head/schema" . -}}
diff --git a/layouts/partials/head/canonical.html b/layouts/partials/head/canonical.html
index d78de84b..49ebaf89 100644
--- a/layouts/partials/head/canonical.html
+++ b/layouts/partials/head/canonical.html
@@ -1,5 +1,9 @@
-
+
+
+{{ if .Site.Params.social.webmentionIO }}
+
+
+{{ end }}
-
diff --git a/layouts/partials/head/favicons.html b/layouts/partials/head/favicons.html
index 10630d52..5c7d667b 100644
--- a/layouts/partials/head/favicons.html
+++ b/layouts/partials/head/favicons.html
@@ -1,17 +1,12 @@
-{{- range (split .pngSizes " ") }}
- {{- $faviconPng := resources.Get (printf "img/favicon-%v.png" .) }}
-
-{{- end -}}
-
{{- $s := slice -}}
{{- range (split .icoSizes " ") }}{{ $s = $s | append (printf "%vx%v" . .) }}{{ end -}}
-{{- $faviconIco := resources.Get "img/favicon.ico" }}
-
+{{- $faviconIco := index .manifest "images/favicon.ico" }}
+
-{{- $faviconSvg := resources.Get "img/favicon.svg" }}
-
+{{- $faviconSvg := index .manifest "images/favicon.svg" }}
+
-{{- $appleIcon := resources.Get "img/apple-touch-icon.png" }}
-
+{{- $appleIcon := index .manifest "images/apple-touch-icon.png" }}
+
diff --git a/layouts/partials/head/open-graph.html b/layouts/partials/head/open-graph.html
index 10e02aa7..db8f1a91 100644
--- a/layouts/partials/head/open-graph.html
+++ b/layouts/partials/head/open-graph.html
@@ -2,11 +2,11 @@
-
+
{{- with .Scratch.Get "pageImage" }}
-
+
@@ -31,7 +31,7 @@
{{ with .Site.Params.social.facebookAppID }}{{ end }}
-
+
{{- with .Site.Author.social.twitter }}
diff --git a/layouts/partials/head/preload.html b/layouts/partials/head/preload.html
index 0f061eb1..c0c7a190 100644
--- a/layouts/partials/head/preload.html
+++ b/layouts/partials/head/preload.html
@@ -1,4 +1 @@
-
-
-
-{{ template "__preload_js" . }}
+{{ template "__head_preload" . }}
diff --git a/layouts/partials/head/schema/article.html b/layouts/partials/head/schema/article.html
index 3536a0f8..2fb45bba 100644
--- a/layouts/partials/head/schema/article.html
+++ b/layouts/partials/head/schema/article.html
@@ -2,8 +2,8 @@
{
"@context": "http://schema.org",
"@type": "BlogPosting",
- "url": {{ with .OutputFormats.Get "html" }}{{ .Permalink }}{{ end }},
- "mainEntityOfPage": {{ with .OutputFormats.Get "html" }}{{ .Permalink }}{{ end }},
+ "url": {{ with .OutputFormats.Get "html" }}{{ print $.Site.Params.baseURL .Permalink }}{{ end }},
+ "mainEntityOfPage": {{ with .OutputFormats.Get "html" }}{{ print $.Site.Params.baseURL .Permalink }}{{ end }},
"name": {{ .Scratch.Get "plainTitle" }},
"headline": {{ .Scratch.Get "plainTitle" }},
"datePublished": {{ .PublishDate.Format "2006-01-02T15:04:05-07:00" }},
@@ -12,22 +12,22 @@
"description": {{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }},
"wordCount": "{{ .WordCount }}",
"author": {
- "@id": {{ print (absURL "/") "#author" }}
+ "@id": {{ print .Site.Params.baseURL $.Site.BaseURL "#author" }}
},
"publisher": {
"@type": "Organization",
"name": {{ .Site.Title }},
- "url": {{ .Site.BaseURL }}{{ with .Scratch.Get "logoImage" }},
+ "url": {{ .Site.Params.baseURL }}{{ with .Scratch.Get "logoImage" }},
"logo": {
"@type": "ImageObject",
- "url": {{ .Permalink }},
+ "url": {{ print $.Site.Params.baseURL .Permalink }},
"width": "{{ .Width }}",
"height": "{{ .Height }}"
}{{ end }}
}{{ with .Scratch.Get "pageImage" }},
"image": {
"@type": "ImageObject",
- "url": {{ .Permalink }},
+ "url": {{ print $.Site.Params.baseURL .Permalink }},
"width": "{{ .Width }}",
"height": "{{ .Height }}"
}{{ end }}
diff --git a/layouts/partials/head/schema/person.html b/layouts/partials/head/schema/person.html
index 8fe4c52c..f24f45a7 100644
--- a/layouts/partials/head/schema/person.html
+++ b/layouts/partials/head/schema/person.html
@@ -3,18 +3,18 @@
{
"@context": "http://schema.org",
"@type": "Person",
- "@id": {{ print (absURL "/") "#author" }},
+ "@id": {{ print $.Site.Params.baseURL $.Site.BaseURL "#author" }},
"name": {{ .name }},
- "url": {{ $.Site.BaseURL }},
+ "url": {{ print $.Site.Params.baseURL $.Site.BaseURL }},
"description": {{ $.Site.Params.description }},{{ with $.Scratch.Get "authorImage" }}
"image": {
"@type": "ImageObject",
- "url": {{ .Permalink }},
+ "url": {{ print $.Site.Params.baseURL .Permalink }},
"width": "{{ .Width }}",
"height": "{{ .Height }}"
},{{ end }}
"sameAs": [
- {{ $.Site.BaseURL }},{{ with .social }}
+ {{ print $.Site.Params.baseURL $.Site.BaseURL }},{{ with .social }}
{{ with .github }}{{ print "https://github.com/" . }},{{ end }}
{{ with .keybase }}{{ print "https://keybase.io/" . }},{{ end }}
{{ with .twitter }}{{ print "https://twitter.com/" . }},{{ end }}
diff --git a/layouts/partials/head/styles.html b/layouts/partials/head/styles.html
index b1b768cb..98c644ae 100644
--- a/layouts/partials/head/styles.html
+++ b/layouts/partials/head/styles.html
@@ -1,11 +1 @@
-{{ $style := resources.Get "sass/main.scss" | resources.ExecuteAsTemplate "sass/main.scss" . | resources.ToCSS (dict "targetPath" "css/main.css") | resources.PostCSS (dict "config" "postcss.config.js") }}
-
-
-{{/* Page-specific styles set via front matter, piped through PostCSS and inlined (see functions/init) */}}
-{{- with .Scratch.Get "pageCss" -}}
-{{ printf "" | safeHTML -}}
-
-{{- printf "" | safeHTML }}
-{{ end -}}
+{{ template "__head_css" . }}
diff --git a/layouts/partials/head/webmention.html b/layouts/partials/head/webmention.html
deleted file mode 100644
index c4277ba2..00000000
--- a/layouts/partials/head/webmention.html
+++ /dev/null
@@ -1,4 +0,0 @@
-{{ if .Site.Params.social.webmentionIO }}
-
-
-{{ end }}
diff --git a/layouts/partials/page/header.html b/layouts/partials/page/header.html
index 59cf3746..80241550 100644
--- a/layouts/partials/page/header.html
+++ b/layouts/partials/page/header.html
@@ -1,9 +1,9 @@