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 @@